1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 15:48:05 +11:00

Compare commits

..

No commits in common. "edb27714880586d9817db783c2dec677f5dd89f8" and "2af959a13dc543d0fc6efec7962e478a5f8e63d1" have entirely different histories.

15 changed files with 78 additions and 172 deletions

View File

@ -9,12 +9,59 @@ CONFIGURATION
ACIA_CTL: IO port for the ACIA's control registers
ACIA_IO: IO port for the ACIA's data registers
ACIA_MEM: Address in memory that can be used variables shared
with ACIA's native words. 8 bytes used.
)
0x20 CONSTANT ACIABUFSZ
( Points to ACIA buf )
(sysv) ACIA(
( Points to ACIA buf end )
(sysv) ACIA)
( Read buf pointer. Pre-inc )
(sysv) ACIAR>
( Write buf pointer. Post-inc )
(sysv) ACIAW>
( This means that if W> == R>, buffer is full.
If R>+1 == W>, buffer is empty. )
(entry) ~ACIA
AF PUSHqq,
HL PUSHqq,
DE PUSHqq,
( Read our character from ACIA into our BUFIDX )
ACIA_CTL INAn,
0x01 ANDn, ( is ACIA rcv buf full? )
JRZ, L2 FWR ( end, no, wrong interrupt cause. )
ACIAW> @ LDHL(nn),
( is it == to ACIAR>? )
DE ACIAR> @ LDdd(nn),
( carry cleared from ANDn above )
DE SBCHLss,
JRZ, L3 FWR ( end, buffer full )
( buffer not full, let's write )
ACIA_IO INAn,
(HL) A LDrr,
( advance W> )
HL INCss,
DE ACIAR) @ LDdd(nn),
DE SUBHLss,
JRNZ, L4 FWR ( skip )
( end of buffer reached )
ACIA( @ LDHL(nn),
L4 FSET ( skip )
ACIAW> @ LD(nn)HL,
L3 FSET L2 FSET ( end )
DE POPqq,
HL POPqq,
AF POPqq,
EI,
RETI,
: ACIA$
H@ DUP DUP ACIA( ! ACIAR> !
1 + ACIAW> ! ( write index starts one position later )
@ -29,9 +76,9 @@ ACIA_MEM: Address in memory that can be used variables shared
0b10010110 ACIA_CTL PC!
( setup interrupt )
( 4e == INTJUMP )
0xc3 0x4e RAM+ C! ( JP upcode )
['] ~ACIA 0x4f RAM+ !
( 51 == INTJUMP )
0xc3 0x51 RAM+ C! ( JP upcode )
['] ~ACIA 0x52 RAM+ !
(im1)
;
@ -39,15 +86,14 @@ ACIA_MEM: Address in memory that can be used variables shared
( As long as R> == W>-1, it means that buffer is empty )
BEGIN ACIAR> @ 1 + ACIAW> @ = NOT UNTIL
( inc then fetch )
1 ACIAR> +!
ACIAR> @ C@
1 ACIAR> +!
;
: EMIT
( As long at CTL bit 1 is low, we are transmitting. wait )
BEGIN ACIA_CTL PC@ 0x02 AND UNTIL
( The way is clear, go! )
ACIA_IO PC!
ACIA_IO SWAP PC!
;

View File

@ -1,55 +0,0 @@
( Save ACIA conf )
ACIA_CTL
: ACIA_CTL [ LITN ] ;
ACIA_IO
: ACIA_IO [ LITN ] ;
( Points to ACIA buf )
: ACIA( [ ACIA_MEM 4 + LITN ] ;
( Points to ACIA buf end )
: ACIA) [ ACIA_MEM 6 + LITN ] ;
( Read buf pointer. Pre-inc )
: ACIAR> [ ACIA_MEM LITN ] ;
( Write buf pointer. Post-inc )
: ACIAW> [ ACIA_MEM 2 + LITN ] ;
( This means that if W> == R>, buffer is full.
If R>+1 == W>, buffer is empty. )
(entry) ~ACIA
AF PUSHqq,
HL PUSHqq,
DE PUSHqq,
( Read our character from ACIA into our BUFIDX )
ACIA_CTL INAn,
0x01 ANDn, ( is ACIA rcv buf full? )
JRZ, L2 FWR ( end, no, wrong interrupt cause. )
ACIAW> LDHL(nn),
( is it == to ACIAR>? )
DE ACIAR> LDdd(nn),
( carry cleared from ANDn above )
DE SBCHLss,
JRZ, L3 FWR ( end, buffer full )
DE ADDHLss, ( restore ACIAW> )
( buffer not full, let's write )
ACIA_IO INAn,
(HL) A LDrr,
( advance W> )
HL INCss,
ACIAW> LD(nn)HL,
DE ACIA) @ LDdd(nn),
DE SUBHLss,
JRNZ, L4 FWR ( skip )
( end of buffer reached )
ACIA( @ LDHL(nn),
ACIAW> LD(nn)HL,
L4 FSET ( skip )
L3 FSET L2 FSET ( end )
DE POPqq,
HL POPqq,
AF POPqq,
EI,
RETI,

View File

@ -4,12 +4,10 @@ FORTHSRCS = core.fs print.fs str.fs parse.fs readln.fs fmt.fs z80a.fs
FORTHSRC_PATHS = ${FORTHSRCS:%=../forth/%} forth/run.fs
OBJS = emul.o libz80/libz80.o
SLATEST = ../tools/slatest
STRIPFC = ../tools/stripfc
.PHONY: all
all: $(TARGETS)
$(STRIPFC):
$(SLATEST):
$(MAKE) -C ../tools
@ -29,10 +27,8 @@ forth/stage1: forth/stage.c $(OBJS) forth/forth0-bin.h
forth/stage1dbg: forth/stage.c $(OBJS) forth/forth0-bin.h
$(CC) -DDEBUG forth/stage.c $(OBJS) -o $@
# We don't really need to use stripfc, but we do it anyway to test that we
# don't mistakenly break our code with that tool. It's easier to debug here.
forth/core.bin: $(FORTHSRC_PATHS) forth/stage1
cat $(FORTHSRC_PATHS) ./forth/stop.fs | $(STRIPFC) | ./forth/stage1 | tee $@ > /dev/null
cat $(FORTHSRC_PATHS) ./forth/stop.fs | ./forth/stage1 | tee $@ > /dev/null
forth/forth1.bin: forth/core.bin $(SLATEST)
cat forth/boot.bin forth/z80c.bin forth/core.bin > $@

View File

@ -115,12 +115,7 @@ those slots...) in boot binaries are made to jump to this address. If you use
one of those slots for an interrupt, write a jump to the appropriate offset in
that RAM location.
SYSTEM SCRATCHPAD is reserved for temporary system storage or can be reserved
by low-level drivers. These are the current usages of this space throughout the
project:
* 0x51-0x53: (c<) pointer during in-memory initialization (see below)
* 0x53-0x5b: ACIA buffer pointers in RC2014 recipes.
SYSTEM SCRATCHPAD is reserved for temporary system storage.
*** Initialization sequence

View File

@ -80,7 +80,7 @@
(parseb) IF EXIT THEN
(parsed) IF EXIT THEN
( nothing works )
LIT< (wnf) (find) DROP EXECUTE
ABORT" unknown word! "
;
' (parse) (parse*) !

View File

@ -28,8 +28,3 @@
: (uflw) ABORT" stack underflow" ;
: (wnf) ABORT" word not found" ;
: BS 8 EMIT ;
: LF 10 EMIT ;
: CR 13 EMIT ;
: SPC 32 EMIT ;

View File

@ -1,4 +1,4 @@
( requires core, parse, print )
( requires core, parse )
( Managing variables in a core module is tricky. Sure, we
have (sysv), but here we need to allocate a big buffer, and
@ -76,5 +76,5 @@
( not EOL? good, inc and return )
DUP IF 1 IN> +! EXIT THEN ( c )
( EOL ? readline. we still return typed char though )
(rdln) ( c )
(rdln) (<c) ( c )
;

View File

@ -5,3 +5,8 @@
1 +
AGAIN
;
: BS 8 EMIT ;
: LF 10 EMIT ;
: CR 13 EMIT ;
: SPC 32 EMIT ;

View File

@ -1,33 +1,25 @@
TARGET = os.bin
BASEDIR = ../..
FDIR = $(BASEDIR)/forth
EDIR = $(BASEDIR)/emul/forth
STAGE2 = $(EDIR)/stage2
FDIR = $(BASEDIR)/emul/forth
STAGE1 = $(FDIR)/stage1
FORTH0 = $(FDIR)/forth0.bin
EMUL = $(BASEDIR)/emul/hw/rc2014/classic
PATHS = pre.fs \
$(FDIR)/core.fs \
$(FDIR)/str.fs \
$(FDIR)/parse.fs \
SRCS = core.fs str.fs parse.fs readln.fs fmt.fs
PATHS = conf.fs \
${SRCS:%=$(BASEDIR)/forth/%} \
$(BASEDIR)/drv/acia.fs \
$(FDIR)/print.fs \
$(FDIR)/readln.fs \
$(FDIR)/fmt.fs \
run.fs
run.fs \
$(FDIR)/stop.fs
SLATEST = $(BASEDIR)/tools/slatest
STRIPFC = $(BASEDIR)/tools/stripfc
.PHONY: all
all: $(TARGET)
$(TARGET): boot.bin z80c.bin $(SLATEST) $(PATHS)
cat boot.bin z80c.bin > $@
$(TARGET): dict.bin $(FORTH0) $(SLATEST)
cat $(FORTH0) dict.bin > $@
$(SLATEST) $@
cat $(PATHS) | $(STRIPFC) >> $@
z80c.bin: boot.bin
cat conf.fs $(FDIR)/z80c.fs $(BASEDIR)/drv/acia.z80 $(FDIR)/icore.fs | $(STAGE2) | tee $@ > /dev/null
boot.bin: conf.fs
cat conf.fs $(FDIR)/boot.fs | $(STAGE2) | tee $@ > /dev/null
dict.bin: conf.fs
cat $(PATHS) | $(STAGE1) > $@
$(SLATEST):
$(MAKE) -C $(BASEDIR)/tools

View File

@ -2,5 +2,4 @@
0xf000 CONSTANT RS_ADDR
0x80 CONSTANT ACIA_CTL
0x81 CONSTANT ACIA_IO
RAMSTART 0x53 + CONSTANT ACIA_MEM

View File

@ -1 +0,0 @@
96 RAM+ HERE !

View File

@ -1,9 +1 @@
: INIT
ACIA$
(c<$)
." Collapse OS" LF
( 0c == CINPTR )
['] (c<) 0x0c RAM+ !
;
INIT
: INIT 5 5 PC! BYE ACIA$ INTERPRET ;

1
tools/.gitignore vendored
View File

@ -5,4 +5,3 @@
/ttysafe
/pingpong
/slatest
/stripfc

View File

@ -5,9 +5,8 @@ FONTCOMPILE_TGT = fontcompile
TTYSAFE_TGT = ttysafe
PINGPONG_TGT = pingpong
SLATEST_TGT = slatest
STRIPFC_TGT = stripfc
TARGETS = $(MEMDUMP_TGT) $(BLKDUMP_TGT) $(UPLOAD_TGT) $(FONTCOMPILE_TGT) \
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(SLATEST_TGT) $(STRIPFC_TGT)
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(SLATEST_TGT)
OBJS = common.o
all: $(TARGETS)
@ -23,7 +22,6 @@ $(FONTCOMPILE_TGT): $(FONTCOMPILE_TGT).c
$(TTYSAFE_TGT): $(TTYSAFE_TGT).c
$(PINGPONG_TGT): $(PINGPONG_TGT).c
$(SLATEST_TGT): $(SLATEST_TGT).c
$(STRIPFC_TGT): $(STRIPFC_TGT).c
$(TARGETS): $(OBJS)
$(CC) $(CFLAGS) $@.c $(OBJS) -o $@

View File

@ -1,55 +0,0 @@
#include <stdio.h>
/* read stdin and strip Forth-style comments before spitting in stdout. This
also deduplicate spaces and newlines.
THIS PARSING IS IMPERFECT. Only a Forth interpreter can reliably detect
comments. For example, a naive parser misinterprets the "(" word definition as
a comment.
We work around this by considering as a comment opener only "(" chars preceeded
by more than once space or by a newline. Hackish, but works.
*/
int main()
{
int spccnt = 0;
int incomment = 0;
int c;
c = getchar();
while ( c != EOF ) {
if (c == '\n') {
// We still spit newlines whenever we see them, Forth interpreter
// doesn't like when they're not there...
putchar(c);
spccnt += 2;
} else if (c == ' ') {
spccnt++;
} else {
if (incomment) {
if ((c == ')') && spccnt) {
incomment = 0;
}
} else {
if ((c == '(') && (spccnt > 1)) {
putchar(' ');
spccnt = 0;
int next = getchar();
if (next <= ' ') {
incomment = 1;
continue;
}
putchar(c);
c = next;
}
if (spccnt) {
putchar(' ');
}
putchar(c);
}
spccnt = 0;
}
c = getchar();
}
return 0;
}