1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-27 11:58:05 +11:00

tools/emul: deduplicate a little bit of C code

This commit is contained in:
Virgil Dupras 2019-12-02 16:35:49 -05:00
parent 15e44ec524
commit 2f07d849a8
8 changed files with 369 additions and 324 deletions

View File

@ -8,3 +8,4 @@
/cfsin/ed /cfsin/ed
/cfsin/basic /cfsin/basic
/cfsin/user.h /cfsin/user.h
*.o

View File

@ -31,15 +31,18 @@ zasm/zasm-bin.h: zasm/zasm.bin
shell/shell: shell/shell.c libz80/libz80.o shell/kernel-bin.h shell/shell: shell/shell.c libz80/libz80.o shell/kernel-bin.h
bshell/shell: bshell/shell.c libz80/libz80.o bshell/shell-bin.h bshell/shell: bshell/shell.c libz80/libz80.o bshell/shell-bin.h
$(ZASMBIN): zasm/zasm.c libz80/libz80.o zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK) $(ZASMBIN): zasm/zasm.c emul.o libz80/libz80.o zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK)
runbin/runbin: runbin/runbin.c libz80/libz80.o runbin/runbin: runbin/runbin.c libz80/libz80.o
$(TARGETS): $(TARGETS):
$(CC) $< libz80/libz80.o -o $@ $(CC) $< emul.o libz80/libz80.o -o $@
libz80/libz80.o: libz80/z80.c libz80/libz80.o: libz80/z80.c
$(MAKE) -C libz80/codegen opcodes $(MAKE) -C libz80/codegen opcodes
$(CC) -Wall -ansi -g -c -o libz80/libz80.o libz80/z80.c $(CC) -Wall -ansi -g -c -o libz80/libz80.o libz80/z80.c
emul.o: emul.c
$(CC) -c -o emul.o emul.c
$(CFSPACK): $(CFSPACK):
$(MAKE) -C ../cfspack $(MAKE) -C ../cfspack
@ -57,4 +60,4 @@ updatebootstrap: $(ZASMBIN) $(INCCFS)
.PHONY: clean .PHONY: clean
clean: clean:
rm -f $(TARGETS) $(SHELLAPPS) zasm/*-bin.h shell/*-bin.h rm -f $(TARGETS) $(SHELLAPPS) emul.o zasm/*-bin.h shell/*-bin.h

View File

@ -1,7 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <termios.h> #include <termios.h>
#include "../libz80/z80.h" #include "../emul.h"
#include "shell-bin.h" #include "shell-bin.h"
/* Collapse OS shell with filesystem /* Collapse OS shell with filesystem
@ -39,8 +39,6 @@
// 3 means incomplete addr setting // 3 means incomplete addr setting
#define FS_ADDR_PORT 0x02 #define FS_ADDR_PORT 0x02
static Z80Context cpu;
static uint8_t mem[0x10000] = {0};
static uint8_t fsdev[MAX_FSDEV_SIZE] = {0}; static uint8_t fsdev[MAX_FSDEV_SIZE] = {0};
static uint32_t fsdev_size = 0; static uint32_t fsdev_size = 0;
static uint32_t fsdev_ptr = 0; static uint32_t fsdev_ptr = 0;
@ -48,105 +46,93 @@ static uint32_t fsdev_ptr = 0;
static int fsdev_addr_lvl = 0; static int fsdev_addr_lvl = 0;
static int running; static int running;
static uint8_t io_read(int unused, uint16_t addr) static uint8_t iord_stdio()
{ {
addr &= 0xff; int c = getchar();
if (addr == STDIO_PORT) { if (c == EOF) {
int c = getchar(); running = 0;
if (c == EOF) { }
running = 0; return (uint8_t)c;
} }
return (uint8_t)c;
} else if (addr == FS_DATA_PORT) { static uint8_t iord_fsdata()
if (fsdev_addr_lvl != 0) { {
fprintf(stderr, "Reading FSDEV in the middle of an addr op (%d)\n", fsdev_ptr); if (fsdev_addr_lvl != 0) {
return 0; fprintf(stderr, "Reading FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
} return 0;
if (fsdev_ptr < fsdev_size) { }
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Reading FSDEV at offset %d\n", fsdev_ptr); fprintf(stderr, "Reading FSDEV at offset %d\n", fsdev_ptr);
#endif #endif
return fsdev[fsdev_ptr]; return fsdev[fsdev_ptr];
} else {
// don't warn when ==, we're not out of bounds, just at the edge.
if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV read at %d\n", fsdev_ptr);
}
return 0;
}
} else if (addr == FS_ADDR_PORT) {
if (fsdev_addr_lvl != 0) {
return 3;
} else if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV addr request at %d / %d\n", fsdev_ptr, fsdev_size);
return 2;
} else if (fsdev_ptr == fsdev_size) {
return 1;
} else {
return 0;
}
} else { } else {
fprintf(stderr, "Out of bounds I/O read: %d\n", addr); // don't warn when ==, we're not out of bounds, just at the edge.
if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV read at %d\n", fsdev_ptr);
}
return 0; return 0;
} }
} }
static void io_write(int unused, uint16_t addr, uint8_t val) static uint8_t iord_fsaddr()
{ {
addr &= 0xff; if (fsdev_addr_lvl != 0) {
if (addr == STDIO_PORT) { return 3;
if (val == 0x04) { // CTRL+D } else if (fsdev_ptr > fsdev_size) {
running = 0; fprintf(stderr, "Out of bounds FSDEV addr request at %d / %d\n", fsdev_ptr, fsdev_size);
} else { return 2;
putchar(val); } else if (fsdev_ptr == fsdev_size) {
} return 1;
} else if (addr == FS_DATA_PORT) {
if (fsdev_addr_lvl != 0) {
fprintf(stderr, "Writing to FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
return;
}
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG
fprintf(stderr, "Writing to FSDEV (%d)\n", fsdev_ptr);
#endif
fsdev[fsdev_ptr] = val;
} else if ((fsdev_ptr == fsdev_size) && (fsdev_ptr < MAX_FSDEV_SIZE)) {
// We're at the end of fsdev, grow it
fsdev[fsdev_ptr] = val;
fsdev_size++;
#ifdef DEBUG
fprintf(stderr, "Growing FSDEV (%d)\n", fsdev_ptr);
#endif
} else {
fprintf(stderr, "Out of bounds FSDEV write at %d\n", fsdev_ptr);
}
} else if (addr == FS_ADDR_PORT) {
if (fsdev_addr_lvl == 0) {
fsdev_ptr = val << 16;
fsdev_addr_lvl = 1;
} else if (fsdev_addr_lvl == 1) {
fsdev_ptr |= val << 8;
fsdev_addr_lvl = 2;
} else {
fsdev_ptr |= val;
fsdev_addr_lvl = 0;
}
} else { } else {
fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val); return 0;
} }
} }
static uint8_t mem_read(int unused, uint16_t addr) static void iowr_stdio(uint8_t val)
{ {
return mem[addr]; if (val == 0x04) { // CTRL+D
running = 0;
} else {
putchar(val);
}
} }
static void mem_write(int unused, uint16_t addr, uint8_t val) static void iowr_fsdata(uint8_t val)
{ {
if (addr < RAMSTART) { if (fsdev_addr_lvl != 0) {
fprintf(stderr, "Writing to ROM (%d)!\n", addr); fprintf(stderr, "Writing to FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
return;
}
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG
fprintf(stderr, "Writing to FSDEV (%d)\n", fsdev_ptr);
#endif
fsdev[fsdev_ptr] = val;
} else if ((fsdev_ptr == fsdev_size) && (fsdev_ptr < MAX_FSDEV_SIZE)) {
// We're at the end of fsdev, grow it
fsdev[fsdev_ptr] = val;
fsdev_size++;
#ifdef DEBUG
fprintf(stderr, "Growing FSDEV (%d)\n", fsdev_ptr);
#endif
} else {
fprintf(stderr, "Out of bounds FSDEV write at %d\n", fsdev_ptr);
}
}
static void iowr_fsaddr(uint8_t val)
{
if (fsdev_addr_lvl == 0) {
fsdev_ptr = val << 16;
fsdev_addr_lvl = 1;
} else if (fsdev_addr_lvl == 1) {
fsdev_ptr |= val << 8;
fsdev_addr_lvl = 2;
} else {
fsdev_ptr |= val;
fsdev_addr_lvl = 0;
} }
mem[addr] = val;
} }
int main() int main()
@ -179,21 +165,22 @@ int main()
tcsetattr(0, TCSAFLUSH, &termInfo); tcsetattr(0, TCSAFLUSH, &termInfo);
Machine *m = emul_init();
m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio;
m->iord[FS_DATA_PORT] = iord_fsdata;
m->iord[FS_ADDR_PORT] = iord_fsaddr;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[FS_DATA_PORT] = iowr_fsdata;
m->iowr[FS_ADDR_PORT] = iowr_fsaddr;
// initialize memory // initialize memory
for (int i=0; i<sizeof(KERNEL); i++) { for (int i=0; i<sizeof(KERNEL); i++) {
mem[i] = KERNEL[i]; m->mem[i] = KERNEL[i];
} }
// Run! // Run!
running = 1; running = 1;
Z80RESET(&cpu);
cpu.ioRead = io_read;
cpu.ioWrite = io_write;
cpu.memRead = mem_read;
cpu.memWrite = mem_write;
while (running && !cpu.halted) { while (running && emul_step());
Z80Execute(&cpu);
}
printf("Done!\n"); printf("Done!\n");
termInfo.c_lflag |= ECHO; termInfo.c_lflag |= ECHO;

77
tools/emul/emul.c Normal file
View File

@ -0,0 +1,77 @@
/* Common code between shell, zasm and runbin.
They all run on the same kind of virtual machine: A z80 CPU, 64K of RAM/ROM.
*/
#include <string.h>
#include "emul.h"
static Machine m;
static uint8_t io_read(int unused, uint16_t addr)
{
addr &= 0xff;
IORD fn = m.iord[addr];
if (fn != NULL) {
return fn();
} else {
fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
return 0;
}
}
static void io_write(int unused, uint16_t addr, uint8_t val)
{
addr &= 0xff;
IOWR fn = m.iowr[addr];
if (fn != NULL) {
fn(val);
} else {
fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val);
}
}
static uint8_t mem_read(int unused, uint16_t addr)
{
return m.mem[addr];
}
static void mem_write(int unused, uint16_t addr, uint8_t val)
{
if (addr < m.ramstart) {
fprintf(stderr, "Writing to ROM (%d)!\n", addr);
}
m.mem[addr] = val;
}
Machine* emul_init()
{
memset(m.mem, 0, 0x10000);
m.ramstart = 0;
for (int i=0; i<0x100; i++) {
m.iord[i] = NULL;
m.iowr[i] = NULL;
}
Z80RESET(&m.cpu);
m.cpu.memRead = mem_read;
m.cpu.memWrite = mem_write;
m.cpu.ioRead = io_read;
m.cpu.ioWrite = io_write;
return &m;
}
bool emul_step()
{
if (!m.cpu.halted) {
Z80Execute(&m.cpu);
return true;
} else {
return false;
}
}
void emul_loop()
{
while (emul_step());
}

