From 82cfb277d300eaa91bdfac41af7420281261c58e Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 14 Sep 2019 20:24:06 +0100 Subject: [PATCH 1/9] sdf: expect ADFS-D images to have interleaved sides. --- src/sdf-geo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdf-geo.c b/src/sdf-geo.c index 44aa4f7f..2353791f 100644 --- a/src/sdf-geo.c +++ b/src/sdf-geo.c @@ -168,7 +168,7 @@ struct sdf_geometry sdf_geo_tab[] = { "ADFS-S", SDF_SIDES_SINGLE, SDF_DENS_DOUBLE, 40, 16, 256, new_adfs }, { "ADFS-M", SDF_SIDES_SINGLE, SDF_DENS_DOUBLE, 80, 16, 256, new_adfs }, { "ADFS-L", SDF_SIDES_INTERLEAVED, SDF_DENS_DOUBLE, 80, 16, 256, new_adfs }, - { "ADFS-D", SDF_SIDES_SEQUENTIAL, SDF_DENS_DOUBLE, 80, 5, 1024, NULL }, + { "ADFS-D", SDF_SIDES_INTERLEAVED, SDF_DENS_DOUBLE, 80, 5, 1024, NULL }, { "Acorn DFS", SDF_SIDES_SINGLE, SDF_DENS_SINGLE, 40, 10, 256, new_dfs_single }, { "Acorn DFS", SDF_SIDES_INTERLEAVED, SDF_DENS_SINGLE, 40, 10, 256, new_dfs_interleaved }, { "Acorn DFS", SDF_SIDES_SEQUENTIAL, SDF_DENS_SINGLE, 40, 10, 256, NULL }, From 33c37fa346fcda6ee9ccd95613a63de98469d44b Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 14 Sep 2019 21:07:32 +0100 Subject: [PATCH 2/9] Issue90: build the hdfmt on Linux/Unix. --- src/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 9b165ed0..b63f57ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ # Makefile.am for B-em -bin_PROGRAMS = b-em jstest gtest +bin_PROGRAMS = b-em hdfmt jstest gtest noinst_SCRIPTS = ../b-em CLEANFILES = $(noinst_SCRIPTS) @@ -125,6 +125,8 @@ if NO_TSEARCH b_em_SOURCES += tsearch.c endif +hdfmt_SOURCES = hdfmt.c + jstest_SOURCES = jstest.c jstest_LDADD = -lallegro -lallegro_main From e544169b9d669ee4e13988d1e57c5137ddc9f8b0 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 14 Sep 2019 21:10:03 +0100 Subject: [PATCH 3/9] Issue90: fix the invalid size error message. --- src/hdfmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hdfmt.c b/src/hdfmt.c index 8dd68de4..477432a0 100644 --- a/src/hdfmt.c +++ b/src/hdfmt.c @@ -150,7 +150,7 @@ int main(int argc, char **argv) } else { - fprintf(stderr, "hdfmt: %s is not a valid size\n", argv[1]); + fprintf(stderr, "hdfmt: %s is not a valid size\n", argv[2]); status = 1; } } From 6387a3dd8c10316c0fb0308337e12d200ad89b52 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Wed, 18 Sep 2019 23:40:21 +0100 Subject: [PATCH 4/9] scsi: add new utilities for SCSI discs. This adds two new utilities. fdresize will re-size (grow) a SCSI hard disc image. fsmap will display an ADFS fsmap. --- src/fsmap.c | 50 ++++++++++++++++ src/hdresize.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 src/fsmap.c create mode 100644 src/hdresize.c diff --git a/src/fsmap.c b/src/fsmap.c new file mode 100644 index 00000000..aeac9e5f --- /dev/null +++ b/src/fsmap.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int status; + + if (argc > 1) { + status = 0; + while (--argc) { + const char *fn = *++argv; + FILE *fp = fopen(fn, "rb"); + if (fp) { + unsigned char fsmap[0x200]; + if (fread(fsmap, sizeof fsmap, 1, fp) == 1) { + puts(fn); + unsigned char *sptr = fsmap; + unsigned char *eptr = fsmap + fsmap[0x1FE]; + unsigned char *lptr = fsmap + 0x100; + while (sptr < eptr) { + uint32_t start = *sptr++; + start |= (*sptr++ << 8); + start |= (*sptr++ << 16); + uint32_t len = *lptr++; + len |= (*lptr++ << 8); + len |= (*lptr++ << 16); + if (len > 0) + printf("%06X %06X (%d)\n", start, len, len); + } + } + else { + fprintf(stderr, "fsmap: unable to read fsmap from %s: %s\n", fn, strerror(errno)); + status = 3; + } + } + else { + fprintf(stderr, "fsmap: unable to open %s for reading: %s\n", fn, strerror(errno)); + status = 2; + } + } + } + else { + fputs("Usage: fsmap [ ... ]\n", stderr); + status = 1; + } + return status; +} diff --git a/src/hdresize.c b/src/hdresize.c new file mode 100644 index 00000000..b1717be3 --- /dev/null +++ b/src/hdresize.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include + +static int parse_size(const char *size) +{ + int value; + char *end; + + value = strtol(size, &end, 10); + switch (*end) { + case 'k': + case 'K': + value *= 1024; + break; + case 'm': + case 'M': + value *= 1024 * 1024; + break; + case 'g': + case 'G': + value *= 1024 * 1024 * 1024; + break; + } + return value; +} + +static inline uint32_t read24(const unsigned char *base) +{ + return base[0] | (base[1] << 8) | (base[2] << 16); +} + +static inline void write24(uint8_t *base, uint32_t value) +{ + base[0] = value & 0xff; + base[1] = (value >> 8) & 0xff; + base[2] = (value >> 16) & 0xff; +} + +static uint8_t checksum(uint8_t *base) +{ + int i = 255, c = 0; + unsigned sum = 255; + while (--i >= 0) { + sum += base[i] + c; + c = 0; + if (sum >= 256) { + sum &= 0xff; + c = 1; + } + } + return sum; +} + +int main(int argc, char **argv) +{ + int status; + + if (argc == 3) { + int size = parse_size(argv[2]); + if (size > 0) { + const char *fn = argv[1]; + size_t len = strlen(fn) + 5; + char *dat_fn = alloca(len); + snprintf(dat_fn, len, "%s.dat", fn); + FILE *dat_fp = fopen(dat_fn, "rb+"); + if (dat_fp) { + unsigned char fsmap[512]; + if (fread(fsmap, sizeof fsmap, 1, dat_fp) == 1) { + if (fsmap[0x1FE] <= 3) { + status = 0; + char *dsc_fn = alloca(len); + snprintf(dsc_fn, len, "%s.dsc", fn); + FILE *dsc_fp = fopen(dsc_fn, "rb+"); + if (dsc_fp) { + unsigned char geom[22]; + if (fread(geom, sizeof geom, 1, dsc_fp) == 1) { + int new_sects = size / 256; + int old_sects = read24(fsmap + 0x0FC); + printf("hdresize: old sectors=%d, new_sects=%d\n", old_sects, new_sects); + if (new_sects > old_sects) { + write24(fsmap + 0x0FC, new_sects); + fsmap[0x0FF] = checksum(fsmap); + unsigned char *ptr = fsmap + 0x100; + write24(ptr, read24(ptr) + (new_sects - old_sects)); + fsmap[0x1ff] = checksum(ptr); + int cyl = 1 + ((new_sects - 1) / (33 * 255)); + geom[13] = cyl % 256; + geom[14] = cyl / 256; + geom[15] = 255; + if (fseek(dsc_fp, 0, SEEK_SET) == 0 && fwrite(geom, sizeof geom, 1, dsc_fp) == 1) { + if (fseek(dat_fp, 0, SEEK_SET) == 0 && fwrite(fsmap, sizeof fsmap, 1, dat_fp) == 1) { + status = 0; + printf("hdresize: %s grown\n", fn); + } + else + { + fprintf(stderr, "hdresize: unable to write fsmap to %s: %s\n", dat_fn, strerror(errno)); + status = 8; + } + } + else { + fprintf(stderr, "hdresize: unable to write geometry to %s: %s\n", dsc_fn, strerror(errno)); + status = 7; + } + } + else { + fputs("hdresize: shrinking not implemented\n", stderr); + status = 6; + } + } + else { + fprintf(stderr, "hdresize: unable to read geometry from %s: %s\n", dsc_fn, strerror(errno)); + status = 5; + } + } + else { + fprintf(stderr, "hdresize: unable to open dsc file %s: %s\n", dsc_fn, strerror(errno)); + status = 2; + } + } + else { + fprintf(stderr, "hdresize: %s has more than one free entry, compact before resizing\n", fn); + status = 4; + } + } + else { + fprintf(stderr, "hdresize: unable to read fsmap from %s: %s\n", dat_fn, strerror(errno)); + status = 3; + } + fclose(dat_fp); + } + else { + fprintf(stderr, "hdresize: unable to open data file %s: %s\n", dat_fn, strerror(errno)); + status = 2; + } + } + else { + fprintf(stderr, "hdresize: %s is not a valid size\n", argv[2]); + status = 1; + } + } + else { + fputs("usage: hdresize \n", stderr); + status = 1; + } + return status; +} + + + + + + + From be548bf81e1a93b2728f04bcec8d43a0b82dae34 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Wed, 18 Sep 2019 23:41:45 +0100 Subject: [PATCH 5/9] Add new executable to the git ignore list. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 81d87a57..74bdfd2c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ src/jstest src/jstest.exe src/gtest src/gtest.exe +src/fsmap +src/hdfmt +src/fdresize From 9fbc6fd6bf6d544830b4362e26b616bca789a451 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Thu, 19 Sep 2019 01:32:19 +0100 Subject: [PATCH 6/9] sdf: improve detection of sequential vs. interleaved sides. --- src/sdf-geo.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/sdf-geo.c b/src/sdf-geo.c index 2353791f..66fbfc23 100644 --- a/src/sdf-geo.c +++ b/src/sdf-geo.c @@ -286,6 +286,10 @@ static int32_t dfs_size(FILE *fp, long offset) base += 8; dirsize -= 8; new_start = ((base[6] & 0x03) << 8) | base[7]; + if (new_start == 0) { + log_debug("sdf: impossible start position"); + return -1; + } if (new_start > cur_start) { log_debug("sdf: catalogue not sorted"); return -1; @@ -326,10 +330,17 @@ static const struct sdf_geometry *find_geo_dfs(const char *fn, const char *ext, } track_bytes = geo->sectors_per_track * geo->sector_size; side_bytes = track_bytes * geo->tracks; - if (fsize > side_bytes && dfs_size(fp, side_bytes) >= 3) - geo += 2; // sequential sided-version. - else if (!strcasecmp(ext, "dsd") || !strcasecmp(ext, "ddd")) - geo++; // interleaved side version. + if (fsize > track_bytes) { + if (dfs_size(fp, track_bytes) >= 3) { + geo++; // interleaved side version. + if (dfs_size(fp, side_bytes) >= 3 && strcasecmp(ext, "dsd") && strcasecmp(ext, "ddd")) + geo++; // sequential side version. + } + else if (dfs_size(fp, side_bytes) >= 3) + geo += 2; // sequential side version. + else if (!strcasecmp(ext, "dsd") || !strcasecmp(ext, "ddd")) + geo++; // interleaved side version. + } return geo; } return NULL; From 1b332eb13826c44476602da97489faa57759dfcd Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 20 Sep 2019 00:01:36 +0100 Subject: [PATCH 7/9] tube: add more debug messages. --- src/tube.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tube.c b/src/tube.c index 2242057d..1353d4c1 100644 --- a/src/tube.c +++ b/src/tube.c @@ -63,8 +63,19 @@ void tube_updateints() if (((tubeula.r1stat & 2) && (tubeula.pstat[0] & 128)) || ((tubeula.r1stat & 4) && (tubeula.pstat[3] & 128))) new_irq |= 1; - if (tubeula.r1stat & 8 && (tubeula.ph3pos == 0 || tubeula.hp3pos > (tubeula.r1stat & 16) ? 1 : 0)) + if (!(tube_irq & 1)) + log_debug("tube: parasite IRQ asserted"); + } + else if (tube_irq & 1) + log_debug("tube: parasite IRQ de-asserted"); + + if (tubeula.r1stat & 8 && (tubeula.ph3pos == 0 || tubeula.hp3pos > (tubeula.r1stat & 16) ? 1 : 0)) { new_irq |= 2; + if (!(tube_irq & 2)) + log_debug("tube: parasite NMI asserted"); + } + else if (tube_irq & 2) + log_debug("tube: parasite NMI de-asserted"); if (tube_type == TUBE6809 && new_irq != tube_irq) tube_6809_int(new_irq); From b377866a3f5fd0dce366d744aceee79d4c3971a9 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 20 Sep 2019 00:02:38 +0100 Subject: [PATCH 8/9] tube: Fix issue#91 by returning 1 for unused bits of R3 status. See the issue on GitHub for more detail but the way the parasite to host transfer type 6 is coded in Pandora relies on the unused bits of the tube R3 status as seen from the parasite (pstat[2]) being 1 rather than 0. When those bits are set to 0 a test for R3 being ready to write to fails to detect R3 being full and the parasite keeps writing to the already full R3 before the host has a chance to read it. Transfer type 6 is used by ADFS so anything written to ADFS would be corruped and this would also crash the 32016 when installing Panos from floppies. --- src/tube.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tube.c b/src/tube.c index 1353d4c1..e9fe7252 100644 --- a/src/tube.c +++ b/src/tube.c @@ -343,7 +343,8 @@ void tube_reset(void) tubeula.ph3pos = 1; tubeula.r1stat = 0; tubeula.hstat[0] = tubeula.hstat[1] = tubeula.hstat[3] = 0x40; - tubeula.pstat[0] = tubeula.pstat[1] = tubeula.pstat[2] = tubeula.pstat[3] = 0x40; + tubeula.pstat[0] = 0x40; + tubeula.pstat[1] = tubeula.pstat[2] = tubeula.pstat[3] = 0x7f; tubeula.hstat[2] = 0xC0; tube_romin = 1; } From aba1558ecf7b93c8352ea8c25097978f7ef70551 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 20 Sep 2019 00:15:00 +0100 Subject: [PATCH 9/9] tube: fix merge failure in 1b332eb13826c44476602da97489faa57759dfcd --- src/tube.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tube.c b/src/tube.c index e9fe7252..90b86d81 100644 --- a/src/tube.c +++ b/src/tube.c @@ -61,7 +61,7 @@ void tube_updateints() if ((tubeula.r1stat & 1) && (tubeula.hstat[3] & 128)) interrupt |= 8; - if (((tubeula.r1stat & 2) && (tubeula.pstat[0] & 128)) || ((tubeula.r1stat & 4) && (tubeula.pstat[3] & 128))) + if (((tubeula.r1stat & 2) && (tubeula.pstat[0] & 128)) || ((tubeula.r1stat & 4) && (tubeula.pstat[3] & 128))) { new_irq |= 1; if (!(tube_irq & 1)) log_debug("tube: parasite IRQ asserted");