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)
return false;
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000);
UINT32 track_pos[164];
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)
continue;
desc_pc_sector sects[256];
UINT8 sect_data[65536];
int tpos = 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 sdatapos = 0;
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++) {
UINT8 hs[16];
io_generic_read(io, hs, pos, 16);
pos += 16;
UINT16 size = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+14));
io_generic_read(io, sect_data, pos+16, size);
pos += 16+size;
if(i == 0)
sector_count = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hs+4));
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, 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);
sects[i].track = hs[0];
sects[i].head = hs[1];
sects[i].sector = hs[2];
sects[i].size = hs[3];
sects[i].actual_size = size;
sects[i].deleted = hs[7] != 0;
sects[i].bad_crc = false;
// 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, 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);
if(size) {
sects[i].data = sect_data + sdatapos;
io_generic_read(io, sects[i].data, pos+16, size);
pos += size;
}
}
// 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);
build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
}
global_free(track_data);
return true;
}
bool d88_format::save(io_generic *io, floppy_image *image)
{
return true;
return false;
}
bool d88_format::supports_save() const
{
return true;
return false;
}
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);
}
}
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
};
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.
//! 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)
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 };
bool fm = mode < 3;
@ -433,135 +433,44 @@ bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
head &= 0x3f;
UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000);
int tpos = 0;
int gap_3 = calc_default_pc_gap3_size(form_factor, actual_size);
// gap 4a , IAM and gap 1
if(fm) {
for(int i=0; i<40; 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<26; i++) fm_w(track_data, tpos, 8, 0xff);
} else {
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);
desc_pc_sector sects[256];
for(int i=0; i<sector_count; i++) {
UINT8 stype = img[pos++];
sects[i].track = tnum ? tnum[i] : track;
sects[i].head = hnum ? hnum[i] : head;
sects[i].sector = snum[i];
sects[i].size = ssize;
sects[i].actual_size = actual_size;
if(stype == 0 || stype > 8) {
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)
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
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)
throw emu_fatalerror("imd_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
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);
for(int i=0; i<sector_count; i++)
if(sects[i].data && (sects[i].data < img || sects[i].data >= img+size))
global_free(sects[i].data);
}
global_free(img);