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

Compare commits

..

No commits in common. "b606dbf9af1d9b22565dfde8b1558d6441c5a938" and "80d730318a6358dadba84406af2945f6d92fd4b1" have entirely different histories.

54 changed files with 565 additions and 273 deletions

View File

@ -6,6 +6,7 @@ MASTER INDEX
150 Extra words 150 Extra words
200 Z80 assembler 260 Cross compilation 200 Z80 assembler 260 Cross compilation
280 Z80 boot code 390 Cross-compiled core 280 Z80 boot code 390 Cross-compiled core
439 XPACKed core
490 TRS-80 Recipe 520 Fonts 490 TRS-80 Recipe 520 Fonts
550 TI-84+ Recipe 580 RC2014 Recipe 550 TI-84+ Recipe 580 RC2014 Recipe

View File

@ -12,5 +12,4 @@ have to consume it to avoid PSP leak.
] -- End interpretative mode. ] -- End interpretative mode.
ABORT -- Resets PS and RS and returns to interpreter. ABORT -- Resets PS and RS and returns to interpreter.
ABORT" x" -- *I* Compiles a ." followed by a ABORT. ABORT" x" -- *I* Compiles a ." followed by a ABORT.
ERR a -- Prints a and ABORT. Defined early and used by EXECUTE a -- Execute wordref at addr a
drivers. (cont.)

View File

@ -1,4 +1,3 @@
EXECUTE a -- Execute wordref at addr a
INTERPRET -- Get a line from stdin, compile it in tmp memory, INTERPRET -- Get a line from stdin, compile it in tmp memory,
then execute the compiled contents. then execute the compiled contents.
LEAVE -- In a DO..LOOP, exit at the next LOOP call. LEAVE -- In a DO..LOOP, exit at the next LOOP call.

View File

