// license:BSD-3-Clause // copyright-holders:Curt Coder /********************************************************************* formats/fdi_dsk.h Floppy format code for Formatted Disk Image (FDI) v2.0 images *********************************************************************/ /* TODO: - everything */ #include #include "imageutl.h" #include "flopimg.h" /*************************************************************************** PARAMETERS ***************************************************************************/ #define LOG 1 #define MAX_TRACKS 180 #define FLAGS_WRITE_PROTECTED 0x01 #define FLAGS_INDEX_SYNC 0x02 /* media type */ enum { TYPE_8_INCH = 0, TYPE_5_25_INCH, TYPE_3_5_INCH, TYPE_3_INCH }; static const char *const MEDIA_TYPE[] = { "8", "5.25", "3.5", "3" }; /* tracks per inch */ enum { TPI_48 = 0, TPI_67, TPI_96, TPI_100, TPI_135, TPI_192 }; static const int TRACKS_PER_INCH[] = { 48, 67, 96, 100, 135, 192 }; /* high level track types */ enum { TRACK_BLANK = 0, /* not supported */ TRACK_AMIGA_DD, /* not supported */ TRACK_AMIGA_HD, /* not supported */ TRACK_ST_DD_9, /* not supported */ TRACK_ST_DD_10, /* not supported */ TRACK_PC_DD_8, /* not supported */ TRACK_PC_DD_9, /* not supported */ TRACK_PC_HD_15, /* not supported */ TRACK_IBM_HD_18, /* not supported */ TRACK_IBM_ED_36, /* not supported */ TRACK_CBM_1541, /* not supported */ TRACK_APPLE_DOS_32, /* not supported */ TRACK_APPLE_DOS_33, /* not supported */ TRACK_APPLE_GCR, /* not supported */ TRACK_IBM_SD_10 /* not supported */ }; //static const int SECTORS_PER_TRACK[] = { 0, 11, 22, 9, 10, 8, 9, 15, 18, 36, -1, -1, -1, -1, 10 }; /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ struct fdidsk_tag { int version; int heads; /* number of physical heads */ int tracks; /* number of physical tracks */ uint32_t track_offset[MAX_TRACKS]; /* offset within data for each track */ uint8_t track_type[MAX_TRACKS]; }; struct fdi_track { uint8_t type; uint8_t size; }; struct fdi_header { uint8_t signature[27]; uint8_t creator[32]; uint8_t comment[80]; uint8_t eof; uint8_t version[2]; uint8_t ltrack[2]; uint8_t lhead; uint8_t type; uint8_t rotspeed; uint8_t flags; uint8_t tpi; uint8_t headwidth; uint8_t reserved[2]; struct fdi_track track[MAX_TRACKS]; }; struct fdi_pulse_track_header { uint8_t numpulses[4]; uint8_t averagesz[3]; uint8_t minsize[3]; uint8_t maxsize[3]; uint8_t indexsize[3]; // uint8_t averagedt[averagesz]; // uint8_t mindata[minsize]; // uint8_t maxdata[maxsize]; // uint8_t indexdata[indexsize]; }; /*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ static inline struct fdidsk_tag *get_tag(floppy_image_legacy *floppy) { return (fdidsk_tag *)floppy_tag(floppy); } /*************************************************************************** IMPLEMENTATION ***************************************************************************/ static int fdi_get_heads_per_disk(floppy_image_legacy *floppy) { return get_tag(floppy)->heads; } static int fdi_get_tracks_per_disk(floppy_image_legacy *floppy) { return get_tag(floppy)->tracks; } static int fdi_get_sectors_per_track(floppy_image_legacy *floppy, int head, int track) { return 0; } static floperr_t fdi_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length) { return FLOPPY_ERROR_SUCCESS; } /* static uint32_t fdi_get_sector_offset(floppy_image_legacy* floppy, int head, int track, int sector) { return 0; } */ static floperr_t fdi_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags) { return FLOPPY_ERROR_UNSUPPORTED; } static floperr_t fdi_read_track(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buflen) { return FLOPPY_ERROR_UNSUPPORTED; } static floperr_t fdi_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen) { return FLOPPY_ERROR_UNSUPPORTED; } static floperr_t fdi_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buffer_len) { return FLOPPY_ERROR_UNSUPPORTED; } static floperr_t fdi_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) { return FLOPPY_ERROR_UNSUPPORTED; } static floperr_t fdi_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) { return FLOPPY_ERROR_UNSUPPORTED; } /*------------------------------------------------- FLOPPY_IDENTIFY( fdi_dsk_identify ) -------------------------------------------------*/ FLOPPY_IDENTIFY( fdi_dsk_identify ) { uint8_t header[25]; floppy_image_read(floppy, header, 0, 25); if (!strncmp((const char *)header, "Formatted Disk Image file", 25)) { *vote = 100; } else { *vote = 0; } return FLOPPY_ERROR_SUCCESS; } /*------------------------------------------------- FLOPPY_CONSTRUCT( fdi_dsk_construct ) -------------------------------------------------*/ FLOPPY_CONSTRUCT( fdi_dsk_construct ) { if (params) { /* create not supported */ return FLOPPY_ERROR_UNSUPPORTED; } struct fdidsk_tag *tag = (struct fdidsk_tag *) floppy_create_tag(floppy, sizeof(struct fdidsk_tag)); if (!tag) return FLOPPY_ERROR_OUTOFMEMORY; /* read header */ struct fdi_header header; floppy_image_read(floppy, &header, 0, sizeof(header)); tag->version = header.version[0]; tag->tracks = pick_integer_be(header.ltrack, 0, 2) + 1; tag->heads = header.lhead + 1; if (LOG) { LOG_FORMATS("FDI creator: %s\n", header.creator); LOG_FORMATS("FDI comment: %s\n", header.comment); LOG_FORMATS("FDI version: %u\n", tag->version); LOG_FORMATS("FDI tracks: %u\n", tag->tracks); LOG_FORMATS("FDI heads: %u\n", tag->heads); LOG_FORMATS("FDI media type: %s\"\n", MEDIA_TYPE[header.type]); LOG_FORMATS("FDI rotation speed: %u\n", header.rotspeed + 128); if (header.flags & FLAGS_WRITE_PROTECTED) LOG_FORMATS("FDI is write protected\n"); if (header.flags & FLAGS_INDEX_SYNC) LOG_FORMATS("FDI is index synchronized\n"); LOG_FORMATS("FDI media TPI: %u\n", TRACKS_PER_INCH[header.tpi]); LOG_FORMATS("FDI head TPI: %u\n", TRACKS_PER_INCH[header.headwidth]); } /* find track offsets */ int offset = sizeof(header); for (int track = 0; track < tag->tracks; track++) { uint8_t type = header.track[track].type; int size = header.track[track].size * 256; if (LOG) LOG_FORMATS("FDI track %d type %02x size %d offset %d\n", track, type, size, offset); tag->track_offset[track] = offset; tag->track_type[track] = type; offset += size; } /* set callbacks */ struct FloppyCallbacks *callbacks = floppy_callbacks(floppy); callbacks->read_track = fdi_read_track; callbacks->get_heads_per_disk = fdi_get_heads_per_disk; callbacks->get_tracks_per_disk = fdi_get_tracks_per_disk; callbacks->get_sector_length = fdi_get_sector_length; callbacks->read_sector = fdi_read_sector; callbacks->read_indexed_sector = fdi_read_indexed_sector; // callbacks->write_track = fdi_write_track; callbacks->write_sector = fdi_write_sector; callbacks->write_indexed_sector = fdi_write_indexed_sector; callbacks->get_indexed_sector_info = fdi_get_indexed_sector_info; callbacks->get_sectors_per_track = fdi_get_sectors_per_track; return FLOPPY_ERROR_SUCCESS; }