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...
This commit is contained in:
parent
490eceab6d
commit
6947fea2a8
4
blk/001
4
blk/001
@ -6,6 +6,6 @@ MASTER INDEX
|
|||||||
160 AVR SPI programmer
|
160 AVR SPI programmer
|
||||||
170-259 unused 260 Cross compilation
|
170-259 unused 260 Cross compilation
|
||||||
280 Z80 boot code 350 Core words
|
280 Z80 boot code 350 Core words
|
||||||
410 PS/2 keyboard subsystem 420 SD Card subsystem
|
410 PS/2 keyboard subsystem 418 Z80 SPI Relay driver
|
||||||
440 8086 boot code
|
420 SD Card subsystem 440 8086 boot code
|
||||||
470-519 unused 520 Fonts
|
470-519 unused 520 Fonts
|
||||||
|
@ -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
|
returns 0 if the device is ready or 1 if it's still running an
|
||||||
exchange. Writing to SPI_DATA initiates an exchange.
|
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".
|
@ -1,7 +1,7 @@
|
|||||||
TARGETS = forth rc2014 sms ti84
|
TARGETS = forth rc2014 sms ti84
|
||||||
OBJS = emul.o z80.o
|
OBJS = emul.o z80.o
|
||||||
RC2014_OBJS = $(OBJS) sio.o acia.o sdc.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
|
TI84_OBJS = $(OBJS) t6a04.o ti84_kbd.o
|
||||||
CDIR = ../../cvm
|
CDIR = ../../cvm
|
||||||
STAGE = $(CDIR)/stage
|
STAGE = $(CDIR)/stage
|
||||||
|
@ -61,6 +61,8 @@ pad are:
|
|||||||
If your ROM is configured with PS/2 keyboard input, run this emulator with the
|
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.
|
`-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.
|
In both cases (pad or keyboard), only port A emulation is supported.
|
||||||
|
|
||||||
Press ESC to quit.
|
Press ESC to quit.
|
||||||
|
@ -143,6 +143,10 @@ int main(int argc, char *argv[])
|
|||||||
case 'c':
|
case 'c':
|
||||||
fprintf(stderr, "Setting up SD card image with %s\n", optarg);
|
fprintf(stderr, "Setting up SD card image with %s\n", optarg);
|
||||||
sdc.fp = fopen(optarg, "r+");
|
sdc.fp = fopen(optarg, "r+");
|
||||||
|
if (sdc.fp == NULL) {
|
||||||
|
fprintf(stderr, "Can't open file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "sms_ports.h"
|
#include "sms_ports.h"
|
||||||
#include "sms_pad.h"
|
#include "sms_pad.h"
|
||||||
#include "ps2_kbd.h"
|
#include "ps2_kbd.h"
|
||||||
|
#include "sdc.h"
|
||||||
|
|
||||||
#define RAMSTART 0xc000
|
#define RAMSTART 0xc000
|
||||||
#define VDP_CMD_PORT 0xbf
|
#define VDP_CMD_PORT 0xbf
|
||||||
@ -19,6 +20,8 @@
|
|||||||
#define PORTS_CTL_PORT 0x3f
|
#define PORTS_CTL_PORT 0x3f
|
||||||
#define PORTS_IO1_PORT 0xdc
|
#define PORTS_IO1_PORT 0xdc
|
||||||
#define PORTS_IO2_PORT 0xdd
|
#define PORTS_IO2_PORT 0xdd
|
||||||
|
#define SDC_CTL 0x05
|
||||||
|
#define SDC_SPI 0x04
|
||||||
#define MAX_ROMSIZE 0x8000
|
#define MAX_ROMSIZE 0x8000
|
||||||
|
|
||||||
static xcb_connection_t *conn;
|
static xcb_connection_t *conn;
|
||||||
@ -39,6 +42,7 @@ static Ports ports;
|
|||||||
static Pad pad;
|
static Pad pad;
|
||||||
static Kbd kbd;
|
static Kbd kbd;
|
||||||
static bool use_kbd = false;
|
static bool use_kbd = false;
|
||||||
|
static SDC sdc;
|
||||||
|
|
||||||
static uint8_t iord_vdp_cmd()
|
static uint8_t iord_vdp_cmd()
|
||||||
{
|
{
|
||||||
@ -86,6 +90,28 @@ static void iowr_ports_ctl(uint8_t val)
|
|||||||
ports_ctl_wr(&ports, 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()
|
void create_window()
|
||||||
{
|
{
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
@ -227,7 +253,7 @@ void event_loop()
|
|||||||
if (vdp_changed) {
|
if (vdp_changed) {
|
||||||
// To avoid overdrawing, we'll let the CPU run a bit to finish its
|
// To avoid overdrawing, we'll let the CPU run a bit to finish its
|
||||||
// drawing operation.
|
// drawing operation.
|
||||||
emul_steps(100);
|
emul_steps(10000);
|
||||||
draw_pixels();
|
draw_pixels();
|
||||||
}
|
}
|
||||||
// A low tech way of checking when the window was closed. The proper way
|
// A low tech way of checking when the window was closed. The proper way
|
||||||
@ -263,7 +289,7 @@ void event_loop()
|
|||||||
|
|
||||||
static void usage()
|
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[])
|
int main(int argc, char *argv[])
|
||||||
@ -272,12 +298,27 @@ int main(int argc, char *argv[])
|
|||||||
usage();
|
usage();
|
||||||
return 1;
|
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;
|
int ch;
|
||||||
while ((ch = getopt(argc, argv, "k")) != -1) {
|
while ((ch = getopt(argc, argv, "kc:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'k':
|
case 'k':
|
||||||
use_kbd = true;
|
use_kbd = true;
|
||||||
break;
|
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) {
|
if (optind != argc-1) {
|
||||||
@ -301,16 +342,12 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "ROM image too large.\n");
|
fprintf(stderr, "ROM image too large.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
vdp_init(&vdp);
|
|
||||||
vdp_changed = false;
|
|
||||||
ports_init(&ports);
|
|
||||||
pad_init(&pad, &ports.THA);
|
|
||||||
kbd_init(&kbd, &ports.THA);
|
|
||||||
if (use_kbd) {
|
if (use_kbd) {
|
||||||
ports.portA_rd = iord_kbd;
|
ports.portA_rd = iord_kbd;
|
||||||
} else {
|
} else {
|
||||||
ports.portA_rd = iord_pad;
|
ports.portA_rd = iord_pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->iord[VDP_CMD_PORT] = iord_vdp_cmd;
|
m->iord[VDP_CMD_PORT] = iord_vdp_cmd;
|
||||||
m->iord[VDP_DATA_PORT] = iord_vdp_data;
|
m->iord[VDP_DATA_PORT] = iord_vdp_data;
|
||||||
m->iord[PORTS_IO1_PORT] = iord_ports_io1;
|
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_CMD_PORT] = iowr_vdp_cmd;
|
||||||
m->iowr[VDP_DATA_PORT] = iowr_vdp_data;
|
m->iowr[VDP_DATA_PORT] = iowr_vdp_data;
|
||||||
m->iowr[PORTS_CTL_PORT] = iowr_ports_ctl;
|
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);
|
conn = xcb_connect(NULL, NULL);
|
||||||
screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
|
||||||
create_window();
|
create_window();
|
||||||
draw_pixels();
|
draw_pixels();
|
||||||
event_loop();
|
event_loop();
|
||||||
emul_printdebug();
|
emul_printdebug();
|
||||||
|
if (sdc.fp) {
|
||||||
|
fclose(sdc.fp);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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
|
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)
|
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.
|
`(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
|
The SDC driver is at B420. It gives you a load range. This means that what
|
||||||
|
Loading…
Reference in New Issue
Block a user