From 5743758c0caeadc9b1b4b57770cba47ce74da113 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 03:06:00 +0000 Subject: [PATCH 01/35] vdfs: enable print_split to be used iteratively. --- src/vdfs.asm | 5 ++++- src/vdfs.c | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vdfs.asm b/src/vdfs.asm index ca09d50d..49f51dc4 100644 --- a/src/vdfs.asm +++ b/src/vdfs.asm @@ -677,7 +677,10 @@ prtextws = &A8 bne loop inc &a9 bne loop -.done rts +.done txa + bne more + rts +.more sta port_cmd } ; The *DUMP command. diff --git a/src/vdfs.c b/src/vdfs.c index 4b4336a0..30dc75ea 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -3907,6 +3907,7 @@ static void cmd_pwd(void) writemem(addr-1, 0x0d); writemem(addr, 0x0a); writemem(addr+1, 0); + x = 0; rom_dispatch(VDFS_ROM_PRINT_SPLIT); } } From 1630ffddcb03cc0b1ab7ea2caebd53d22d67624a Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 03:07:10 +0000 Subject: [PATCH 02/35] vdfs: add pre-built ROM from the previous commit. --- roms/general/vdfs.rom | Bin 5536 -> 5542 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/roms/general/vdfs.rom b/roms/general/vdfs.rom index d1fc289bfdb98ea5580898de00ed2ff0acaf0e42..70d8fe34895960c0c00da68190e84b3f3f6d50c5 100644 GIT binary patch delta 442 zcmZ3Wy-Zt5{$+!YdSjC`yOXYKu0oiLTQGyExrwp4sl`O8`Lsj2Val9YA8VUwLri6mQf2T_EV?+khTWR6dh!l-C-It&l?n>){wt_-D&%x1?Cw~y%I9ml zLe6AC4hxx@4h8v6nAjo)1qlE7e~_BVsT}utG&>jlzrYOC{$g+S&8IkXSb~9y-Yw`Z6dP-Go~(L27CFGz%PZ2sXiW)6GiO-eIC2N delta 479 zcmZ3cy+B(^{$+!YdSjC`yOXYKu0oiLTQEb4QA(?GF*q1H7Dc9So%SumcN%*9^BR@t_aVbSTyP3+c;rIYuuJBgQdfXz~n z>r_bVP}thBWR=hRc7?Rb;v5z-WgQBVoiMRQ3;Ea(MN87o$DCd}}F%E5RLB`_Y6%Do)@tM*Rn0~$A#AliY$v9_x_w*E~LS>aZ2loz1ub~6%t}%edD=|Id}3Nky(OCQx`FV SgW#0FFNLJ3K2DR Date: Fri, 26 Jan 2024 13:58:50 +0000 Subject: [PATCH 03/35] mmb: move MMB functions from sdf-acc.c to a new mmb.c This is the first step of consolidating MMB function in a specific module before adding new MMB functions. --- src/Makefile.am | 1 + src/config.c | 1 + src/gui-allegro.c | 1 + src/main.c | 1 + src/mmb.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++ src/mmb.h | 20 +++++ src/sdf-acc.c | 196 +------------------------------------------ src/sdf.h | 11 +-- src/vdfs.c | 1 + 9 files changed, 240 insertions(+), 202 deletions(-) create mode 100644 src/mmb.c create mode 100644 src/mmb.h diff --git a/src/Makefile.am b/src/Makefile.am index 23d05df2..3cabd488 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -83,6 +83,7 @@ b_em_SOURCES = \ mc6809nc/mc6809_dis.c \ main.c \ mem.c \ + mmb.c \ model.c \ mouse.c \ mmccard.c \ diff --git a/src/config.c b/src/config.c index bfaa6071..66557a5b 100644 --- a/src/config.c +++ b/src/config.c @@ -9,6 +9,7 @@ #include "keyboard.h" #include "main.h" #include "mem.h" +#include "mmb.h" #include "model.h" #include "mouse.h" #include "mmccard.h" diff --git a/src/gui-allegro.c b/src/gui-allegro.c index 349ec07d..dc3004b3 100644 --- a/src/gui-allegro.c +++ b/src/gui-allegro.c @@ -14,6 +14,7 @@ #include "keydef-allegro.h" #include "main.h" #include "mem.h" +#include "mmb.h" #include "model.h" #include "mouse.h" #include "music5000.h" diff --git a/src/main.c b/src/main.c index 053f0fd7..1dc1dd86 100644 --- a/src/main.c +++ b/src/main.c @@ -30,6 +30,7 @@ #include "main.h" #include "6809tube.h" #include "mem.h" +#include "mmb.h" #include "mouse.h" #include "midi.h" #include "music4000.h" diff --git a/src/mmb.c b/src/mmb.c new file mode 100644 index 00000000..634dbbd5 --- /dev/null +++ b/src/mmb.c @@ -0,0 +1,210 @@ +#define _DEBUG +/* + * B-EM MMB - Support for MMB files. + * + * This B-Em module is to support MMB files which are containers + * containing a number of SSD disc images with an index at the start. + * + * This module works with the SDF module to enable disk images to + * be inserted and then access via the normal FDC and therefore + * Acorn DFS without the need to load a MMB-specific filing system. + */ + +#include "b-em.h" +#include "disc.h" +#include "mmb.h" +#include "sdf.h" +#include "6502.h" +#include "mem.h" +#include "vdfs.h" + +#define MMB_DISC_SIZE (200*1024) +#define MMB_NAME_SIZE 16 +#define MMB_ZONE_DISCS 511 +#define MMB_ZONE_CAT_SIZE (MMB_ZONE_DISCS*MMB_NAME_SIZE) +#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_NAME_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) +#define MMB_ZONE_SKIP_SIZE (MMB_ZONE_DISCS*MMB_DISC_SIZE+MMB_NAME_SIZE) + +static unsigned mmb_boot_discs[4]; +static unsigned mmb_cat_size; +static char *mmb_cat; +unsigned mmb_ndisc; +char *mmb_fn; + +static void mmb_read_error(const char *fn, FILE *fp) +{ + if (ferror(fp)) + log_error("mmb: read error on MMB file %s: %s", fn, strerror(errno)); + else + log_error("mmb: unexpected EOF on MMB file %s", fn); + fclose(fp); +} + +static unsigned mmb_calc_offset(unsigned disc) +{ + unsigned zone_start = disc / MMB_ZONE_DISCS; + unsigned zone_index = disc % MMB_ZONE_DISCS; + unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + MMB_NAME_SIZE + zone_index * MMB_DISC_SIZE; + log_debug("mmb: mmb_calc_offset(%u) -> zone_start=%u, zone_index=%u, offset=%u", disc, zone_start, zone_index, offset); + return offset; +} + +void mmb_load(char *fn) +{ + writeprot[0] = 0; + FILE *fp = fopen(fn, "rb+"); + if (fp == NULL) { + if ((fp = fopen(fn, "rb")) == NULL) { + log_error("Unable to open file '%s' for reading - %s", fn, strerror(errno)); + return; + } + writeprot[0] = 1; + } + unsigned char header[16]; + if (fread(header, sizeof(header), 1, fp) != 1) { + mmb_read_error(fn, fp); + return; + } + mmb_boot_discs[0] = header[0] | (header[4] << 8); + mmb_boot_discs[1] = header[1] | (header[5] << 8); + mmb_boot_discs[2] = header[2] | (header[6] << 8); + mmb_boot_discs[3] = header[3] | (header[7] << 8); + unsigned extra_zones = header[8]; + extra_zones = ((extra_zones & 0xf0) == 0xa0) ? extra_zones & 0x0f : 0; + unsigned reqd_cat_size = (extra_zones + 1) * MMB_ZONE_CAT_SIZE; + log_debug("mmb: mmb extra zones=%u, mmb cat total size=%u", extra_zones, reqd_cat_size); + if (reqd_cat_size != mmb_cat_size) { + if (mmb_cat) + free(mmb_cat); + if (!(mmb_cat = malloc(reqd_cat_size))) { + log_error("mmb: out of memory allocating MMB catalogue"); + return; + } + mmb_cat_size = reqd_cat_size; + } + if (fread(mmb_cat, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { + mmb_read_error(fn, fp); + return; + } + char *mmb_ptr = mmb_cat + MMB_ZONE_CAT_SIZE; + char *mmb_end = mmb_cat + reqd_cat_size; + while (mmb_ptr < mmb_end) { + if (fseek(fp, MMB_ZONE_SKIP_SIZE, SEEK_CUR)) { + log_error("mmb: seek error on MMB file %s: %s", fn, strerror(errno)); + fclose(fp); + return; + } + if (fread(mmb_ptr, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { + mmb_read_error(fn, fp); + return; + } + mmb_ptr += MMB_ZONE_CAT_SIZE; + } + unsigned i = 0; + for (mmb_ptr = mmb_cat; mmb_ptr < mmb_end; mmb_ptr += 16) + log_debug("mmb: mmb#%04u=%-12.12s", i++, mmb_ptr); + if (mmb_fp) { + fclose(mmb_fp); + if (sdf_fp[1] == mmb_fp) { + sdf_mount(1, fn, fp, &sdf_geometries.dfs_10s_seq_80t); + writeprot[1] = writeprot[0]; + mmb_offset[1][0] = mmb_calc_offset(mmb_boot_discs[2]); + mmb_offset[1][1] = mmb_calc_offset(mmb_boot_discs[3]); + } + } + sdf_mount(0, fn, fp, &sdf_geometries.dfs_10s_seq_80t); + mmb_offset[0][0] = mmb_calc_offset(mmb_boot_discs[0]); + mmb_offset[0][1] = mmb_calc_offset(mmb_boot_discs[1]); + mmb_fp = fp; + mmb_fn = fn; + mmb_ndisc = (extra_zones + 1) * MMB_ZONE_DISCS; + if (fdc_spindown) + fdc_spindown(); +} + +static void mmb_eject_one(int drive) +{ + ALLEGRO_PATH *path; + + if (sdf_fp[drive] == mmb_fp) { + disc_close(drive); + if ((path = discfns[drive])) + disc_load(drive, path); + } +} + +void mmb_eject(void) +{ + if (mmb_fp) { + mmb_eject_one(0); + mmb_eject_one(1); + } + if (mmb_fn) { + free(mmb_fn); + mmb_fn = NULL; + } + mmb_ndisc = 0; +} + +static void reset_one(int drive) +{ + if (sdf_fp[drive] == mmb_fp) { + mmb_offset[drive][0] = mmb_calc_offset(0); + mmb_offset[drive][1] = mmb_calc_offset(1); + } +} + +void mmb_reset(void) +{ + if (mmb_fp) { + reset_one(0); + reset_one(1); + } +} + +void mmb_pick(unsigned drive, unsigned side, unsigned disc) +{ + log_debug("mmb: picking MMB disc, drive=%d, side=%d, disc=%d", drive, side, disc); + + if (sdf_fp[drive] != mmb_fp) { + disc_close(drive); + sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); + } + mmb_offset[drive][side] = mmb_calc_offset(disc); + if (fdc_spindown) + fdc_spindown(); +} + +static inline int cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const char *cat_nxt) +{ + do { + char cat_ch = *cat_ptr++; + char nam_ch = *nam_ptr++; + if (!nam_ch) { + if (!cat_ch) + break; + else + return -1; + } + if ((cat_ch ^ nam_ch) & 0x5f) + return -1; + } while (cat_nxt != cat_ptr); + return (cat_nxt - mmb_cat) / 16 - 1; +} + +int mmb_find(const char *name) +{ + const char *cat_ptr = mmb_cat; + const char *cat_end = mmb_cat + mmb_cat_size; + + do { + const char *cat_nxt = cat_ptr + 16; + int i = cat_name_cmp(name, cat_ptr, cat_nxt); + if (i >= 0) { + log_debug("mmb: found MMB SSD '%s' at %d", name, i); + return i; + } + cat_ptr = cat_nxt; + } while (cat_ptr < cat_end); + return -1; +} diff --git a/src/mmb.h b/src/mmb.h new file mode 100644 index 00000000..66912aaa --- /dev/null +++ b/src/mmb.h @@ -0,0 +1,20 @@ +/* + * B-EM MMB - Support for MMB files - interface. + */ + +#ifndef MMB_INC +#define MMB_INC + +extern FILE *mmb_fp; +extern char *mmb_fn; +extern unsigned mmb_ndisc; +extern off_t mmb_offset[NUM_DRIVES][2]; + +// Functions for MMB files. +void mmb_load(char *fn); +void mmb_eject(void); +void mmb_pick(unsigned drive, unsigned side, unsigned disc); +void mmb_reset(void); +int mmb_find(const char *name); + +#endif diff --git a/src/sdf-acc.c b/src/sdf-acc.c index 5827dcc2..269cefd7 100644 --- a/src/sdf-acc.c +++ b/src/sdf-acc.c @@ -18,22 +18,10 @@ #include "disc.h" #include "sdf.h" -#define MMB_DISC_SIZE (200*1024) -#define MMB_NAME_SIZE 16 -#define MMB_ZONE_DISCS 511 -#define MMB_ZONE_CAT_SIZE (MMB_ZONE_DISCS*MMB_NAME_SIZE) -#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_NAME_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) -#define MMB_ZONE_SKIP_SIZE (MMB_ZONE_DISCS*MMB_DISC_SIZE+MMB_NAME_SIZE) - -static FILE *sdf_fp[NUM_DRIVES], *mmb_fp; +FILE *sdf_fp[NUM_DRIVES], *mmb_fp; +off_t mmb_offset[NUM_DRIVES][2]; static const struct sdf_geometry *geometry[NUM_DRIVES]; static uint8_t current_track[NUM_DRIVES]; -static off_t mmb_offset[NUM_DRIVES][2]; -static unsigned mmb_boot_discs[4]; -static unsigned mmb_cat_size; -static char *mmb_cat; -unsigned mmb_ndisc; -char *mmb_fn; typedef enum { ST_IDLE, @@ -602,7 +590,7 @@ static void sdf_spindown(int drive) } } -static void sdf_mount(int drive, const char *fn, FILE *fp, const struct sdf_geometry *geo) +void sdf_mount(int drive, const char *fn, FILE *fp, const struct sdf_geometry *geo) { sdf_fp[drive] = fp; log_info("Loaded drive %d with %s, format %s, %s, %d tracks, %s, %d %d byte sectors/track", @@ -662,181 +650,3 @@ void sdf_new_disc(int drive, ALLEGRO_PATH *fn, const struct sdf_geometry *geo) log_error("sdf: drive %d: unable to open disk image %s for writing: %s", drive, cpath, strerror(errno)); } } - -static void mmb_read_error(const char *fn, FILE *fp) -{ - if (ferror(fp)) - log_error("sdf: read error on MMB file %s: %s", fn, strerror(errno)); - else - log_error("sdf: unexpected EOF on MMB file %s", fn); - fclose(fp); -} - -static unsigned mmb_calc_offset(unsigned disc) -{ - unsigned zone_start = disc / MMB_ZONE_DISCS; - unsigned zone_index = disc % MMB_ZONE_DISCS; - unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + MMB_NAME_SIZE + zone_index * MMB_DISC_SIZE; - log_debug("sdf: mmb_calc_offset(%u) -> zone_start=%u, zone_index=%u, offset=%u", disc, zone_start, zone_index, offset); - return offset; -} - -void mmb_load(char *fn) -{ - writeprot[0] = 0; - FILE *fp = fopen(fn, "rb+"); - if (fp == NULL) { - if ((fp = fopen(fn, "rb")) == NULL) { - log_error("Unable to open file '%s' for reading - %s", fn, strerror(errno)); - return; - } - writeprot[0] = 1; - } - unsigned char header[16]; - if (fread(header, sizeof(header), 1, fp) != 1) { - mmb_read_error(fn, fp); - return; - } - mmb_boot_discs[0] = header[0] | (header[4] << 8); - mmb_boot_discs[1] = header[1] | (header[5] << 8); - mmb_boot_discs[2] = header[2] | (header[6] << 8); - mmb_boot_discs[3] = header[3] | (header[7] << 8); - unsigned extra_zones = header[8]; - extra_zones = ((extra_zones & 0xf0) == 0xa0) ? extra_zones & 0x0f : 0; - unsigned reqd_cat_size = (extra_zones + 1) * MMB_ZONE_CAT_SIZE; - log_debug("sdf-acc: mmb extra zones=%u, mmb cat total size=%u", extra_zones, reqd_cat_size); - if (reqd_cat_size != mmb_cat_size) { - if (mmb_cat) - free(mmb_cat); - if (!(mmb_cat = malloc(reqd_cat_size))) { - log_error("sdf: out of memory allocating MMB catalogue"); - return; - } - mmb_cat_size = reqd_cat_size; - } - if (fread(mmb_cat, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { - mmb_read_error(fn, fp); - return; - } - char *mmb_ptr = mmb_cat + MMB_ZONE_CAT_SIZE; - char *mmb_end = mmb_cat + reqd_cat_size; - while (mmb_ptr < mmb_end) { - if (fseek(fp, MMB_ZONE_SKIP_SIZE, SEEK_CUR)) { - log_error("sdf: seek error on MMB file %s: %s", fn, strerror(errno)); - fclose(fp); - return; - } - if (fread(mmb_ptr, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { - mmb_read_error(fn, fp); - return; - } - mmb_ptr += MMB_ZONE_CAT_SIZE; - } - unsigned i = 0; - for (mmb_ptr = mmb_cat; mmb_ptr < mmb_end; mmb_ptr += 16) - log_debug("sdf-acc: mmb#%04u=%-12.12s", i++, mmb_ptr); - if (mmb_fp) { - fclose(mmb_fp); - if (sdf_fp[1] == mmb_fp) { - sdf_mount(1, fn, fp, &sdf_geometries.dfs_10s_seq_80t); - writeprot[1] = writeprot[0]; - mmb_offset[1][0] = mmb_calc_offset(mmb_boot_discs[2]); - mmb_offset[1][1] = mmb_calc_offset(mmb_boot_discs[3]); - } - } - sdf_mount(0, fn, fp, &sdf_geometries.dfs_10s_seq_80t); - mmb_offset[0][0] = mmb_calc_offset(mmb_boot_discs[0]); - mmb_offset[0][1] = mmb_calc_offset(mmb_boot_discs[1]); - mmb_fp = fp; - mmb_fn = fn; - mmb_ndisc = (extra_zones + 1) * MMB_ZONE_DISCS; - if (fdc_spindown) - fdc_spindown(); -} - -static void mmb_eject_one(int drive) -{ - ALLEGRO_PATH *path; - - if (sdf_fp[drive] == mmb_fp) { - disc_close(drive); - if ((path = discfns[drive])) - disc_load(drive, path); - } -} - -void mmb_eject(void) -{ - if (mmb_fp) { - mmb_eject_one(0); - mmb_eject_one(1); - } - if (mmb_fn) { - free(mmb_fn); - mmb_fn = NULL; - } - mmb_ndisc = 0; -} - -static void reset_one(int drive) -{ - if (sdf_fp[drive] == mmb_fp) { - mmb_offset[drive][0] = mmb_calc_offset(0); - mmb_offset[drive][1] = mmb_calc_offset(1); - } -} - -void mmb_reset(void) -{ - if (mmb_fp) { - reset_one(0); - reset_one(1); - } -} - -void mmb_pick(unsigned drive, unsigned side, unsigned disc) -{ - log_debug("sdf: picking MMB disc, drive=%d, side=%d, disc=%d", drive, side, disc); - - if (sdf_fp[drive] != mmb_fp) { - disc_close(drive); - sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); - } - mmb_offset[drive][side] = mmb_calc_offset(disc); - if (fdc_spindown) - fdc_spindown(); -} - -static inline int cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const char *cat_nxt) -{ - do { - char cat_ch = *cat_ptr++; - char nam_ch = *nam_ptr++; - if (!nam_ch) { - if (!cat_ch) - break; - else - return -1; - } - if ((cat_ch ^ nam_ch) & 0x5f) - return -1; - } while (cat_nxt != cat_ptr); - return (cat_nxt - mmb_cat) / 16 - 1; -} - -int mmb_find(const char *name) -{ - const char *cat_ptr = mmb_cat; - const char *cat_end = mmb_cat + mmb_cat_size; - - do { - const char *cat_nxt = cat_ptr + 16; - int i = cat_name_cmp(name, cat_ptr, cat_nxt); - if (i >= 0) { - log_debug("mmb: found MMB SSD '%s' at %d", name, i); - return i; - } - cat_ptr = cat_nxt; - } while (cat_ptr < cat_end); - return -1; -} diff --git a/src/sdf.h b/src/sdf.h index 352e321e..dd4d3035 100644 --- a/src/sdf.h +++ b/src/sdf.h @@ -50,8 +50,7 @@ struct sdf_geometry_set { extern const struct sdf_geometry_set sdf_geometries; -extern char *mmb_fn; -extern unsigned mmb_ndisc; +extern FILE *sdf_fp[]; // In sdf-geo.c const struct sdf_geometry *sdf_find_geo(const char *fn, const char *ext, FILE *fp); @@ -60,16 +59,10 @@ const char *sdf_desc_dens(const struct sdf_geometry *geo); // In sdf-acc.c void sdf_new_disc(int drive, ALLEGRO_PATH *fn, const struct sdf_geometry *geo); +void sdf_mount(int drive, const char *fn, FILE *fp, const struct sdf_geometry *geo); void sdf_load(int drive, const char *fn, const char *ext); FILE *sdf_owseek(uint8_t drive, uint8_t sector, uint8_t track, uint8_t side, uint16_t ssize); -// Functions for MMB files. -void mmb_load(char *fn); -void mmb_eject(void); -void mmb_pick(unsigned drive, unsigned side, unsigned disc); -void mmb_reset(void); -int mmb_find(const char *name); - //DB: bodge for VS #ifdef _MSC_VER //not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw diff --git a/src/vdfs.c b/src/vdfs.c index 30dc75ea..f7471804 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -40,6 +40,7 @@ #include "led.h" #include "main.h" #include "mem.h" +#include "mmb.h" #include "model.h" #include "sdf.h" #include "tube.h" From 8c707472637233c16110f628636418ca11368c88 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 15:09:41 +0000 Subject: [PATCH 04/35] mmb: move *DIN from VDFS to new MMB module. --- src/mmb.c | 93 ++++++++++++++++++++- src/mmb.h | 2 +- src/vdfs.c | 236 +++++++++++++++++------------------------------------ src/vdfs.h | 2 + 4 files changed, 169 insertions(+), 164 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 634dbbd5..0029778e 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -192,7 +192,7 @@ static inline int cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const c return (cat_nxt - mmb_cat) / 16 - 1; } -int mmb_find(const char *name) +static int mmb_find(const char *name) { const char *cat_ptr = mmb_cat; const char *cat_end = mmb_cat + mmb_cat_size; @@ -208,3 +208,94 @@ int mmb_find(const char *name) } while (cat_ptr < cat_end); return -1; } + +static const char err_disc_not_fnd[] = "\xd6" "Disk not found in MMB file"; +static const char err_bad_drive_id[] = "\x94" "Bad drive ID"; + +static int mmb_parse_find(uint16_t addr) +{ + char name[17]; + int ch = readmem(addr++); + int i = 0; + bool quote = false; + + if (ch == '"') { + quote = true; + ch = readmem(addr++); + } + while (ch != '\r' && i < sizeof(name) && ((quote && ch != '"') || (!quote && ch != ' '))) { + name[i++] = ch; + ch = readmem(addr++); + } + name[i] = 0; + if ((i = mmb_find(name)) < 0) + vdfs_error(err_disc_not_fnd); + return i; +} + +static bool mmb_check_pick(unsigned drive, unsigned disc) +{ + if (disc >= mmb_ndisc) { + vdfs_error(err_disc_not_fnd); + return false; + } + unsigned side; + switch(drive) { + case 0: + case 1: + side = 0; + break; + case 2: + case 3: + drive &= 1; + disc--; + side = 1; + break; + default: + log_debug("vdfs: mmb_check_pick: invalid logical drive %d", drive); + vdfs_error(err_bad_drive_id); + return false; + } + mmb_pick(drive, side, disc); + return true; +} + +void mmb_cmd_din(uint16_t addr) +{ + int num1 = 0, num2 = 0; + uint16_t addr2 = addr; + int ch = readmem(addr2); + while (ch >= '0' && ch <= '9') { + num1 = num1 * 10 + ch - '0'; + ch = readmem(++addr2); + } + if (ch == ' ' || ch == '\r') { + while (ch == ' ') + ch = readmem(++addr2); + if (ch == '\r') + mmb_check_pick(0, num1); + else { + addr = addr2; + while (ch >= '0' && ch <= '9') { + num2 = num2 * 10 + ch - '0'; + ch = readmem(++addr2); + } + if (ch == ' ' || ch == '\r') { + while (ch == ' ') + ch = readmem(++addr2); + if (ch == '\r' && num1 >= 0 && num1 <= 3) + mmb_check_pick(num1, num2); + else + vdfs_error(err_bad_drive_id); + } + else if ((num2 = mmb_parse_find(addr)) >= 0) { + if (num1 >= 0 && num1 <= 3) + mmb_check_pick(num1, num2); + else + vdfs_error(err_bad_drive_id); + } + } + } + else if ((num1 = mmb_parse_find(addr)) >= 0) + mmb_check_pick(0, num1); +} diff --git a/src/mmb.h b/src/mmb.h index 66912aaa..0d6cf085 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -15,6 +15,6 @@ void mmb_load(char *fn); void mmb_eject(void); void mmb_pick(unsigned drive, unsigned side, unsigned disc); void mmb_reset(void); -int mmb_find(const char *name); +void mmb_cmd_din(uint16_t addr); #endif diff --git a/src/vdfs.c b/src/vdfs.c index f7471804..73e4d029 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -572,7 +572,7 @@ static const char err_eof[] = "\xdf" "EOF"; */ -static void adfs_error(const char *err) +void vdfs_error(const char *err) { uint16_t addr = 0x100; int ch; @@ -614,7 +614,7 @@ static void adfs_hosterr(int errnum) default: msg = err_discerr; } - adfs_error(msg); + vdfs_error(msg); } // Populate a VDFS entry from host information. @@ -1376,7 +1376,7 @@ static uint16_t parse_name(vdfs_path *path, uint16_t addr) *ptr++ = ch; ch = readmem(++addr); } - adfs_error(err_badname); + vdfs_error(err_badname); return 0; } @@ -1386,7 +1386,7 @@ static bool check_valid_dir(vdfs_dirlib *dir) if (ent && ent->attribs & ATTR_IS_DIR) return true; log_warn("vdfs: %s directory is not valid", dir->desc); - adfs_error(err_baddir); + vdfs_error(err_baddir); return false; } @@ -1465,7 +1465,7 @@ static vdfs_entry *find_entry_dfs(const vdfs_path *path, vdfs_findres *res, vdfs const char *filename = path->path; log_debug("vdfs: find_entry_dfs, filename=%.*s, dfsdir=%c", len, filename, srchdir); if (!len) { - adfs_error(err_badname); + vdfs_error(err_badname); res->parent = NULL; return NULL; } @@ -1473,7 +1473,7 @@ static vdfs_entry *find_entry_dfs(const vdfs_path *path, vdfs_findres *res, vdfs if (ic == ':') { int drive = filename[1]; if (len < 4 || drive < '0' || drive > '3' || filename[2] != '.') { - adfs_error(err_badname); + vdfs_error(err_badname); res->parent = NULL; return NULL; } @@ -1489,7 +1489,7 @@ static vdfs_entry *find_entry_dfs(const vdfs_path *path, vdfs_findres *res, vdfs } res->dfs_dir = srchdir; if (len > MAX_FILE_NAME) { - adfs_error(err_badname); + vdfs_error(err_badname); res->parent = NULL; return NULL; } @@ -1897,7 +1897,7 @@ static int16_t swr_calc_addr(uint8_t flags, uint32_t *st_ptr, int16_t romid) // Find the nth RAM bank. if ((romid = mem_findswram(banks)) < 0) { - adfs_error(err_no_swr); + vdfs_error(err_no_swr); return -1; } log_debug("vdfs: swr_calc_addr: pseudo addr bank=%02d, start=%04x", romid, start); @@ -1905,12 +1905,12 @@ static int16_t swr_calc_addr(uint8_t flags, uint32_t *st_ptr, int16_t romid) // Absolutre addressing. if (start < 0x8000 || start >= 0xc000) { - adfs_error(err_badaddr); + vdfs_error(err_badaddr); return -1; } if ((romid > 16) | !rom_slots[romid].swram) { - adfs_error(err_no_swr); + vdfs_error(err_no_swr); return -1; } log_debug("vdfs: swr_calc_addr: abs addr bank=%02d, start=%04x", romid, start); @@ -1936,7 +1936,7 @@ static void exec_swr_fs(uint8_t flags, uint16_t fname, int8_t romid, uint32_t st if (ent && ent->attribs & ATTR_EXISTS) { FILE *fp; if (ent->attribs & ATTR_IS_DIR) - adfs_error(err_wont); + vdfs_error(err_wont); else if ((fp = fopen(ent->host_path, "rb"))) { if (fread(rom + romid * 0x4000 + start, len, 1, fp) != 1 && ferror(fp)) log_warn("vdfs: error reading file '%s': %s", ent->host_fn, strerror(errno)); @@ -1946,9 +1946,9 @@ static void exec_swr_fs(uint8_t flags, uint16_t fname, int8_t romid, uint32_t st adfs_hosterr(errno); } } else - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } else - adfs_error(err_too_big); + vdfs_error(err_too_big); } else { // write sideways RAM to file. @@ -1970,9 +1970,9 @@ static void exec_swr_fs(uint8_t flags, uint16_t fname, int8_t romid, uint32_t st } else log_warn("vdfs: unable to create file '%s': %s", ent->host_fn, strerror(errno)); } else - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } else - adfs_error(err_too_big); + vdfs_error(err_too_big); } } } @@ -2169,7 +2169,7 @@ static bool cmd_srload(uint16_t addr) if ((addr = srp_start(addr, &start))) return srp_tail(addr, 0xC0, fnadd, start, 0); } - adfs_error(err_badparms); + vdfs_error(err_badparms); return true; } @@ -2184,7 +2184,7 @@ static bool cmd_srsave(uint16_t addr) return srp_tail(addr, 0x40, fnadd, start, len); } } - adfs_error(err_badparms); + vdfs_error(err_badparms); return true; } @@ -2209,7 +2209,7 @@ static void srcopy(uint16_t addr, uint8_t flags) } } } - adfs_error(err_badparms); + vdfs_error(err_badparms); } /* @@ -2222,7 +2222,7 @@ static bool no_wildcards(const vdfs_path *path) for (int len = path->len; len; --len) { int ch = *ptr++; if (ch == '*' || ch == '#') { - adfs_error(err_wildcard); + vdfs_error(err_wildcard); return false; } } @@ -2381,24 +2381,24 @@ static void osfile_write(uint32_t pb, const vdfs_path *path, uint32_t (*callback if (ent) { if (ent->attribs & (ATTR_OPEN_READ|ATTR_OPEN_WRITE)) { log_debug("vdfs: attempt to save file %.*s which is already open via OSFIND", res.acorn_len, res.acorn_fn); - adfs_error(err_isopen); + vdfs_error(err_isopen); return; } if (ent->attribs & ATTR_EXISTS) { if (ent->attribs & ATTR_IS_DIR) { log_debug("vdfs: attempt to create file %.*s over an existing dir", res.acorn_len, res.acorn_fn); - adfs_error(err_direxist); + vdfs_error(err_direxist); return; } } } else if (!res.parent) { log_debug("vdfs: osfile_write, no parent into which to create new file"); - adfs_error(res.errmsg); + vdfs_error(res.errmsg); return; } else if (!(ent = add_new_file(&res))) { - adfs_error(err_nomem); + vdfs_error(err_nomem); return; } if ((fp = fopen(ent->host_path, "wb"))) { @@ -2616,9 +2616,9 @@ static void delete_file(vdfs_entry *ent) show_activity(); if (ent->attribs & ATTR_IS_DIR) { if (ent == cur_dir.dir) - adfs_error(err_delcsd); + vdfs_error(err_delcsd); else if (ent == lib_dir.dir) - adfs_error(err_dellib); + vdfs_error(err_dellib); else if (rmdir(ent->host_path) == 0) { if (ent == prev_dir.dir) prev_dir = cur_dir; @@ -2679,7 +2679,7 @@ static void osfile_cdir(const vdfs_path *path) if (ent->attribs & ATTR_EXISTS) { if (!(ent->attribs & ATTR_IS_DIR)) { log_debug("vdfs: attempt to create dir %.*s on top of an existing file", res.acorn_len, res.acorn_fn); - adfs_error(err_filexist); // file in the way. + vdfs_error(err_filexist); // file in the way. } } else create_dir(ent); @@ -2693,7 +2693,7 @@ static void osfile_cdir(const vdfs_path *path) } } else { log_debug("vdfs: attempt to create dir %.*s in non-existent directory", res.acorn_len, res.acorn_fn); - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } } } @@ -2752,7 +2752,7 @@ static void osfile_load(uint32_t pb, const vdfs_path *path) vdfs_entry *ent = find_entry(path, &res, &cur_dir); if (ent && ent->attribs & ATTR_EXISTS) { if (ent->attribs & ATTR_IS_DIR) - adfs_error(err_wont); + vdfs_error(err_wont); else { FILE *fp = fopen(ent->host_path, "rb"); if (fp) { @@ -2779,7 +2779,7 @@ static void osfile_load(uint32_t pb, const vdfs_path *path) } } } else - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } static void osfile(void) @@ -2851,7 +2851,7 @@ static vdfs_open_file *get_open_read(int channel) log_debug("vdfs: attempt to use closed channel %d", channel); } else log_debug("vdfs: channel %d out of range", channel); - adfs_error(err_channel); + vdfs_error(err_channel); return NULL; } @@ -2886,21 +2886,21 @@ static vdfs_open_file *get_open_write(int channel) if (cp->fp) return cp; log_debug("vdfs: attempt to use write to channel %d not open for write", channel); - adfs_error(err_channel); + vdfs_error(err_channel); } else { log_debug("vdfs: attempt to write to a read-only channel %d", channel); - adfs_error(err_nupdate); + vdfs_error(err_nupdate); } } else { log_debug("vdfs: attempt to use closed channel %d", channel); - adfs_error(err_channel); + vdfs_error(err_channel); } } else { log_debug("vdfs: channel %d out of range\n", channel); - adfs_error(err_channel); + vdfs_error(err_channel); } return NULL; } @@ -2939,7 +2939,7 @@ static void osfind(void) if (channel >= 0 && channel < NUM_CHANNELS) close_file(channel); else - adfs_error(err_channel); + vdfs_error(err_channel); } } else if (check_valid_dir(&cur_dir)) { // open file. @@ -2950,7 +2950,7 @@ static void osfind(void) do { if (++channel >= NUM_CHANNELS) { log_debug("vdfs: no free channel"); - adfs_error(err_nfile); + vdfs_error(err_nfile); return; } } while (vdfs_chan[channel].ent); @@ -2964,13 +2964,13 @@ static void osfind(void) } } else if (!res.parent) { - adfs_error(res.errmsg); + vdfs_error(res.errmsg); return; } if (acorn_mode == 0x40) { if (ent && ent->attribs & ATTR_EXISTS) { if (ent->attribs & ATTR_OPEN_WRITE) - adfs_error(err_isopen); + vdfs_error(err_isopen); else { mode = "rb"; attribs = ATTR_OPEN_READ; @@ -2981,7 +2981,7 @@ static void osfind(void) if (!no_wildcards(&path)) return; if (ent && (ent->attribs & ATTR_EXISTS) && (ent->attribs & (ATTR_OPEN_READ|ATTR_OPEN_WRITE))) - adfs_error(err_isopen); + vdfs_error(err_isopen); else { mode = "wb"; attribs = ATTR_OPEN_WRITE; @@ -2993,7 +2993,7 @@ static void osfind(void) attribs = ATTR_OPEN_READ|ATTR_OPEN_WRITE; if (ent && ent->attribs & ATTR_EXISTS) { if (ent->attribs & (ATTR_OPEN_READ|ATTR_OPEN_WRITE)) - adfs_error(err_isopen); + vdfs_error(err_isopen); else mode = "rb+"; } @@ -3348,7 +3348,7 @@ static void osargs_set_ptr(vdfs_open_file *cp) putc(0, fp); } else - adfs_error(err_nupdate); + vdfs_error(err_nupdate); } else fseek(fp, new_seq, SEEK_SET); @@ -3383,7 +3383,7 @@ static void osargs_set_ext(vdfs_open_file *cp) fseek(fp, seq_ptr, SEEK_SET); } else - adfs_error(err_nupdate); + vdfs_error(err_nupdate); } static void osargs(void) @@ -3460,7 +3460,7 @@ static uint_least16_t cmd_access_parse(uint16_t addr, int ch) else if (ch == 'T' || ch == 't') attribs |= ATTR_NL_TRANS; else { - adfs_error(err_badparms); + vdfs_error(err_badparms); return ATTR_BAD_CHAR; } ch = readmem(addr++); @@ -3478,7 +3478,7 @@ static uint_least16_t cmd_access_parse(uint16_t addr, int ch) else if (ch == 'E' || ch == 'e') attribs |= ATTR_OTHR_EXEC; else { - adfs_error(err_badparms); + vdfs_error(err_badparms); return ATTR_BAD_CHAR; } ch = readmem(addr++); @@ -3724,22 +3724,22 @@ static void cmd_copy(uint16_t addr) else { /* destination is a file */ if (find_next(old_ent, &old_res)) - adfs_error(err_wildcard); + vdfs_error(err_wildcard); else copy_file(old_ent, new_ent); } } else if (find_next(old_ent, &old_res)) - adfs_error(err_wildcard); + vdfs_error(err_wildcard); else if ((new_ent = add_new_file(&new_res)) && copy_file(old_ent, new_ent)) new_ent->attribs |= ATTR_EXISTS; } else - adfs_error(old_res.errmsg); + vdfs_error(old_res.errmsg); } else { log_debug("vdfs: copy attempted with an empty filename"); - adfs_error(err_badcopy); + vdfs_error(err_badcopy); } } } @@ -3759,7 +3759,7 @@ static void cmd_delete(uint16_t addr) delete_file(ent); return; } - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } } } @@ -3776,9 +3776,9 @@ static vdfs_entry *lookup_dir(uint16_t addr) if (ent->attribs & ATTR_IS_DIR) return ent; else - adfs_error(err_notdir); + vdfs_error(err_notdir); } else - adfs_error(res.errmsg); + vdfs_error(res.errmsg); } } return NULL; @@ -3791,7 +3791,7 @@ static vdfs_entry *parse_adfs_dir(uint16_t addr, int *drive) ch = readmem(++addr); if (ch < '0' || ch > '7') { log_debug("vdfs: parse_adfs_dir, bad drive number"); - adfs_error(err_badparms); + vdfs_error(err_badparms); return NULL; } *drive = ch - '0'; @@ -3800,7 +3800,7 @@ static vdfs_entry *parse_adfs_dir(uint16_t addr, int *drive) if (ch == '\r') return &root_dir; log_debug("vdfs: parse_adfs_dir, missing dot"); - adfs_error(err_badparms); + vdfs_error(err_badparms); return NULL; } ++addr; @@ -3836,7 +3836,7 @@ static void parse_dfs_dir(uint16_t addr, vdfs_dirlib *dir) if (ch == ':') { ch = readmem(addr++); if (ch < '0' || ch > '3') { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } drive = ch - '0'; @@ -3849,7 +3849,7 @@ static void parse_dfs_dir(uint16_t addr, vdfs_dirlib *dir) if (ch == '\r') dir->drive = drive; else - adfs_error(err_baddir); + vdfs_error(err_baddir); return; } } @@ -3863,7 +3863,7 @@ static void parse_dfs_dir(uint16_t addr, vdfs_dirlib *dir) return; } } - adfs_error(err_baddir); + vdfs_error(err_baddir); } static void cmd_dir_dfs(uint16_t addr) @@ -3882,7 +3882,7 @@ static void cmd_drive(uint16_t addr) if (ch >= '0' && (ch <= '3' || (ch <= '7' && !(fs_flags & DFS_MODE)))) cur_dir.drive = ch - '0'; else - adfs_error(err_badparms); + vdfs_error(err_badparms); } static uint16_t cmd_pwd_recurse(uint16_t addr, vdfs_entry *ent) @@ -3952,7 +3952,7 @@ static void run_file(const char *err) ent = find_entry(&path, &res, &lib_dir); if (ent && ent->attribs & ATTR_EXISTS) { if (ent->attribs & ATTR_IS_DIR) - adfs_error(err_wont); + vdfs_error(err_wont); else { FILE *fp = fopen(ent->host_path, "rb"); if (fp) { @@ -3976,7 +3976,7 @@ static void run_file(const char *err) } } else - adfs_error(err); + vdfs_error(err); } } } @@ -4029,7 +4029,7 @@ static void rename_file(uint16_t addr) rename_tail(old_ent, new_ent); } else { log_debug("vdfs: new file '%.*s' for rename already exists", new_res.acorn_len, new_res.acorn_fn); - adfs_error(err_exists); + vdfs_error(err_exists); } } else rename_tail(old_ent, new_ent); @@ -4038,11 +4038,11 @@ static void rename_file(uint16_t addr) rename_tail(old_ent, new_ent); } else { log_debug("vdfs: old file '%.*s' for rename not found", old_res.acorn_len, old_res.acorn_fn); - adfs_error(old_res.errmsg); + vdfs_error(old_res.errmsg); } } else { log_debug("vdfs: rename attempted with an empty filename"); - adfs_error(err_badren); + vdfs_error(err_badren); } } } @@ -4162,7 +4162,7 @@ static void fsclaim(uint16_t addr) rom_dispatch(VDFS_ROM_FSCLAIM); return; } - adfs_error(err_badparms); + vdfs_error(err_badparms); } /* @@ -4188,11 +4188,11 @@ static bool cat_prep_adfs(uint16_t addr, vdfs_dirlib *dir) if (ent->attribs & ATTR_IS_DIR) { cat_dir = ent; } else { - adfs_error(err_notdir); + vdfs_error(err_notdir); return false; } } else { - adfs_error(res.errmsg); + vdfs_error(res.errmsg); return false; } } @@ -4326,7 +4326,7 @@ static void file_info(uint16_t addr) rom_dispatch(VDFS_ROM_INFO); return; } - adfs_error(info_res.errmsg); + vdfs_error(info_res.errmsg); } } } @@ -4471,7 +4471,7 @@ static void cmd_osw7f(uint16_t addr) osw7fmc_tab = osw7fmc_tabs[ent->act - VDFS_ACT_OSW7F_NONE - 1]; } else - adfs_error(err_badcmd); + vdfs_error(err_badcmd); } } @@ -4520,7 +4520,7 @@ static void cmd_vdfs(uint16_t addr) else if (ch == 'D' || ch == 'd') vdfs_dfs_mode(); else if (ch != '\r') { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } if (!(fs_flags & VDFS_ACTIVE)) { @@ -4529,99 +4529,11 @@ static void cmd_vdfs(uint16_t addr) } } -static int mmb_parse_find(uint16_t addr) -{ - char name[17]; - int ch = readmem(addr++); - int i = 0; - bool quote = false; - - if (ch == '"') { - quote = true; - ch = readmem(addr++); - } - while (ch != '\r' && i < sizeof(name) && ((quote && ch != '"') || (!quote && ch != ' '))) { - name[i++] = ch; - ch = readmem(addr++); - } - name[i] = 0; - if ((i = mmb_find(name)) < 0) - adfs_error(err_discerr); - return i; -} - -static bool mmb_check_pick(unsigned drive, unsigned disc) -{ - if (disc >= mmb_ndisc) { - adfs_error(err_notfound); - return false; - } - unsigned side; - switch(drive) { - case 0: - case 1: - side = 0; - break; - case 2: - case 3: - drive &= 1; - disc--; - side = 1; - break; - default: - log_debug("vdfs: mmb_check_pick: invalid logical drive %d", drive); - adfs_error(err_badparms); - return false; - } - mmb_pick(drive, side, disc); - return true; -} - -static void cmd_mmb_din(uint16_t addr) -{ - int num1 = 0, num2 = 0; - uint16_t addr2 = addr; - int ch = readmem(addr2); - while (ch >= '0' && ch <= '9') { - num1 = num1 * 10 + ch - '0'; - ch = readmem(++addr2); - } - if (ch == ' ' || ch == '\r') { - while (ch == ' ') - ch = readmem(++addr2); - if (ch == '\r') - mmb_check_pick(0, num1); - else { - addr = addr2; - while (ch >= '0' && ch <= '9') { - num2 = num2 * 10 + ch - '0'; - ch = readmem(++addr2); - } - if (ch == ' ' || ch == '\r') { - while (ch == ' ') - ch = readmem(++addr2); - if (ch == '\r' && num1 >= 0 && num1 <= 3) - mmb_check_pick(num1, num2); - else - adfs_error(err_badparms); - } - else if ((num2 = mmb_parse_find(addr)) >= 0) { - if (num1 >= 0 && num1 <= 3) - mmb_check_pick(num1, num2); - else - adfs_error(err_badparms); - } - } - } - else if ((num1 = mmb_parse_find(addr)) >= 0) - mmb_check_pick(0, num1); -} - static void needs_filename(enum vdfs_action act, uint16_t addr) { int ch = readmem(addr); if (ch == '\r') { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } x = addr & 0xff; @@ -4633,7 +4545,7 @@ static void cmd_dump(uint16_t addr) { int ch = readmem(addr); if (ch == '\r') { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } x = addr & 0xff; @@ -4651,7 +4563,7 @@ static void cmd_dump(uint16_t addr) do { ch = hex2nyb(ch); if (ch == -1) { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } start = start << 4 | ch; @@ -4668,7 +4580,7 @@ static void cmd_dump(uint16_t addr) do { ch = hex2nyb(ch); if (ch == -1) { - adfs_error(err_badparms); + vdfs_error(err_badparms); return; } offset = offset << 4 | ch; @@ -4733,7 +4645,7 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) break; case VDFS_ACT_INFO: if (readmem(addr) == '\r') - adfs_error(err_badcmd); + vdfs_error(err_badcmd); else file_info(addr); break; @@ -4781,7 +4693,7 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) cmd_osw7f(addr); break; case VDFS_ACT_MMBDIN: - cmd_mmb_din(addr); + mmb_cmd_din(addr); break; case VDFS_ACT_DRIVE: cmd_drive(addr); diff --git a/src/vdfs.h b/src/vdfs.h index 6258aed0..69f98bd2 100644 --- a/src/vdfs.h +++ b/src/vdfs.h @@ -14,6 +14,8 @@ extern void vdfs_set_root(const char *dir); extern void vdfs_loadstate(FILE *f); extern void vdfs_savestate(FILE *f); +extern void vdfs_error(const char *msg); + extern const char *vdfs_cfg_root; #endif From 7e127072a5e101cf2af3b1958e826d15edeb3f15 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 15:11:08 +0000 Subject: [PATCH 05/35] vdfs: rename adfs_hosterr to vdfs_hosterr for consistency. --- src/vdfs.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/vdfs.c b/src/vdfs.c index 73e4d029..c00ce144 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -585,7 +585,7 @@ void vdfs_error(const char *err) pc = 0x100; // jump to BRK sequence just created. } -static void adfs_hosterr(int errnum) +static void vdfs_hosterr(int errnum) { const char *msg; @@ -1943,7 +1943,7 @@ static void exec_swr_fs(uint8_t flags, uint16_t fname, int8_t romid, uint32_t st fclose(fp); } else { log_warn("vdfs: unable to load file '%s': %s", ent->host_fn, strerror(errno)); - adfs_hosterr(errno); + vdfs_hosterr(errno); } } else vdfs_error(res.errmsg); @@ -2422,7 +2422,7 @@ static void osfile_write(uint32_t pb, const vdfs_path *path, uint32_t (*callback else { int err = errno; log_warn("vdfs: unable to create file '%s': %s", ent->host_fn, strerror(err)); - adfs_hosterr(err); + vdfs_hosterr(err); } } } @@ -2626,14 +2626,14 @@ static void delete_file(vdfs_entry *ent) delete_inf(ent); a = 2; } else - adfs_hosterr(errno); + vdfs_hosterr(errno); } else { if (unlink(ent->host_path) == 0) { ent->attribs &= ~ATTR_EXISTS; delete_inf(ent); a = 1; } else - adfs_hosterr(errno); + vdfs_hosterr(errno); } } @@ -2665,7 +2665,7 @@ static void create_dir(vdfs_entry *ent) a = 2; } else { - adfs_hosterr(errno); + vdfs_hosterr(errno); log_debug("vdfs: unable to mkdir '%s': %s", ent->host_path, strerror(errno)); } } @@ -2775,7 +2775,7 @@ static void osfile_load(uint32_t pb, const vdfs_path *path) } } else { log_warn("vdfs: unable to load file '%s': %s", ent->host_fn, strerror(errno)); - adfs_hosterr(errno); + vdfs_hosterr(errno); } } } else @@ -3572,7 +3572,7 @@ static bool copy_file(vdfs_entry *old_ent, vdfs_entry *new_ent) { BOOL res = CopyFile(old_ent->host_path, new_ent->host_path, FALSE); if (!res) - adfs_hosterr(errno); + vdfs_hosterr(errno); return res; } @@ -3586,14 +3586,14 @@ static bool copy_loop(const char *old_fn, int old_fd, const char *new_fn, int ne while (bytes > 0) { if (write(new_fd, buf, bytes) != bytes) { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: error writing %s: %s", new_fn, strerror(err)); return false; } } if (bytes < 0) { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: error reading %s: %s", old_fn, strerror(err)); return false; } @@ -3617,13 +3617,13 @@ static bool copy_file(vdfs_entry *old_ent, vdfs_entry *new_ent) res = copy_loop(old_ent->host_path, old_fd, new_ent->host_path, new_fd); else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: copy_file_range failed %s to %s: %s", old_ent->host_path, new_ent->host_path, strerror(err)); } } else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: unable to fstat '%s': %s", old_ent->host_path, strerror(err)); } #else @@ -3633,14 +3633,14 @@ static bool copy_file(vdfs_entry *old_ent, vdfs_entry *new_ent) } else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: unable to open %s for writing: %s", new_ent->host_path, strerror(err)); } close(old_fd); } else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: unable to open %s for reading: %s", old_ent->host_path, strerror(err)); } return res; @@ -3661,33 +3661,33 @@ static bool copy_file(vdfs_entry *old_ent, vdfs_entry *new_ent) ch = getc(old_fp); if (ferror(old_fp)) { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: read error on %s: %s", old_ent->host_path, strerror(err)); res = false; } if (ferror(new_fp)) { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: write error on %s: %s", new_ent->host_path, strerror(err)); res = false; } if (fclose(new_fp)) { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: write error on %s: %s", new_ent->host_path, strerror(err)); res = false; } } else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: unable to open %s for writing: %s", new_ent->host_path, strerror(err)); } fclose(old_fp); } else { int err = errno; - adfs_hosterr(err); + vdfs_hosterr(err); log_warn("vdfs: unable to open %s for reading: %s", old_ent->host_path, strerror(err)); } return res; @@ -3971,7 +3971,7 @@ static void run_file(const char *err) fclose(fp); } else { log_warn("vdfs: unable to run file '%s': %s", ent->host_path, strerror(errno)); - adfs_hosterr(errno); + vdfs_hosterr(errno); } } } @@ -4004,7 +4004,7 @@ static void rename_tail(vdfs_entry *old_ent, vdfs_entry *new_ent) delete_inf(old_ent); write_back(new_ent); } else { - adfs_hosterr(errno); + vdfs_hosterr(errno); log_debug("vdfs: failed to rename '%s' to '%s': %s", old_ent->host_path, new_ent->host_path, strerror(errno)); } } From d5c8726aa7824c62213b52c61dacbe204c81797d Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 15:54:43 +0000 Subject: [PATCH 06/35] mmb/vdfs: DABOUT command and generalisation of split_print. This generalises the abilty to put data into the sideways ROM bank that VDFS is in, after the VDFS code, for printing via OSWRCH so it can be used in other modules, updates the PWD command to use this, then uses it to implement the DABOUT MMB command. --- src/mmb.c | 8 ++++++++ src/mmb.h | 2 ++ src/vdfs.c | 50 ++++++++++++++++++++++++++++++++------------------ src/vdfs.h | 2 ++ 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 0029778e..41d0c965 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -299,3 +299,11 @@ void mmb_cmd_din(uint16_t addr) else if ((num1 = mmb_parse_find(addr)) >= 0) mmb_check_pick(0, num1); } + +static const char mmb_about_str[] = "B-Em internal MMB\r\n"; + +void mmb_cmd_dabout(void) +{ + memcpy(vdfs_split_addr(), mmb_about_str, sizeof(mmb_about_str)); + vdfs_split_go(0); +} diff --git a/src/mmb.h b/src/mmb.h index 0d6cf085..45d672bb 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -15,6 +15,8 @@ void mmb_load(char *fn); void mmb_eject(void); void mmb_pick(unsigned drive, unsigned side, unsigned disc); void mmb_reset(void); + +void mmb_cmd_dabout(void); void mmb_cmd_din(uint16_t addr); #endif diff --git a/src/vdfs.c b/src/vdfs.c index c00ce144..656fc4e6 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -280,6 +280,7 @@ enum vdfs_action { VDFS_ACT_OSW7F_AC2, VDFS_ACT_OSW7F_WATF, VDFS_ACT_OSW7F_WAT5, + VDFS_ACT_MMBDABT, VDFS_ACT_MMBDIN, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, @@ -3885,31 +3886,41 @@ static void cmd_drive(uint16_t addr) vdfs_error(err_badparms); } -static uint16_t cmd_pwd_recurse(uint16_t addr, vdfs_entry *ent) +uint8_t *vdfs_split_addr(void) +{ + unsigned romno = readmem(0xf4); + unsigned page = rom_slots[romno & 0x0f].split; + writemem(0xa8, 0); + writemem(0xa9, page); + return rom + (romno * ROM_SIZE) + ((page - 0x80) << 8); +} + +void vdfs_split_go(unsigned after) +{ + x = after; + rom_dispatch(VDFS_ROM_PRINT_SPLIT); +} + +static uint8_t *cmd_pwd_recurse(uint8_t *dptr, vdfs_entry *ent) { vdfs_entry *parent = ent->parent; if (parent && parent != ent) - addr = cmd_pwd_recurse(addr, parent); - const char *ptr = ent->acorn_fn; - for (int len = ent->acorn_len; len; --len) - writemem(addr++, *ptr++); - writemem(addr++, '.'); - return addr; + dptr = cmd_pwd_recurse(dptr, parent); + unsigned len = ent->acorn_len; + memcpy(dptr, ent->acorn_fn, len); + dptr+= len; + *dptr++ = '.'; + return dptr; } static void cmd_pwd(void) { if (check_valid_dir(&cur_dir)) { - int romno = readmem(0xf4); - uint16_t addr = (rom_slots[romno & 0x0f].split) << 8; - log_debug("vdfs: cmd_pwd, addr=%04X\n", addr); - writemem16(0xa8, addr); - addr = cmd_pwd_recurse(addr, cur_dir.dir); - writemem(addr-1, 0x0d); - writemem(addr, 0x0a); - writemem(addr+1, 0); - x = 0; - rom_dispatch(VDFS_ROM_PRINT_SPLIT); + uint8_t *ptr = cmd_pwd_recurse(vdfs_split_addr(), cur_dir.dir); + ptr[-1] = 0x0d; + ptr[0] = 0x0a; + ptr[1] = 0x00; + vdfs_split_go(0); } } @@ -4692,6 +4703,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_OSW7F: cmd_osw7f(addr); break; + case VDFS_ACT_MMBDABT: + mmb_cmd_dabout(); + break; case VDFS_ACT_MMBDIN: mmb_cmd_din(addr); break; @@ -4946,7 +4960,7 @@ static const struct cmdent ctab_always[] = { }; static const struct cmdent ctab_mmb[] = { - { "DAbout", VDFS_ACT_NOP }, + { "DAbout", VDFS_ACT_MMBDABT }, { "Din", VDFS_ACT_MMBDIN } }; diff --git a/src/vdfs.h b/src/vdfs.h index 69f98bd2..07e71d0d 100644 --- a/src/vdfs.h +++ b/src/vdfs.h @@ -15,6 +15,8 @@ extern void vdfs_loadstate(FILE *f); extern void vdfs_savestate(FILE *f); extern void vdfs_error(const char *msg); +extern uint8_t *vdfs_split_addr(void); +extern void vdfs_split_go(unsigned after); extern const char *vdfs_cfg_root; From 4b84d6b6c28da6f053a4eef841ec912051702fe3 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 17:07:19 +0000 Subject: [PATCH 07/35] mmb: add a very basic DCAT command (no filtering). --- src/mmb.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/mmb.h | 2 ++ src/vdfs.c | 8 +++++++- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index 41d0c965..f3ceb428 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -30,6 +30,8 @@ static unsigned mmb_cat_size; static char *mmb_cat; unsigned mmb_ndisc; char *mmb_fn; +static int mmb_dcat_posn; +static int mmb_dcat_count; static void mmb_read_error(const char *fn, FILE *fp) { @@ -307,3 +309,50 @@ void mmb_cmd_dabout(void) memcpy(vdfs_split_addr(), mmb_about_str, sizeof(mmb_about_str)); vdfs_split_go(0); } + +void mmb_cmd_dcat_cont(void) +{ + if (readmem(0xff) & 0x80) + vdfs_error("\x17" "Escape"); + else { + uint8_t *dest = vdfs_split_addr(); + const char *cat_ptr = mmb_cat + mmb_dcat_posn * 16; + const char *cat_end = mmb_cat + mmb_cat_size; + while (cat_ptr < cat_end) { + if (*cat_ptr) { + ++mmb_dcat_count; + dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); + for (int i = 0; i < 12; ++i) { + int ch = cat_ptr[i] & 0x7f; + if (ch < ' ' || ch > 0x7e) + ch = ' '; + *dest++ = ch; + } + *dest++ = ' '; + int flag = cat_ptr[15]; + if (flag == 0xf0) + flag = 'U'; + else if (flag == 0) + flag = 'P'; + else + flag = ' '; + *dest++ = flag; + *dest = 0; + vdfs_split_go(0x16); + return; + } + cat_ptr += MMB_NAME_SIZE; + ++mmb_dcat_posn; + } + snprintf((char *)dest, 20, "\r\n%d disks found\r\n", mmb_dcat_count); + vdfs_split_go(0); + } +} + +void mmb_cmd_dcat_start(uint16_t addr) +{ + log_debug("mmb: begin dcat, mmb_cat_size=%d", mmb_cat_size); + mmb_dcat_count = 0; + mmb_dcat_posn = 0; + mmb_cmd_dcat_cont(); +} diff --git a/src/mmb.h b/src/mmb.h index 45d672bb..3e30eee2 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -18,5 +18,7 @@ void mmb_reset(void); void mmb_cmd_dabout(void); void mmb_cmd_din(uint16_t addr); +void mmb_cmd_dcat_start(uint16_t addr); +void mmb_cmd_dcat_cont(void); #endif diff --git a/src/vdfs.c b/src/vdfs.c index 656fc4e6..1bc789ee 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -282,6 +282,7 @@ enum vdfs_action { VDFS_ACT_OSW7F_WAT5, VDFS_ACT_MMBDABT, VDFS_ACT_MMBDIN, + VDFS_ACT_MMBDCAT, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, VDFS_ACT_COPY, @@ -4709,6 +4710,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDIN: mmb_cmd_din(addr); break; + case VDFS_ACT_MMBDCAT: + mmb_cmd_dcat_start(addr); + break; case VDFS_ACT_DRIVE: cmd_drive(addr); break; @@ -4961,7 +4965,8 @@ static const struct cmdent ctab_always[] = { static const struct cmdent ctab_mmb[] = { { "DAbout", VDFS_ACT_MMBDABT }, - { "Din", VDFS_ACT_MMBDIN } + { "Din", VDFS_ACT_MMBDIN }, + { "DCat", VDFS_ACT_MMBDCAT } }; static const struct cmdent ctab_enabled[] = { @@ -5149,6 +5154,7 @@ static inline void dispatch(uint8_t value) case 0x13: rest_ram(); break; case 0x14: info_next(); break; case 0x15: log_time(); break; + case 0x16: mmb_cmd_dcat_cont(); break; default: log_warn("vdfs: function code %d not recognised", value); } } From 7332936bcd68aa9fde0bbbc7d5a4269d90f612b8 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 18:35:58 +0000 Subject: [PATCH 08/35] mmb: add the correct filtering options to the DCAT command. --- src/mmb.c | 81 +++++++++++++++++++++++++++++++++++++++++++++--------- src/vdfs.c | 2 +- src/vdfs.h | 1 + 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index f3ceb428..29912d65 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -19,19 +19,23 @@ #include "vdfs.h" #define MMB_DISC_SIZE (200*1024) -#define MMB_NAME_SIZE 16 +#define MMB_ENTRY_SIZE 16 #define MMB_ZONE_DISCS 511 -#define MMB_ZONE_CAT_SIZE (MMB_ZONE_DISCS*MMB_NAME_SIZE) -#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_NAME_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) -#define MMB_ZONE_SKIP_SIZE (MMB_ZONE_DISCS*MMB_DISC_SIZE+MMB_NAME_SIZE) +#define MMB_ZONE_CAT_SIZE (MMB_ZONE_DISCS*MMB_ENTRY_SIZE) +#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_ENTRY_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) +#define MMB_ZONE_SKIP_SIZE (MMB_ZONE_DISCS*MMB_DISC_SIZE+MMB_ENTRY_SIZE) +#define MMB_NAME_SIZE 12 static unsigned mmb_boot_discs[4]; static unsigned mmb_cat_size; static char *mmb_cat; unsigned mmb_ndisc; char *mmb_fn; -static int mmb_dcat_posn; -static int mmb_dcat_count; +static unsigned mmb_dcat_posn; +static unsigned mmb_dcat_end; +static unsigned mmb_dcat_count; +static unsigned mmb_dcat_pat_len; +static char mmb_dcat_pattern[MMB_NAME_SIZE]; static void mmb_read_error(const char *fn, FILE *fp) { @@ -46,7 +50,7 @@ static unsigned mmb_calc_offset(unsigned disc) { unsigned zone_start = disc / MMB_ZONE_DISCS; unsigned zone_index = disc % MMB_ZONE_DISCS; - unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + MMB_NAME_SIZE + zone_index * MMB_DISC_SIZE; + unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + MMB_ENTRY_SIZE + zone_index * MMB_DISC_SIZE; log_debug("mmb: mmb_calc_offset(%u) -> zone_start=%u, zone_index=%u, offset=%u", disc, zone_start, zone_index, offset); return offset; } @@ -317,12 +321,11 @@ void mmb_cmd_dcat_cont(void) else { uint8_t *dest = vdfs_split_addr(); const char *cat_ptr = mmb_cat + mmb_dcat_posn * 16; - const char *cat_end = mmb_cat + mmb_cat_size; - while (cat_ptr < cat_end) { - if (*cat_ptr) { + while (mmb_dcat_posn < mmb_dcat_end) { + if (*cat_ptr && vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, cat_ptr, MMB_NAME_SIZE)) { ++mmb_dcat_count; dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); - for (int i = 0; i < 12; ++i) { + for (int i = 0; i < MMB_NAME_SIZE; ++i) { int ch = cat_ptr[i] & 0x7f; if (ch < ' ' || ch > 0x7e) ch = ' '; @@ -341,7 +344,7 @@ void mmb_cmd_dcat_cont(void) vdfs_split_go(0x16); return; } - cat_ptr += MMB_NAME_SIZE; + cat_ptr += MMB_ENTRY_SIZE; ++mmb_dcat_posn; } snprintf((char *)dest, 20, "\r\n%d disks found\r\n", mmb_dcat_count); @@ -351,8 +354,60 @@ void mmb_cmd_dcat_cont(void) void mmb_cmd_dcat_start(uint16_t addr) { - log_debug("mmb: begin dcat, mmb_cat_size=%d", mmb_cat_size); + /* Defaults for an unfiltered list */ mmb_dcat_count = 0; mmb_dcat_posn = 0; + mmb_dcat_end = mmb_cat_size / MMB_ENTRY_SIZE; + mmb_dcat_pattern[0] = '*'; + mmb_dcat_pat_len = 1; + + int ch = readmem(addr++); + while (ch == ' ' || ch == '\t') + ch = readmem(addr++); + if (ch != '\r') { + unsigned value1 = 0; + uint16_t addr2 = addr; + while (ch >= '0' && ch <= '9') { + value1 = (value1 * 10) + (ch - '0'); + ch = readmem(addr2++); + } + if (ch == ' ' || ch == '\t' || ch == '\r') { + log_debug("mmb: mmb_cmd_dcat_start, found 1st number=%u", value1); + unsigned max_value = mmb_dcat_end; + if (value1 > max_value) + value1 = max_value; + mmb_dcat_end = value1; + while (ch == ' ' || ch == '\t') + ch = readmem(addr2++); + addr = addr2; + if (ch != '\r') { + unsigned value2 = 0; + while (ch >= '0' && ch <= '9') { + value2 = (value2 * 10) + (ch - '0'); + ch = readmem(addr2++); + } + if (ch == ' ' || ch == '\t' || ch == '\r') { + log_debug("mmb: mmb_cmd_dcat_start, found 2nd number=%u", value2); + if (value2 > max_value) + value2 = max_value; + mmb_dcat_posn = value1; + mmb_dcat_end = value2; + while (ch == ' ' || ch == '\t') + ch = readmem(addr2++); + addr = addr2; + } + } + } + if (ch != '\r') { + log_debug("mmb: mmb_cmd_dcat_start, pattern found"); + unsigned pat_ix = 0; + do { + mmb_dcat_pattern[pat_ix++] = ch; + ch = readmem(addr++); + } while (pat_ix < MMB_NAME_SIZE && ch != ' ' && ch != '\t' && ch != '\r'); + mmb_dcat_pat_len = pat_ix; + log_debug("mmb: mmb_cmd_dcat_start, pattern=%.*s", pat_ix, mmb_dcat_pattern); + } + } mmb_cmd_dcat_cont(); } diff --git a/src/vdfs.c b/src/vdfs.c index 1bc789ee..f33a9ad8 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -1144,7 +1144,7 @@ static vdfs_entry *acorn_search(vdfs_entry *dir, vdfs_entry *obj) return NULL; } -static bool vdfs_wildmat(const char *pattern, unsigned pat_len, const char *candidate, unsigned can_len) +bool vdfs_wildmat(const char *pattern, unsigned pat_len, const char *candidate, unsigned can_len) { log_debug("vdfs: vdfs_wildmat, pattern=%.*s, candidate=%.*s", pat_len, pattern, can_len, candidate); while (pat_len) { diff --git a/src/vdfs.h b/src/vdfs.h index 07e71d0d..a0ce3613 100644 --- a/src/vdfs.h +++ b/src/vdfs.h @@ -15,6 +15,7 @@ extern void vdfs_loadstate(FILE *f); extern void vdfs_savestate(FILE *f); extern void vdfs_error(const char *msg); +extern bool vdfs_wildmat(const char *pattern, unsigned pat_len, const char *candidate, unsigned can_len); extern uint8_t *vdfs_split_addr(void); extern void vdfs_split_go(unsigned after); From d964187b5362d460ff266d09ab2532d568821825 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 18:37:53 +0000 Subject: [PATCH 09/35] mmb: use mmb prefix on function names consistently. --- src/mmb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 29912d65..cae0d494 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -152,7 +152,7 @@ void mmb_eject(void) mmb_ndisc = 0; } -static void reset_one(int drive) +static void mmb_reset_one(int drive) { if (sdf_fp[drive] == mmb_fp) { mmb_offset[drive][0] = mmb_calc_offset(0); @@ -163,8 +163,8 @@ static void reset_one(int drive) void mmb_reset(void) { if (mmb_fp) { - reset_one(0); - reset_one(1); + mmb_reset_one(0); + mmb_reset_one(1); } } @@ -181,7 +181,7 @@ void mmb_pick(unsigned drive, unsigned side, unsigned disc) fdc_spindown(); } -static inline int cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const char *cat_nxt) +static inline int mmb_cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const char *cat_nxt) { do { char cat_ch = *cat_ptr++; @@ -205,7 +205,7 @@ static int mmb_find(const char *name) do { const char *cat_nxt = cat_ptr + 16; - int i = cat_name_cmp(name, cat_ptr, cat_nxt); + int i = mmb_cat_name_cmp(name, cat_ptr, cat_nxt); if (i >= 0) { log_debug("mmb: found MMB SSD '%s' at %d", name, i); return i; From 91dc50675447624af0c7f0146337eb1eff406b20 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 21:48:45 +0000 Subject: [PATCH 10/35] main: remove debug left on by accident. --- src/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.c b/src/main.c index 1dc1dd86..3401c237 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,3 @@ -#define _DEBUG /*B-em v2.2 by Tom Walker Main loop + start/finish code*/ From dfb6fb4771c87e44da38b1b9c775f321cec7af26 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 21:49:24 +0000 Subject: [PATCH 11/35] autoboot: revert to simulating for autoboot. At some point the implementation of autoboot had been changed so that, instead of the simulating the shift key being pressed, it altered the start up options to invert the boot flag, i.e. so the OS would tell the filing system to boot if the shift key was NOT held down. Unfortunately, this is not compatible with setting autoboot before a sofware initiated soft break on a Master because, in that case, the OS does not re-read the startup options from CMOS so the boot flag cannot be overridden. This change revers to simulating the depression of the shift key. --- src/cmos.c | 7 +++++-- src/keyboard.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cmos.c b/src/cmos.c index fd82ddae..3d46cd8a 100644 --- a/src/cmos.c +++ b/src/cmos.c @@ -1,3 +1,4 @@ +#define _DEBUG /*B-em v2.2 by Tom Walker Master 128 CMOS emulation*/ @@ -161,8 +162,10 @@ static uint8_t get_cmos(unsigned addr) else if (curtube == 9) value = cmos_fix_tube_lang(value, 7); } - else if (addr == 0x1e && autoboot) - value |= 0x10; + else if (addr == 0x1e && autoboot) { + log_debug("cmos: faking boot option for autoboot"); + value &= ~0x10; + } return value; } } diff --git a/src/keyboard.c b/src/keyboard.c index cba1d434..1cf1c92d 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,3 +1,4 @@ +#define _DEBUG #include "b-em.h" #include "main.h" #include "via.h" @@ -1187,13 +1188,15 @@ void key_scan(int row, int col) { } bool key_is_down(void) { - if (keyrow == 0 && keycol >= 2 && keycol <= 9) { - if (keycol == 6 && autoboot > 0) + if (keyrow == 0) { + if (keycol == 0 && autoboot > 0) { + log_debug("keyboard: return shift is down (autoboot=%d), pc=%04X", autoboot, pc); return true; - return kbdips & (1 << (9 - keycol)); + } + else if (keycol >= 2 && keycol <= 9) + return kbdips & (1 << (9 - keycol)); } - else - return bbcmatrix[keycol][keyrow]; + return bbcmatrix[keycol][keyrow]; } bool key_any_down(void) From 7cde67221e72252e7293d44f02300fc0fec14d1b Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 21:53:16 +0000 Subject: [PATCH 12/35] mmb: implement the DBOOT command. --- src/mmb.c | 21 ++++++++++++++++----- src/mmb.h | 3 ++- src/vdfs.c | 5 +++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index cae0d494..b423f2c9 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -15,6 +15,7 @@ #include "mmb.h" #include "sdf.h" #include "6502.h" +#include "main.h" #include "mem.h" #include "vdfs.h" @@ -266,8 +267,9 @@ static bool mmb_check_pick(unsigned drive, unsigned disc) return true; } -void mmb_cmd_din(uint16_t addr) +bool mmb_cmd_din(uint16_t addr) { + bool worked = false; int num1 = 0, num2 = 0; uint16_t addr2 = addr; int ch = readmem(addr2); @@ -279,7 +281,7 @@ void mmb_cmd_din(uint16_t addr) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r') - mmb_check_pick(0, num1); + worked = mmb_check_pick(0, num1); else { addr = addr2; while (ch >= '0' && ch <= '9') { @@ -290,20 +292,29 @@ void mmb_cmd_din(uint16_t addr) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r' && num1 >= 0 && num1 <= 3) - mmb_check_pick(num1, num2); + worked = mmb_check_pick(num1, num2); else vdfs_error(err_bad_drive_id); } else if ((num2 = mmb_parse_find(addr)) >= 0) { if (num1 >= 0 && num1 <= 3) - mmb_check_pick(num1, num2); + worked = mmb_check_pick(num1, num2); else vdfs_error(err_bad_drive_id); } } } else if ((num1 = mmb_parse_find(addr)) >= 0) - mmb_check_pick(0, num1); + worked = mmb_check_pick(0, num1); + return worked; +} + +void mmb_cmd_dboot(uint16_t addr) +{ + if (mmb_cmd_din(addr)) { + autoboot = 150; + main_key_break(); + } } static const char mmb_about_str[] = "B-Em internal MMB\r\n"; diff --git a/src/mmb.h b/src/mmb.h index 3e30eee2..aebdaa34 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -17,7 +17,8 @@ void mmb_pick(unsigned drive, unsigned side, unsigned disc); void mmb_reset(void); void mmb_cmd_dabout(void); -void mmb_cmd_din(uint16_t addr); +bool mmb_cmd_din(uint16_t addr); +void mmb_cmd_dboot(uint16_t addr); void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); diff --git a/src/vdfs.c b/src/vdfs.c index f33a9ad8..1e7cbe15 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -282,6 +282,7 @@ enum vdfs_action { VDFS_ACT_OSW7F_WAT5, VDFS_ACT_MMBDABT, VDFS_ACT_MMBDIN, + VDFS_ACT_MMBDBOT, VDFS_ACT_MMBDCAT, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, @@ -4710,6 +4711,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDIN: mmb_cmd_din(addr); break; + case VDFS_ACT_MMBDBOT: + mmb_cmd_dboot(addr); + break; case VDFS_ACT_MMBDCAT: mmb_cmd_dcat_start(addr); break; @@ -4966,6 +4970,7 @@ static const struct cmdent ctab_always[] = { static const struct cmdent ctab_mmb[] = { { "DAbout", VDFS_ACT_MMBDABT }, { "Din", VDFS_ACT_MMBDIN }, + { "DBoot", VDFS_ACT_MMBDBOT }, { "DCat", VDFS_ACT_MMBDCAT } }; From 26d88b164a0578ce4a44f2e26f91466e4a4bb27d Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 22:58:54 +0000 Subject: [PATCH 13/35] mmb: load the correct disc into drives 2 and 3. --- src/mmb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index b423f2c9..4842cc74 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -255,7 +255,6 @@ static bool mmb_check_pick(unsigned drive, unsigned disc) case 2: case 3: drive &= 1; - disc--; side = 1; break; default: From 90e30cf43a52fcdcee3355f46aa6c68272a6a955 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 23:01:44 +0000 Subject: [PATCH 14/35] mmb: add the DDRIVE command. --- src/mmb.c | 65 +++++++++++++++++++++++++++++++++++++++++------------- src/mmb.h | 1 + src/vdfs.c | 7 +++++- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 4842cc74..a8e08e8f 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -37,6 +37,7 @@ static unsigned mmb_dcat_end; static unsigned mmb_dcat_count; static unsigned mmb_dcat_pat_len; static char mmb_dcat_pattern[MMB_NAME_SIZE]; +static int mmb_loaded_discs[4] = { -1, -1, -1, -1 }; static void mmb_read_error(const char *fn, FILE *fp) { @@ -117,11 +118,15 @@ void mmb_load(char *fn) writeprot[1] = writeprot[0]; mmb_offset[1][0] = mmb_calc_offset(mmb_boot_discs[2]); mmb_offset[1][1] = mmb_calc_offset(mmb_boot_discs[3]); + mmb_loaded_discs[2] = mmb_boot_discs[2]; + mmb_loaded_discs[3] = mmb_boot_discs[3]; } } sdf_mount(0, fn, fp, &sdf_geometries.dfs_10s_seq_80t); mmb_offset[0][0] = mmb_calc_offset(mmb_boot_discs[0]); mmb_offset[0][1] = mmb_calc_offset(mmb_boot_discs[1]); + mmb_loaded_discs[0] = mmb_boot_discs[0]; + mmb_loaded_discs[1] = mmb_boot_discs[1]; mmb_fp = fp; mmb_fn = fn; mmb_ndisc = (extra_zones + 1) * MMB_ZONE_DISCS; @@ -250,10 +255,12 @@ static bool mmb_check_pick(unsigned drive, unsigned disc) switch(drive) { case 0: case 1: + mmb_loaded_discs[drive] = disc; side = 0; break; case 2: case 3: + mmb_loaded_discs[drive] = disc; drive &= 1; side = 1; break; @@ -324,6 +331,26 @@ void mmb_cmd_dabout(void) vdfs_split_go(0); } +static uint8_t *mmb_name_flag(uint8_t *dest, const char *cat_ptr) +{ + for (int i = 0; i < MMB_NAME_SIZE; ++i) { + int ch = cat_ptr[i] & 0x7f; + if (ch < ' ' || ch > 0x7e) + ch = ' '; + *dest++ = ch; + } + *dest++ = ' '; + int flag = cat_ptr[15]; + if (flag == 0xf0) + flag = 'U'; + else if (flag == 0) + flag = 'P'; + else + flag = ' '; + *dest++ = flag; + return dest; +} + void mmb_cmd_dcat_cont(void) { if (readmem(0xff) & 0x80) @@ -335,21 +362,7 @@ void mmb_cmd_dcat_cont(void) if (*cat_ptr && vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, cat_ptr, MMB_NAME_SIZE)) { ++mmb_dcat_count; dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); - for (int i = 0; i < MMB_NAME_SIZE; ++i) { - int ch = cat_ptr[i] & 0x7f; - if (ch < ' ' || ch > 0x7e) - ch = ' '; - *dest++ = ch; - } - *dest++ = ' '; - int flag = cat_ptr[15]; - if (flag == 0xf0) - flag = 'U'; - else if (flag == 0) - flag = 'P'; - else - flag = ' '; - *dest++ = flag; + dest = mmb_name_flag(dest, cat_ptr); *dest = 0; vdfs_split_go(0x16); return; @@ -421,3 +434,25 @@ void mmb_cmd_dcat_start(uint16_t addr) } mmb_cmd_dcat_cont(); } + +static const char mmb_no_discs[] = "No discs loaded\r\n"; + +void mmb_cmd_ddrive(uint16_t addr) +{ + uint8_t *dest = vdfs_split_addr(); + bool loaded = false; + for (int drive = 0; drive < 4; ++drive) { + int disc = mmb_loaded_discs[drive]; + if (disc >= 0) { + dest += sprintf((char *)dest, "%u: %5u ", drive, disc); + dest = mmb_name_flag(dest, mmb_cat + disc * MMB_ENTRY_SIZE); + *dest++ = '\r'; + *dest++ = '\n'; + loaded = true; + } + *dest = 0; + } + if (!loaded) + memcpy(dest, mmb_no_discs, sizeof(mmb_no_discs)); + vdfs_split_go(0); +} diff --git a/src/mmb.h b/src/mmb.h index aebdaa34..6ccfd354 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -21,5 +21,6 @@ bool mmb_cmd_din(uint16_t addr); void mmb_cmd_dboot(uint16_t addr); void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); +void mmb_cmd_ddrive(uint16_t addr); #endif diff --git a/src/vdfs.c b/src/vdfs.c index 1e7cbe15..5fc8c37d 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -284,6 +284,7 @@ enum vdfs_action { VDFS_ACT_MMBDIN, VDFS_ACT_MMBDBOT, VDFS_ACT_MMBDCAT, + VDFS_ACT_MMBDDRV, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, VDFS_ACT_COPY, @@ -4717,6 +4718,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDCAT: mmb_cmd_dcat_start(addr); break; + case VDFS_ACT_MMBDDRV: + mmb_cmd_ddrive(addr); + break; case VDFS_ACT_DRIVE: cmd_drive(addr); break; @@ -4971,7 +4975,8 @@ static const struct cmdent ctab_mmb[] = { { "DAbout", VDFS_ACT_MMBDABT }, { "Din", VDFS_ACT_MMBDIN }, { "DBoot", VDFS_ACT_MMBDBOT }, - { "DCat", VDFS_ACT_MMBDCAT } + { "DCat", VDFS_ACT_MMBDCAT }, + { "DDrive", VDFS_ACT_MMBDDRV } }; static const struct cmdent ctab_enabled[] = { From 5bd8a215ded19d5892de7adfdb6f62cd5b8e681b Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Fri, 26 Jan 2024 23:19:44 +0000 Subject: [PATCH 15/35] mmb: implement the DFREE command. --- src/mmb.c | 41 ++++++++++++++++++++++++++++++----------- src/mmb.h | 1 + src/vdfs.c | 7 ++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index a8e08e8f..e9a04b91 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -29,7 +29,7 @@ static unsigned mmb_boot_discs[4]; static unsigned mmb_cat_size; -static char *mmb_cat; +static unsigned char *mmb_cat; unsigned mmb_ndisc; char *mmb_fn; static unsigned mmb_dcat_posn; @@ -94,8 +94,8 @@ void mmb_load(char *fn) mmb_read_error(fn, fp); return; } - char *mmb_ptr = mmb_cat + MMB_ZONE_CAT_SIZE; - char *mmb_end = mmb_cat + reqd_cat_size; + unsigned char *mmb_ptr = mmb_cat + MMB_ZONE_CAT_SIZE; + unsigned char *mmb_end = mmb_cat + reqd_cat_size; while (mmb_ptr < mmb_end) { if (fseek(fp, MMB_ZONE_SKIP_SIZE, SEEK_CUR)) { log_error("mmb: seek error on MMB file %s: %s", fn, strerror(errno)); @@ -187,7 +187,7 @@ void mmb_pick(unsigned drive, unsigned side, unsigned disc) fdc_spindown(); } -static inline int mmb_cat_name_cmp(const char *nam_ptr, const char *cat_ptr, const char *cat_nxt) +static inline int mmb_cat_name_cmp(const char *nam_ptr, const unsigned char *cat_ptr, const unsigned char *cat_nxt) { do { char cat_ch = *cat_ptr++; @@ -206,11 +206,11 @@ static inline int mmb_cat_name_cmp(const char *nam_ptr, const char *cat_ptr, con static int mmb_find(const char *name) { - const char *cat_ptr = mmb_cat; - const char *cat_end = mmb_cat + mmb_cat_size; + const unsigned char *cat_ptr = mmb_cat; + const unsigned char *cat_end = mmb_cat + mmb_cat_size; do { - const char *cat_nxt = cat_ptr + 16; + const unsigned char *cat_nxt = cat_ptr + 16; int i = mmb_cat_name_cmp(name, cat_ptr, cat_nxt); if (i >= 0) { log_debug("mmb: found MMB SSD '%s' at %d", name, i); @@ -331,7 +331,7 @@ void mmb_cmd_dabout(void) vdfs_split_go(0); } -static uint8_t *mmb_name_flag(uint8_t *dest, const char *cat_ptr) +static uint8_t *mmb_name_flag(uint8_t *dest, const unsigned char *cat_ptr) { for (int i = 0; i < MMB_NAME_SIZE; ++i) { int ch = cat_ptr[i] & 0x7f; @@ -357,9 +357,9 @@ void mmb_cmd_dcat_cont(void) vdfs_error("\x17" "Escape"); else { uint8_t *dest = vdfs_split_addr(); - const char *cat_ptr = mmb_cat + mmb_dcat_posn * 16; + const unsigned char *cat_ptr = mmb_cat + mmb_dcat_posn * 16; while (mmb_dcat_posn < mmb_dcat_end) { - if (*cat_ptr && vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, cat_ptr, MMB_NAME_SIZE)) { + if (*cat_ptr && vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, (char *)cat_ptr, MMB_NAME_SIZE)) { ++mmb_dcat_count; dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); dest = mmb_name_flag(dest, cat_ptr); @@ -454,5 +454,24 @@ void mmb_cmd_ddrive(uint16_t addr) } if (!loaded) memcpy(dest, mmb_no_discs, sizeof(mmb_no_discs)); - vdfs_split_go(0); + vdfs_split_go(0); +} + +void mmb_cmd_dfree(void) +{ + unsigned total = 0; + unsigned unform = 0; + const unsigned char *ptr = mmb_cat; + const unsigned char *end = ptr + mmb_cat_size; + while (ptr < end) { + if (ptr[15] == 0xf0) { + ++unform; + ++total; + } + else if (ptr[0]) + ++total; + ptr += MMB_ENTRY_SIZE; + } + sprintf((char *)vdfs_split_addr(), "%u of %u disks free (unformatted)\r\n", unform, total); + vdfs_split_go(0); } diff --git a/src/mmb.h b/src/mmb.h index 6ccfd354..bc866c32 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -22,5 +22,6 @@ void mmb_cmd_dboot(uint16_t addr); void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); void mmb_cmd_ddrive(uint16_t addr); +void mmb_cmd_dfree(void); #endif diff --git a/src/vdfs.c b/src/vdfs.c index 5fc8c37d..e81f3434 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -285,6 +285,7 @@ enum vdfs_action { VDFS_ACT_MMBDBOT, VDFS_ACT_MMBDCAT, VDFS_ACT_MMBDDRV, + VDFS_ACT_MMBDFRE, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, VDFS_ACT_COPY, @@ -4721,6 +4722,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDDRV: mmb_cmd_ddrive(addr); break; + case VDFS_ACT_MMBDFRE: + mmb_cmd_dfree(); + break; case VDFS_ACT_DRIVE: cmd_drive(addr); break; @@ -4976,7 +4980,8 @@ static const struct cmdent ctab_mmb[] = { { "Din", VDFS_ACT_MMBDIN }, { "DBoot", VDFS_ACT_MMBDBOT }, { "DCat", VDFS_ACT_MMBDCAT }, - { "DDrive", VDFS_ACT_MMBDDRV } + { "DDrive", VDFS_ACT_MMBDDRV }, + { "DFree", VDFS_ACT_MMBDFRE } }; static const struct cmdent ctab_enabled[] = { From 70cbdfe2cf3acc3513efe6be2a9d8b2a4eb16f35 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 27 Jan 2024 03:03:44 +0000 Subject: [PATCH 16/35] keyboard: turn off debug. --- src/keyboard.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/keyboard.c b/src/keyboard.c index 1cf1c92d..6625447f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,4 +1,3 @@ -#define _DEBUG #include "b-em.h" #include "main.h" #include "via.h" From ce89a6339385628b003e24467157c91047ff6a86 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 27 Jan 2024 03:04:19 +0000 Subject: [PATCH 17/35] mmb: fix DIN command and implement the DOP command. This commit adds the DOP command however, both the DOP and DIN commands are specified as working on the current drive if the drive number is not specified. The DIN command did not previously do this but defaulted to drive zero if a drive was not specified because, not being a filing system like MMFS, the MMB module doesn't have a current drive. This commit includes code to check the active filing system and, if it is DFS, ask DFS for the current drive (via OSGBPB) to use a a better default. --- src/mmb.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/mmb.h | 1 + src/vdfs.asm | 71 +++++++++++++++++++++++++++++++++++---------- src/vdfs.c | 16 +++++----- 4 files changed, 144 insertions(+), 26 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index e9a04b91..4c528f43 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -287,7 +287,7 @@ bool mmb_cmd_din(uint16_t addr) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r') - worked = mmb_check_pick(0, num1); + worked = mmb_check_pick(x, num1); else { addr = addr2; while (ch >= '0' && ch <= '9') { @@ -311,7 +311,7 @@ bool mmb_cmd_din(uint16_t addr) } } else if ((num1 = mmb_parse_find(addr)) >= 0) - worked = mmb_check_pick(0, num1); + worked = mmb_check_pick(x, num1); return worked; } @@ -364,7 +364,7 @@ void mmb_cmd_dcat_cont(void) dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); dest = mmb_name_flag(dest, cat_ptr); *dest = 0; - vdfs_split_go(0x16); + vdfs_split_go(0x17); return; } cat_ptr += MMB_ENTRY_SIZE; @@ -475,3 +475,79 @@ void mmb_cmd_dfree(void) sprintf((char *)vdfs_split_addr(), "%u of %u disks free (unformatted)\r\n", unform, total); vdfs_split_go(0); } + +static const char err_disc_not_loaded[] = "\xd6" "Disk not loaded in that drive"; +static const char err_bad_dop_oper[] = "\x94" "Bad DOP operation"; +static const char err_no_unformatted[] = "\xd6" "No unformatted discs"; +static const char err_wprotect[] = "\xc1" "MMB file not open for update"; + +static void mmb_dop_find_unformatted(unsigned drive) +{ + const unsigned char *ptr = mmb_cat; + const unsigned char *end = ptr + mmb_cat_size; + while (ptr < end) { + if (ptr[15] == 0xf0) { + int disc = (ptr - mmb_cat) / MMB_ENTRY_SIZE; + mmb_check_pick(drive, disc); + return; + } + ptr += MMB_ENTRY_SIZE; + } + vdfs_error(err_no_unformatted); +} + +static void mmb_dop_flags(unsigned drive, int op) +{ + if (writeprot[0]) + vdfs_error(err_wprotect); + else { + int disc = mmb_loaded_discs[drive]; + if (disc < 0) + vdfs_error(err_disc_not_loaded); + else { + unsigned char *cat_ptr = mmb_cat + disc * MMB_ENTRY_SIZE; + if (op == 'P') + cat_ptr[15] &= 0xf0; + else if (op == 'U') + cat_ptr[15] |= 0x0f; + else if (op == 'K') + cat_ptr[15] |= 0xf0; + else if (op == 'R') + cat_ptr[15] &= 0x0f; + else { + vdfs_error(err_bad_dop_oper); + return; + } + /* write changed entry back to disk */ + unsigned zone_start = disc / MMB_ZONE_DISCS; + unsigned zone_index = disc % MMB_ZONE_DISCS; + unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + (zone_index + 1) * MMB_ENTRY_SIZE; + if (fseek(mmb_fp, offset, SEEK_SET) == -1) + log_error("unable to seek on MMB file: %s", strerror(errno)); + else if (fwrite(cat_ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) + log_error("unable to write back to MMB file: %s", strerror(errno)); + } + } +} + +void mmb_cmd_dop(uint16_t addr) +{ + unsigned drive = x; + int op = readmem(addr++) & 0x5f; + int ch = readmem(addr++); + while (ch == ' ' || ch == '\t') + ch = readmem(addr++); + if (ch >= '0' && ch <= '9') { + drive = 0; + do { + drive = (drive * 10) + (ch & 0x0f); + ch = readmem(addr++); + } while (ch >= '0' && ch <= '9'); + } + if (drive >= 4) + vdfs_error(err_bad_drive_id); + else if (op == 'N') + mmb_dop_find_unformatted(drive); + else + mmb_dop_flags(drive, op); +} diff --git a/src/mmb.h b/src/mmb.h index bc866c32..4751b268 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -23,5 +23,6 @@ void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); void mmb_cmd_ddrive(uint16_t addr); void mmb_cmd_dfree(void); +void mmb_cmd_dop(uint16_t addr); #endif diff --git a/src/vdfs.asm b/src/vdfs.asm index 49f51dc4..3105e336 100644 --- a/src/vdfs.asm +++ b/src/vdfs.asm @@ -158,6 +158,8 @@ prtextws = &A8 equw cmd_append ; *APPEND. equw opt1_print equw print_split + equw mmb_din + equw mmb_dop .dispend ; Stubs to transfer control to the vdfs.c module. @@ -648,23 +650,41 @@ prtextws = &A8 bcc dir_info rts -.not_found -{ - ldx #end-msg -.loop lda msg,x - sta &0100,x +.mmb_din lda #&16 + bne mmb_common +.mmb_dop lda #&18 +.mmb_common pha + lda #&00 + tay + jsr OSARGS + cmp #&04 + beq mmb_dfs +.mmb_baddrv ldx #&00 + beq mmb_tail +.mmb_dfs lda #&0d + sta &0101 + sta &0105 + ldy #&01 + sty &0102 + lda #&ff + sta &0103 + sta &0104 + lda #&00 + ldx #&08 +.mmb_clear sta &0107,X dex - bpl loop - jmp &0100 -.msg brk - equb &d6 - equs "Not found" - equb &00 -.end -} - -.opt1_print jsr pr_all - lda #&01 + bne mmb_clear + lda #&06 + jsr OSGBPB + lda &010d + cmp #&01 + bne mmb_baddrv + lda &010e + and #&03 + tax +.mmb_tail pla + sta port_cmd + lda #&00 rts .print_split @@ -683,6 +703,25 @@ prtextws = &A8 .more sta port_cmd } +.not_found +{ + ldx #end-msg +.loop lda msg,x + sta &0100,x + dex + bpl loop + jmp &0100 +.msg brk + equb &d6 + equs "Not found" + equb &00 +.end +} + +.opt1_print jsr pr_all + lda #&01 + rts + ; The *DUMP command. .cmd_dump diff --git a/src/vdfs.c b/src/vdfs.c index e81f3434..2de8373c 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -250,6 +250,8 @@ enum vdfs_action { VDFS_ROM_APPEND, VDFS_ROM_OPT1, VDFS_ROM_PRINT_SPLIT, + VDFS_ROM_MMBDIN, + VDFS_ROM_MMBDOP, VDFS_ACT_NOP, VDFS_ACT_QUIT, VDFS_ACT_SRLOAD, @@ -281,7 +283,6 @@ enum vdfs_action { VDFS_ACT_OSW7F_WATF, VDFS_ACT_OSW7F_WAT5, VDFS_ACT_MMBDABT, - VDFS_ACT_MMBDIN, VDFS_ACT_MMBDBOT, VDFS_ACT_MMBDCAT, VDFS_ACT_MMBDDRV, @@ -4710,9 +4711,6 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDABT: mmb_cmd_dabout(); break; - case VDFS_ACT_MMBDIN: - mmb_cmd_din(addr); - break; case VDFS_ACT_MMBDBOT: mmb_cmd_dboot(addr); break; @@ -4735,6 +4733,7 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) cmd_copy(addr); break; default: + cmd_tail = addr; rom_dispatch(act); } return true; @@ -4977,11 +4976,12 @@ static const struct cmdent ctab_always[] = { static const struct cmdent ctab_mmb[] = { { "DAbout", VDFS_ACT_MMBDABT }, - { "Din", VDFS_ACT_MMBDIN }, + { "Din", VDFS_ROM_MMBDIN }, { "DBoot", VDFS_ACT_MMBDBOT }, { "DCat", VDFS_ACT_MMBDCAT }, { "DDrive", VDFS_ACT_MMBDDRV }, - { "DFree", VDFS_ACT_MMBDFRE } + { "DFree", VDFS_ACT_MMBDFRE }, + { "DOP", VDFS_ROM_MMBDOP } }; static const struct cmdent ctab_enabled[] = { @@ -5169,7 +5169,9 @@ static inline void dispatch(uint8_t value) case 0x13: rest_ram(); break; case 0x14: info_next(); break; case 0x15: log_time(); break; - case 0x16: mmb_cmd_dcat_cont(); break; + case 0x16: mmb_cmd_din(cmd_tail); break; + case 0x17: mmb_cmd_dcat_cont(); break; + case 0x18: mmb_cmd_dop(cmd_tail); break; default: log_warn("vdfs: function code %d not recognised", value); } } From fe4c5d3e56ed1de521b5daa074c44d4d46dd8f07 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 27 Jan 2024 03:09:40 +0000 Subject: [PATCH 18/35] mmb: add pre-built VDFS ROM for the previous commit. --- roms/general/vdfs.rom | Bin 5542 -> 5623 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/roms/general/vdfs.rom b/roms/general/vdfs.rom index 70d8fe34895960c0c00da68190e84b3f3f6d50c5..ed78cf22cb09b90980a9c7f626790379966df727 100644 GIT binary patch delta 1229 zcmYjQZA@EL7(VCr_5((ttE?ceSvnDjAS#vjkorWkii|%K= z^};^kYhlAT=4bqEftg?^Ou`G{E8!!N>1ZMPZP*%f#J-8G#D0lg^!xpng^18E4C4DC zclQNe1j)vkgq0ym;x0y7;8){k%vYrad=fg$d-+HCLH-&31%8Bo9bbmE_A5NPsi6R?;h0Cf#TR{|=k16#3@7UknjNxFpUc0ose3nTPKSx~KoRy86=&`R_f4 zZ(A%PkWO#k88*|MGx!5$z?xHkK}pA0(JV7!8_MAu%-Q39kHkPkXQ<5p4n0Lb6!o~; zYbqYh@1J5`GjK&k1n8C<^?T5$hagl`=n$*XJ9iB0cEh&K$Tq0Lq?1N`)(E9NUJ9gc zZ65HVuA-v3vP~*0YuC8y53;*8xL<|McOaq=-^)I^JI7}M%(HVlGSaX&gK|6<@KObu zqxcC;?Iha@bNF-CQTP9`t0rH%JyqmrkyqSk6c<_BaTRz-wd(kjI-G=|1(Gc#9ZGnJ z#{b8uLbJ*!!`d<=Hkl#yLj!9h_t#0ir2kgiG=U zF`$ByHN!lV3)yPet}|v_RE+@qqQ2fCR!J9x1b|DHbq+xA{nJO^MPo-N-hKtBCxA}U zi>@o_(vSEfeW%^;nI$ya*|b_(wOpz5=m%x4hQ`zSZ2ud%Z(C3w?>p-P%6)u5^0lMG<5u?JqmUmE-CmILMHnFt~&fU1J$ zGTdMQNx06`ZC?(cW5KOG+HPh0rlN81o2E7x#ivb|+CL16iman4uS(Z~@;bRiUs?@4 zSE#g8y?l_Jh-l6UJYI2_F^A?06>qQyXw+lL5c)MJ9!#E6mqW=(y13G$!Z|av>D#i( zlr3u;Q+hd)k=DYR{@Q$`dRf=xi^KuD=$?uL{i1t14h#YLH`Kz4ebR6gzi(|bnqop) zGRNjq)}4&u@#Mb;zrt9mwHvhtrkC||?V*m%cO}vTBXCW;| delta 1222 zcmYjQZ)jUp6o2m}&7W@hv)FXCZPweaqp7u+*>!CPhAvbW=fh4mWZ*XQVU&n<9k_kk zG<`{4{uGxqy$vLcVtAU7n>CUWm@DpmC=po()~90kP4-1w6+)P90U12+eQ8}E@11+j zJ-_pN=iGB{ec;wWd)FVcY#-Q{fF0H;bu6Ad&j@x zKNW1@hxn^J3R%M|p^fl~=veG*Y$|po))F6Im|gJ4))pTwa>-~ik-Qi_8a~TkfG^SP zi$zYLG99TU3xnjP7Z|a`ZKXdq+!sqQPTPGBZj5trZ*gb1^V}3himq8umACLB)jjT% z8?13)Qzq{W=aqoB)>%`NWJ#Z0#Zom5k1{=ncz@#Y{jEoPq$e+*duBG{B<6SToHF2@ zoA486!cr#5V9;f?V2~K050v50%on~uKxAluC9Oz`cAvx#hy}d;CcUF_Y@Yc*!&YU1 z0>Ar#GXUNXAb_jHuV4h1o*S0kM(Zx4&`yZaAddK|gBI;UtcXVxIUWQqi)=6t${ZUEVg_8Ja1)mnS0ALyu%x#8 z{!e@FjSJ7_t1NEEhM$ySAoky+J)1HzVWVi?_81ipMtTr~PfRk`R3IHd3c*tkQI*(+ z+CsojJ;Gj*<(DY>fw|67G_~>e%oQ*-bM=z;B1Hmd7;9?Np>eP-=W1(ky=l-E2xJk? zIGZEKLrT823?9lw6DGkmwrQql2lQ#i=o4^NV?TZz@%b8q zX8GFJGbyZ?15v_{nK1lCJ4RoFCY@{l^+;m?dZS=E0=|iSnP;Db!8G*hMs3$4pewqw zhexJiZ^{Y=in=~J27lAt>F=E-|EjX z_oAhq<`31Uaa1)E1<9zO&wNIf=FAPecymbaNx8RuJ5~d-W9>qU#&}*##T5Qj>5=h! zRp)R#O{rH8&!?%T)x(K2rHM#?fo`>MT$B^AV(HU Date: Sat, 27 Jan 2024 03:55:55 +0000 Subject: [PATCH 19/35] mmb: fix bugs in DIN/DBOOT. --- src/mmb.c | 22 ++++++++++++++++------ src/mmb.h | 2 +- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 4c528f43..d13e4628 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -273,7 +273,7 @@ static bool mmb_check_pick(unsigned drive, unsigned disc) return true; } -bool mmb_cmd_din(uint16_t addr) +bool mmb_din_common(uint16_t addr, unsigned default_drive) { bool worked = false; int num1 = 0, num2 = 0; @@ -287,7 +287,7 @@ bool mmb_cmd_din(uint16_t addr) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r') - worked = mmb_check_pick(x, num1); + worked = mmb_check_pick(default_drive, num1); else { addr = addr2; while (ch >= '0' && ch <= '9') { @@ -311,13 +311,18 @@ bool mmb_cmd_din(uint16_t addr) } } else if ((num1 = mmb_parse_find(addr)) >= 0) - worked = mmb_check_pick(x, num1); + worked = mmb_check_pick(default_drive, num1); return worked; } +void mmb_cmd_din(uint16_t addr) +{ + mmb_din_common(addr, x); +} + void mmb_cmd_dboot(uint16_t addr) { - if (mmb_cmd_din(addr)) { + if (mmb_din_common(addr, 0)) { autoboot = 150; main_key_break(); } @@ -480,6 +485,7 @@ static const char err_disc_not_loaded[] = "\xd6" "Disk not loaded in that drive" static const char err_bad_dop_oper[] = "\x94" "Bad DOP operation"; static const char err_no_unformatted[] = "\xd6" "No unformatted discs"; static const char err_wprotect[] = "\xc1" "MMB file not open for update"; +static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static void mmb_dop_find_unformatted(unsigned drive) { @@ -522,10 +528,14 @@ static void mmb_dop_flags(unsigned drive, int op) unsigned zone_start = disc / MMB_ZONE_DISCS; unsigned zone_index = disc % MMB_ZONE_DISCS; unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + (zone_index + 1) * MMB_ENTRY_SIZE; - if (fseek(mmb_fp, offset, SEEK_SET) == -1) + if (fseek(mmb_fp, offset, SEEK_SET) == -1) { log_error("unable to seek on MMB file: %s", strerror(errno)); - else if (fwrite(cat_ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) + vdfs_error(err_write_err); + } + else if (fwrite(cat_ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) { log_error("unable to write back to MMB file: %s", strerror(errno)); + vdfs_error(err_write_err); + } } } } diff --git a/src/mmb.h b/src/mmb.h index 4751b268..27f05b6b 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -17,7 +17,7 @@ void mmb_pick(unsigned drive, unsigned side, unsigned disc); void mmb_reset(void); void mmb_cmd_dabout(void); -bool mmb_cmd_din(uint16_t addr); +void mmb_cmd_din(uint16_t addr); void mmb_cmd_dboot(uint16_t addr); void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); From 951895f119d18de9cf0ce72a7a68083449c6bfcf Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sat, 27 Jan 2024 16:43:54 +0000 Subject: [PATCH 20/35] mmb: implement the DRECAT command. --- src/mmb.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mmb.h | 1 + src/vdfs.c | 7 ++++++- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index d13e4628..340a4e26 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -485,6 +485,7 @@ static const char err_disc_not_loaded[] = "\xd6" "Disk not loaded in that drive" static const char err_bad_dop_oper[] = "\x94" "Bad DOP operation"; static const char err_no_unformatted[] = "\xd6" "No unformatted discs"; static const char err_wprotect[] = "\xc1" "MMB file not open for update"; +static const char err_read_err[] = "\xc7" "Error reading MMB file"; static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static void mmb_dop_find_unformatted(unsigned drive) @@ -561,3 +562,54 @@ void mmb_cmd_dop(uint16_t addr) else mmb_dop_flags(drive, op); } + +void mmb_cmd_drecat(void) +{ + if (writeprot[0]) + vdfs_error(err_wprotect); + else { + unsigned char *cat_zone = mmb_cat; + unsigned char *cat_end = cat_zone + mmb_cat_size; + off_t zone_start = 0; + unsigned zone_num = 0; + while (cat_zone < cat_end) { + unsigned char *cat_ptr = cat_zone; + off_t zone_ptr = zone_start + MMB_ZONE_CAT_SIZE + MMB_ENTRY_SIZE; + off_t zone_end = zone_start + MMB_ZONE_FULL_SIZE; + bool dirty = false; + while (cat_ptr < cat_end && zone_ptr < zone_end) { + unsigned char title[MMB_NAME_SIZE]; + if (fseek(mmb_fp, zone_ptr, SEEK_SET) == -1 || + fread(title, 8, 1, mmb_fp) != 1 || + fseek(mmb_fp, zone_ptr+0x100, SEEK_SET) ==-1 || + fread(title+8, 4, 1, mmb_fp) != 1) + { + log_error("mmb: read error on MMB file %s: %s", mmb_fn, strerror(errno)); + vdfs_error(err_read_err); + return; + } + if (memcmp(cat_ptr, title, MMB_NAME_SIZE)) { + memcpy(cat_ptr, title, MMB_NAME_SIZE); + dirty = true; + } + cat_ptr += MMB_ENTRY_SIZE; + zone_ptr += MMB_DISC_SIZE; + } + if (dirty) { + off_t offset = zone_start + MMB_ENTRY_SIZE; + log_debug("mmb: zone #%u dirty, writing to %08lx", zone_num, offset); + if (fseek(mmb_fp, offset, SEEK_SET) == -1 || + fwrite(cat_zone, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) + { + log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + vdfs_error(err_write_err); + return; + } + } + log_debug("mmb: zone end, zone: %u, zone_start=%08lx, dirty=%d", zone_num, zone_start, dirty); + ++zone_num; + zone_start = zone_ptr; + cat_zone = cat_ptr; + } + } +} diff --git a/src/mmb.h b/src/mmb.h index 27f05b6b..6b2158be 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -24,5 +24,6 @@ void mmb_cmd_dcat_cont(void); void mmb_cmd_ddrive(uint16_t addr); void mmb_cmd_dfree(void); void mmb_cmd_dop(uint16_t addr); +void mmb_cmd_drecat(void); #endif diff --git a/src/vdfs.c b/src/vdfs.c index 2de8373c..279b9f93 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -287,6 +287,7 @@ enum vdfs_action { VDFS_ACT_MMBDCAT, VDFS_ACT_MMBDDRV, VDFS_ACT_MMBDFRE, + VDFS_ACT_MMBRCAT, VDFS_ACT_DRIVE, VDFS_ACT_ACCESS, VDFS_ACT_COPY, @@ -4723,6 +4724,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBDFRE: mmb_cmd_dfree(); break; + case VDFS_ACT_MMBRCAT: + mmb_cmd_drecat(); + break; case VDFS_ACT_DRIVE: cmd_drive(addr); break; @@ -4981,7 +4985,8 @@ static const struct cmdent ctab_mmb[] = { { "DCat", VDFS_ACT_MMBDCAT }, { "DDrive", VDFS_ACT_MMBDDRV }, { "DFree", VDFS_ACT_MMBDFRE }, - { "DOP", VDFS_ROM_MMBDOP } + { "DOP", VDFS_ROM_MMBDOP }, + { "DRECAT", VDFS_ACT_MMBRCAT } }; static const struct cmdent ctab_enabled[] = { From ef96b95b7fc0e4a51ba103a2a728e1976bf06660 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 00:36:13 +0000 Subject: [PATCH 21/35] mmb: store MMB index internally in zones - upload mmb_load. This introduces a mmb_zone structure which keeps account of how many discs are valid in each zone. It also updates the mmb_load function to load the file into this, read the base zone and load the correct set of discs at boot. --- src/mmb.c | 282 ++++++++++++++++++++++++++++++++---------------------- src/mmb.h | 1 - 2 files changed, 166 insertions(+), 117 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 340a4e26..feb988a1 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -19,15 +19,31 @@ #include "mem.h" #include "vdfs.h" -#define MMB_DISC_SIZE (200*1024) #define MMB_ENTRY_SIZE 16 +#define MMB_NAME_SIZE 12 +#define MMB_DISC_SIZE (200*1024) #define MMB_ZONE_DISCS 511 -#define MMB_ZONE_CAT_SIZE (MMB_ZONE_DISCS*MMB_ENTRY_SIZE) -#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_ENTRY_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) +#define MMB_ZONE_CAT_SIZE ((MMB_ZONE_DISCS+1)*MMB_ENTRY_SIZE) +#define MMB_ZONE_FULL_SIZE (MMB_ZONE_CAT_SIZE+MMB_ZONE_DISCS*MMB_DISC_SIZE) + +struct mmb_zone { + unsigned num_discs; + unsigned char header[MMB_ENTRY_SIZE]; + unsigned char index[MMB_ZONE_DISCS][MMB_ENTRY_SIZE]; +}; + +/* +#define MMB_ENTRY_SIZE 16 #define MMB_ZONE_SKIP_SIZE (MMB_ZONE_DISCS*MMB_DISC_SIZE+MMB_ENTRY_SIZE) #define MMB_NAME_SIZE 12 +*/ +static bool mmb_writeprot; +static unsigned mmb_num_zones; +static unsigned mmb_base_zone; +static struct mmb_zone *mmb_zones; static unsigned mmb_boot_discs[4]; + static unsigned mmb_cat_size; static unsigned char *mmb_cat; unsigned mmb_ndisc; @@ -39,6 +55,9 @@ static unsigned mmb_dcat_pat_len; static char mmb_dcat_pattern[MMB_NAME_SIZE]; static int mmb_loaded_discs[4] = { -1, -1, -1, -1 }; +static const char err_disc_not_fnd[] = "\xd6" "Disk not found in MMB file"; +static const char err_bad_drive_id[] = "\x94" "Bad drive ID"; + static void mmb_read_error(const char *fn, FILE *fp) { if (ferror(fp)) @@ -48,99 +67,141 @@ static void mmb_read_error(const char *fn, FILE *fp) fclose(fp); } -static unsigned mmb_calc_offset(unsigned disc) +static long mmb_boot_offset(unsigned drive) { - unsigned zone_start = disc / MMB_ZONE_DISCS; - unsigned zone_index = disc % MMB_ZONE_DISCS; - unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + MMB_ENTRY_SIZE + zone_index * MMB_DISC_SIZE; - log_debug("mmb: mmb_calc_offset(%u) -> zone_start=%u, zone_index=%u, offset=%u", disc, zone_start, zone_index, offset); - return offset; + unsigned disc = mmb_boot_discs[drive]; + unsigned zone = mmb_base_zone; + if (disc < mmb_zones[zone].num_discs) { + long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + disc * MMB_DISC_SIZE; + log_debug("mmb: mmb_boot_offset, drive=%u, disc=%u -> offset=%08lx", drive, disc, offset); + return offset; + } + else { + log_debug("mmb: mmb_boot_offset, drive=%u, disc=%u -> invalid disc", drive, disc); + return 0; + } +} + +static void mmb_boot_drive(unsigned drive) +{ + long sideA = mmb_boot_offset(drive); + long sideB = mmb_boot_offset(drive+2); + if (sideA || sideB) { + if (sdf_fp[drive] != mmb_fp) { + disc_close(drive); + sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); + } + writeprot[drive] = mmb_writeprot; + if (sideA) { + mmb_offset[drive][0] = sideA; + mmb_loaded_discs[drive] = mmb_boot_discs[drive]; + } + if (sideB) { + mmb_offset[drive][1] = sideB - MMB_DISC_SIZE; + mmb_loaded_discs[drive+2] = mmb_boot_discs[drive+2]; + } + } +} + +void mmb_reset(void) +{ + if (mmb_fp) { + mmb_boot_drive(0); + mmb_boot_drive(1); + if (fdc_spindown) + fdc_spindown(); + } } void mmb_load(char *fn) { - writeprot[0] = 0; + log_info("mmb: load file '%s'", fn); + /* + * Start by reading the new MMB file into local variables and + * freshly malloced memory so as not to disturb any file already + * open. + */ + bool new_writeprot = false; FILE *fp = fopen(fn, "rb+"); if (fp == NULL) { if ((fp = fopen(fn, "rb")) == NULL) { log_error("Unable to open file '%s' for reading - %s", fn, strerror(errno)); return; } - writeprot[0] = 1; + new_writeprot = true; } unsigned char header[16]; if (fread(header, sizeof(header), 1, fp) != 1) { mmb_read_error(fn, fp); return; } - mmb_boot_discs[0] = header[0] | (header[4] << 8); - mmb_boot_discs[1] = header[1] | (header[5] << 8); - mmb_boot_discs[2] = header[2] | (header[6] << 8); - mmb_boot_discs[3] = header[3] | (header[7] << 8); - unsigned extra_zones = header[8]; - extra_zones = ((extra_zones & 0xf0) == 0xa0) ? extra_zones & 0x0f : 0; - unsigned reqd_cat_size = (extra_zones + 1) * MMB_ZONE_CAT_SIZE; - log_debug("mmb: mmb extra zones=%u, mmb cat total size=%u", extra_zones, reqd_cat_size); - if (reqd_cat_size != mmb_cat_size) { - if (mmb_cat) - free(mmb_cat); - if (!(mmb_cat = malloc(reqd_cat_size))) { - log_error("mmb: out of memory allocating MMB catalogue"); - return; - } - mmb_cat_size = reqd_cat_size; + log_dump("mmb header: ", header, 16); + unsigned new_num_zones = 1; + unsigned new_base_zone = 0; + unsigned zone_byte = header[8]; + if ((zone_byte & 0xf0) == 0xa0) { + new_num_zones = (zone_byte & 0x0f) + 1; + new_base_zone = (header[9] & 0x0f); + if (new_base_zone >= new_num_zones) + new_base_zone = 0; } - if (fread(mmb_cat, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { - mmb_read_error(fn, fp); + log_info("mmb: num_zones=%u, base_zone=%u", new_num_zones, new_base_zone); + struct mmb_zone *new_zones = malloc(new_num_zones * sizeof(struct mmb_zone)); + if (!new_zones) { + log_error("mmb: out of memory allocating MMB catalogue"); + fclose(fp); return; } - unsigned char *mmb_ptr = mmb_cat + MMB_ZONE_CAT_SIZE; - unsigned char *mmb_end = mmb_cat + reqd_cat_size; - while (mmb_ptr < mmb_end) { - if (fseek(fp, MMB_ZONE_SKIP_SIZE, SEEK_CUR)) { + for (unsigned zone_no = 0; zone_no < new_num_zones; ++zone_no) { + if (fseek(fp, zone_no * MMB_ZONE_FULL_SIZE, SEEK_SET)) { log_error("mmb: seek error on MMB file %s: %s", fn, strerror(errno)); + free(new_zones); fclose(fp); return; } - if (fread(mmb_ptr, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { + if (fread(new_zones[zone_no].header, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { mmb_read_error(fn, fp); + free(new_zones); return; } - mmb_ptr += MMB_ZONE_CAT_SIZE; - } - unsigned i = 0; - for (mmb_ptr = mmb_cat; mmb_ptr < mmb_end; mmb_ptr += 16) - log_debug("mmb: mmb#%04u=%-12.12s", i++, mmb_ptr); - if (mmb_fp) { - fclose(mmb_fp); - if (sdf_fp[1] == mmb_fp) { - sdf_mount(1, fn, fp, &sdf_geometries.dfs_10s_seq_80t); - writeprot[1] = writeprot[0]; - mmb_offset[1][0] = mmb_calc_offset(mmb_boot_discs[2]); - mmb_offset[1][1] = mmb_calc_offset(mmb_boot_discs[3]); - mmb_loaded_discs[2] = mmb_boot_discs[2]; - mmb_loaded_discs[3] = mmb_boot_discs[3]; + new_zones[zone_no].num_discs = MMB_ZONE_DISCS; + for (unsigned discno = 0; discno < MMB_ZONE_DISCS; ++discno) { + if (new_zones[zone_no].index[discno][15] == 0xff) { + new_zones[zone_no].num_discs = discno; + break; + } } } - sdf_mount(0, fn, fp, &sdf_geometries.dfs_10s_seq_80t); - mmb_offset[0][0] = mmb_calc_offset(mmb_boot_discs[0]); - mmb_offset[0][1] = mmb_calc_offset(mmb_boot_discs[1]); - mmb_loaded_discs[0] = mmb_boot_discs[0]; - mmb_loaded_discs[1] = mmb_boot_discs[1]; + /* + * Now the file has been read successfully, replace the static + * variables for the current file with the new one and free any + * malloced memory. + */ + if (mmb_zones) + free(mmb_zones); + mmb_zones = new_zones; + if (mmb_fp) + fclose(mmb_fp); mmb_fp = fp; mmb_fn = fn; - mmb_ndisc = (extra_zones + 1) * MMB_ZONE_DISCS; - if (fdc_spindown) - fdc_spindown(); + mmb_writeprot = new_writeprot; + mmb_num_zones = new_num_zones; + mmb_base_zone = new_base_zone; + + const unsigned char *zone_hdr = new_zones[new_base_zone].header; + mmb_boot_discs[0] = zone_hdr[0] | (zone_hdr[4] << 8); + mmb_boot_discs[1] = zone_hdr[1] | (zone_hdr[5] << 8); + mmb_boot_discs[2] = zone_hdr[2] | (zone_hdr[6] << 8); + mmb_boot_discs[3] = zone_hdr[3] | (zone_hdr[7] << 8); + mmb_reset(); } static void mmb_eject_one(int drive) { - ALLEGRO_PATH *path; - if (sdf_fp[drive] == mmb_fp) { disc_close(drive); - if ((path = discfns[drive])) + ALLEGRO_PATH *path = discfns[drive]; + if (path) disc_load(drive, path); } } @@ -150,41 +211,60 @@ void mmb_eject(void) if (mmb_fp) { mmb_eject_one(0); mmb_eject_one(1); + fclose(mmb_fp); + mmb_fp = NULL; + } + if (mmb_zones) { + free(mmb_zones); + mmb_zones = NULL; } if (mmb_fn) { free(mmb_fn); mmb_fn = NULL; } - mmb_ndisc = 0; } -static void mmb_reset_one(int drive) +static long mmb_calc_offset(unsigned disc) { - if (sdf_fp[drive] == mmb_fp) { - mmb_offset[drive][0] = mmb_calc_offset(0); - mmb_offset[drive][1] = mmb_calc_offset(1); + unsigned zone = disc / MMB_ZONE_DISCS; + unsigned posn = disc % MMB_ZONE_DISCS; + if (posn < mmb_zones[zone].num_discs) { + long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + posn * MMB_DISC_SIZE; + log_debug("mmb: mmb_calc_offset(%u) -> zone=%u, posn=%u, offset=%08lx", disc, zone, posn, offset); + return offset; } -} - -void mmb_reset(void) -{ - if (mmb_fp) { - mmb_reset_one(0); - mmb_reset_one(1); + else { + log_debug("mmb: mmb_calc_offset(%u) -> invalid disc", disc); + return 0; } } -void mmb_pick(unsigned drive, unsigned side, unsigned disc) +static bool mmb_pick(unsigned drive, unsigned disc) { - log_debug("mmb: picking MMB disc, drive=%d, side=%d, disc=%d", drive, side, disc); - - if (sdf_fp[drive] != mmb_fp) { - disc_close(drive); - sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); + log_debug("mmb: picking MMB disc, drive=%d, disc=%d", drive, disc); + if (drive & ~0x03) { + log_debug("vdfs: mmb_check_pick: invalid logical drive"); + vdfs_error(err_bad_drive_id); + return false; + } + long offset = mmb_calc_offset(disc); + if (offset) { + if (sdf_fp[drive] != mmb_fp) { + disc_close(drive); + sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); + } + unsigned side = (drive & 0x02) >> 1; + if (side) + offset -= MMB_DISC_SIZE; + mmb_offset[drive & 0x01][side] = mmb_calc_offset(disc); + if (fdc_spindown) + fdc_spindown(); + return true; + } + else { + vdfs_error(err_disc_not_fnd); + return false; } - mmb_offset[drive][side] = mmb_calc_offset(disc); - if (fdc_spindown) - fdc_spindown(); } static inline int mmb_cat_name_cmp(const char *nam_ptr, const unsigned char *cat_ptr, const unsigned char *cat_nxt) @@ -221,9 +301,6 @@ static int mmb_find(const char *name) return -1; } -static const char err_disc_not_fnd[] = "\xd6" "Disk not found in MMB file"; -static const char err_bad_drive_id[] = "\x94" "Bad drive ID"; - static int mmb_parse_find(uint16_t addr) { char name[17]; @@ -245,34 +322,6 @@ static int mmb_parse_find(uint16_t addr) return i; } -static bool mmb_check_pick(unsigned drive, unsigned disc) -{ - if (disc >= mmb_ndisc) { - vdfs_error(err_disc_not_fnd); - return false; - } - unsigned side; - switch(drive) { - case 0: - case 1: - mmb_loaded_discs[drive] = disc; - side = 0; - break; - case 2: - case 3: - mmb_loaded_discs[drive] = disc; - drive &= 1; - side = 1; - break; - default: - log_debug("vdfs: mmb_check_pick: invalid logical drive %d", drive); - vdfs_error(err_bad_drive_id); - return false; - } - mmb_pick(drive, side, disc); - return true; -} - bool mmb_din_common(uint16_t addr, unsigned default_drive) { bool worked = false; @@ -287,7 +336,7 @@ bool mmb_din_common(uint16_t addr, unsigned default_drive) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r') - worked = mmb_check_pick(default_drive, num1); + worked = mmb_pick(default_drive, num1); else { addr = addr2; while (ch >= '0' && ch <= '9') { @@ -298,20 +347,20 @@ bool mmb_din_common(uint16_t addr, unsigned default_drive) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r' && num1 >= 0 && num1 <= 3) - worked = mmb_check_pick(num1, num2); + worked = mmb_pick(num1, num2); else vdfs_error(err_bad_drive_id); } else if ((num2 = mmb_parse_find(addr)) >= 0) { if (num1 >= 0 && num1 <= 3) - worked = mmb_check_pick(num1, num2); + worked = mmb_pick(num1, num2); else vdfs_error(err_bad_drive_id); } } } else if ((num1 = mmb_parse_find(addr)) >= 0) - worked = mmb_check_pick(default_drive, num1); + worked = mmb_pick(default_drive, num1); return worked; } @@ -495,7 +544,7 @@ static void mmb_dop_find_unformatted(unsigned drive) while (ptr < end) { if (ptr[15] == 0xf0) { int disc = (ptr - mmb_cat) / MMB_ENTRY_SIZE; - mmb_check_pick(drive, disc); + mmb_pick(drive, disc); return; } ptr += MMB_ENTRY_SIZE; @@ -565,6 +614,7 @@ void mmb_cmd_dop(uint16_t addr) void mmb_cmd_drecat(void) { + log_debug("mmb: sdf_fp[0]=%p, sdf_fp[1]=%p, mmb_fp=%p", sdf_fp[0], sdf_fp[1], mmb_fp); if (writeprot[0]) vdfs_error(err_wprotect); else { diff --git a/src/mmb.h b/src/mmb.h index 6b2158be..2a862eec 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -13,7 +13,6 @@ extern off_t mmb_offset[NUM_DRIVES][2]; // Functions for MMB files. void mmb_load(char *fn); void mmb_eject(void); -void mmb_pick(unsigned drive, unsigned side, unsigned disc); void mmb_reset(void); void mmb_cmd_dabout(void); From 4e767304d6321df19cb626a75dfc22dc416eb961 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 00:48:14 +0000 Subject: [PATCH 22/35] mmb: fix the DDRIVE command. --- src/mmb.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index feb988a1..c36c803c 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -222,11 +222,15 @@ void mmb_eject(void) free(mmb_fn); mmb_fn = NULL; } + mmb_loaded_discs[0] = -1; + mmb_loaded_discs[1] = -1; + mmb_loaded_discs[2] = -1; + mmb_loaded_discs[3] = -1; } static long mmb_calc_offset(unsigned disc) { - unsigned zone = disc / MMB_ZONE_DISCS; + unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; unsigned posn = disc % MMB_ZONE_DISCS; if (posn < mmb_zones[zone].num_discs) { long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + posn * MMB_DISC_SIZE; @@ -498,11 +502,15 @@ void mmb_cmd_ddrive(uint16_t addr) for (int drive = 0; drive < 4; ++drive) { int disc = mmb_loaded_discs[drive]; if (disc >= 0) { - dest += sprintf((char *)dest, "%u: %5u ", drive, disc); - dest = mmb_name_flag(dest, mmb_cat + disc * MMB_ENTRY_SIZE); - *dest++ = '\r'; - *dest++ = '\n'; - loaded = true; + unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; + unsigned posn = disc % MMB_ZONE_DISCS; + if (posn < mmb_zones[zone].num_discs) { + dest += sprintf((char *)dest, ":%u %4u ", drive, disc); + dest = mmb_name_flag(dest, mmb_zones[zone].index[posn]); + *dest++ = '\r'; + *dest++ = '\n'; + loaded = true; + } } *dest = 0; } From b214b626aeca51b41dedc3d7c9d97e834586ca92 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 00:57:03 +0000 Subject: [PATCH 23/35] mmb: update *DIN and mmb_pick. This removes a 2nd call to mmb_calc_offset to re-calculate the offset already known and add updating of the mmb_discs_loaded array that supports *DDRIVE. --- src/mmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index c36c803c..e0c44b88 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -260,7 +260,8 @@ static bool mmb_pick(unsigned drive, unsigned disc) unsigned side = (drive & 0x02) >> 1; if (side) offset -= MMB_DISC_SIZE; - mmb_offset[drive & 0x01][side] = mmb_calc_offset(disc); + mmb_offset[drive & 0x01][side] = offset; + mmb_loaded_discs[drive] = disc; if (fdc_spindown) fdc_spindown(); return true; From 701fe22676bc63847f7a2f3abb4a9716462bd084 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 01:07:07 +0000 Subject: [PATCH 24/35] mmb: update the *DFREE command. --- src/mmb.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index e0c44b88..1910186a 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -524,16 +524,11 @@ void mmb_cmd_dfree(void) { unsigned total = 0; unsigned unform = 0; - const unsigned char *ptr = mmb_cat; - const unsigned char *end = ptr + mmb_cat_size; - while (ptr < end) { - if (ptr[15] == 0xf0) { - ++unform; - ++total; - } - else if (ptr[0]) - ++total; - ptr += MMB_ENTRY_SIZE; + for (unsigned zone_no = 0; zone_no < mmb_num_zones; ++zone_no) { + for (unsigned disc = 0; disc < mmb_zones[zone_no].num_discs; ++disc) + if (mmb_zones[zone_no].index[disc][15] == 0xf0) + ++unform; + total += mmb_zones[zone_no].num_discs; } sprintf((char *)vdfs_split_addr(), "%u of %u disks free (unformatted)\r\n", unform, total); vdfs_split_go(0); From c0bb2138d5d35f49a68c634323708081b832efb3 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 01:21:06 +0000 Subject: [PATCH 25/35] mmb: update the *DCAT command --- src/mmb.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 1910186a..2a7be13b 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -416,17 +416,20 @@ void mmb_cmd_dcat_cont(void) vdfs_error("\x17" "Escape"); else { uint8_t *dest = vdfs_split_addr(); - const unsigned char *cat_ptr = mmb_cat + mmb_dcat_posn * 16; while (mmb_dcat_posn < mmb_dcat_end) { - if (*cat_ptr && vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, (char *)cat_ptr, MMB_NAME_SIZE)) { - ++mmb_dcat_count; - dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); - dest = mmb_name_flag(dest, cat_ptr); - *dest = 0; - vdfs_split_go(0x17); - return; + unsigned zone = mmb_dcat_posn / MMB_ZONE_DISCS; + unsigned posn = mmb_dcat_posn % MMB_ZONE_DISCS; + if (posn < mmb_zones[zone].num_discs) { + const unsigned char *ptr = mmb_zones[zone].index[posn]; + if (vdfs_wildmat(mmb_dcat_pattern, mmb_dcat_pat_len, (const char *)ptr, MMB_NAME_SIZE)) { + ++mmb_dcat_count; + dest += snprintf((char *)dest, 80, "%5d ", mmb_dcat_posn++); + dest = mmb_name_flag(dest, ptr); + *dest = 0; + vdfs_split_go(0x17); + return; + } } - cat_ptr += MMB_ENTRY_SIZE; ++mmb_dcat_posn; } snprintf((char *)dest, 20, "\r\n%d disks found\r\n", mmb_dcat_count); @@ -439,7 +442,7 @@ void mmb_cmd_dcat_start(uint16_t addr) /* Defaults for an unfiltered list */ mmb_dcat_count = 0; mmb_dcat_posn = 0; - mmb_dcat_end = mmb_cat_size / MMB_ENTRY_SIZE; + mmb_dcat_end = mmb_num_zones * MMB_ZONE_DISCS; mmb_dcat_pattern[0] = '*'; mmb_dcat_pat_len = 1; @@ -491,6 +494,7 @@ void mmb_cmd_dcat_start(uint16_t addr) log_debug("mmb: mmb_cmd_dcat_start, pattern=%.*s", pat_ix, mmb_dcat_pattern); } } + mmb_dcat_posn += mmb_base_zone * MMB_ZONE_DISCS; mmb_cmd_dcat_cont(); } From 667b10d38d3806ced10dafac3c24dbbcdc240021 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 02:00:35 +0000 Subject: [PATCH 26/35] mmb: update the *DOP command. --- src/mmb.c | 125 ++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 2a7be13b..c2a96d44 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -152,22 +152,22 @@ void mmb_load(char *fn) fclose(fp); return; } - for (unsigned zone_no = 0; zone_no < new_num_zones; ++zone_no) { - if (fseek(fp, zone_no * MMB_ZONE_FULL_SIZE, SEEK_SET)) { + for (unsigned zone = 0; zone < new_num_zones; ++zone) { + if (fseek(fp, zone * MMB_ZONE_FULL_SIZE, SEEK_SET)) { log_error("mmb: seek error on MMB file %s: %s", fn, strerror(errno)); free(new_zones); fclose(fp); return; } - if (fread(new_zones[zone_no].header, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { + if (fread(new_zones[zone].header, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { mmb_read_error(fn, fp); free(new_zones); return; } - new_zones[zone_no].num_discs = MMB_ZONE_DISCS; + new_zones[zone].num_discs = MMB_ZONE_DISCS; for (unsigned discno = 0; discno < MMB_ZONE_DISCS; ++discno) { - if (new_zones[zone_no].index[discno][15] == 0xff) { - new_zones[zone_no].num_discs = discno; + if (new_zones[zone].index[discno][15] == 0xff) { + new_zones[zone].num_discs = discno; break; } } @@ -228,19 +228,19 @@ void mmb_eject(void) mmb_loaded_discs[3] = -1; } -static long mmb_calc_offset(unsigned disc) +static void mmb_mount(unsigned drive, unsigned zone, unsigned posn) { - unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; - unsigned posn = disc % MMB_ZONE_DISCS; - if (posn < mmb_zones[zone].num_discs) { - long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + posn * MMB_DISC_SIZE; - log_debug("mmb: mmb_calc_offset(%u) -> zone=%u, posn=%u, offset=%08lx", disc, zone, posn, offset); - return offset; - } - else { - log_debug("mmb: mmb_calc_offset(%u) -> invalid disc", disc); - return 0; - } + if (sdf_fp[drive] != mmb_fp) { + disc_close(drive); + sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); + } + unsigned side = (drive & 0x02) >> 1; + long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + posn * MMB_DISC_SIZE;; + if (side) + offset -= MMB_DISC_SIZE; + mmb_offset[drive & 0x01][side] = offset; + if (fdc_spindown) + fdc_spindown(); } static bool mmb_pick(unsigned drive, unsigned disc) @@ -251,19 +251,11 @@ static bool mmb_pick(unsigned drive, unsigned disc) vdfs_error(err_bad_drive_id); return false; } - long offset = mmb_calc_offset(disc); - if (offset) { - if (sdf_fp[drive] != mmb_fp) { - disc_close(drive); - sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); - } - unsigned side = (drive & 0x02) >> 1; - if (side) - offset -= MMB_DISC_SIZE; - mmb_offset[drive & 0x01][side] = offset; + unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; + unsigned posn = disc % MMB_ZONE_DISCS; + if (posn < mmb_zones[zone].num_discs) { + mmb_mount(drive, zone, posn); mmb_loaded_discs[drive] = disc; - if (fdc_spindown) - fdc_spindown(); return true; } else { @@ -528,11 +520,11 @@ void mmb_cmd_dfree(void) { unsigned total = 0; unsigned unform = 0; - for (unsigned zone_no = 0; zone_no < mmb_num_zones; ++zone_no) { - for (unsigned disc = 0; disc < mmb_zones[zone_no].num_discs; ++disc) - if (mmb_zones[zone_no].index[disc][15] == 0xf0) + for (unsigned zone = mmb_base_zone; zone < mmb_num_zones; ++zone) { + for (unsigned disc = 0; disc < mmb_zones[zone].num_discs; ++disc) + if (mmb_zones[zone].index[disc][15] == 0xf0) ++unform; - total += mmb_zones[zone_no].num_discs; + total += mmb_zones[zone].num_discs; } sprintf((char *)vdfs_split_addr(), "%u of %u disks free (unformatted)\r\n", unform, total); vdfs_split_go(0); @@ -547,15 +539,14 @@ static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static void mmb_dop_find_unformatted(unsigned drive) { - const unsigned char *ptr = mmb_cat; - const unsigned char *end = ptr + mmb_cat_size; - while (ptr < end) { - if (ptr[15] == 0xf0) { - int disc = (ptr - mmb_cat) / MMB_ENTRY_SIZE; - mmb_pick(drive, disc); - return; + for (unsigned zone = mmb_base_zone; zone < mmb_num_zones; ++zone) { + for (unsigned disc = 0; disc < mmb_zones[zone].num_discs; ++disc) { + if (mmb_zones[zone].index[disc][15] == 0xf0) { + mmb_mount(drive, zone, disc); + mmb_loaded_discs[drive] = disc + (zone - mmb_base_zone) * MMB_ZONE_DISCS; + return; + } } - ptr += MMB_ENTRY_SIZE; } vdfs_error(err_no_unformatted); } @@ -569,30 +560,32 @@ static void mmb_dop_flags(unsigned drive, int op) if (disc < 0) vdfs_error(err_disc_not_loaded); else { - unsigned char *cat_ptr = mmb_cat + disc * MMB_ENTRY_SIZE; - if (op == 'P') - cat_ptr[15] &= 0xf0; - else if (op == 'U') - cat_ptr[15] |= 0x0f; - else if (op == 'K') - cat_ptr[15] |= 0xf0; - else if (op == 'R') - cat_ptr[15] &= 0x0f; - else { - vdfs_error(err_bad_dop_oper); - return; - } - /* write changed entry back to disk */ - unsigned zone_start = disc / MMB_ZONE_DISCS; - unsigned zone_index = disc % MMB_ZONE_DISCS; - unsigned offset = zone_start * MMB_ZONE_FULL_SIZE + (zone_index + 1) * MMB_ENTRY_SIZE; - if (fseek(mmb_fp, offset, SEEK_SET) == -1) { - log_error("unable to seek on MMB file: %s", strerror(errno)); - vdfs_error(err_write_err); - } - else if (fwrite(cat_ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) { - log_error("unable to write back to MMB file: %s", strerror(errno)); - vdfs_error(err_write_err); + unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; + unsigned posn = disc % MMB_ZONE_DISCS; + if (posn < mmb_zones[zone].num_discs) { + unsigned char *ptr = mmb_zones[zone].index[posn]; + if (op == 'P' && ptr[15] != 0xf0) + ptr[15] = 0; + else if (op == 'U' && ptr[15] != 0xf0) + ptr[15] = 0x0f; + else if (op == 'K') + ptr[15] = 0xf0; + else if (op == 'R') + ptr[15] &= 0x0f; + else { + vdfs_error(err_bad_dop_oper); + return; + } + /* write changed entry back to disk */ + unsigned offset = zone * MMB_ZONE_FULL_SIZE + (posn + 1) * MMB_ENTRY_SIZE; + if (fseek(mmb_fp, offset, SEEK_SET) == -1) { + log_error("unable to seek on MMB file: %s", strerror(errno)); + vdfs_error(err_write_err); + } + else if (fwrite(ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) { + log_error("unable to write back to MMB file: %s", strerror(errno)); + vdfs_error(err_write_err); + } } } } From 0bf2c8eb3e8332cf16ccda31f21e0b44f9baa7b3 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Sun, 28 Jan 2024 21:21:07 +0000 Subject: [PATCH 27/35] mmb: update *DRECAT command --- src/mmb.c | 60 ++++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index c2a96d44..2b2287e4 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -615,52 +615,44 @@ void mmb_cmd_dop(uint16_t addr) void mmb_cmd_drecat(void) { - log_debug("mmb: sdf_fp[0]=%p, sdf_fp[1]=%p, mmb_fp=%p", sdf_fp[0], sdf_fp[1], mmb_fp); - if (writeprot[0]) + if (mmb_writeprot) vdfs_error(err_wprotect); else { - unsigned char *cat_zone = mmb_cat; - unsigned char *cat_end = cat_zone + mmb_cat_size; - off_t zone_start = 0; - unsigned zone_num = 0; - while (cat_zone < cat_end) { - unsigned char *cat_ptr = cat_zone; - off_t zone_ptr = zone_start + MMB_ZONE_CAT_SIZE + MMB_ENTRY_SIZE; - off_t zone_end = zone_start + MMB_ZONE_FULL_SIZE; + log_debug("mmb: begin recatalogue"); + for (unsigned zone = mmb_base_zone; zone < mmb_num_zones; ++zone) { + long zone_start = zone * MMB_ZONE_FULL_SIZE; + long offset = zone_start + MMB_ZONE_CAT_SIZE; bool dirty = false; - while (cat_ptr < cat_end && zone_ptr < zone_end) { - unsigned char title[MMB_NAME_SIZE]; - if (fseek(mmb_fp, zone_ptr, SEEK_SET) == -1 || - fread(title, 8, 1, mmb_fp) != 1 || - fseek(mmb_fp, zone_ptr+0x100, SEEK_SET) ==-1 || - fread(title+8, 4, 1, mmb_fp) != 1) - { - log_error("mmb: read error on MMB file %s: %s", mmb_fn, strerror(errno)); - vdfs_error(err_read_err); - return; - } - if (memcmp(cat_ptr, title, MMB_NAME_SIZE)) { - memcpy(cat_ptr, title, MMB_NAME_SIZE); - dirty = true; + for (unsigned disc = 0; disc < mmb_zones[zone].num_discs; ++disc) { + if (mmb_zones[zone].index[disc][15] != 0xf0) { + unsigned char title[MMB_NAME_SIZE]; + if (fseek(mmb_fp, offset, SEEK_SET) == -1 || + fread(title, 8, 1, mmb_fp) != 1 || + fseek(mmb_fp, offset+0x100, SEEK_SET) ==-1 || + fread(title+8, 4, 1, mmb_fp) != 1) + { + log_error("mmb: read error on MMB file %s: %s", mmb_fn, strerror(errno)); + vdfs_error(err_read_err); + return; + } + if (memcmp(mmb_zones[zone].index[disc], title, MMB_NAME_SIZE)) { + memcpy(mmb_zones[zone].index[disc], title, MMB_NAME_SIZE); + dirty = true; + } } - cat_ptr += MMB_ENTRY_SIZE; - zone_ptr += MMB_DISC_SIZE; + offset += MMB_DISC_SIZE; } if (dirty) { - off_t offset = zone_start + MMB_ENTRY_SIZE; - log_debug("mmb: zone #%u dirty, writing to %08lx", zone_num, offset); - if (fseek(mmb_fp, offset, SEEK_SET) == -1 || - fwrite(cat_zone, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) + log_debug("mmb: zone #%u dirty, writing to %08lx", zone, zone_start); + if (fseek(mmb_fp, zone_start, SEEK_SET) == -1 || + fwrite(mmb_zones[zone].header, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) { log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); vdfs_error(err_write_err); return; } } - log_debug("mmb: zone end, zone: %u, zone_start=%08lx, dirty=%d", zone_num, zone_start, dirty); - ++zone_num; - zone_start = zone_ptr; - cat_zone = cat_ptr; } + log_debug("mmb: recatalogue finished"); } } From 9b5682ef6dfb30c6d2762356a58333f7bc86bbb8 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 00:02:35 +0000 Subject: [PATCH 28/35] mmb: add the *DOUT and *DONBOOT commands. --- src/mmb.c | 109 ++++++++++++++++++++++++++++++++++++++------------- src/mmb.h | 2 + src/vdfs.asm | 6 +++ src/vdfs.c | 8 +++- 4 files changed, 96 insertions(+), 29 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 2b2287e4..19896589 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -57,6 +57,9 @@ static int mmb_loaded_discs[4] = { -1, -1, -1, -1 }; static const char err_disc_not_fnd[] = "\xd6" "Disk not found in MMB file"; static const char err_bad_drive_id[] = "\x94" "Bad drive ID"; +static const char err_wprotect[] = "\xc1" "MMB file not open for update"; +static const char err_read_err[] = "\xc7" "Error reading MMB file"; +static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static void mmb_read_error(const char *fn, FILE *fp) { @@ -319,9 +322,8 @@ static int mmb_parse_find(uint16_t addr) return i; } -bool mmb_din_common(uint16_t addr, unsigned default_drive) +static void mmb_twoargs(uint16_t addr, unsigned default_drive, bool (*action)(unsigned drive, unsigned disc)) { - bool worked = false; int num1 = 0, num2 = 0; uint16_t addr2 = addr; int ch = readmem(addr2); @@ -333,7 +335,7 @@ bool mmb_din_common(uint16_t addr, unsigned default_drive) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r') - worked = mmb_pick(default_drive, num1); + action(default_drive, num1); else { addr = addr2; while (ch >= '0' && ch <= '9') { @@ -344,36 +346,100 @@ bool mmb_din_common(uint16_t addr, unsigned default_drive) while (ch == ' ') ch = readmem(++addr2); if (ch == '\r' && num1 >= 0 && num1 <= 3) - worked = mmb_pick(num1, num2); + action(num1, num2); else vdfs_error(err_bad_drive_id); } else if ((num2 = mmb_parse_find(addr)) >= 0) { if (num1 >= 0 && num1 <= 3) - worked = mmb_pick(num1, num2); + action(num1, num2); else vdfs_error(err_bad_drive_id); } } } else if ((num1 = mmb_parse_find(addr)) >= 0) - worked = mmb_pick(default_drive, num1); - return worked; + action(default_drive, num1); } void mmb_cmd_din(uint16_t addr) { - mmb_din_common(addr, x); + mmb_twoargs(addr, x, mmb_pick); } void mmb_cmd_dboot(uint16_t addr) { - if (mmb_din_common(addr, 0)) { + unsigned disc = mmb_parse_find(addr); + if (disc >= 0 && mmb_pick(0, disc)) { autoboot = 150; main_key_break(); } } +static bool mmb_onboot_act(unsigned drive, unsigned disc) +{ + if (mmb_writeprot) { + vdfs_error(err_wprotect); + return false; + } + else { + mmb_zones[mmb_base_zone].header[drive] = disc; + long zone_start = mmb_base_zone * MMB_ZONE_FULL_SIZE; + if (fseek(mmb_fp, zone_start, SEEK_SET) == -1 || + fwrite(mmb_zones[mmb_base_zone].header, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) + { + log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + vdfs_error(err_write_err); + return false; + } + return true; + } +} + +void mmb_cmd_donboot(uint16_t addr) +{ + mmb_twoargs(addr, x, mmb_onboot_act); +} + +static int mmb_parse_drive(uint16_t addr, int drive) +{ + int ch = readmem(addr++); + while (ch == ' ' || ch == '\t') + ch = readmem(addr++); + if (ch >= '0' && ch <= '9') { + drive = 0; + do { + drive = (drive * 10) + (ch & 0x0f); + ch = readmem(addr++); + } while (ch >= '0' && ch <= '9'); + } + if (drive >= 4) { + vdfs_error(err_bad_drive_id); + drive = -1; + } + return drive; +} + +void mmb_cmd_dout(uint16_t addr) +{ + int drive = mmb_parse_drive(addr, x); + log_debug("mmb: dout, ldrive=%d", drive); + if (drive >= 0) { + if (mmb_loaded_discs[drive] >= 0) { + mmb_loaded_discs[drive] = -1; + int oside = drive ^ 0x02; + if (mmb_loaded_discs[oside] < 0) { + drive &= 1; + mmb_offset[drive][0] = 0; + mmb_offset[drive][1] = 0; + sdf_fp[drive] = NULL; + if (discfns[drive]) + disc_load(drive, discfns[drive]); + } + } + } +} + static const char mmb_about_str[] = "B-Em internal MMB\r\n"; void mmb_cmd_dabout(void) @@ -533,9 +599,6 @@ void mmb_cmd_dfree(void) static const char err_disc_not_loaded[] = "\xd6" "Disk not loaded in that drive"; static const char err_bad_dop_oper[] = "\x94" "Bad DOP operation"; static const char err_no_unformatted[] = "\xd6" "No unformatted discs"; -static const char err_wprotect[] = "\xc1" "MMB file not open for update"; -static const char err_read_err[] = "\xc7" "Error reading MMB file"; -static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static void mmb_dop_find_unformatted(unsigned drive) { @@ -593,24 +656,14 @@ static void mmb_dop_flags(unsigned drive, int op) void mmb_cmd_dop(uint16_t addr) { - unsigned drive = x; int op = readmem(addr++) & 0x5f; - int ch = readmem(addr++); - while (ch == ' ' || ch == '\t') - ch = readmem(addr++); - if (ch >= '0' && ch <= '9') { - drive = 0; - do { - drive = (drive * 10) + (ch & 0x0f); - ch = readmem(addr++); - } while (ch >= '0' && ch <= '9'); + int drive = mmb_parse_drive(addr, x); + if (drive >= 0) { + if (op == 'N') + mmb_dop_find_unformatted(drive); + else + mmb_dop_flags(drive, op); } - if (drive >= 4) - vdfs_error(err_bad_drive_id); - else if (op == 'N') - mmb_dop_find_unformatted(drive); - else - mmb_dop_flags(drive, op); } void mmb_cmd_drecat(void) diff --git a/src/mmb.h b/src/mmb.h index 2a862eec..817a7201 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -24,5 +24,7 @@ void mmb_cmd_ddrive(uint16_t addr); void mmb_cmd_dfree(void); void mmb_cmd_dop(uint16_t addr); void mmb_cmd_drecat(void); +void mmb_cmd_donboot(uint16_t addr); +void mmb_cmd_dout(uint16_t addr); #endif diff --git a/src/vdfs.asm b/src/vdfs.asm index 3105e336..d4a030a6 100644 --- a/src/vdfs.asm +++ b/src/vdfs.asm @@ -160,6 +160,8 @@ prtextws = &A8 equw print_split equw mmb_din equw mmb_dop + equw mmb_onboot + equw mmb_dout .dispend ; Stubs to transfer control to the vdfs.c module. @@ -653,6 +655,10 @@ prtextws = &A8 .mmb_din lda #&16 bne mmb_common .mmb_dop lda #&18 + bne mmb_common +.mmb_onboot lda #&19 + bne mmb_common +.mmb_dout lda #&1a .mmb_common pha lda #&00 tay diff --git a/src/vdfs.c b/src/vdfs.c index 279b9f93..df16f9ec 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -252,6 +252,8 @@ enum vdfs_action { VDFS_ROM_PRINT_SPLIT, VDFS_ROM_MMBDIN, VDFS_ROM_MMBDOP, + VDFS_ROM_MMBONBT, + VDFS_ROM_MMBDOUT, VDFS_ACT_NOP, VDFS_ACT_QUIT, VDFS_ACT_SRLOAD, @@ -4986,7 +4988,9 @@ static const struct cmdent ctab_mmb[] = { { "DDrive", VDFS_ACT_MMBDDRV }, { "DFree", VDFS_ACT_MMBDFRE }, { "DOP", VDFS_ROM_MMBDOP }, - { "DRECAT", VDFS_ACT_MMBRCAT } + { "DONboot", VDFS_ROM_MMBONBT }, + { "DOUt", VDFS_ROM_MMBDOUT }, + { "DREcat", VDFS_ACT_MMBRCAT } }; static const struct cmdent ctab_enabled[] = { @@ -5177,6 +5181,8 @@ static inline void dispatch(uint8_t value) case 0x16: mmb_cmd_din(cmd_tail); break; case 0x17: mmb_cmd_dcat_cont(); break; case 0x18: mmb_cmd_dop(cmd_tail); break; + case 0x19: mmb_cmd_donboot(cmd_tail); break; + case 0x1a: mmb_cmd_dout(cmd_tail); break; default: log_warn("vdfs: function code %d not recognised", value); } } From bf74a7de74d92690ff23041e2c4134c6038eccc5 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 00:06:38 +0000 Subject: [PATCH 29/35] mmb: add pre-built VDFS ROM for the previous commit. --- roms/general/vdfs.rom | Bin 5623 -> 5635 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/roms/general/vdfs.rom b/roms/general/vdfs.rom index ed78cf22cb09b90980a9c7f626790379966df727..20ddbfdd6cb03e40903c68cc926dbca7cbbced48 100644 GIT binary patch delta 1373 zcmYjQeM}o=7{9xgLScoj4&>XHp|ShGEt@i!{xQf#Dqen8CQY3K5`#IPJHXLgpZ9s*=l6WR z&$F`2v%9$R_fC2b<1WdpuR8KNdggFL3sL*>W7ReL+WLyWJ#v6K!^|Z@+&uFc|zO_<8U~@Qu(&|Ihuu1k1yZhUde-g;U{AeZ22$_B`9bHnKacBAO9nuvjiN=N#D~!=|2=iF+C^|ec&F8faUGRC(CDtjU8lGd`t(9TXOk8H;qm`{XMGy1;*yQCoJ-BVkBgifVn*YQHp&eozy6U<1V#n%YT@?=aPpqx`hVUgz$T zaF+H)cEkZ&2vj$6VuHnNEKT7~b_^dv*VU+UfSzDu=%=pkq$ORD%ud_bafrD+v!-B= z55K369erJ02b<^#{&Xhlm|(q8Oo`)=zckL71u4#D3({pSN02_?wg{MH$CRzOQx9N( z02&%1>d_${9gl73Ve7>&`*ew5^0Sv94%{OD|8 z;|`{EONaXiAo;fi9jbI7r-+mO~E8`37E{8}g`F9mh?OOv;A zzcG~bhlUB`bg*}r$e0fH4HG86@+Yb=igj`;KV!3-wuRZKTr|0Cvr#*n#?9>t&kqa? z;C~@$6_O6Vw2IA_?nVR{L8nN=62MNt$n491Vb}USSfz6^^7y^q(d S|A0VC{8WA!EX&ROivIwFyNX5t delta 1322 zcmYjQZ%iCj5Z~Q9j^odj>tT@st*=GpYN4s2R%j}=h~#QEmDp-b+t?$u1RJ%DEt;6d zvUj)KAG^n&$8ES6(#zVr+&j2>hPH$coA^Nlnu1$xY{Dnw2Z3q`D3;jJtn-#)*=**` zy!V^=&CHwUtz6z&vTd%N-zj)Xv+Ju~{|LR)(0GJ7b-Jdud2e-h$&UxCh4aE);cd?i z&rx5o__Fwe_^_kJ&-p6?eZf$egoneU;nSVnJ$HJ34m%>w$WM{!$ZwGwe!u@au~V!U z8}Tld-+WzAm{@6Fzk?%se<7z13$xKHwsCbBW7b)>M|eeO6y6lx6`F-JfK=<-(Y!tj zi?-}`^|{cffM#_1pBGv+)VfeMVbaRU0VOx)LCyGIw#)%qN5=Q9i|FD_B@<)N9$dk_ z^jy%>{nz;HuX)-(l_ys0b_m_Oey7O>J6Ev4H8{p71%S?(6`RH>6=)3K=+(4J74@i?R@FIm9BXnnmp~HW!R|wH*NZiP71)t z*o_lx&nkMp-%AYq12+QIfUc@fQLhJXQlxRD7$41Q-h5r`XV_czWu9S~Uk;zWfLhMB zef&Oy`tej&?H0c`P9U#%k~V=BmKa3$^h^QxKqb#wT37*pX{lxV@TkS<__QNVtn>n$ zNC34M30Sw36(+EXR`)BgY5e0m$f%PB?LZzrD#%E*hC# zO#%h&Fypq#c(=9c>B+$A1hoZ`8bJBMt0}%QfK+_JT2nR|K<9#MdoXjW_KZ$3c--n_ zd+?(5=8n&UimsWUnX~Hcptelz19t(?g%&o_0btT?oyK7s)^bj;wxO!r56wrw>D5>W z{T@_~#V*t3cuaz&HA!;ZeXhr6Yt|}c&02?4Pj;r%xv&v_Zs^Yqlcv&+&M0FZ@pMI* ztPxLll(7V~KhQR_a!_r;cO6cPH6kWe+Yndi;9htw_UPF67~|ev@(7aFA?fhR6_S%! zipelpZiR%;N{9(APzqm`kTG1ieHf5yfQm@s|A|7<@EB_Cr#nfr>*^ jyhTMFeY^W1CiPi_TSzRqLoV_e@V2H1lazowj}rd}PTg(- From 12c49c83e3d4f155f50a7e54b4265de42dcd64d7 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 15:17:27 +0000 Subject: [PATCH 30/35] mmb: refactor last commit to use existing mmb_eject_one. --- src/mmb.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 19896589..6994a375 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -428,14 +428,8 @@ void mmb_cmd_dout(uint16_t addr) if (mmb_loaded_discs[drive] >= 0) { mmb_loaded_discs[drive] = -1; int oside = drive ^ 0x02; - if (mmb_loaded_discs[oside] < 0) { - drive &= 1; - mmb_offset[drive][0] = 0; - mmb_offset[drive][1] = 0; - sdf_fp[drive] = NULL; - if (discfns[drive]) - disc_load(drive, discfns[drive]); - } + if (mmb_loaded_discs[oside] < 0) + mmb_eject_one(drive & 1); } } } From 7183c489a24eea1edec73aef56e93e186de5fa31 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 17:43:55 +0000 Subject: [PATCH 31/35] mmb: fix bug causing mmb_fp to be overwritten. --- src/mmb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index 6994a375..359cae3f 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -233,11 +233,12 @@ void mmb_eject(void) static void mmb_mount(unsigned drive, unsigned zone, unsigned posn) { + unsigned side = (drive & 0x02) >> 1; + drive &= 1; if (sdf_fp[drive] != mmb_fp) { disc_close(drive); sdf_mount(drive, mmb_fn, mmb_fp, &sdf_geometries.dfs_10s_seq_80t); } - unsigned side = (drive & 0x02) >> 1; long offset = zone * MMB_ZONE_FULL_SIZE + MMB_ZONE_CAT_SIZE + posn * MMB_DISC_SIZE;; if (side) offset -= MMB_DISC_SIZE; From f369e4f7e6fd07d8b5ab6bdc139cffa4b1e2a440 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 17:54:25 +0000 Subject: [PATCH 32/35] mmb: add *DBASE command. --- src/mmb.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++-------- src/mmb.h | 1 + src/vdfs.c | 5 ++++ 3 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 359cae3f..9b62e48a 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -60,6 +60,7 @@ static const char err_bad_drive_id[] = "\x94" "Bad drive ID"; static const char err_wprotect[] = "\xc1" "MMB file not open for update"; static const char err_read_err[] = "\xc7" "Error reading MMB file"; static const char err_write_err[] = "\xc7" "Error writing to MMB file"; +static const char err_bad_zone[] = "\x94" "Not that many zones in MMB file"; static void mmb_read_error(const char *fn, FILE *fp) { @@ -249,12 +250,6 @@ static void mmb_mount(unsigned drive, unsigned zone, unsigned posn) static bool mmb_pick(unsigned drive, unsigned disc) { - log_debug("mmb: picking MMB disc, drive=%d, disc=%d", drive, disc); - if (drive & ~0x03) { - log_debug("vdfs: mmb_check_pick: invalid logical drive"); - vdfs_error(err_bad_drive_id); - return false; - } unsigned zone = disc / MMB_ZONE_DISCS + mmb_base_zone; unsigned posn = disc % MMB_ZONE_DISCS; if (posn < mmb_zones[zone].num_discs) { @@ -262,10 +257,21 @@ static bool mmb_pick(unsigned drive, unsigned disc) mmb_loaded_discs[drive] = disc; return true; } - else { - vdfs_error(err_disc_not_fnd); + return false; +} + +static bool mmb_check_pick(unsigned drive, unsigned disc) +{ + log_debug("mmb: picking MMB disc, drive=%d, disc=%d", drive, disc); + if (drive & ~0x03) { + log_debug("vdfs: mmb_check_pick: invalid logical drive"); + vdfs_error(err_bad_drive_id); return false; } + if (mmb_pick(drive, disc)) + return true; + vdfs_error(err_disc_not_fnd); + return false; } static inline int mmb_cat_name_cmp(const char *nam_ptr, const unsigned char *cat_ptr, const unsigned char *cat_nxt) @@ -365,13 +371,13 @@ static void mmb_twoargs(uint16_t addr, unsigned default_drive, bool (*action)(un void mmb_cmd_din(uint16_t addr) { - mmb_twoargs(addr, x, mmb_pick); + mmb_twoargs(addr, x, mmb_check_pick); } void mmb_cmd_dboot(uint16_t addr) { unsigned disc = mmb_parse_find(addr); - if (disc >= 0 && mmb_pick(0, disc)) { + if (disc >= 0 && mmb_check_pick(0, disc)) { autoboot = 150; main_key_break(); } @@ -704,3 +710,47 @@ void mmb_cmd_drecat(void) log_debug("mmb: recatalogue finished"); } } + +static void mmb_rebase(unsigned drive) +{ + if (!mmb_pick(drive, mmb_loaded_discs[drive])) + mmb_loaded_discs[drive] = -1; + unsigned oside = drive + 2; + if (!mmb_pick(oside, mmb_loaded_discs[oside])) + mmb_loaded_discs[oside] = -1; + if (mmb_loaded_discs[drive] == -1 && mmb_loaded_discs[oside] == -1) + mmb_eject_one(drive); +} + +void mmb_cmd_dbase(uint16_t addr) +{ + int ch = readmem(addr++); + if (ch >= '0' && ch <= '9') { + unsigned zone = 0; + do { + zone = zone * 10 + (ch & 0x0f); + ch = readmem(addr++); + } while (ch >= '0' && ch <= '9'); + + if (mmb_writeprot) + vdfs_error(err_wprotect); + else if (zone < mmb_num_zones) { + mmb_zones[0].header[9] = zone; + if (fseek(mmb_fp, 0, SEEK_SET) == -1 || + fwrite(mmb_zones[0].header, MMB_ENTRY_SIZE, 1, mmb_fp) != 1) + { + log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + vdfs_error(err_write_err); + } + mmb_base_zone = zone; + mmb_rebase(0); + mmb_rebase(1); + } + else + vdfs_error(err_bad_zone); + } + else if (ch == '\r') { + sprintf((char *)vdfs_split_addr(), "MMB Base: %2u\r\nMMB Size: %2u\r\n", mmb_base_zone, mmb_num_zones); + vdfs_split_go(0); + } +} diff --git a/src/mmb.h b/src/mmb.h index 817a7201..875431a3 100644 --- a/src/mmb.h +++ b/src/mmb.h @@ -17,6 +17,7 @@ void mmb_reset(void); void mmb_cmd_dabout(void); void mmb_cmd_din(uint16_t addr); +void mmb_cmd_dbase(uint16_t addr); void mmb_cmd_dboot(uint16_t addr); void mmb_cmd_dcat_start(uint16_t addr); void mmb_cmd_dcat_cont(void); diff --git a/src/vdfs.c b/src/vdfs.c index df16f9ec..a556a5a7 100644 --- a/src/vdfs.c +++ b/src/vdfs.c @@ -254,6 +254,7 @@ enum vdfs_action { VDFS_ROM_MMBDOP, VDFS_ROM_MMBONBT, VDFS_ROM_MMBDOUT, + VDFS_ACT_MMBDBAS, VDFS_ACT_NOP, VDFS_ACT_QUIT, VDFS_ACT_SRLOAD, @@ -4729,6 +4730,9 @@ static bool vdfs_do(enum vdfs_action act, uint16_t addr) case VDFS_ACT_MMBRCAT: mmb_cmd_drecat(); break; + case VDFS_ACT_MMBDBAS: + mmb_cmd_dbase(addr); + break; case VDFS_ACT_DRIVE: cmd_drive(addr); break; @@ -4983,6 +4987,7 @@ static const struct cmdent ctab_always[] = { static const struct cmdent ctab_mmb[] = { { "DAbout", VDFS_ACT_MMBDABT }, { "Din", VDFS_ROM_MMBDIN }, + { "DBAse", VDFS_ACT_MMBDBAS }, { "DBoot", VDFS_ACT_MMBDBOT }, { "DCat", VDFS_ACT_MMBDCAT }, { "DDrive", VDFS_ACT_MMBDDRV }, From ab2d1e0b5119ae68f1ee0e6803bedc62544a8632 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 18:10:19 +0000 Subject: [PATCH 33/35] mmb: consolidate writing and associated error reporting. --- src/mmb.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 9b62e48a..214d7863 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -65,12 +65,25 @@ static const char err_bad_zone[] = "\x94" "Not that many zones in MMB file"; static void mmb_read_error(const char *fn, FILE *fp) { if (ferror(fp)) - log_error("mmb: read error on MMB file %s: %s", fn, strerror(errno)); + log_error("mmb: error reading MMB file %s: %s", fn, strerror(errno)); else log_error("mmb: unexpected EOF on MMB file %s", fn); fclose(fp); } +static bool mmb_write(long offset, void *ptr, size_t size) +{ + if (fseek(mmb_fp, offset, SEEK_SET) < 0) { + log_error("mmb: error seeking on MMB file %s: %s", mmb_fn, strerror(errno)); + return false; + } + if (fwrite(ptr, size, 1, mmb_fp) != 1) { + log_error("mmb: error writing on MMB file %s: %s", mmb_fn, strerror(errno)); + return false; + } + return true; +} + static long mmb_boot_offset(unsigned drive) { unsigned disc = mmb_boot_discs[drive]; @@ -392,10 +405,7 @@ static bool mmb_onboot_act(unsigned drive, unsigned disc) else { mmb_zones[mmb_base_zone].header[drive] = disc; long zone_start = mmb_base_zone * MMB_ZONE_FULL_SIZE; - if (fseek(mmb_fp, zone_start, SEEK_SET) == -1 || - fwrite(mmb_zones[mmb_base_zone].header, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) - { - log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + if (!mmb_write(zone_start, mmb_zones[mmb_base_zone].header, MMB_ZONE_CAT_SIZE)) { vdfs_error(err_write_err); return false; } @@ -642,14 +652,8 @@ static void mmb_dop_flags(unsigned drive, int op) } /* write changed entry back to disk */ unsigned offset = zone * MMB_ZONE_FULL_SIZE + (posn + 1) * MMB_ENTRY_SIZE; - if (fseek(mmb_fp, offset, SEEK_SET) == -1) { - log_error("unable to seek on MMB file: %s", strerror(errno)); - vdfs_error(err_write_err); - } - else if (fwrite(ptr, MMB_ENTRY_SIZE, 1, mmb_fp) != 1 || fflush(mmb_fp)) { - log_error("unable to write back to MMB file: %s", strerror(errno)); + if (!mmb_write(offset, ptr, MMB_ENTRY_SIZE)) vdfs_error(err_write_err); - } } } } @@ -685,7 +689,7 @@ void mmb_cmd_drecat(void) fseek(mmb_fp, offset+0x100, SEEK_SET) ==-1 || fread(title+8, 4, 1, mmb_fp) != 1) { - log_error("mmb: read error on MMB file %s: %s", mmb_fn, strerror(errno)); + log_error("mmb: error reading MMB file %s: %s", mmb_fn, strerror(errno)); vdfs_error(err_read_err); return; } @@ -698,10 +702,7 @@ void mmb_cmd_drecat(void) } if (dirty) { log_debug("mmb: zone #%u dirty, writing to %08lx", zone, zone_start); - if (fseek(mmb_fp, zone_start, SEEK_SET) == -1 || - fwrite(mmb_zones[zone].header, MMB_ZONE_CAT_SIZE, 1, mmb_fp) != 1) - { - log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + if (!mmb_write(zone_start, mmb_zones[zone].header, MMB_ZONE_CAT_SIZE)) { vdfs_error(err_write_err); return; } @@ -736,12 +737,8 @@ void mmb_cmd_dbase(uint16_t addr) vdfs_error(err_wprotect); else if (zone < mmb_num_zones) { mmb_zones[0].header[9] = zone; - if (fseek(mmb_fp, 0, SEEK_SET) == -1 || - fwrite(mmb_zones[0].header, MMB_ENTRY_SIZE, 1, mmb_fp) != 1) - { - log_error("mmb: write error on MMB file %s: %s", mmb_fn, strerror(errno)); + if (!mmb_write(0, mmb_zones[0].header, MMB_ENTRY_SIZE)) vdfs_error(err_write_err); - } mmb_base_zone = zone; mmb_rebase(0); mmb_rebase(1); From daf325953591e448699f57735efe8326648add4f Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 22:53:38 +0000 Subject: [PATCH 34/35] mmb: consolidate reading and associated error reporting. --- src/mmb.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/mmb.c b/src/mmb.c index 214d7863..3657536f 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -62,13 +62,20 @@ static const char err_read_err[] = "\xc7" "Error reading MMB file"; static const char err_write_err[] = "\xc7" "Error writing to MMB file"; static const char err_bad_zone[] = "\x94" "Not that many zones in MMB file"; -static void mmb_read_error(const char *fn, FILE *fp) +static bool mmb_read(const char *fn, FILE *fp, long offset, void *ptr, size_t size) { - if (ferror(fp)) - log_error("mmb: error reading MMB file %s: %s", fn, strerror(errno)); - else - log_error("mmb: unexpected EOF on MMB file %s", fn); - fclose(fp); + if (fseek(fp, offset, SEEK_SET) < 0) { + log_error("mmb: error seeking on MMB file %s: %s", fn, strerror(errno)); + return false; + } + if (fread(ptr, size, 1, fp) != 1) { + if (ferror(fp)) + log_error("mmb: error reading MMB file %s: %s", fn, strerror(errno)); + else + log_error("mmb: unexpected EOF on MMB file %s", fn); + return false; + } + return true; } static bool mmb_write(long offset, void *ptr, size_t size) @@ -148,8 +155,8 @@ void mmb_load(char *fn) new_writeprot = true; } unsigned char header[16]; - if (fread(header, sizeof(header), 1, fp) != 1) { - mmb_read_error(fn, fp); + if (!mmb_read(fn, fp, 0, header, sizeof(header))) { + fclose(fp); return; } log_dump("mmb header: ", header, 16); @@ -170,17 +177,11 @@ void mmb_load(char *fn) return; } for (unsigned zone = 0; zone < new_num_zones; ++zone) { - if (fseek(fp, zone * MMB_ZONE_FULL_SIZE, SEEK_SET)) { - log_error("mmb: seek error on MMB file %s: %s", fn, strerror(errno)); + if (!mmb_read(fn, fp, zone * MMB_ZONE_FULL_SIZE, new_zones[zone].header, MMB_ZONE_CAT_SIZE)) { free(new_zones); fclose(fp); return; } - if (fread(new_zones[zone].header, MMB_ZONE_CAT_SIZE, 1, fp) != 1) { - mmb_read_error(fn, fp); - free(new_zones); - return; - } new_zones[zone].num_discs = MMB_ZONE_DISCS; for (unsigned discno = 0; discno < MMB_ZONE_DISCS; ++discno) { if (new_zones[zone].index[discno][15] == 0xff) { @@ -684,12 +685,9 @@ void mmb_cmd_drecat(void) for (unsigned disc = 0; disc < mmb_zones[zone].num_discs; ++disc) { if (mmb_zones[zone].index[disc][15] != 0xf0) { unsigned char title[MMB_NAME_SIZE]; - if (fseek(mmb_fp, offset, SEEK_SET) == -1 || - fread(title, 8, 1, mmb_fp) != 1 || - fseek(mmb_fp, offset+0x100, SEEK_SET) ==-1 || - fread(title+8, 4, 1, mmb_fp) != 1) + if (!mmb_read(mmb_fn, mmb_fp, offset, title, 8) || + !mmb_read(mmb_fn, mmb_fp, offset+0x100, title+8, 4)) { - log_error("mmb: error reading MMB file %s: %s", mmb_fn, strerror(errno)); vdfs_error(err_read_err); return; } From 742c28e4e605dd0ce266ff3702616edc5d7eb395 Mon Sep 17 00:00:00 2001 From: Steve Fosdick Date: Tue, 30 Jan 2024 23:14:00 +0000 Subject: [PATCH 35/35] mmb: update debug message. --- src/mmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mmb.c b/src/mmb.c index 3657536f..8209421a 100644 --- a/src/mmb.c +++ b/src/mmb.c @@ -441,7 +441,7 @@ static int mmb_parse_drive(uint16_t addr, int drive) void mmb_cmd_dout(uint16_t addr) { int drive = mmb_parse_drive(addr, x); - log_debug("mmb: dout, ldrive=%d", drive); + log_debug("mmb: dout, drive=%d", drive); if (drive >= 0) { if (mmb_loaded_discs[drive] >= 0) { mmb_loaded_discs[drive] = -1;