emul/zasm: use libcfs

This allows us to get rid of the zasm.sh wrapper.
This commit is contained in:
Virgil Dupras 2019-12-31 15:07:39 -05:00
parent 4cde58fd83
commit 097c677641
22 changed files with 131 additions and 161 deletions

View File

@ -65,12 +65,9 @@ look like:
Once this is written, you can build it with `zasm`, which takes code from stdin
and spits binary to stdout. Because out code has includes, however, you need
to supply zasm with a block device containing a CFS containing the files to
include. This sounds, compicated, but it's managed by the `tools/zasm.sh` shell
script. The invocation would look like (it builds a CFS with the contents of
both `kernel/` and `apps/` folders):
to supply zasm with include folders or files. The invocation would look like
tools/zasm.sh kernel/ apps/ < glue.asm > collapseos.bin
emul/zasm/zasm kernel/ apps/ < glue.asm > collapseos.bin
## Building zasm
@ -79,7 +76,7 @@ Collapse OS has its own assembler written in z80 assembly. We call it
but because it is written in z80 assembler, it needs to be emulated (with
[libz80][libz80]).
So, the first step is to build zasm. Open `tools/emul/README.md` and follow
So, the first step is to build zasm. Open `emul/README.md` and follow
instructions there.
## Platform constants
@ -162,5 +159,5 @@ and this much depends on the part you select. But if you want a shell, you will
usually end it with `basStart`, which never returns.
[rc2014]: https://rc2014.co.uk/
[zasm]: ../tools/emul/README.md
[zasm]: ../emul/README.md
[libz80]: https://github.com/ggambetta/libz80

View File

