int td0dsk_t::data_read(UINT8 *buf, UINT16 size) { if (floppy_file_offset + size > io_generic_size(floppy_file) ) { size = io_generic_size(floppy_file) - floppy_file_offset; } io_generic_read(floppy_file,buf,floppy_file_offset,size); floppy_file_offset += size; return size; }
void rx50img_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { head_count = 1; uint32_t expected_size = 0; uint64_t size = io_generic_size(io); track_count = 80; sector_count = 10; expected_size = 512 * track_count * head_count * sector_count; if (size == expected_size) // standard format has 409600 byte return; /* track_count = 40; sector_count = 9; // [VT 180] expected_size = 512 * track_count * head_count * sector_count; if (size == expected_size) return; track_count = 40; sector_count = 8; // [DOS] expected_size = 512 * track_count * head_count * sector_count; if (size == expected_size) return; */ track_count = head_count = sector_count = 0; }
void io_generic_write(struct io_generic *generic, const void *buffer, UINT64 offset, size_t length) { UINT64 filler_size = 0; char filler_buffer[1024]; size_t bytes_to_write; UINT64 size; size = io_generic_size(generic); if (size < offset) { filler_size = offset - size; offset = size; } io_generic_seek(generic, offset); if (filler_size) { memset(filler_buffer, generic->filler, sizeof(buffer)); do { bytes_to_write = (filler_size > sizeof(filler_buffer)) ? sizeof(filler_buffer) : (size_t) filler_size; generic->procs->writeproc(generic->file, filler_buffer, bytes_to_write); filler_size -= bytes_to_write; } while(filler_size > 0); } if (length > 0) generic->procs->writeproc(generic->file, buffer, length); }
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; }
int mgt_format::identify(io_generic *io, UINT32 form_factor) { int size = io_generic_size(io); if(/*size == 737280 || */ size == 819200) return 50; return 0; }
int mgt_format::identify(io_generic *io, uint32_t form_factor) { uint64_t size = io_generic_size(io); if(/*size == 737280 || */ size == 819200) return 50; return 0; }
bool ipf_format::load(io_generic *io, floppy_image *image) { UINT32 size = io_generic_size(io); UINT8 *data = global_alloc_array(UINT8, size); io_generic_read(io, data, 0, size); bool res = parse(data, size, image); global_free(data); return res; }
int dip_format::identify(io_generic *io, UINT32 form_factor) { UINT64 size = io_generic_size(io); if (size == 0x134000 + 0x100) return 100; return 0; }
bool apd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image) { uint64_t size = io_generic_size(io); std::vector<uint8_t> img(size); io_generic_read(io, &img[0], 0, size); int err; std::vector<uint8_t> gz_ptr; z_stream d_stream; int inflate_size = (img[size - 1] << 24) | (img[size - 2] << 16) | (img[size - 3] << 8) | img[size - 4]; uint8_t *in_ptr = &img[0]; if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) { gz_ptr.resize(inflate_size); d_stream.zalloc = nullptr; d_stream.zfree = nullptr; d_stream.opaque = nullptr; d_stream.next_in = in_ptr; d_stream.avail_in = size; d_stream.next_out = &gz_ptr[0]; d_stream.avail_out = inflate_size; err = inflateInit2(&d_stream, MAX_WBITS | 16); if (err != Z_OK) { LOG_FORMATS("inflateInit2 error: %d\n", err); return false; } err = inflate(&d_stream, Z_FINISH); if (err != Z_STREAM_END && err != Z_OK) { LOG_FORMATS("inflate error: %d\n", err); return false; } err = inflateEnd(&d_stream); if (err != Z_OK) { LOG_FORMATS("inflateEnd error: %d\n", err); return false; } size = inflate_size; img = gz_ptr; } int data = 0x7d0; for (int track = 0; track < 166; track++) { uint32_t sdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x0])); uint32_t ddlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x4])); uint32_t qdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x8])); if (sdlen > 0) { generate_track_from_bitstream(track / 2, track % 2, &img[data], sdlen, image); data += (sdlen + 7) >> 3; } if (ddlen > 0) { generate_track_from_bitstream(track / 2, track % 2, &img[data], ddlen, image); data += (ddlen + 7) >> 3; }
void st_format::find_size(io_generic *io, int &track_count, int &head_count, int §or_count) { int size = io_generic_size(io); for(track_count=80; track_count <= 82; track_count++) for(head_count=1; head_count <= 2; head_count++) for(sector_count=9; sector_count <= 11; sector_count++) if(size == 512*track_count*head_count*sector_count) return; track_count = head_count = sector_count = 0; }
void st_format::find_size(io_generic *io, UINT8 &track_count, UINT8 &head_count, UINT8 §or_count) { UINT64 size = io_generic_size(io); for(track_count=80; track_count <= 82; track_count++) for(head_count=1; head_count <= 2; head_count++) for(sector_count=9; sector_count <= 11; sector_count++) if(size == (UINT32)512*track_count*head_count*sector_count) return; track_count = head_count = sector_count = 0; }
int td0dsk_t::data_read(uint8_t *buf, uint16_t size) { uint64_t image_size = io_generic_size(floppy_file); if (size > image_size - floppy_file_offset) { size = image_size - floppy_file_offset; } io_generic_read(floppy_file,buf,floppy_file_offset,size); floppy_file_offset += size; return size; }
int victor9k_format::find_size(io_generic *io, UINT32 form_factor) { UINT64 size = io_generic_size(io); for(int i=0; formats[i].sector_count; i++) { const format &f = formats[i]; if(size == (UINT32) f.sector_count*f.sector_base_size*f.head_count) return i; } return -1; }
int flex_format::identify(io_generic *io, UINT32 form_factor) { io_generic_read(io, &info, 256 * 2, sizeof(struct sysinfo_sector)); if(((info.last_trk+1) * info.last_sec) * 256 == io_generic_size(io)) { logerror("flex_dsk: %i tracks, %i sectors\n",info.last_trk+1,info.last_sec); return 100; } return 0; }
int d88_format::identify(io_generic *io, UINT32 form_factor) { UINT64 size = io_generic_size(io); UINT8 h[32]; io_generic_read(io, h, 0, 32); if((LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x1c)) == size) && (h[0x1b] == 0x00 || h[0x1b] == 0x10 || h[0x1b] == 0x20 || h[0x1b] == 0x30 || h[0x1b] == 0x40)) return 100; return 0; }
int d88_format::identify(io_generic *io, uint32_t form_factor) { uint64_t size = io_generic_size(io); uint8_t h[32]; io_generic_read(io, h, 0, 32); if((little_endianize_int32(*(uint32_t *)(h+0x1c)) == size) && (h[0x1b] == 0x00 || h[0x1b] == 0x10 || h[0x1b] == 0x20 || h[0x1b] == 0x30 || h[0x1b] == 0x40)) return 100; return 0; }
/* Default implementation for find_size. May be overwritten by subclasses. */ int wd177x_format::find_size(io_generic *io, uint32_t form_factor) { uint64_t size = io_generic_size(io); for(int i=0; formats[i].form_factor; i++) { const format &f = formats[i]; if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; if(size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; } return -1; }
int upd765_format::find_size(io_generic *io, UINT32 form_factor) { int size = io_generic_size(io); for(int i=0; formats[i].form_factor; i++) { const format &f = formats[i]; if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; if(size == compute_track_size(f) * f.track_count * f.head_count) return i; } return -1; }
void esqimg_format::find_size(io_generic *io, int &track_count, int &head_count, int §or_count) { int size = io_generic_size(io); track_count = 80; head_count = 2; sector_count = 10; if (size == 512*track_count*head_count*sector_count) { return; } track_count = head_count = sector_count = 0; }
void esq8img_format::find_size(io_generic *io, int &track_count, int &head_count, int §or_count) { int size = io_generic_size(io); track_count = 80; head_count = 1; sector_count = 6; if (size == 5632 * 80) { return; } track_count = head_count = sector_count = 0; }
bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { UINT64 size = io_generic_size(io); dynamic_buffer img(size); io_generic_read(io, &img[0], 0, size); if (img[POS_VERSION]) { throw emu_fatalerror("g64_format: Unsupported version %u", img[POS_VERSION]); } int track_count = img[POS_TRACK_COUNT]; int head = 0; for (int track = 0; track < track_count; track++) { int cylinder = track % TRACK_COUNT; if (track == TRACK_COUNT) head = 1; UINT32 tpos = POS_TRACK_OFFSET + (track * 4); UINT32 spos = tpos + (track_count * 4); UINT32 dpos = pick_integer_le(&img[0], tpos, 4); if (!dpos) continue; if (dpos > size) throw emu_fatalerror("g64_format: Track %u offset %06x out of bounds", track, dpos); UINT32 speed_zone = pick_integer_le(&img[0], spos, 4); if (speed_zone > 3) throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track); UINT16 track_bytes = pick_integer_le(&img[0], dpos, 2); int track_size = track_bytes * 8; LOG_FORMATS("head %u track %u offs %u size %u cell %ld\n", head, cylinder, dpos, track_bytes, 200000000L/track_size); generate_track_from_bitstream(cylinder, head, &img[dpos+2], track_size, image); } if (!head) image->set_variant(floppy_image::SSSD); else image->set_variant(floppy_image::DSSD); return true; }
bool victor9k_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]; UINT64 size = io_generic_size(io); dynamic_buffer img; img.resize(size); io_generic_read(io, img, 0, size); log_boot_sector(img); int track_offset = 0; for (int head = 0; head < f.head_count; head++) { for (int track = 0; track < f.track_count; track++) { int current_size = 0; int total_size = 200000000./cell_size[speed_zone[head][track]]; int sector_count = sectors_per_track[head][track]; int track_size = sector_count*f.sector_base_size; floppy_image_format_t::desc_e *desc = get_sector_desc(f, current_size, sector_count); int remaining_size = total_size - current_size; if(remaining_size < 0) throw emu_fatalerror("victor9k_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size); // Fixup the end gap desc[18].p2 = remaining_size / 8; desc[19].p2 = remaining_size & 7; desc[19].p1 >>= remaining_size & 0x01; desc_s sectors[40]; build_sector_description(f, img, track_offset, sectors, sector_count); generate_track(desc, track, head, sectors, sector_count, total_size, image); track_offset += track_size; } } image->set_variant(f.variant); return true; }
void cc525dsdd_format::find_size(io_generic *io, UINT8 &track_count, UINT8 &head_count, UINT8 §or_count) { UINT64 size = io_generic_size(io); track_count = 77; head_count = 2; sector_count = 9; UINT32 expected_size = 512 * track_count*head_count*sector_count; if (size == expected_size) { return; } track_count = head_count = sector_count = 0; }
int pc98fdi_format::identify(io_generic *io, UINT32 form_factor) { UINT64 size = io_generic_size(io); UINT8 h[32]; io_generic_read(io, h, 0, 32); UINT32 hsize = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0x8)); UINT32 psize = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0xc)); UINT32 ssize = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0x10)); UINT32 scnt = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0x14)); UINT32 sides = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0x18)); UINT32 ntrk = LITTLE_ENDIANIZE_INT32(*(UINT32 *) (h + 0x1c)); if(size == hsize + psize && psize == ssize*scnt*sides*ntrk) return 100; return 0; }
int poly_cpm_format::identify(io_generic *io, uint32_t form_factor) { uint8_t boot[16]; uint64_t size = io_generic_size(io); // check for valid sizes if (size == 630784 || size == 622592 || size == 256256) { // check for Poly CP/M boot sector io_generic_read(io, boot, 0, 16); if (memcmp(boot, "\x86\xc3\xb7\x00\x00\x8e\x10\xc0\xbf\x00\x01\xbf\xe0\x60\x00\x00", 16) == 0) { return 100; } } return 0; }
void io_generic_read(struct io_generic *generic, void *buffer, UINT64 offset, size_t length) { UINT64 size; size_t bytes_read; size = io_generic_size(generic); if (size <= offset) { bytes_read = 0; } else { io_generic_seek(generic, offset); bytes_read = generic->procs->readproc(generic->file, buffer, length); } memset(((UINT8 *) buffer) + bytes_read, generic->filler, length - bytes_read); }
int oric_dsk_format::identify(io_generic *io, UINT32 form_factor) { UINT8 h[256]; io_generic_read(io, h, 0, 256); if(memcmp(h, "MFM_DISK", 8)) return 0; 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]; int geom = (h[19] << 24) | (h[18] << 16) | (h[17] << 8) | h[16]; int size = io_generic_size(io); if(sides < 0 || sides > 2 || geom != 1 || size != 256+6400*sides*tracks) return 0; return 100; }
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); if (img[VERSION]) { throw emu_fatalerror("g64_format: Unsupported version %u", img[VERSION]); } int track_count = img[TRACK_COUNT]; int head = 0; for (int track = 0; track < track_count; track++) { offs_t track_offset = pick_integer_le(img, TRACK_OFFSET + (track * 4), 4); if (!track_offset) continue; if (track_offset > size) throw emu_fatalerror("g64_format: Track %u offset %06x out of bounds", track, track_offset); offs_t speed_zone = pick_integer_le(img, SPEED_ZONE + (track * 4), 4); if (speed_zone > 3) throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track); UINT16 track_bytes = pick_integer_le(img, track_offset, 2); int track_size = track_bytes * 8; LOG_FORMATS("track %u size %u cell %ld\n", track, track_size, 200000000L/track_size); generate_track_from_bitstream(track, head, &img[track_offset+2], track_size, image); } global_free(img); image->set_variant(floppy_image::SSSD); return true; }
int bbc_adfs_format::find_size(io_generic *io, UINT32 form_factor) { UINT8 map[3]; UINT32 sectors; // read sector count from free space map io_generic_read(io, map, 0xfc, 3); sectors = map[0] + (map[1] << 8) + (map[2] << 16); UINT64 size = io_generic_size(io); for(int i=0; formats[i].form_factor; i++) { const format &f = formats[i]; if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // valid images will have sector counts adfs-s = 0x280; adfs-m = 0x500; adfs-l = 0xa00; though many adfs-s images are incorrect if ((size == (UINT64)compute_track_size(f) * f.track_count * f.head_count) && (sectors == 0x280 || sectors == 0x500 || sectors == 0xa00)) { return i; } } return -1; }
int dmk_format::identify(io_generic *io, UINT32 form_factor) { const int header_size = 16; UINT8 header[header_size]; UINT64 size = io_generic_size(io); io_generic_read(io, header, 0, header_size); int tracks = header[1]; int track_size = ( header[3] << 8 ) | header[2]; int heads = (header[4] & 0x10) ? 1 : 2; // The first header byte must be 00 or FF if (header[0] != 0x00 && header[0] != 0xff) { return 0; } // Bytes C-F must be zero if (header[0x0c] != 0 || header[0xd] != 0 || header[0xe] != 0 || header[0xf] != 0) { return 0; } // Check track size within limits if (track_size < 0x80 || track_size > 0x3FFF ) { return 0; } if (size == header_size + heads * tracks * track_size) { return 70; } return 0; }