mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 10:28:05 +11:00
Compare commits
7 Commits
e3c885085d
...
eed67c4768
Author | SHA1 | Date | |
---|---|---|---|
|
eed67c4768 | ||
|
359991c005 | ||
|
097c677641 | ||
|
4cde58fd83 | ||
|
72357fec86 | ||
|
40f56dd6dc | ||
|
c5c6ef4c6c |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
|
*.o
|
||||||
/kernel/user.h
|
/kernel/user.h
|
||||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,3 +1,3 @@
|
|||||||
[submodule "tools/emul/libz80"]
|
[submodule "emul/libz80"]
|
||||||
path = tools/emul/libz80
|
path = emul/libz80
|
||||||
url = https://github.com/ggambetta/libz80.git
|
url = https://github.com/ggambetta/libz80.git
|
||||||
|
10
README.md
10
README.md
@ -34,11 +34,11 @@ path to giving Collapse OS a try.
|
|||||||
* `recipes`: collection of recipes that assemble parts together on a specific
|
* `recipes`: collection of recipes that assemble parts together on a specific
|
||||||
machine.
|
machine.
|
||||||
* `doc`: User guide for when you've successfully installed Collapse OS.
|
* `doc`: User guide for when you've successfully installed Collapse OS.
|
||||||
* `tools`: Tools for working with Collapse OS from "modern" environments. Mostly
|
* `tools`: Tools for working with Collapse OS from "modern" environments. For
|
||||||
development tools, but also contains emulated zasm, which is
|
example, tools for facilitating data upload to a Collapse OS machine
|
||||||
necessary to build Collapse OS from a non-Collapse OS machine.
|
through a serial port.
|
||||||
|
* `emul`: Emulated applications, such as zasm and the shell.
|
||||||
Each folder has a README with more details.
|
* `tests`: Automated test suite for the whole project.
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
|
@ -65,12 +65,9 @@ look like:
|
|||||||
|
|
||||||
Once this is written, you can build it with `zasm`, which takes code from stdin
|
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
|
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
|
to supply zasm with include folders or files. The invocation would look like
|
||||||
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):
|
|
||||||
|
|
||||||
tools/zasm.sh kernel/ apps/ < glue.asm > collapseos.bin
|
emul/zasm/zasm kernel/ apps/ < glue.asm > collapseos.bin
|
||||||
|
|
||||||
## Building zasm
|
## 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
|
but because it is written in z80 assembler, it needs to be emulated (with
|
||||||
[libz80][libz80]).
|
[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.
|
instructions there.
|
||||||
|
|
||||||
## Platform constants
|
## 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.
|
usually end it with `basStart`, which never returns.
|
||||||
|
|
||||||
[rc2014]: https://rc2014.co.uk/
|
[rc2014]: https://rc2014.co.uk/
|
||||||
[zasm]: ../tools/emul/README.md
|
[zasm]: ../emul/README.md
|
||||||
[libz80]: https://github.com/ggambetta/libz80
|
[libz80]: https://github.com/ggambetta/libz80
|
||||||
|
0
tools/emul/.gitignore → emul/.gitignore
vendored
0
tools/emul/.gitignore → emul/.gitignore
vendored
@ -1,27 +1,28 @@
|
|||||||
CFSPACK = ../cfspack/cfspack
|
CFSPACK_OBJ = ../tools/cfspack/libcfs.o
|
||||||
TARGETS = shell/shell zasm/zasm runbin/runbin
|
TARGETS = shell/shell zasm/zasm runbin/runbin
|
||||||
KERNEL = ../../kernel
|
KERNEL = ../kernel
|
||||||
APPS = ../../apps
|
APPS = ../apps
|
||||||
ZASMBIN = zasm/zasm
|
ZASMBIN = zasm/zasm
|
||||||
AVRABIN = zasm/avra
|
AVRABIN = zasm/avra
|
||||||
ZASMSH = ../zasm.sh
|
|
||||||
SHELLAPPS = zasm ed
|
SHELLAPPS = zasm ed
|
||||||
SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
|
SHELLTGTS = ${SHELLAPPS:%=cfsin/%}
|
||||||
CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
|
CFSIN_CONTENTS = $(SHELLTGTS) cfsin/user.h
|
||||||
OBJS = emul.o libz80/libz80.o
|
OBJS = emul.o libz80/libz80.o
|
||||||
|
SHELLOBJS = $(OBJS) $(CFSPACK_OBJ)
|
||||||
|
ZASMOBJS = $(SHELLOBJS)
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS)
|
all: $(TARGETS) $(AVRABIN) $(CFSIN_CONTENTS)
|
||||||
|
|
||||||
# -o in sync with SHELL_CODE in shell/glue.asm
|
# -o in sync with SHELL_CODE in shell/glue.asm
|
||||||
shell/shell.bin: shell/glue.asm $(ZASMBIN)
|
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
|
shell/shell-bin.h: shell/shell.bin
|
||||||
./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null
|
./bin2c.sh KERNEL < shell/shell.bin | tee $@ > /dev/null
|
||||||
|
|
||||||
shell/shell: shell/shell.c $(OBJS) shell/shell-bin.h
|
shell/shell: shell/shell.c $(SHELLOBJS) shell/shell-bin.h
|
||||||
$(CC) shell/shell.c $(OBJS) -o $@
|
$(CC) shell/shell.c $(SHELLOBJS) -o $@
|
||||||
|
|
||||||
zasm/kernel-bin.h: zasm/kernel.bin
|
zasm/kernel-bin.h: zasm/kernel.bin
|
||||||
./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null
|
./bin2c.sh KERNEL < zasm/kernel.bin | tee $@ > /dev/null
|
||||||
@ -29,17 +30,17 @@ zasm/kernel-bin.h: zasm/kernel.bin
|
|||||||
zasm/zasm-bin.h: zasm/zasm.bin
|
zasm/zasm-bin.h: zasm/zasm.bin
|
||||||
./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null
|
./bin2c.sh USERSPACE < zasm/zasm.bin | tee $@ > /dev/null
|
||||||
|
|
||||||
$(ZASMBIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK)
|
$(ZASMBIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/zasm-bin.h
|
||||||
$(CC) zasm/zasm.c $(OBJS) -o $@
|
$(CC) zasm/zasm.c $(ZASMOBJS) -o $@
|
||||||
|
|
||||||
zasm/avra.bin: $(ZASMBIN)
|
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
|
zasm/avra-bin.h: zasm/avra.bin
|
||||||
./bin2c.sh USERSPACE < zasm/avra.bin | tee $@ > /dev/null
|
./bin2c.sh USERSPACE < zasm/avra.bin | tee $@ > /dev/null
|
||||||
|
|
||||||
$(AVRABIN): zasm/zasm.c $(OBJS) zasm/kernel-bin.h zasm/avra-bin.h
|
$(AVRABIN): zasm/zasm.c $(ZASMOBJS) zasm/kernel-bin.h zasm/avra-bin.h
|
||||||
$(CC) -D AVRA zasm/zasm.c $(OBJS) -o $@
|
$(CC) -D AVRA zasm/zasm.c $(ZASMOBJS) -o $@
|
||||||
|
|
||||||
runbin/runbin: runbin/runbin.c $(OBJS)
|
runbin/runbin: runbin/runbin.c $(OBJS)
|
||||||
$(CC) runbin/runbin.c $(OBJS) -o $@
|
$(CC) runbin/runbin.c $(OBJS) -o $@
|
||||||
@ -51,20 +52,20 @@ libz80/libz80.o: libz80/z80.c
|
|||||||
emul.o: emul.c
|
emul.o: emul.c
|
||||||
$(CC) -c -o emul.o emul.c
|
$(CC) -c -o emul.o emul.c
|
||||||
|
|
||||||
$(CFSPACK):
|
$(CFSPACK_OBJ): ${@:%.o=%.c}
|
||||||
$(MAKE) -C ../cfspack
|
$(MAKE) -C ../tools/cfspack
|
||||||
|
|
||||||
# -o in sync with USER_CODE in shell/user.h
|
# -o in sync with USER_CODE in shell/user.h
|
||||||
$(SHELLTGTS): $(ZASMBIN)
|
$(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
|
cfsin/user.h: shell/user.h
|
||||||
cp shell/user.h $@
|
cp shell/user.h $@
|
||||||
|
|
||||||
.PHONY: updatebootstrap
|
.PHONY: updatebootstrap
|
||||||
updatebootstrap: $(ZASMBIN)
|
updatebootstrap: $(ZASMBIN)
|
||||||
$(ZASMSH) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
|
$(ZASMBIN) $(KERNEL) < zasm/glue.asm > zasm/kernel.bin
|
||||||
$(ZASMSH) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
|
$(ZASMBIN) $(KERNEL) $(APPS) zasm/user.h < $(APPS)/zasm/glue.asm > zasm/zasm.bin
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
@ -8,7 +8,7 @@ emulator.
|
|||||||
First, make sure that the `libz80` git submodule is checked out. If not, run
|
First, make sure that the `libz80` git submodule is checked out. If not, run
|
||||||
`git submodule init && git submodule update`.
|
`git submodule init && git submodule update`.
|
||||||
|
|
||||||
After that, you can run `make` and it builds all tools.
|
After that, you can run `make` and it builds all applications.
|
||||||
|
|
||||||
## shell
|
## shell
|
||||||
|
|
@ -4,6 +4,7 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include "../emul.h"
|
#include "../emul.h"
|
||||||
#include "shell-bin.h"
|
#include "shell-bin.h"
|
||||||
|
#include "../../tools/cfspack/cfs.h"
|
||||||
|
|
||||||
/* Collapse OS shell with filesystem
|
/* Collapse OS shell with filesystem
|
||||||
*
|
*
|
||||||
@ -138,21 +139,7 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "Can't open %s\n", optarg);
|
fprintf(stderr, "Can't open %s\n", optarg);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
fprintf(stderr, "Initializing filesystem from %s\n", optarg);
|
||||||
default:
|
|
||||||
fprintf(stderr, "Usage: shell [-f fsdev]\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Setup fs blockdev
|
|
||||||
if (fp == NULL) {
|
|
||||||
fp = popen("../cfspack/cfspack cfsin", "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
fprintf(stderr, "Can't initialize filesystem. Leaving blank.\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fp != NULL) {
|
|
||||||
fprintf(stderr, "Initializing filesystem\n");
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int c;
|
int c;
|
||||||
while ((c = fgetc(fp)) != EOF && i < MAX_FSDEV_SIZE) {
|
while ((c = fgetc(fp)) != EOF && i < MAX_FSDEV_SIZE) {
|
||||||
@ -163,8 +150,22 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pclose(fp);
|
pclose(fp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Usage: shell [-f fsdev]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Setup fs blockdev
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr, "Initializing filesystem from cfsin\n");
|
||||||
|
fp = fmemopen(fsdev, MAX_FSDEV_SIZE, "w");
|
||||||
|
set_spit_stream(fp);
|
||||||
|
if (spitdir("cfsin", "", NULL) != 0) {
|
||||||
|
fprintf(stderr, "Can't initialize filesystem. Leaving blank.\n");
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tty = isatty(fileno(stdin));
|
bool tty = isatty(fileno(stdin));
|
||||||
struct termios termInfo;
|
struct termios termInfo;
|
||||||
if (tty) {
|
if (tty) {
|
@ -1,7 +1,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include "../emul.h"
|
#include "../emul.h"
|
||||||
|
#include "../../tools/cfspack/cfs.h"
|
||||||
#include "kernel-bin.h"
|
#include "kernel-bin.h"
|
||||||
#ifdef AVRA
|
#ifdef AVRA
|
||||||
#include "avra-bin.h"
|
#include "avra-bin.h"
|
||||||
@ -51,6 +54,7 @@
|
|||||||
// By default, we don't spit what zasm prints. Too noisy. Define VERBOSE if
|
// By default, we don't spit what zasm prints. Too noisy. Define VERBOSE if
|
||||||
// you want to spit this content to stderr.
|
// you want to spit this content to stderr.
|
||||||
//#define VERBOSE
|
//#define VERBOSE
|
||||||
|
#define MAX_FSDEV_SIZE 0x80000
|
||||||
|
|
||||||
// STDIN buffer, allows us to seek and tell
|
// STDIN buffer, allows us to seek and tell
|
||||||
static uint8_t inpt[STDIN_BUFSIZE];
|
static uint8_t inpt[STDIN_BUFSIZE];
|
||||||
@ -58,8 +62,7 @@ static int inpt_size;
|
|||||||
static int inpt_ptr;
|
static int inpt_ptr;
|
||||||
static uint8_t middle_of_seek_tell = 0;
|
static uint8_t middle_of_seek_tell = 0;
|
||||||
|
|
||||||
static uint8_t fsdev[0x80000] = {0};
|
static uint8_t fsdev[MAX_FSDEV_SIZE] = {0};
|
||||||
static uint32_t fsdev_size = 0;
|
|
||||||
static uint32_t fsdev_ptr = 0;
|
static uint32_t fsdev_ptr = 0;
|
||||||
static uint8_t fsdev_seek_tell_cnt = 0;
|
static uint8_t fsdev_seek_tell_cnt = 0;
|
||||||
|
|
||||||
@ -88,7 +91,7 @@ static uint8_t iord_stdin_seek()
|
|||||||
|
|
||||||
static uint8_t iord_fsdata()
|
static uint8_t iord_fsdata()
|
||||||
{
|
{
|
||||||
if (fsdev_ptr < fsdev_size) {
|
if (fsdev_ptr < MAX_FSDEV_SIZE) {
|
||||||
return fsdev[fsdev_ptr++];
|
return fsdev[fsdev_ptr++];
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -99,7 +102,7 @@ static uint8_t iord_fsseek()
|
|||||||
{
|
{
|
||||||
if (fsdev_seek_tell_cnt != 0) {
|
if (fsdev_seek_tell_cnt != 0) {
|
||||||
return fsdev_seek_tell_cnt;
|
return fsdev_seek_tell_cnt;
|
||||||
} else if (fsdev_ptr >= fsdev_size) {
|
} else if (fsdev_ptr >= MAX_FSDEV_SIZE) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@ -130,7 +133,7 @@ static void iowr_stdin_seek(uint8_t val)
|
|||||||
|
|
||||||
static void iowr_fsdata(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;
|
fsdev[fsdev_ptr++] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,12 +162,51 @@ static void iowr_stderr(uint8_t val)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: zasm [-o org] [include-dir-or-file...] < source > binary\n");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc > 3) {
|
char *init_org = "00";
|
||||||
fprintf(stderr, "Too many args\n");
|
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;
|
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();
|
Machine *m = emul_init();
|
||||||
m->iord[STDIO_PORT] = iord_stdio;
|
m->iord[STDIO_PORT] = iord_stdio;
|
||||||
m->iord[STDIN_SEEK_PORT] = iord_stdin_seek;
|
m->iord[STDIN_SEEK_PORT] = iord_stdin_seek;
|
||||||
@ -182,31 +224,9 @@ int main(int argc, char *argv[])
|
|||||||
for (int i=0; i<sizeof(USERSPACE); i++) {
|
for (int i=0; i<sizeof(USERSPACE); i++) {
|
||||||
m->mem[i+USER_CODE] = 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.
|
// glue.asm knows that it needs to fetch these arguments at this address.
|
||||||
m->mem[0xff00] = init_org[0];
|
m->mem[0xff00] = init_org[0];
|
||||||
m->mem[0xff01] = init_org[1];
|
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
|
// read stdin in buffer
|
||||||
inpt_size = 0;
|
inpt_size = 0;
|
||||||
inpt_ptr = 0;
|
inpt_ptr = 0;
|
@ -1,9 +1,10 @@
|
|||||||
TARGET = os.bin
|
TARGET = os.bin
|
||||||
ZASM = ../../tools/zasm.sh
|
BASEDIR = ../..
|
||||||
KERNEL = ../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
$(TARGET): glue.asm
|
$(TARGET): glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
@ -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:
|
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.
|
Running `make` will also work.
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
TARGET = os.bin
|
TARGET = os.bin
|
||||||
ZASM = ../../../tools/zasm.sh
|
BASEDIR = ../../..
|
||||||
KERNEL = ../../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
$(TARGET): glue.asm
|
$(TARGET): glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ jp aciaInt
|
|||||||
.equ STDIO_PUTC aciaPutC
|
.equ STDIO_PUTC aciaPutC
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.inc "lib/args.asm"
|
|
||||||
.equ AT28W_RAMSTART STDIO_RAMEND
|
.equ AT28W_RAMSTART STDIO_RAMEND
|
||||||
.inc "at28w/main.asm"
|
.inc "at28w/main.asm"
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@ PROGNAME = ps2ctl
|
|||||||
AVRDUDEMCU ?= t45
|
AVRDUDEMCU ?= t45
|
||||||
AVRDUDEARGS ?= -c usbtiny -P usb
|
AVRDUDEARGS ?= -c usbtiny -P usb
|
||||||
TARGETS = $(PROGNAME).hex os.bin
|
TARGETS = $(PROGNAME).hex os.bin
|
||||||
ZASM = ../../../tools/zasm.sh
|
BASEDIR = ../../..
|
||||||
KERNEL = ../../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
|
|
||||||
@ -14,13 +15,13 @@ all: $(TARGETS)
|
|||||||
@echo Done!
|
@echo Done!
|
||||||
|
|
||||||
send: $(PROGNAME).hex
|
send: $(PROGNAME).hex
|
||||||
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
|
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
|
||||||
|
|
||||||
$(PROGNAME).hex: $(PROGNAME).asm
|
$(PROGNAME).hex: $(PROGNAME).asm
|
||||||
avra -o $@ $<
|
avra -o $@ $(PROGNAME).asm
|
||||||
|
|
||||||
os.bin: glue.asm
|
os.bin: glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGETS) *.eep.hex *.obj os.bin
|
rm -f $(TARGETS) *.eep.hex *.obj os.bin
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
TARGETS = os.bin cfsin/helo
|
TARGETS = os.bin cfsin/helo
|
||||||
TOOLS = ../../../tools
|
BASEDIR = ../../..
|
||||||
ZASM = $(TOOLS)/zasm.sh
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
KERNEL = ../../../kernel
|
KERNEL = $(BASEDIR)/kernel
|
||||||
APPS = ../../../apps
|
APPS = $(BASEDIR)/apps
|
||||||
CFSPACK = $(TOOLS)/cfspack/cfspack
|
CFSPACK = $(BASEDIR)/tools/cfspack/cfspack
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGETS) sdcard.cfs
|
all: $(TARGETS) sdcard.cfs
|
||||||
os.bin: glue.asm
|
os.bin: glue.asm
|
||||||
cfsin/helo: helo.asm
|
cfsin/helo: helo.asm
|
||||||
$(TARGETS):
|
$(TARGETS):
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
|
||||||
$(CFSPACK):
|
$(CFSPACK):
|
||||||
make -C $(TOOLS)/cfspack
|
make -C $(BASEDIR)/tools/cfspack
|
||||||
|
|
||||||
sdcard.cfs: cfsin $(CFSPACK)
|
sdcard.cfs: cfsin $(CFSPACK)
|
||||||
$(CFSPACK) $< > $@
|
$(CFSPACK) cfsin > $@
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
SHELLAPPS = zasm sdct memt at28w
|
SHELLAPPS = zasm sdct memt at28w
|
||||||
APPTARGETS = ${SHELLAPPS:%=cfsin/%}
|
APPTARGETS = ${SHELLAPPS:%=cfsin/%}
|
||||||
CFSTARGETS = $(APPTARGETS) cfsin/user.h
|
CFSTARGETS = $(APPTARGETS) cfsin/user.h
|
||||||
BASE = ../../..
|
BASEDIR = ../../..
|
||||||
TOOLS = $(BASE)/tools
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
ZASM = $(TOOLS)/zasm.sh
|
KERNEL = $(BASEDIR)/kernel
|
||||||
KERNEL = $(BASE)/kernel
|
APPS = $(BASEDIR)/apps
|
||||||
APPS = $(BASE)/apps
|
CFSPACK = $(BASEDIR)/tools/cfspack/cfspack
|
||||||
CFSPACK = $(TOOLS)/cfspack/cfspack
|
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: os.bin sdcard.cfs
|
all: os.bin sdcard.cfs
|
||||||
|
|
||||||
os.bin: glue.asm
|
os.bin: glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
|
||||||
$(CFSPACK):
|
$(CFSPACK):
|
||||||
make -C $(TOOLS)/cfspack
|
make -C $(BASEDIR)/tools/cfspack
|
||||||
|
|
||||||
sdcard.cfs: $(CFSTARGETS) $(CFSPACK)
|
sdcard.cfs: $(CFSTARGETS) $(CFSPACK)
|
||||||
$(CFSPACK) cfsin > $@
|
$(CFSPACK) cfsin > $@
|
||||||
@ -24,7 +23,7 @@ $(APPTARGETS): $(ZASMBIN)
|
|||||||
$(ZASM) $(KERNEL) $(APPS) user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
|
$(ZASM) $(KERNEL) $(APPS) user.h < $(APPS)/${@:cfsin/%=%}/glue.asm > $@
|
||||||
|
|
||||||
cfsin/user.h: user.h
|
cfsin/user.h: user.h
|
||||||
cp $< $@
|
cp user.h $@
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
TARGET = os.sms
|
TARGET = os.sms
|
||||||
ZASM = ../../tools/zasm.sh
|
BASEDIR = ../..
|
||||||
KERNEL = ../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
$(TARGET): glue.asm
|
$(TARGET): glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
@ -2,9 +2,10 @@ PROGNAME = ps2ctl
|
|||||||
AVRDUDEMCU ?= t45
|
AVRDUDEMCU ?= t45
|
||||||
AVRDUDEARGS ?= -c usbtiny -P usb
|
AVRDUDEARGS ?= -c usbtiny -P usb
|
||||||
TARGETS = $(PROGNAME).hex os.sms
|
TARGETS = $(PROGNAME).hex os.sms
|
||||||
ZASM = ../../../tools/zasm.sh
|
BASEDIR = ../../..
|
||||||
KERNEL = ../../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
|
|
||||||
@ -14,13 +15,13 @@ all: $(TARGETS)
|
|||||||
@echo Done!
|
@echo Done!
|
||||||
|
|
||||||
send: $(PROGNAME).hex
|
send: $(PROGNAME).hex
|
||||||
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$<
|
avrdude $(AVRDUDEARGS) -p $(AVRDUDEMCU) -U flash:w:$(PROGNAME).hex
|
||||||
|
|
||||||
$(PROGNAME).hex: $(PROGNAME).asm
|
$(PROGNAME).hex: $(PROGNAME).asm
|
||||||
avra -o $@ $<
|
avra -o $@ $(PROGNAME).asm
|
||||||
|
|
||||||
os.sms: glue.asm
|
os.sms: glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGETS) *.eep.hex *.obj os.bin
|
rm -f $(TARGETS) *.eep.hex *.obj os.bin
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
ZASM = ../../../tools/zasm.sh
|
BASEDIR = ../../..
|
||||||
KERNEL = ../../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
all: os.sms
|
all: os.sms
|
||||||
|
|
||||||
# -o value synced with offset in glue.asm
|
# -o value synced with offset in glue.asm
|
||||||
ed.bin: $(APPS)/ed/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
|
# -o value synced with offset in glue.asm
|
||||||
zasm.bin: $(APPS)/zasm/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
|
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:
|
clean:
|
||||||
rm -f os.sms ed.bin zasm.bin
|
rm -f os.sms ed.bin zasm.bin
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
TARGET = os.rom
|
TARGET = os.rom
|
||||||
ZASM = ../../tools/zasm.sh
|
BASEDIR = ../..
|
||||||
KERNEL = ../../kernel
|
ZASM = $(BASEDIR)/emul/zasm/zasm
|
||||||
APPS = ../../apps
|
KERNEL = $(BASEDIR)/kernel
|
||||||
|
APPS = $(BASEDIR)/apps
|
||||||
MKTIUPGRADE = mktiupgrade
|
MKTIUPGRADE = mktiupgrade
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
$(TARGET): glue.asm
|
$(TARGET): glue.asm
|
||||||
$(ZASM) $(KERNEL) $(APPS) < $< > $@
|
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@
|
||||||
truncate -s 1M $@
|
truncate -s 1M $@
|
||||||
|
|
||||||
os.8xu: $(TARGET)
|
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
|
.PHONY: send
|
||||||
send: os.8xu
|
send: os.8xu
|
||||||
tilp -n --calc ti84+ --cable DirectLink $<
|
tilp -n --calc ti84+ --cable DirectLink os.8xu
|
||||||
|
14
runtests.sh
14
runtests.sh
@ -4,15 +4,9 @@ git submodule init
|
|||||||
git submodule update
|
git submodule update
|
||||||
git clean -fxd
|
git clean -fxd
|
||||||
|
|
||||||
cd tools/emul
|
make -C emul
|
||||||
make
|
make -C tests
|
||||||
|
|
||||||
cd ../tests
|
|
||||||
make
|
|
||||||
|
|
||||||
# let's try again with an updated zasm
|
# let's try again with an updated zasm
|
||||||
cd ../emul
|
make -C emul updatebootstrap all
|
||||||
make updatebootstrap all
|
make -C tests
|
||||||
|
|
||||||
cd ../tests
|
|
||||||
make
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
EMULDIR = ../emul
|
EMULDIR = ../emul
|
||||||
CFSPACK = ../cfspack/cfspack
|
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
@ -8,10 +7,3 @@ run:
|
|||||||
cd zasm && ./runtests.sh
|
cd zasm && ./runtests.sh
|
||||||
cd avra && ./runtests.sh
|
cd avra && ./runtests.sh
|
||||||
cd shell && ./runtests.sh
|
cd shell && ./runtests.sh
|
||||||
|
|
||||||
$(CFSPACK):
|
|
||||||
$(MAKE) -C ../cfspack
|
|
||||||
|
|
||||||
.PHONY: cfs
|
|
||||||
cfs: $(CFSPACK)
|
|
||||||
$(CFSPACK) shell/cfsin > shell/test.cfs
|
|
@ -1,12 +1,12 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
ZASM=../../zasm.sh
|
ZASM=../../emul/zasm/avra
|
||||||
AVRINC=../../../avr
|
AVRINC=../../avr
|
||||||
|
|
||||||
cmpas() {
|
cmpas() {
|
||||||
FN=$1
|
FN=$1
|
||||||
EXPECTED=$(xxd ${FN%.*}.expected)
|
EXPECTED=$(xxd ${FN%.*}.expected)
|
||||||
ACTUAL=$(cat ${FN} | "${ZASM}" -a "${AVRINC}" | xxd)
|
ACTUAL=$(cat ${FN} | "${ZASM}" "${AVRINC}" | xxd)
|
||||||
if [ "$ACTUAL" = "$EXPECTED" ]; then
|
if [ "$ACTUAL" = "$EXPECTED" ]; then
|
||||||
echo ok
|
echo ok
|
||||||
else
|
else
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
EMULDIR=../../emul
|
EMULDIR=../../emul
|
||||||
SHELL=../../emul/shell/shell
|
SHELL="${EMULDIR}/shell/shell"
|
||||||
|
|
||||||
replay() {
|
replay() {
|
||||||
fn=$1
|
fn=$1
|
@ -2,10 +2,9 @@
|
|||||||
set -e
|
set -e
|
||||||
# TODO: find POSIX substitute to that PIPESTATUS thing
|
# TODO: find POSIX substitute to that PIPESTATUS thing
|
||||||
|
|
||||||
BASE=../../..
|
BASE=../..
|
||||||
TOOLS=../..
|
ZASM="${BASE}/emul/zasm/zasm"
|
||||||
ZASM="${TOOLS}/zasm.sh"
|
RUNBIN="${BASE}/emul/runbin/runbin"
|
||||||
RUNBIN="${TOOLS}/emul/runbin/runbin"
|
|
||||||
KERNEL="${BASE}/kernel"
|
KERNEL="${BASE}/kernel"
|
||||||
APPS="${BASE}/apps"
|
APPS="${BASE}/apps"
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# no "set -e" because we test errors
|
# no "set -e" because we test errors
|
||||||
|
|
||||||
ZASM=../../zasm.sh
|
ZASM=../../emul/zasm/zasm
|
||||||
|
|
||||||
chkerr() {
|
chkerr() {
|
||||||
echo "Check that '$1' results in error $2"
|
echo "Check that '$1' results in error $2"
|
@ -1,9 +1,9 @@
|
|||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
KERNEL=../../../kernel
|
BASE=../..
|
||||||
APPS=../../../apps
|
KERNEL="${BASE}/kernel"
|
||||||
ZASM=../../zasm.sh
|
APPS="${BASE}/apps"
|
||||||
ASMFILE=${APPS}/zasm/instr.asm
|
ZASM="${BASE}/emul/zasm/zasm"
|
||||||
|
|
||||||
cmpas() {
|
cmpas() {
|
||||||
FN=$1
|
FN=$1
|
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
*.o
|
|
||||||
/memdump
|
/memdump
|
||||||
/blkdump
|
/blkdump
|
||||||
/upload
|
/upload
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
TARGETS = cfspack cfsunpack
|
TARGETS = cfspack cfsunpack
|
||||||
|
|
||||||
|
CFSPACK_OBJS = cfspack.o libcfs.o
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
cfspack: cfspack.c
|
cfspack: $(CFSPACK_OBJS)
|
||||||
$(CC) $(CFLAGS) -o $@ cfspack.c
|
$(CC) $(LDFLAGS) -o $@ $(CFSPACK_OBJS)
|
||||||
|
|
||||||
cfsunpack: cfsunpack.c
|
cfsunpack: cfsunpack.c
|
||||||
$(CC) $(CFLAGS) -o $@ cfsunpack.c
|
$(CC) $(CFLAGS) -o $@ cfsunpack.c
|
||||||
|
10
tools/cfspack/cfs.h
Normal file
10
tools/cfspack/cfs.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#define BLKSIZE 0x100
|
||||||
|
#define HEADERSIZE 0x20
|
||||||
|
#define MAX_FN_LEN 25 // 26 - null char
|
||||||
|
#define MAX_FILE_SIZE (BLKSIZE * 0x100) - HEADERSIZE
|
||||||
|
|
||||||
|
void set_spit_stream(FILE *stream);
|
||||||
|
int is_regular_file(char *path);
|
||||||
|
void spitempty();
|
||||||
|
int spitblock(char *fullpath, char *fn);
|
||||||
|
int spitdir(char *path, char *prefix, char **patterns);
|
@ -7,139 +7,7 @@
|
|||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define BLKSIZE 0x100
|
#include "cfs.h"
|
||||||
#define HEADERSIZE 0x20
|
|
||||||
#define MAX_FN_LEN 25 // 26 - null char
|
|
||||||
#define MAX_FILE_SIZE (BLKSIZE * 0x100) - HEADERSIZE
|
|
||||||
|
|
||||||
int is_regular_file(char *path)
|
|
||||||
{
|
|
||||||
struct stat path_stat;
|
|
||||||
stat(path, &path_stat);
|
|
||||||
return S_ISREG(path_stat.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void spitempty()
|
|
||||||
{
|
|
||||||
putchar('C');
|
|
||||||
putchar('F');
|
|
||||||
putchar('S');
|
|
||||||
for (int i=0; i<0x20-3; i++) {
|
|
||||||
putchar(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int spitblock(char *fullpath, char *fn)
|
|
||||||
{
|
|
||||||
FILE *fp = fopen(fullpath, "r");
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
long fsize = ftell(fp);
|
|
||||||
if (fsize > MAX_FILE_SIZE) {
|
|
||||||
fclose(fp);
|
|
||||||
fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Compute block count.
|
|
||||||
* We always have at least one, which contains 0x100 bytes - 0x20, which is
|
|
||||||
* metadata. The rest of the blocks have a steady 0x100.
|
|
||||||
*/
|
|
||||||
unsigned char blockcount = 1;
|
|
||||||
int fsize2 = fsize - (BLKSIZE - HEADERSIZE);
|
|
||||||
if (fsize2 > 0) {
|
|
||||||
blockcount += (fsize2 / BLKSIZE);
|
|
||||||
}
|
|
||||||
if (blockcount * BLKSIZE < fsize + HEADERSIZE) {
|
|
||||||
blockcount++;
|
|
||||||
}
|
|
||||||
putchar('C');
|
|
||||||
putchar('F');
|
|
||||||
putchar('S');
|
|
||||||
putchar(blockcount);
|
|
||||||
// file size is little endian
|
|
||||||
putchar(fsize & 0xff);
|
|
||||||
putchar((fsize >> 8) & 0xff);
|
|
||||||
int fnlen = strlen(fn);
|
|
||||||
for (int i=0; i<MAX_FN_LEN; i++) {
|
|
||||||
if (i < fnlen) {
|
|
||||||
putchar(fn[i]);
|
|
||||||
} else {
|
|
||||||
putchar(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// And the last FN char which is always null
|
|
||||||
putchar(0);
|
|
||||||
char buf[MAX_FILE_SIZE] = {0};
|
|
||||||
rewind(fp);
|
|
||||||
fread(buf, fsize, 1, fp);
|
|
||||||
fclose(fp);
|
|
||||||
fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int spitdir(char *path, char *prefix, char **patterns)
|
|
||||||
{
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *ep;
|
|
||||||
|
|
||||||
int prefixlen = strlen(prefix);
|
|
||||||
dp = opendir(path);
|
|
||||||
if (dp == NULL) {
|
|
||||||
fprintf(stderr, "Couldn't open directory.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
while (ep = readdir(dp)) {
|
|
||||||
if ((strcmp(ep->d_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ep->d_type != DT_DIR && ep->d_type != DT_REG) {
|
|
||||||
fprintf(stderr, "Only regular file or directories are supported\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int slen = strlen(ep->d_name);
|
|
||||||
if (prefixlen + slen> MAX_FN_LEN) {
|
|
||||||
fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
char fullpath[0x1000];
|
|
||||||
strcpy(fullpath, path);
|
|
||||||
strcat(fullpath, "/");
|
|
||||||
strcat(fullpath, ep->d_name);
|
|
||||||
char newprefix[MAX_FN_LEN];
|
|
||||||
strcpy(newprefix, prefix);
|
|
||||||
if (prefixlen > 0) {
|
|
||||||
strcat(newprefix, "/");
|
|
||||||
}
|
|
||||||
strcat(newprefix, ep->d_name);
|
|
||||||
if (ep->d_type == DT_DIR) {
|
|
||||||
int r = spitdir(fullpath, newprefix, patterns);
|
|
||||||
if (r != 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char **p = patterns;
|
|
||||||
// if we have no pattern, we match all
|
|
||||||
int matches = (*p) == NULL ? 1 : 0;
|
|
||||||
while (*p) {
|
|
||||||
if (fnmatch(*p, ep->d_name, 0) == 0) {
|
|
||||||
matches = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (!matches) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int r = spitblock(fullpath, newprefix);
|
|
||||||
if (r != 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usage()
|
void usage()
|
||||||
{
|
{
|
||||||
|
152
tools/cfspack/libcfs.c
Normal file
152
tools/cfspack/libcfs.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "cfs.h"
|
||||||
|
|
||||||
|
#define PUTC(c) putc(c, spitstream)
|
||||||
|
|
||||||
|
static FILE *spitstream = NULL;
|
||||||
|
|
||||||
|
void set_spit_stream(FILE *stream)
|
||||||
|
{
|
||||||
|
spitstream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_regular_file(char *path)
|
||||||
|
{
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path, &path_stat);
|
||||||
|
return S_ISREG(path_stat.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spitempty()
|
||||||
|
{
|
||||||
|
if (spitstream == NULL) spitstream = stdout;
|
||||||
|
PUTC('C');
|
||||||
|
PUTC('F');
|
||||||
|
PUTC('S');
|
||||||
|
for (int i=0; i<0x20-3; i++) {
|
||||||
|
PUTC(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int spitblock(char *fullpath, char *fn)
|
||||||
|
{
|
||||||
|
if (spitstream == NULL) spitstream = stdout;
|
||||||
|
FILE *fp = fopen(fullpath, "r");
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
long fsize = ftell(fp);
|
||||||
|
if (fsize > MAX_FILE_SIZE) {
|
||||||
|
fclose(fp);
|
||||||
|
fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Compute block count.
|
||||||
|
* We always have at least one, which contains 0x100 bytes - 0x20, which is
|
||||||
|
* metadata. The rest of the blocks have a steady 0x100.
|
||||||
|
*/
|
||||||
|
unsigned char blockcount = 1;
|
||||||
|
int fsize2 = fsize - (BLKSIZE - HEADERSIZE);
|
||||||
|
if (fsize2 > 0) {
|
||||||
|
blockcount += (fsize2 / BLKSIZE);
|
||||||
|
}
|
||||||
|
if (blockcount * BLKSIZE < fsize + HEADERSIZE) {
|
||||||
|
blockcount++;
|
||||||
|
}
|
||||||
|
PUTC('C');
|
||||||
|
PUTC('F');
|
||||||
|
PUTC('S');
|
||||||
|
PUTC(blockcount);
|
||||||
|
// file size is little endian
|
||||||
|
PUTC(fsize & 0xff);
|
||||||
|
PUTC((fsize >> 8) & 0xff);
|
||||||
|
int fnlen = strlen(fn);
|
||||||
|
for (int i=0; i<MAX_FN_LEN; i++) {
|
||||||
|
if (i < fnlen) {
|
||||||
|
PUTC(fn[i]);
|
||||||
|
} else {
|
||||||
|
PUTC(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// And the last FN char which is always null
|
||||||
|
PUTC(0);
|
||||||
|
char buf[MAX_FILE_SIZE] = {0};
|
||||||
|
rewind(fp);
|
||||||
|
fread(buf, fsize, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, spitstream);
|
||||||
|
fflush(spitstream);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spitdir(char *path, char *prefix, char **patterns)
|
||||||
|
{
|
||||||
|
DIR *dp;
|
||||||
|
struct dirent *ep;
|
||||||
|
|
||||||
|
int prefixlen = strlen(prefix);
|
||||||
|
dp = opendir(path);
|
||||||
|
if (dp == NULL) {
|
||||||
|
fprintf(stderr, "Couldn't open directory.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
while ((ep = readdir(dp))) {
|
||||||
|
if ((strcmp(ep->d_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ep->d_type != DT_DIR && ep->d_type != DT_REG) {
|
||||||
|
fprintf(stderr, "Only regular file or directories are supported\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int slen = strlen(ep->d_name);
|
||||||
|
if (prefixlen + slen> MAX_FN_LEN) {
|
||||||
|
fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char fullpath[0x1000];
|
||||||
|
strcpy(fullpath, path);
|
||||||
|
strcat(fullpath, "/");
|
||||||
|
strcat(fullpath, ep->d_name);
|
||||||
|
char newprefix[MAX_FN_LEN];
|
||||||
|
strcpy(newprefix, prefix);
|
||||||
|
if (prefixlen > 0) {
|
||||||
|
strcat(newprefix, "/");
|
||||||
|
}
|
||||||
|
strcat(newprefix, ep->d_name);
|
||||||
|
if (ep->d_type == DT_DIR) {
|
||||||
|
int r = spitdir(fullpath, newprefix, patterns);
|
||||||
|
if (r != 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
char **p = patterns;
|
||||||
|
// if we have no pattern, we match all
|
||||||
|
if (p && *p) {
|
||||||
|
int matches = 0;
|
||||||
|
while (*p) {
|
||||||
|
if (fnmatch(*p, ep->d_name, 0) == 0) {
|
||||||
|
matches = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (!matches) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int r = spitblock(fullpath, newprefix);
|
||||||
|
if (r != 0) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dp);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Calls tools/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}/emul/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}/emul/zasm/avra"
|
|
||||||
;;
|
|
||||||
o)
|
|
||||||
org=${OPTARG}
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND-1))
|
|
||||||
|
|
||||||
# wrapper around ./emul/zasm/zasm that prepares includes CFS prior to call
|
|
||||||
CFSPACK="${DIR}/cfspack/cfspack"
|
|
||||||
INCCFS=$(mktemp)
|
|
||||||
|
|
||||||
"${CFSPACK}" -p "*.h" -p "*.asm" -p "*.bin" "$@" > "${INCCFS}"
|
|
||||||
|
|
||||||
"${ZASMBIN}" "${org}" "${INCCFS}"
|
|
||||||
RES=$?
|
|
||||||
rm "${INCCFS}"
|
|
||||||
exit $RES
|
|
Loading…
Reference in New Issue
Block a user