recipes/trs80: move RECV program to blkfs

This commit is contained in:
Virgil Dupras 2020-05-05 22:15:56 -04:00
parent 60b4bbf28a
commit b89fa2981f
9 changed files with 62 additions and 293 deletions

View File

@ -8,7 +8,7 @@ MASTER INDEX
280 Z80 boot code 350 ACIA driver
370 SD Card driver 390 Inner core
420 Core words 480 AT28 Driver
490 TRS80 Drivers
490 TRS-80 Recipe

11
blk/490
View File

@ -1,8 +1,11 @@
TRS-80 Drivers
TRS-80 Recipe
Drivers for the TRS-80 keyboard, video and floppy. At the
moment, they are thin layer over the drivers provided by
TRSDOS' SVC.
Support code for the TRS-80 recipe. Contains drivers for the
keyboard, video and floppy. At the moment, they are thin layer
over the drivers provided by TRSDOS' SVC.
Load the Z80 words with "492 LOAD" and the high level part
with "498 LOAD".
There is also the RECV program at B502 and the XCOMP unit at
B504

16
blk/502 Normal file
View File

@ -0,0 +1,16 @@
( We process the 0x20 exception by pre-putting a mask in the
(HL) we're going to write to. If it wasn't a 0x20, we put a
0xff mask. If it was a 0x20, we put a 0x7f mask. )
: @GET,
A 0x03 LDrn, ( @GET )
DE COM_DRV_ADDR LDddnn,
0x28 RSTn, JRNZ, L2 FWR ( maybeerror )
A ORr,
CZ RETcc, ( Sending a straight NULL ends the comm. ) ;
: @PUT, ( @PUT that char back )
C A LDrr,
A 0x04 LDrn, ( @PUT )
0x28 RSTn, JRNZ, L3 FWR ( error )
A C LDrr, ;
H@ ORG !
HL DEST_ADDR LDddnn, ( cont. )

15
blk/503 Normal file
View File

@ -0,0 +1,15 @@
BEGIN,
A 0xff LDrn, (HL) A LDrr, ( default mask )
L1 BSET ( loop2 ) @GET, @PUT,
0x20 CPn, JRZ, L4 FWR ( escapechar )
( not an escape char, just apply the mask and write )
(HL) ANDr, (HL) A LDrr,
HL INCss,
JR, AGAIN,
L4 FSET ( escapechar, adjust by setting (hl) to 0x7f )
7 (HL) RESbr, JR, L1 BWR ( loop2 )
L2 FSET ( maybeerror, was it an error? )
A ORr, JRZ, L1 BWR ( loop2, not an error )
L3 FSET ( error )
C A LDrr, ( error code from @GET/@PUT )
A 0x1a LDrn, ( @ERROR ) 0x28 RSTn, RET,

View File

@ -103,11 +103,26 @@ As stated in the overview, we need a program on the TRS-80 that:
3. Adjusts `ttysafe` escapes
4. Stores received bytes in memory
That program has already been written, it's in `recv.asm` in this folder. You
can get the binary with `zasm < recv.asm | xxd`.
You're in luck: that program has already been written. It's in B502 and B503.
You can compile it with:
It's designed to run from offset `0x5000` and write received data in `0x3000`
and onwards.
212 LOAD ( z80 assembler )
0x0238 CONSTANT COM_DRV_ADDR
0x3000 CONSTANT DEST_ADDR
502 LOAD
503 LOAD
Then, you can use `DUMP` to visualize the data you'll need to punch in:
H@ ORG @ - ORG @ DUMP
It can run from any offset (all jumps in it are relative), but writes to
`DEST_ADDR`. Make sure you don't place it in a way to be overwritten by its
received data.
Wondering what is that `COM_DRV_ADDR` constant? That's the DCB handle of your
`*cl` device. You will need to get that address before you continue. Go read
the following section and come back here.
How will you punch that in? The `debug` program! This very useful piece of
software is supplied in TRSDOS. To invoke it, first run `debug (on)` and then
@ -123,17 +138,12 @@ begin punching in with `h5000<space>`. This will bring up a visual indicator of
the address being edited. Punch in the stuff with a space in between each byte
and end the edit session with `x`.
But wait, it's not that easy! You see those `0xffff` addresses? They're
placeholders. You need to replace those values with your DCB handle for `*cl`.
See below.
## Getting your DCB address
In the previous step, you need to replace the `0xffff` placeholders in
`recv.asm` with your "DCB" address for `*cl`. That address is your driver
"handle". To get it, first get the address where the driver is loaded in
memory. You can get this by running `device (b=y)`. That address you see next
to `*cl`? that's it. But that's not our DCB.
In the previous step, you need to set `COM_DRV_ADDR` to your "DCB" address for
`*cl`. That address is your driver "handle". To get it, first get the address
where the driver is loaded in memory. You can get this by running `device
(b=y)`. That address you see next to `*cl`? that's it. But that's not our DCB.
To get your DBC, go explore that memory area. Right after the part where there's
the `*cl` string, there's the DCB address (little endian). On my setup, the

