pc floppies: Merge the common parts of d88/imd [O. Galibert]

This commit is contained in:
Olivier Galibert 2012-11-20 20:33:37 +00:00
parent 8a1f60fcfd
commit a0c70ecb0c
4 changed files with 228 additions and 194 deletions

View File

@ -504,7 +504,6 @@ bool d88_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
if(!head_count) if(!head_count)
return false; return false;
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000);
UINT32 track_pos[164]; UINT32 track_pos[164];
io_generic_read(io, track_pos, 32, 164*4); io_generic_read(io, track_pos, 32, 164*4);
@ -514,97 +513,49 @@ bool d88_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
if(!pos) if(!pos)
continue; continue;
desc_pc_sector sects[256];
UINT8 sect_data[65536]; UINT8 sect_data[65536];
int tpos = 0; int sdatapos = 0;
// gap 4a , IAM and gap 1
for(int i=0; i<80; i++) mfm_w(track_data, tpos, 8, 0x4e);
for(int i=0; i<12; i++) mfm_w(track_data, tpos, 8, 0x00);
for(int i=0; i< 3; i++) raw_w(track_data, tpos, 16, 0x5224);
mfm_w(track_data, tpos, 8, 0xfc);
for(int i=0; i<50; i++) mfm_w(track_data, tpos, 8, 0x4e);
// Read all sector headers to compute the available and expected size for gap3
int sector_count = 1; int sector_count = 1;
int gap3 = 84;
int etpos = tpos;
int rpos = pos;
for(int i=0; i<sector_count; i++) {
UINT8 hs[16];
io_generic_read(io, hs, rpos, 16);
UINT16 size = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+14));
rpos += 16+size;
if(i == 0) {
sector_count = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+4));
if(size < 512)
gap3 = form_factor == floppy_image::FF_35 ? 54 : 50;
else
gap3 = form_factor == floppy_image::FF_35 ? 84 : 80;
}
etpos += (12+3+5+2+22+12+3+1+size+2)*16;
}
if(etpos > cell_count)
throw emu_fatalerror("d88_format: Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos);
if(etpos + gap3*16*(sector_count-1) > cell_count)
gap3 = (cell_count - etpos) / 16 / (sector_count-1);
// Build the track
for(int i=0; i<sector_count; i++) { for(int i=0; i<sector_count; i++) {
UINT8 hs[16]; UINT8 hs[16];
io_generic_read(io, hs, pos, 16); io_generic_read(io, hs, pos, 16);
pos += 16;
UINT16 size = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+14)); UINT16 size = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+14));
io_generic_read(io, sect_data, pos+16, size); if(i == 0)
pos += 16+size; sector_count = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+4));
int cpos; sects[i].track = hs[0];
UINT16 crc; sects[i].head = hs[1];
// sync and IDAM and gap 2 sects[i].sector = hs[2];
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); sects[i].size = hs[3];
cpos = tpos; sects[i].actual_size = size;
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); sects[i].deleted = hs[7] != 0;
mfm_w(track_data, tpos, 8, 0xfe); sects[i].bad_crc = false;
mfm_w(track_data, tpos, 8, hs[0]);
mfm_w(track_data, tpos, 8, hs[1]);
mfm_w(track_data, tpos, 8, hs[2]);
mfm_w(track_data, tpos, 8, hs[3]);
crc = calc_crc_ccitt(track_data, cpos, tpos);
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<22; j++) mfm_w(track_data, tpos, 8, 0x4e);
// sync, DAM, data and gap 3 if(size) {
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); sects[i].data = sect_data + sdatapos;
cpos = tpos; io_generic_read(io, sects[i].data, pos+16, size);
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); pos += size;
mfm_w(track_data, tpos, 8, hs[7] ? 0xf8 : 0xfb); }
for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, sect_data[j]);
crc = calc_crc_ccitt(track_data, cpos, tpos);
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap3; j++) mfm_w(track_data, tpos, 8, 0x4e);
} }
// Gap 4b build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
while(tpos < cell_count-15) mfm_w(track_data, tpos, 8, 0x4e);
raw_w(track_data, tpos, cell_count-tpos, 0x9254 >> (16+tpos-cell_count));
generate_track_from_levels(track, head, track_data, cell_count, 0, image);
} }
global_free(track_data);
return true; return true;
} }
bool d88_format::save(io_generic *io, floppy_image *image) bool d88_format::save(io_generic *io, floppy_image *image)
{ {
return true; return false;
} }
bool d88_format::supports_save() const bool d88_format::supports_save() const
{ {
return true; return false;
} }
const floppy_format_type FLOPPY_D88_FORMAT = &floppy_image_format_creator<d88_format>; const floppy_format_type FLOPPY_D88_FORMAT = &floppy_image_format_creator<d88_format>;

