mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 12:58:09 +11:00
basic: add fls command
Also, add the new `bshell` emulated tool. BASIC is on its way to replace the shell.
This commit is contained in:
parent
aad8efeff7
commit
13f935aa88
@ -25,6 +25,16 @@ Because the goal is not to provide a foundation for complex programs, I'm
|
||||
planning on intentionally crippling this BASIC dialect for the sake of
|
||||
simplicity.
|
||||
|
||||
## Glueing
|
||||
|
||||
The `glue.asm` file in this folder represents the minimal basic system. There
|
||||
are additional modules that can be added that aren't added by default, such
|
||||
as `fs.asm` because they require kernel options that might not be available.
|
||||
|
||||
To include these modules, you'll need to write your own glue file and to hook
|
||||
extra commands through `BAS_FINDHOOK`. Look for examples in `tools/emul` and
|
||||
in recipes.
|
||||
|
||||
## Usage
|
||||
|
||||
Upon launch, a prompt is presented, waiting for a command. There are two types
|
||||
@ -123,3 +133,14 @@ output I/O on port 42 with value 3.
|
||||
|
||||
**sleep**: Sleep a number of "units" specified by the supplied expression. A
|
||||
"unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 microseconds.
|
||||
|
||||
## Optional modules
|
||||
|
||||
As explained in "glueing" section abolve, this folder contains optional modules.
|
||||
Here's the documentation for them.
|
||||
|
||||
### fs
|
||||
|
||||
`fs.asm` provides those commands:
|
||||
|
||||
**fls**: prints the list of files contained in the active filesystem.
|
||||
|
15
apps/basic/fs.asm
Normal file
15
apps/basic/fs.asm
Normal file
@ -0,0 +1,15 @@
|
||||
; FS-related basic commands
|
||||
|
||||
basFLS:
|
||||
ld iy, .iter
|
||||
jp fsIter
|
||||
.iter:
|
||||
ld a, FS_META_FNAME_OFFSET
|
||||
call addHL
|
||||
call printstr
|
||||
jp printcrlf
|
||||
|
||||
basFSCmds:
|
||||
.dw basFLS
|
||||
.db "fls", 0, 0, 0
|
||||
.db 0xff, 0xff, 0xff ; end of table
|
@ -7,6 +7,7 @@
|
||||
.inc "user.h"
|
||||
.inc "err.h"
|
||||
|
||||
call basInit
|
||||
jp basStart
|
||||
|
||||
; RAM space used in different routines for short term processing.
|
||||
|
@ -7,16 +7,24 @@
|
||||
; Important note: this is **not** a line number, it's a pointer to a line index
|
||||
; in buffer. If it's not zero, its a valid pointer.
|
||||
.equ BAS_PNEXTLN @+2
|
||||
; Points to a routine to call when a command isn't found in the "core" cmd
|
||||
; table. This gives the opportunity to glue code to configure extra commands.
|
||||
.equ BAS_FINDHOOK @+2
|
||||
.equ BAS_RAMEND @+2
|
||||
|
||||
; *** Code ***
|
||||
basStart:
|
||||
basInit:
|
||||
ld (BAS_INITSP), sp
|
||||
call varInit
|
||||
call bufInit
|
||||
xor a
|
||||
ld (BAS_PNEXTLN), a
|
||||
ld (BAS_PNEXTLN+1), a
|
||||
ld hl, unsetZ
|
||||
ld (BAS_FINDHOOK), hl
|
||||
ret
|
||||
|
||||
basStart:
|
||||
ld hl, .welcome
|
||||
call printstr
|
||||
call printcrlf
|
||||
@ -48,10 +56,35 @@ basLoop:
|
||||
.sPrompt:
|
||||
.db "> ", 0
|
||||
|
||||
; Tries to find command specified in (DE) (must be null-terminated) in cmd
|
||||
; table in (HL). If found, sets IX to point to the associated routine. If
|
||||
; not found, calls BAS_FINDHOOK so that we look through extra commands
|
||||
; configured by glue code.
|
||||
; Destroys HL.
|
||||
; Z is set if found, unset otherwise.
|
||||
basFindCmd:
|
||||
; cmd table starts with routine pointer, skip
|
||||
inc hl \ inc hl
|
||||
.loop:
|
||||
call strcmp
|
||||
jr z, .found
|
||||
ld a, 8
|
||||
call addHL
|
||||
ld a, (hl)
|
||||
cp 0xff
|
||||
jr nz, .loop
|
||||
jp unsetZ
|
||||
.found:
|
||||
dec hl \ dec hl
|
||||
call intoHL
|
||||
push hl \ pop ix
|
||||
ret
|
||||
|
||||
; Call command in (HL) after having looked for it in cmd table in (DE).
|
||||
; If found, jump to it. If not found, unset Z. We expect commands to set Z
|
||||
; on success. Therefore, when calling basCallCmd results in NZ, we're not sure
|
||||
; where the error come from, but well...
|
||||
; If found, jump to it. If not found, try (BAS_FINDHOOK). If still not found,
|
||||
; unset Z. We expect commands to set Z on success. Therefore, when calling
|
||||
; basCallCmd results in NZ, we're not sure where the error come from, but
|
||||
; well...
|
||||
basCallCmd:
|
||||
; let's see if it's a variable assignment.
|
||||
call varTryAssign
|
||||
@ -64,24 +97,17 @@ basCallCmd:
|
||||
; cmd table in the stack, which we want in HL and we have the rest of
|
||||
; the cmdline in (HL), which we want in the stack!
|
||||
ex (sp), hl
|
||||
inc hl \ inc hl
|
||||
.loop:
|
||||
call strcmp
|
||||
jr z, .found
|
||||
ld a, 8
|
||||
call addHL
|
||||
ld a, (hl)
|
||||
cp 0xff
|
||||
jr nz, .loop
|
||||
; not found
|
||||
pop hl ; <-- lvl 1
|
||||
jp unsetZ
|
||||
.found:
|
||||
dec hl \ dec hl
|
||||
call intoHL
|
||||
push hl \ pop ix
|
||||
call basFindCmd
|
||||
jr z, .skip
|
||||
; not found, try BAS_FINDHOOK
|
||||
ld ix, (BAS_FINDHOOK)
|
||||
call callIX
|
||||
.skip:
|
||||
; regardless of the result, we need to balance the stack.
|
||||
; Bring back rest of the command string from the stack
|
||||
pop hl ; <-- lvl 1
|
||||
ret nz
|
||||
; cmd found, skip whitespace and then jump!
|
||||
call rdSep
|
||||
jp (ix)
|
||||
|
||||
|
1
tools/emul/.gitignore
vendored
1
tools/emul/.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
/shell/shell
|
||||
/bshell/shell
|
||||
/zasm/zasm
|
||||
/runbin/runbin
|
||||
/*/*-bin.h
|
||||
|
@ -1,10 +1,10 @@
|
||||
CFSPACK = ../cfspack/cfspack
|
||||
TARGETS = shell/shell zasm/zasm runbin/runbin
|
||||
TARGETS = shell/shell bshell/shell zasm/zasm runbin/runbin
|
||||
KERNEL = ../../kernel
|
||||
APPS = ../../apps
|
||||
ZASMBIN = zasm/zasm
|
||||
ZASMSH = ../zasm.sh
|
||||
SHELLAPPS = $(addprefix cfsin/, zasm ed basic)
|
||||
SHELLAPPS = $(addprefix cfsin/, zasm ed)
|
||||
CFSIN_CONTENTS = $(SHELLAPPS) cfsin/user.h
|
||||
|
||||
.PHONY: all
|
||||
@ -17,6 +17,12 @@ shell/shell.bin: $(APPS)/shell/glue.asm $(ZASMBIN)
|
||||
shell/kernel-bin.h: shell/glue.asm shell/shell.bin $(ZASMBIN)
|
||||
$(ZASMSH) $(KERNEL) shell/shell.bin < $< | ./bin2c.sh KERNEL | tee $@ > /dev/null
|
||||
|
||||
bshell/shell.bin: bshell/glue.asm $(ZASMBIN)
|
||||
$(ZASMSH) $(KERNEL) bshell/user.h $(APPS) < $< | tee $@ > /dev/null
|
||||
|
||||
bshell/shell-bin.h: bshell/shell.bin
|
||||
./bin2c.sh KERNEL < $< | tee $@ > /dev/null
|
||||
|
||||
zasm/kernel-bin.h: zasm/kernel.bin
|
||||
./bin2c.sh KERNEL < $< | tee $@ > /dev/null
|
||||
|
||||
@ -24,6 +30,7 @@ zasm/zasm-bin.h: zasm/zasm.bin
|
||||
./bin2c.sh USERSPACE < $< | tee $@ > /dev/null
|
||||
|
||||
shell/shell: shell/shell.c libz80/libz80.o shell/kernel-bin.h
|
||||
bshell/shell: bshell/shell.c libz80/libz80.o bshell/shell-bin.h
|
||||
$(ZASMBIN): zasm/zasm.c libz80/libz80.o zasm/kernel-bin.h zasm/zasm-bin.h $(CFSPACK)
|
||||
runbin/runbin: runbin/runbin.c libz80/libz80.o
|
||||
$(TARGETS):
|
||||
@ -50,4 +57,4 @@ updatebootstrap: $(ZASMBIN) $(INCCFS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(TARGETS) $(SHELLAPPS) {zasm,shell}/*-bin.h
|
||||
rm -f $(TARGETS) $(SHELLAPPS) zasm/*-bin.h shell/*-bin.h
|
||||
|
@ -25,6 +25,11 @@ We don't try to emulate real hardware to ease the development of device drivers
|
||||
because so far, I don't see the advantage of emulation versus running code on
|
||||
the real thing.
|
||||
|
||||
## bshell
|
||||
|
||||
The `basic` app is on its way to replace the shell. It is wrapped in the z80
|
||||
emulator in the same way that the shell is and interacts with `cfsin` similarly.
|
||||
|
||||
## zasm
|
||||
|
||||
`zasm/zasm` is `apps/zasm` wrapped in an emulator. It is quite central to the
|
||||
|
172
tools/emul/bshell/glue.asm
Normal file
172
tools/emul/bshell/glue.asm
Normal file
@ -0,0 +1,172 @@
|
||||
.inc "blkdev.h"
|
||||
.inc "fs.h"
|
||||
.inc "err.h"
|
||||
.inc "ascii.h"
|
||||
.equ RAMSTART 0x4000
|
||||
.equ STDIO_PORT 0x00
|
||||
.equ FS_DATA_PORT 0x01
|
||||
.equ FS_ADDR_PORT 0x02
|
||||
|
||||
jp init
|
||||
|
||||
; *** JUMP TABLE ***
|
||||
jp strncmp
|
||||
jp upcase
|
||||
jp findchar
|
||||
jp blkSelPtr
|
||||
jp blkSel
|
||||
jp blkSet
|
||||
jp blkSeek
|
||||
jp blkTell
|
||||
jp blkGetB
|
||||
jp blkPutB
|
||||
jp fsFindFN
|
||||
jp fsOpen
|
||||
jp fsGetB
|
||||
jp fsPutB
|
||||
jp fsSetSize
|
||||
jp fsOn
|
||||
jp fsIter
|
||||
jp fsAlloc
|
||||
jp fsDel
|
||||
jp fsHandle
|
||||
jp printstr
|
||||
jp printnstr
|
||||
jp _blkGetB
|
||||
jp _blkPutB
|
||||
jp _blkSeek
|
||||
jp _blkTell
|
||||
jp printcrlf
|
||||
jp stdioGetC
|
||||
jp stdioPutC
|
||||
jp stdioReadLine
|
||||
|
||||
.inc "core.asm"
|
||||
.inc "str.asm"
|
||||
|
||||
.equ BLOCKDEV_RAMSTART RAMSTART
|
||||
.equ BLOCKDEV_COUNT 4
|
||||
.inc "blockdev.asm"
|
||||
; List of devices
|
||||
.dw fsdevGetB, fsdevPutB
|
||||
.dw stdoutGetB, stdoutPutB
|
||||
.dw stdinGetB, stdinPutB
|
||||
.dw mmapGetB, mmapPutB
|
||||
|
||||
|
||||
.equ MMAP_START 0xe000
|
||||
.inc "mmap.asm"
|
||||
|
||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||
.equ STDIO_GETC emulGetC
|
||||
.equ STDIO_PUTC emulPutC
|
||||
.inc "stdio.asm"
|
||||
|
||||
.equ FS_RAMSTART STDIO_RAMEND
|
||||
.equ FS_HANDLE_COUNT 2
|
||||
.inc "fs.asm"
|
||||
|
||||
; *** BASIC ***
|
||||
|
||||
; RAM space used in different routines for short term processing.
|
||||
.equ SCRATCHPAD_SIZE 0x20
|
||||
.equ SCRATCHPAD FS_RAMEND
|
||||
.inc "lib/util.asm"
|
||||
.inc "lib/ari.asm"
|
||||
.inc "lib/parse.asm"
|
||||
.inc "lib/fmt.asm"
|
||||
.equ EXPR_PARSE parseLiteralOrVar
|
||||
.inc "lib/expr.asm"
|
||||
.inc "basic/util.asm"
|
||||
.inc "basic/parse.asm"
|
||||
.inc "basic/tok.asm"
|
||||
.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
|
||||
.inc "basic/var.asm"
|
||||
.equ BUF_RAMSTART VAR_RAMEND
|
||||
.inc "basic/buf.asm"
|
||||
.equ BAS_RAMSTART BUF_RAMEND
|
||||
.inc "basic/main.asm"
|
||||
|
||||
; Extra cmds
|
||||
.inc "basic/fs.asm"
|
||||
|
||||
init:
|
||||
di
|
||||
; setup stack
|
||||
ld sp, 0xffff
|
||||
call fsInit
|
||||
ld a, 0 ; select fsdev
|
||||
ld de, BLOCKDEV_SEL
|
||||
call blkSel
|
||||
call fsOn
|
||||
call basInit
|
||||
ld hl, basFindCmdExtra
|
||||
ld (BAS_FINDHOOK), hl
|
||||
jp basStart
|
||||
|
||||
basFindCmdExtra:
|
||||
ld hl, basFSCmds
|
||||
jp basFindCmd
|
||||
|
||||
emulGetC:
|
||||
; Blocks until a char is returned
|
||||
in a, (STDIO_PORT)
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
emulPutC:
|
||||
out (STDIO_PORT), a
|
||||
ret
|
||||
|
||||
fsdevGetB:
|
||||
ld a, e
|
||||
out (FS_ADDR_PORT), a
|
||||
ld a, h
|
||||
out (FS_ADDR_PORT), a
|
||||
ld a, l
|
||||
out (FS_ADDR_PORT), a
|
||||
in a, (FS_ADDR_PORT)
|
||||
or a
|
||||
ret nz
|
||||
in a, (FS_DATA_PORT)
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
|
||||
fsdevPutB:
|
||||
push af
|
||||
ld a, e
|
||||
out (FS_ADDR_PORT), a
|
||||
ld a, h
|
||||
out (FS_ADDR_PORT), a
|
||||
ld a, l
|
||||
out (FS_ADDR_PORT), a
|
||||
in a, (FS_ADDR_PORT)
|
||||
cp 2 ; only A > 1 means error
|
||||
jr nc, .error ; A >= 2
|
||||
pop af
|
||||
out (FS_DATA_PORT), a
|
||||
cp a ; ensure Z
|
||||
ret
|
||||
.error:
|
||||
pop af
|
||||
jp unsetZ ; returns
|
||||
|
||||
.equ STDOUT_HANDLE FS_HANDLES
|
||||
|
||||
stdoutGetB:
|
||||
ld ix, STDOUT_HANDLE
|
||||
jp fsGetB
|
||||
|
||||
stdoutPutB:
|
||||
ld ix, STDOUT_HANDLE
|
||||
jp fsPutB
|
||||
|
||||
.equ STDIN_HANDLE FS_HANDLES+FS_HANDLE_SIZE
|
||||
|
||||
stdinGetB:
|
||||
ld ix, STDIN_HANDLE
|
||||
jp fsGetB
|
||||
|
||||
stdinPutB:
|
||||
ld ix, STDIN_HANDLE
|
||||
jp fsPutB
|
203
tools/emul/bshell/shell.c
Normal file
203
tools/emul/bshell/shell.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include "../libz80/z80.h"
|
||||
#include "shell-bin.h"
|
||||
|
||||
/* Collapse OS shell with filesystem
|
||||
*
|
||||
* On startup, if "cfsin" directory exists, it packs it as a afke block device
|
||||
* and loads it in. Upon halting, unpcks the contents of that block device in
|
||||
* "cfsout" directory.
|
||||
*
|
||||
* Memory layout:
|
||||
*
|
||||
* 0x0000 - 0x3fff: ROM code from shell.asm
|
||||
* 0x4000 - 0x4fff: Kernel memory
|
||||
* 0x5000 - 0xffff: Userspace
|
||||
*
|
||||
* I/O Ports:
|
||||
*
|
||||
* 0 - stdin / stdout
|
||||
* 1 - Filesystem blockdev data read/write. Reads and write data to the address
|
||||
* previously selected through port 2
|
||||
*/
|
||||
|
||||
//#define DEBUG
|
||||
#define MAX_FSDEV_SIZE 0x20000
|
||||
|
||||
// in sync with shell.asm
|
||||
#define RAMSTART 0x4000
|
||||
#define STDIO_PORT 0x00
|
||||
#define FS_DATA_PORT 0x01
|
||||
// Controls what address (24bit) the data port returns. To select an address,
|
||||
// this port has to be written to 3 times, starting with the MSB.
|
||||
// Reading this port returns an out-of-bounds indicator. Meaning:
|
||||
// 0 means addr is within bounds
|
||||
// 1 means that we're equal to fsdev size (error for reading, ok for writing)
|
||||
// 2 means more than fsdev size (always invalid)
|
||||
// 3 means incomplete addr setting
|
||||
#define FS_ADDR_PORT 0x02
|
||||
|
||||
static Z80Context cpu;
|
||||
static uint8_t mem[0x10000] = {0};
|
||||
static uint8_t fsdev[MAX_FSDEV_SIZE] = {0};
|
||||
static uint32_t fsdev_size = 0;
|
||||
static uint32_t fsdev_ptr = 0;
|
||||
// 0 = idle, 1 = received MSB (of 24bit addr), 2 = received middle addr
|
||||
static int fsdev_addr_lvl = 0;
|
||||
static int running;
|
||||
|
||||
static uint8_t io_read(int unused, uint16_t addr)
|
||||
{
|
||||
addr &= 0xff;
|
||||
if (addr == STDIO_PORT) {
|
||||
int c = getchar();
|
||||
if (c == EOF) {
|
||||
running = 0;
|
||||
}
|
||||
return (uint8_t)c;
|
||||
} else if (addr == FS_DATA_PORT) {
|
||||
if (fsdev_addr_lvl != 0) {
|
||||
fprintf(stderr, "Reading FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
|
||||
return 0;
|
||||
}
|
||||
if (fsdev_ptr < fsdev_size) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Reading FSDEV at offset %d\n", fsdev_ptr);
|
||||
#endif
|
||||
return fsdev[fsdev_ptr];
|
||||
} else {
|
||||
// don't warn when ==, we're not out of bounds, just at the edge.
|
||||
if (fsdev_ptr > fsdev_size) {
|
||||
fprintf(stderr, "Out of bounds FSDEV read at %d\n", fsdev_ptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else if (addr == FS_ADDR_PORT) {
|
||||
if (fsdev_addr_lvl != 0) {
|
||||
return 3;
|
||||
} else if (fsdev_ptr > fsdev_size) {
|
||||
fprintf(stderr, "Out of bounds FSDEV addr request at %d / %d\n", fsdev_ptr, fsdev_size);
|
||||
return 2;
|
||||
} else if (fsdev_ptr == fsdev_size) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Out of bounds I/O read: %d\n", addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void io_write(int unused, uint16_t addr, uint8_t val)
|
||||
{
|
||||
addr &= 0xff;
|
||||
if (addr == STDIO_PORT) {
|
||||
if (val == 0x04) { // CTRL+D
|
||||
running = 0;
|
||||
} else {
|
||||
putchar(val);
|
||||
}
|
||||
} else if (addr == FS_DATA_PORT) {
|
||||
if (fsdev_addr_lvl != 0) {
|
||||
fprintf(stderr, "Writing to FSDEV in the middle of an addr op (%d)\n", fsdev_ptr);
|
||||
return;
|
||||
}
|
||||
if (fsdev_ptr < fsdev_size) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Writing to FSDEV (%d)\n", fsdev_ptr);
|
||||
#endif
|
||||
fsdev[fsdev_ptr] = val;
|
||||
} else if ((fsdev_ptr == fsdev_size) && (fsdev_ptr < MAX_FSDEV_SIZE)) {
|
||||
// We're at the end of fsdev, grow it
|
||||
fsdev[fsdev_ptr] = val;
|
||||
fsdev_size++;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Growing FSDEV (%d)\n", fsdev_ptr);
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "Out of bounds FSDEV write at %d\n", fsdev_ptr);
|
||||
}
|
||||
} else if (addr == FS_ADDR_PORT) {
|
||||
if (fsdev_addr_lvl == 0) {
|
||||
fsdev_ptr = val << 16;
|
||||
fsdev_addr_lvl = 1;
|
||||
} else if (fsdev_addr_lvl == 1) {
|
||||
fsdev_ptr |= val << 8;
|
||||
fsdev_addr_lvl = 2;
|
||||
} else {
|
||||
fsdev_ptr |= val;
|
||||
fsdev_addr_lvl = 0;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Out of bounds I/O write: %d / %d (0x%x)\n", addr, val, val);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (addr < RAMSTART) {
|
||||
fprintf(stderr, "Writing to ROM (%d)!\n", addr);
|
||||
}
|
||||
mem[addr] = val;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Setup fs blockdev
|
||||
FILE *fp = popen("../cfspack/cfspack cfsin", "r");
|
||||
if (fp != NULL) {
|
||||
printf("Initializing filesystem\n");
|
||||
int i = 0;
|
||||
int c = fgetc(fp);
|
||||
while (c != EOF) {
|
||||
fsdev[i] = c & 0xff;
|
||||
i++;
|
||||
c = fgetc(fp);
|
||||
}
|
||||
fsdev_size = i;
|
||||
pclose(fp);
|
||||
} else {
|
||||
printf("Can't initialize filesystem. Leaving blank.\n");
|
||||
}
|
||||
|
||||
// Turn echo off: the shell takes care of its own echoing.
|
||||
struct termios termInfo;
|
||||
if (tcgetattr(0, &termInfo) == -1) {
|
||||
printf("Can't setup terminal.\n");
|
||||
return 1;
|
||||
}
|
||||
termInfo.c_lflag &= ~ECHO;
|
||||
termInfo.c_lflag &= ~ICANON;
|
||||
tcsetattr(0, TCSAFLUSH, &termInfo);
|
||||
|
||||
|
||||
// initialize memory
|
||||
for (int i=0; i<sizeof(KERNEL); i++) {
|
||||
mem[i] = KERNEL[i];
|
||||
}
|
||||
// Run!
|
||||
running = 1;
|
||||
Z80RESET(&cpu);
|
||||
cpu.ioRead = io_read;
|
||||
cpu.ioWrite = io_write;
|
||||
cpu.memRead = mem_read;
|
||||
cpu.memWrite = mem_write;
|
||||
|
||||
while (running && !cpu.halted) {
|
||||
Z80Execute(&cpu);
|
||||
}
|
||||
|
||||
printf("Done!\n");
|
||||
termInfo.c_lflag |= ECHO;
|
||||
termInfo.c_lflag |= ICANON;
|
||||
tcsetattr(0, TCSAFLUSH, &termInfo);
|
||||
return 0;
|
||||
}
|
35
tools/emul/bshell/user.h
Normal file
35
tools/emul/bshell/user.h
Normal file
@ -0,0 +1,35 @@
|
||||
.equ SHELL_RAMSTART 0x4100
|
||||
.equ USER_CODE 0x4200
|
||||
|
||||
; *** JUMP TABLE ***
|
||||
.equ strncmp 0x03
|
||||
.equ upcase @+3
|
||||
.equ findchar @+3
|
||||
.equ blkSelPtr @+3
|
||||
.equ blkSel @+3
|
||||
.equ blkSet @+3
|
||||
.equ blkSeek @+3
|
||||
.equ blkTell @+3
|
||||
.equ blkGetB @+3
|
||||
.equ blkPutB @+3
|
||||
.equ fsFindFN @+3
|
||||
.equ fsOpen @+3
|
||||
.equ fsGetB @+3
|
||||
.equ fsPutB @+3
|
||||
.equ fsSetSize @+3
|
||||
.equ fsOn @+3
|
||||
.equ fsIter @+3
|
||||
.equ fsAlloc @+3
|
||||
.equ fsDel @+3
|
||||
.equ fsHandle @+3
|
||||
.equ printstr @+3
|
||||
.equ printnstr @+3
|
||||
.equ _blkGetB @+3
|
||||
.equ _blkPutB @+3
|
||||
.equ _blkSeek @+3
|
||||
.equ _blkTell @+3
|
||||
.equ printcrlf @+3
|
||||
.equ stdioGetC @+3
|
||||
.equ stdioPutC @+3
|
||||
.equ stdioReadLine @+3
|
||||
|
Loading…
Reference in New Issue
Block a user