bool ccvf_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { const format &f = formats[0]; UINT64 size = io_generic_size(io); dynamic_buffer img(size); io_generic_read(io, &img[0], 0, size); std::string ccvf = std::string((const char *)&img[0], size); dynamic_buffer bytes(78720); int start = 0, end = 0; std::string line; UINT32 byteoffs = 0; char hex[3] = {0}; do { end = ccvf.find_first_of(10, start); line.assign(ccvf.substr(start, end)); if (line.find("Compucolor Virtual Floppy Disk Image") != std::string::npos && line.find("Label") != std::string::npos && line.find("Track") != std::string::npos) { for (int byte = 0; byte < 32; byte++) { if (byteoffs==78720) break; hex[0]=line[byte * 2]; hex[1]=line[(byte * 2) + 1]; bytes[byteoffs++] = strtol(hex, nullptr, 16); } } start = end + 1; } while (start > 0 && end != -1); UINT64 pos = 0; int total_size = 200000000/f.cell_size; for(int track=0; track < f.track_count; track++) { std::vector<UINT32> buffer; int offset = 0; for (int i=0; i<1920 && pos<size; i++, pos++) { for (int bit=0; bit<8; bit++) { bit_w(buffer, BIT(bytes[pos], bit), f.cell_size); } } if (offset < total_size) { // pad the remainder of the track with sync int count = total_size-buffer.size(); for (int i=0; i<count;i++) { bit_w(buffer, (track > 0) ? 1 : 0, f.cell_size); } } generate_track_from_levels(track, 0, buffer, 0, image); } image->set_variant(f.variant); return true; }
bool oric_dsk_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { UINT8 h[256]; UINT8 t[6250+3]; UINT32 stream[100000]; t[6250] = t[6251] = t[6252] = 0; io_generic_read(io, h, 0, 256); int sides = (h[11] << 24) | (h[10] << 16) | (h[ 9] << 8) | h[ 8]; int tracks = (h[15] << 24) | (h[14] << 16) | (h[13] << 8) | h[12]; for(int side=0; side<sides; side++) for(int track=0; track<tracks; track++) { io_generic_read(io, t, 256+6400*(tracks*side + track), 6250); int pos = 0; int sector_size = 128; for(int i=0; i<6250; i++) { if(t[i] == 0xc2 && t[i+1] == 0xc2 && t[i+2] == 0xc2) { raw_w(stream, pos, 16, 0x5224); raw_w(stream, pos, 16, 0x5224); raw_w(stream, pos, 16, 0x5224); i += 2; continue; } if(t[i] == 0xa1 && t[i+1] == 0xa1 && t[i+2] == 0xa1) { raw_w(stream, pos, 16, 0x4489); raw_w(stream, pos, 16, 0x4489); raw_w(stream, pos, 16, 0x4489); int copy; if(t[i+3] == 0xfe) { copy = 7; sector_size = 128 << (t[i+7] & 3); logerror("%02x %x - %02x %02x %02x %02x\n", track, side, t[i+4], t[i+5], t[i+6], t[i+7]); } else if(t[i+3] == 0xfb) copy = sector_size+3; else copy = 0; for(int j=0; j<copy; j++) mfm_w(stream, pos, 8, t[i+3+j]); i += 2+copy; continue; } mfm_w(stream, pos, 8, t[i]); } generate_track_from_levels(track, side, stream, 100000, 0, image); } return true; }
bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { UINT64 size = io_generic_size(io); UINT8 *img = global_alloc_array(UINT8, size); io_generic_read(io, img, 0, size); int version = img[0x08]; if (version) throw emu_fatalerror("g64_format: Unsupported version %u", version); int track_count = img[0x09]; int pos = 0x0c; int track_offset[84*2]; for(int track = 0; track < track_count; track++) { track_offset[track] = pick_integer_le(img, pos, 4); pos += 4; } int speed_zone_offset[84*2]; for(int track = 0; track < track_count; track++) { speed_zone_offset[track] = pick_integer_le(img, pos, 4); pos += 4; } for(int track = 0; track < track_count; track++) { int track_size = 0; pos = track_offset[track]; if (pos > 0) { track_size = pick_integer_le(img, pos, 2); pos +=2; if (speed_zone_offset[track] > 3) throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track); UINT32 cell_size = c1541_cell_size[speed_zone_offset[track]]; int total_size = 200000000/cell_size; UINT32 *buffer = global_alloc_array_clear(UINT32, total_size); int offset = 0; for (int i=0; i<track_size; i++, pos++) { for (int bit=7; bit>=0; bit--) { bit_w(buffer, offset++, BIT(img[pos], bit), cell_size); if (offset == total_size) break; } } if (offset < total_size) { // pad the remainder of the track with sync int count = (total_size-offset); for (int i=0; i<count; i++) { bit_w(buffer, offset++, 1, cell_size); } } int physical_track = track >= 84 ? track - 84 : track; int head = track >= 84; generate_track_from_levels(physical_track, head, buffer, total_size, 0, image); global_free(buffer); } } image->set_variant(floppy_image::SSSD); return true; }
bool dmk_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { const int header_size = 16; UINT8 header[header_size]; io_generic_read(io, header, 0, header_size); const int tracks = header[1]; const int track_size = ( header[3] << 8 ) | header[2]; const int heads = (header[4] & 0x10) ? 1 : 2; const bool is_sd = (header[4] & 0x40) ? true : false; const int raw_track_size = 2 * 8 * ( track_size - 0x80 ); if (is_sd) { if (heads == 2) { image->set_variant(floppy_image::DSSD); } else { image->set_variant(floppy_image::SSSD); } } else { if (heads == 2) { image->set_variant(floppy_image::DSDD); } else { image->set_variant(floppy_image::SSDD); } } for (int track = 0; track < tracks; track++) { for (int head = 0; head < heads; head++) { dynamic_array<UINT8> track_data(track_size); dynamic_array<UINT32> raw_track_data(raw_track_size); int iam_location = -1; int idam_location[64]; int dam_location[64]; int tpos = 0; // Read track io_generic_read(io, track_data, header_size + ( heads * track + head ) * track_size, track_size); for (int i = 0; i < 64; i++) { idam_location[i] = -1; dam_location[i] = -1; } // Find IDAM locations UINT16 track_header_offset = 0; UINT16 track_offset = ( ( track_data[track_header_offset + 1] << 8 ) | track_data[track_header_offset] ) & 0x3fff; track_header_offset += 2; while ( track_offset != 0 && track_offset >= 0x83 && track_offset < track_size && track_header_offset < 0x80 ) { // Assume 3 bytes before IDAM pointers are the start of IDAM indicators idam_location[(track_header_offset/2) - 1] = track_offset - 3; // Scan for DAM location for (int i = track_offset + 53; i > track_offset + 10; i--) { if ((track_data[i] == 0xfb || track_data[i] == 0xf8) && track_data[i-1] == 0xa1 && track_data[i-2] == 0xa1) { dam_location[(track_header_offset/2) - 1] = i - 3; break; } } track_offset = ( ( track_data[track_header_offset + 1] << 8 ) | track_data[track_header_offset] ) & 0x3fff; track_header_offset += 2; }; // Find IAM location for(int i = idam_location[0] - 1; i >= 3; i--) { // It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes if (track_data[i] == 0xfc && track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2) { iam_location = i - 3; break; } } int idam_index = 0; int dam_index = 0; for (int offset = 0x80; offset < track_size; offset++) { if (offset == iam_location) { // Write IAM raw_w(raw_track_data, tpos, 16, 0x5224); raw_w(raw_track_data, tpos, 16, 0x5224); raw_w(raw_track_data, tpos, 16, 0x5224); offset += 3; } if (offset == idam_location[idam_index]) { raw_w(raw_track_data, tpos, 16, 0x4489); raw_w(raw_track_data, tpos, 16, 0x4489); raw_w(raw_track_data, tpos, 16, 0x4489); idam_index += 1; offset += 3; } if (offset == dam_location[dam_index]) { raw_w(raw_track_data, tpos, 16, 0x4489); raw_w(raw_track_data, tpos, 16, 0x4489); raw_w(raw_track_data, tpos, 16, 0x4489); dam_index += 1; offset += 3; } mfm_w(raw_track_data, tpos, 8, track_data[offset]); } generate_track_from_levels(track, head, raw_track_data, raw_track_size, 0, image); } } return true; }
bool d88_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { UINT8 h[32]; io_generic_read(io, h, 0, 32); int cell_count = 0; int track_count = 0; int head_count = 0; switch(h[0x1b]) { case 0x00: cell_count = 100000; track_count = 42; head_count = 2; image->set_variant(floppy_image::DSDD); break; case 0x10: cell_count = 100000; track_count = 82; head_count = 2; image->set_variant(floppy_image::DSQD); break; case 0x20: cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666; track_count = 82; head_count = 2; image->set_variant(floppy_image::DSHD); break; case 0x30: cell_count = 100000; track_count = 42; head_count = 1; image->set_variant(floppy_image::SSDD); break; case 0x40: cell_count = 100000; track_count = 82; head_count = 1; image->set_variant(floppy_image::SSQD); break; } if(!head_count) return false; UINT32 track_pos[164]; io_generic_read(io, track_pos, 32, 164*4); for(int track=0; track < track_count; track++) for(int head=0; head < head_count; head++) { int pos = LITTLE_ENDIANIZE_INT32(track_pos[track * head_count + head]); if(!pos) continue; UINT32 track_data[210000]; 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); // Updated after reading the first header int sector_count = 1; int gap3 = 84; for(int i=0; i<sector_count; i++) { UINT8 hs[16]; io_generic_read(io, hs, 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)); if(size < 512) gap3 = form_factor == floppy_image::FF_35 ? 54 : 50; else gap3 = form_factor == floppy_image::FF_35 ? 84 : 80; } 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); // 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, 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 if(tpos > cell_count) throw emu_fatalerror("d88_format: Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, tpos); 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); } return true; }