From 4125809067e54e15dfa34c5a062f32226c6ee1d2 Mon Sep 17 00:00:00 2001 From: Tormod Volden Date: Tue, 2 Feb 2016 22:18:36 +0100 Subject: [PATCH] Add mooh cartridge module Support for the 512KB memory extension (DAT) on the MOOH cartridge. Also includes a crude CRT9128 emulation for debug output. Signed-off-by: Tormod Volden --- src/Makefile.am | 1 + src/cart.c | 2 + src/mooh.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/xroar.c | 4 ++ 4 files changed, 186 insertions(+) create mode 100644 src/mooh.c diff --git a/src/Makefile.am b/src/Makefile.am index 0996719..0535060 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -46,6 +46,7 @@ xroar_SOURCES = \ mpi.c mpi.h \ ntsc.c ntsc.h \ nx32.c \ + mooh.c \ orch90.c \ path.c path.h \ printer.c printer.h \ diff --git a/src/cart.c b/src/cart.c index 42d679a..2e19425 100644 --- a/src/cart.c +++ b/src/cart.c @@ -63,6 +63,7 @@ extern struct cart_module cart_orch90_module; extern struct cart_module cart_mpi_module; extern struct cart_module cart_ide_module; extern struct cart_module cart_nx32_module; +extern struct cart_module cart_mooh_module; static struct slist *cart_modules = NULL; @@ -228,6 +229,7 @@ void cart_config_print_all(FILE *f, _Bool all) { void cart_init(void) { // reverse order + cart_modules = slist_prepend(cart_modules, &cart_mooh_module); cart_modules = slist_prepend(cart_modules, &cart_nx32_module); cart_modules = slist_prepend(cart_modules, &cart_ide_module); cart_modules = slist_prepend(cart_modules, &cart_mpi_module); diff --git a/src/mooh.c b/src/mooh.c new file mode 100644 index 0000000..3d772ab --- /dev/null +++ b/src/mooh.c @@ -0,0 +1,179 @@ +/* + * Emulation of MOOH memory expansion (DAT) + * 2016 Tormod Volden + */ + +#include +#include +#include "cart.h" +#include "becker.h" + +/* Number of 8KB mappable RAM pages in cartridge */ +#define MEMPAGES 0x40 +#define TASK_MASK 0x3F /* 6 bit task registers */ + +struct mooh { + struct cart cart; + uint8_t extmem[0x2000 * MEMPAGES]; + _Bool mmu_enable; + _Bool crm_enable; + uint8_t taskreg[8][2]; + uint8_t task; + _Bool have_becker; + char crt9128_reg_addr; +}; + +static struct cart *mooh_new(struct cart_config *); + +struct cart_module cart_mooh_module = { + .name = "mooh", + .description = "mooh memory cartridge", + .new = mooh_new, +}; + +static void mooh_reset(struct cart *c); +static uint8_t mooh_read(struct cart *c, uint16_t A, _Bool P2, _Bool R2, uint8_t D); +static void mooh_write(struct cart *c, uint16_t A, _Bool P2, _Bool R2, uint8_t D); +static void mooh_detach(struct cart *c); + +struct cart *mooh_new(struct cart_config *cc) { + struct mooh *n = xmalloc(sizeof(*n)); + *n = (struct mooh){0}; + struct cart *c = &n->cart; + + c->config = cc; + cart_rom_init(c); + c->read = mooh_read; + c->write = mooh_write; + c->reset = mooh_reset; + c->detach = mooh_detach; + + n->have_becker = (cc->becker_port && becker_open()); + + return c; +} + +static void mooh_reset(struct cart *c) { + struct mooh *n = (struct mooh *)c; + int i; + + n->mmu_enable = 0; + n->crm_enable = 0; + n->task = 0; + for (i = 0; i < 8; i++) + n->taskreg[i][0] = n->taskreg[i][1] = 0xFF & TASK_MASK; + if (n->have_becker) + becker_reset(); + n->crt9128_reg_addr = 0; +} + +static void mooh_detach(struct cart *c) { + struct mooh *n = (struct mooh *)c; + if (n->have_becker) + becker_close(); +} + +static uint8_t mooh_read(struct cart *c, uint16_t A, _Bool P2, _Bool R2, uint8_t D) { + struct mooh *n = (struct mooh *)c; + int segment; + int offset; + int bank; + int crm; + + (void)R2; + c->EXTMEM = 0; + if ((A & 0xFFF0) == 0xFFA0) { + return n->taskreg[A & 7][(A & 8) >> 3]; +#if 0 + /* not implemented in MOOH fw 1 */ + } else if (A == 0xFF90) { + return (n->crm_enable << 3) | (n->mmu_enable << 6); + } else if (A == 0xFF91) { + return n->task; +#endif + } else if (n->mmu_enable && (A < 0xFF00 || (A >= 0xFFF0 && n->crm_enable))) { + segment = A >> 13; + offset = A & 0x1FFF; + if (n->crm_enable && (A >> 8) == 0xFE) { + crm = 1; + bank = 0x3F; /* used for storing crm */ + offset |= 0x100; /* A8 high */ + } else if (n->crm_enable && A >= 0xFFF0) { + crm = 1; + bank = 0x3F; + } else { + crm = 0; + bank = n->taskreg[segment][n->task]; + } + + if (bank != 0x3F || crm) { + c->EXTMEM = 1; + return n->extmem[bank * 0x2000 + offset]; + } + } + if (P2 && n->have_becker) { + switch (A & 3) { + case 0x1: + return becker_read_status(); + case 0x2: + return becker_read_data(); + default: + break; + } + } + return D; +} + +static void mooh_write(struct cart *c, uint16_t A, _Bool P2, _Bool R2, uint8_t D) { + struct mooh *n = (struct mooh *)c; + int segment; + int offset; + int bank; + int crm; + + (void)R2; + c->EXTMEM = 0; + + /* poor man's CRT9128 Wordpak emulation */ + if (A == 0xFF7D) + n->crt9128_reg_addr = D; + if (A == 0xFF7C && n->crt9128_reg_addr == 0x0d) + fprintf(stderr, "%c", D); + + if ((A & 0xFFF0) == 0xFFA0) { + n->taskreg[A & 7][(A & 8) >> 3] = D & TASK_MASK; + } else if (A == 0xFF90) { + n->crm_enable = (D & 8) >> 3; + n->mmu_enable = (D & 64) >> 6; + } else if (A == 0xFF91) { + n->task = D & 1; + } else if (n->mmu_enable && (A < 0xFF00 || (A >= 0xFFF0 && n->crm_enable))) { + segment = A >> 13; + offset = A & 0x1FFF; + if (n->crm_enable && (A >> 8) == 0xFE) { + crm = 1; + bank = 0x3F; /* last 8K bank */ + offset |= 0x100; /* A8 high */ + } else if (n->crm_enable && A >= 0xFFF0) { + crm = 1; + bank = 0x3F; + } else { + crm = 0; + bank = n->taskreg[segment][n->task]; + } + + if (bank != 0x3F || crm) { + n->extmem[bank * 0x2000 + offset] = D; + c->EXTMEM = 1; + } + } + if (P2 && n->have_becker) { + switch (A & 3) { + case 0x2: + becker_write_data(D); + break; + default: + break; + } + } +} diff --git a/src/xroar.c b/src/xroar.c index 82ceea4..5ea8625 100644 --- a/src/xroar.c +++ b/src/xroar.c @@ -326,6 +326,10 @@ static char const * const default_config[] = { "cart nx32", "cart-desc NX32 memory cartridge", "cart-type nx32", + // mooh memory cartridge + "cart mooh", + "cart-desc MOOH memory cartridge", + "cart-type mooh", // ROM lists -- 2.7.4