1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 19:28:06 +11:00

Compare commits

..

No commits in common. "c0b7b455700c96623cbd47a0d3dd41d6a3e8cac5" and "8d3da4c0de00d5c7f4b98cc0710cb23c0af20624" have entirely different histories.

8 changed files with 172 additions and 124 deletions

View File

@ -1,5 +1,6 @@
TARGETS = forth stage blkfs
OBJS = emul.o libz80/libz80.o
BIN2C = ../tools/bin2c
BLKPACK = ../tools/blkpack
BLKUNPACK = ../tools/blkunpack
@ -9,29 +10,34 @@ all: $(TARGETS)
$(BLKPACK):
$(MAKE) -C ../tools
.PHONY: $(BLKUNPACK)
.PHONY: $(BIN2C) $(BLKUNPACK)
$(BIN2C): $(BLKPACK)
$(BLKUNPACK): $(BLKPACK)
stage: stage.c $(OBJS)
$(CC) stage.c $(OBJS) -o $@
# not dependent on forth.bin to avoid circular deps.
forth-bin.h: $(BIN2C)
$(BIN2C) KERNEL < forth.bin > $@
stage: stage.c $(OBJS) forth-bin.h
$(CC) stage.c -DBLKFS_PATH=\"`pwd`/blkfs\" $(OBJS) -o $@
blkfs: $(BLKPACK)
$(BLKPACK) ../blk > $@
forth: forth.c $(OBJS)
$(CC) forth.c $(OBJS) -lncurses -o $@
forth: forth.c $(OBJS) forth-bin.h
$(CC) forth.c -DBLKFS_PATH=\"`pwd`/blkfs\" $(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
$(CC) -c -o emul.o emul.c
.PHONY: updatebootstrap
updatebootstrap: stage xcomp.fs pack
./stage < xcomp.fs | tee forth.bin > /dev/null
./stage < xcomp.fs > forth.bin
.PHONY: pack
pack:

View File

@ -25,25 +25,16 @@ First, make sure that the `libz80` git submodule is checked out. If not, run
After that, you can run `make` and it builds the `forth` interpreter.
## Usage
Run `./forth` to get the Collapse OS prompt. 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 (which is yet to implement).
## Problems?
If the `forth` executable works badly (hangs, spew garbage, etc.),
If the libz80-wrapped zasm executable works badly (hangs, spew garbage, etc.),
it's probably because you've broken your bootstrap binaries. They're 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`.

View File

