mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-02 20:20:55 +11:00
Compare commits
2 Commits
39f3637c60
...
f3992ed598
Author | SHA1 | Date | |
---|---|---|---|
|
f3992ed598 | ||
|
1ae51bea3a |
@ -18,3 +18,10 @@ HL to a pointer to unparsed arguments in string form, null terminated.
|
|||||||
|
|
||||||
The userspace application is expected to set A on return. 0 means success,
|
The userspace application is expected to set A on return. 0 means success,
|
||||||
non-zero means error.
|
non-zero means error.
|
||||||
|
|
||||||
|
A userspace application can expect the `SP` pointer to be properly set. If it
|
||||||
|
moves it, it should take care of returning it where it was before returning
|
||||||
|
because otherwise, it will break the kernel.
|
||||||
|
|
||||||
|
Apps in Collapse OS are design to be ROM-compatible, that is, they don't write
|
||||||
|
to addresses that are part of the code's address space.
|
||||||
|
16
apps/basic/README.md
Normal file
16
apps/basic/README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# basic
|
||||||
|
|
||||||
|
**Work in progress, not finished.**
|
||||||
|
|
||||||
|
This is a BASIC interpreter which is being written from scratch for Collapse OS.
|
||||||
|
There are many existing z80 implementations around, some of them open source
|
||||||
|
and most of them good and efficient, but because a lot of that code overlaps
|
||||||
|
with code that has already been written for zasm, I believe that it's better to
|
||||||
|
reuse those bits of code.
|
||||||
|
|
||||||
|
Integrating an existing BASIC to Collapse OS seemed a bigger challenge than
|
||||||
|
writing from scratch, so here I am, writing from scratch again...
|
||||||
|
|
||||||
|
The biggest challenge here is to extract code from zasm, adapt it to fit BASIC,
|
||||||
|
not break anything, and have the wisdom to see when copy/pasting is a better
|
||||||
|
idea.
|
17
apps/basic/glue.asm
Normal file
17
apps/basic/glue.asm
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
; *** Requirements ***
|
||||||
|
; addHL
|
||||||
|
; printstr
|
||||||
|
; printcrlf
|
||||||
|
; stdioReadLine
|
||||||
|
; strncmp
|
||||||
|
;
|
||||||
|
.inc "user.h"
|
||||||
|
|
||||||
|
.inc "err.h"
|
||||||
|
.org USER_CODE
|
||||||
|
|
||||||
|
jp basStart
|
||||||
|
|
||||||
|
.inc "lib/parse.asm"
|
||||||
|
.equ BAS_RAMSTART USER_RAMSTART
|
||||||
|
.inc "basic/main.asm"
|
87
apps/basic/main.asm
Normal file
87
apps/basic/main.asm
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
; *** Variables ***
|
||||||
|
; Value of `SP` when basic was first invoked. This is where SP is going back to
|
||||||
|
; on restarts.
|
||||||
|
.equ BAS_INITSP BAS_RAMSTART
|
||||||
|
; **Pointer** to current line number
|
||||||
|
.equ BAS_PCURLN @+2
|
||||||
|
.equ BAS_RAMEND @+2
|
||||||
|
|
||||||
|
; *** Code ***
|
||||||
|
basStart:
|
||||||
|
ld (BAS_INITSP), sp
|
||||||
|
xor a
|
||||||
|
ld hl, .welcome
|
||||||
|
call printstr
|
||||||
|
call printcrlf
|
||||||
|
ld hl, .welcome+2 ; points to a zero word
|
||||||
|
ld (BAS_PCURLN), hl
|
||||||
|
jr basPrompt
|
||||||
|
|
||||||
|
.welcome:
|
||||||
|
.db "OK", 0, 0
|
||||||
|
|
||||||
|
basPrompt:
|
||||||
|
ld hl, .sPrompt
|
||||||
|
call printstr
|
||||||
|
call stdioReadLine
|
||||||
|
call parseDecimal
|
||||||
|
jr z, .number
|
||||||
|
call basDirect
|
||||||
|
jr basPrompt
|
||||||
|
.number:
|
||||||
|
; do nothing for now, we only support direct mode.
|
||||||
|
ld hl, .sNumber
|
||||||
|
call basPrintLn
|
||||||
|
jr basPrompt
|
||||||
|
.sNumber:
|
||||||
|
.db "A number!", 0
|
||||||
|
.sPrompt:
|
||||||
|
.db "> ", 0
|
||||||
|
|
||||||
|
basDirect:
|
||||||
|
ex de, hl
|
||||||
|
ld hl, basCmds1
|
||||||
|
.loop:
|
||||||
|
ld a, 4
|
||||||
|
call strncmp
|
||||||
|
jr z, .found
|
||||||
|
ld a, 6
|
||||||
|
call addHL
|
||||||
|
ld a, (hl)
|
||||||
|
cp 0xff
|
||||||
|
jr nz, .loop
|
||||||
|
ld hl, .sUnknown
|
||||||
|
jr basPrintLn
|
||||||
|
|
||||||
|
.found:
|
||||||
|
inc hl \ inc hl \ inc hl \ inc hl
|
||||||
|
call intoHL
|
||||||
|
jp (hl)
|
||||||
|
|
||||||
|
.sUnknown:
|
||||||
|
.db "Unknown command", 0
|
||||||
|
|
||||||
|
basPrintLn:
|
||||||
|
call printcrlf
|
||||||
|
call printstr
|
||||||
|
jp printcrlf
|
||||||
|
|
||||||
|
; *** Commands ***
|
||||||
|
basBYE:
|
||||||
|
ld hl, .sBye
|
||||||
|
call basPrintLn
|
||||||
|
; To quit the loop, let's return the stack to its initial value and
|
||||||
|
; then return.
|
||||||
|
xor a
|
||||||
|
ld sp, (BAS_INITSP)
|
||||||
|
ret
|
||||||
|
.sBye:
|
||||||
|
.db "Goodbye!", 0
|
||||||
|
|
||||||
|
; direct only
|
||||||
|
basCmds1:
|
||||||
|
.db "bye", 0
|
||||||
|
.dw basBYE
|
||||||
|
; statements
|
||||||
|
basCmds2:
|
||||||
|
.db 0xff ; end of table
|
1
tools/emul/.gitignore
vendored
1
tools/emul/.gitignore
vendored
@ -4,4 +4,5 @@
|
|||||||
/*/*-bin.h
|
/*/*-bin.h
|
||||||
/cfsin/zasm
|
/cfsin/zasm
|
||||||
/cfsin/ed
|
/cfsin/ed
|
||||||
|
/cfsin/basic
|
||||||
/cfsin/user.h
|
/cfsin/user.h
|
||||||
|
@ -4,7 +4,7 @@ KERNEL = ../../kernel
|
|||||||
APPS = ../../apps
|
APPS = ../../apps
|
||||||
ZASMBIN = zasm/zasm
|
ZASMBIN = zasm/zasm
|
||||||
ZASMSH = ../zasm.sh
|
ZASMSH = ../zasm.sh
|
||||||
SHELLAPPS = $(addprefix cfsin/, zasm ed)
|
SHELLAPPS = $(addprefix cfsin/, zasm ed basic)
|
||||||
CFSIN_CONTENTS = $(SHELLAPPS) cfsin/user.h
|
CFSIN_CONTENTS = $(SHELLAPPS) cfsin/user.h
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
@ -65,6 +65,7 @@ ADD IY, DE
|
|||||||
ADD IY, IY
|
ADD IY, IY
|
||||||
ADD IY, SP
|
ADD IY, SP
|
||||||
AND (HL)
|
AND (HL)
|
||||||
|
AND (IX)
|
||||||
AND (IX+1)
|
AND (IX+1)
|
||||||
AND (IX-1)
|
AND (IX-1)
|
||||||
AND (IX+10)
|
AND (IX+10)
|
||||||
@ -73,6 +74,7 @@ AND (IX+100)
|
|||||||
AND (IX-100)
|
AND (IX-100)
|
||||||
AND (IX+127)
|
AND (IX+127)
|
||||||
AND (IX-127)
|
AND (IX-127)
|
||||||
|
AND (IY)
|
||||||
AND (IY+1)
|
AND (IY+1)
|
||||||
AND (IY-1)
|
AND (IY-1)
|
||||||
AND (IY+10)
|
AND (IY+10)
|
||||||
|
Binary file not shown.
@ -6,12 +6,6 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Those lines below are improperly assembled by scas and are skipped by tests.
|
|
||||||
BLACKLIST = {
|
|
||||||
"AND (IX)",
|
|
||||||
"AND (IY)",
|
|
||||||
}
|
|
||||||
|
|
||||||
argspecTbl = {
|
argspecTbl = {
|
||||||
'A': "A",
|
'A': "A",
|
||||||
'B': "B",
|
'B': "B",
|
||||||
@ -124,11 +118,6 @@ def eargs(args):
|
|||||||
newargs = ['$+'+s for s in args[:-1]]
|
newargs = ['$+'+s for s in args[:-1]]
|
||||||
return newargs + ['$-'+s for s in args[:-1]]
|
return newargs + ['$-'+s for s in args[:-1]]
|
||||||
|
|
||||||
def p(line):
|
|
||||||
if line not in BLACKLIST:
|
|
||||||
print(line)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
asmfile = sys.argv[1]
|
asmfile = sys.argv[1]
|
||||||
with open(asmfile, 'rt') as fp:
|
with open(asmfile, 'rt') as fp:
|
||||||
@ -164,11 +153,11 @@ def main():
|
|||||||
if n in {'JR', 'DJNZ'} and a2 == 'n':
|
if n in {'JR', 'DJNZ'} and a2 == 'n':
|
||||||
args2 = eargs(args2)
|
args2 = eargs(args2)
|
||||||
for arg2 in args2:
|
for arg2 in args2:
|
||||||
p(f"{n} {arg1}, {arg2}")
|
print(f"{n} {arg1}, {arg2}")
|
||||||
else:
|
else:
|
||||||
p(f"{n} {arg1}")
|
print(f"{n} {arg1}")
|
||||||
else:
|
else:
|
||||||
p(n)
|
print(n)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user