22
tools/emul/emul.h Normal file
View File

@ -0,0 +1,22 @@
#include <stdint.h>
#include <stdbool.h>
#include "libz80/z80.h"
typedef uint8_t (*IORD) ();
typedef void (*IOWR) (uint8_t data);
typedef struct {
Z80Context cpu;
uint8_t mem[0x10000];
// Set to non-zero to specify where ROM ends. Any memory write attempt
// below ramstart will trigger a warning.
uint16_t ramstart;
// Array of 0x100 function pointers to IO read and write routines. Leave to
// NULL when IO port is unhandled.
IORD iord[0x100];
IOWR iowr[0x100];
} Machine;
Machine* emul_init();
bool emul_step();
void emul_loop();

View File

@ -1,44 +1,19 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "../libz80/z80.h" #include "../emul.h"
/* runbin loads binary from stdin directly in memory address 0 then runs it /* runbin loads binary from stdin directly in memory address 0 then runs it
* until it halts. The return code is the value of the register A at halt time. * until it halts. The return code is the value of the register A at halt time.
*/ */
static Z80Context cpu;
static uint8_t mem[0x10000];
static uint8_t io_read(int unused, uint16_t addr)
{
addr &= 0xff;
fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
return 0;
}
static void io_write(int unused, uint16_t addr, uint8_t val)
{
addr &= 0xff;
fprintf(stderr, "Out of bounds I/O write: %d / %d\n", addr, val);
}
static uint8_t mem_read(int unused, uint16_t addr)
{
return mem[addr];
}
static void mem_write(int unused, uint16_t addr, uint8_t val)
{
mem[addr] = val;
}
int main() int main()
{ {
Machine *m = emul_init();
// read stdin in mem // read stdin in mem
int i = 0; int i = 0;
int c = getchar(); int c = getchar();
while (c != EOF) { while (c != EOF) {
mem[i] = c & 0xff; m->mem[i] = c & 0xff;
i++; i++;
c = getchar(); c = getchar();
} }
@ -46,15 +21,7 @@ int main()
fprintf(stderr, "No input, aborting\n"); fprintf(stderr, "No input, aborting\n");
return 1; return 1;
} }
Z80RESET(&cpu); emul_loop();
cpu.ioRead = io_read; return m->cpu.R1.br.A;
cpu.ioWrite = io_write;
cpu.memRead = mem_read;
cpu.memWrite = mem_write;
while (!cpu.halted) {
Z80Execute(&cpu);
}
return cpu.R1.br.A;
} }