View File

@ -2463,3 +2463,162 @@ void floppy_image_format_t::get_track_data_fm_pc(int track, int head, floppy_ima
memset(sd, 0, sector_size); memset(sd, 0, sector_size);
} }
} }
int floppy_image_format_t::calc_default_pc_gap3_size(UINT32 form_factor, int sector_size)
{
return
form_factor == floppy_image::FF_8 ? 25 :
sector_size < 512 ?
(form_factor == floppy_image::FF_35 ? 54 : 50) :
(form_factor == floppy_image::FF_35 ? 84 : 80);
}
void floppy_image_format_t::build_wd_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2)
{
build_pc_track_fm(track, head, image, cell_count, sector_count, sects, gap_3, -1, gap_1, gap_2);
}
void floppy_image_format_t::build_wd_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2)
{
build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, gap_3, -1, gap_1, gap_2);
}
void floppy_image_format_t::build_pc_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a, int gap_1, int gap_2)
{
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000);
int tpos = 0;
// gap 4a , IAM and gap 1
if(gap_4a != -1) {
for(int i=0; i<gap_4a; i++) fm_w(track_data, tpos, 8, 0xff);
for(int i=0; i< 6; i++) fm_w(track_data, tpos, 8, 0x00);
raw_w(track_data, tpos, 16, 0xf77a);
}
for(int i=0; i<gap_1; i++) fm_w(track_data, tpos, 8, 0xff);
int total_size = 0;
for(int i=0; i<sector_count; i++)
total_size += sects[i].actual_size;
int etpos = tpos;
etpos += (sector_count*(6+5+2+11+6+1+2) + total_size)*16;
if(etpos > cell_count)
throw emu_fatalerror("Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos);
if(etpos + gap_3*16*(sector_count-1) > cell_count)
gap_3 = (cell_count - etpos) / 16 / (sector_count-1);
// Build the track
for(int i=0; i<sector_count; i++) {
int cpos;
UINT16 crc;
// sync and IDAM and gap 2
for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
raw_w(track_data, tpos, 16, 0xf57e);
fm_w (track_data, tpos, 8, sects[i].track);
fm_w (track_data, tpos, 8, sects[i].head);
fm_w (track_data, tpos, 8, sects[i].sector);
fm_w (track_data, tpos, 8, sects[i].size);
crc = calc_crc_ccitt(track_data, cpos, tpos);
fm_w (track_data, tpos, 16, crc);
for(int j=0; j<gap_2; j++) fm_w(track_data, tpos, 8, 0xff);
if(!sects[i].data)
for(int j=0; j<6+1+sects[i].actual_size+2+gap_3; j++) fm_w(track_data, tpos, 8, 0xff);
else {
// sync, DAM, data and gap 3
for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
raw_w(track_data, tpos, 16, sects[i].deleted ? 0xf56a : 0xf56f);
for(int j=0; j<sects[i].actual_size; j++) fm_w(track_data, tpos, 8, sects[i].data[j]);
crc = calc_crc_ccitt(track_data, cpos, tpos);
if(sects[i].bad_crc)
crc = 0xffff^crc;
fm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap_3; j++) fm_w(track_data, tpos, 8, 0xff);
}
}
// Gap 4b
while(tpos < cell_count-15) fm_w(track_data, tpos, 8, 0xff);
raw_w(track_data, tpos, cell_count-tpos, 0xffff >> (16+tpos-cell_count));
generate_track_from_levels(track, head, track_data, cell_count, 0, image);
global_free(track_data);
}
void floppy_image_format_t::build_pc_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a, int gap_1, int gap_2)
{
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000);
int tpos = 0;
// gap 4a , IAM and gap 1
if(gap_4a != -1) {
for(int i=0; i<gap_4a; i++) mfm_w(track_data, tpos, 8, 0x4e);
for(int i=0; i<12; i++) mfm_w(track_data, tpos, 8, 0x00);
for(int i=0; i< 3; i++) raw_w(track_data, tpos, 16, 0x5224);
mfm_w(track_data, tpos, 8, 0xfc);
}
for(int i=0; i<gap_1; i++) mfm_w(track_data, tpos, 8, 0x4e);
int total_size = 0;
for(int i=0; i<sector_count; i++)
total_size += sects[i].actual_size;
int etpos = tpos;
etpos += (sector_count*(12+3+5+2+gap_2+12+3+1+2) + total_size)*16;
if(etpos > cell_count)
throw emu_fatalerror("Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos);
if(etpos + gap_3*16*(sector_count-1) > cell_count)
gap_3 = (cell_count - etpos) / 16 / (sector_count-1);
// Build the track
for(int i=0; i<sector_count; i++) {
int cpos;
UINT16 crc;
// sync and IDAM and gap 2
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489);
mfm_w(track_data, tpos, 8, 0xfe);
mfm_w(track_data, tpos, 8, sects[i].track);
mfm_w(track_data, tpos, 8, sects[i].head);
mfm_w(track_data, tpos, 8, sects[i].sector);
mfm_w(track_data, tpos, 8, sects[i].size);
crc = calc_crc_ccitt(track_data, cpos, tpos);
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap_2; j++) mfm_w(track_data, tpos, 8, 0x4e);
if(!sects[i].data)
for(int j=0; j<12+4+sects[i].actual_size+2+gap_3; j++) mfm_w(track_data, tpos, 8, 0x4e);
else {
// sync, DAM, data and gap 3
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489);
mfm_w(track_data, tpos, 8, sects[i].deleted ? 0xf8 : 0xfb);
for(int j=0; j<sects[i].actual_size; j++) mfm_w(track_data, tpos, 8, sects[i].data[j]);
crc = calc_crc_ccitt(track_data, cpos, tpos);
if(sects[i].bad_crc)
crc = 0xffff^crc;
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap_3; j++) mfm_w(track_data, tpos, 8, 0x4e);
}
}
// Gap 4b
while(tpos < cell_count-15) mfm_w(track_data, tpos, 8, 0x4e);
raw_w(track_data, tpos, cell_count-tpos, 0x9254 >> (16+tpos-cell_count));
generate_track_from_levels(track, head, track_data, cell_count, 0, image);
global_free(track_data);
}

