I had some issues writing some of these words (especially with doubles and single cells mixed on the stack), so I still have stack comments left in them. That was quite handy for debugging them, but I did have the lingering thought that I should make a new word for stack comments, perhaps "SC(" for Stack Comments, that prints out what I think should be on the stack and the actual values that are there - I could even make it a deferred word so that I could change it to just be silent when I'm not debugging anymore. Forth is a bit mind bending when you realize that you can make it do whatever you want that seems useful or amusing.
I didn't end up writing my stack comment helper word, but I'd be interested in how others do debugging. I found the ability to copy and paste chunks of code and then be able to inspect the stack very helpful, along with dump for checking my buffers and data structures. I also snuck a bunch of ".s" in the tricky spots.
Code: Select all
\ Continued from previous code
: bin ; ( Required by ANS, but we're ignoring it. )
( File access methods )
1 constant r/o 2 constant w/o 3 constant r/w
: findfile ( fileid 'findfile direntry_addr -- f )
( This word is used to help find a file in a directory )
( with walkdirectory. It needs the address of a fileid )
( structure with just the name filled in to be on the )
( stack -- under the things walkdirectory needs. )
( cr ." checking " dup 0B type cr .s ( DEBUG )
0B ( length to compare )
3 pick ( bring fileid struct address over )
( >filename -- but offset is zero)
0B compare ;
: eof? ( fileid -- f ) ( return true if at end of file )
dup >fileposition 2@ rot >filesize 2@ d= ;
( open-file - simplified for read-only access )
: open-file ( c-addr u fam -- fileid ior )
>r ( save fam )
newfileid ( Allot memory for the file info )
( c-addr u fileid ) -rot 2 pick swap move ( filename )
( fileid ) r> over >attrib c! ( save fam )
( fileid ) working_dir init_directory
( fileid ) ['] findfile working_dir walkdirectory
( fileid direntry|0 )
?dup 0= if
cr ." Can't open file: " dup 0B type cr
1 ( ior of 1 = Can't open file ) exit
then
( fileid direntry ) swap >r ( save fileid )
dup >clustLOW @ ( first cluster LSB )
over >clustHI @ ( first cluster MSB )
( direntry firstcluster.d )
2dup r@ >firstcluster 2! ( Save first cluster )
2dup r@ >currentcluster 2! ( start at first cluster )
( direntry firstcluster.d )
cluster>sector r@ >currentsector 2! ( starting sector )
( direntry ) dup >filesize 32bit@ r@ >filesize 2!
( direntry ) drop ( Done with direntry )
r> ( bring back fileid structure )
dup >fileposition d0!
dup >linestart d0!
0 ( no errors/exceptions )
;
: read-char ( fileid -- c ) ( Note: does not check eof )
dup >currentsector 2@ sector>buffer ( Get the sector )
dup >fileposition 2@ ( Get the position in the file )
drop 200 ( 512 ) mod ( Get offset into buffer )
sectorbuff + c@ swap ( Get the character )
( c fileid )
( Move to next character )
dup >fileposition d1+! ( increment fileposition )
( Check to see if we've wrapped to a new sector )
dup >fileposition 2@ drop 200 ( 512 ) mod 0= if
nextsector ( uses fileid ) else drop ( the fileid )
then
;
: file-position ( fileid -- ud ior )
>fileposition 2@ ( Get current position )
0 ( No error ) ;
: file-size ( fileid -- ud ior )
>filesize 2@ ( Get file size )
0 ( No error ) ;
: sectorff ( #bytes.d fileid -- )
( Sector fast-forward - follow FAT chain )
( to determine current cluster/sector values. )
( Assumes starting from beginning of file. )
>r ( Save fileid )
( Move to next sector for every 512 bytes )
( Divide count by 512 - using shifts )
9 drshift
begin
2dup d0<>
while
r@ nextsector ( Move to the next sector )
1. d- ( Reduce the count )
repeat
r> drop 2drop ;
: reposition-file ( ud fileid -- ior )
>r ( Save the fileid )
r@ >filesize 2@ 2over ( newpos filesize newpos )
d< if ( Check bounds )
." Cannot resize beyond end of file"
r> drop 2drop exit then
( New position is ok. Save it. )
2dup r@ >fileposition 2!
( Rewind the file to the first sector )
r@ >firstcluster 2@ ( Get the first cluster )
2dup r@ >currentcluster 2! ( Make first cluster current )
cluster>sector ( Determine sector for this cluster )
r@ >currentsector 2! ( Make that the current )
r> sectorff ( Follow the FAT chains to the right sector )
0 ( IO Result - no error ) ;Code: Select all
\ Continued from previous code
: catfile ( fileid -- ) ( Copy file contents to screen )
>r ( Save fileid ) cr ( Start on the next line )
begin r@ eof? 0= while r@ read-char emit repeat r> drop ;
: rewind ( fileid -- )
( Move fileposition back to beginning of file )
0. rot reposition-file drop ;Code: Select all
: lcd.fs s" LCD FS " ; ( A filename in direntry format ) ok
lcd.fs r/o open-file drop constant lcdfileid ok
lcdfileid catfile
( LCD Routines - SamCo - 2018-11-15 ) hex
: lcd-init ( -- ) 38 7FC0 c! 0E 7FC0 c! ;
: lcd-busy ( -- ) ( Wait until LCD is not busy )
begin 7FC0 c@ 80 and while repeat ;
: lcd-cmd ( cmd -- ) ( Send an LCD command )
lcd-busy 7FC0 c! ; allow-native
: lcd-char ( char -- ) ( Send an LCD character )
lcd-busy 7FC1 c! ; allow-native
: lcd-type ( addr n -- ) ( Send a string to the LCD )
0 ?do dup i + c@ lcd-char loop drop ;
: lcd." ( Make and send string ) postpone s" lcd-type ;
( Helper words )
: lcd-line1 ( -- ) 80 lcd-cmd ; allow-native
: lcd-line2 ( -- ) C0 lcd-cmd ; allow-native
: lcd-clear ( -- ) 01 lcd-cmd ; allow-native
decimal
ok