Compare commits

...

4 Commits

Author SHA1 Message Date
Virgil Dupras
830aad69a7 recipe/rc2014/selfhost: new recipe 2020-04-25 16:03:01 -04:00
Virgil Dupras
13771d8c92 xcomp: add XPACK 2020-04-25 16:02:47 -04:00
Virgil Dupras
389b23fe1a Change C<? mechanic
It's now a simple flag updated by the C< implementation. No more
routine pointer.

The goal is to avoid tons of "ok" during a LOAD operation.
2020-04-25 09:10:25 -04:00
Virgil Dupras
4160c8ebbf recipes/rc2014: busting the 8K limit again! 2020-04-25 08:15:17 -04:00
15 changed files with 127 additions and 29 deletions

View File

@ -1,5 +1,6 @@
C<?* is a pointer to a word being called by C<?. If 0 or 1,
will return that value as-is.
C<? is a flag indicating whether a character is waiting in the
input stream. 1 means yes, 0 means no. It is the responsibility
of C<* to update that flag.
WORDBUF is the buffer used by WORD
@ -12,5 +13,4 @@ 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.
(cont.)

View File

@ -1 +1 @@
263 LOAD 265 LOAD
263 LOAD 265 LOAD 268 LOAD

6
blk/267 Normal file
View File

@ -0,0 +1,6 @@
XPACK - pack source code
The goal of this word is to pack source code in tight places,
such as on the boot section of an EEPROM. It takes a block
number, reads it and packs it to HERE. It normalizes all
whitespaces to a single space and ignore comments.

16
blk/268 Normal file
View File

