static floperr_t g64_read_track(floppy_image_legacy *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen) { /* The following is written into the buffer: n bytes of track data 1982 bytes of speed zone data get_track_size() returns n (size of track data) */ struct g64dsk_tag *tag = get_tag(floppy); floperr_t err; UINT64 track_offset; UINT16 track_length = tag->track_size[head][track]; // get track offset err = get_track_offset(floppy, head, track, &track_offset); if (err) return err; if ((head <= tag->heads) && track_offset) { if (buflen < track_length) { printf("G64 track buffer too small: %u < %u!", (UINT32)buflen, track_length); exit(-1); } // read track data floppy_image_read(floppy, ((UINT8*)buffer), track_offset + 2, track_length); // skip the 2 track length bytes in the beginning of track data if (tag->speed_zone_offset[head][track] > 3) { // read speed block floppy_image_read(floppy, ((UINT8*)buffer) + track_length, tag->speed_zone_offset[head][track], G64_SPEED_BLOCK_SIZE); } else { // create a speed block with the same speed zone for the whole track UINT8 speed = tag->speed_zone_offset[head][track] & 0x03; UINT8 speed_byte = (speed << 6) | (speed << 4) | (speed << 2) | speed; memset(((UINT8*)buffer) + track_length, speed_byte, G64_SPEED_BLOCK_SIZE); } LOG_FORMATS("G64 side %u track %.1f length %u\n", head, get_dos_track(track), track_length); } else { // no data for given track, or tried to read side 1 memset(((UINT8*)buffer), 0, buflen); LOG_FORMATS("G64 side %u track %.1f\n", head, get_dos_track(track)); } return FLOPPY_ERROR_SUCCESS; }
static floperr_t g64_read_track(floppy_image *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen) { struct g64dsk_tag *tag = get_tag(floppy); floperr_t err; UINT64 track_offset; UINT16 track_length = 0; /* get track offset */ err = get_track_offset(floppy, head, track, &track_offset); if (err) return err; if (!head && track_offset) { if (buflen < tag->track_size) { printf("G64 track buffer too small: %u!", (UINT32)buflen); exit(-1); } /* read track */ floppy_image_read(floppy, buffer, track_offset + 2, tag->track_size); } else { /* set track length to 0 */ memset(buffer, 0, buflen); } if (LOG) LOG_FORMATS("G64 track %.1f length %u\n", get_dos_track(track), track_length); return FLOPPY_ERROR_SUCCESS; }
static void read_g64_header(floppy_image_legacy *floppy, struct g64dsk_tag *tag, int head, UINT64 &pos) { UINT8 header[HEADER_LENGTH]; UINT64 start_pos = pos; // read header floppy_image_read(floppy, header, pos, HEADER_LENGTH); // get version tag->version = header[8]; if (!head) LOG_FORMATS("G64 version: %u\n", tag->version); // get number of tracks tag->tracks = header[9]; LOG_FORMATS("G64 side %u tracks: %u\n", head, tag->tracks); // get track size UINT16 track_size = (header[0xb] << 8) | header[0xa]; // get data offsets pos = 0xc; for (int i = 0; i < tag->tracks; i++) { tag->track_offset[head][i] = pick_integer_le(header, pos, 4); if (tag->track_offset[head][i]) { tag->track_offset[head][i] += start_pos; } pos += 4; } // get speed zone information UINT32 track_offs = 0; for (int i = 0; i < tag->tracks; i++) { tag->speed_zone_offset[head][i] = pick_integer_le(header, pos, 4); if (tag->speed_zone_offset[head][i] >= 4) { tag->speed_zone_offset[head][i] += start_pos; } pos += 4; tag->track_size[head][i] = g64_get_track_size(floppy, head, i); if (tag->track_offset[head][i] != 0) { LOG_FORMATS("G64 side %u track %.1f offset %05x length %04x ", head, get_dos_track(i), tag->track_offset[head][i], tag->track_size[head][i]); track_offs = tag->track_offset[head][i]; if (tag->speed_zone_offset[head][i] < 4) { LOG_FORMATS("speed %u\n", tag->speed_zone_offset[head][i]); } else { LOG_FORMATS("speed offset %04x\n", tag->speed_zone_offset[head][i]); } } } pos = track_offs + 2 + track_size; }