View File

@ -1,11 +0,0 @@
.inc "user.h"
ld hl, sAwesome
call printstr
xor a ; success
ret
sAwesome:
.db "Assembled from a TRS-80", 0x0d, 0

View File

@ -1,200 +0,0 @@
; RAMSTART is a label at the end of the file
.equ RAMEND 0xcfff
; Address of the *CL driver. Same as in recv.asm
.equ COM_DRV_ADDR 0x0238
; in sync with user.h. Last BAS_RAMEND: 0x600b
.equ USER_CODE 0x6100
; Free memory in TRSDOS starts at 0x3000
.org 0x3000
jp init
; *** Jump Table ***
jp strncmp
jp upcase
jp findchar
jp printstr
jp printcrlf
jp blkSet
jp blkSel
jp _blkGetB
jp _blkPutB
jp _blkSeek
jp _blkTell
jp fsFindFN
jp fsOpen
jp fsGetB
jp fsPutB
jp fsSetSize
jp stdioPutC
jp stdioReadLine
.inc "err.h"
.inc "blkdev.h"
.inc "fs.h"
.inc "ascii.h"
.inc "core.asm"
.inc "str.asm"
.inc "trs80/kbd.asm"
.inc "trs80/vid.asm"
.equ FLOPPY_RAMSTART RAMSTART
.inc "trs80/floppy.asm"
.equ GRID_RAMSTART FLOPPY_RAMEND
.equ GRID_ROWS TRS80_ROWS
.equ GRID_COLS TRS80_COLS
.equ GRID_SETCELL trs80SetCell
.equ GRID_GETC trs80GetC
.equ gridPushScr fastPushScr
.inc "grid.asm"
.equ BLOCKDEV_RAMSTART GRID_RAMEND
.equ BLOCKDEV_COUNT 3
.inc "blockdev.asm"
; List of devices
.dw floppyGetB, floppyPutB
.dw blk1GetB, blk1PutB
.dw blk2GetB, blk2PutB
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC gridGetC
.equ STDIO_PUTC gridPutC
.equ STDIO_SETCUR gridSetCurH
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
.equ FS_HANDLE_COUNT 2
.inc "fs.asm"
; *** BASIC ***
; RAM space used in different routines for short term processing.
.equ SCRATCHPAD_SIZE STDIO_BUFSIZE
.equ SCRATCHPAD FS_RAMEND
.inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm"
.inc "lib/fmt.asm"
.equ EXPR_PARSE parseLiteralOrVar
.inc "lib/expr.asm"
.inc "basic/util.asm"
.inc "basic/parse.asm"
.inc "basic/tok.asm"
.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
.inc "basic/var.asm"
.equ BUF_RAMSTART VAR_RAMEND
.inc "basic/buf.asm"
.equ BFS_RAMSTART BUF_RAMEND
.inc "basic/fs.asm"
.inc "basic/blk.asm"
.inc "basic/floppy.asm"
.equ BAS_RAMSTART BFS_RAMEND
.inc "basic/main.asm"
.out BAS_RAMEND
init:
ld sp, RAMEND
call gridInit
call floppyInit
call fsInit
call basInit
ld hl, basFindCmdExtra
ld (BAS_FINDHOOK), hl
xor a
ld de, BLOCKDEV_SEL
call blkSel
jp basStart
; Receive a byte from *cl and put it in A.
; Returns A > 0xff when receiving the last byte
recvCmd:
xor a
ld (VAR_TBL+1), a ; pre-set MSB
; put a 0xff mask in B, which will become 0x7f if we receive a 0x20
ld b, 0xff
.inner:
ld a, 0x03 ; @GET
ld de, COM_DRV_ADDR
rst 0x28
jr nz, .maybeerror
or a
jr z, .eof ; Sending a straight NULL ends the comm.
; @PUT that char back
ld c, a
ld a, 0x04 ; @PUT
ld de, COM_DRV_ADDR
rst 0x28
ret nz ; error
ld a, c
cp 0x20
jr z, .escapechar
; not an escape char, good
and b ; apply mask
ld (VAR_TBL), a
xor a ; ensure Z
ret
.maybeerror:
; was it an error?
or a
jr z, .inner ; not an error, just loop
ret ; error
.escapechar:
ld b, 0x7f
jr .inner
.eof:
dec a ; A = 0xff
ld (VAR_TBL+1), a
xor a ; ensure Z
ret
basFindCmdExtra:
ld hl, basFloppyCmds
call basFindCmd
ret z
ld hl, basBLKCmds
call basFindCmd
ret z
ld hl, basFSCmds
call basFindCmd
ret z
ld hl, .cmds
call basFindCmd
ret z
jp basPgmHook
.cmds:
.db "recv", 0
.dw recvCmd
.db 0xff ; end of table
fastPushScr:
push hl
ld hl, GRID_BUF
call trs80PushScr
pop hl
ret
; *** blkdev 1: file handle 0 ***
blk1GetB:
ld ix, FS_HANDLES
jp fsGetB
blk1PutB:
ld ix, FS_HANDLES
jp fsPutB
; *** blkdev 2: file handle 1 ***
blk2GetB:
ld ix, FS_HANDLES+FS_HANDLE_SIZE
jp fsGetB
blk2PutB:
ld ix, FS_HANDLES+FS_HANDLE_SIZE
jp fsPutB
RAMSTART:

