/********************************************************************* formats/dsk_dsk.c DSK disk images *********************************************************************/ #include #include "imageutl.h" #include "flopimg.h" #define MV_CPC "MV - CPC" #define EXTENDED "EXTENDED" struct dskdsk_tag { int disk_image_type; /* image type: standard or extended */ int heads; int tracks; int sector_size; UINT64 track_offsets[84*2]; /* offset within data for each track */ }; static struct dskdsk_tag *get_tag(floppy_image_legacy *floppy) { struct dskdsk_tag *tag; tag = (dskdsk_tag *)floppy_tag(floppy); return tag; } FLOPPY_IDENTIFY( dsk_dsk_identify ) { UINT8 header[8]; floppy_image_read(floppy, header, 0, 8); if ( memcmp( header, MV_CPC, 8 ) ==0) { *vote = 100; } else if ( memcmp( header, EXTENDED, 8 ) ==0) { *vote = 100; } else { *vote = 0; } return FLOPPY_ERROR_SUCCESS; } static int dsk_get_heads_per_disk(floppy_image_legacy *floppy) { return get_tag(floppy)->heads; } static int dsk_get_tracks_per_disk(floppy_image_legacy *floppy) { return get_tag(floppy)->tracks; } static UINT64 dsk_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 offs; UINT64 track_offset; UINT8 track_info[0x100]; UINT8 sectors_per_track; int i; /* translate the sector to a raw sector */ /* check to see if we are out of range */ if ((head < 0) || (head >= get_tag(floppy)->heads) || (track < 0) || (track >= get_tag(floppy)->tracks) || (sector < 0) ) return FLOPPY_ERROR_SEEKERROR; track_offset = dsk_get_track_offset(floppy, head, track); floppy_image_read(floppy, track_info, track_offset, 0x100); sectors_per_track = track_info[0x015]; if (!sector_is_index) { if (sector >= sectors_per_track) { return FLOPPY_ERROR_SEEKERROR; } } if (get_tag(floppy)->disk_image_type==0) { get_tag(floppy)->sector_size = (1<<(track_info[0x014]+7)); offs = track_offset + 0x100 +sector * get_tag(floppy)->sector_size; } else { get_tag(floppy)->sector_size = track_info[0x18 + (sector<<3) + 6] + (track_info[0x18+(sector<<3) + 7]<<8); offs = track_offset + 0x100; for (i=0;isector_size; } return FLOPPY_ERROR_SUCCESS; } static floperr_t dsk_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) { floperr_t retVal; UINT64 offset; UINT8 sector_info[0x100]; int pos; retVal = get_offset(floppy, head, track, sector_index, FALSE, NULL); offset = dsk_get_track_offset(floppy,head,track); pos = 0x18 + (sector_index << 3); floppy_image_read(floppy, sector_info, offset, 0x100); if (cylinder) *cylinder = sector_info[pos + 0]; if (side) *side = sector_info[pos + 1]; if (sector) *sector = sector_info[pos + 2]; if (sector_length) { *sector_length = 1 << (sector_info[pos + 3] + 7); } if (flags) *flags = (sector_info[pos + 5] & 0x40) ? ID_FLAG_DELETED_DATA : 0; return retVal; } FLOPPY_CONSTRUCT( dsk_dsk_construct ) { struct FloppyCallbacks *callbacks; struct dskdsk_tag *tag; UINT8 header[0x100]; UINT64 tmp = 0; int i; int skip,cnt; if(params) { // create return FLOPPY_ERROR_UNSUPPORTED; } floppy_image_read(floppy, header, 0, 0x100); #ifdef SPOT_DUPLICATES // this allow to spot .dsk files with same data and different headers, making easier to debug softlists. UINT32 temp_size = floppy_image_size(floppy); UINT8 tmp_copy[temp_size - 0x100]; floppy_image_read(floppy,tmp_copy,0x100,temp_size - 0x100); printf("CRC16: %d\n", ccitt_crc16(0xffff, tmp_copy, temp_size - 0x100)); #endif tag = (struct dskdsk_tag *) floppy_create_tag(floppy, sizeof(struct dskdsk_tag)); if (!tag) return FLOPPY_ERROR_OUTOFMEMORY; tag->heads = header[0x31]; if (tag->heads==1) { skip = 2; } else { skip = 1; } tag->tracks = header[0x30]; cnt =0; if ( memcmp( header, MV_CPC, 8 ) ==0) { tag->disk_image_type = 0; tmp = 0x100; for (i=0; itracks * tag->heads; i++) { tag->track_offsets[cnt] = tmp; tmp += pick_integer_le(header, 0x32, 2); cnt += skip; } } else { tag->disk_image_type = 1; tmp = 0x100; for (i=0; itracks * tag->heads; i++) { tag->track_offsets[cnt] = tmp; tmp += header[0x34 + i] << 8; cnt += skip; } } callbacks = floppy_callbacks(floppy); callbacks->read_sector = dsk_read_sector; callbacks->write_sector = dsk_write_sector; callbacks->read_indexed_sector = dsk_read_indexed_sector; callbacks->write_indexed_sector = dsk_write_indexed_sector; callbacks->get_sector_length = dsk_get_sector_length; callbacks->get_heads_per_disk = dsk_get_heads_per_disk; callbacks->get_tracks_per_disk = dsk_get_tracks_per_disk; callbacks->get_indexed_sector_info = dsk_get_indexed_sector_info; return FLOPPY_ERROR_SUCCESS; } #include "emu.h" #include "dsk_dsk.h" #define DSK_FORMAT_HEADER "MV - CPC" #define EXT_FORMAT_HEADER "EXTENDED CPC DSK" dsk_format::dsk_format() : floppy_image_format_t() { } const char *dsk_format::name() const { return "dsk"; } const char *dsk_format::description() const { return "CPC DSK Format"; } const char *dsk_format::extensions() const { return "dsk"; } bool dsk_format::supports_save() const { return false; } int dsk_format::identify(io_generic *io, UINT32 form_factor) { UINT8 header[16]; io_generic_read(io, &header, 0, sizeof(header)); if ( memcmp( header, DSK_FORMAT_HEADER, 8 ) ==0) { return 100; } if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) { return 100; } return 0; } #pragma pack(1) struct track_header { UINT8 headertag[13]; UINT16 unused1; UINT8 unused1b; UINT8 track_number; UINT8 side_number; UINT8 datarate; UINT8 rec_mode; UINT8 sector_size_code; UINT8 number_of_sector; UINT8 gap3_length; UINT8 filler_byte; }; struct sector_header { UINT8 track; UINT8 side; UINT8 sector_id; UINT8 sector_size_code; UINT8 fdc_status_reg1; UINT8 fdc_status_reg2; UINT16 data_lenght; }; #pragma pack() bool dsk_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { UINT8 header[100]; bool extendformat = FALSE; io_generic_read(io, &header, 0, sizeof(header)); if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) { extendformat = TRUE; } int heads = header[0x31]; int skip = 1; if (heads==1) { skip = 2; } int tracks = header[0x30]; UINT64 track_offsets[84*2]; int cnt =0; if (!extendformat) { int tmp = 0x100; for (int i=0; i;