diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/lib/formats/thom_dsk.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/lib/formats/thom_dsk.cpp')
-rw-r--r-- | src/lib/formats/thom_dsk.cpp | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/src/lib/formats/thom_dsk.cpp b/src/lib/formats/thom_dsk.cpp new file mode 100644 index 00000000000..ed9d977b723 --- /dev/null +++ b/src/lib/formats/thom_dsk.cpp @@ -0,0 +1,393 @@ +// license:BSD-3-Clause +// copyright-holders:Antoine Mine +/********************************************************************* + + formats/thom_dsk.c + + Thomson disk images + + Based on work of Antoine Mine' + +*********************************************************************/ + +#include <string.h> +#include <assert.h> +#include "thom_dsk.h" +#include "basicdsk.h" + +static const int sap_magic_num = 0xB3; /* simple XOR crypt */ + + +static const char sap_header[] = + "\001SYSTEME D'ARCHIVAGE PUKALL S.A.P. " + "(c) Alexandre PUKALL Avril 1998"; + + +static const UINT16 sap_crc[] = +{ + 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387, + 0x8408, 0x9489, 0xa50a, 0xb58b, 0xc60c, 0xd68d, 0xe70e, 0xf78f, +}; + +struct sap_dsk_tag +{ + int tracks; + int sector_size; + int sector_pos[80][16]; /* remember sector position in file */ +}; + +static UINT16 thom_sap_crc( UINT8* data, int size ) +{ + int i; + UINT16 crc = 0xffff, crc2; + for ( i = 0; i < size; i++ ) + { + crc2 = ( crc >> 4 ) ^ sap_crc[ ( crc ^ data[i] ) & 15 ]; + crc = ( crc2 >> 4 ) ^ sap_crc[ ( crc2 ^ (data[i] >> 4) ) & 15 ]; + } + return crc; +} + +static struct sap_dsk_tag *get_tag(floppy_image_legacy *floppy) +{ + struct sap_dsk_tag *tag; + tag = (sap_dsk_tag *)floppy_tag(floppy); + return tag; +} + + +static FLOPPY_IDENTIFY(sap_dsk_identify) +{ + char header[0x100]; + floppy_image_read(floppy, header, 0, sizeof(sap_header)); + if (!memcmp( header, sap_header, sizeof(sap_header) ) ) + { + *vote= 100; + } else { + *vote = 0; + } + return FLOPPY_ERROR_SUCCESS; +} +static int sap_get_heads_per_disk(floppy_image_legacy *floppy) +{ + return 1; +} + +static int sap_get_tracks_per_disk(floppy_image_legacy *floppy) +{ + return get_tag(floppy)->tracks; +} + + +static floperr_t get_offset(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, UINT64 *offset) +{ + UINT64 offs; + struct sap_dsk_tag *tag = get_tag(floppy); + /* translate the sector to a raw sector */ + if (!sector_is_index) + { + sector -= 1; + } + /* check to see if we are out of range */ + if ((head < 0) || (head >= 1) || (track < 0) || (track >=tag->tracks) + || (sector < 0) || (sector >= 16)) + return FLOPPY_ERROR_SEEKERROR; + + offs = tag->sector_pos[track][sector]; + if (offs <= 0 ) + return FLOPPY_ERROR_SEEKERROR; + + if (offset) + *offset = offs; + return FLOPPY_ERROR_SUCCESS; +} + + + +static floperr_t internal_sap_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; + int i; + UINT8 *buf; + err = get_offset(floppy, head, track, sector, sector_is_index, &offset); + if (err) + return err; + + floppy_image_read(floppy, buffer, offset+4, buflen); + buf = (UINT8*)buffer; + for (i=0;i<buflen;i++) { + buf[i] ^= sap_magic_num; + } + return FLOPPY_ERROR_SUCCESS; +} + + + +static floperr_t internal_sap_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int sector_is_index, const void *buffer, size_t buflen, int ddam) +{ + UINT64 offset; + floperr_t err; + UINT8 buf[256+6]; + UINT16 crc; + int i; + err = get_offset(floppy, head, track, sector, sector_is_index, &offset); + if (err) + return err; + + /* buf = 4-byte header + sector + 2-byte CRC */ + floppy_image_read(floppy, buf, offset, 4); + for (i=0;i<buflen;i++) { + buf[i+4] = ((UINT8*)buffer)[i]; + } + crc = thom_sap_crc( buf, buflen+4 ); + buf[buflen+4] = crc >> 8; + buf[buflen+5] = crc & 0xff; + for (i=0;i<buflen;i++) { + buf[i+4] ^= sap_magic_num; + } + floppy_image_write(floppy, buf, offset, buflen+6); + + return FLOPPY_ERROR_SUCCESS; +} + + +static floperr_t sap_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen) +{ + return internal_sap_read_sector(floppy, head, track, sector, FALSE, buffer, buflen); +} + +static floperr_t sap_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) +{ + return internal_sap_write_sector(floppy, head, track, sector, FALSE, buffer, buflen, ddam); +} + +static floperr_t sap_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen) +{ + return internal_sap_read_sector(floppy, head, track, sector, TRUE, buffer, buflen); +} + +static floperr_t sap_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) +{ + return internal_sap_write_sector(floppy, head, track, sector, TRUE, buffer, buflen, ddam); +} + +static floperr_t sap_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 sap_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 err; + UINT8 header[4]; + UINT64 offset = 0; + sector_index += 1; + err = get_offset(floppy, head, track, sector_index, FALSE, &offset); + + floppy_image_read(floppy, header, offset, 4); + if (cylinder) + *cylinder = header[2]; + if (side) + *side = head; + if (sector) + *sector = header[3]; + if (sector_length) + *sector_length = get_tag(floppy)->sector_size; + if (flags) + /* TODO: read DAM or DDAM and determine flags */ + *flags = 0; + return err; +} + +static floperr_t sap_post_format(floppy_image_legacy *floppy, option_resolution *params) +{ + int track,sector; + int pos; + UINT8 buf[256], header[4]; + struct sap_dsk_tag *tag; + tag = (struct sap_dsk_tag *) floppy_create_tag(floppy, sizeof(struct sap_dsk_tag)); + + /* default options */ + if ( !tag->tracks ) + { + tag->tracks = 80; + tag->sector_size = 256; + } + + /* create SAP file header */ + floppy_image_write( floppy, sap_header, 0, 66 ); + + for ( track = 0; track < 80; track++ ) + for ( sector = 0; sector < 16; sector++ ) + tag->sector_pos[track][sector] = 0; + + /* create all sectors with valid header and CRC */ + memset(buf, 0xe5, 256); + pos = 0x42; + header[0] = (tag->sector_size==128) ? 1 : 0; + header[1] = 0; + for ( track = 0, pos = 0x42; track < tag->tracks; track++ ) + for ( sector = 0; sector < 16; sector++, pos += tag->sector_size + 6 ) { + tag->sector_pos[track][sector] = pos; + header[2] = track; + header[3] = sector + 1; + floppy_image_write(floppy, header, pos, 4); + sap_write_indexed_sector( floppy, 0, track, sector, buf, tag->sector_size, 0 ); + } + + return FLOPPY_ERROR_SUCCESS; +} + + +static FLOPPY_CONSTRUCT(sap_dsk_construct) +{ + struct FloppyCallbacks *callbacks; + struct sap_dsk_tag *tag; + int j; + UINT8 fmt; + tag = (struct sap_dsk_tag *) floppy_create_tag(floppy, sizeof(struct sap_dsk_tag)); + if (!tag) + return FLOPPY_ERROR_OUTOFMEMORY; + + /* guess format */ + floppy_image_read(floppy, &fmt, 0x42, 1); + if ( fmt==1 ) tag->sector_size = 128; else tag->sector_size = 256; + + /* start with an empty offset table */ + tag->tracks = 0; + for ( int i = 0; i < 80; i++ ) + for ( j = 0; j < 16; j++ ) + tag->sector_pos[i][j] = 0; + + /* count tracks & fill sector offset table */ + for ( UINT64 i = 0x42; i+4 < floppy_image_size(floppy); i += tag->sector_size + 6 ) // CRC 2 bytes + 4 bytes sector header + { + UINT8 sector, track; + floppy_image_read(floppy, &track, i+2, 1); + floppy_image_read(floppy, §or, i+3, 1); + if ( track >= 80 || sector < 1 || sector > 16 ) continue; + if ( track > tag->tracks ) tag->tracks = track+1; + tag->sector_pos[track][sector-1] = i; + } + callbacks = floppy_callbacks(floppy); + callbacks->read_sector = sap_read_sector; + callbacks->write_sector = sap_write_sector; + callbacks->read_indexed_sector = sap_read_indexed_sector; + callbacks->write_indexed_sector = sap_write_indexed_sector; + callbacks->get_sector_length = sap_get_sector_length; + callbacks->get_heads_per_disk = sap_get_heads_per_disk; + callbacks->get_tracks_per_disk = sap_get_tracks_per_disk; + callbacks->get_indexed_sector_info = sap_get_indexed_sector_info; + callbacks->post_format = sap_post_format; + + return FLOPPY_ERROR_SUCCESS; +} + +static FLOPPY_IDENTIFY(qdd_dsk_identify) +{ + *vote = (floppy_image_size(floppy) == (51200)) ? 100 : 0; + return FLOPPY_ERROR_SUCCESS; +} + +/* fixed interlacing map for QDDs */ +static int thom_qdd_map[400]; + +static int qdd_translate_sector(floppy_image_legacy *floppy, int sector) +{ + return thom_qdd_map[sector-1]; +} + +static void thom_qdd_compute_map ( void ) +{ + /* this map is hardcoded in the QDD BIOS */ + static const int p[6][4] = + { + { 20, 2, 14, 8 }, { 21, 19, 13, 7 }, + { 22, 18, 12, 6 }, { 23, 17, 11, 5 }, + { 24, 16, 10, 4 }, { 1, 15, 9, 3 } + }; + static const int q[4] = { 0, 8, 4, 12 }; + int t, s; + for ( t = 0; t < 24; t++ ) + { + for ( s = 0; s < 16; s++ ) + { + thom_qdd_map[ t*16 + s ] = p[ t/4 ][ s%4 ] * 16 + (s/4) + 4*(t%4); + } + } + for ( s = 0; s < 16; s++ ) + { + thom_qdd_map[ 24*16 + s ] = q[ s%4 ] + (s/4); + } +} + +static FLOPPY_CONSTRUCT(qdd_dsk_construct) +{ + struct basicdsk_geometry geometry; + + thom_qdd_compute_map(); + + memset(&geometry, 0, sizeof(geometry)); + geometry.heads = 1; + geometry.first_sector_id = 1; + geometry.sector_length = 128; + geometry.tracks = 1; + geometry.sectors = 400; + geometry.translate_sector = qdd_translate_sector; + return basicdsk_construct(floppy, &geometry); +} + + +/* ----------------------------------------------------------------------- */ + +LEGACY_FLOPPY_OPTIONS_START(thomson) + + LEGACY_FLOPPY_OPTION(fdmfm2, "fd", "Thomson FD (MFM) 80 tracks disk image (3\"1/2 DD)", basicdsk_identify_default, basicdsk_construct_default, NULL, + HEADS([1]) + TRACKS([80]) + SECTORS([16]) + SECTOR_LENGTH([256]) + FIRST_SECTOR_ID([1])) + + LEGACY_FLOPPY_OPTION(fdmfm, "fd", "Thomson FD (MFM) 40 tracks disk image (5\"1/4 DD)", basicdsk_identify_default, basicdsk_construct_default, NULL, + HEADS([1]) + TRACKS([40]) + SECTORS([16]) + SECTOR_LENGTH([256]) + FIRST_SECTOR_ID([1])) + + LEGACY_FLOPPY_OPTION(fd2, "fd", "Thomson FD (FM) 80 tracks disk image (3\"1/2 SD)", basicdsk_identify_default, basicdsk_construct_default, NULL, + HEADS([1]) + TRACKS([80]) + SECTORS([16]) + SECTOR_LENGTH([128]) + FIRST_SECTOR_ID([1])) + + LEGACY_FLOPPY_OPTION(fd, "fd", "Thomson FD (FM) 40 tracks disk image (5\"1/4 SD)", basicdsk_identify_default, basicdsk_construct_default, NULL, + HEADS([1]) + TRACKS([40]) + SECTORS([16]) + SECTOR_LENGTH([128]) + FIRST_SECTOR_ID([1])) + + LEGACY_FLOPPY_OPTION(sap,"sap", "Thomson SAP floppy disk image", sap_dsk_identify, sap_dsk_construct, NULL, NULL) + + LEGACY_FLOPPY_OPTION(qdd,"qd", "Thomson QDD floppy disk image (2\"8 SD)", qdd_dsk_identify, qdd_dsk_construct, NULL, + HEADS([1]) + TRACKS([1]) + SECTORS([400]) + SECTOR_LENGTH([128]) + FIRST_SECTOR_ID([0])) + +LEGACY_FLOPPY_OPTIONS_END |