View File

@ -1,45 +0,0 @@
.equ COM_DRV_ADDR 0x0238 ; replace with *CL's DCB addr
.equ DEST_ADDR 0x3000 ; memory address where to put contents.
; We process the 0x20 exception by pre-putting a mask in the (HL) we're going
; to write to. If it wasn't a 0x20, we put a 0xff mask. If it was a 0x20, we
; put a 0x7f mask.
ld hl, DEST_ADDR
loop:
ld a, 0xff
ld (hl), a ; default mask
loop2:
ld a, 0x03 ; @GET
ld de, COM_DRV_ADDR
rst 0x28
jr nz, maybeerror
or a
ret z ; Sending a straight NULL ends the comm.
; @PUT that char back
ld c, a
ld a, 0x04 ; @PUT
rst 0x28
jr nz, error
ld a, c
cp 0x20
jr z, escapechar
; not an escape char, just apply the mask and write
and (hl)
ld (hl), a
inc hl
jr loop
escapechar:
; adjust by setting (hl) to 0x7f
res 7, (hl)
jr loop2
maybeerror:
; was it an error?
or a
jr z, loop2 ; not an error, just loop
; error
error:
ld c, a ; Error code from @GET/@PUT
ld a, 0x1a ; @ERROR
rst 0x28
ret

View File

@ -1,19 +0,0 @@
.org 0x6100
.equ strncmp 0x3003
.equ upcase @+3
.equ findchar @+3
.equ printstr @+3
.equ printcrlf @+3
.equ blkSet @+3
.equ blkSel @+3
.equ _blkGetB @+3
.equ _blkPutB @+3
.equ _blkSeek @+3
.equ _blkTell @+3
.equ fsFindFN @+3
.equ fsOpen @+3
.equ fsGetB @+3
.equ fsPutB @+3
.equ fsSetSize @+3
.equ stdioPutC @+3
.equ stdioReadLine @+3