View File

@ -1,7 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <termios.h> #include <termios.h>
#include "../libz80/z80.h" #include "../emul.h"
#include "kernel-bin.h" #include "kernel-bin.h"
/* Collapse OS shell with filesystem /* Collapse OS shell with filesystem
@ -39,8 +39,6 @@
// 3 means incomplete addr setting // 3 means incomplete addr setting
#define FS_ADDR_PORT 0x02 #define FS_ADDR_PORT 0x02
static Z80Context cpu;
static uint8_t mem[0x10000] = {0};
static uint8_t fsdev[MAX_FSDEV_SIZE] = {0}; static uint8_t fsdev[MAX_FSDEV_SIZE] = {0};
static uint32_t fsdev_size = 0; static uint32_t fsdev_size = 0;
static uint32_t fsdev_ptr = 0; static uint32_t fsdev_ptr = 0;
@ -48,105 +46,93 @@ static uint32_t fsdev_ptr = 0;
static int fsdev_addr_lvl = 0; static int fsdev_addr_lvl = 0;
static int running; static int running;
static uint8_t io_read(int unused, uint16_t addr) static uint8_t iord_stdio()
{ {
addr &= 0xff; int c = getchar();
if (addr == STDIO_PORT) { if (c == EOF) {
int c = getchar(); running = 0;
if (c == EOF) { }
running = 0; return (uint8_t)c;
} }
return (uint8_t)c;
} else if (addr == FS_DATA_PORT) { static uint8_t iord_fsdata()
if (fsdev_addr_lvl != 0) { {
fprintf(stderr, "Reading FSDEV in the middle of an addr op (%d)\n", fsdev_ptr); if (fsdev_addr_lvl != 0) {
return 0; fprintf(stderr, "Reading FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
} return 0;
if (fsdev_ptr < fsdev_size) { }
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Reading FSDEV at offset %d\n", fsdev_ptr); fprintf(stderr, "Reading FSDEV at offset %d\n", fsdev_ptr);
#endif #endif
return fsdev[fsdev_ptr]; return fsdev[fsdev_ptr];
} else {
// don't warn when ==, we're not out of bounds, just at the edge.
if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV read at %d\n", fsdev_ptr);
}
return 0;
}
} else if (addr == FS_ADDR_PORT) {
if (fsdev_addr_lvl != 0) {
return 3;
} else if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV addr request at %d / %d\n", fsdev_ptr, fsdev_size);
return 2;
} else if (fsdev_ptr == fsdev_size) {
return 1;
} else {
return 0;
}
} else { } else {
fprintf(stderr, "Out of bounds I/O read: %d\n", addr); // don't warn when ==, we're not out of bounds, just at the edge.
if (fsdev_ptr > fsdev_size) {
fprintf(stderr, "Out of bounds FSDEV read at %d\n", fsdev_ptr);
}
return 0; return 0;
} }
} }
static void io_write(int unused, uint16_t addr, uint8_t val) static uint8_t iord_fsaddr()
{ {
addr &= 0xff; if (fsdev_addr_lvl != 0) {
if (addr == STDIO_PORT) { return 3;
if (val == 0x04) { // CTRL+D } else if (fsdev_ptr > fsdev_size) {
running = 0; fprintf(stderr, "Out of bounds FSDEV addr request at %d / %d\n", fsdev_ptr, fsdev_size);
} else { return 2;
putchar(val); } else if (fsdev_ptr == fsdev_size) {
} return 1;
} else if (addr == FS_DATA_PORT) {
if (fsdev_addr_lvl != 0) {
fprintf(stderr, "Writing to FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
return;
}
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG
fprintf(stderr, "Writing to FSDEV (%d)\n", fsdev_ptr);
#endif
fsdev[fsdev_ptr] = val;
} else if ((fsdev_ptr == fsdev_size) && (fsdev_ptr < MAX_FSDEV_SIZE)) {
// We're at the end of fsdev, grow it
fsdev[fsdev_ptr] = val;
fsdev_size++;
#ifdef DEBUG
fprintf(stderr, "Growing FSDEV (%d)\n", fsdev_ptr);
#endif
} else {
fprintf(stderr, "Out of bounds FSDEV write at %d\n", fsdev_ptr);
}
} else if (addr == FS_ADDR_PORT) {
if (fsdev_addr_lvl == 0) {
fsdev_ptr = val << 16;
fsdev_addr_lvl = 1;
} else if (fsdev_addr_lvl == 1) {
fsdev_ptr |= val << 8;
fsdev_addr_lvl = 2;
} else {
fsdev_ptr |= val;
fsdev_addr_lvl = 0;
}
} else { } else {
fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val); return 0;
} }
} }
static uint8_t mem_read(int unused, uint16_t addr) static void iowr_stdio(uint8_t val)
{ {
return mem[addr]; if (val == 0x04) { // CTRL+D
running = 0;
} else {
putchar(val);
}
} }
static void mem_write(int unused, uint16_t addr, uint8_t val) static void iowr_fsdata(uint8_t val)
{ {
if (addr < RAMSTART) { if (fsdev_addr_lvl != 0) {
fprintf(stderr, "Writing to ROM (%d)!\n", addr); fprintf(stderr, "Writing to FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
return;
}
if (fsdev_ptr < fsdev_size) {
#ifdef DEBUG
fprintf(stderr, "Writing to FSDEV (%d)\n", fsdev_ptr);
#endif
fsdev[fsdev_ptr] = val;
} else if ((fsdev_ptr == fsdev_size) && (fsdev_ptr < MAX_FSDEV_SIZE)) {
// We're at the end of fsdev, grow it
fsdev[fsdev_ptr] = val;
fsdev_size++;
#ifdef DEBUG
fprintf(stderr, "Growing FSDEV (%d)\n", fsdev_ptr);
#endif
} else {
fprintf(stderr, "Out of bounds FSDEV write at %d\n", fsdev_ptr);
}
}
static void iowr_fsaddr(uint8_t val)
{
if (fsdev_addr_lvl == 0) {
fsdev_ptr = val << 16;
fsdev_addr_lvl = 1;
} else if (fsdev_addr_lvl == 1) {
fsdev_ptr |= val << 8;
fsdev_addr_lvl = 2;
} else {
fsdev_ptr |= val;
fsdev_addr_lvl = 0;
} }
mem[addr] = val;
} }
int main() int main()
@ -179,21 +165,22 @@ int main()
tcsetattr(0, TCSAFLUSH, &termInfo); tcsetattr(0, TCSAFLUSH, &termInfo);
Machine *m = emul_init();
m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio;
m->iord[FS_DATA_PORT] = iord_fsdata;
m->iord[FS_ADDR_PORT] = iord_fsaddr;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[FS_DATA_PORT] = iowr_fsdata;
m->iowr[FS_ADDR_PORT] = iowr_fsaddr;
// initialize memory // initialize memory
for (int i=0; i<sizeof(KERNEL); i++) { for (int i=0; i<sizeof(KERNEL); i++) {
mem[i] = KERNEL[i]; m->mem[i] = KERNEL[i];
} }
// Run! // Run!
running = 1; running = 1;
Z80RESET(&cpu);
cpu.ioRead = io_read;
cpu.ioWrite = io_write;
cpu.memRead = mem_read;
cpu.memWrite = mem_write;
while (running && !cpu.halted) { while (running && emul_step());
Z80Execute(&cpu);
}
printf("Done!\n"); printf("Done!\n");
termInfo.c_lflag |= ECHO; termInfo.c_lflag |= ECHO;

View File

@ -1,7 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../libz80/z80.h" #include "../emul.h"
#include "kernel-bin.h" #include "kernel-bin.h"
#include "zasm-bin.h" #include "zasm-bin.h"
@ -48,8 +48,6 @@
// you want to spit this content to stderr. // you want to spit this content to stderr.
//#define VERBOSE //#define VERBOSE
static Z80Context cpu;
static uint8_t mem[0x10000];
// STDIN buffer, allows us to seek and tell // STDIN buffer, allows us to seek and tell
static uint8_t inpt[STDIN_BUFSIZE]; static uint8_t inpt[STDIN_BUFSIZE];
static int inpt_size; static int inpt_size;
@ -61,100 +59,100 @@ static uint32_t fsdev_size = 0;
static uint32_t fsdev_ptr = 0; static uint32_t fsdev_ptr = 0;
static uint8_t fsdev_seek_tell_cnt = 0; static uint8_t fsdev_seek_tell_cnt = 0;
static uint8_t io_read(int unused, uint16_t addr) static uint8_t iord_stdio()
{ {
addr &= 0xff; if (inpt_ptr < inpt_size) {
if (addr == STDIO_PORT) { return inpt[inpt_ptr++];
if (inpt_ptr < inpt_size) {
return inpt[inpt_ptr++];
} else {
return 0;
}
} else if (addr == STDIN_SEEK_PORT) {
if (middle_of_seek_tell) {
middle_of_seek_tell = 0;
return inpt_ptr & 0xff;
} else {
#ifdef DEBUG
fprintf(stderr, "tell %d\n", inpt_ptr);
#endif
middle_of_seek_tell = 1;
return inpt_ptr >> 8;
}
} else if (addr == FS_DATA_PORT) {
if (fsdev_ptr < fsdev_size) {
return fsdev[fsdev_ptr++];
} else {
return 0;
}
} else if (addr == FS_SEEK_PORT) {
if (fsdev_seek_tell_cnt != 0) {
return fsdev_seek_tell_cnt;
} else if (fsdev_ptr >= fsdev_size) {
return 1;
} else {
return 0;
}
} else { } else {
fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
return 0; return 0;
} }
} }
static void io_write(int unused, uint16_t addr, uint8_t val) static uint8_t iord_stdin_seek()
{ {
addr &= 0xff; if (middle_of_seek_tell) {
if (addr == STDIO_PORT) { middle_of_seek_tell = 0;
// When mem-dumping, we don't output regular stuff. return inpt_ptr & 0xff;
#ifndef MEMDUMP
putchar(val);
#endif
} else if (addr == STDIN_SEEK_PORT) {
if (middle_of_seek_tell) {
inpt_ptr |= val;
middle_of_seek_tell = 0;
#ifdef DEBUG
fprintf(stderr, "seek %d\n", inpt_ptr);
#endif
} else {
inpt_ptr = (val << 8) & 0xff00;
middle_of_seek_tell = 1;
}
} else if (addr == FS_DATA_PORT) {
if (fsdev_ptr < fsdev_size) {
fsdev[fsdev_ptr++] = val;
}
} else if (addr == FS_SEEK_PORT) {
if (fsdev_seek_tell_cnt == 0) {
fsdev_ptr = val << 16;
fsdev_seek_tell_cnt = 1;
} else if (fsdev_seek_tell_cnt == 1) {
fsdev_ptr |= val << 8;
fsdev_seek_tell_cnt = 2;
} else {
fsdev_ptr |= val;
fsdev_seek_tell_cnt = 0;
#ifdef DEBUG
fprintf(stderr, "FS seek %d\n", fsdev_ptr);
#endif
}
} else if (addr == STDERR_PORT) {
#ifdef VERBOSE
fputc(val, stderr);
#endif
} else { } else {
fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val); #ifdef DEBUG
fprintf(stderr, "tell %d\n", inpt_ptr);
#endif
middle_of_seek_tell = 1;
return inpt_ptr >> 8;
} }
} }
static uint8_t mem_read(int unused, uint16_t addr) static uint8_t iord_fsdata()
{ {
return mem[addr]; if (fsdev_ptr < fsdev_size) {
return fsdev[fsdev_ptr++];
} else {
return 0;
}
} }
static void mem_write(int unused, uint16_t addr, uint8_t val) static uint8_t iord_fsseek()
{ {
mem[addr] = val; if (fsdev_seek_tell_cnt != 0) {
return fsdev_seek_tell_cnt;
} else if (fsdev_ptr >= fsdev_size) {
return 1;
} else {
return 0;
}
}
static void iowr_stdio(uint8_t val)
{
// When mem-dumping, we don't output regular stuff.
#ifndef MEMDUMP
putchar(val);
#endif
}
static void iowr_stdin_seek(uint8_t val)
{
if (middle_of_seek_tell) {
inpt_ptr |= val;
middle_of_seek_tell = 0;
#ifdef DEBUG
fprintf(stderr, "seek %d\n", inpt_ptr);
#endif
} else {
inpt_ptr = (val << 8) & 0xff00;
middle_of_seek_tell = 1;
}
}
static void iowr_fsdata(uint8_t val)
{
if (fsdev_ptr < fsdev_size) {
fsdev[fsdev_ptr++] = val;
}
}
static void iowr_fsseek(uint8_t val)
{
if (fsdev_seek_tell_cnt == 0) {
fsdev_ptr = val << 16;
fsdev_seek_tell_cnt = 1;
} else if (fsdev_seek_tell_cnt == 1) {
fsdev_ptr |= val << 8;
fsdev_seek_tell_cnt = 2;
} else {
fsdev_ptr |= val;
fsdev_seek_tell_cnt = 0;
#ifdef DEBUG
fprintf(stderr, "FS seek %d\n", fsdev_ptr);
#endif
}
}
static void iowr_stderr(uint8_t val)
{
#ifdef VERBOSE
fputc(val, stderr);
#endif
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -163,12 +161,22 @@ int main(int argc, char *argv[])
fprintf(stderr, "Too many args\n"); fprintf(stderr, "Too many args\n");
return 1; return 1;
} }
Machine *m = emul_init();
m->iord[STDIO_PORT] = iord_stdio;
m->iord[STDIN_SEEK_PORT] = iord_stdin_seek;
m->iord[FS_DATA_PORT] = iord_fsdata;
m->iord[FS_SEEK_PORT] = iord_fsseek;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[STDIN_SEEK_PORT] = iowr_stdin_seek;
m->iowr[FS_DATA_PORT] = iowr_fsdata;
m->iowr[FS_SEEK_PORT] = iowr_fsseek;
m->iowr[STDERR_PORT] = iowr_stderr;
// initialize memory // initialize memory
for (int i=0; i<sizeof(KERNEL); i++) { for (int i=0; i<sizeof(KERNEL); i++) {
mem[i] = KERNEL[i]; m->mem[i] = KERNEL[i];
} }
for (int i=0; i<sizeof(USERSPACE); i++) { for (int i=0; i<sizeof(USERSPACE); i++) {
mem[i+USER_CODE] = USERSPACE[i]; m->mem[i+USER_CODE] = USERSPACE[i];
} }
char *init_org = "00"; char *init_org = "00";
if (argc >= 2) { if (argc >= 2) {
@ -178,8 +186,8 @@ int main(int argc, char *argv[])
} }
} }
// glue.asm knows that it needs to fetch these arguments at this address. // glue.asm knows that it needs to fetch these arguments at this address.
mem[0xff00] = init_org[0]; m->mem[0xff00] = init_org[0];
mem[0xff01] = init_org[1]; m->mem[0xff01] = init_org[1];
fsdev_size = 0; fsdev_size = 0;
if (argc == 3) { if (argc == 3) {
FILE *fp = fopen(argv[2], "r"); FILE *fp = fopen(argv[2], "r");
@ -209,25 +217,18 @@ int main(int argc, char *argv[])
} }
inpt_size = inpt_ptr; inpt_size = inpt_ptr;
inpt_ptr = 0; inpt_ptr = 0;
Z80RESET(&cpu);
cpu.ioRead = io_read;
cpu.ioWrite = io_write;
cpu.memRead = mem_read;
cpu.memWrite = mem_write;
while (!cpu.halted) { emul_loop();
Z80Execute(&cpu);
}
#ifdef MEMDUMP #ifdef MEMDUMP
for (int i=0; i<0x10000; i++) { for (int i=0; i<0x10000; i++) {
putchar(mem[i]); putchar(mem[i]);
} }
#endif #endif
fflush(stdout); fflush(stdout);
int res = cpu.R1.br.A; int res = m->cpu.R1.br.A;
if (res != 0) { if (res != 0) {
int lineno = cpu.R1.wr.HL; int lineno = m->cpu.R1.wr.HL;
int inclineno = cpu.R1.wr.DE; int inclineno = m->cpu.R1.wr.DE;
if (inclineno) { if (inclineno) {
fprintf( fprintf(
stderr, stderr,