/* This is a .D88 disc image format. */ #include "driver.h" #include "includes/d88.h" #include "devices/flopdrv.h" #include "image.h" #define d88image_MAX_DRIVES 4 #define VERBOSE 1 static d88image d88image_drives[d88image_MAX_DRIVES]; static void d88image_seek_callback(mess_image *img,int); static int d88image_get_sectors_per_track(mess_image *img,int); static void d88image_get_id_callback(mess_image *img, chrn_id *, int, int); static void d88image_read_sector_data_into_buffer(mess_image *img, int side, int index1, char *ptr, int length); static void d88image_write_sector_data_from_buffer(mess_image *img, int side, int index1, const char *ptr, int length,int ddam); static floppy_interface d88image_floppy_interface= { d88image_seek_callback, d88image_get_sectors_per_track, /* done */ d88image_get_id_callback, /* done */ d88image_read_sector_data_into_buffer, /* done */ d88image_write_sector_data_from_buffer, /* done */ NULL, NULL }; static d88image *get_d88image(mess_image *img) { return &d88image_drives[image_index_in_device(img)]; } DEVICE_INIT(d88image_floppy) { return floppy_drive_init(image, &d88image_floppy_interface); } /* attempt to insert a disk into the drive specified with id */ DEVICE_LOAD(d88image_floppy) { UINT8 tmp8; UINT16 tmp16; UINT32 tmp32; int i,j,k; unsigned long toffset; d88image *w; int id = image_index_in_device(image); assert(id < d88image_MAX_DRIVES); w = &d88image_drives[id]; w->image_file = image; w->mode = image_is_writable(image); /* the following line is unsafe, but floppy_drives_init assumes we start on track 0, so we need to reflect this */ w->track = 0; image_fread(w->image_file, w->disk_name, 17); for(i=0;i<9;i++) image_fread(w->image_file, &tmp8, 1); image_fread(w->image_file, &tmp8, 1); w->write_protected = (tmp8&0x10 || !w->mode); image_fread(w->image_file, &tmp8, 1); w->disktype = tmp8 >> 4; image_fread(w->image_file, &tmp32, 4); w->image_size = LITTLE_ENDIANIZE_INT32(tmp32); for(i = 0; iimage_file, 0x20 + i*4, SEEK_SET); image_fread(w->image_file, &tmp32, 4); toffset = LITTLE_ENDIANIZE_INT32(tmp32); if(toffset) { image_fseek(w->image_file, toffset + 4, SEEK_SET); image_fread(w->image_file, &tmp16, 2); w->num_sects[i] = LITTLE_ENDIANIZE_INT16(tmp16); w->sects[i] = image_malloc(image, sizeof(d88sect)*w->num_sects[i]); image_fseek(w->image_file, toffset, SEEK_SET); for(j=0;jnum_sects[i];j++) { image_fread(w->image_file, &(w->sects[i][j].C), 1); image_fread(w->image_file, &(w->sects[i][j].H), 1); image_fread(w->image_file, &(w->sects[i][j].R), 1); image_fread(w->image_file, &(w->sects[i][j].N), 1); image_fread(w->image_file, &tmp16, 2); image_fread(w->image_file, &tmp8, 1); w->sects[i][j].den=tmp8&0x40 ? (w->disktype==2 ? DEN_FM_HI : DEN_FM_LO) : (w->disktype==2 ? DEN_MFM_HI : DEN_MFM_LO); image_fread(w->image_file, &tmp8, 1); w->sects[i][j].flags=tmp8&0x10 ? ID_FLAG_DELETED_DATA : 0; image_fread(w->image_file, &tmp8, 1); switch(tmp8 & 0xf0) { case 0xa0: w->sects[i][j].flags|=ID_FLAG_CRC_ERROR_IN_ID_FIELD; break; case 0xb0: w->sects[i][j].flags|=ID_FLAG_CRC_ERROR_IN_DATA_FIELD; break; } for(k=0;k<5;k++) image_fread(w->image_file, &tmp8, 1); image_fread(w->image_file, &tmp16, 2); w->sects[i][j].offset = image_ftell(w->image_file); image_fseek(w->image_file, LITTLE_ENDIANIZE_INT16(tmp16), SEEK_CUR); } } else { w->num_sects[i] = 0; w->sects[i]=NULL; } } return INIT_PASS; } /* seek to track/head/sector relative position in image file */ static int d88image_seek(d88image * w, UINT8 t, UINT8 h, UINT8 s) { unsigned long offset; /* allow two additional tracks */ if (t >= D88_NUM_TRACK/2) { logerror("d88image track %d >= %d\n", t, D88_NUM_TRACK/2); return 0; } if (h >= 2) { logerror("d88image head %d >= %d\n", h, 2); return 0; } if (s >= w->num_sects[t*2+h]) { logerror("d88image sector %d\n", w->num_sects[t*2+h]); return 0; } offset = w->sects[t*2+h][s].offset; #if VERBOSE logerror("d88image seek track:%d head:%d sector:%d-> offset #0x%08lX\n", t, h, s, offset); #endif if (offset > w->image_size) { logerror("d88image seek offset %ld >= %ld\n", offset, w->image_size); return 0; } if (image_fseek(w->image_file, offset, SEEK_SET) < 0) { logerror("d88image seek failed\n"); return 0; } return 1; } static void d88image_get_id_callback(mess_image *img, chrn_id *id, int id_index, int side) { d88image *w = get_d88image(img); d88sect *s = &(w->sects[w->track*2+side][id_index]); /* construct a id value */ id->C = s->C; id->H = s->H; id->R = s->R; id->N = s->N; id->data_id = id_index; id->flags = s->flags; } static int d88image_get_sectors_per_track(mess_image *img, int side) { d88image *w = get_d88image(img); /* attempting to access an invalid side or track? */ if ((side>=2) || (w->track>=D88_NUM_TRACK/2)) { /* no sectors */ return 0; } /* return number of sectors per track */ return w->num_sects[w->track*2+side]; } static void d88image_seek_callback(mess_image *img, int physical_track) { d88image *w = get_d88image(img); w->track = physical_track; } static void d88image_write_sector_data_from_buffer(mess_image *img, int side, int index1, const char *ptr, int length, int ddam) { d88image *w = get_d88image(img); d88sect *s = &(w->sects[w->track*2+side][index1]); if (d88image_seek(w, w->track, side, index1)) { image_fwrite(w->image_file, ptr, length); } s->flags = ddam ? ID_FLAG_DELETED_DATA : 0; } static void d88image_read_sector_data_into_buffer(mess_image *img, int side, int index1, char *ptr, int length) { d88image *w = get_d88image(img); if (d88image_seek(w, w->track, side, index1)) { image_fread(w->image_file, ptr, length); } }