@ -1,26 +1,13 @@
/* Common code between forth and stage binaries.
/* Common code between shell, zasm and runbin.
They all run on the same kind of virtual machine: A z80 CPU, 64K of RAM/ROM.
*/
#include <string.h>
#include "emul.h"
// Port for block reads. Write 2 bytes, MSB first, on that port and then
// read 1024 bytes from the DATA port.
#define BLK_PORT 0x03
#define BLKDATA_PORT 0x04
#ifndef BLKFS_PATH
#error BLKFS_PATH needed
#endif
#ifndef FBIN_PATH
#error FBIN_PATH needed
#endif
static Machine m;
static ushort traceval = 0;
static uint16_t blkid = 0;
static FILE *blkfp;
static uint8_t io_read(int unused, uint16_t addr)
{
@ -45,23 +32,6 @@ static void io_write(int unused, uint16_t addr, uint8_t val)
}
}
static void iowr_blk(uint8_t val)
{
blkid <<= 8;
blkid |= val;
fseek(blkfp, blkid*1024, SEEK_SET);
}
static uint8_t iord_blkdata()
{
return getc(blkfp);
}
static void iowr_blkdata(uint8_t val)
{
putc(val, blkfp);
}
static uint8_t mem_read(int unused, uint16_t addr)
{
return m.mem[addr];
@ -80,26 +50,7 @@ static void mem_write(int unused, uint16_t addr, uint8_t val)
Machine* emul_init()
{
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH);
blkfp = fopen(BLKFS_PATH, "r+");
if (!blkfp) {
fprintf(stderr, "Can't open\n");
return NULL;
}
// initialize memory
memset(m.mem, 0, 0x10000);
FILE *bfp = fopen(FBIN_PATH, "r");
if (!bfp) {
fprintf(stderr, "Can't open forth.bin\n");
return NULL;
}
int i = 0;
int c = getc(bfp);
while (c != EOF) {
m.mem[i++] = c;
c = getc(bfp);
}
fclose(bfp);
m.ramstart = 0;
m.minsp = 0xffff;
m.maxix = 0;
@ -112,16 +63,9 @@ Machine* emul_init()
m.cpu.memWrite = mem_write;
m.cpu.ioRead = io_read;
m.cpu.ioWrite = io_write;
m.iowr[BLK_PORT] = iowr_blk;
m.iord[BLKDATA_PORT] = iord_blkdata;
m.iowr[BLKDATA_PORT] = iowr_blkdata;
return &m;
}
void emul_deinit()
{
fclose(blkfp);
}
bool emul_step()
{
@ -173,12 +117,6 @@ void emul_memdump()
fclose(fp);
}
void emul_debugstr(char *s)
{
sprintf(s, "SP %04x (%04x) IX %04x (%04x)",
m.cpu.R1.wr.SP, m.minsp, m.cpu.R1.wr.IX, m.maxix);
}
void emul_printdebug()
{
fprintf(stderr, "Min SP: %04x\n", m.minsp);

View File

@ -29,11 +29,9 @@ typedef enum {
} Tristate;
Machine* emul_init();
void emul_deinit();
bool emul_step();
bool emul_steps(unsigned int steps);
void emul_loop();
void emul_trace(ushort addr);
void emul_memdump();
void emul_debugstr(char *s);
void emul_printdebug();

View File

@ -4,9 +4,8 @@
#include <curses.h>
#include <termios.h>
#include "emul.h"
#include "forth-bin.h"
#define WCOLS 80
#define WLINES 32
// in sync with glue.asm
#define RAMSTART 0x900
#define STDIO_PORT 0x00
@ -19,16 +18,9 @@
#define BLKDATA_PORT 0x04
static FILE *fp;
static FILE *blkfp;
static int retcode = 0;
WINDOW *bw, *dw, *w;
void debug_panel()
{
char buf[30];
emul_debugstr(buf);
mvwaddnstr(dw, 0, 0, buf, 30);
wrefresh(dw);
}
static uint16_t blkid = 0;
static uint8_t iord_stdio()
{
@ -36,8 +28,7 @@ static uint8_t iord_stdio()
if (fp != NULL) {
c = getc(fp);
} else {
debug_panel();
c = wgetch(w);
c = getch();
}
if (c == EOF) {
c = 4; // ASCII EOT
@ -51,10 +42,7 @@ static void iowr_stdio(uint8_t val)
putchar(val);
} else {
if (val >= 0x20 || val == '\n') {
wechochar(w, val);
} else if (val == 0x08) {
int y, x; getyx(w, y, x);
wmove(w, y, x-1);
echochar(val);
}
}
}
@ -64,46 +52,89 @@ static void iowr_ret(uint8_t val)
retcode = val;
}
int main(int argc, char *argv[])
static void iowr_blk(uint8_t val)
{
Machine *m = emul_init();
if (m == NULL) {
return 1;
blkid <<= 8;
blkid |= val;
if (blkfp != NULL) {
fseek(blkfp, blkid*1024, SEEK_SET);
}
}
static uint8_t iord_blkdata()
{
uint8_t res = 0;
if (blkfp != NULL) {
int c = getc(blkfp);
if (c != EOF) {
res = c;
}
}
return res;
}
static void iowr_blkdata(uint8_t val)
{
if (blkfp != NULL) {
putc(val, blkfp);
}
}
int run()
{
#ifdef BLKFS_PATH
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH);
blkfp = fopen(BLKFS_PATH, "r+");
if (!blkfp) {
fprintf(stderr, "Can't open\n");
}
#else
blkfp = NULL;
#endif
Machine *m = emul_init();
m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[RET_PORT] = iowr_ret;
w = NULL;
m->iowr[BLK_PORT] = iowr_blk;
m->iord[BLKDATA_PORT] = iord_blkdata;
m->iowr[BLKDATA_PORT] = iowr_blkdata;
// initialize memory
for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i];
}
// Run!
while (emul_step());
if (blkfp != NULL) {
fclose(blkfp);
}
return retcode;
}
int main(int argc, char *argv[])
{
if (argc == 2) {
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Can't open %s\n", argv[1]);
return 1;
}
while (emul_step());
int ret = run();
fclose(fp);
return ret;
} else if (argc == 1) {
fp = NULL;
initscr(); cbreak(); noecho(); nl(); clear();
// border window
bw = newwin(WLINES+2, WCOLS+2, 0, 0);
wborder(bw, 0, 0, 0, 0, 0, 0, 0, 0);
wrefresh(bw);
// debug panel
dw = newwin(1, 30, LINES-1, COLS-30);
w = newwin(WLINES, WCOLS, 1, 1);
scrollok(w, 1);
while (emul_steps(1000)) {
debug_panel();
}
nocbreak(); echo(); delwin(w); delwin(bw); delwin(dw); endwin();
scrollok(stdscr, 1);
int ret = run();
nocbreak(); echo(); endwin();
printf("\nDone!\n");
emul_printdebug();
return ret;
} else {
fprintf(stderr, "Usage: ./forth [filename]\n");
retcode = 1;
return 1;
}
emul_deinit();
return retcode;
}

