diff options
Diffstat (limited to 'trunk/src/lib/formats/cqm_dsk.c')
-rw-r--r-- | trunk/src/lib/formats/cqm_dsk.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/trunk/src/lib/formats/cqm_dsk.c b/trunk/src/lib/formats/cqm_dsk.c new file mode 100644 index 00000000000..0b15e44e216 --- /dev/null +++ b/trunk/src/lib/formats/cqm_dsk.c @@ -0,0 +1,228 @@ +/********************************************************************* + + formats/cqm_dsk.c + + CopyQM disk images + +*********************************************************************/ + +#include <string.h> +#include "flopimg.h" + +#define CQM_HEADER_SIZE 133 + +struct cqmdsk_tag +{ + int heads; + int tracks; + int sector_size; + int sector_per_track; + int sector_base; + int interleave; + int skew; + + UINT8* buf; + UINT64 track_offsets[84*2]; /* offset within data for each track */ +}; + + +static struct cqmdsk_tag *get_tag(floppy_image_legacy *floppy) +{ + struct cqmdsk_tag *tag; + tag = (cqmdsk_tag *)floppy_tag(floppy ); + return tag; +} + + + +FLOPPY_IDENTIFY( cqm_dsk_identify ) +{ + UINT8 header[2]; + + floppy_image_read(floppy, header, 0, 2); + if (header[0]=='C' && header[1]=='Q') { + *vote = 100; + } else { + *vote = 0; + } + return FLOPPY_ERROR_SUCCESS; +} + +static int cqm_get_heads_per_disk(floppy_image_legacy *floppy) +{ + return get_tag(floppy)->heads; +} + +static int cqm_get_tracks_per_disk(floppy_image_legacy *floppy) +{ + return get_tag(floppy)->tracks; +} + +static UINT64 cqm_get_track_offset(floppy_image_legacy *floppy, int head, int track) +{ + return get_tag(floppy)->track_offsets[(track<<1) + head]; +} + +static floperr_t get_offset(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, UINT64 *offset) +{ + UINT64 pos = 0; + UINT8 data; + INT16 len; + int s; + + if ((head < 0) || (head >= get_tag(floppy)->heads) || (track < 0) || (track >= get_tag(floppy)->tracks) + || (sector < 0) ) + return FLOPPY_ERROR_SEEKERROR; + + pos = cqm_get_track_offset(floppy,head,track); + s = 0; + do { + floppy_image_read(floppy, &len, pos, 2); + pos+=2; + if(len<0) { + floppy_image_read(floppy, &data, pos, 1); + memset(get_tag(floppy)->buf + s,data, -len); + pos++; + s += -len; + } else { + floppy_image_read(floppy, get_tag(floppy)->buf + s, pos, len); + pos+=len; + s += len; + } + } while(s<get_tag(floppy)->sector_size*get_tag(floppy)->sector_per_track); + + if (offset) + *offset = sector * get_tag(floppy)->sector_size; + return FLOPPY_ERROR_SUCCESS; +} + + + +static floperr_t internal_cqm_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, void *buffer, size_t buflen) +{ + UINT64 offset; + floperr_t err; + + // take sector offset + err = get_offset(floppy, head, track, sector, sector_is_index, &offset); + if (err) + return err; + memcpy(buffer,get_tag(floppy)->buf+offset,buflen); + return FLOPPY_ERROR_SUCCESS; +} + + +static floperr_t cqm_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen) +{ + return internal_cqm_read_sector(floppy, head, track, sector, FALSE, buffer, buflen); +} + +static floperr_t cqm_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen) +{ + return internal_cqm_read_sector(floppy, head, track, sector, TRUE, buffer, buflen); +} + +static floperr_t cqm_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, UINT32 *sector_length) +{ + floperr_t err; + err = get_offset(floppy, head, track, sector, FALSE, NULL); + if (err) + return err; + + if (sector_length) { + *sector_length = get_tag(floppy)->sector_size; + } + return FLOPPY_ERROR_SUCCESS; +} + +static floperr_t cqm_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags) +{ + if (sector_index >= get_tag(floppy)->sector_per_track) return FLOPPY_ERROR_SEEKERROR; + + if (cylinder) { + *cylinder = track; + } + if (side) { + *side = head; + } + if (sector) { + *sector = get_tag(floppy)->sector_base + sector_index; + } + if (sector_length) { + *sector_length = get_tag(floppy)->sector_size; + } + if (flags) + *flags = 0; + return FLOPPY_ERROR_SUCCESS; +} + +FLOPPY_CONSTRUCT( cqm_dsk_construct ) +{ + struct FloppyCallbacks *callbacks; + struct cqmdsk_tag *tag; + UINT8 header[CQM_HEADER_SIZE]; + UINT64 pos = 0; + INT16 len; + int head; + int track; + int s; + if(params) + { + // create + return FLOPPY_ERROR_UNSUPPORTED; + } + + tag = (struct cqmdsk_tag *) floppy_create_tag(floppy, sizeof(struct cqmdsk_tag)); + if (!tag) + return FLOPPY_ERROR_OUTOFMEMORY; + + floppy_image_read(floppy, header, 0, CQM_HEADER_SIZE); + + tag->sector_size = (header[0x04] << 8) + header[0x03]; + tag->sector_per_track = header[0x10]; + tag->heads = header[0x12]; + tag->tracks = header[0x5b]; + tag->sector_base = header[0x71] + 1; + tag->interleave = header[0x74]; + tag->skew = header[0x75]; + + // header + comment size to position on first data block + + pos = CQM_HEADER_SIZE + (header[0x70] << 8) + header[0x6f]; + track = 0; + head = 0; + tag->buf = (UINT8*)malloc(tag->sector_size*tag->sector_per_track); + do { + tag->track_offsets[(track<<1) + head] = pos; + s = 0; + do { + floppy_image_read(floppy, &len, pos, 2); + pos+=2; + if(len<0) { + pos++; + s += -len; + } else { + pos+=len; + s += len; + } + } while(s<tag->sector_size*tag->sector_per_track); + if(head ==0 && tag->heads > 1) { + head = 1; + } else { + head = 0; + track++; + } + } while(pos < floppy_image_size(floppy)); + + + callbacks = floppy_callbacks(floppy); + callbacks->read_sector = cqm_read_sector; + callbacks->read_indexed_sector = cqm_read_indexed_sector; + callbacks->get_sector_length = cqm_get_sector_length; + callbacks->get_heads_per_disk = cqm_get_heads_per_disk; + callbacks->get_tracks_per_disk = cqm_get_tracks_per_disk; + callbacks->get_indexed_sector_info = cqm_get_indexed_sector_info; + + return FLOPPY_ERROR_SUCCESS; +} + |