1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-02 04:20:55 +11:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Virgil Dupras
c0b7b45570 emul: fix backspace
it was broken in the move to ncurses.
2020-05-23 14:47:19 -04:00
Virgil Dupras
7f3e55cb51 emul: add live register stats in the corner 2020-05-23 14:42:36 -04:00
Virgil Dupras
08b0c56ff6 emul: run Collapse OS inside a limited, fixed window
This will allow us to implement AT-XY, paving the way to all sorts
of nice new things.
2020-05-23 14:23:03 -04:00
Virgil Dupras
1d4b75add2 emul: deduplicate some code 2020-05-23 10:08:40 -04:00
Virgil Dupras
93c6d150e2 emul: don't embed forth.bin in emul binaries
Read the contents of forth.bin at runtime. This allows us to get
rid of the bin2c tooling.
2020-05-23 09:54:26 -04:00
8 changed files with 124 additions and 172 deletions

View File

@ -1,6 +1,5 @@
TARGETS = forth stage blkfs TARGETS = forth stage blkfs
OBJS = emul.o libz80/libz80.o OBJS = emul.o libz80/libz80.o
BIN2C = ../tools/bin2c
BLKPACK = ../tools/blkpack BLKPACK = ../tools/blkpack
BLKUNPACK = ../tools/blkunpack BLKUNPACK = ../tools/blkunpack
@ -10,34 +9,29 @@ all: $(TARGETS)
$(BLKPACK): $(BLKPACK):
$(MAKE) -C ../tools $(MAKE) -C ../tools
.PHONY: $(BIN2C) $(BLKUNPACK) .PHONY: $(BLKUNPACK)
$(BIN2C): $(BLKPACK)
$(BLKUNPACK): $(BLKPACK) $(BLKUNPACK): $(BLKPACK)
# not dependent on forth.bin to avoid circular deps. stage: stage.c $(OBJS)
forth-bin.h: $(BIN2C) $(CC) stage.c $(OBJS) -o $@
$(BIN2C) KERNEL < forth.bin > $@
stage: stage.c $(OBJS) forth-bin.h
$(CC) stage.c -DBLKFS_PATH=\"`pwd`/blkfs\" $(OBJS) -o $@
blkfs: $(BLKPACK) blkfs: $(BLKPACK)
$(BLKPACK) ../blk > $@ $(BLKPACK) ../blk > $@
forth: forth.c $(OBJS) forth-bin.h forth: forth.c $(OBJS)
$(CC) forth.c -DBLKFS_PATH=\"`pwd`/blkfs\" $(OBJS) -lncurses -o $@ $(CC) forth.c $(OBJS) -lncurses -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 emul.o: emul.c
$(CC) -c -o emul.o emul.c $(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/blkfs\" -c -o emul.o emul.c
.PHONY: updatebootstrap .PHONY: updatebootstrap
updatebootstrap: stage xcomp.fs pack updatebootstrap: stage xcomp.fs pack
./stage < xcomp.fs > forth.bin ./stage < xcomp.fs | tee forth.bin > /dev/null
.PHONY: pack .PHONY: pack
pack: pack:

View File

@ -25,16 +25,25 @@ First, make sure that the `libz80` git submodule is checked out. If not, run
After that, you can run `make` and it builds the `forth` interpreter. After that, you can run `make` and it builds the `forth` interpreter.
## Usage
Run `./forth` to get the Collapse OS prompt. Type `0 LIST` for help. Run `./forth` to get the Collapse OS prompt. Type `0 LIST` for help.
The program is a curses interface with a limited, fixed size so that it can
provide a AT-XY interface (which is yet to implement).
## Problems? ## Problems?
If the libz80-wrapped zasm executable works badly (hangs, spew garbage, etc.), If the `forth` executable works badly (hangs, spew garbage, etc.),
it's probably because you've broken your bootstrap binaries. They're easy to it's probably because you've broken your bootstrap binaries. They're easy to
mistakenly break. To verify if you've done that, look at your git status. If mistakenly break. To verify if you've done that, look at your git status. If
`forth.bin` is modified, try resetting it and then run `make clean all`. Things `forth.bin` is modified, try resetting it and then run `make clean all`. Things
should go better afterwards. should go better afterwards.
A modified `blkfs` can also break things (although even with a completely broken
blkfs, you should still get to prompt), you might want to run `make pack` to
ensure that the `blkfs` file is in sync with the contents of the `blk/` folder.
If that doesn't work, there's also the nuclear option of `git reset --hard` If that doesn't work, there's also the nuclear option of `git reset --hard`
and `git clean -fxd`. and `git clean -fxd`.

View File

@ -1,13 +1,26 @@
/* Common code between shell, zasm and runbin. /* Common code between forth and stage binaries.
They all run on the same kind of virtual machine: A z80 CPU, 64K of RAM/ROM. They all run on the same kind of virtual machine: A z80 CPU, 64K of RAM/ROM.
*/ */
#include <string.h> #include <string.h>
#include "emul.h" #include "emul.h"
// Port for block reads. Write 2 bytes, MSB first, on that port and then
// read 1024 bytes from the DATA port.
#define BLK_PORT 0x03
#define BLKDATA_PORT 0x04
#ifndef BLKFS_PATH
#error BLKFS_PATH needed
#endif
#ifndef FBIN_PATH
#error FBIN_PATH needed
#endif
static Machine m; static Machine m;
static ushort traceval = 0; static ushort traceval = 0;
static uint16_t blkid = 0;
static FILE *blkfp;
static uint8_t io_read(int unused, uint16_t addr) static uint8_t io_read(int unused, uint16_t addr)
{ {
@ -32,6 +45,23 @@ static void io_write(int unused, uint16_t addr, uint8_t val)
} }
} }
static void iowr_blk(uint8_t val)
{
blkid <<= 8;
blkid |= val;
fseek(blkfp, blkid*1024, SEEK_SET);
}
static uint8_t iord_blkdata()
{
return getc(blkfp);
}
static void iowr_blkdata(uint8_t val)
{
putc(val, blkfp);
}
static uint8_t mem_read(int unused, uint16_t addr) static uint8_t mem_read(int unused, uint16_t addr)
{ {
return m.mem[addr]; return m.mem[addr];
@ -50,7 +80,26 @@ static void mem_write(int unused, uint16_t addr, uint8_t val)
Machine* emul_init() Machine* emul_init()
{ {
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH);
blkfp = fopen(BLKFS_PATH, "r+");
if (!blkfp) {
fprintf(stderr, "Can't open\n");
return NULL;
}
// initialize memory
memset(m.mem, 0, 0x10000); memset(m.mem, 0, 0x10000);
FILE *bfp = fopen(FBIN_PATH, "r");
if (!bfp) {
fprintf(stderr, "Can't open forth.bin\n");
return NULL;
}
int i = 0;
int c = getc(bfp);
while (c != EOF) {
m.mem[i++] = c;
c = getc(bfp);
}
fclose(bfp);
m.ramstart = 0; m.ramstart = 0;
m.minsp = 0xffff; m.minsp = 0xffff;
m.maxix = 0; m.maxix = 0;
@ -63,9 +112,16 @@ Machine* emul_init()
m.cpu.memWrite = mem_write; m.cpu.memWrite = mem_write;
m.cpu.ioRead = io_read; m.cpu.ioRead = io_read;
m.cpu.ioWrite = io_write; m.cpu.ioWrite = io_write;
m.iowr[BLK_PORT] = iowr_blk;
m.iord[BLKDATA_PORT] = iord_blkdata;
m.iowr[BLKDATA_PORT] = iowr_blkdata;
return &m; return &m;
} }
void emul_deinit()
{
fclose(blkfp);
}
bool emul_step() bool emul_step()
{ {
@ -117,6 +173,12 @@ void emul_memdump()
fclose(fp); fclose(fp);
} }
void emul_debugstr(char *s)
{
sprintf(s, "SP %04x (%04x) IX %04x (%04x)",
m.cpu.R1.wr.SP, m.minsp, m.cpu.R1.wr.IX, m.maxix);
}
void emul_printdebug() void emul_printdebug()
{ {
fprintf(stderr, "Min SP: %04x\n", m.minsp); fprintf(stderr, "Min SP: %04x\n", m.minsp);

View File

@ -29,9 +29,11 @@ typedef enum {
} Tristate; } Tristate;
Machine* emul_init(); Machine* emul_init();
void emul_deinit();
bool emul_step(); bool emul_step();
bool emul_steps(unsigned int steps); bool emul_steps(unsigned int steps);
void emul_loop(); void emul_loop();
void emul_trace(ushort addr); void emul_trace(ushort addr);
void emul_memdump(); void emul_memdump();
void emul_debugstr(char *s);
void emul_printdebug(); void emul_printdebug();

View File

@ -4,8 +4,9 @@
#include <curses.h> #include <curses.h>
#include <termios.h> #include <termios.h>
#include "emul.h" #include "emul.h"
#include "forth-bin.h"
#define WCOLS 80
#define WLINES 32
// in sync with glue.asm // in sync with glue.asm
#define RAMSTART 0x900 #define RAMSTART 0x900
#define STDIO_PORT 0x00 #define STDIO_PORT 0x00
@ -18,9 +19,16 @@
#define BLKDATA_PORT 0x04 #define BLKDATA_PORT 0x04
static FILE *fp; static FILE *fp;
static FILE *blkfp;
static int retcode = 0; static int retcode = 0;
static uint16_t blkid = 0; WINDOW *bw, *dw, *w;
void debug_panel()
{
char buf[30];
emul_debugstr(buf);
mvwaddnstr(dw, 0, 0, buf, 30);
wrefresh(dw);
}
static uint8_t iord_stdio() static uint8_t iord_stdio()
{ {
@ -28,7 +36,8 @@ static uint8_t iord_stdio()
if (fp != NULL) { if (fp != NULL) {
c = getc(fp); c = getc(fp);
} else { } else {
c = getch(); debug_panel();
c = wgetch(w);
} }
if (c == EOF) { if (c == EOF) {
c = 4; // ASCII EOT c = 4; // ASCII EOT
@ -42,7 +51,10 @@ static void iowr_stdio(uint8_t val)
putchar(val); putchar(val);
} else { } else {
if (val >= 0x20 || val == '\n') { if (val >= 0x20 || val == '\n') {
echochar(val); wechochar(w, val);
} else if (val == 0x08) {
int y, x; getyx(w, y, x);
wmove(w, y, x-1);
} }
} }
} }
@ -52,89 +64,46 @@ static void iowr_ret(uint8_t val)
retcode = val; retcode = val;
} }
static void iowr_blk(uint8_t val) int main(int argc, char *argv[])
{ {
blkid <<= 8;
blkid |= val;
if (blkfp != NULL) {
fseek(blkfp, blkid*1024, SEEK_SET);
}
}
static uint8_t iord_blkdata()
{
uint8_t res = 0;
if (blkfp != NULL) {
int c = getc(blkfp);
if (c != EOF) {
res = c;
}
}
return res;
}
static void iowr_blkdata(uint8_t val)
{
if (blkfp != NULL) {
putc(val, blkfp);
}
}
int run()
{
#ifdef BLKFS_PATH
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH);
blkfp = fopen(BLKFS_PATH, "r+");
if (!blkfp) {
fprintf(stderr, "Can't open\n");
}
#else
blkfp = NULL;
#endif
Machine *m = emul_init(); Machine *m = emul_init();
if (m == NULL) {
return 1;
}
m->ramstart = RAMSTART; m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio; m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio; m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[RET_PORT] = iowr_ret; m->iowr[RET_PORT] = iowr_ret;
m->iowr[BLK_PORT] = iowr_blk; w = NULL;
m->iord[BLKDATA_PORT] = iord_blkdata;
m->iowr[BLKDATA_PORT] = iowr_blkdata;
// initialize memory
for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i];
}
// Run!
while (emul_step());
if (blkfp != NULL) {
fclose(blkfp);
}
return retcode;
}
int main(int argc, char *argv[])
{
if (argc == 2) { if (argc == 2) {
fp = fopen(argv[1], "r"); fp = fopen(argv[1], "r");
if (fp == NULL) { if (fp == NULL) {
fprintf(stderr, "Can't open %s\n", argv[1]); fprintf(stderr, "Can't open %s\n", argv[1]);
return 1; return 1;
} }
int ret = run(); while (emul_step());
fclose(fp); fclose(fp);
return ret;
} else if (argc == 1) { } else if (argc == 1) {
fp = NULL; fp = NULL;
initscr(); cbreak(); noecho(); nl(); clear(); initscr(); cbreak(); noecho(); nl(); clear();
scrollok(stdscr, 1); // border window
int ret = run(); bw = newwin(WLINES+2, WCOLS+2, 0, 0);
nocbreak(); echo(); endwin(); wborder(bw, 0, 0, 0, 0, 0, 0, 0, 0);
wrefresh(bw);
// debug panel
dw = newwin(1, 30, LINES-1, COLS-30);
w = newwin(WLINES, WCOLS, 1, 1);
scrollok(w, 1);
while (emul_steps(1000)) {
debug_panel();
}
nocbreak(); echo(); delwin(w); delwin(bw); delwin(dw); endwin();
printf("\nDone!\n"); printf("\nDone!\n");
emul_printdebug(); emul_printdebug();
return ret;
} else { } else {
fprintf(stderr, "Usage: ./forth [filename]\n"); fprintf(stderr, "Usage: ./forth [filename]\n");
return 1; retcode = 1;
} }
emul_deinit();
return retcode;
} }

