@@ -24,9 +24,10 @@ tools. | |||
## Getting started | |||
Usage documentation is in-system, so access to documentation requires you to | |||
run Collapse OS. Fortunately, doing so in an emulator is easy. | |||
run Collapse OS. Fortunately, building and running Collapse OS on a POSIX | |||
environment is easy. | |||
See `/emul/README.md` for getting an emulated system running. | |||
See `/cvm/README.md` for instructions. | |||
Then, run `0 LIST` for an introduction, follow instructions from there. | |||
@@ -0,0 +1,47 @@ | |||
# C VM | |||
This is a C implementation of Collapse OS' native words. It allows Collapse OS | |||
to run natively on any POSIX environment. | |||
## Requirements | |||
You need `ncurses` to build the `forth` executable. In debian-based distros, | |||
it's `libncurses5-dev`. | |||
## Build | |||
Running `make` will yield `forth` and `stage` executables. | |||
## Usage | |||
To play around Collapse OS, you'll want to run `./forth`. 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. | |||
You can get a REPL by launching the program with [`rlwrap(1)`][rlwrap] like | |||
this: | |||
rlwrap -e '' -m -S '> ' ./forth /dev/stdin | |||
## Problems? | |||
If the `forth` executable works badly (hangs, spew garbage, etc.), | |||
it's probably because you've broken your bootstrap binary. It's easy to | |||
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 | |||
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` | |||
and `git clean -fxd`. | |||
If that still doesn't work, it might be because the current commit you're on | |||
is broken, but that is rather rare: the repo on Github is plugged on Travis | |||
and it checks that everything is smooth. | |||
[rlwrap]: https://linux.die.net/man/1/rlwrap |
@@ -1,4 +1,2 @@ | |||
/stage | |||
/forth | |||
/*-bin.h | |||
/blkfs | |||
/forth.bin |
@@ -1,47 +1,30 @@ | |||
TARGETS = forth stage | |||
TARGETS = forth | |||
OBJS = emul.o libz80/libz80.o | |||
BLKPACK = ../tools/blkpack | |||
BLKUNPACK = ../tools/blkunpack | |||
CDIR = ../cvm | |||
STAGE = $(CDIR)/stage | |||
BLKFS = $(CDIR)/blkfs | |||
.PHONY: all | |||
all: $(TARGETS) | |||
$(BLKPACK): | |||
$(MAKE) -C ../tools | |||
.PHONY: $(BLKUNPACK) | |||
$(BLKUNPACK): $(BLKPACK) | |||
stage: stage.c $(OBJS) blkfs | |||
$(CC) stage.c $(OBJS) -o $@ | |||
blkfs: $(BLKPACK) | |||
$(BLKPACK) ../blk > $@ | |||
forth: forth.c $(OBJS) blkfs | |||
forth: forth.c $(OBJS) $(CDIR)/blkfs | |||
$(CC) forth.c $(OBJS) -lncurses -o $@ | |||
libz80/libz80.o: libz80/z80.c | |||
$(MAKE) -C libz80/codegen opcodes | |||
$(CC) -Wall -ansi -g -c -o libz80/libz80.o libz80/z80.c | |||
emul.o: emul.c | |||
$(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/blkfs\" -c -o emul.o emul.c | |||
emul.o: emul.c forth.bin $(BLKFS) | |||
$(CC) -DFBIN_PATH=\"`pwd`/forth.bin\" -DBLKFS_PATH=\"`pwd`/$(BLKFS)\" -c -o emul.o emul.c | |||
.PHONY: updatebootstrap | |||
updatebootstrap: stage xcomp.fs pack | |||
./stage < xcomp.fs > new.bin | |||
mv new.bin forth.bin | |||
forth.bin: xcomp.fs $(STAGE) | |||
$(CDIR)/stage < xcomp.fs > $@ | |||
.PHONY: pack | |||
pack: | |||
rm blkfs && $(MAKE) blkfs | |||
$(BLKFS): $(STAGE) | |||
.PHONY: unpack | |||
unpack: | |||
$(BLKUNPACK) ../blk < blkfs | |||
$(STAGE): | |||
$(MAKE) -C $(CDIR) all | |||
.PHONY: clean | |||
clean: | |||
rm -f $(TARGETS) emul.o *-bin.h blkfs libz80/libz80.o | |||
rm -f $(TARGETS) emul.o *.bin libz80/libz80.o |
@@ -1,80 +0,0 @@ | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <unistd.h> | |||
#include "emul.h" | |||
/* Staging binaries | |||
The role of a stage executable is to compile definitions in a dictionary and | |||
then spit the difference between the starting binary and the new binary. | |||
That binary can then be grafted to an exiting Forth binary to augment its | |||
dictionary. | |||
We could, if we wanted, run only with the bootstrap binary and compile core | |||
defs at runtime, but that would mean that those defs live in RAM. In may system, | |||
RAM is much more constrained than ROM, so it's worth it to give ourselves the | |||
trouble of compiling defs to binary. | |||
*/ | |||
#define RAMSTART 0 | |||
#define STDIO_PORT 0x00 | |||
// 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) | |||
#define HERE_PORT 0x02 | |||
static int running; | |||
// We support double-pokes, that is, a first poke to tell where to start the | |||
// dump and a second one to tell where to stop. If there is only one poke, it's | |||
// then ending HERE and we start at sizeof(KERNEL). | |||
static uint16_t start_here = 0; | |||
static uint16_t end_here = 0; | |||
static uint8_t iord_stdio() | |||
{ | |||
int c = getc(stdin); | |||
if (c == EOF) { | |||
running = 0; | |||
} | |||
return (uint8_t)c; | |||
} | |||
static void iowr_stdio(uint8_t val) | |||
{ | |||
// comment if you don't like verbose staging output | |||
putc(val, stderr); | |||
} | |||
static void iowr_here(uint8_t val) | |||
{ | |||
start_here <<=8; | |||
start_here |= (end_here >> 8); | |||
end_here <<= 8; | |||
end_here |= val; | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
Machine *m = emul_init(); | |||
if (m == NULL) { | |||
return 1; | |||
} | |||
m->ramstart = RAMSTART; | |||
m->iord[STDIO_PORT] = iord_stdio; | |||
m->iowr[STDIO_PORT] = iowr_stdio; | |||
m->iowr[HERE_PORT] = iowr_here; | |||
// Run! | |||
running = 1; | |||
while (running && emul_step()); | |||
// We're done, now let's spit dict data | |||
for (int i=start_here; i<end_here; i++) { | |||
putchar(m->mem[i]); | |||
} | |||
emul_deinit(); | |||
emul_printdebug(); | |||
return 0; | |||
} | |||
@@ -4,11 +4,12 @@ git submodule init | |||
git submodule update | |||
git clean -fxd | |||
make -C cvm | |||
make -C emul | |||
make -C tests | |||
# verify that forth.bin is stable | |||
cp emul/forth.bin ref.bin | |||
make -C emul updatebootstrap | |||
cmp emul/forth.bin ref.bin | |||
cp cvm/forth.bin ref.bin | |||
make -C cvm updatebootstrap | |||
cmp cvm/forth.bin ref.bin | |||
rm ref.bin |