@ -0,0 +1,16 @@
: XPACK ( blkno -- )
BLK@
BLK( 0x2e RAM+ ! ( boot ptr )
['] (boot<) 0x08 RAM+ ! ( C<* override )
BEGIN
WORD
0x2e RAM+ @ BLK( 1024 + < IF
DUP LIT< ( S= IF
DROP [COMPILE] (
ELSE
SCPY 0x20 H@ 1- C!
THEN 0 ( loop again )
ELSE 1 ( stop looping ) THEN
UNTIL
0 0x08 RAM+ !
;

View File

@ -2,7 +2,7 @@
for an abort message )
: (parse) (parsed) NOT IF ABORT THEN ;
: C<? 0x06 RAM+ @ DUP 2 > IF EXECUTE THEN ( 06 == C<?* ) ;
: C<? 0x06 RAM+ @ ;
: C<
0x08 RAM+ @ ( 08 == C<* override )
DUP NOT IF DROP 0x0c RAM+ @ THEN ( 0c == C<* )

Binary file not shown.

View File

@ -61,17 +61,21 @@
;
: LOAD
( save BLK>, C<* override and boot< ptr to RSP )
( save restorable variables to RSP )
BLK> @ >R
0x08 RAM+ @ >R
0x2e RAM+ @ >R
0x06 RAM+ @ >R ( C<? )
0x2e RAM+ @ >R ( boot ptr )
BLK@
( Point to beginning of BLK )
BLK( 0x2e RAM+ !
( 08 == C<* override )
['] _ 0x08 RAM+ !
( While we interpret, don't print "ok" after every word )
1 0x06 RAM+ ! ( 06 == C<? )
INTERPRET
R> 0x2e RAM+ !
R> 0x06 RAM+ !
( Before we restore C<* are we restoring it to "_"?
if yes, it means we're in a nested LOAD which means we
should also load back the saved BLK>. Otherwise, we can

View File

@ -18,7 +18,8 @@
: BEGIN H@ ; IMMEDIATE
: AGAIN COMPILE (br) H@ - , ; IMMEDIATE
: UNTIL COMPILE (?br) H@ - , ; IMMEDIATE
: ( BEGIN LIT< ) WORD S= UNTIL ; IMMEDIATE
: _ 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
@ -27,6 +28,8 @@
"_": words starting with "_" are meant to be "private",
that is, only used by their immediate surrondings.
40 is ASCII for '('. We do this to simplify XPACK's task of
not mistakenly consider '(' definition as a comment.
LITS: 34 == litWord
LITA: 36 == addrWord
COMPILE: Tough one. Get addr of caller word (example above

View File

@ -54,7 +54,7 @@
DUP @ 25136 = NOT IF 0 EXIT THEN ( a 0 )
( We have "0b" prefix )
2+
0 ( a r )
0 ( a r )
BEGIN
SWAP C@+ ( r a+1 c )
DUP NOT IF 2DROP 1 EXIT THEN ( r 1 )

View File

@ -59,15 +59,18 @@
LF IN( IN> !
;
: RDLN<? IN> @ C@ ;
( And finally, implement a replacement for the (c<) routine )
( And finally, implement C<* )
: RDLN<
RDLN<? ( c )
( not EOL? good, inc and return )
DUP IF 1 IN> +! EXIT THEN ( c )
( EOL ? readline. we still return typed char though )
(rdln) ( c )
IN> @ C@
DUP IF
( not EOL? good, inc and return )
1 IN> +!
ELSE
( EOL ? readline. we still return null though )
(rdln)
THEN
( update C<? flag )
IN> @ C@ 0 > 0x06 RAM+ ! ( 06 == C<? )
;
( Initializes the readln subsystem )
@ -78,7 +81,7 @@
the last typed 0x0a and one for the following NULL. )
INBUFSZ 4 + ALLOT
(infl)
['] RDLN<? 0x06 RAM+ !
['] RDLN< 0x0c RAM+ !
1 0x06 RAM+ ! ( 06 == C<? )
;

View File

@ -25,7 +25,7 @@ are other recipes related to the RC2014:
* [Writing to a AT28 from Collapse OS](eeprom/README.md)
* [Accessing a MicroSD card](sdcard/README.md)
* [Assembling binaries](zasm/README.md)
* [Self-hosting](selfhost/README.md)
* [Interfacing a PS/2 keyboard](ps2/README.md)
## Recipe

View File

@ -1,7 +1,2 @@
: (c<) KEY DUP EMIT ;
: _
ACIA$
." Collapse OS" CRLF
( 0c == CINPTR )
['] (c<) 0x0c RAM+ !
; _
: x KEY DUP EMIT ;
: _ ACIA$ (ok) ['] x 0x0c RAM+ ! ; _

View File

@ -105,5 +105,22 @@ And thats it! You have full access to disk block mechanism:
(at this moment, the driver is a bit slow though...)
## How do I fill my SD card with Collapse OS' FS?
Very easy. You see that `/emul/blkfs` file? You dump it to your raw device.
For example, if the device you get when you insert your SD card is `/dev/sdb`,
then you type `cat emul/blkfs | sudo tee /dev/sdb > /dev/null`.
## What to do on SDerr?
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
inconsistent state. If your at the beginning of it, it's easier to restart it
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`.
[schematic]: spirelay/spirelay.pdf
[inspiration]: https://www.ecstaticlyrics.com/electronics/SPI/fast_z80_interface.html

View File

@ -0,0 +1,54 @@
# Assembling Collapse OS from within it
This is where we tie lose ends, complete the circle, loop the loop: we assemble
a new Collapse OS *entirely* from within Collapse OS and write it to EEPROM,
either for another RC2014 or for an OS upgrade.
## Gathering parts
* stage4 from `sdcard` recipe. If you want to write to EEPROM as the final step,
you'll need a hybrid stage4 that also includes stuff from the `eeprom` recipe.
## Building stage 1
### Part 1
Building the first part of stage 1 (the binary part, before the inlined-source
part) from within Collapse OS is actually very similar from building it from a
modern environment. If you take the time to look at the base recipe `Makefile`,
you'll see `cat xcomp.fs | $(STAGE2)`. That command builds part 1. Open
`xcomp.fs` in a text editor and take a look at it.
To assemble stage 1 from RC2014, all you need to do is to type those commands
in the same order, and replace the `H@ 256 /MOD 2 PC! 2 PC!` lines with `H@ .X`.
Those commands will inform you of the begin/end offsets of the assembled binary.
The meaning of these commands is not explained here. You are encouraged to read
the in-system documentation for more information.
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 ready to assemble part 2.
### What to do on SDerr?
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
inconsistent state. If your at the beginning of it, it's easier to restart it
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.
### Part 2
TODO

View File

@ -13,7 +13,7 @@ by more than once space or by a newline. Hackish, but works.
int main()
{
int spccnt = 2; // if the first char is a (, consider it a comment opener.
int spccnt = 1; // if the first char is a (, consider it a comment opener.
int incomment = 0;
int c;
c = getchar();
@ -24,7 +24,7 @@ int main()
// doesn't like when they're not there...
putchar(c);
}
spccnt += 2;
spccnt += 1;
} else if (c == ' ') {
spccnt++;
} else {
@ -33,7 +33,7 @@ int main()
incomment = 0;
}
} else {
if ((c == '(') && (spccnt > 1)) {
if ((c == '(') && spccnt) {
putchar(' ');
spccnt = 0;
int next = getchar();