diff --git a/apps/basic/README.md b/apps/basic/README.md index c6d9b83..b9242a6 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -82,15 +82,17 @@ are initialized to zero on launch. There are two types of commands: normal and direct-only. The latter can only be invoked in direct mode, not through a code listing. -**bye**. Direct-only. Quits BASIC +**bye**: Direct-only. Quits BASIC -**list**. Direct-only. Prints all lines in the code listing, prefixing them +**list**: Direct-only. Prints all lines in the code listing, prefixing them with their associated line number. -**run**. Direct-only. Runs code from the listing, starting with the first one. +**run**: Direct-only. Runs code from the listing, starting with the first one. If `goto` was previously called in direct mode, we start from that line instead. -**print**. Prints the result of the specified expression, then CR/LF. Can be +**clear**: Direct-only. Clears the current code listing. + +**print**: Prints the result of the specified expression, then CR/LF. Can be given multiple arguments. In that case, all arguments are printed separately with a space in between. For example, `print 12 13` prints `12 13` @@ -98,16 +100,16 @@ Unlike anywhere else, the `print` command can take a string inside a double quote. That string will be printed as-is. For example, `print "foo" 40+2` will print `foo 42`. -**goto**. Make the next line to be executed the line number specified as an +**goto**: Make the next line to be executed the line number specified as an argument. Errors out if line doesn't exist. Argument can be an expression. If invoked in direct mode, `run` must be called to actually run the line (followed by the next, and so on). -**if**. If specified condition is true, execute the rest of the line. Otherwise, +**if**: If specified condition is true, execute the rest of the line. Otherwise, do nothing. For example, `if 2>1 print 12` prints `12` and `if 2<1 print 12` does nothing. The argument for this command is a "thruth expression". -**input**. Prompts the user for a numerical value and puts that value in the +**input**: Prompts the user for a numerical value and puts that value in the specified variable. The prompted value is evaluated as an expression and then stored where specified. For example, `input x` stores the result of the evaluation in variable `x`. Before the variable name, a quoted string literal @@ -144,3 +146,7 @@ Here's the documentation for them. `fs.asm` provides those commands: **fls**: prints the list of files contained in the active filesystem. + +**ldbas**: loads the content of the file specified in the argument (as an +unquoted filename) and replace the current code listing with this contents. Any +line not starting with a number is ignored (not an error). diff --git a/apps/basic/buf.asm b/apps/basic/buf.asm index 010c2d2..dee6a1b 100644 --- a/apps/basic/buf.asm +++ b/apps/basic/buf.asm @@ -22,6 +22,7 @@ bufInit: ld (BUF_LFREE), hl ld hl, BUF_POOL ld (BUF_PFREE), hl + cp a ; ensure Z ret ; Add line at (HL) with line number DE to the buffer. The string at (HL) should diff --git a/apps/basic/fs.asm b/apps/basic/fs.asm index b9fed42..d236ebf 100644 --- a/apps/basic/fs.asm +++ b/apps/basic/fs.asm @@ -1,4 +1,8 @@ ; FS-related basic commands +; *** Variables *** +; Handle of the target file +.equ BFS_FILE_HDL BFS_RAMSTART +.equ BFS_RAMEND @+FS_HANDLE_SIZE basFLS: ld iy, .iter @@ -9,7 +13,57 @@ basFLS: call printstr jp printcrlf + +basLDBAS: + call fsFindFN + ret nz + call bufInit + ld ix, BFS_FILE_HDL + call fsOpen + ld hl, 0 + ld de, SCRATCHPAD +.loop: + ld ix, BFS_FILE_HDL + call fsGetB + jr nz, .loopend + inc hl + or a ; null? hum, weird. same as LF + jr z, .lineend + cp LF + jr z, .lineend + ld (de), a + inc de + jr .loop +.lineend: + ; We've just finished reading a line, writing each char in the pad. + ; Null terminate it. + xor a + ld (de), a + ; Ok, line ready + push hl ; --> lvl 1. current file position + ld hl, SCRATCHPAD + call parseDecimal + jr nz, .notANumber + push ix \ pop de + call toSep + call rdSep + call bufAdd + pop hl ; <-- lvl 1 + ret nz + ld de, SCRATCHPAD + jr .loop +.notANumber: + pop hl ; <-- lvl 1 + ld de, SCRATCHPAD + jr .loop +.loopend: + cp a + ret + + basFSCmds: .dw basFLS .db "fls", 0, 0, 0 + .dw basLDBAS + .db "ldbas", 0 .db 0xff, 0xff, 0xff ; end of table diff --git a/apps/basic/main.asm b/apps/basic/main.asm index 3abb284..d331ff5 100644 --- a/apps/basic/main.asm +++ b/apps/basic/main.asm @@ -139,7 +139,7 @@ basBYE: basLIST: call bufFirst - ret nz + jr nz, .end .loop: ld e, (ix) ld d, (ix+1) @@ -153,6 +153,7 @@ basLIST: call printcrlf call bufNext jr z, .loop +.end: cp a ; ensure Z ret @@ -383,6 +384,8 @@ basCmds1: .db "list", 0, 0 .dw basRUN .db "run", 0, 0, 0 + .dw bufInit + .db "clear", 0 ; statements basCmds2: .dw basPRINT diff --git a/tools/emul/bshell/glue.asm b/tools/emul/bshell/glue.asm index 939d4e3..b1e217a 100644 --- a/tools/emul/bshell/glue.asm +++ b/tools/emul/bshell/glue.asm @@ -84,11 +84,10 @@ .inc "basic/var.asm" .equ BUF_RAMSTART VAR_RAMEND .inc "basic/buf.asm" -.equ BAS_RAMSTART BUF_RAMEND -.inc "basic/main.asm" - -; Extra cmds +.equ BFS_RAMSTART BUF_RAMEND .inc "basic/fs.asm" +.equ BAS_RAMSTART BFS_RAMEND +.inc "basic/main.asm" init: di diff --git a/tools/emul/cfsin/count.bas b/tools/emul/cfsin/count.bas new file mode 100644 index 0000000..30896b0 --- /dev/null +++ b/tools/emul/cfsin/count.bas @@ -0,0 +1,5 @@ +10 print "Count to 10" +20 a=0 +30 a=a+1 +40 print a +50 if a<10 goto 30