mirror of
https://github.com/mgcaret/of816.git
synced 2025-01-21 00:31:55 +00:00
351 lines
7.8 KiB
Forth
351 lines
7.8 KiB
Forth
\ W65C816SXB ROM loader. Itself in FCode, this defines some words to bootstrap
|
|
\ any FCode and files in the SXB's flash ROM.
|
|
|
|
\ This provides two facilities: FCode loader, and romfs.
|
|
\ romfs provides a simple filesystem of up to 32K (one bank of ROM) in the SXB for
|
|
\ files. Basic ANSI-ish functions to open/read/close the files are provided
|
|
\ as well as include and included. romfs was inspired by SLOF's romfs.
|
|
\ romfs may be omitted during tokenization by defining the commad-line symbol no-romfs
|
|
\ i.e. adding -d no-romfs to the toke command line, this saves more than 1K of output
|
|
\ in the tokenized FCode.
|
|
|
|
\ Note that the SXB-specific word $SXB-READROM takes a virtual address of the form
|
|
\ $bbaaaaaa where bb is the ROM bank to select, and the address is then used to read it
|
|
\ For practical purposes to read the ROM the addresses are restricted to:
|
|
\ $00008000-$0000FFFF - bank 0, $01008000-$0100FFFF - bank 1,
|
|
\ $02008000-$0200FFFF - bank 2, $03008000-$0300FFFF - bank 3.
|
|
|
|
start1 hex
|
|
|
|
." W65C816SXB ROM loader by M.G. ... "
|
|
|
|
headers
|
|
|
|
headerless
|
|
|
|
\ Stuff we need to get to that isn't supported by FCode
|
|
defer $sxb-readrom
|
|
s" $sxb-readrom" $find 0= if ." no $SXB-READROM" abort then to $sxb-readrom
|
|
|
|
[ifndef] no-romfs
|
|
defer -trailing
|
|
s" -trailing" $find drop to -trailing
|
|
defer parse-word
|
|
s" parse-word" $find drop to parse-word
|
|
|
|
: 2w@ dup w@ swap wa1+ w@ ;
|
|
|
|
\ temp vars for file I/O, headerless to save space
|
|
\ $fileno is used for susequent conditionals to compile remaining romfs code
|
|
0 value $fileno
|
|
0 value $bufsz
|
|
0 value $buffer
|
|
0 value $incbuffer
|
|
[endif]
|
|
|
|
headers
|
|
|
|
\ a $100-byte page buffer is provided to avoid slow reads of the ROM to a certain extent
|
|
fffffffff value $sxb-readrom-page
|
|
0 value $sxb-readrom-buf
|
|
|
|
[ifexist] $fileno
|
|
0 value $sxb-romfs-filebuf
|
|
0 value $sxb-romfs-files
|
|
0 value $sxb-romfs-tab
|
|
[endif]
|
|
|
|
\ fetch a page to the page buffer, allocating it if necessary, and doing nothing if
|
|
\ it's already in the page buffer
|
|
: $sxb-rom-fetchpage ( v-addr -- v-addr )
|
|
$sxb-readrom-buf 0= if
|
|
100 alloc-mem to $sxb-readrom-buf
|
|
ffffffff to $sxb-readrom-page ( invalid page number )
|
|
then
|
|
dup 8 >> $sxb-readrom-page <> if
|
|
dup ffffff00 and $sxb-readrom-buf 100 $sxb-readrom
|
|
dup 8 >> to $sxb-readrom-page
|
|
then
|
|
;
|
|
|
|
\ Byte read function for the ROM, used to execute FCode.
|
|
: $sxb-rom-rb@ ( v-addr -- byte )
|
|
$sxb-rom-fetchpage ff and $sxb-readrom-buf + c@
|
|
;
|
|
|
|
\ Free the page buffer to return memory to the user
|
|
: $sxb-readrom-free ( -- )
|
|
$sxb-readrom-buf if
|
|
$sxb-readrom-buf 100 free-mem
|
|
then
|
|
0 to $sxb-readrom-buf
|
|
ffffffff to $sxb-readrom-page
|
|
;
|
|
|
|
\ Magic test for FCode
|
|
: $$fcode-at? ( v-addr -- f )
|
|
$sxb-rom-fetchpage ff and $sxb-readrom-buf + @ 4346474D =
|
|
;
|
|
|
|
[ifexist] $fileno
|
|
\ Magit test for romfs
|
|
: $$romfs-at? ( v-addr -- f )
|
|
$sxb-rom-fetchpage ff and $sxb-readrom-buf + @ 5346474D =
|
|
;
|
|
[endif]
|
|
|
|
external
|
|
|
|
[ifexist] $fileno
|
|
\ Holds location of discovered romfs
|
|
0 value $sxb-romfs
|
|
[endif]
|
|
|
|
\ see if there is FCode in the SXB ROM at v-addr.
|
|
: $sxb-rom-fcode-at? ( v-addr -- f )
|
|
$$fcode-at? $sxb-readrom-free
|
|
;
|
|
|
|
[ifexist] $fileno
|
|
\ see if there is romfs in the SXB ROM at v-addr.
|
|
: $sxb-rom-romfs-at? ( v-addr -- f )
|
|
$$romfs-at? $sxb-readrom-free
|
|
;
|
|
[endif]
|
|
|
|
\ byte-load FCode in the SXB ROM.
|
|
: $sxb-rom-byte-load ( v-addr -- )
|
|
dup $$fcode-at? if
|
|
cell+ ['] $sxb-rom-rb@ ['] byte-load catch
|
|
$sxb-readrom-free
|
|
dup if
|
|
nip nip
|
|
then
|
|
throw
|
|
else
|
|
." no FCode at " . true abort
|
|
then
|
|
;
|
|
|
|
headers
|
|
|
|
\ Scan a bank for FCode and execute any that is found
|
|
: $sxb-fc-boot-bank ( bank -- )
|
|
1000000 *
|
|
ffff 8000 do dup i + dup $$fcode-at? if
|
|
$sxb-rom-byte-load
|
|
else
|
|
drop
|
|
then
|
|
1000 +loop
|
|
drop
|
|
;
|
|
|
|
[ifexist] $fileno
|
|
\ scan a bank for romfs and update $sxb-romfs if found
|
|
: $romfs-find-bank ( bank -- )
|
|
1000000 *
|
|
ffff 8000 do dup i + dup $$romfs-at? if
|
|
to $sxb-romfs leave
|
|
else
|
|
drop
|
|
then
|
|
1000 +loop
|
|
drop
|
|
;
|
|
|
|
\ return address of romfs or throw exception
|
|
: $sxb-romfs? ( -- addr )
|
|
$sxb-romfs ?dup 0= if d# -37 throw then
|
|
;
|
|
|
|
\ Normalize file ID and make sure it is valid
|
|
: romfs-file? ( u1 -- u2 / u2 = normalized file ID )
|
|
ffff and dup $sxb-romfs-files u>= if d# -38 throw then
|
|
;
|
|
|
|
\ Get file name of file in romfs
|
|
: romfs-file ( u -- c-addr u2 )
|
|
romfs-file? $sxb-romfs?
|
|
$sxb-rom-fetchpage drop $sxb-readrom-buf cell+ char+ swap 4 << + c -trailing
|
|
;
|
|
|
|
\ Return info about a romfs file
|
|
: romfs-finfo ( -- offset length )
|
|
romfs-file drop c + 2w@
|
|
;
|
|
|
|
\ Find a file in the romfs, return file number if we find it
|
|
: romfs-ffind ( c-addr u -- u2 true | false )
|
|
-1 -rot $sxb-romfs-files 0 ?do
|
|
2dup i romfs-file 2 pick = if
|
|
\ lengths equal
|
|
swap comp 0= if
|
|
i -rot >r >r swap drop r> r>
|
|
then
|
|
else
|
|
\ lengths unequal
|
|
3drop
|
|
then
|
|
loop
|
|
2drop
|
|
dup 0< if
|
|
drop false
|
|
else
|
|
true
|
|
then
|
|
;
|
|
|
|
\ Get ROMfs table entry for file number
|
|
: $romfs-t# ( file# -- addr )
|
|
2* cells $sxb-romfs-tab +
|
|
;
|
|
|
|
\ "open" a romfs file
|
|
\ Set up table entry for the file with current (start) and end addresses.
|
|
: $romfs-open ( u -- )
|
|
>r r@ romfs-finfo over + $sxb-romfs + swap $sxb-romfs + swap r> $romfs-t# 2!
|
|
;
|
|
|
|
\ "close" a romfs file. Set current address to end address
|
|
: $romfs-close ( u -- )
|
|
$romfs-t# >r r@ 2@ swap drop dup r> 2!
|
|
$sxb-readrom-free
|
|
;
|
|
|
|
\ Check if we hit EOF in open romfs file
|
|
: $romfs-eof? ( u -- f )
|
|
$romfs-t# 2@ u>=
|
|
;
|
|
|
|
\ Byte read routine for romfs
|
|
: $romfs-rb@ ( u -- byte )
|
|
$romfs-t# dup >r @ dup 1+ r> ! $sxb-rom-rb@
|
|
;
|
|
|
|
\ See if we hit a line-ending char
|
|
: is-eol?
|
|
case
|
|
0d of true endof \ CR
|
|
0a of true endof \ LF
|
|
>r false r>
|
|
endcase
|
|
;
|
|
|
|
\ Locate a romfs in the SXB ROM, updating $sxb-romfs and $sxb-romfs-files if found
|
|
\ and allocating the access table
|
|
: $romfs-find ( -- )
|
|
4 1 do $sxb-romfs if leave else i $romfs-find-bank then loop
|
|
$sxb-romfs if
|
|
$sxb-romfs $sxb-rom-fetchpage drop $sxb-readrom-buf cell+ c@ dup to $sxb-romfs-files
|
|
2* cells dup alloc-mem dup to $sxb-romfs-tab swap erase
|
|
then
|
|
$sxb-readrom-free
|
|
;
|
|
[endif]
|
|
|
|
external
|
|
|
|
\ Find and execute all FCode in ROM at $1000-aligned addresses
|
|
: $sxb-fc-boot
|
|
4 1 do i $sxb-fc-boot-bank loop
|
|
$sxb-readrom-free
|
|
;
|
|
|
|
[ifexist] $fileno
|
|
\ List files in romfs
|
|
: romfs-list
|
|
$sxb-romfs-files 0 ?do
|
|
i romfs-file type cr
|
|
loop
|
|
$sxb-readrom-free
|
|
;
|
|
|
|
\ open file in romfs
|
|
: open-file ( c-addr u fam -- fileid 0 )
|
|
drop
|
|
romfs-ffind if
|
|
dup 10000 or swap $romfs-open 0
|
|
else
|
|
d# -69 throw
|
|
endif
|
|
;
|
|
|
|
\ report position in open file
|
|
: file-position ( fid -- u )
|
|
romfs-file? $romfs-t# 2@ swap -
|
|
;
|
|
|
|
\ close romfs file
|
|
: close-file ( fileid -- 0 )
|
|
romfs-file? $romfs-close 0
|
|
$sxb-readrom-free
|
|
;
|
|
|
|
\ read open romfs file
|
|
: read-file ( c-addr u fileid - u2 0 )
|
|
romfs-file? to $fileno to $bufsz to $buffer
|
|
0
|
|
$bufsz 0 ?do
|
|
$fileno $romfs-eof? if leave then
|
|
$fileno $romfs-rb@
|
|
over $buffer + c! 1+
|
|
loop
|
|
0
|
|
;
|
|
|
|
\ read a line from open romfs file
|
|
: read-line ( c-addr u fileid - u2 f 0 )
|
|
romfs-file? to $fileno to $bufsz to $buffer
|
|
0
|
|
$bufsz 0 ?do
|
|
$fileno $romfs-eof? if leave then
|
|
$fileno $romfs-rb@
|
|
dup is-eol? if drop leave then
|
|
over $buffer + c! 1+
|
|
loop
|
|
$fileno $romfs-eof? 0= 0
|
|
;
|
|
|
|
headers
|
|
|
|
\ read and evaluate each line of file in romfs describe in incbuf
|
|
\ incbuf is a buffer 1 cell+80 bytes long, with the file id in the cell
|
|
: $inc ( incbuf -- )
|
|
$incbuffer ?dup 0= if d# -9 throw then
|
|
begin
|
|
>r r@ cell+ 80 r@ @
|
|
read-line 2drop
|
|
r@ cell+ swap eval
|
|
r> dup @ romfs-file?
|
|
$romfs-eof? until
|
|
drop
|
|
;
|
|
|
|
external
|
|
|
|
\ allocate a buffer and evaulate the given file
|
|
: included ( c-addr u -- )
|
|
0 open-file drop
|
|
$incbuffer >r 80 cell+ alloc-mem dup to $incbuffer !
|
|
['] $inc catch r> swap >r $incbuffer swap to $incbuffer
|
|
dup @ close-file drop 80 cell+ free-mem
|
|
r> throw
|
|
;
|
|
|
|
\ parse name and perform the function of included
|
|
: include ( " name " -- )
|
|
parse-word included
|
|
;
|
|
|
|
$romfs-find
|
|
[endif]
|
|
|
|
." loaded!" cr
|
|
|
|
[ifexist] $fileno
|
|
$sxb-romfs ?dup if ." ROMfs at " u. cr then
|
|
[endif]
|
|
|
|
fcode-end
|