From b29073b01ddaf3c116c896ef60015822e39eb13e Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Mon, 25 Nov 2019 21:41:37 -0500 Subject: [PATCH] basic: add fopen command --- apps/basic/README.md | 105 ++++++++++++++++++++++++------------------- apps/basic/fs.asm | 18 ++++++++ 2 files changed, 78 insertions(+), 45 deletions(-) diff --git a/apps/basic/README.md b/apps/basic/README.md index 2abfd6f..23963fd 100644 --- a/apps/basic/README.md +++ b/apps/basic/README.md @@ -108,50 +108,53 @@ If `goto` was previously called in direct mode, we start from that line instead. **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` +**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` 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 -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). +**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, -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". +**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 `A`. -The prompted value is evaluated as an expression and then stored. The command -takes an optional string literal parameter. If present, that string will be -printed before asking for input. Unlike a `print` call, there is no CR/LF after -that print. +**input []**: Prompts the user for a numerical value and puts that +value in `A`. The prompted value is evaluated as an expression and then stored. +The command takes an optional string literal parameter. If present, that string +will be printed before asking for input. Unlike a `print` call, there is no +CR/LF after that print. -**peek/deek**: Put the value at specified memory address into `A`. peek is for +**peek/deek **: Put the value at specified memory address into `A`. peek is for a single byte, deek is for a word (little endian). For example, `peek 42` puts the byte value contained in memory address 0x002a into variable `A`. `deek 42` does the same as peek, but also puts the value of 0x002b into `A`'s MSB. -**poke/doke**: Put the value of specified expression into specified memory -address. For example, `poke 42 0x102+0x40` puts `0x42` in memory address -0x2a (MSB is ignored) and `doke 42 0x102+0x40` does the same as poke, but also -puts `0x01` in memory address 0x2b. +**poke/doke **: Put the value of specified expression into +specified memory address. For example, `poke 42 0x102+0x40` puts `0x42` in +memory address 0x2a (MSB is ignored) and `doke 42 0x102+0x40` does the same +as poke, but also puts `0x01` in memory address 0x2b. -**in**: Same thing as `peek`, but for a I/O port. `in 42` generates an input -I/O on port 42 and stores the byte result in `A`. +**in **: Same thing as `peek`, but for a I/O port. `in 42` generates an +input I/O on port 42 and stores the byte result in `A`. -**out**: Same thing as `poke`, but for a I/O port. `out 42 1+2` generates an -output I/O on port 42 with value 3. +**out **: Same thing as `poke`, but for a I/O port. `out 42 1+2` +generates an output I/O on port 42 with value 3. -**sleep**: Sleep a number of "units" specified by the supplied expression. A -"unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 microseconds. +**sleep **: Sleep a number of "units" specified by the supplied +expression. A "unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 +microseconds. -**addr**: This very handy returns (in `A`), the address you query for. You can -query for two types of things: commands or special stuff. +**addr **: This very handy returns (in `A`), the address you query for. +You can query for two types of things: commands or special stuff. If you query for a command, type the name of the command as an argument. The address of the associated routine will be returned. @@ -160,12 +163,12 @@ Then, there's the *special stuff*. This is the list of things you can query for: * `$`: the scratchpad. -**usr**: This calls the memory address specified as an expression argument. -Before doing so, it sets the registers according to a specific logic: Variable -`A`'s LSB goes in register `A`, variable `D` goes in register `DE`, `H` in `HL` -`B` in `BC` and `X` in `IX`. `IY` can't be used because it's used for the jump. -Then, after the call, the value of the registers are put back into the -variables following the same logic. +**usr **: This calls the memory address specified as an expression +argument. Before doing so, it sets the registers according to a specific +logic: Variable `A`'s LSB goes in register `A`, variable `D` goes in register +`DE`, `H` in `HL` `B` in `BC` and `X` in `IX`. `IY` can't be used because +it's used for the jump. Then, after the call, the value of the registers are +put back into the variables following the same logic. Let's say, for example, that you want to use the kernel's `printstr` to print the contents of the scratchpad. First, you would call `addr $` to put the @@ -183,14 +186,15 @@ Here's the documentation for them. Block devices commands. Block devices are configured during kernel initialization and are referred to by numbers. -**bsel**: Select the active block device. The active block device is the target -of all commands below. You select it by specifying its number. For example, -`bsel 0` selects the first configured device. `bsel 1` selects the second. +**bsel **: Select the active block device. The active block device is +the target of all commands below. You select it by specifying its number. For +example, `bsel 0` selects the first configured device. `bsel 1` selects the +second. A freshly selected blkdev begins with its "pointer" at 0. -**seek**: Moves the blkdev "pointer" to the specified offset. The first -argument is the offset's least significant half (blkdev supports 32-bit +**seek **: Moves the blkdev "pointer" to the specified offset. The +first argument is the offset's least significant half (blkdev supports 32-bit addressing). Is is interpreted as an unsigned integer. The second argument is optional and is the most significant half of the address. @@ -199,9 +203,9 @@ It defaults to 0. **getb**: Read a byte in active blkdev at current pointer, then advance the pointer by one. Read byte goes in `A`. -**putb**: Writes a byte in active blkdev at current pointer, then advance the -pointer by one. The value of the byte is determined by the expression supplied -as an argument. Example: `putb 42`. +**putb **: Writes a byte in active blkdev at current pointer, then +advance the pointer by one. The value of the byte is determined by the +expression supplied as an argument. Example: `putb 42`. ### fs @@ -209,6 +213,17 @@ as an argument. Example: `putb 42`. **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). +**fopen **: Open file "fname" in handle "fhandle". File handles +are specified in kernel glue code and are in limited number. The kernel glue +code also maps to blkids through the glue code. So to know what you're doing +here, you have to look at your glue code. + +In the emulated code, there are two file handles. Handle 0 maps to blkid 1 and +handle 1 maps to blkid 2. + +Once a file is opened, you can use the mapped blkid as you would with any block +device (bseek, getb, putb). + +**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/fs.asm b/apps/basic/fs.asm index d236ebf..bff2c3d 100644 --- a/apps/basic/fs.asm +++ b/apps/basic/fs.asm @@ -61,9 +61,27 @@ basLDBAS: ret +basFOPEN: + call rdExpr ; file handle index + ret nz + push ix \ pop de + ld a, e + call fsHandle + ; DE now points to file handle + call rdSep + ; HL now holds the string we look for + call fsFindFN + ret nz ; not found + ; Found! + ; FS_PTR points to the file we want to open + push de \ pop ix ; IX now points to the file handle. + jp fsOpen + basFSCmds: .dw basFLS .db "fls", 0, 0, 0 .dw basLDBAS .db "ldbas", 0 + .dw basFOPEN + .db "fopen", 0 .db 0xff, 0xff, 0xff ; end of table