1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 09:38:06 +11:00

Compare commits

..

No commits in common. "fc23a7c4a1d96b8e75e357f955a24065ff2c3783" and "a0daed68129147119d7c574f00ddc00cda31cf56" have entirely different histories.

6 changed files with 48 additions and 156 deletions

View File

@ -108,53 +108,50 @@ If `goto` was previously called in direct mode, we start from that line instead.
**clear**: Direct-only. Clears the current code listing. **clear**: Direct-only. Clears the current code listing.
**print <what> [<what>]**: Prints the result of the specified expression, **print**: Prints the result of the specified expression, then CR/LF. Can be
then CR/LF. Can be given multiple arguments. In that case, all arguments are given multiple arguments. In that case, all arguments are printed separately
printed separately with a space in between. For example, `print 12 13` prints with a space in between. For example, `print 12 13` prints `12 13<cr><lf>`
`12 13<cr><lf>`
Unlike anywhere else, the `print` command can take a string inside a double 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 quote. That string will be printed as-is. For example, `print "foo" 40+2` will
print `foo 42`. print `foo 42`.
**goto <lineno>**: Make the next line to be executed the line number **goto**: Make the next line to be executed the line number specified as an
specified as an argument. Errors out if line doesn't exist. Argument can be argument. Errors out if line doesn't exist. Argument can be an expression. If
an expression. If invoked in direct mode, `run` must be called to actually invoked in direct mode, `run` must be called to actually run the line (followed
run the line (followed by the next, and so on). by the next, and so on).
**if <cond> <cmd>**: If specified condition is true, execute the rest of the **if**: If specified condition is true, execute the rest of the line. Otherwise,
line. Otherwise, do nothing. For example, `if 2>1 print 12` prints `12` and `if do nothing. For example, `if 2>1 print 12` prints `12` and `if 2<1 print 12`
2<1 print 12` does nothing. The argument for this command is a "thruth does nothing. The argument for this command is a "thruth expression".
expression".
**input [<prompt>]**: Prompts the user for a numerical value and puts that **input**: Prompts the user for a numerical value and puts that value in `A`.
value in `A`. The prompted value is evaluated as an expression and then stored. The prompted value is evaluated as an expression and then stored. The command
The command takes an optional string literal parameter. If present, that string takes an optional string literal parameter. If present, that string will be
will be printed before asking for input. Unlike a `print` call, there is no printed before asking for input. Unlike a `print` call, there is no CR/LF after
CR/LF after that print. that print.
**peek/deek <addr>**: 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 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` 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. does the same as peek, but also puts the value of 0x002b into `A`'s MSB.
**poke/doke <addr> <val>**: Put the value of specified expression into **poke/doke**: Put the value of specified expression into specified memory
specified memory address. For example, `poke 42 0x102+0x40` puts `0x42` in address. For example, `poke 42 0x102+0x40` puts `0x42` in memory address
memory address 0x2a (MSB is ignored) and `doke 42 0x102+0x40` does the same 0x2a (MSB is ignored) and `doke 42 0x102+0x40` does the same as poke, but also
as poke, but also puts `0x01` in memory address 0x2b. puts `0x01` in memory address 0x2b.
**in <port>**: Same thing as `peek`, but for a I/O port. `in 42` generates an **in**: Same thing as `peek`, but for a I/O port. `in 42` generates an input
input I/O on port 42 and stores the byte result in `A`. I/O on port 42 and stores the byte result in `A`.
**out <port> <val>**: Same thing as `poke`, but for a I/O port. `out 42 1+2` **out**: Same thing as `poke`, but for a I/O port. `out 42 1+2` generates an
generates an output I/O on port 42 with value 3. output I/O on port 42 with value 3.
**sleep <units>**: Sleep a number of "units" specified by the supplied **sleep**: Sleep a number of "units" specified by the supplied expression. A
expression. A "unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 "unit" depends on the CPU clock speed. At 4MHz, it is roughly 8 microseconds.
microseconds.
**addr <what>**: This very handy returns (in `A`), the address you query for. **addr**: This very handy returns (in `A`), the address you query for. You can
You can query for two types of things: commands or special stuff. 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 If you query for a command, type the name of the command as an argument. The
address of the associated routine will be returned. address of the associated routine will be returned.
@ -163,12 +160,12 @@ Then, there's the *special stuff*. This is the list of things you can query for:
* `$`: the scratchpad. * `$`: the scratchpad.
**usr <addr>**: This calls the memory address specified as an expression **usr**: This calls the memory address specified as an expression argument.
argument. Before doing so, it sets the registers according to a specific Before doing so, it sets the registers according to a specific logic: Variable
logic: Variable `A`'s LSB goes in register `A`, variable `D` goes in register `A`'s LSB goes in register `A`, variable `D` goes in register `DE`, `H` in `HL`
`DE`, `H` in `HL` `B` in `BC` and `X` in `IX`. `IY` can't be used because `B` in `BC` and `X` in `IX`. `IY` can't be used because it's used for the jump.
it's used for the jump. Then, after the call, the value of the registers are Then, after the call, the value of the registers are put back into the
put back into the variables following the same logic. variables following the same logic.
Let's say, for example, that you want to use the kernel's `printstr` to print 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 the contents of the scratchpad. First, you would call `addr $` to put the
@ -186,15 +183,14 @@ Here's the documentation for them.
Block devices commands. Block devices are configured during kernel Block devices commands. Block devices are configured during kernel
initialization and are referred to by numbers. initialization and are referred to by numbers.
**bsel <blkid>**: Select the active block device. The active block device is **bsel**: Select the active block device. The active block device is the target
the target of all commands below. You select it by specifying its number. For of all commands below. You select it by specifying its number. For example,
example, `bsel 0` selects the first configured device. `bsel 1` selects the `bsel 0` selects the first configured device. `bsel 1` selects the second.
second.
A freshly selected blkdev begins with its "pointer" at 0. A freshly selected blkdev begins with its "pointer" at 0.
**seek <lsw> <msw>**: Moves the blkdev "pointer" to the specified offset. The **seek**: Moves the blkdev "pointer" to the specified offset. The first
first argument is the offset's least significant half (blkdev supports 32-bit argument is the offset's least significant half (blkdev supports 32-bit
addressing). Is is interpreted as an unsigned integer. addressing). Is is interpreted as an unsigned integer.
The second argument is optional and is the most significant half of the address. The second argument is optional and is the most significant half of the address.
@ -203,9 +199,9 @@ It defaults to 0.
**getb**: Read a byte in active blkdev at current pointer, then advance the **getb**: Read a byte in active blkdev at current pointer, then advance the
pointer by one. Read byte goes in `A`. pointer by one. Read byte goes in `A`.
**putb <val>**: Writes a byte in active blkdev at current pointer, then **putb**: Writes a byte in active blkdev at current pointer, then advance the
advance the pointer by one. The value of the byte is determined by the pointer by one. The value of the byte is determined by the expression supplied
expression supplied as an argument. Example: `putb 42`. as an argument. Example: `putb 42`.
### fs ### fs
@ -213,35 +209,6 @@ expression supplied as an argument. Example: `putb 42`.
**fls**: prints the list of files contained in the active filesystem. **fls**: prints the list of files contained in the active filesystem.
**fopen <fhandle> <fname>**: Open file "fname" in handle "fhandle". File handles **ldbas**: loads the content of the file specified in the argument (as an
are specified in kernel glue code and are in limited number. The kernel glue unquoted filename) and replace the current code listing with this contents. Any
code also maps to blkids through the glue code. So to know what you're doing line not starting with a number is ignored (not an error).
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).
**fnew <blkcnt> <fname>**: Allocates space of "blkcnt" blocks (each block is
0x100 bytes in size) for a new file names "fname". Maximum blkcnt is 0xff.
**fdel <fname>**: Mark file named "fname" as deleted.
**ldbas <fname>**: 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).
**basPgmHook**: That is not a command, but a routine to hook into
`BAS_FINDHOOK`. If you do, whenever a command name isn't found, the filesystem
is iterated to see if it finds a file with the same name. If it does, it loads
its contents at `USER_CODE` (from `user.h`) and calls that address, with HL
pointing to the the remaining args in the command line.
The user code called this way follows the *usr* convention for output, that is,
it converts all registers at the end of the call and stores them in appropriate
variables. If `A` is nonzero, an error is considered to have occurred.
It doesn't do var-to-register transfers on input, however. Only HL is passed
through (with the contents of the command line).

View File

@ -4,7 +4,6 @@
.equ BFS_FILE_HDL BFS_RAMSTART .equ BFS_FILE_HDL BFS_RAMSTART
.equ BFS_RAMEND @+FS_HANDLE_SIZE .equ BFS_RAMEND @+FS_HANDLE_SIZE
; Lists filenames in currently active FS
basFLS: basFLS:
ld iy, .iter ld iy, .iter
jp fsIter jp fsIter
@ -62,79 +61,9 @@ basLDBAS:
ret 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
; Takes one byte block number to allocate as well we one string arg filename
; and allocates a new file in the current fs.
basFNEW:
call rdExpr ; file block count
ret nz
call rdSep ; HL now points to filename
push ix \ pop de
ld a, e
jp fsAlloc
; Deletes filename with specified name
basFDEL:
call fsFindFN
ret nz
; Found! delete
jp fsDel
basPgmHook:
; Cmd to find is in (DE)
ex de, hl
; (HL) is suitable for a direct fsFindFN call
call fsFindFN
ret nz
; We have a file! Let's load it in memory
ld ix, BFS_FILE_HDL
call fsOpen
ld hl, 0 ; addr that we read in file handle
ld de, USER_CODE ; addr in mem we write to
.loop:
call fsGetB ; we use Z at end of loop
ld (de), a ; Z preserved
inc hl ; Z preserved in 16-bit
inc de ; Z preserved in 16-bit
jr z, .loop
; Ready to jump. Return .call in IX and basCallCmd will take care
; of setting (HL) to the arg string. .call then takes care of wrapping
; the USER_CODE call.
ld ix, .call
cp a ; ensure Z
ret
.call:
ld iy, USER_CODE
call callIY
call basR2Var
or a ; Z set only if A is zero
ret
basFSCmds: basFSCmds:
.dw basFLS .dw basFLS
.db "fls", 0, 0, 0 .db "fls", 0, 0, 0
.dw basLDBAS .dw basLDBAS
.db "ldbas", 0 .db "ldbas", 0
.dw basFOPEN
.db "fopen", 0
.dw basFNEW
.db "fnew", 0, 0
.dw basFDEL
.db "fdel", 0, 0
.db 0xff, 0xff, 0xff ; end of table .db 0xff, 0xff, 0xff ; end of table

View File

@ -415,7 +415,6 @@ basUSR:
; and finally, A ; and finally, A
ld a, (VAR_TBL) ld a, (VAR_TBL)
call callIY call callIY
basR2Var: ; Just send reg to vars. Used in basPgmHook
; Same dance, opposite way ; Same dance, opposite way
ld (VAR_TBL), a ld (VAR_TBL), a
ld (VAR_TBL+46), ix ld (VAR_TBL+46), ix

View File

@ -555,7 +555,7 @@ fsIter:
call nz, callIY call nz, callIY
call fsNext call fsNext
jr z, .loop ; Z set? fsNext was successful jr z, .loop ; Z set? fsNext was successful
cp a ; ensure Z or a ; ensure Z
ret ret
; Delete currently active file ; Delete currently active file

View File

@ -3,7 +3,6 @@
.inc "err.h" .inc "err.h"
.inc "ascii.h" .inc "ascii.h"
.equ RAMSTART 0x4000 .equ RAMSTART 0x4000
.equ USER_CODE 0x4200
.equ STDIO_PORT 0x00 .equ STDIO_PORT 0x00
.equ FS_DATA_PORT 0x01 .equ FS_DATA_PORT 0x01
.equ FS_ADDR_PORT 0x02 .equ FS_ADDR_PORT 0x02
@ -110,9 +109,7 @@ basFindCmdExtra:
call basFindCmd call basFindCmd
ret z ret z
ld hl, basBLKCmds ld hl, basBLKCmds
call basFindCmd jp basFindCmd
ret z
jp basPgmHook
emulGetC: emulGetC:
; Blocks until a char is returned ; Blocks until a char is returned

View File

@ -1,5 +1,5 @@
.equ SHELL_RAMSTART 0x4100 .equ SHELL_RAMSTART 0x4100
.equ USER_CODE 0x4200 ; in sync with glue.asm .equ USER_CODE 0x4200
; *** JUMP TABLE *** ; *** JUMP TABLE ***
.equ strncmp 0x03 .equ strncmp 0x03