--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_hfe.c Sat Oct 09 17:47:01 2021 +0100
@@ -0,0 +1,339 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rpcemu.h"
+#include "disc.h"
+#include "disc_hfe.h"
+#include "disc_mfm_common.h"
+
+static disc_funcs hfe_disc_funcs;
+
+static void hfe_writeback(int drive);
+
+#define TRACK_ENCODING_ISOIBM_MFM 0x00
+#define TRACK_ENCODING_AMIGA_MFM 0x01
+#define TRACK_ENCODING_ISOIBM_FM 0x02
+#define TRACK_ENCODING_EMU_FM 0x03
+
+typedef struct hfe_header_t {
+ char signature[8]; /*Should be HXCPICFE*/
+ uint8_t revision;
+ uint8_t nr_of_tracks;
+ uint8_t nr_of_sides;
+ uint8_t track_encoding;
+ uint16_t bitrate;
+ uint16_t floppy_rpm;
+ uint8_t floppy_interface_mode;
+ uint8_t dnu;
+ uint16_t track_list_offset;
+ uint8_t write_allowed;
+ uint8_t single_step;
+ uint8_t track0s0_altencoding;
+ uint8_t track0s0_encoding;
+ uint8_t track0s1_altencoding;
+ uint8_t track0s1_encoding;
+} hfe_header_t;
+
+typedef struct hfe_track_t {
+ uint16_t offset;
+ uint16_t track_len;
+} hfe_track_t;
+
+typedef struct hfe_t {
+ hfe_header_t header;
+ hfe_track_t *tracks;
+ mfm_t mfm;
+ FILE *f;
+ int current_track;
+ int write_prot;
+} hfe_t;
+
+static hfe_t hfe[4];
+
+static int hfe_drive;
+
+static int hfe_load_header(hfe_t *hfe)
+{
+ hfe_header_t *header = &hfe->header;
+
+ fread(header->signature, 8, 1, hfe->f);
+ header->revision = getc(hfe->f);
+ header->nr_of_tracks = getc(hfe->f);
+ header->nr_of_sides = getc(hfe->f);
+ header->track_encoding = getc(hfe->f);
+ fread(&header->bitrate, 2, 1, hfe->f);
+ fread(&header->floppy_rpm, 2, 1, hfe->f);
+ header->floppy_interface_mode = getc(hfe->f);
+ header->dnu = getc(hfe->f);
+ fread(&header->track_list_offset, 2, 1, hfe->f);
+ header->write_allowed = getc(hfe->f);
+ header->single_step = getc(hfe->f);
+ header->track0s0_altencoding = getc(hfe->f);
+ header->track0s0_encoding = getc(hfe->f);
+ header->track0s1_altencoding = getc(hfe->f);
+ header->track0s1_encoding = getc(hfe->f);
+
+ if (strncmp(header->signature, "HXCPICFE", 8)) {
+ rpclog("HFE signature does not match\n");
+ return -1;
+ }
+ if (header->revision != 0) {
+ rpclog("HFE revision %i unsupported\n", header->revision);
+ return -1;
+ }
+
+// rpclog("HFE: %i tracks, %i sides\n", header->nr_of_tracks, header->nr_of_sides);
+// rpclog(" track_list_offset: %i\n", header->track_list_offset);
+ hfe->tracks = malloc(header->nr_of_tracks * header->nr_of_sides * sizeof(hfe_track_t));
+ fseek(hfe->f, header->track_list_offset * 0x200, SEEK_SET);
+ fread(hfe->tracks, header->nr_of_tracks * header->nr_of_sides * sizeof(hfe_track_t), 1, hfe->f);
+
+ return 0;
+}
+
+void hfe_init()
+{
+// printf("hfe reset\n");
+ memset(hfe, 0, sizeof(hfe));
+}
+
+void hfe_load(int drive, const char *fn)
+{
+ hfe[drive].write_prot = 0;
+ memset(&hfe[drive], 0, sizeof(hfe_t));
+ hfe[drive].f = fopen(fn, "rb+");
+ if (!hfe[drive].f) {
+ hfe[drive].f = fopen(fn, "rb");
+ if (!hfe[drive].f)
+ return;
+ hfe[drive].write_prot = 1;
+ }
+ hfe_load_header(&hfe[drive]);
+ hfe[drive].mfm.write_protected = hfe[drive].write_prot;
+ hfe[drive].mfm.writeback = hfe_writeback;
+
+ drive_funcs[drive] = &hfe_disc_funcs;
+ //rpclog("Loaded as hfe\n");
+
+ drive_funcs[drive]->seek(drive, disc_get_current_track(drive));
+}
+
+static void hfe_close(int drive)
+{
+ if (hfe[drive].tracks) {
+ free(hfe[drive].tracks);
+ hfe[drive].tracks = NULL;
+ }
+ if (hfe[drive].f) {
+ fclose(hfe[drive].f);
+ hfe[drive].f = NULL;
+ }
+}
+
+static void do_bitswap(uint8_t *data, int size)
+{
+ int c;
+
+ for (c = 0; c < size; c++) {
+ uint8_t new_val = 0;
+
+ if (data[c] & 0x01)
+ new_val |= 0x80;
+ if (data[c] & 0x02)
+ new_val |= 0x40;
+ if (data[c] & 0x04)
+ new_val |= 0x20;
+ if (data[c] & 0x08)
+ new_val |= 0x10;
+ if (data[c] & 0x10)
+ new_val |= 0x08;
+ if (data[c] & 0x20)
+ new_val |= 0x04;
+ if (data[c] & 0x40)
+ new_val |= 0x02;
+ if (data[c] & 0x80)
+ new_val |= 0x01;
+
+ data[c] = new_val;
+ }
+}
+
+static void upsample_track(uint8_t *data, int size)
+{
+ int c;
+
+ for (c = size-1; c >= 0; c--) {
+ uint8_t new_data = 0;
+
+ if (data[c] & 0x08)
+ new_data |= 0x80;
+ if (data[c] & 0x04)
+ new_data |= 0x20;
+ if (data[c] & 0x02)
+ new_data |= 0x08;
+ if (data[c] & 0x01)
+ new_data |= 0x02;
+ data[c*2+1] = new_data;
+
+ new_data = 0;
+ if (data[c] & 0x80)
+ new_data |= 0x80;
+ if (data[c] & 0x40)
+ new_data |= 0x20;
+ if (data[c] & 0x20)
+ new_data |= 0x08;
+ if (data[c] & 0x10)
+ new_data |= 0x02;
+ data[c*2] = new_data;
+ }
+}
+
+static void downsample_track(uint8_t *data, int size)
+{
+ int c;
+
+ for (c = 0; c < size; c++) {
+ uint8_t new_data = 0;
+
+ if (data[c*2+1] & 0x80)
+ new_data |= 0x08;
+ if (data[c*2+1] & 0x20)
+ new_data |= 0x04;
+ if (data[c*2+1] & 0x08)
+ new_data |= 0x02;
+ if (data[c*2+1] & 0x02)
+ new_data |= 0x01;
+ if (data[c*2] & 0x80)
+ new_data |= 0x80;
+ if (data[c*2] & 0x20)
+ new_data |= 0x40;
+ if (data[c*2] & 0x08)
+ new_data |= 0x20;
+ if (data[c*2] & 0x02)
+ new_data |= 0x10;
+ data[c] = new_data;
+ }
+}
+
+static void hfe_seek(int drive, int track)
+{
+ hfe_header_t *header = &hfe[drive].header;
+ mfm_t *mfm = &hfe[drive].mfm;
+ int c;
+
+ if (!hfe[drive].f) {
+ memset(mfm->track_data[0], 0, 65536);
+ memset(mfm->track_data[1], 0, 65536);
+ return;
+ }
+// printf("Track start %i\n",track);
+ if (track < 0)
+ track = 0;
+ if (track >= header->nr_of_tracks)
+ track = header->nr_of_tracks - 1;
+
+ hfe->current_track = track;
+
+// rpclog("hfe_seek: drive=%i track=%i\n", drive, track);
+// rpclog(" offset=%04x size=%04x\n", hfe[drive].tracks[track].offset, hfe[drive].tracks[track].track_len);
+ fseek(hfe[drive].f, hfe[drive].tracks[track].offset * 0x200, SEEK_SET);
+// rpclog(" start=%06x\n", ftell(hfe[drive].f));
+ for (c = 0; c < (hfe[drive].tracks[track].track_len/2); c += 0x100) {
+ fread(&mfm->track_data[0][c], 256, 1, hfe[drive].f);
+ fread(&mfm->track_data[1][c], 256, 1, hfe[drive].f);
+ }
+// rpclog(" end=%06x\n", ftell(hfe[drive].f));
+ mfm->track_index[0] = 0;
+ mfm->track_index[1] = 0;
+ mfm->track_len[0] = (hfe[drive].tracks[track].track_len*8)/2;
+ mfm->track_len[1] = (hfe[drive].tracks[track].track_len*8)/2;
+ do_bitswap(mfm->track_data[0], (mfm->track_len[0] + 7) / 8);
+ do_bitswap(mfm->track_data[1], (mfm->track_len[1] + 7) / 8);
+
+ if (header->bitrate < 400) {
+ upsample_track(mfm->track_data[0], (mfm->track_len[0] + 7) / 8);
+ upsample_track(mfm->track_data[1], (mfm->track_len[1] + 7) / 8);
+ mfm->track_len[0] *= 2;
+ mfm->track_len[1] *= 2;
+ }
+
+// rpclog(" SD side 0 Track %i Len %i Index %i\n", track, mfm->track_len[0][0], mfm->track_index[0][0]);
+// rpclog(" SD side 1 Track %i Len %i Index %i\n", track, mfm->track_len[1][0], mfm->track_index[1][0]);
+// rpclog(" DD side 0 Track %i Len %i Index %i\n", track, mfm->track_len[0], mfm->track_index[0]);
+// rpclog(" DD side 1 Track %i Len %i Index %i\n", track, mfm->track_len[1], mfm->track_index[1]);
+}
+
+static void hfe_writeback(int drive)
+{
+ hfe_header_t *header = &hfe[drive].header;
+ mfm_t *mfm = &hfe[drive].mfm;
+ int track = hfe[drive].current_track;
+ uint8_t track_data[2][65536];
+ int c;
+
+// rpclog("hfe_writeback: drive=%i track=%i\n", drive, track);
+
+ for (c = 0; c < 2; c++) {
+ int track_len = mfm->track_len[c];
+ memcpy(track_data[c], mfm->track_data[c], (track_len + 7) / 8);
+
+ if (header->bitrate < 400) {
+ downsample_track(track_data[c], (track_len + 7) / 8);
+ track_len /= 2;
+ }
+ do_bitswap(track_data[c], (track_len + 7) / 8);
+ }
+
+ fseek(hfe[drive].f, hfe[drive].tracks[track].offset * 0x200, SEEK_SET);
+// rpclog(" at %06x\n", ftell(hfe[drive].f));
+ for (c = 0; c < (hfe[drive].tracks[track].track_len/2); c += 0x100) {
+ fwrite(&track_data[0][c], 256, 1, hfe[drive].f);
+ fwrite(&track_data[1][c], 256, 1, hfe[drive].f);
+ }
+}
+
+static void hfe_readsector(int drive, int sector, int track, int side, int density)
+{
+ hfe_drive = drive;
+ mfm_readsector(&hfe[drive].mfm, drive, sector, track, side, density);
+}
+
+static void hfe_writesector(int drive, int sector, int track, int side, int density)
+{
+ hfe_drive = drive;
+ mfm_writesector(&hfe[drive].mfm, drive, sector, track, side, density);
+}
+
+static void hfe_readaddress(int drive, int track, int side, int density)
+{
+ hfe_drive = drive;
+ mfm_readaddress(&hfe[drive].mfm, drive, track, side, density);
+}
+
+static void hfe_format(int drive, int track, int side, int density)
+{
+ hfe_drive = drive;
+ mfm_format(&hfe[drive].mfm, drive, track, side, density);
+}
+
+static void hfe_stop()
+{
+ mfm_stop(&hfe[hfe_drive].mfm);
+}
+
+static void hfe_poll()
+{
+ mfm_common_poll(&hfe[hfe_drive].mfm);
+}
+
+static disc_funcs hfe_disc_funcs = {
+ .seek = hfe_seek,
+ .readsector = hfe_readsector,
+ .writesector = hfe_writesector,
+ .readaddress = hfe_readaddress,
+ .poll = hfe_poll,
+ .format = hfe_format,
+ .stop = hfe_stop,
+ .close = hfe_close
+};
\ No newline at end of file
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/disc_hfe.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_hfe.h Sat Oct 09 17:47:01 2021 +0100
@@ -0,0 +1,2 @@
+extern void hfe_init();
+extern void hfe_load(int drive, const char *fn);
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/disc_mfm_common.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_mfm_common.c Sat Oct 09 17:47:01 2021 +0100
@@ -0,0 +1,470 @@
+/*Common handling for raw FM/MFM bitstreams*/
+#include <stdint.h>
+#include "rpcemu.h"
+#include "disc.h"
+#include "disc_mfm_common.h"
+#include "fdc.h"
+
+static uint16_t CRCTable[256];
+
+static void mfm_setupcrc(uint16_t poly)
+{
+ int c = 256, bc;
+ uint16_t crctemp;
+
+ while(c--) {
+ crctemp = c << 8;
+ bc = 8;
+
+ while(bc--) {
+ if(crctemp & 0x8000)
+ crctemp = (crctemp << 1) ^ poly;
+ else
+ crctemp <<= 1;
+ }
+
+ CRCTable[c] = crctemp;
+ }
+}
+
+void mfm_init(void)
+{
+ mfm_setupcrc(0x1021);
+}
+
+
+void mfm_readsector(mfm_t *mfm, int drive, int sector, int track, int side, int density)
+{
+ mfm->revs = 0;
+ mfm->sector = sector;
+ mfm->track = track;
+ mfm->side = side;
+ mfm->drive = drive;
+ mfm->density = density;
+ //rpclog("mfm Read sector %i %i %i %i %i\n",drive,side,track,sector, density);
+
+ mfm->in_read = 1;
+ mfm->sync_required = (density != 2);
+}
+
+void mfm_writesector(mfm_t *mfm, int drive, int sector, int track, int side, int density)
+{
+ mfm->revs = 0;
+ mfm->sector = sector;
+ mfm->track = track;
+ mfm->side = side;
+ mfm->drive = drive;
+ //rpclog("Write sector %i %i %i %i %i\n",drive,side,track,sector,density);
+
+ mfm->in_write = 1;
+ mfm->sync_required = (density != 2);
+}
+
+void mfm_readaddress(mfm_t *mfm, int drive, int track, int side, int density)
+{
+ mfm->revs = 0;
+ mfm->track = track;
+ mfm->side = side;
+ mfm->density = density;
+ mfm->drive = drive;
+ //rpclog("Read address %i %i %i %i\n",drive,side,track,density);
+
+ mfm->in_readaddr = 1;
+ mfm->sync_required = (density != 2);
+}
+
+void mfm_format(mfm_t *mfm, int drive, int track, int side, int density)
+{
+ mfm->revs = 0;
+ mfm->track = track;
+ mfm->side = side;
+ mfm->density = density;
+ mfm->drive = drive;
+// printf("Format %i %i %i\n",drive,side,track);
+
+ mfm->in_format = 1;
+ mfm->sync_required = 0;
+}
+
+void mfm_stop(mfm_t *mfm)
+{
+ mfm->in_read = mfm->in_write = mfm->in_readaddr = mfm->in_format = 0;
+ mfm->nextsector = mfm->ddidbitsleft = mfm->pollbitsleft = 0;
+}
+
+
+static void calccrc(mfm_t *mfm, uint8_t byte)
+{
+ mfm->crc = (mfm->crc << 8) ^ CRCTable[(mfm->crc >> 8) ^ byte];
+}
+
+static uint16_t pack_2us(uint32_t in_data)
+{
+ uint16_t out_data = 0;
+ int c;
+
+ for (c = 0; c < 16; c++) {
+ if (in_data & (2 << c*2))
+ out_data |= (1 << c);
+ }
+
+ return out_data;
+}
+static uint16_t pack_4us(uint64_t in_data)
+{
+ uint16_t out_data = 0;
+ int c;
+
+ for (c = 0; c < 16; c++) {
+ if (in_data & (8ull << c*4))
+ out_data |= (1 << c);
+ }
+
+ return out_data;
+}
+
+static uint8_t decodefm(uint16_t dat)
+{
+ uint8_t temp;
+ temp = 0;
+ if (dat & 0x0001) temp |= 1;
+ if (dat & 0x0004) temp |= 2;
+ if (dat & 0x0010) temp |= 4;
+ if (dat & 0x0040) temp |= 8;
+ if (dat & 0x0100) temp |= 16;
+ if (dat & 0x0400) temp |= 32;
+ if (dat & 0x1000) temp |= 64;
+ if (dat & 0x4000) temp |= 128;
+ return temp;
+}
+
+static uint64_t encode_fm_4us(uint8_t data)
+{
+ uint64_t fm_data = 0x8080808080808080ull; /*Clock bits*/
+ int c;
+
+ for (c = 7; c >= 0; c--) {
+ if (data & (1 << c))
+ fm_data |= 8ull << (c*8);
+ }
+
+ return fm_data;
+}
+
+static uint32_t encode_mfm_2us(mfm_t *mfm, uint8_t data)
+{
+ uint32_t mfm_data = 0;
+ int c;
+
+ for (c = 7; c >= 0; c--) {
+ if (data & (1 << c))
+ mfm_data |= 2 << (c*4);
+ else if (!mfm->last_bit)
+ mfm_data |= 8 << (c*4);
+
+ mfm->last_bit = data & (1 << c);
+ }
+
+ return mfm_data;
+}
+
+static uint16_t encode_mfm_1us(mfm_t *mfm, uint8_t data)
+{
+ uint16_t mfm_data = 0;
+ int c;
+
+ for (c = 7; c >= 0; c--) {
+ if (data & (1 << c))
+ mfm_data |= 1 << (c*2);
+ else if (!mfm->last_bit)
+ mfm_data |= 2 << (c*2);
+
+ mfm->last_bit = data & (1 << c);
+ }
+
+ return mfm_data;
+}
+
+static void next_bit(mfm_t *mfm)
+{
+ mfm->pos++;
+
+ if (mfm->pos >= mfm->track_len[mfm->side]) {
+// rpclog("disc loop %i index %i\n", mfm->pos,mfm->track_index[mfm->side]);
+ mfm->pos = 0;
+ }
+
+ if (mfm->pos == mfm->track_index[mfm->side]) {
+// rpclog("disc index %i %i\n", mfm->pos, mfm->indextime_blank);
+ if (mfm->track_len[mfm->side]) {
+ fdc_indexpulse();
+ if (mfm->in_read || mfm->in_readaddr || mfm->in_write)
+ mfm->revs++;
+ } else {
+ mfm->indextime_blank--;
+ if (mfm->indextime_blank <= 0) {
+ mfm->indextime_blank = 6250 * 8;
+ fdc_indexpulse();
+ if (mfm->in_read || mfm->in_readaddr || mfm->in_write)
+ mfm->revs++;
+ }
+ }
+ if ((mfm->in_read || mfm->in_readaddr || mfm->in_write) && mfm->revs == 3) {
+// rpclog("hfe_poll: Not found!\n");
+ fdc_notfound();
+ mfm->in_read = mfm->in_readaddr = mfm->in_write = 0;
+ }
+ }
+}
+
+void mfm_common_poll(mfm_t *mfm)
+{
+ int tempi, c, polls;
+ int nr_bits = 4 >> mfm->density;
+
+ if (mfm->density == 3) {
+ for (polls = 0; polls < 8; polls++)
+ next_bit(mfm);
+ return;
+ }
+
+ for (polls = 0; polls < 16; polls++) {
+ uint16_t new_data;
+
+ if (mfm->sync_required) {
+ if (mfm->density == 0) {
+ for (c = 0; c < nr_bits; c++) {
+ int tempi = mfm->track_data[mfm->side][(mfm->pos >> 3) & 0xFFFF] & (1 << (7-(mfm->pos & 7)));
+ mfm->buffer <<= 1;
+ mfm->buffer |= (tempi ? 1 : 0);
+ next_bit(mfm);
+
+ if ((mfm->buffer & 0x8080808080808080ull) == 0x8080808080808080ull &&
+ !(mfm->buffer & 0x7777777777777777ull)) {
+ mfm->sync_required = 0;
+ break;
+ }
+ }
+ }
+ else if (mfm->density == 1) {
+ for (c = 0; c < nr_bits; c++) {
+ int tempi = mfm->track_data[mfm->side][(mfm->pos >> 3) & 0xFFFF] & (1 << (7-(mfm->pos & 7)));
+ mfm->buffer <<= 1;
+ mfm->buffer |= (tempi ? 1 : 0);
+ next_bit(mfm);
+
+ if ((mfm->buffer & 0xffff) == 0x8888) {
+ mfm->sync_required = 0;
+ break;
+ }
+ }
+ }
+
+ if (mfm->sync_required)
+ continue;
+ }
+
+ if (mfm->in_format) {
+ mfm->in_format = 0;
+ fdc_writeprotect();
+ continue;
+ }
+ if (mfm->in_write && mfm->write_protected) {
+ mfm->in_write = 0;
+ fdc_writeprotect();
+ continue;
+ }
+
+ if (mfm->rw_write) {
+// if (!mfm->writedatapoll)
+// fatal("rw_write but not writedatapoll\n");
+ if (mfm->pollbitsleft == 16) {
+ uint8_t write_data;
+
+ if (mfm->pollbytesleft <= 2) {
+ write_data = (mfm->pollbytesleft == 2) ? (mfm->crc >> 8) : (mfm->crc & 0xff);
+ } else {
+ int c = fdc_getdata(mfm->pollbytesleft == 3);
+
+ write_data = c & 0xff;
+ calccrc(mfm, write_data);
+ }
+
+ if (mfm->density == 2)
+ mfm->buffer = (uint64_t)encode_mfm_1us(mfm, write_data) << 48;
+ else if (mfm->density == 1)
+ mfm->buffer = (uint64_t)encode_mfm_2us(mfm, write_data) << 32;
+ else
+ mfm->buffer = encode_fm_4us(write_data);
+// rpclog("MFM write %04i %02x %016llx %06i %04x\n", mfm->pollbytesleft, write_data, mfm->buffer, mfm->pos, mfm->crc);
+ }
+
+ for (c = 0; c < nr_bits; c++) {
+ if (mfm->buffer & (1ull << 63))
+ mfm->track_data[mfm->side][(mfm->pos >> 3) & 0xFFFF] |= (1 << (7-(mfm->pos & 7)));
+ else
+ mfm->track_data[mfm->side][(mfm->pos >> 3) & 0xFFFF] &= ~(1 << (7-(mfm->pos & 7)));
+ mfm->buffer <<= 1;
+ next_bit(mfm);
+ }
+
+ mfm->pollbitsleft--;
+ if (!mfm->pollbitsleft) {
+ mfm->pollbytesleft--;
+ if (mfm->pollbytesleft) {
+ mfm->pollbitsleft = 16; /*Set up another word if we need it*/
+ } else {
+// rpclog("MFM finished write\n");
+ fdc_finishread();
+ mfm->writedatapoll = 0;
+ mfm->rw_write = 0;
+ mfm->in_write = 0;
+ mfm->writeback(mfm->drive);
+ }
+ }
+ } else {
+ for (c = 0; c < nr_bits; c++) {
+ tempi = mfm->track_data[mfm->side][(mfm->pos >> 3) & 0xFFFF] & (1 << (7-(mfm->pos & 7)));
+ mfm->buffer <<= 1;
+ mfm->buffer |= (tempi ? 1 : 0);
+ next_bit(mfm);
+ }
+ if (mfm->density == 2)
+ new_data = mfm->buffer & 0xffff;
+ else if (mfm->density == 1)
+ new_data = pack_2us(mfm->buffer);
+ else
+ new_data = pack_4us(mfm->buffer);
+
+ if (!mfm->in_read && !mfm->in_readaddr && !mfm->in_write)
+ continue;
+
+ if (mfm->pollbitsleft)
+ mfm->pollbitsleft--;
+ if (!mfm->pollbitsleft && mfm->pollbytesleft) {
+ mfm->pollbytesleft--;
+ if (mfm->pollbytesleft)
+ mfm->pollbitsleft = 16; /*Set up another word if we need it*/
+ if (mfm->readidpoll) {
+ mfm->sectordat[5 - mfm->pollbytesleft] = decodefm(new_data);
+ if (mfm->in_readaddr) {
+// rpclog("inreadaddr - %02X\n", hfe_sectordat[5 - mfm->pollbytesleft]);
+ fdc_data(mfm->sectordat[5 - mfm->pollbytesleft]);
+ }
+ if (!mfm->pollbytesleft) {
+ if ((mfm->sectordat[0] == mfm->track && mfm->sectordat[2] == mfm->sector) || mfm->in_readaddr) {
+ mfm->crc = (mfm->density) ? 0xcdb4 : 0xffff;
+ calccrc(mfm, 0xFE);
+ for (c = 0; c < 4; c++)
+ calccrc(mfm, mfm->sectordat[c]);
+ if ((mfm->crc >> 8) != mfm->sectordat[4] || (mfm->crc & 0xFF) != mfm->sectordat[5]) {
+// printf("Header CRC error : %02X %02X %02X %02X\n",crc>>8,crc&0xFF,hfesectordat[4],hfesectordat[5]);
+ if (mfm->in_readaddr) {
+// rpclog("inreadaddr - %02X\n", mfm->sector);
+ fdc_sectorid(mfm->sectordat[0], mfm->sectordat[1], mfm->sectordat[2], mfm->sectordat[3]);
+ }
+ else
+ mfm->readidpoll = 0;
+ } else if (mfm->sectordat[0] == mfm->track && mfm->sectordat[2] == mfm->sector && (mfm->in_read || mfm->in_write) && !mfm->in_readaddr) {
+ mfm->nextsector = 1;
+ mfm->readidpoll = 0;
+ mfm->sectorsize = (1 << (mfm->sectordat[3] + 7)) + 2;
+ mfm->fdc_sectorsize = mfm->sectordat[3];
+ } else if (mfm->in_readaddr) {
+// rpclog("hfe_poll: ID %02x %02x %02x %02x %02x %02x\n", hfe_sectordat[0], hfe_sectordat[1], hfe_sectordat[2], hfe_sectordat[3], hfe_sectordat[4], hfe_sectordat[5]);
+ fdc_sectorid(mfm->sectordat[0], mfm->sectordat[1], mfm->sectordat[2], mfm->sectordat[3]);
+ mfm->in_readaddr = 0;
+ }
+ }
+ }
+ }
+ if (mfm->readdatapoll) {
+// rpclog("data %i %04x\n", mfm->pollbytesleft, new_data);
+ if (mfm->pollbytesleft > 1)
+ calccrc(mfm, decodefm(new_data));
+ else
+ mfm->sectorcrc[1 - mfm->pollbytesleft] = decodefm(new_data);
+ if (!mfm->pollbytesleft) {
+ mfm->in_read = 0;
+ if ((mfm->crc >> 8) != mfm->sectorcrc[0] || (mfm->crc & 0xFF) != mfm->sectorcrc[1]) {
+// rpclog("Data CRC error : %02X %02X %02X %02X\n",mfm->crc>>8,mfm->crc&0xFF,mfm->sectorcrc[0],mfm->sectorcrc[1]);
+ fdc_data(decodefm(mfm->lastdat[1]));
+ fdc_finishread();
+ fdc_datacrcerror();
+ mfm->readdatapoll = 0;
+ } else {
+// rpclog("End of hfe read %02X %02X %02X %02X\n",mfm->crc>>8,mfm->crc&0xFF,mfm->sectorcrc[0],mfm->sectorcrc[1]);
+ fdc_data(decodefm(mfm->lastdat[1]));
+ fdc_finishread();
+ }
+ }
+ else if (mfm->lastdat[1] != 0) {
+ fdc_data(decodefm(mfm->lastdat[1]));
+ }
+ mfm->lastdat[1] = mfm->lastdat[0];
+ mfm->lastdat[0] = new_data;
+ if (!mfm->pollbytesleft)
+ mfm->readdatapoll = 0;
+ }
+ }
+
+ if (mfm->density && !mfm->readdatapoll) {
+ if (new_data == 0x4489) {
+ mfm->ddidbitsleft = 16;
+ } else if (mfm->ddidbitsleft) {
+ mfm->ddidbitsleft--;
+ if (!mfm->ddidbitsleft) {
+// rpclog("ID bits over %04X %02X %i\n",new_data,decodefm(new_data),mfm->pos);
+ if (decodefm(new_data) == 0xFE) {
+// rpclog("Sector header\n");
+ mfm->pollbytesleft = 6;
+ mfm->pollbitsleft = 16;
+ mfm->readidpoll = 1;
+ } else if (decodefm(new_data) == 0xFB) {
+ if (mfm->nextsector) {
+ mfm->pollbytesleft = mfm->sectorsize;
+ mfm->pollbitsleft = 16;
+ mfm->readdatapoll = mfm->in_read;
+ mfm->writedatapoll = mfm->in_write;
+ mfm->rw_write = mfm->in_write;
+ mfm->nextsector = 0;
+ mfm->crc = 0xcdb4;
+ if (new_data == 0xF56A) {
+ calccrc(mfm, 0xF8);
+ mfm->last_bit = 0;
+ } else {
+ calccrc(mfm, 0xFB);
+ mfm->last_bit = 1;
+ }
+ mfm->lastdat[0] = mfm->lastdat[1] = 0;
+ }
+ }
+ }
+ }
+ } else if (!mfm->readdatapoll) {
+ if (new_data == 0xF57E) {
+// rpclog("FM sector header %i\n", mfm->pos);
+ mfm->pollbytesleft = 6;
+ mfm->pollbitsleft = 16;
+ mfm->readidpoll = 1;
+ } if (new_data == 0xF56F || new_data == 0xF56A) {
+// rpclog("FM sector data %i %i\n", mfm->pos, mfm->nextsector);
+ if (mfm->nextsector) {
+ mfm->pollbytesleft = mfm->sectorsize;
+ mfm->pollbitsleft = 16;
+ mfm->readdatapoll = mfm->in_read;
+ mfm->writedatapoll = mfm->in_write;
+ mfm->rw_write = mfm->in_write;
+ mfm->nextsector = 0;
+ mfm->crc = 0xffff;
+ if (new_data == 0xF56A)
+ calccrc(mfm, 0xF8);
+ else
+ calccrc(mfm, 0xFB);
+ mfm->lastdat[0] = mfm->lastdat[1] = 0;
+ }
+ }
+ }
+ }
+ }
+}
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/disc_mfm_common.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/disc_mfm_common.h Sat Oct 09 17:47:01 2021 +0100
@@ -0,0 +1,34 @@
+typedef struct mfm_t
+{
+ uint8_t track_data[2][65536]; /*[side][byte]*/
+ int track_len[3];
+ int track_index[3];
+
+ int sector, track, side, drive, density;
+
+ int in_read, in_write, in_readaddr, in_format;
+ int sync_required;
+ uint64_t buffer;
+ int pos, revs;
+ int indextime_blank;
+ int pollbytesleft, pollbitsleft, ddidbitsleft;
+ int readidpoll, readdatapoll, writedatapoll;
+ int rw_write;
+ int nextsector;
+ uint8_t sectordat[1026];
+ uint16_t crc;
+ int lastdat[2], sectorcrc[2];
+ int sectorsize, fdc_sectorsize;
+ int last_bit;
+
+ int write_protected;
+ void (*writeback)(int drive);
+} mfm_t;
+
+extern void mfm_init(void);
+extern void mfm_common_poll(mfm_t *mfm);
+extern void mfm_readsector(mfm_t *mfm, int drive, int sector, int track, int side, int density);
+extern void mfm_writesector(mfm_t *mfm, int drive, int sector, int track, int side, int density);
+extern void mfm_readaddress(mfm_t *mfm, int drive, int track, int side, int density);
+extern void mfm_format(mfm_t *mfm, int drive, int track, int side, int density);
+extern void mfm_stop(mfm_t *mfm);
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/fdc.c
--- a/src/fdc.c Sat Oct 09 17:23:31 2021 +0100
+++ b/src/fdc.c Sat Oct 09 17:47:01 2021 +0100
@@ -34,6 +34,7 @@
#include "arm.h"
#include "disc.h"
#include "disc_adf.h"
+#include "disc_hfe.h"
/* FDC commands */
enum {
@@ -175,6 +176,7 @@
const char *extension;
long len;
static const Format *format;
+ int is_hfe = 0;
assert(drive == 0 || drive == 1); // Only support two drives
assert(fn != NULL); // Must have filename
@@ -217,8 +219,10 @@
} else {
format = &formats[DISC_FORMAT_DOS_360K];
}
+ } else if (strcasecmp(extension, ".hfe") == 0) {
+ is_hfe = 1;
} else {
- error("Unknown disc image file extension '%s', must be .adf or .adl", extension);
+ error("Unknown disc image file extension '%s', must be .adf, .adl, .img or .hfe", extension);
fclose(f);
return;
}
@@ -229,8 +233,11 @@
drive_funcs[drive] = NULL;
}
- rpclog("fdc_image_load: %s (%ld) loaded as '%s'\n", fn, len, format->name);
- adf_load(drive, fn, format->sectors, format->sectorsize, format->sides, format->tracks == 40,
+ rpclog("fdc_image_load: %s (%ld) loaded as '%s'\n", fn, len, format ? format->name : "HFE");
+ if (is_hfe)
+ hfe_load(drive, fn);
+ else
+ adf_load(drive, fn, format->sectors, format->sectorsize, format->sides, format->tracks == 40,
format->density ? 1 : 2, format->sectorskew);
}
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/qt5/main_window.cpp
--- a/src/qt5/main_window.cpp Sat Oct 09 17:23:31 2021 +0100
+++ b/src/qt5/main_window.cpp Sat Oct 09 17:47:01 2021 +0100
@@ -661,7 +661,7 @@
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Disc Image"),
"",
- tr("All disc images (*.adf *.adl *.img);;ADFS D/E/F Disc Image (*.adf);;ADFS L Disc Image (*.adl);;DOS Disc Image (*.img)"));
+ tr("All disc images (*.adf *.adl *.hfe *.img);;ADFS D/E/F Disc Image (*.adf);;ADFS L Disc Image (*.adl);;DOS Disc Image (*.img);;HFE Disc Image (*.hfe)"));
/* fileName is NULL if user hit cancel */
if(fileName != NULL) {
@@ -675,7 +675,7 @@
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Disc Image"),
"",
- tr("All disc images (*.adf *.adl *.img);;ADFS D/E/F Disc Image (*.adf);;ADFS L Disc Image (*.adl);;DOS Disc Image (*.img)"));
+ tr("All disc images (*.adf *.adl *.hfe *.img);;ADFS D/E/F Disc Image (*.adf);;ADFS L Disc Image (*.adl);;DOS Disc Image (*.img);;HFE Disc Image (*.hfe)"));
/* fileName is NULL if user hit cancel */
if(fileName != NULL) {
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/qt5/rpcemu.pro
--- a/src/qt5/rpcemu.pro Sat Oct 09 17:23:31 2021 +0100
+++ b/src/qt5/rpcemu.pro Sat Oct 09 17:47:01 2021 +0100
@@ -28,6 +28,8 @@
../arm.h \
../disc.h \
../disc_adf.h \
+ ../disc_hfe.h \
+ ../disc_mfm_common.h \
main_window.h \
configure_dialog.h \
about_dialog.h \
@@ -57,6 +59,8 @@
../i8042.c \
../disc.c \
../disc_adf.c \
+ ../disc_hfe.c \
+ ../disc_mfm_common.c \
settings.cpp \
rpc-qt5.cpp \
main_window.cpp \
diff -r ca4be2ca9a9a -r 3c256b7d0551 src/rpcemu.c
--- a/src/rpcemu.c Sat Oct 09 17:23:31 2021 +0100
+++ b/src/rpcemu.c Sat Oct 09 17:47:01 2021 +0100
@@ -53,6 +53,8 @@
#include "fdc.h"
#include "hostfs.h"
#include "disc_adf.h"
+#include "disc_hfe.h"
+#include "disc_mfm_common.h"
#ifdef RPCEMU_NETWORKING
#include "network.h"
@@ -307,6 +309,8 @@
cmos_init();
fdc_init();
adf_init();
+ hfe_init();
+ mfm_init();
fdc_image_load("boot.adf", 0);
fdc_image_load("notboot.adf", 1);
initvideo();
_______________________________________________
RPCEmu mailing list
RPCEmu@riscos.info
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu
No comments:
Post a Comment