From 6947fea2a871ae451b4fb8f6161719a981aff192 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 25 Oct 2020 16:53:58 -0400 Subject: [PATCH] emul/z80: add SD card support to SMS It works (in emulation, but soon on real hardware!), but the LIST command is awkward due to tight screen estate... --- blk/001 | 4 +-- recipes/rc2014/blk/615 => blk/418 | 2 +- recipes/rc2014/blk/616 => blk/419 | 0 emul/z80/Makefile | 2 +- emul/z80/README.md | 2 ++ emul/z80/rc2014.c | 4 +++ emul/z80/sms.c | 61 ++++++++++++++++++++++++++++++++++----- recipes/rc2014/sdcard.md | 2 +- 8 files changed, 64 insertions(+), 13 deletions(-) rename recipes/rc2014/blk/615 => blk/418 (86%) rename recipes/rc2014/blk/616 => blk/419 (100%) diff --git a/blk/001 b/blk/001 index 635366a..7b63637 100644 --- a/blk/001 +++ b/blk/001 @@ -6,6 +6,6 @@ MASTER INDEX 160 AVR SPI programmer 170-259 unused 260 Cross compilation 280 Z80 boot code 350 Core words -410 PS/2 keyboard subsystem 420 SD Card subsystem -440 8086 boot code +410 PS/2 keyboard subsystem 418 Z80 SPI Relay driver +420 SD Card subsystem 440 8086 boot code 470-519 unused 520 Fonts diff --git a/recipes/rc2014/blk/615 b/blk/418 similarity index 86% rename from recipes/rc2014/blk/615 rename to blk/418 index 69080af..f14c60e 100644 --- a/recipes/rc2014/blk/615 +++ b/blk/418 @@ -7,4 +7,4 @@ to SPI_CTL, we expect a bitmask of the device to select, with returns 0 if the device is ready or 1 if it's still running an exchange. Writing to SPI_DATA initiates an exchange. -Provides the SPI relay protocol. Load driver with "596 LOAD". +Provides the SPI relay protocol. Load driver with "419 LOAD". diff --git a/recipes/rc2014/blk/616 b/blk/419 similarity index 100% rename from recipes/rc2014/blk/616 rename to blk/419 diff --git a/emul/z80/Makefile b/emul/z80/Makefile index 7f1951f..bff3a11 100644 --- a/emul/z80/Makefile +++ b/emul/z80/Makefile @@ -1,7 +1,7 @@ TARGETS = forth rc2014 sms ti84 OBJS = emul.o z80.o RC2014_OBJS = $(OBJS) sio.o acia.o sdc.o -SMS_OBJS = $(OBJS) sms_vdp.o sms_ports.o sms_pad.o ps2_kbd.o +SMS_OBJS = $(OBJS) sms_vdp.o sms_ports.o sms_pad.o ps2_kbd.o sdc.o TI84_OBJS = $(OBJS) t6a04.o ti84_kbd.o CDIR = ../../cvm STAGE = $(CDIR)/stage diff --git a/emul/z80/README.md b/emul/z80/README.md index 94596c8..090882a 100644 --- a/emul/z80/README.md +++ b/emul/z80/README.md @@ -61,6 +61,8 @@ pad are: If your ROM is configured with PS/2 keyboard input, run this emulator with the `-k` flag to replace SMS pad emulation with keyboard emulation. +The `-c` option connects a SD card in the same way as the RC2014 emulator. + In both cases (pad or keyboard), only port A emulation is supported. Press ESC to quit. diff --git a/emul/z80/rc2014.c b/emul/z80/rc2014.c index 12703ae..eb89a96 100644 --- a/emul/z80/rc2014.c +++ b/emul/z80/rc2014.c @@ -143,6 +143,10 @@ int main(int argc, char *argv[]) case 'c': fprintf(stderr, "Setting up SD card image with %s\n", optarg); sdc.fp = fopen(optarg, "r+"); + if (sdc.fp == NULL) { + fprintf(stderr, "Can't open file\n"); + return 1; + } break; } } diff --git a/emul/z80/sms.c b/emul/z80/sms.c index 2c76791..055d3fc 100644 --- a/emul/z80/sms.c +++ b/emul/z80/sms.c @@ -12,6 +12,7 @@ #include "sms_ports.h" #include "sms_pad.h" #include "ps2_kbd.h" +#include "sdc.h" #define RAMSTART 0xc000 #define VDP_CMD_PORT 0xbf @@ -19,6 +20,8 @@ #define PORTS_CTL_PORT 0x3f #define PORTS_IO1_PORT 0xdc #define PORTS_IO2_PORT 0xdd +#define SDC_CTL 0x05 +#define SDC_SPI 0x04 #define MAX_ROMSIZE 0x8000 static xcb_connection_t *conn; @@ -39,6 +42,7 @@ static Ports ports; static Pad pad; static Kbd kbd; static bool use_kbd = false; +static SDC sdc; static uint8_t iord_vdp_cmd() { @@ -86,6 +90,28 @@ static void iowr_ports_ctl(uint8_t val) ports_ctl_wr(&ports, val); } +static uint8_t iord_sdc_spi() +{ + return sdc_spi_rd(&sdc); +} + +static void iowr_sdc_spi(uint8_t val) +{ + sdc_spi_wr(&sdc, val); +} + +// in emulation, exchanges are always instantaneous, so we +// always report as ready. +static uint8_t iord_sdc_ctl() +{ + return 0; +} + +static void iowr_sdc_ctl(uint8_t val) +{ + sdc_ctl_wr(&sdc, val); +} + void create_window() { uint32_t mask; @@ -227,7 +253,7 @@ void event_loop() if (vdp_changed) { // To avoid overdrawing, we'll let the CPU run a bit to finish its // drawing operation. - emul_steps(100); + emul_steps(10000); draw_pixels(); } // A low tech way of checking when the window was closed. The proper way @@ -263,7 +289,7 @@ void event_loop() static void usage() { - fprintf(stderr, "Usage: ./sms [-k] /path/to/rom\n"); + fprintf(stderr, "Usage: ./sms [-k] [-c sdcard.img] /path/to/rom\n"); } int main(int argc, char *argv[]) @@ -272,12 +298,27 @@ int main(int argc, char *argv[]) usage(); return 1; } + vdp_init(&vdp); + vdp_changed = false; + ports_init(&ports); + pad_init(&pad, &ports.THA); + kbd_init(&kbd, &ports.THA); + sdc_init(&sdc); + int ch; - while ((ch = getopt(argc, argv, "k")) != -1) { + while ((ch = getopt(argc, argv, "kc:")) != -1) { switch (ch) { case 'k': use_kbd = true; break; + case 'c': + fprintf(stderr, "Setting up SD card image with %s\n", optarg); + sdc.fp = fopen(optarg, "r+"); + if (sdc.fp == NULL) { + fprintf(stderr, "Can't open file\n"); + return 1; + } + break; } } if (optind != argc-1) { @@ -301,16 +342,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "ROM image too large.\n"); return 1; } - vdp_init(&vdp); - vdp_changed = false; - ports_init(&ports); - pad_init(&pad, &ports.THA); - kbd_init(&kbd, &ports.THA); if (use_kbd) { ports.portA_rd = iord_kbd; } else { ports.portA_rd = iord_pad; } + m->iord[VDP_CMD_PORT] = iord_vdp_cmd; m->iord[VDP_DATA_PORT] = iord_vdp_data; m->iord[PORTS_IO1_PORT] = iord_ports_io1; @@ -319,11 +356,19 @@ int main(int argc, char *argv[]) m->iowr[VDP_CMD_PORT] = iowr_vdp_cmd; m->iowr[VDP_DATA_PORT] = iowr_vdp_data; m->iowr[PORTS_CTL_PORT] = iowr_ports_ctl; + m->iord[SDC_SPI] = iord_sdc_spi; + m->iowr[SDC_SPI] = iowr_sdc_spi; + m->iord[SDC_CTL] = iord_sdc_ctl; + m->iowr[SDC_CTL] = iowr_sdc_ctl; + conn = xcb_connect(NULL, NULL); screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; create_window(); draw_pixels(); event_loop(); emul_printdebug(); + if (sdc.fp) { + fclose(sdc.fp); + } return 0; } diff --git a/recipes/rc2014/sdcard.md b/recipes/rc2014/sdcard.md index ad9f7f7..adb02b9 100644 --- a/recipes/rc2014/sdcard.md +++ b/recipes/rc2014/sdcard.md @@ -84,7 +84,7 @@ and `SPI_CTL`, which are respectively `4` and `5` in our relay design. You also need to tell the SDC subsystem which SPI device to activate by defining the `SDC_DEVID` (1, 2, 4, 8 for device 0, 1, 2 or 3) -You can then load the driver with `616 LOAD`. This driver provides +You can then load the driver with `419 LOAD`. This driver provides `(spix)` and `(spie)` which are then used in the SDC driver. The SDC driver is at B420. It gives you a load range. This means that what