View File

@ -2,6 +2,11 @@
#include <stdio.h>
#include <unistd.h>
#include "emul.h"
#include "forth-bin.h"
#ifndef BLKFS_PATH
#error BLKFS_PATH needed
#endif
/* Staging binaries
@ -23,6 +28,10 @@ trouble of compiling defs to binary.
// 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
// Port for block reads. Write 2 bytes, MSB first, on that port and then
// read 1024 bytes from the DATA port.
#define BLK_PORT 0x03
#define BLKDATA_PORT 0x04
static int running;
// We support double-pokes, that is, a first poke to tell where to start the
@ -30,6 +39,8 @@ static int running;
// then ending HERE and we start at sizeof(KERNEL).
static uint16_t start_here = 0;
static uint16_t end_here = 0;
static uint16_t blkid = 0;
static FILE *blkfp;
static uint8_t iord_stdio()
{
@ -53,16 +64,38 @@ static void iowr_here(uint8_t val)
end_here |= val;
}
static void iowr_blk(uint8_t val)
{
blkid <<= 8;
blkid |= val;
fseek(blkfp, blkid*1024, SEEK_SET);
}
static uint8_t iord_blkdata()
{
return getc(blkfp);
}
int main(int argc, char *argv[])
{
Machine *m = emul_init();
if (m == NULL) {
fprintf(stderr, "Using blkfs %s\n", BLKFS_PATH);
blkfp = fopen(BLKFS_PATH, "r+");
if (!blkfp) {
fprintf(stderr, "Can't open\n");
return 1;
}
Machine *m = emul_init();
m->ramstart = RAMSTART;
m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[HERE_PORT] = iowr_here;
m->iowr[BLK_PORT] = iowr_blk;
m->iord[BLKDATA_PORT] = iord_blkdata;
// initialize memory
for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i];
}
// Run!
running = 1;
@ -72,7 +105,6 @@ int main(int argc, char *argv[])
for (int i=start_here; i<end_here; i++) {
putchar(m->mem[i]);
}
emul_deinit();
emul_printdebug();
return 0;
}

View File

@ -2,12 +2,13 @@ MEMDUMP_TGT = memdump
UPLOAD_TGT = upload
TTYSAFE_TGT = ttysafe
PINGPONG_TGT = pingpong
BIN2C_TGT = bin2c
EXEC_TGT = exec
BLKPACK_TGT = blkpack
BLKUNPACK_TGT = blkunpack
BLKUP_TGT = blkup
TARGETS = $(MEMDUMP_TGT) $(UPLOAD_TGT) \
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(EXEC_TGT) $(BLKPACK_TGT) \
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) \
$(BLKUNPACK_TGT) $(BLKUP_TGT)
OBJS = common.o
@ -21,6 +22,7 @@ $(MEMDUMP_TGT): $(MEMDUMP_TGT).c
$(UPLOAD_TGT): $(UPLOAD_TGT).c
$(TTYSAFE_TGT): $(TTYSAFE_TGT).c
$(PINGPONG_TGT): $(PINGPONG_TGT).c
$(BIN2C_TGT): $(BIN2C_TGT).c
$(EXEC_TGT): $(EXEC_TGT).c
$(BLKPACK_TGT): $(BLKPACK_TGT).c
$(BLKUNPACK_TGT): $(BLKUNPACK_TGT).c

50
tools/bin2c.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 Byron Grobe
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BUFSZ 32
static const char intro[] = "static const unsigned char %s[] = {\n ";
int main(int argc, char **argv) {
int n;
int col = 0;
uint8_t buf[BUFSZ];
if (argc < 2) {
fprintf(stderr, "Specify a name for the data structure...\n");
return 1;
}
printf(intro, argv[1]);
while(!feof(stdin)) {
n = fread(buf, 1, BUFSZ, stdin);
for(int i = 0; i < n; ++i) {
if (col+4 >= 76) {
printf("\n ");
col = 0;
}
printf("0x%.2x, ", buf[i]);
col += 6;
}
}
printf("};\n");
}