void upd765_format::extract_sectors(floppy_image *image, const format &f, desc_s *sdesc, int track, int head) { UINT8 bitstream[500000/8]; UINT8 sectdata[50000]; desc_xs sectors[256]; int track_size; // Extract the sectors generate_bitstream_from_track(track, head, f.cell_size, bitstream, track_size, image); switch (f.encoding) { case floppy_image::FM: extract_sectors_from_bitstream_fm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata)); break; case floppy_image::MFM: extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata)); break; } for(int i=0; i<f.sector_count; i++) { desc_s &ds = sdesc[i]; desc_xs &xs = sectors[ds.sector_id]; if(!xs.data) memset((void *)ds.data, 0, ds.size); else if(xs.size < ds.size) { memcpy((void *)ds.data, xs.data, xs.size); memset((UINT8 *)ds.data + xs.size, 0, xs.size - ds.size); } else memcpy((void *)ds.data, xs.data, ds.size); } }
int g64_format::generate_bitstream(int track, int head, int speed_zone, UINT8 *trackbuf, int &track_size, floppy_image *image) { int cell_size = c1541_cell_size[speed_zone]; generate_bitstream_from_track(track, head, cell_size, trackbuf, track_size, image); int actual_cell_size = 200000000L/track_size; // allow a tolerance of +- 10 us (3990..4010 -> 4000) return ((actual_cell_size >= cell_size-10) && (actual_cell_size <= cell_size+10)) ? speed_zone : -1; }
void upd765_format::check_compatibility(floppy_image *image, int *candidates, int &candidates_count) { UINT8 bitstream[500000/8]; UINT8 sectdata[50000]; desc_xs sectors[256]; int track_size; // Extract the sectors generate_bitstream_from_track(0, 0, formats[candidates[0]].cell_size, bitstream, track_size, image); switch (formats[candidates[0]].encoding) { case floppy_image::FM: extract_sectors_from_bitstream_fm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata)); break; case floppy_image::MFM: extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata)); break; } // Check compatibility with every candidate, copy in-place int *ok_cands = candidates; for(int i=0; i != candidates_count; i++) { const format &f = formats[candidates[i]]; int ns = 0; for(int j=0; j<256; j++) if(sectors[j].data) { int sid; if(f.sector_base_id == -1) { for(sid=0; sid < f.sector_count; sid++) if(f.per_sector_id[sid] == j) break; } else sid = j - f.sector_base_id; if(sid < 0 || sid > f.sector_count) goto fail; if(f.sector_base_size) { if(sectors[j].size != f.sector_base_size) goto fail; } else { if(sectors[j].size != f.per_sector_size[sid]) goto fail; } ns++; } if(ns == f.sector_count) *ok_cands++ = candidates[i]; fail: ; } candidates_count = ok_cands - candidates; }
bool vdk_format::save(io_generic *io, floppy_image *image) { uint8_t bitstream[500000/8]; uint8_t sector_data[50000]; desc_xs sectors[256]; uint64_t file_offset = 0; int track_count, head_count; image->get_actual_geometry(track_count, head_count); // write header uint8_t header[12]; header[0] = 'd'; header[1] = 'k'; header[2] = sizeof(header) % 0x100; header[3] = sizeof(header) / 0x100; header[4] = 0x10; header[5] = 0x10; header[6] = 'M'; header[7] = 0x01; header[8] = track_count; header[9] = head_count; header[10] = 0; header[11] = 0; io_generic_write(io, header, file_offset, sizeof(header)); file_offset += sizeof(header); // write disk data for (int track = 0; track < track_count; track++) { for (int head = 0; head < head_count; head++) { int track_size; generate_bitstream_from_track(track, head, 2000, bitstream, track_size, image); extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sector_data, sizeof(sector_data)); for (int i = 0; i < SECTOR_COUNT; i++) { io_generic_write(io, sectors[FIRST_SECTOR_ID + i].data, file_offset, SECTOR_SIZE); file_offset += SECTOR_SIZE; } } } return true; }
bool mfm_format::save(io_generic *io, floppy_image *image) { // TODO: HD support MFMIMG header; int track_count, head_count; image->get_actual_geometry(track_count, head_count); memcpy(&header.headername, MFM_FORMAT_HEADER, 7); header.number_of_track = track_count; header.number_of_side = head_count; header.floppyRPM = 0; header.floppyBitRate = 250; header.floppyiftype = 4; header.mfmtracklistoffset = sizeof(MFMIMG); io_generic_write(io, &header, 0, sizeof(MFMIMG)); int tpos = sizeof(MFMIMG); int dpos = tpos + track_count*head_count*sizeof(MFMTRACKIMG); UINT8 trackbuf[150000/8]; for(int track=0; track < track_count; track++) { for(int side=0; side < head_count; side++) { int track_size; generate_bitstream_from_track(track, side, 2000, trackbuf, track_size, image); track_size = (track_size+7)/8; MFMTRACKIMG trackdesc; trackdesc.track_number = track; trackdesc.side_number = side; trackdesc.mfmtracksize = track_size; trackdesc.mfmtrackoffset = dpos; io_generic_write(io, &trackdesc, tpos, sizeof(MFMTRACKIMG)); io_generic_write(io, trackbuf, dpos, track_size); tpos += sizeof(MFMTRACKIMG); dpos += track_size; } } return true; }
bool jvc_format::save(io_generic *io, floppy_image *image) { UINT8 bitstream[500000/8]; UINT8 sector_data[50000]; desc_xs sectors[256]; UINT64 file_offset = 0; int track_count, head_count; image->get_actual_geometry(track_count, head_count); // we'll write a header if the disk is two-sided if (head_count == 2) { UINT8 header[2]; header[0] = 18; header[1] = 2; io_generic_write(io, header, file_offset, sizeof(header)); file_offset += sizeof(header); } // write disk data for (int track = 0; track < track_count; track++) { for (int head = 0; head < head_count; head++) { int track_size; generate_bitstream_from_track(track, head, 2000, bitstream, track_size, image); extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sector_data, sizeof(sector_data)); for (int i = 0; i < 18; i++) { if (sectors[1 + i].size != 256) emu_fatalerror("jvc_format: invalid sector size: %d\n", sectors[1 + i].size); io_generic_write(io, sectors[1 + i].data, file_offset, sectors[1 + i].size); file_offset += sectors[1 + i].size; } } } return true; }
bool ti99_floppy_format::save(io_generic *io, floppy_image *image) { int act_track_size = 0; UINT8 bitstream[500000/8]; UINT8 trackdata[9216]; // max size int cellsizes[] = { 2000, 4000, 1000, 2000 }; // Do we use double-stepping? // If our image was loaded into a 80-track drive, we will always write 80 tracks. int maxtrack, maxheads; image->get_maximal_geometry(maxtrack, maxheads); if (maxtrack > 80) maxtrack = 80; else { if (maxtrack > 35 && maxtrack < 80) maxtrack = 40; else maxtrack = 35; } int attempt = 0; int sector[36]; int maxsect = 18; bool write = true; // We expect a bitstream of length 50000 for FM and 100000 for MFM for(int head=0; head < 2; head++) { int track = 0; while (track < maxtrack) { int cell_size = cellsizes[attempt]; int encoding = get_encoding(cell_size); int track_size = get_track_size(cell_size, 36); // max number of sectors // Retrieve the cells from the flux sequence generate_bitstream_from_track(track, head, cell_size, bitstream, act_track_size, image); // Maybe the track has become longer due to moving splices if (act_track_size > 200000000/cell_size) act_track_size = 200000000/cell_size; int marks = decode_bitstream(bitstream, trackdata, sector, act_track_size, encoding, (encoding==floppy_image::FM)? 0xff:0x4e, track_size); if (track==0) { if (head==0) { // Find the highest sector in the track // This is only needed for the SDF format int i=35; while (i>=0 && sector[i]==-1) i--; if (i>18) maxsect = 36; else { if (i>16) maxsect = 18; else { if (i>9) maxsect = 16; else maxsect = 9; } } if (TRACE) osd_printf_info("ti99_dsk: Sectors/track: %d\n", maxsect); // We try different cell sizes until we find a fitting size. // If this fails, we fall back to a size of 2000 ns // The criterion for a successful decoding is that we find at least // 6 ID or data address marks on the track. It is highly unlikely // to find so many marks with a wrong cell size. if (marks < 6 && attempt < 4) { if (TRACE) osd_printf_verbose("ti99_dsk: Decoding with cell size %d failed.\n", cell_size); attempt++; write = false; } else write = true; } else { if (marks < 6) { if (min_heads()==1) { if (TRACE) osd_printf_info("ti99_dsk: We don't have a second side and the format allows for single-sided recording.\n"); return true; } else { osd_printf_warning("ti99_dsk: No second side, but this format requires two-sided recording. Saving empty tracks.\n"); } } } } if (write) { if (TRACE) { if (head == 0 && track == 0) { if (marks >=6) { if (TRACE) osd_printf_info("ti99_dsk: Decoding with cell size %d successful.\n", cell_size); } else osd_printf_info("ti99_dsk: No address marks found on track 0. Assuming MFM format.\n"); } } // Save to the file write_track(io, trackdata, sector, track, head, maxsect, maxtrack, track_size); track++; } } } return true; }