diff --git a/apps/README.md b/apps/README.md new file mode 100644 index 0000000..02d5a9b --- /dev/null +++ b/apps/README.md @@ -0,0 +1,3 @@ +# User applications + +This folder contains code designed to be loaded and ran in RAM. diff --git a/apps/zasm/README.md b/apps/zasm/README.md new file mode 100644 index 0000000..2c06264 --- /dev/null +++ b/apps/zasm/README.md @@ -0,0 +1,15 @@ +# z80 assembler + +This is probably the most critical part of the Collapse OS project. If this app +can be brought to completion, it pretty much makes the project a success because +it ensures self-reproduction. + +## Running on a "modern" machine + +To be able to develop zasm efficiently, [libz80][libz80] is used to run zasm +on a modern machine. The code lives in `emul` and ran be built with `make`, +provided that you have a copy libz80 living in `emul/libz80`. + +The resulting `zasm` binary takes asm code in stdin and spits binary in stdout. + +[libz80]: https://github.com/ggambetta/libz80 diff --git a/apps/zasm/emul/.gitignore b/apps/zasm/emul/.gitignore new file mode 100644 index 0000000..e4c0035 --- /dev/null +++ b/apps/zasm/emul/.gitignore @@ -0,0 +1,4 @@ +libz80 +wrapper.h +zasm.h +zasm diff --git a/apps/zasm/emul/Makefile b/apps/zasm/emul/Makefile new file mode 100644 index 0000000..a22e427 --- /dev/null +++ b/apps/zasm/emul/Makefile @@ -0,0 +1,11 @@ +zasm: zasm.c libz80/libz80.so wrapper.h zasm.h + cc $< -l z80 -L./libz80 -Wl,-rpath ./libz80 -o $@ + +libz80/libz80.so: libz80/Makefile + make -C libz80 + +wrapper.h: wrapper.asm + scas -o - $< | ./bin2c.sh WRAPPER > $@ + +zasm.h: ../zasm.asm + scas -o - $< | ./bin2c.sh ZASM > $@ diff --git a/apps/zasm/emul/bin2c.sh b/apps/zasm/emul/bin2c.sh new file mode 100755 index 0000000..62f0c09 --- /dev/null +++ b/apps/zasm/emul/bin2c.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "unsigned char $1[] = { " +xxd -i - +echo " };" diff --git a/apps/zasm/emul/wrapper.asm b/apps/zasm/emul/wrapper.asm new file mode 100644 index 0000000..c83630e --- /dev/null +++ b/apps/zasm/emul/wrapper.asm @@ -0,0 +1,13 @@ +; setup the stack +ld hl, 0xffff +ld sp, hl +; zasm input +ld hl, 0x9000 +; zasm output +ld hl, 0xc000 +call zasm +; signal the emulator we're done +out (0), a +halt +zasm: +; beginning of the code diff --git a/apps/zasm/emul/zasm.c b/apps/zasm/emul/zasm.c new file mode 100644 index 0000000..751917d --- /dev/null +++ b/apps/zasm/emul/zasm.c @@ -0,0 +1,64 @@ +#include +#include "libz80/z80.h" +#include "wrapper.h" +#include "zasm.h" + +/* zasm is a "pure memory" application. It starts up being told memory location + * to read and memory location to write. + * + * This program works be writing stdin in a specific location in memory, run + * zasm in a special wrapper, wait until we receive the stop signal, then + * spit the contents of the dest memory to stdout. + */ +static Z80Context cpu; +static uint8_t mem[0xffff]; +static int running; + + +static uint8_t io_read(int unused, uint16_t addr) +{ + return 0; +} + +static void io_write(int unused, uint16_t addr, uint8_t val) +{ + // zasm doesn't do any IO. If we receive any IO, it means that we're done + // because the wrapper told us through an "out" + running = 0; +} + +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() +{ + // initialize memory + int wrapperlen = sizeof(WRAPPER); + for (int i=0; i