View File

@ -2,11 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include "emul.h" #include "emul.h"
#include "forth-bin.h"
#ifndef BLKFS_PATH
#error BLKFS_PATH needed
#endif
/* Staging binaries /* Staging binaries
@ -28,10 +23,6 @@ trouble of compiling defs to binary.
// To know which part of RAM to dump, we listen to port 2, which at the end of // To know which part of RAM to dump, we listen to port 2, which at the end of
// its compilation process, spits its HERE addr to port 2 (MSB first) // its compilation process, spits its HERE addr to port 2 (MSB first)
#define HERE_PORT 0x02 #define HERE_PORT 0x02
// Port for block reads. Write 2 bytes, MSB first, on that port and then
// read 1024 bytes from the DATA port.
#define BLK_PORT 0x03
#define BLKDATA_PORT 0x04
static int running; static int running;
// We support double-pokes, that is, a first poke to tell where to start the // We support double-pokes, that is, a first poke to tell where to start the
@ -39,8 +30,6 @@ static int running;
// then ending HERE and we start at sizeof(KERNEL). // then ending HERE and we start at sizeof(KERNEL).
static uint16_t start_here = 0; static uint16_t start_here = 0;
static uint16_t end_here = 0; static uint16_t end_here = 0;
static uint16_t blkid = 0;
static FILE *blkfp;
static uint8_t iord_stdio() static uint8_t iord_stdio()
{ {
@ -64,38 +53,16 @@ static void iowr_here(uint8_t val)
end_here |= val; end_here |= val;
} }
static void iowr_blk(uint8_t val)
{
blkid <<= 8;
blkid |= val;
fseek(blkfp, blkid*1024, SEEK_SET);
}
static uint8_t iord_blkdata()
{
return getc(blkfp);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH); Machine *m = emul_init();
blkfp = fopen(BLKFS_PATH, "r+"); if (m == NULL) {
if (!blkfp) {
fprintf(stderr, "Can't open\n");
return 1; return 1;
} }
Machine *m = emul_init();
m->ramstart = RAMSTART; m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio; m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio; m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[HERE_PORT] = iowr_here; m->iowr[HERE_PORT] = iowr_here;
m->iowr[BLK_PORT] = iowr_blk;
m->iord[BLKDATA_PORT] = iord_blkdata;
// initialize memory
for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i];
}
// Run! // Run!
running = 1; running = 1;
@ -105,6 +72,7 @@ int main(int argc, char *argv[])
for (int i=start_here; i<end_here; i++) { for (int i=start_here; i<end_here; i++) {
putchar(m->mem[i]); putchar(m->mem[i]);
} }
emul_deinit();
emul_printdebug(); emul_printdebug();
return 0; return 0;
} }

View File

@ -2,13 +2,12 @@ MEMDUMP_TGT = memdump
UPLOAD_TGT = upload UPLOAD_TGT = upload
TTYSAFE_TGT = ttysafe TTYSAFE_TGT = ttysafe
PINGPONG_TGT = pingpong PINGPONG_TGT = pingpong
BIN2C_TGT = bin2c
EXEC_TGT = exec EXEC_TGT = exec
BLKPACK_TGT = blkpack BLKPACK_TGT = blkpack
BLKUNPACK_TGT = blkunpack BLKUNPACK_TGT = blkunpack
BLKUP_TGT = blkup BLKUP_TGT = blkup
TARGETS = $(MEMDUMP_TGT) $(UPLOAD_TGT) \ TARGETS = $(MEMDUMP_TGT) $(UPLOAD_TGT) \
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) \ $(TTYSAFE_TGT) $(PINGPONG_TGT) $(EXEC_TGT) $(BLKPACK_TGT) \
$(BLKUNPACK_TGT) $(BLKUP_TGT) $(BLKUNPACK_TGT) $(BLKUP_TGT)
OBJS = common.o OBJS = common.o
@ -22,7 +21,6 @@ $(MEMDUMP_TGT): $(MEMDUMP_TGT).c
$(UPLOAD_TGT): $(UPLOAD_TGT).c $(UPLOAD_TGT): $(UPLOAD_TGT).c
$(TTYSAFE_TGT): $(TTYSAFE_TGT).c $(TTYSAFE_TGT): $(TTYSAFE_TGT).c
$(PINGPONG_TGT): $(PINGPONG_TGT).c $(PINGPONG_TGT): $(PINGPONG_TGT).c
$(BIN2C_TGT): $(BIN2C_TGT).c
$(EXEC_TGT): $(EXEC_TGT).c $(EXEC_TGT): $(EXEC_TGT).c
$(BLKPACK_TGT): $(BLKPACK_TGT).c $(BLKPACK_TGT): $(BLKPACK_TGT).c
$(BLKUNPACK_TGT): $(BLKUNPACK_TGT).c $(BLKUNPACK_TGT): $(BLKUNPACK_TGT).c

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2020 Byron Grobe
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BUFSZ 32
static const char intro[] = "static const unsigned char %s[] = {\n ";
int main(int argc, char **argv) {
int n;
int col = 0;
uint8_t buf[BUFSZ];
if (argc < 2) {
fprintf(stderr, "Specify a name for the data structure...\n");
return 1;
}
printf(intro, argv[1]);
while(!feof(stdin)) {
n = fread(buf, 1, BUFSZ, stdin);
for(int i = 0; i < n; ++i) {
if (col+4 >= 76) {
printf("\n ");
col = 0;
}
printf("0x%.2x, ", buf[i]);
col += 6;
}
}
printf("};\n");
}