summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/lib/formats/cqm_dsk.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/lib/formats/cqm_dsk.c')
-rw-r--r--trunk/src/lib/formats/cqm_dsk.c228
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;
+}
+