diff --git a/src/lib/formats/g64_dsk.c b/src/lib/formats/g64_dsk.c index 395dac5cc5a..6b89b266503 100644 --- a/src/lib/formats/g64_dsk.c +++ b/src/lib/formats/g64_dsk.c @@ -4,30 +4,31 @@ Floppy format code for Commodore 1541 GCR disk images + http://www.unusedino.de/ec64/technical/formats/g64.html + *********************************************************************/ /* TODO: - - speed zones - - writing + - write to disk */ #define XTAL_16MHz 16000000 #define XTAL_12MHz 12000000 + #include "g64_dsk.h" #include "flopimg.h" +#include "imageutl.h" /*************************************************************************** PARAMETERS ***************************************************************************/ -#define LOG 0 - -#define HEADER_LENGTH 0x2ac /* standard length for 84 half tracks */ -#define MAX_TRACKS 84 +#define HEADER_LENGTH 0x2ac // standard length for 84 half tracks +#define MAX_TRACKS 84 /*************************************************************************** TYPE DEFINITIONS @@ -36,11 +37,11 @@ struct g64dsk_tag { int version; - int heads; /* number of physical heads */ - int tracks; /* number of physical tracks */ - UINT16 track_size; /* size of each track */ - UINT32 track_offset[MAX_TRACKS]; /* offset within data for each track */ - UINT32 speed_zone_offset[MAX_TRACKS]; /* offset within data for each track */ + int heads; // number of physical heads + int tracks; // number of physical tracks + UINT16 track_size[MAX_TRACKS]; // size of each track + UINT32 track_offset[MAX_TRACKS]; // offset within data for each track + UINT32 speed_zone_offset[MAX_TRACKS]; // offset within data for each track }; /*************************************************************************** @@ -108,17 +109,21 @@ static floperr_t get_track_offset(floppy_image_legacy *floppy, int head, int tra static UINT32 g64_get_track_size(floppy_image_legacy *floppy, int head, int track) { - /* get track offset */ + // get track offset + UINT32 track_length = 0; UINT64 track_offset; floperr_t err = get_track_offset(floppy, head, track, &track_offset); if (err) return 0; - /* read track length */ - UINT8 size[2]; - floppy_image_read(floppy, &size, track_offset, 2); - UINT32 track_length = (size[1] << 8) | size[0]; + // read track length + if (track_offset > 0) + { + UINT8 size[2]; + floppy_image_read(floppy, &size, track_offset, 2); + track_length = pick_integer_le(size, 0, 2); + } return track_length; } @@ -130,12 +135,23 @@ static UINT32 g64_get_track_size(floppy_image_legacy *floppy, int head, int trac 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 = 0; + UINT16 track_length = tag->track_size[track]; - /* get track offset */ + // get track offset err = get_track_offset(floppy, head, track, &track_offset); if (err) @@ -143,18 +159,32 @@ static floperr_t g64_read_track(floppy_image_legacy *floppy, int head, int track if (!head && track_offset) { - if (buflen < tag->track_size) { printf("G64 track buffer too small: %u!", (UINT32)buflen); exit(-1); } + if (buflen < track_length) { printf("G64 track buffer too small: %u < %u!", (UINT32)buflen, track_length); exit(-1); } - /* read track */ - floppy_image_read(floppy, buffer, track_offset + 2, tag->track_size); + // 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[track] > 3) + { + // read speed block + floppy_image_read(floppy, ((UINT8*)buffer) + track_length, tag->speed_zone_offset[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[track] & 0x03; + UINT8 speed_byte = (speed << 6) | (speed << 4) | (speed << 2) | speed; + + memset(((UINT8*)buffer) + track_length, speed_byte, G64_SPEED_BLOCK_SIZE); + } } else { - /* set track length to 0 */ - memset(buffer, 0, buflen); + // no data for given track, or tried to read side 1 + memset(((UINT8*)buffer), 0, buflen); } - if (LOG) LOG_FORMATS("G64 track %.1f length %u\n", get_dos_track(track), track_length); + LOG_FORMATS("G64 track %.1f length %u\n", get_dos_track(track), track_length); return FLOPPY_ERROR_SUCCESS; } @@ -231,12 +261,12 @@ FLOPPY_CONSTRUCT( g64_dsk_construct ) struct FloppyCallbacks *callbacks; struct g64dsk_tag *tag; UINT8 header[HEADER_LENGTH]; - UINT64 pos = 0; + UINT64 pos = 0xc; int i; if (params) { - /* create not supported */ + // create not supported return FLOPPY_ERROR_UNSUPPORTED; } @@ -244,46 +274,46 @@ FLOPPY_CONSTRUCT( g64_dsk_construct ) if (!tag) return FLOPPY_ERROR_OUTOFMEMORY; - /* version */ - floppy_image_read(floppy, header, pos, 0x0c); pos += 0xc; - tag->version = header[8]; - if (LOG) LOG_FORMATS("G64 version: %u\n", tag->version); + // read header + floppy_image_read(floppy, header, 0, HEADER_LENGTH); - /* number of half tracks */ + // get version + tag->version = header[8]; + LOG_FORMATS("G64 version: %u\n", tag->version); + + // get number of tracks tag->heads = 1; tag->tracks = header[9]; - if (LOG) LOG_FORMATS("G64 tracks: %u\n", tag->tracks); + LOG_FORMATS("G64 tracks: %u\n", tag->tracks); - /* size of each stored half track */ - tag->track_size = (header[11] << 8) | header[10]; - if (LOG) LOG_FORMATS("G64 track size: %04x\n", tag->track_size); - - /* data offsets */ + // get data offsets for (i = 0; i < tag->tracks; i++) { - floppy_image_read(floppy, header, pos, 4); pos += 4; - tag->track_offset[i] = (header[3] << 24) | (header[2] << 16) | (header[1] << 8) | header[0]; - - if (LOG) LOG_FORMATS("G64 track %.1f data offset: %04x\n", get_dos_track(i), tag->track_offset[i]); + tag->track_offset[i] = pick_integer_le(header, pos, 4); + pos += 4; } - /* speed zone offsets */ + // get speed zone information for (i = 0; i < tag->tracks; i++) { - floppy_image_read(floppy, header, pos, 4); pos += 4; - tag->speed_zone_offset[i] = (header[3] << 24) | (header[2] << 16) | (header[1] << 8) | header[0]; + tag->speed_zone_offset[i] = pick_integer_le(header, pos, 4); + pos += 4; - if (LOG) + tag->track_size[i] = g64_get_track_size(floppy, 0, i); + + if (tag->track_offset[i] > 0) { + LOG_FORMATS("G64 track %.1f offset %05x length %04x ", get_dos_track(i), tag->track_offset[i], tag->track_size[i]); + if (tag->speed_zone_offset[i] < 4) { - LOG_FORMATS("G64 track %.1f speed zone: %u\n", get_dos_track(i), tag->speed_zone_offset[i]); + LOG_FORMATS("speed %u\n", tag->speed_zone_offset[i]); } else { - LOG_FORMATS("G64 track %.1f speed zone offset: %04x\n", get_dos_track(i), tag->speed_zone_offset[i]); + LOG_FORMATS("speed offset %04x\n", tag->speed_zone_offset[i]); } } } - /* set callbacks */ + // set callbacks callbacks = floppy_callbacks(floppy); callbacks->read_track = g64_read_track; diff --git a/src/lib/formats/g64_dsk.h b/src/lib/formats/g64_dsk.h index 20c5a6d253b..d8f793de514 100644 --- a/src/lib/formats/g64_dsk.h +++ b/src/lib/formats/g64_dsk.h @@ -15,9 +15,10 @@ MACROS / CONSTANTS ***************************************************************************/ -#define G64_SYNC_MARK 0x3ff /* 10 consecutive 1-bits */ +#define G64_SYNC_MARK 0x3ff /* 10 consecutive 1-bits */ -#define G64_BUFFER_SIZE 16384 +#define G64_BUFFER_SIZE 16384 +#define G64_SPEED_BLOCK_SIZE 1982 const int C2040_BITRATE[] = {