View File

@ -469,6 +469,21 @@ protected:
const UINT8 *data; //!< Data within this sector const UINT8 *data; //!< Data within this sector
}; };
struct desc_pc_sector {
UINT8 track, head, sector, size;
int actual_size;
UINT8 *data;
bool deleted;
bool bad_crc;
};
int calc_default_pc_gap3_size(UINT32 form_factor, int sector_size);
void build_wd_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2);
void build_wd_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_1, int gap_2=22);
void build_pc_track_fm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=40, int gap_1=26, int gap_2=11);
void build_pc_track_mfm(int track, int head, floppy_image *image, int cell_count, int sector_count, const desc_pc_sector *sects, int gap_3, int gap_4a=80, int gap_1=50, int gap_2=22);
//! @brief Extract standard sectors from a regenerated bitstream. //! @brief Extract standard sectors from a regenerated bitstream.
//! Sectors must point to an array of 256 desc_xs. //! Sectors must point to an array of 256 desc_xs.

View File

@ -414,7 +414,7 @@ bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
if(ssize == 0xff) if(ssize == 0xff)
throw emu_fatalerror("imd_format: Unsupported variable sector size on track %d head %d", track, head); throw emu_fatalerror("imd_format: Unsupported variable sector size on track %d head %d", track, head);
UINT32 size = ssize < 7 ? 128 << ssize : 8192; UINT32 actual_size = ssize < 7 ? 128 << ssize : 8192;
static const int rates[3] = { 500000, 300000, 250000 }; static const int rates[3] = { 500000, 300000, 250000 };
bool fm = mode < 3; bool fm = mode < 3;
@ -433,135 +433,44 @@ bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
head &= 0x3f; head &= 0x3f;
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000); int gap_3 = calc_default_pc_gap3_size(form_factor, actual_size);
int tpos = 0;
// gap 4a , IAM and gap 1 desc_pc_sector sects[256];
if(fm) {
for(int i=0; i<40; i++) fm_w(track_data, tpos, 8, 0xff); for(int i=0; i<sector_count; i++) {
for(int i=0; i< 6; i++) fm_w(track_data, tpos, 8, 0x00); UINT8 stype = img[pos++];
raw_w(track_data, tpos, 16, 0xf77a); sects[i].track = tnum ? tnum[i] : track;
for(int i=0; i<26; i++) fm_w(track_data, tpos, 8, 0xff); sects[i].head = hnum ? hnum[i] : head;
} else { sects[i].sector = snum[i];
for(int i=0; i<80; i++) mfm_w(track_data, tpos, 8, 0x4e); sects[i].size = ssize;
for(int i=0; i<12; i++) mfm_w(track_data, tpos, 8, 0x00); sects[i].actual_size = actual_size;
for(int i=0; i< 3; i++) raw_w(track_data, tpos, 16, 0x5224);
mfm_w(track_data, tpos, 8, 0xfc); if(stype == 0 || stype > 8) {
for(int i=0; i<50; i++) mfm_w(track_data, tpos, 8, 0x4e); sects[i].data = NULL;
} else {
sects[i].deleted = stype == 3 || stype == 4 || stype == 7 || stype == 8;
sects[i].bad_crc = stype == 5 || stype == 6 || stype == 7 || stype == 8;
if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
sects[i].data = global_alloc_array(UINT8, actual_size);
memset(sects[i].data, img[pos++], actual_size);
} else {
sects[i].data = img + pos;
pos += actual_size;
}
}
} }
// Compute the available and expected size for gap3
int gap3 = form_factor == floppy_image::FF_8 ? 25 :
size < 512 ?
(form_factor == floppy_image::FF_35 ? 54 : 50) :
(form_factor == floppy_image::FF_35 ? 84 : 80);
int etpos = tpos;
if(fm) if(fm)
etpos += sector_count*(6+5+2+11+6+1+size+2)*16; build_pc_track_fm(track, head, image, cell_count, sector_count, sects, gap_3);
else else
etpos += sector_count*(12+3+5+2+22+12+3+1+size+2)*16; build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, gap_3);
if(etpos > cell_count) for(int i=0; i<sector_count; i++)
throw emu_fatalerror("imd_format: Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos); if(sects[i].data && (sects[i].data < img || sects[i].data >= img+size))
global_free(sects[i].data);
if(etpos + gap3*16*(sector_count-1) > cell_count)
gap3 = (cell_count - etpos) / 16 / (sector_count-1);
// Build the track
if(fm) {
for(int i=0; i<sector_count; i++) {
UINT8 stype = img[pos++];
int cpos;
UINT16 crc;
// sync and IDAM and gap 2
for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
raw_w(track_data, tpos, 16, 0xf57e);
fm_w (track_data, tpos, 8, tnum ? tnum[i] : track);
fm_w (track_data, tpos, 8, hnum ? hnum[i] : head);
fm_w (track_data, tpos, 8, snum[i]);
fm_w (track_data, tpos, 8, ssize);
crc = calc_crc_ccitt(track_data, cpos, tpos);
fm_w (track_data, tpos, 16, crc);
for(int j=0; j<11; j++) fm_w(track_data, tpos, 8, 0xff);
if(stype == 0 || stype > 8)
for(int j=0; j<6+1+size+2+gap3; j++) fm_w(track_data, tpos, 8, 0xff);
else {
// sync, DAM, data and gap 3
for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
raw_w(track_data, tpos, 16, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf56a : 0xf56f);
if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos]);
pos++;
} else
for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos++]);
crc = calc_crc_ccitt(track_data, cpos, tpos);
if(stype == 5 || stype == 6 || stype == 7 || stype == 8)
crc = 0xffff^crc;
fm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap3; j++) fm_w(track_data, tpos, 8, 0xff);
}
}
// Gap 4b
while(tpos < cell_count-15) fm_w(track_data, tpos, 8, 0xff);
raw_w(track_data, tpos, cell_count-tpos, 0xffff >> (16+tpos-cell_count));
} else {
for(int i=0; i<sector_count; i++) {
UINT8 stype = img[pos++];
int cpos;
UINT16 crc;
// sync and IDAM and gap 2
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489);
mfm_w(track_data, tpos, 8, 0xfe);
mfm_w(track_data, tpos, 8, tnum ? tnum[i] : track);
mfm_w(track_data, tpos, 8, hnum ? hnum[i] : head);
mfm_w(track_data, tpos, 8, snum[i]);
mfm_w(track_data, tpos, 8, ssize);
crc = calc_crc_ccitt(track_data, cpos, tpos);
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<22; j++) mfm_w(track_data, tpos, 8, 0x4e);
if(stype == 0 || stype > 8)
for(int j=0; j<12+4+size+2+gap3; j++) mfm_w(track_data, tpos, 8, 0x4e);
else {
// sync, DAM, data and gap 3
for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00);
cpos = tpos;
for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489);
mfm_w(track_data, tpos, 8, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf8 : 0xfb);
if(stype == 2 || stype == 4 || stype == 6 || stype == 8) {
for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos]);
pos++;
} else
for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos++]);
if(stype == 5 || stype == 6 || stype == 7 || stype == 8)
crc = 0xffff^crc;
crc = calc_crc_ccitt(track_data, cpos, tpos);
mfm_w(track_data, tpos, 16, crc);
for(int j=0; j<gap3; j++) mfm_w(track_data, tpos, 8, 0x4e);
}
}
// Gap 4b
while(tpos < cell_count-15) mfm_w(track_data, tpos, 8, 0x4e);
raw_w(track_data, tpos, cell_count-tpos, 0x9254 >> (16+tpos-cell_count));
}
generate_track_from_levels(track, head, track_data, cell_count, 0, image);
global_free(track_data);
} }
global_free(img); global_free(img);