@ -1,13 +1,14 @@
VARIABLE XCURRENT VARIABLE XCURRENT
: XCON XCURRENT CURRENT* ! ; : XCON XCURRENT CURRENT* ! ;
: XCOFF 0x02 RAM+ CURRENT* ! ; : XCOFF 0x02 RAM+ CURRENT* ! ;
: (xentry) XCON (entry) XCOFF ; : (xentry) XCON (entry) XCOFF ;
: XCREATE (xentry) 11 C, ; : XCREATE (xentry) 11 C, ;
: XCODE XCON CODE XCOFF ; : XCODE XCON CODE XCOFF ;
: XIMM XCON IMMEDIATE XCOFF ; : XIMM XCON IMMEDIATE XCOFF ;
: _xapply ( a -- a-off ) : _xapply ( a -- a-off )
DUP ORG @ > IF ORG @ - BIN( @ + THEN ; DUP ORG @ > IF ORG @ - BIN( @ + THEN ;
: X' XCON ' XCOFF ;
: X['] XCON ' _xapply LITA XCOFF ; : X['] XCON ' _xapply LITA XCOFF ;
: XCOMPILE : XCOMPILE
XCON ' _xapply LITA XCON ' _xapply LITA

View File

@ -1,5 +1,4 @@
: ABORT (resSP) QUIT ; : ABORT (resSP) QUIT ;
: ERR LIT< (print) (find) IF EXECUTE THEN ABORT ;
: = CMP NOT ; : < CMP -1 = ; : > CMP 1 = ; : = CMP NOT ; : < CMP -1 = ; : > CMP 1 = ;
: 0< 32767 > ; : >= < NOT ; : <= > NOT ; : 0>= 0< NOT ; : 0< 32767 > ; : >= < NOT ; : <= > NOT ; : 0>= 0< NOT ;
( n l h -- f ) ( n l h -- f )

23
blk/409
View File

@ -1,16 +1,7 @@
( Words here until the end of the low part, unlike words : INTERPRET
preceeding them, aren't immediately needed for boot. But its BEGIN
better to have as many words as possible in the xcomp part. ) WORD DUP C@ EOT? IF DROP EXIT THEN
: H@ HERE @ ; (find)
: IMMEDIATE NOT IF (parse) ELSE EXECUTE THEN
CURRENT @ 1- C<? NOT IF LIT< (ok) (find) IF EXECUTE THEN THEN
DUP C@ 128 OR SWAP C! ; AGAIN ;
: IMMED? 1- C@ 0x80 AND ;
: +! SWAP OVER @ + SWAP ! ;
: -^ SWAP - ;
: / /MOD SWAP DROP ;
: MOD /MOD DROP ;
: ALLOT HERE +! ;
: CREATE (entry) 11 ( 11 == cellWord ) C, ;
: VARIABLE CREATE 2 ALLOT ;
: LEAVE R> R> DROP I 1- >R >R ;

22
blk/410
View File

@ -1,13 +1,11 @@
: '? WORD (find) ; ( system c< simply reads source from binary, starting at
: ' LATEST. Convenient way to bootstrap a new system. )
'? (?br) [ 4 , ] EXIT : (boot<)
LIT< (wnf) (find) DROP EXECUTE ( 2e == BOOT C< PTR )
0x2e RAM+ @ ( a )
DUP C@ ( a c )
SWAP 1 + ( c a+1 )
0x2e RAM+ ! ( c )
; ;
: ROLL
DUP NOT IF EXIT THEN
1+ DUP PICK ( n val )
SWAP 2 * (roll) ( val )
SWAP DROP
;
: 2OVER 3 PICK 3 PICK ;
: 2SWAP 3 ROLL 3 ROLL ;

26
blk/411
View File

@ -1,13 +1,13 @@
: MOVE ( a1 a2 u -- ) : BOOT
( u ) 0 DO ( a1 a2 ) 0x02 RAM+ CURRENT* !
SWAP C@+ ( a2 a1+1 x ) CURRENT @ 0x2e RAM+ ! ( 2e == BOOT C< PTR )
ROT C!+ ( a1+1 a2+1 ) 0 0x08 RAM+ ! ( 08 == C<* override )
LOOP 2DROP ; 0 0x53 RAM+ ! ( 53 == (emit) override )
: MOVE- ( a1 a2 u -- ) 0 0x55 RAM+ ! ( 55 == (key) override )
SWAP OVER + 1- ( a1 u a2+u-1 ) 0 0x0a RAM+ ! ( NLPTR )
ROT 2 PICK + 1- ( u a2+u-1 a1+u-1 ) ( 0c == C<* )
ROT ( u ) 0 DO ( a2 a1 ) ['] (boot<) 0x0c RAM+ !
C@- ( a2 a1-1 x ) ( boot< always has a char waiting. 06 == C<?* )
ROT C!- ( a1-1 a2-1 ) SWAP ( a2 a1 ) 1 0x06 RAM+ !
LOOP 2DROP ; INTERPRET BYE ;
: PREV 3 - DUP @ - ;

27
blk/412
View File

@ -1,13 +1,16 @@
: WORD( ( Words here until the end of the low part, unlike words
DUP 1- C@ ( name len field ) preceeding them, aren't immediately needed for boot. But its
127 AND ( 0x7f. remove IMMEDIATE flag ) better to have as many words as possible in the xcomp part. )
3 + ( fixed header len ) : H@ HERE @ ;
- : IMMEDIATE
; CURRENT @ 1-
: FORGET DUP C@ 128 OR SWAP C!
' DUP ( w w )
( HERE must be at the end of prev's word, that is, at the
beginning of w. )
WORD( HERE ! ( w )
PREV CURRENT !
; ;
: +! SWAP OVER @ + SWAP ! ;
: -^ SWAP - ;
: / /MOD SWAP DROP ;
: MOD /MOD DROP ;
: ALLOT HERE +! ;
: CREATE (entry) 11 ( 11 == cellWord ) C, ;
: LEAVE R> R> DROP I 1- >R >R ;

26
blk/413
View File

@ -1,15 +1,13 @@
: DOES> : '? WORD (find) ;
( Overwrite cellWord in CURRENT ) : '
( 43 == doesWord ) '? (?br) [ 4 , ] EXIT
43 CURRENT @ C! LIT< (wnf) (find) DROP EXECUTE
( When we have a DOES>, we forcefully place HERE to 4
bytes after CURRENT. This allows a DOES word to use ","
and "C," without messing everything up. )
CURRENT @ 3 + HERE !
( HERE points to where we should write R> )
R> ,
( We're done. Because we've popped RS, we'll exit parent
definition )
; ;
: CONSTANT CREATE , DOES> @ ; : ROLL
DUP NOT IF EXIT THEN
1+ DUP PICK ( n val )
SWAP 2 * (roll) ( val )
SWAP DROP
;
: 2OVER 3 PICK 3 PICK ;
: 2SWAP 3 ROLL 3 ROLL ;

18
blk/414
View File

@ -1,5 +1,13 @@
: [IF] : MOVE ( a1 a2 u -- )
IF EXIT THEN ( u ) 0 DO ( a1 a2 )
LIT< [THEN] BEGIN DUP WORD S= UNTIL DROP ; SWAP C@+ ( a2 a1+1 x )
: [THEN] ; ROT C!+ ( a1+1 a2+1 )
LOOP 2DROP ;
: MOVE- ( a1 a2 u -- )
SWAP OVER + 1- ( a1 u a2+u-1 )
ROT 2 PICK + 1- ( u a2+u-1 a1+u-1 )
ROT ( u ) 0 DO ( a2 a1 )
C@- ( a2 a1-1 x )
ROT C!- ( a1-1 a2-1 ) SWAP ( a2 a1 )
LOOP 2DROP ;
: PREV 3 - DUP @ - ;

13
blk/415 Normal file
View File

@ -0,0 +1,13 @@
: WORD(
DUP 1- C@ ( name len field )
127 AND ( 0x7f. remove IMMEDIATE flag )
3 + ( fixed header len )
-
;
: FORGET
' DUP ( w w )
( HERE must be at the end of prev's word, that is, at the
beginning of w. )
WORD( HERE ! ( w )
PREV CURRENT !
;

View File

@ -1 +1 @@
1 20 LOADR+ ( xcomp core high ) 1 16 LOADR+ ( xcomp core high )

12
blk/421
View File

@ -1,16 +1,14 @@
: EMIT : EMIT
( 0x53==(emit) override ) ( 0x53==(emit) override )
0x53 RAM+ @ DUP IF EXECUTE ELSE DROP (emit) THEN ; 0x53 RAM+ @ DUP IF EXECUTE ELSE DROP (emit) THEN ;
: (print) : (print)
BEGIN BEGIN
C@+ ( a+1 c ) C@+ ( a+1 c )
( exit if null or 0xd ) ( exit if null or 0xd )
DUP 0xd = OVER NOT OR IF 2DROP EXIT THEN DUP 0xd = OVER NOT OR IF 2DROP EXIT THEN
EMIT ( a ) EMIT ( a )
AGAIN ; AGAIN
: BS 8 EMIT ; : LF 10 EMIT ; : CR 13 EMIT ; ;
: CRLF CR LF ; : SPC 32 EMIT ;
: NL 0x0a RAM+ @ ( NLPTR ) DUP IF EXECUTE ELSE DROP CRLF THEN ;
: (ok) SPC LIT" ok" (print) NL ;
: (uflw) LIT" stack underflow" ERR ;
: (wnf) (print) SPC LIT" word not found" ERR ;

14
blk/422
View File

@ -1,7 +1,15 @@
: ," : ,"
BEGIN BEGIN
C< DUP 34 ( ASCII " ) = IF DROP EXIT THEN C, C<
( 34 is ASCII for " )
DUP 34 = IF DROP EXIT THEN C,
AGAIN ; AGAIN ;
: LIT" 34 , ( litWord ) ," 0 C, ; IMMEDIATE
: ." [COMPILE] LIT" COMPILE (print) ; IMMEDIATE : ."
34 , ( 34 == litWord ) ," 0 C,
COMPILE (print)
; IMMEDIATE
: ABORT" [COMPILE] ." COMPILE ABORT ; IMMEDIATE : ABORT" [COMPILE] ." COMPILE ABORT ; IMMEDIATE
: BS 8 EMIT ; : LF 10 EMIT ; : CR 13 EMIT ;
: CRLF CR LF ; : SPC 32 EMIT ;
: NL 0x0a RAM+ @ ( NLPTR ) DUP IF EXECUTE ELSE DROP CRLF THEN ;

11
blk/432
View File

@ -1,14 +1,3 @@
: INTERPRET
BEGIN
WORD DUP C@ EOT? IF DROP EXIT THEN
(find) NOT IF (parse) ELSE EXECUTE THEN
C<? NOT IF (ok) THEN
AGAIN ;
( Read from BOOT C< PTR and inc it. )
: (boot<)
( 2e == BOOT C< PTR )
0x2e ( BOOT C< PTR ) RAM+ @ DUP C@ ( a c )
SWAP 1 + 0x2e RAM+ ! ( c ) ;
( pre-comment for tight LOAD: The 0x08==I check after INTERPRET ( pre-comment for tight LOAD: The 0x08==I check after INTERPRET
is to check whether we're restoring to "_", the word above. is to check whether we're restoring to "_", the word above.
if yes, then we're in a nested load. Also, the 1 in 0x06 is if yes, then we're in a nested load. Also, the 1 in 0x06 is

14
blk/435 Normal file
View File

@ -0,0 +1,14 @@
( LITN has to be defined after the last immediate usage of
it to avoid bootstrapping issues )
: LITN 32 , , ( 32 == NUMBER ) ;
: IMMED? 1- C@ 0x80 AND ;
( ';' can't have its name right away because, when created, it
is not an IMMEDIATE yet and will not be treated properly by
xcomp. )
: _
['] EXIT ,
R> DROP ( exit : )
; IMMEDIATE

29
blk/436
View File

@ -1,13 +1,16 @@
: BOOT XCURRENT @ ( to PSP )
0x02 RAM+ CURRENT* ! : :
CURRENT @ 0x2e RAM+ ! ( 2e == BOOT C< PTR ) (entry)
0 0x08 RAM+ ! ( 08 == C<* override ) ( We cannot use LITN as IMMEDIATE because of bootstrapping
0 0x53 RAM+ ! ( 53 == (emit) override ) issues. Same thing for ",".
0 0x55 RAM+ ! ( 55 == (key) override ) 32 == NUMBER 14 == compiledWord )
0 0x0a RAM+ ! ( NLPTR ) [ 32 H@ ! 2 ALLOT 14 H@ ! 2 ALLOT ] C,
( 0c == C<* ) BEGIN
['] (boot<) 0x0c RAM+ ! WORD
( boot< always has a char waiting. 06 == C<?* ) (find)
1 0x06 RAM+ ! ( is word )
INTERPRET BYE ; IF DUP IMMED? IF EXECUTE ELSE , THEN
( maybe number )
ELSE (parse) LITN THEN
AGAIN ;
( from PSP ) ';' SWAP 4 - C!

15
blk/437
View File

@ -1,15 +0,0 @@
( Now we have "as late as possible" stuff )
: DO COMPILE 2>R H@ ; IMMEDIATE
: LOOP COMPILE (loop) H@ - , ; IMMEDIATE
( LEAVE is implemented in low xcomp )
: LITN 32 , , ( 32 == NUMBER ) ;
( gets its name at the very end. can't comment afterwards )
: _ BEGIN LIT< ) WORD S= UNTIL ; IMMEDIATE
: _ ( : will get its name almost at the very end )
(entry)
[ 14 ( == compiledWord ) LITN ] C,
BEGIN
WORD (find)
IF ( is word ) DUP IMMED? IF EXECUTE ELSE , THEN
ELSE ( maybe number ) (parse) LITN THEN
AGAIN ;

14
blk/438
View File

@ -1,14 +0,0 @@
: IF ( -- a | a: br cell addr )
COMPILE (?br) H@ 2 ALLOT ( br cell allot )
; IMMEDIATE
: THEN ( a -- | a: br cell addr )
DUP H@ -^ SWAP ( a-H a ) !
; IMMEDIATE
: ELSE ( a1 -- a2 | a1: IF cell a2: ELSE cell )
COMPILE (br)
2 ALLOT
DUP H@ -^ SWAP ( a-H a )
!
H@ 2- ( push a. -2 for allot offset )
; IMMEDIATE

23
blk/439
View File

@ -1,9 +1,14 @@
: BEGIN H@ ; IMMEDIATE XPACKed core
: AGAIN COMPILE (br) H@ - , ; IMMEDIATE
: UNTIL COMPILE (?br) H@ - , ; IMMEDIATE Most of Collapse OS' core words are cross compiled (B390).
: [ INTERPRET ; IMMEDIATE However, some of them are too dynamically referenced to be
: ] R> DROP ; cross-compiled without great pain, so we XPACK (B267) them,
: LIT< WORD 34 , SCPY 0 C, ; IMMEDIATE that is, we put them in source form in the target's
: LITA 36 , , ; initialization section (see B89).
: COMPILE ' LITA ['] , , ; IMMEDIATE
: [COMPILE] ' , ; IMMEDIATE These words will be compiled into RAM at initialization, which
is a bit wasteful both in RAM and in boot time, so we will
typically relink (B120) that newly compiled binary and append
it to our existing binary for optimal resource usage.
Load range: 440-446

19
blk/440
View File

@ -1,11 +1,10 @@
( ';' can't have its name right away because, when created, it : [ INTERPRET ; IMMEDIATE
is not an IMMEDIATE yet and will not be treated properly by : ] R> DROP ;
xcomp. ) : LIT< WORD 34 , SCPY 0 C, ; IMMEDIATE
: _ : LITA 36 , , ;
['] EXIT ,
R> DROP ( exit : )
; IMMEDIATE
: ['] ' LITA ; IMMEDIATE : ['] ' LITA ; IMMEDIATE
';' X' _ 4 - C! ( give ; its name ) : COMPILE ' LITA ['] , , ; IMMEDIATE
':' X' _ 4 - C! ( give : its name ) : [COMPILE] ' , ; IMMEDIATE
'(' X' _ 4 - C! : BEGIN H@ ; IMMEDIATE
: AGAIN COMPILE (br) H@ - , ; IMMEDIATE
: UNTIL COMPILE (?br) H@ - , ; IMMEDIATE

13
blk/441 Normal file
View File

@ -0,0 +1,13 @@
: _ BEGIN LIT< ) WORD S= UNTIL ; IMMEDIATE
40 CURRENT @ 4 - C!
( Hello, hello, krkrkrkr... do you hear me?
Ah, voice at last! Some lines above need comments
BTW: Forth lines limited to 64 cols because of default
input buffer size in Collapse OS
40 is ASCII for '('. We do this to simplify XPACK's task of
not mistakenly consider '(' definition as a comment.
LIT<: 34 == litWord
LITA: 36 == addrWord
COMPILE: Tough one. Get addr of caller word (example above
(br)) and then call LITA on it. )

11
blk/442 Normal file
View File

@ -0,0 +1,11 @@
: IF ( -- a | a: br cell addr )
COMPILE (?br)
H@ ( push a )
2 ALLOT ( br cell allot )
; IMMEDIATE
: THEN ( a -- | a: br cell addr )
DUP H@ -^ SWAP ( a-H a )
!
; IMMEDIATE

12
blk/443 Normal file
View File

@ -0,0 +1,12 @@
: ELSE ( a1 -- a2 | a1: IF cell a2: ELSE cell )
COMPILE (br)
2 ALLOT
DUP H@ -^ SWAP ( a-H a )
!
H@ 2- ( push a. -2 for allot offset )
; IMMEDIATE
: [IF]
IF EXIT THEN
LIT< [THEN] BEGIN DUP WORD S= UNTIL DROP ;
: [THEN] ;

14
blk/444 Normal file
View File

@ -0,0 +1,14 @@
: DOES>
( Overwrite cellWord in CURRENT )
( 43 == doesWord )
43 CURRENT @ C!
( When we have a DOES>, we forcefully place HERE to 4
bytes after CURRENT. This allows a DOES word to use ","
and "C," without messing everything up. )
CURRENT @ 3 + HERE !
( HERE points to where we should write R> )
R> ,
( We're done. Because we've popped RS, we'll exit parent
definition )
;

8
blk/445 Normal file
View File

@ -0,0 +1,8 @@
: VARIABLE CREATE 2 ALLOT ;
: CONSTANT CREATE , DOES> @ ;
( In addition to pushing H@ this compiles 2>R so that loop
variables are sent to PS at runtime )
: DO COMPILE 2>R H@ ; IMMEDIATE
: LOOP COMPILE (loop) H@ - , ; IMMEDIATE
( LEAVE is implemented in xcomp )

3
blk/446 Normal file
View File

@ -0,0 +1,3 @@
: (ok) SPC ." ok" NL ;
: (uflw) ABORT" stack underflow" ;
: (wnf) (print) SPC ABORT" word not found" ;

View File

@ -4,7 +4,8 @@ Support code for the TRS-80 recipe. Contains drivers for the
keyboard, video and floppy. At the moment, they are thin layer keyboard, video and floppy. At the moment, they are thin layer
over the drivers provided by TRSDOS' SVC. over the drivers provided by TRSDOS' SVC.
Load with "492 LOAD". Load the Z80 words with "492 LOAD" and the high level part
with "498 LOAD".
There is also the RECV program at B502 and the XCOMP unit at There is also the RECV program at B502 and the XCOMP unit at
B504 B504

View File

@ -1 +1 @@
1 8 LOADR+ 1 5 LOADR+

1
blk/498 Normal file
View File

@ -0,0 +1 @@
1 2 LOADR+

View File

@ -1,4 +1,4 @@
: _err LIT" FDerr" ERR ; : _err ABORT" FDerr" ;
: _cylsec ( sec -- cs, return sector/cylinder for given secid ) : _cylsec ( sec -- cs, return sector/cylinder for given secid )
( 4 256b sectors per block, 10 sec per cyl, 40 cyl max ) ( 4 256b sectors per block, 10 sec per cyl, 40 cyl max )
10 /MOD ( sec cyl ) 10 /MOD ( sec cyl )

View File

@ -2,6 +2,6 @@
: FD! ['] @WRSEC SWAP FD@! ; : FD! ['] @WRSEC SWAP FD@! ;
: FD$ ['] FD@ BLK@* ! ['] FD! BLK!* ! ; : FD$ ['] FD@ BLK@* ! ['] FD! BLK!* ! ;
: _err LIT" *CLerr" ERR ; : _err ABORT" *CLerr" ;
: *CL< 0 BEGIN DROP 0x0238 @GET UNTIL ; : *CL< 0 BEGIN DROP 0x0238 @GET UNTIL ;
: *CL> 0x0238 @PUT NOT IF _err THEN ; : *CL> 0x0238 @PUT NOT IF _err THEN ;

View File

@ -4,4 +4,4 @@ Support code for the RC2014 recipe. Contains drivers for the
ACIA, SD card and AT28 EEPROM. ACIA, SD card and AT28 EEPROM.
581 ACIA 590 AT28 EEPROM 581 ACIA 590 AT28 EEPROM
600 SD card 618 Xcomp unit 600 SD card

15
blk/618
View File

@ -1,15 +0,0 @@
0x8000 CONSTANT RAMSTART
0xf000 CONSTANT RS_ADDR 0xfffa CONSTANT PS_ADDR
0x80 CONSTANT ACIA_CTL 0x81 CONSTANT ACIA_IO
4 CONSTANT SDC_SPI
5 CONSTANT SDC_CSLOW 6 CONSTANT SDC_CSHIGH
RAMSTART 0x70 + CONSTANT ACIA_MEM
212 LOAD ( z80 assembler )
262 LOAD ( xcomp ) 270 LOAD ( xcomp overrides )
282 LOAD ( boot.z80 ) 393 LOAD ( xcomp core low )
582 LOAD ( acia )
420 LOAD ( xcomp core high )
(entry) _
( Update LATEST )
PC ORG @ 8 + !
," : _ ACIA$ RDLN$ (ok) ; _ "

5
emul/.gitignore vendored
View File

@ -1,4 +1,7 @@
/stage /stage1
/stage1dbg
/stage2
/forth /forth
/*-bin.h /*-bin.h
/stage0.bin
/blkfs /blkfs

View File

@ -1,4 +1,4 @@
TARGETS = forth stage TARGETS = forth stage2
OBJS = emul.o libz80/libz80.o OBJS = emul.o libz80/libz80.o
BIN2C = ../tools/bin2c BIN2C = ../tools/bin2c
BLKPACK = ../tools/blkpack BLKPACK = ../tools/blkpack
@ -14,12 +14,24 @@ $(BLKPACK):
$(BIN2C): $(BLKPACK) $(BIN2C): $(BLKPACK)
$(BLKUNPACK): $(BLKPACK) $(BLKUNPACK): $(BLKPACK)
stage0.bin: stage2 xcomp.fs
cat xcomp.fs | ./stage2 > stage0.bin
stage0-bin.h: stage0.bin $(BIN2C)
$(BIN2C) KERNEL < stage0.bin > $@
stage1: stage.c $(OBJS) stage0-bin.h
$(CC) stage.c $(OBJS) -o $@
stage1dbg: stage.c $(OBJS) stage0-bin.h
$(CC) -DDEBUG stage.c $(OBJS) -o $@
# not dependent on forth.bin to avoid circular deps. # not dependent on forth.bin to avoid circular deps.
forth-bin.h: $(BIN2C) forth-bin.h: $(BIN2C)
$(BIN2C) KERNEL < forth.bin > $@ $(BIN2C) KERNEL < forth.bin > $@
stage: stage.c $(OBJS) forth-bin.h blkfs-bin.h stage2: stage.c $(OBJS) forth-bin.h blkfs-bin.h
$(CC) stage.c $(OBJS) -o $@ $(CC) -DSTAGE2 stage.c $(OBJS) -o $@
blkfs: $(BLKPACK) blkfs: $(BLKPACK)
$(BLKPACK) ../blk > $@ $(BLKPACK) ../blk > $@
@ -39,8 +51,8 @@ emul.o: emul.c
.PHONY: updatebootstrap .PHONY: updatebootstrap
updatebootstrap: stage xcomp.fs updatebootstrap: stage1 stage1.fs
./stage < xcomp.fs > forth.bin ./stage1 < stage1.fs > forth.bin
.PHONY: pack .PHONY: pack
pack: pack:

Binary file not shown.

View File

@ -2,8 +2,12 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include "emul.h" #include "emul.h"
#ifdef STAGE2
#include "forth-bin.h" #include "forth-bin.h"
#include "blkfs-bin.h" #include "blkfs-bin.h"
#else
#include "stage0-bin.h"
#endif
/* Staging binaries /* Staging binaries
@ -70,6 +74,7 @@ static void iowr_here(uint8_t val)
end_here |= val; end_here |= val;
} }
#ifdef STAGE2
static void iowr_blk(uint8_t val) static void iowr_blk(uint8_t val)
{ {
blkid <<= 8; blkid <<= 8;
@ -81,6 +86,7 @@ static uint8_t iord_blkdata()
{ {
return BLKFS[blkpos++]; return BLKFS[blkpos++];
} }
#endif
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -89,8 +95,10 @@ int main(int argc, char *argv[])
m->iord[STDIO_PORT] = iord_stdio; m->iord[STDIO_PORT] = iord_stdio;
m->iowr[STDIO_PORT] = iowr_stdio; m->iowr[STDIO_PORT] = iowr_stdio;
m->iowr[HERE_PORT] = iowr_here; m->iowr[HERE_PORT] = iowr_here;
#ifdef STAGE2
m->iowr[BLK_PORT] = iowr_blk; m->iowr[BLK_PORT] = iowr_blk;
m->iord[BLKDATA_PORT] = iord_blkdata; m->iord[BLKDATA_PORT] = iord_blkdata;
#endif
// initialize memory // initialize memory
for (int i=0; i<sizeof(KERNEL); i++) { for (int i=0; i<sizeof(KERNEL); i++) {
m->mem[i] = KERNEL[i]; m->mem[i] = KERNEL[i];

28
emul/stage1.fs Normal file
View File

@ -0,0 +1,28 @@
: EFS@
256 /MOD 3 PC! 3 PC!
1024 0 DO
4 PC@
BLK( I + C!
LOOP
;
: EFS!
256 /MOD 3 PC! 3 PC!
1024 0 DO
BLK( I + C@ 4 PC!
LOOP
;
: INIT
CURRENT @ HERE !
BLK$
['] EFS@ BLK@* !
['] EFS! BLK!* !
RDLN$
LIT< _sys [entry]
." Collapse OS" NL
;
(entry) _
H@ 0x08 BIN+ ! ( update LATEST )
," INIT "
H@ 256 /MOD 2 PC! 2 PC!

View File

@ -9,32 +9,12 @@
393 LOAD ( xcomp core low ) 393 LOAD ( xcomp core low )
: (emit) 0 PC! ; : (emit) 0 PC! ;
: (key) 0 PC@ ; : (key) 0 PC@ ;
: EFS@
256 /MOD 3 PC! 3 PC!
1024 0 DO
4 PC@
BLK( I + C!
LOOP
;
: EFS!
256 /MOD 3 PC! 3 PC!
1024 0 DO
BLK( I + C@ 4 PC!
LOOP
;
420 LOAD ( xcomp core high ) 420 LOAD ( xcomp core high )
(entry) _ (entry) _
( Update LATEST ) ( Update LATEST )
PC ORG @ 8 + ! PC ORG @ 8 + !
," CURRENT @ HERE ! " ," CURRENT @ HERE ! "
," : INIT " 440 446 XPACKR
," BLK$ " ," ' (key) 12 RAM+ ! "
," ['] EFS@ BLK@* ! "
," ['] EFS! BLK!* ! "
," RDLN$ "
," LIT< _sys [entry] "
," LIT< CollapseOS (print) NL "
," ; INIT "
ORG @ 256 /MOD 2 PC! 2 PC! ORG @ 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC! H@ 256 /MOD 2 PC! 2 PC!

View File

@ -1,14 +1,14 @@
TARGET = os.bin TARGET = stage1.bin
BASEDIR = ../.. BASEDIR = ../..
FDIR = $(BASEDIR)/forth FDIR = $(BASEDIR)/forth
EDIR = $(BASEDIR)/emul EDIR = $(BASEDIR)/emul
STAGE = $(EDIR)/stage STAGE2 = $(EDIR)/stage2
EMUL = $(BASEDIR)/emul/hw/rc2014/classic EMUL = $(BASEDIR)/emul/hw/rc2014/classic
.PHONY: all .PHONY: all
all: $(TARGET) all: $(TARGET)
$(TARGET): xcomp.fs $(STAGE) $(TARGET): xcomp.fs $(STAGE2)
cat xcomp.fs | $(STAGE) > $@ cat xcomp.fs | $(STAGE2) > $@
$(SLATEST): $(SLATEST):
$(MAKE) -C $(BASEDIR)/tools $(MAKE) -C $(BASEDIR)/tools

View File

@ -40,7 +40,7 @@ device I use in this recipe.
### Gathering parts ### Gathering parts
* A "classic" RC2014 with Serial I/O * A "classic" RC2014 with Serial I/O
* [Forth's stage binary][stage] * [Forth's stage 2 binary][stage2]
* [romwrite][romwrite] and its specified dependencies * [romwrite][romwrite] and its specified dependencies
* [GNU screen][screen] * [GNU screen][screen]
* A FTDI-to-TTL cable to connect to the Serial I/O module * A FTDI-to-TTL cable to connect to the Serial I/O module
@ -50,10 +50,24 @@ device I use in this recipe.
Modules used in this build are configured through the `conf.fs` file in this Modules used in this build are configured through the `conf.fs` file in this
folder. There isn't much to configure, but it's there. folder. There isn't much to configure, but it's there.
### Build the binary ### Build stage 1
Building the binary is as simple as running `make`. This will yield `os.bin` Self-bootstrapping is in Forth's DNA, which is really nice, but it makes
which can then be written to EEPROM. cross-compiling a bit tricky. It's usually much easier to bootstrap a Forth
from itself than trying to compile it from a foreign host.
This makes us adopt a 2 stages strategy. A tiny core is built from a foreign
host, and then we run that tiny core on the target machine and let it bootstrap
itself, then write our full interpreter binary.
We could have this recipe automate that 2 stage build process all automatically,
but that would rob you of all your fun, right? Instead, we'll run that 2nd
stage on the RC2014 itself!
To build your stage 1, run `make` in this folder, this will yield `stage1.bin`.
This will contain that tiny core and, appended to it, the Forth source code it
needs to run to bootstrap itself. When it's finished bootstrapping, you will
get a prompt to a full Forth interpreter.
### Emulate ### Emulate
@ -86,9 +100,131 @@ identify the tty bound to it (in my case, `/dev/ttyUSB0`). Then:
screen /dev/ttyUSB0 115200 screen /dev/ttyUSB0 115200
Press the reset button on the RC2014 and the "ok" prompt should appear. Press the reset button on the RC2014 to have Forth begin its bootstrap process.
Note that it has to build more than half of itself from source. It takes about
30 seconds to complete.
Once bootstrapping is done you should see the Collapse OS prompt. That's a full
Forth interpreter. You can have fun right now.
However, that long boot time is kinda annoying. Moreover, that bootstrap code
being in source form takes precious space from our 8K ROM. That brings us to
building stage 2.
### Building stage 2
You're about to learn a lot about this platform and its self-bootstrapping
nature, but its a bumpy ride. Grab something. Why not a beer?
Our stage 1 prompt is the result of Forth's inner core interpreting the source
code of the Full Forth, which was appended to the binary inner core in ROM.
This results in a compiled dictionary, in RAM, at address 0x8000+system RAM.
Wouldn't it be great if we could save that compiled binary in ROM and save the
system the trouble of recompiling itself on boot?
Unfortunately, this compiled dictionary isn't usable as-is. Offsets compiled in
there are compiled based on a 0x8000-or-so base offset. What we need is a
0xa00-or-so base offset, that is, something suitable to be appended to the boot
binary, in ROM, in binary form.
Fortunately, inside the compiled source is the contents of the Linker (B120)
which will allow us to relink our compiled dictionary so that in can be
relocated in ROM, next to our boot binary. I won't go into relinking details.
Look at the source. For now, let's just use it:
RLCORE
That command will take the dict from `' H@` up to `CURRENT`, copy it in free
memory and then relocate it. It will print 3 addresses during its processing.
The first address is the top copied address. The process didn't touch memory
above this point. The second address is the wordref of the last copied entry.
The 3rd is the bottom address of the copied dict. When that last address is
printed, the processing is over (because we don't have a `>` prompt, we don't
have any other indicator that the process is over).
### Assembling the stage 2 binary
At that point, we have a fully relocated binary in memory. Depending on our
situations, the next steps differ.
* If we're on a RC2014 that has writing capabilities to permanent storage,
we'll want to assemble that binary directly on the RC2014 and write it to
permanent storage.
* If we're on a RC2014 that doesn't have those capabilities, we'll want to dump
memory on our modern environment using `/tools/memdump` and then assemble that
binary there.
* If we're in the emulator, we'll want to dump our memory using `CTRL+E` and
then assemble our stage 2 binary from that dump.
In these instructions, we assume an emulated environment. I'll use actual
offsets of an actual assembling session, but these of course are only examples.
It is very likely that these will not be the same offsets for you.
So you've pressed `CTRL+E` and you have a `memdump` file. Open it with a hex
editor (I like `hexedit`) to have a look around and to decide what we'll extract
from that memdump. `RLCORE` already gave you important offsets (in my case,
`9a3c`, `99f6` and `8d60`), but although the beginning of will always be the
same (`8d60`), the end offset depends on the situation.
If you look at data between `99f6` and `9a3c`, you'll see that this data is not
100% dictionary entry material. Some of it is buffer data allocated at
initialization. To locate the end of a word, look for `0042`, the address for
`EXIT`. In my case, it's at `9a1a` and it's the end of the `INIT` word.
Moreover, the `INIT` routine that is in there is not quite what we want,
because it doesn't contain the `HERE` adjustment that we find in `pre.fs`.
We'll want to exclude it from our binary, so let's go a bit further, at `99cf`,
ending at `99de`.
So, the end of our compiled dict is actually `99de`. Alright, let's extract it:
dd if=memdump bs=1 skip=36192 count=3198 > dict.bin
`36192` is `8d60` and `3198` is `99de-8d60`. This needs to be prepended by the
boot binary. We already have `stage1.bin`, but this binary contains bootstrap
source code we don't need any more. To strip it, we'll need to `dd` it out to
`LATEST`, in my case `098b`:
dd if=stage1.bin bs=1 count=2443 > s1pre.bin
Now we can combine our binaries:
cat s1pre.bin dict.bin > stage2.bin
Is it ready to run yet? no. There are 3 adjustments we need to manually make
using our hex editor.
1. We need to link `H@` to the hook word of the boot binary. In my case, it's
a matter of writing `02` at `08ec` and `00` at `08ed`, `H@`'s prev field.
2. We need to end our binary with a hook word. It can have a zero-length name
and the prev field needs to properly point to the previous wordref. In my
case, that was `RLCORE` at offset `1559` for a `stage2.bin` size of `1568`,
which means that I appended `0F 00 00` at the end of the file.
3. Finally, we need to adjust `LATEST` which is at offset `08`. This needs to
point to the last wordref of the file, which is equal to the length of
`stage2.bin` because we've just added a hook word. This means that we write
`6B` at offset `08` and `15` at offset `09`.
Now are we ready yet? ALMOST! There's one last thing we need to do: add runtime
source. In our case, because we have a compiled dict, the only source we need
to include is initialization code. We've stripped it from our stage1 earlier,
we need to re-add it.
Look at `xcomp.fs`. You see that `," bla bla bla"` line? That's initialization
code. Copy it to a file like `run.fs` (without the `,"`) and build your final
binary:
cat stage2.bin run.fs > stage2r.bin
That's it! our binary is ready to run!
../../emul/hw/rc2014/classic stage2r.bin
And there you have it, a stage2 binary that you've assembled yourself.
[rc2014]: https://rc2014.co.uk [rc2014]: https://rc2014.co.uk
[romwrite]: https://github.com/hsoft/romwrite [romwrite]: https://github.com/hsoft/romwrite
[stage]: ../../emul [stage2]: ../../emul
[screen]: https://www.gnu.org/software/screen/ [screen]: https://www.gnu.org/software/screen/

View File

@ -8,6 +8,7 @@ itself.
## Gathering parts ## Gathering parts
* A RC2014 Classic * A RC2014 Classic
* `stage2.bin` from the base recipe
* An extra AT28C64B * An extra AT28C64B
* 1x 40106 inverter gates * 1x 40106 inverter gates
* Proto board, RC2014 header pins, wires, IC sockets, etc. * Proto board, RC2014 header pins, wires, IC sockets, etc.
@ -32,21 +33,46 @@ in write protection mode, but I preferred building my own module.
I don't think you need a schematic. It's really simple. I don't think you need a schematic. It's really simple.
### Building the binary ### Assembling stage 3
You build the binary by modifying the base recipe's `xcomp` unit. This binary Stage 2 gives you a full interpreter, but it's missing the "Addressed devices"
is missing 2 things: Addressed devices and the AT28 Driver. module and the AT28 driver. We'll need to assemble a stage 3.
Addressed devices are at B140. If you read that block, you'll see that it tells When you'll have a system with function disk block system, you'll be able to
you to load block 142. Open the `xcomp` unit and locate the ACIA driver loading directly `LOAD` them, but for this recipe, we can't assume you have, so what
line. Insert your new load line after that one. you'll have to do is to manually paste the code from the appropriate blocks.
Addressed devices are at B140. To know what you have to paste, open the loader
block (B142) and see what blocks it loads. For each of the blocks, copy/paste
the code in your interpreter.
Do the same thing with the AT28 driver (B590) Do the same thing with the AT28 driver (B590)
You also have to modify the initialization sequence at the end of the `xcomp` If you're doing the real thing and not using the emulator, pasting so much code
unit to include `ADEV$`. at once might freeze up the RC2014, so it is recommended that you use
`/tools/exec` that let the other side enough time to breathe.
Build again, write `os.com` to EEPROM. After your pasting, you'll have a compiled dict of that code in memory. You'll
need to relocate it in the same way you did for stage 2, but instead of using
`RLCORE`, which is a convenience word hardcoded for stage 1, we'll parametrize
`RLDICT`, the word doing the real work.
`RLDICT` takes 2 arguments, `target` and `offset`. `target` is the first word
of your relocated dict. In our case, it's going to be `' ADEVMEM+`. `offset` is
the offset we'll apply to every eligible word references in our dict. In our
case, that offset is the offset of the *beginning* of the `ADEVMEM+` entry (that
is, `' ADEVMEM+ WORD(` minus the offset of the last word (which should be a hook
word) in the ROM binary.
That offset can be conveniently fetched from code because it is the value of
the `LATEST` constant in stable ABI, which is at offset `0x08`. Therefore, our
offset value is:
' ADEVMEM+ WORD( 0x08 @ -
You can now run `RLDICT` and proceed with concatenation (and manual adjustments
of course) as you did with stage 2. Don't forget to adjust `run.fs` so that it
runs `ADEV$`.
## Writing contents to the AT28 ## Writing contents to the AT28

View File

@ -70,23 +70,35 @@ instead.
## Building your binary ## Building your binary
The binary built in the base recipe doesn't have SDC drivers. Using the same Your Collapse OS binary needs the SDC drivers which need to be inserted during
instructions as in the `eeprom` recipe, you'll need to insert those drivers. Cross Compilation, which needs you need to recompile it from stage 1. First,
The SDC driver is at B600. It gives you a load range. This means that what look at B600. You'll see that it indicates a block range for the driver. That
you need to insert in `xcomp` will look like: needs to be loaded.
Open xcomp.fs from base recipe and locate acia loading. You'll insert a line
right after that that will look like:
602 616 LOADR ( sdc ) 602 616 LOADR ( sdc )
You also need to add `BLK$` to the init sequence. Normally, that's all you need to do. However, you have a little problem: You're
busting the 8K ROM limit. But it's ok, you can remove the linker's XPACKing
line: because you'll have access to the blkfs from SD card, you can load it
from there!
Removing the linker from XPACKing will free enough space for your binary to fit
in 8K. You also have to add `BLK$` to initialization routine.
Build it and write it to EEPROM. Build it and write it to EEPROM.
If you want, once you're all set with the SD card, you can relink core words
like you did in the base recipe for optimal resource usage.
## Testing in the emulator ## Testing in the emulator
The RC2014 emulator includes SDC emulation. You can attach a SD card image to The RC2014 emulator includes SDC emulation. You can attach a SD card image to
it by invoking it with a second argument: it by invoking it with a second argument:
../../../emul/hw/rc2014/classic os.bin ../../../emul/blkfs ../../../emul/hw/rc2014/classic stage3.bin ../../../emul/blkfs
You will then run with a SD card having the contents from `/blk`. You will then run with a SD card having the contents from `/blk`.

View File

@ -9,34 +9,24 @@ either for another RC2014 or for an OS upgrade.
* stage3 from `sdcard` recipe. If you want to write to EEPROM as the final step, * stage3 from `sdcard` recipe. If you want to write to EEPROM as the final step,
you'll need a hybrid stage3 that also includes stuff from the `eeprom` recipe. you'll need a hybrid stage3 that also includes stuff from the `eeprom` recipe.
## Building the binary ## Building stage 1
Build Collapse OS' from within Collapse OS is very similar to how we do Build Collapse OS' stage 1 from within Collapse OS is very similar to how we do
it from the makefile. If you take the time to look at the base recipe it from the makefile. If you take the time to look at the base recipe
`Makefile`, you'll see `cat xcomp.fs | $(STAGE)`. That's the thing. Open `Makefile`, you'll see `cat xcomp.fs | $(STAGE2)`. That's the thing. Open
`xcomp.fs` in a text editor and take a look at it. You'll see that it loads `xcomp.fs` in a text editor and take a look at it.
B618, which contains the meat, and then spits stuff to port 2, which is a
special signal for the `stage` binary.
To assemble from RC2014, all you need to do is load B618. This will To assemble stage 1 from RC2014, all you need to do is to type those commands
yield a binary in memory. To know the start/end offset of the binary, you'll in the same order, and replace the `/MOD 2 PC! 2 PC!` words with `.X`.
type the same two commands and in `xcomp.fs`, but replace the `/MOD 2 PC! 2 PC!` Those commands will inform you of the begin/end offsets of the assembled binary.
words with `.X`. Then, write that binary between those offsets on your target
media. That binary should be the exact same as what you get in `os.bin`
when you run `make`.
Go ahead, run that. However, one thing you should know is that because the SD I'm not going to explain in detail what each command do, but only give you an
card driver is a bit slow, some of these commands take a long time. Multiple overview of what is happening. You are encouraged to read the in-system
minutes. Be patient.
Is that it? Yes. But for your own enlightenment, open B618 and look at it, I'll
give you an overview of its contents. I'm not going to explain in detail what
each command do, however. You are encouraged to read the in-system
documentation for more information. documentation for more information.
The first part is configuration of your new system. When RAM starts, where RSP The first part is configuration of your new system. When RAM starts, where RSP
and PSP start, what ports to use for what device, etc. These configuration starts, what ports to use for what device, etc. These configuration declarations
declarations are expected in the boot code and driver code. are expected in the boot code and driver code.
Then, we load the Z80 assembler and the cross compiler (xcomp for short), which Then, we load the Z80 assembler and the cross compiler (xcomp for short), which
we'll of course need for the task ahead. we'll of course need for the task ahead.
@ -51,15 +41,41 @@ close the binary with a hook word. We're finished with cross-compiling.
We're at the offset that will be `CURRENT` on boot, so we update `LATEST`. We're at the offset that will be `CURRENT` on boot, so we update `LATEST`.
Then, we spit the init source code that will be interpreted on boot. Then, we spit the source code that will be interpreted by stage 1 on boot so
And... that's it! that it bootstraps itself to a full interpreter. Not all units are there
because they don't fit in 8K, but they're sufficient for our needs. We also
need the linker so that we can relink ourselves to stage 2.
Finally, we have initialization code, then a spit of the ending offset.
Go ahead, run that. However, one thing you should know is that because the SD
card driver is a bit slow, some of these commands take a long time. Multiple
minutes. Be patient.
Once all your commands are run and that you have your begin/end offset (write
them down somewhere), you're at the same point as you were after the `make`
part of the base recipe. The contents between your start and end offset is the
exact same as the contents of `stage1.bin` when you run `make`. Continue your
deployment from there.
Good luck!
### What to do on SDerr? ### What to do on SDerr?
If you get `SDerr` in the middle of a LOAD operation, something went wrong with If you get `SDerr` in the middle of a LOAD operation, something went wrong with
the SD card. The bad news is that it left your xcomp operation in an the SD card. The bad news is that it left your xcomp operation in an
inconsistent state. The easiest thing to do it to restart the operation from inconsistent state. If your at the beginning of it, it's easier to restart it
scratch. Those error are not frequent unless hardware is faulty. entirely.
If you're towards the end, you might want to repair it. To do so, you'll have to
bring your `XCURRENT` and `HERE` values to where they were before the LOAD
operation. You could have thought ahead and printed them before the LOAD, but if
you didn't, you'll just have to dig in your memory with `DUMP`.
You're looking at the offset of the last wordref of the *previous* LOAD
operation. That offset is going in `XCURRENT`. Then, you're looking at the end
of that word. That offset goes in `HERE`. Once you've done that, relaunch your
LOAD.
### Verifying ### Verifying

View File

@ -1,3 +1,25 @@
618 LOAD 0x8000 CONSTANT RAMSTART
0xf000 CONSTANT RS_ADDR
0xfffa CONSTANT PS_ADDR
0x80 CONSTANT ACIA_CTL
0x81 CONSTANT ACIA_IO
4 CONSTANT SDC_SPI
5 CONSTANT SDC_CSLOW
6 CONSTANT SDC_CSHIGH
RAMSTART 0x70 + CONSTANT ACIA_MEM
212 LOAD ( z80 assembler )
262 LOAD ( xcomp )
270 LOAD ( xcomp overrides )
282 LOAD ( boot.z80 )
393 LOAD ( xcomp core low )
582 LOAD ( acia )
420 LOAD ( xcomp core high )
(entry) _
( Update LATEST )
PC ORG @ 8 + !
440 446 XPACKR ( core )
123 132 XPACKR ( linker )
," : _ ACIA$ RDLN$ (ok) ; _ "
ORG @ 256 /MOD 2 PC! 2 PC! ORG @ 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC! H@ 256 /MOD 2 PC! 2 PC!

View File

@ -1,15 +1,15 @@
TARGET = os.bin TARGET = stage1.bin
BASEDIR = ../.. BASEDIR = ../..
FDIR = $(BASEDIR)/forth FDIR = $(BASEDIR)/forth
EDIR = $(BASEDIR)/emul EDIR = $(BASEDIR)/emul
STAGE = $(EDIR)/stage STAGE2 = $(EDIR)/stage2
EMUL = $(BASEDIR)/emul/hw/ti/ti84 EMUL = $(BASEDIR)/emul/hw/ti/ti84
MKTIUPGRADE = mktiupgrade MKTIUPGRADE = mktiupgrade
.PHONY: all .PHONY: all
all: $(TARGET) all: $(TARGET)
$(TARGET): xcomp.fs $(STAGE) $(TARGET): xcomp.fs $(STAGE2)
cat xcomp.fs | $(STAGE) > $@ cat xcomp.fs | $(STAGE2) > $@
$(EMUL): $(EMUL):
$(MAKE) -C ${@:%/ti84=%} $(MAKE) -C ${@:%/ti84=%}

View File

@ -38,7 +38,7 @@ screen as output and its builtin keyboard as input.
## Build the ROM ## Build the ROM
Running `make` will result in `os.rom` being created. Running `make` will result in `stage1.rom` being created.
## Emulate ## Emulate

View File

@ -68,6 +68,7 @@ CREATE ~FNT CPFNT3x5
(entry) _ (entry) _
( Update LATEST ) ( Update LATEST )
PC ORG @ 8 + ! PC ORG @ 8 + !
440 446 XPACKR ( core )
," : _ LCD$ KBD$ (ok) RDLN$ ; _ " ," : _ LCD$ KBD$ (ok) RDLN$ ; _ "
ORG @ 0x100 - 256 /MOD 2 PC! 2 PC! ORG @ 0x100 - 256 /MOD 2 PC! 2 PC!
H@ 256 /MOD 2 PC! 2 PC! H@ 256 /MOD 2 PC! 2 PC!

View File

@ -1,8 +1,8 @@
TARGET = os.bin TARGET = stage1.bin
EDIR = ../../emul EDIR = ../../emul
STAGE = $(EDIR)/stage STAGE2 = $(EDIR)/stage2
.PHONY: all .PHONY: all
all: $(TARGET) all: $(TARGET)
$(TARGET): xcomp.fs $(STAGE) $(TARGET): xcomp.fs $(STAGE2)
cat xcomp.fs | $(STAGE) > $@ cat xcomp.fs | $(STAGE2) > $@

View File

@ -67,10 +67,10 @@ kind of reception! You're gonna feel real badass about it too...
* `_` is `CLEAR+ENTER`. * `_` is `CLEAR+ENTER`.
## Building the binary ## Building the stage 1
You can build the binary to send to the TRS-80 with `make`, which will yield You can start the process by building the stage 1 binary. Running `make` in
`os.bin`. You'll need it later. this folder will yield a `stage1.bin` file. You'll need it later.
## Testing serial communication ## Testing serial communication

View File

@ -7,13 +7,15 @@ RS_ADDR 0x80 - CONSTANT RAMSTART
0x3000 BIN( ! 0x3000 BIN( !
282 LOAD ( boot.z80 ) 282 LOAD ( boot.z80 )
492 LOAD ( trs80.z80 )
393 LOAD ( xcomp core low ) 393 LOAD ( xcomp core low )
492 LOAD ( trs80 )
420 LOAD ( xcomp core high ) 420 LOAD ( xcomp core high )
(entry) _ (entry) _
( Update LATEST ) ( Update LATEST )
PC ORG @ 8 + ! PC ORG @ 8 + !
," CURRENT @ HERE ! " ," CURRENT @ HERE ! "
440 446 XPACKR ( core )
499 500 XPACKR ( trs80.fs )
( 0x0a == NLPTR. TRS-80 wants CR-only newlines ) ( 0x0a == NLPTR. TRS-80 wants CR-only newlines )
," : _ ['] CR 0x0a RAM+ ! BLK$ FD$ (ok) RDLN$ ; _ " ," : _ ['] CR 0x0a RAM+ ! BLK$ FD$ (ok) RDLN$ ; _ "
ORG @ 256 /MOD 2 PC! 2 PC! ORG @ 256 /MOD 2 PC! 2 PC!

View File

@ -2,7 +2,8 @@
: SDC_SPI 4 ; : SDC_SPI 4 ;
: SDC_CSLOW 5 ; : SDC_CSLOW 5 ;
: SDC_CSHIGH 6 ; : SDC_CSHIGH 6 ;
602 616 LOADR ( sdc ) 372 LOAD ( sdc.z80 )
374 LOAD ( sdc.fs )
0x0000 0x00 _crc16 0x0000 #eq 0x0000 0x00 _crc16 0x0000 #eq
0x0000 0x01 _crc16 0x1021 #eq 0x0000 0x01 _crc16 0x1021 #eq