bool upd765_format::save(io_generic *io, floppy_image *image) { // Count the number of formats int formats_count; for(formats_count=0; formats[formats_count].form_factor; formats_count++); // Allocate the storage for the list of testable formats for a // given cell size int *candidates = global_alloc_array(int, formats_count); // Format we're finally choosing int chosen_candidate = -1; // Previously tested cell size int min_cell_size = 0; for(;;) { // Build the list of all formats for the immediatly superior cell size int cur_cell_size = 0; int candidates_count = 0; for(int i=0; i != formats_count; i++) { if(image->get_form_factor() == floppy_image::FF_UNKNOWN || image->get_form_factor() == formats[i].form_factor) { if(formats[i].cell_size == cur_cell_size) candidates[candidates_count++] = i; else if((!cur_cell_size || formats[i].cell_size < cur_cell_size) && formats[i].cell_size > min_cell_size) { candidates[0] = i; candidates_count = 1; cur_cell_size = formats[i].cell_size; } } } min_cell_size = cur_cell_size; // No candidates with a cell size bigger than the previously // tested one, we're done if(!candidates_count) break; // Filter with track 0 head 0 check_compatibility(image, candidates, candidates_count); // Nobody matches, try with the next cell size if(!candidates_count) continue; // We have a match at that cell size, we just need to find the // best one given the geometry // If there's only one, we're done if(candidates_count == 1) { chosen_candidate = candidates[0]; break; } // Otherwise, find the best int tracks, heads; image->get_actual_geometry(tracks, heads); chosen_candidate = candidates[0]; for(int i=1; i != candidates_count; i++) { const format &cc = formats[chosen_candidate]; const format &cn = formats[candidates[i]]; // Handling enough sides is better than not if(cn.head_count >= heads && cc.head_count < heads) goto change; else if(cc.head_count >= heads && cn.head_count < heads) goto dont_change; // Since we're limited to two heads, at that point head // count is identical for both formats. // Handling enough tracks is better than not if(cn.track_count >= tracks && cc.track_count < tracks) goto change; else if(cn.track_count >= tracks && cc.track_count < tracks) goto dont_change; // Both are on the same side of the track count, so closest is best if(cc.track_count < tracks && cn.track_count > cc.track_count) goto change; if(cc.track_count >= tracks && cn.track_count < cc.track_count) goto change; goto dont_change; change: chosen_candidate = candidates[i]; dont_change: ; } // We have a winner, bail out break; } // No match, pick the first one and be done with it if(chosen_candidate == -1) chosen_candidate = 0; const format &f = formats[chosen_candidate]; int track_size = compute_track_size(f); UINT8 sectdata[40*512]; desc_s sectors[40]; build_sector_description(f, sectdata, sectors); for(int track=0; track < f.track_count; track++) for(int head=0; head < f.head_count; head++) { extract_sectors(image, f, sectors, track, head); io_generic_write(io, sectdata, (track*f.head_count + head)*track_size, track_size); } return true; }
bool wd177x_format::save(io_generic *io, floppy_image *image) { // Count the number of formats int formats_count; for(formats_count=0; formats[formats_count].form_factor; formats_count++) {}; // Allocate the storage for the list of testable formats for a // given cell size std::vector<int> candidates; // Format we're finally choosing int chosen_candidate = -1; // Previously tested cell size int min_cell_size = 0; for(;;) { // Build the list of all formats for the immediately superior cell size int cur_cell_size = 0; candidates.clear(); for(int i=0; i != formats_count; i++) { if(image->get_form_factor() == floppy_image::FF_UNKNOWN || image->get_form_factor() == formats[i].form_factor) { if(formats[i].cell_size == cur_cell_size) candidates.push_back(i); else if((!cur_cell_size || formats[i].cell_size < cur_cell_size) && formats[i].cell_size > min_cell_size) { candidates.clear(); candidates.push_back(i); cur_cell_size = formats[i].cell_size; } } } min_cell_size = cur_cell_size; // No candidates with a cell size bigger than the previously // tested one, we're done if(candidates.empty()) break; // Filter with track 0 head 0 check_compatibility(image, candidates); // Nobody matches, try with the next cell size if(candidates.empty()) continue; // We have a match at that cell size, we just need to find the // best one given the geometry // If there's only one, we're done if(candidates.size() == 1) { chosen_candidate = candidates[0]; break; } // Otherwise, find the best int tracks, heads; image->get_actual_geometry(tracks, heads); chosen_candidate = candidates[0]; for(unsigned int i=1; i != candidates.size(); i++) { const format &cc = formats[chosen_candidate]; const format &cn = formats[candidates[i]]; // Handling enough sides is better than not if(cn.head_count >= heads && cc.head_count < heads) goto change; else if(cc.head_count >= heads && cn.head_count < heads) goto dont_change; // Handling enough tracks is better than not if(cn.track_count >= tracks && cc.track_count < tracks) goto change; else if(cc.track_count >= tracks && cn.track_count < tracks) goto dont_change; // Both are on the same side of the track count, so closest is best if(cc.track_count < tracks && cn.track_count > cc.track_count) goto change; if(cc.track_count >= tracks && cn.track_count < cc.track_count) goto change; // Lower number of heads is better if (cn.head_count < cc.head_count && cn.head_count <= heads) goto change; goto dont_change; change: chosen_candidate = candidates[i]; dont_change: ; } // We have a winner, bail out break; } // No match, pick the first one and be done with it if(chosen_candidate == -1) chosen_candidate = 0; const format &f = formats[chosen_candidate]; int track_size = compute_track_size(f); uint8_t sectdata[40*512]; desc_s sectors[40]; for(int track=0; track < f.track_count; track++) for(int head=0; head < f.head_count; head++) { build_sector_description(f, sectdata, sectors, track, head); extract_sectors(image, f, sectors, track, head); io_generic_write(io, sectdata, get_image_offset(f, head, track), track_size); } return true; }
bool upd765_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { int type = find_size(io, form_factor); if(type == -1) return false; const format &f = formats[type]; floppy_image_format_t::desc_e desc[] = { /* 00 */ { MFM, 0x4e, f.gap_4a }, /* 01 */ { MFM, 0x00, 12 }, /* 02 */ { RAW, 0x5224, 3 }, /* 03 */ { MFM, 0xfc, 1 }, /* 04 */ { MFM, 0x4e, f.gap_1 }, /* 05 */ { SECTOR_LOOP_START, 0, f.sector_count-1 }, /* 06 */ { MFM, 0x00, 12 }, /* 07 */ { CRC_CCITT_START, 1 }, /* 08 */ { RAW, 0x4489, 3 }, /* 09 */ { MFM, 0xfe, 1 }, /* 10 */ { TRACK_ID }, /* 11 */ { HEAD_ID }, /* 12 */ { SECTOR_ID }, /* 13 */ { SIZE_ID }, /* 14 */ { CRC_END, 1 }, /* 15 */ { CRC, 1 }, /* 16 */ { MFM, 0x4e, f.gap_2 }, /* 17 */ { MFM, 0x00, 12 }, /* 18 */ { CRC_CCITT_START, 2 }, /* 19 */ { RAW, 0x4489, 3 }, /* 20 */ { MFM, 0xfb, 1 }, /* 21 */ { SECTOR_DATA, -1 }, /* 22 */ { CRC_END, 2 }, /* 23 */ { CRC, 2 }, /* 24 */ { MFM, 0x4e, f.gap_3 }, /* 25 */ { SECTOR_LOOP_END }, /* 26 */ { MFM, 0x4e, 0 }, /* 27 */ { RAWBITS, 0x9254, 0 }, /* 28 */ { END } }; int current_size = (f.gap_4a+12+3+1+f.gap_1)*16; if(f.sector_base_size) current_size += f.sector_base_size * f.sector_count * 16; else { for(int j=0; j != f.sector_count; j++) current_size += f.per_sector_size[j] * 16; } current_size += (12+3+1+4+2+f.gap_2+12+3+1+2+f.gap_3) * f.sector_count * 16; int total_size = 200000000/f.cell_size; int remaining_size = total_size - current_size; if(remaining_size < 0) throw emu_fatalerror("upd765_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size); // Fixup the end gap desc[26].p2 = remaining_size / 16; desc[27].p2 = remaining_size & 15; desc[27].p1 >>= 16-(remaining_size & 15); int track_size = compute_track_size(f); UINT8 sectdata[40*512]; desc_s sectors[40]; build_sector_description(f, sectdata, sectors); for(int track=0; track < f.track_count; track++) for(int head=0; head < f.head_count; head++) { io_generic_read(io, sectdata, (track*f.head_count + head)*track_size, track_size); generate_track(desc, track, head, sectors, f.sector_count, total_size, image); } image->set_variant(f.variant); return true; }