mirror of
https://github.com/hsoft/collapseos.git
synced 2024-12-25 05:08:05 +11:00
emul: build from "cvm" instead of from itself
The C VM now runs the show.
This commit is contained in:
parent
1312817117
commit
a65f674c74
@ -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.
|
||||
|
||||
|
47
cvm/README.md
Normal file
47
cvm/README.md
Normal file
@ -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
|
4
emul/.gitignore
vendored
4
emul/.gitignore
vendored
@ -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
|
||||
|
||||
forth.bin: xcomp.fs $(STAGE)
|
||||
$(CDIR)/stage < xcomp.fs > $@
|
||||
|
||||
.PHONY: updatebootstrap
|
||||
updatebootstrap: stage xcomp.fs pack
|
||||
./stage < xcomp.fs > new.bin
|
||||
mv new.bin forth.bin
|
||||
$(BLKFS): $(STAGE)
|
||||
|
||||
.PHONY: pack
|
||||
pack:
|
||||
rm blkfs && $(MAKE) blkfs
|
||||
|
||||
.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
|
||||
|
BIN
emul/forth.bin
BIN
emul/forth.bin
Binary file not shown.
80
emul/stage.c
80
emul/stage.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user