@ -4,19 +4,19 @@ KERNEL = ../kernel
APPS = ../apps
ZASMBIN = zasm/zasm
AVRABIN = zasm/avra
ZASMSH = ./zasm.sh
SHELLAPPS = zasm ed
SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
OBJS = emul.o libz80/libz80.o
SHELLOBJS = $(OBJS) $(CFSPACK_OBJ)
ZASMOBJS = $(SHELLOBJS)
.PHONY: all
all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS)
# -o in sync with SHELL_CODE in shell/glue.asm
shell/shell.bin: shell/glue.asm $(ZASMBIN)
$(ZASMSH) $(KERNEL) shell/user.h $(APPS) < shell/glue.asm | tee $@ > /dev/null
$(ZASMBIN) $(KERNEL) shell/user.h $(APPS) < shell/glue.asm | tee $@ > /dev/null
shell/shell-bin.h: shell/shell.bin
./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null
@ -30,17 +30,17 @@ zasm/kernel-bin.h: zasm/kernel.bin
zasm/zasm-bin.h: zasm/zasm.bin
./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null
$(ZASMBIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK)
$(CC) zasm/zasm.c $(OBJS) -o $@
$(ZASMBIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/zasm-bin.h
$(CC) zasm/zasm.c $(ZASMOBJS) -o $@
zasm/avra.bin: $(ZASMBIN)
$(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/gluea.asm > $@
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/gluea.asm > $@
zasm/avra-bin.h: zasm/avra.bin
./bin2c.sh USERSPACE < zasm/avra.bin | tee $@ > /dev/null
$(AVRABIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/avra-bin.h
$(CC) -D AVRA zasm/zasm.c $(OBJS) -o $@
$(AVRABIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/avra-bin.h
$(CC) -D AVRA zasm/zasm.c $(ZASMOBJS) -o $@
runbin/runbin: runbin/runbin.c $(OBJS)
$(CC) runbin/runbin.c $(OBJS) -o $@
@ -52,20 +52,20 @@ libz80/libz80.o: libz80/z80.c
emul.o: emul.c
$(CC) -c -o emul.o emul.c
$(CFSPACK):
$(CFSPACK_OBJ): ${@:%.o=%.c}
$(MAKE) -C ../tools/cfspack
# -o in sync with USER_CODE in shell/user.h
$(SHELLTGTS): $(ZASMBIN)
$(ZASMSH) -o 42 $(KERNEL) $(APPS) shell/user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
$(ZASMBIN) -o 42 $(KERNEL) $(APPS) shell/user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
cfsin/user.h: shell/user.h
cp shell/user.h $@
.PHONY: updatebootstrap
updatebootstrap: $(ZASMBIN)
$(ZASMSH) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
$(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
$(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
.PHONY: clean
clean:

View File

@ -1,44 +0,0 @@
#!/usr/bin/env bash
# Calls emul/zasm/zasm in a convenient manner by wrapping specified
# paths to include in a single CFS file and then pass that file to zasm.
# Additionally, it takes a "-o" argument to set the initial ".org" of the
# binary. For example, "zasm.sh -o 4f < foo.asm" assembles foo.asm as if it
# started with the line ".org 0x4f00".
# The -a flag makes us switch to the AVR assembler
# readlink -f doesn't work with macOS's implementation
# so, if we can't get readlink -f to work, try python with a realpath implementation
ABS_PATH=$(readlink -f "$0" || python -c "import os; print(os.path.realpath('$0'))")
DIR=$(dirname "${ABS_PATH}")
ZASMBIN="${DIR}/zasm/zasm"
usage() { echo "Usage: $0 [-a] [-o <hexorg>] <paths-to-include>..." 1>&2; exit 1; }
org='00'
while getopts ":ao:" opt; do
case "${opt}" in
a)
ZASMBIN="${DIR}/zasm/avra"
;;
o)
org=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
# wrapper around ./zasm/zasm that prepares includes CFS prior to call
CFSPACK="${DIR}/../tools/cfspack/cfspack"
INCCFS=$(mktemp)
"${CFSPACK}" -p "*.h" -p "*.asm" -p "*.bin" "$@" > "${INCCFS}"
"${ZASMBIN}" "${org}" "${INCCFS}"
RES=$?
rm "${INCCFS}"
exit $RES

View File

@ -1,7 +1,10 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include "../emul.h"
#include "../../tools/cfspack/cfs.h"
#include "kernel-bin.h"
#ifdef AVRA
#include "avra-bin.h"
@ -51,6 +54,7 @@
// By default, we don't spit what zasm prints. Too noisy. Define VERBOSE if
// you want to spit this content to stderr.
//#define VERBOSE
#define MAX_FSDEV_SIZE 0x80000
// STDIN buffer, allows us to seek and tell
static uint8_t inpt[STDIN_BUFSIZE];
@ -58,8 +62,7 @@ static int inpt_size;
static int inpt_ptr;
static uint8_t middle_of_seek_tell = 0;
static uint8_t fsdev[0x80000] = {0};
static uint32_t fsdev_size = 0;
static uint8_t fsdev[MAX_FSDEV_SIZE] = {0};
static uint32_t fsdev_ptr = 0;
static uint8_t fsdev_seek_tell_cnt = 0;
@ -88,7 +91,7 @@ static uint8_t iord_stdin_seek()
static uint8_t iord_fsdata()
{
if (fsdev_ptr < fsdev_size) {
if (fsdev_ptr < MAX_FSDEV_SIZE) {
return fsdev[fsdev_ptr++];
} else {
return 0;
@ -99,7 +102,7 @@ static uint8_t iord_fsseek()
{
if (fsdev_seek_tell_cnt != 0) {
return fsdev_seek_tell_cnt;
} else if (fsdev_ptr >= fsdev_size) {
} else if (fsdev_ptr >= MAX_FSDEV_SIZE) {
return 1;
} else {
return 0;
@ -130,7 +133,7 @@ static void iowr_stdin_seek(uint8_t val)
static void iowr_fsdata(uint8_t val)
{
if (fsdev_ptr < fsdev_size) {
if (fsdev_ptr < MAX_FSDEV_SIZE) {
fsdev[fsdev_ptr++] = val;
}
}
@ -159,11 +162,50 @@ static void iowr_stderr(uint8_t val)
#endif
}
void usage()
{
fprintf(stderr, "Usage: zasm [-o org] [include-dir-or-file...] < source > binary\n");
}
int main(int argc, char *argv[])
{
if (argc > 3) {
fprintf(stderr, "Too many args\n");
return 1;
char *init_org = "00";
while (1) {
int c = getopt(argc, argv, "o:");
if (c < 0) {
break;
}
switch (c) {
case 'o':
init_org = optarg;
if (strlen(init_org) != 2) {
fprintf(stderr, "Initial org must be a two-character hex string");
}
break;
default:
usage();
return 1;
}
}
if (argc-optind > 0) {
FILE *fp = fmemopen(fsdev, MAX_FSDEV_SIZE, "w");
set_spit_stream(fp);
char *patterns[4] = {"*.h", "*.asm", "*.bin", 0};
for (int i=optind; i<argc; i++) {
int res;
if (is_regular_file(argv[i])) {
// special case: just one file
res = spitblock(argv[i], basename(argv[i]));
} else {
res = spitdir(argv[i], "", patterns);
}
if (res != 0) {
fprintf(stderr, "Error while building the include CFS.\n");
fclose(fp);
return 1;
}
}
fclose(fp);
}
Machine *m = emul_init();
m->iord[STDIO_PORT] = iord_stdio;
@ -182,31 +224,9 @@ int main(int argc, char *argv[])
for (int i=0; i<sizeof(USERSPACE); i++) {
m->mem[i+USER_CODE] = USERSPACE[i];
}
char *init_org = "00";
if (argc >= 2) {
init_org = argv[1];
if (strlen(init_org) != 2) {
fprintf(stderr, "Initial org must be a two-character hex string");
}
}
// glue.asm knows that it needs to fetch these arguments at this address.
m->mem[0xff00] = init_org[0];
m->mem[0xff01] = init_org[1];
fsdev_size = 0;
if (argc == 3) {
FILE *fp = fopen(argv[2], "r");
if (fp == NULL) {
fprintf(stderr, "Can't open file %s\n", argv[1]);
return 1;
}
int c = fgetc(fp);
while (c != EOF) {
fsdev[fsdev_size] = c;
fsdev_size++;
c = fgetc(fp);
}
fclose(fp);
}
// read stdin in buffer
inpt_size = 0;
inpt_ptr = 0;

View File

@ -1,9 +1,10 @@
TARGET = os.bin
ZASM = ../../tools/zasm.sh
KERNEL = ../../kernel
APPS = ../../apps
BASEDIR = ../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@

View File

@ -77,7 +77,7 @@ is decoupled from the ACIA and can get its IO from anything. See comments in
We only have the shell to build, so it's rather straightforward:
../../tools/zasm.sh ../../kernel < glue.asm > os.bin
../../emul/zasm/zasm ../../kernel < glue.asm > os.bin
Running `make` will also work.

View File

@ -1,10 +1,11 @@
TARGET = os.bin
ZASM = ../../../tools/zasm.sh
KERNEL = ../../../kernel
APPS = ../../../apps
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@

View File

@ -33,7 +33,6 @@ jp aciaInt
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.inc "lib/args.asm"
.equ AT28W_RAMSTART STDIO_RAMEND
.inc "at28w/main.asm"

View File

@ -2,9 +2,10 @@ PROGNAME = ps2ctl
AVRDUDEMCU ?= t45
AVRDUDEARGS ?= -c usbtiny -P usb
TARGETS = $(PROGNAME).hex os.bin
ZASM = ../../../tools/zasm.sh
KERNEL = ../../../kernel
APPS = ../../../apps
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
# Rules
@ -14,13 +15,13 @@ all: $(TARGETS)
@echo Done!
send: $(PROGNAME).hex
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
$(PROGNAME).hex: $(PROGNAME).asm
avra -o $@ $<
avra -o $@ $(PROGNAME).asm
os.bin: glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
clean:
rm -f $(TARGETS) *.eep.hex *.obj os.bin

View File

@ -1,19 +1,19 @@
TARGETS = os.bin cfsin/helo
TOOLS = ../../../tools
ZASM = $(TOOLS)/zasm.sh
KERNEL = ../../../kernel
APPS = ../../../apps
CFSPACK = $(TOOLS)/cfspack/cfspack
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
CFSPACK = $(BASEDIR)/tools/cfspack/cfspack
.PHONY: all
all: $(TARGETS) sdcard.cfs
os.bin: glue.asm
cfsin/helo: helo.asm
$(TARGETS):
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
$(CFSPACK):
make -C $(TOOLS)/cfspack
make -C $(BASEDIR)/tools/cfspack
sdcard.cfs: cfsin $(CFSPACK)
$(CFSPACK) $< > $@
$(CFSPACK) cfsin > $@

View File

@ -1,21 +1,20 @@
SHELLAPPS = zasm sdct memt at28w
APPTARGETS = ${SHELLAPPS:%=cfsin/%}
CFSTARGETS = $(APPTARGETS) cfsin/user.h
BASE = ../../..
TOOLS = $(BASE)/tools
ZASM = $(TOOLS)/zasm.sh
KERNEL = $(BASE)/kernel
APPS = $(BASE)/apps
CFSPACK = $(TOOLS)/cfspack/cfspack
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
CFSPACK = $(BASEDIR)/tools/cfspack/cfspack
.PHONY: all
all: os.bin sdcard.cfs
os.bin: glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
$(CFSPACK):
make -C $(TOOLS)/cfspack
make -C $(BASEDIR)/tools/cfspack
sdcard.cfs: $(CFSTARGETS) $(CFSPACK)
$(CFSPACK) cfsin > $@
@ -24,7 +23,7 @@ $(APPTARGETS): $(ZASMBIN)
$(ZASM) $(KERNEL) $(APPS) user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
cfsin/user.h: user.h
cp $< $@
cp user.h $@
.PHONY: clean
clean:

View File

@ -1,9 +1,10 @@
TARGET = os.sms
ZASM = ../../tools/zasm.sh
KERNEL = ../../kernel
APPS = ../../apps
BASEDIR = ../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@

View File

@ -2,9 +2,10 @@ PROGNAME = ps2ctl
AVRDUDEMCU ?= t45
AVRDUDEARGS ?= -c usbtiny -P usb
TARGETS = $(PROGNAME).hex os.sms
ZASM = ../../../tools/zasm.sh
KERNEL = ../../../kernel
APPS = ../../../apps
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
# Rules
@ -14,13 +15,13 @@ all: $(TARGETS)
@echo Done!
send: $(PROGNAME).hex
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
$(PROGNAME).hex: $(PROGNAME).asm
avra -o $@ $<
avra -o $@ $(PROGNAME).asm
os.sms: glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
clean:
rm -f $(TARGETS) *.eep.hex *.obj os.bin

View File

@ -1,20 +1,21 @@
ZASM = ../../../tools/zasm.sh
KERNEL = ../../../kernel
APPS = ../../../apps
BASEDIR = ../../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
.PHONY: all clean
all: os.sms
# -o value synced with offset in glue.asm
ed.bin: $(APPS)/ed/glue.asm
$(ZASM) -o 19 $(KERNEL) $(APPS) user.h < $< > $@
$(ZASM) -o 1f $(KERNEL) $(APPS) user.h < $(APPS)/ed/glue.asm > $@
# -o value synced with offset in glue.asm
zasm.bin: $(APPS)/zasm/glue.asm
$(ZASM) -o 1d $(KERNEL) $(APPS) user.h < $< > $@
$(ZASM) -o 24 $(KERNEL) $(APPS) user.h < $(APPS)/zasm/glue.asm > $@
os.sms: glue.asm ed.bin zasm.bin
$(ZASM) $(KERNEL) $(APPS) ed.bin zasm.bin < $< > $@
$(ZASM) $(KERNEL) $(APPS) ed.bin zasm.bin < glue.asm > $@
clean:
rm -f os.sms ed.bin zasm.bin

View File

@ -1,18 +1,19 @@
TARGET = os.rom
ZASM = ../../tools/zasm.sh
KERNEL = ../../kernel
APPS = ../../apps
BASEDIR = ../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
MKTIUPGRADE = mktiupgrade
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) $(APPS) < $< > $@
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
truncate -s 1M $@
os.8xu: $(TARGET)
$(MKTIUPGRADE) -p -k keys/0A.key -d TI-84+ $< $@ 00
$(MKTIUPGRADE) -p -k keys/0A.key -d TI-84+ $(TARGET) $@ 00
.PHONY: send
send: os.8xu
tilp -n --calc ti84+ --cable DirectLink $<
tilp -n --calc ti84+ --cable DirectLink os.8xu

View File

@ -1,5 +1,4 @@
EMULDIR = ../emul
CFSPACK = ../tools/cfspack/cfspack
.PHONY: run
run:
@ -8,10 +7,3 @@ run:
cd zasm && ./runtests.sh
cd avra && ./runtests.sh
cd shell && ./runtests.sh
$(CFSPACK):
$(MAKE) -C ../tools/cfspack
.PHONY: cfs
cfs: $(CFSPACK)
$(CFSPACK) shell/cfsin > shell/test.cfs

View File

@ -1,12 +1,12 @@
#!/bin/sh -e
ZASM=../../emul/zasm.sh
ZASM=../../emul/zasm/avra
AVRINC=../../avr
cmpas() {
FN=$1
EXPECTED=$(xxd ${FN%.*}.expected)
ACTUAL=$(cat ${FN} | "${ZASM}" -a "${AVRINC}" | xxd)
ACTUAL=$(cat ${FN} | "${ZASM}" "${AVRINC}" | xxd)
if [ "$ACTUAL" = "$EXPECTED" ]; then
echo ok
else

View File

@ -6,7 +6,7 @@ SHELL="${EMULDIR}/shell/shell"
replay() {
fn=$1
replayfn=${fn%.*}.expected
ACTUAL=$("${SHELL}" -f test.cfs < "${fn}" 2> /dev/null)
ACTUAL=$("${SHELL}" < "${fn}" 2> /dev/null)
EXPECTED=$(cat ${replayfn})
if [ "$ACTUAL" = "$EXPECTED" ]; then
echo ok

Binary file not shown.

View File

@ -3,7 +3,7 @@ set -e
# TODO: find POSIX substitute to that PIPESTATUS thing
BASE=../..
ZASM="${BASE}/emul/zasm.sh"
ZASM="${BASE}/emul/zasm/zasm"
RUNBIN="${BASE}/emul/runbin/runbin"
KERNEL="${BASE}/kernel"
APPS="${BASE}/apps"

View File

@ -2,7 +2,7 @@
# no "set -e" because we test errors
ZASM=../../emul/zasm.sh
ZASM=../../emul/zasm/zasm
chkerr() {
echo "Check that '$1' results in error $2"

View File

@ -3,7 +3,7 @@
BASE=../..
KERNEL="${BASE}/kernel"
APPS="${BASE}/apps"
ZASM="${BASE}/emul/zasm.sh"
ZASM="${BASE}/emul/zasm/zasm"
cmpas() {
FN=$1