forked from MirrorRepos/RomWBW
Browse Source
New **experimental** adaptation of XModem called XMX.COM: - Fixes occasional "stall" at startup (I think) - Reduces HBIOS overhead substantially - Automatically uses the console port no matter what COM port the console is onpatch
16 changed files with 666 additions and 31 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,570 @@ |
|||
;======================================================================= |
|||
; |
|||
; XMHB.Z80 - XMODEM12 PATCH FILE FOR ROMWBW HBIOS |
|||
; |
|||
; Wayne Warthen - wwarthen@gmail.com |
|||
; |
|||
; 2020-05-23 WBW Rewrite for HBIOS FastPath(tm) |
|||
; |
|||
;======================================================================= |
|||
; |
|||
ASEG |
|||
; |
|||
BASE EQU 100H ; Start of CP/M normal program area |
|||
; |
|||
BDOS EQU 0005H ; BDOS function dispatch vector |
|||
; |
|||
;======================================================================= |
|||
; |
|||
; Jump table: The jump table must be in exactly the same sequence as the |
|||
; one in XMODEM. Note the ORG of 103H - This jump table has no jump to |
|||
; 'BEGIN'. |
|||
; |
|||
ORG BASE + 3 ; start after 'JMP BEGIN' |
|||
; |
|||
JP CONOUT ; must be 00000h if not used, see below |
|||
JP MINIT ; initialization routine (if needed) |
|||
JP UNINIT ; undo whatever 'MINIT' did (or return) |
|||
JPTBL: |
|||
JP SENDR ; send character (via pop psw) |
|||
JP CAROK ; test for carrier |
|||
JP MDIN ; receive data byte |
|||
JP GETCHR ; get character from modem |
|||
JP RCVRDY ; check receive ready |
|||
JP SNDRDY ; check send ready |
|||
JP SPEED ; get speed value for file transfer time |
|||
JP EXTRA1 ; extra for custom routine |
|||
JP EXTRA2 ; extra for custom routine |
|||
JP EXTRA3 ; extra for custom routine |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Output character to console |
|||
; |
|||
CONOUT EQU 0 ; not used |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Initialize modem |
|||
; |
|||
; This procedure has been usurped to dynamically detect the type |
|||
; of system we are running on and install the *real* jump table |
|||
; entries as appropriate. |
|||
; |
|||
MINIT: |
|||
; Announce |
|||
LD DE,TAG ; Tagline |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Identify BIOS (RomWBW HBIOS or UNA UBIOS) |
|||
CALL IDBIO ; 1=HBIOS, 2=UBIOS |
|||
LD (BIOID),A ; Save it |
|||
DEC A ; Test for HBIOS |
|||
JR Z,HINIT ; Do HBIOS setup |
|||
DEC A ; Test for UBIOS |
|||
JR Z,UINIT ; Do UBIOS setup |
|||
; |
|||
; Neither UNA nor RomWBW |
|||
LD DE,ERR_BIO ; BIOS error message |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
JP 0 ; Bail out! |
|||
; |
|||
MINIT_RET: |
|||
PUSH HL ; Save HL (JP table adr) |
|||
|
|||
; Display port notification string |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Declare experimental |
|||
LD DE,EXP_LBL ; Declare experimental |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Newline |
|||
LD C,9 ; BDOS string display function |
|||
LD DE,CRLF ; Newline |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Copy real vectors into active jump table |
|||
POP HL ; Recover HL |
|||
LD DE,JPTBL ; Real jump table is destination |
|||
LD BC,7 * 3 ; Copy 7 3-byte entries |
|||
LDIR ; Do the copy |
|||
; |
|||
; Return with CPU speed in A |
|||
LD A,(CPUSPD) ; A := CPU speed in MHz |
|||
LD HL,(RCVSCL) ; HL := receive scalar |
|||
RET ; and return |
|||
; |
|||
HINIT: |
|||
; Display RomWBW notification string |
|||
LD DE,HBTAG ; BIOS notification string |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Get CPU speed from RomWBW HBIOS and save it |
|||
LD B,0F8H ; HBIOS SYSGET function 0xF8 |
|||
LD C,0F0H ; CPUINFO subfunction 0xF0 |
|||
RST 08 ; Do it, L := CPU speed in MHz |
|||
LD A,L ; Move it to A |
|||
LD (CPUSPD),A ; Save it |
|||
; |
|||
JP H_INIT ; Otherwise, use HBIOS I/O |
|||
; |
|||
UINIT: |
|||
; Display UNA notification string |
|||
LD DE,UBTAG ; BIOS notification string |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
; |
|||
; Get CPU speed from UNA and save it |
|||
LD C,0F8H ; UNA BIOS Get PHI function |
|||
RST 08 ; Returns speed in Hz in DE:HL |
|||
LD B,4 ; Divide MHz in DE:HL by 100000H |
|||
UINIT1: |
|||
SRL D ; ... to get approx CPU speed in |
|||
RR E ; ...MHz. Throw away HL, and |
|||
DJNZ UINIT1 ; ...right shift DE by 4. |
|||
INC E ; Fix up for value truncation |
|||
LD A,E ; Put in A |
|||
LD (CPUSPD),A ; Save it |
|||
; |
|||
JP U_INIT ; UNA BIOS init |
|||
; |
|||
HWERR: |
|||
; Failed to identify target comm hardware |
|||
LD DE,ERR_HW ; Hardware error message |
|||
LD C,9 ; BDOS string display function |
|||
CALL BDOS ; Do it |
|||
JP 0 ; Bail out! |
|||
; |
|||
; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 |
|||
; |
|||
IDBIO: |
|||
; |
|||
; Check for UNA (UBIOS) |
|||
LD A,(0FFFDH) ; fixed location of UNA API vector |
|||
CP 0C3H ; jp instruction? |
|||
JR NZ,IDBIO1 ; if not, not UNA |
|||
LD HL,(0FFFEH) ; get jp address |
|||
LD A,(HL) ; get byte at target address |
|||
CP 0FDH ; first byte of UNA push ix instruction |
|||
JR NZ,IDBIO1 ; if not, not UNA |
|||
INC HL ; point to next byte |
|||
LD A,(HL) ; get next byte |
|||
CP 0E5H ; second byte of UNA push ix instruction |
|||
JR NZ,IDBIO1 ; if not, not UNA, check others |
|||
LD A,2 ; UNA BIOS id = 2 |
|||
RET ; and done |
|||
; |
|||
IDBIO1: |
|||
; Check for RomWBW (HBIOS) |
|||
LD HL,(0FFFEH) ; HL := HBIOS ident location |
|||
LD A,'W' ; First byte of ident |
|||
CP (HL) ; Compare |
|||
JR NZ,IDBIO2 ; Not HBIOS |
|||
INC HL ; Next byte of ident |
|||
LD A,~'W' ; Second byte of ident |
|||
CP (HL) ; Compare |
|||
JR NZ,IDBIO2 ; Not HBIOS |
|||
LD A,1 ; HBIOS BIOS id = 1 |
|||
RET ; and done |
|||
; |
|||
IDBIO2: |
|||
; No idea what this is |
|||
XOR A ; Setup return value of 0 |
|||
RET ; and done |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Uninitialize modem |
|||
; |
|||
UNINIT: |
|||
LD A,(BIOID) |
|||
CP 1 ; Is HBIOS? |
|||
JR Z,H_UNINIT ; Handle HBIOS |
|||
CP 2 ; Is UBIOS? |
|||
JR Z,U_UNINIT ; Handle UBIOS |
|||
RET ; Just return |
|||
; |
|||
H_UNINIT: |
|||
; HBIOS: Reset character device 0 |
|||
LD B,04H ; HBIOS CIOINIT function 0x04 |
|||
LD C,80H ; Unit = 80 (console) |
|||
LD DE,-1 ; Reset w/ current settings |
|||
RST 08 ; Do it |
|||
RET ; not initialized, so no 'UN-INITIALIZE' |
|||
; |
|||
U_UNINIT: |
|||
; UBIOS: Reset character device 0 |
|||
LD C,10H ; UNA INIT function 0x10 |
|||
LD B,0 ; Unit = 0 |
|||
LD DE,-1 ; Reset w/ current settings |
|||
RST 08 ; Do it |
|||
RET ; not initialized, so no 'UN-INITIALIZE' |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; The following are all dummy routines that are unused because MINIT |
|||
; dynamically installs the real jump table. |
|||
; |
|||
SENDR: |
|||
CAROK: |
|||
MDIN: |
|||
GETCHR: |
|||
RCVRDY: |
|||
SNDRDY: |
|||
SPEED: |
|||
EXTRA1: |
|||
EXTRA2: |
|||
EXTRA3: |
|||
RET |
|||
; |
|||
BIOID DB 0 ; BIOS ID, 1=HBIOS, 2=UBIOS |
|||
CPUSPD DB 10 ; CPU speed in MHz |
|||
RCVSCL DW 6600 ; RECV loop timeout scalar |
|||
; |
|||
TAG DB "RomWBW, 23-May-2020$" |
|||
; |
|||
COM_LBL DB ", HBIOS FastPath on COM?:$" |
|||
EXP_LBL DB 13, 10, 13, 10, "*** Experimental ***$" |
|||
; |
|||
UBTAG DB " [UNA]$" |
|||
HBTAG DB " [WBW]$" |
|||
; |
|||
CRLF DB 13, 10, "$" |
|||
; |
|||
ERR_BIO DB 13, 10, 13, 10, "++ Unknown BIOS ++", 13, 10, "$" |
|||
ERR_HW DB 13, 10, 13, 10, "++ Unknown Hardware ++", 13, 10, "$" |
|||
; |
|||
;======================================================================= |
|||
;======================================================================= |
|||
; |
|||
; RomWBW HBIOS Interface |
|||
; |
|||
;======================================================================= |
|||
;======================================================================= |
|||
; |
|||
; Following jump table is dynamically patched over initial jump |
|||
; table at program startup. See MINIT above. Note that only a |
|||
; subset of the jump table is overlaid (SENDR to SPEED). |
|||
; |
|||
H_JPTBL: |
|||
JP H_SENDR ; send character (via pop psw) |
|||
JP H_CAROK ; test for carrier |
|||
JP H_MDIN ; receive data byte |
|||
JP H_GETCHR ; get character from modem |
|||
JP H_RCVRDY ; check receive ready |
|||
JP H_SNDRDY ; check send ready |
|||
JP H_SPEED ; get speed value for file transfer time |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; HBIOS initialization |
|||
; |
|||
H_INIT: |
|||
LD HL,2150 ; Smaller receive loop timeout scalar |
|||
LD (RCVSCL),HL ; ... to compensate for BIOS overhead |
|||
; |
|||
; Get HBIOS bank id |
|||
LD BC,0F8F2H ; HBIOS SYSGET, Bank Info |
|||
RST 08 ; do it |
|||
LD A,D ; BIOS bank id to A |
|||
LD (H_BNKID),A ; save it |
|||
; |
|||
; Patch SENDR w/ FastPath addresses |
|||
LD BC,0F801H ; Get CIO func/data adr |
|||
LD D,01H ; Func=CIO OUT |
|||
LD A,(H_UNIT) ; get desired char unit |
|||
LD E,A ; and put in E |
|||
RST 08 |
|||
; handle error? |
|||
LD (H_SCDAT),DE ; Plug in data adr |
|||
LD (H_SCFN),HL ; Plug in func adr |
|||
; |
|||
; Patch GETCHR/MDIN w/ FastPath addresses |
|||
LD BC,0F801H ; Get CIO func/data adr |
|||
LD D,00H ; Func=CIO IN |
|||
LD A,(H_UNIT) ; get desired char unit |
|||
LD E,A ; and put in E |
|||
RST 08 |
|||
; handle error? |
|||
LD (H_GCDAT),DE ; Plug in data adr |
|||
LD (H_GCFN),HL ; Plug in func adr |
|||
; |
|||
; Patch RCVRDY w/ FastPath addresses |
|||
LD BC,0F801H ; Get CIO func/data adr |
|||
LD D,02H ; Func=CIO IST |
|||
LD A,(H_UNIT) ; get desired char unit |
|||
LD E,A ; and put in E |
|||
RST 08 |
|||
; handle error? |
|||
LD (H_RRDAT),DE ; Plug in data adr |
|||
LD (H_RRFN),HL ; Plug in func adr |
|||
; |
|||
; Patch SNDRDY w/ FastPath addresses |
|||
LD BC,0F801H ; Get CIO func/data adr |
|||
LD D,03H ; Func=CIO OST |
|||
LD A,(H_UNIT) ; get desired char unit |
|||
LD E,A ; and put in E |
|||
RST 08 |
|||
; handle error? |
|||
LD (H_SRDAT),DE ; Plug in data adr |
|||
LD (H_SRFN),HL ; Plug in func adr |
|||
; |
|||
LD HL,H_JPTBL |
|||
LD DE,COM_LBL |
|||
JP MINIT_RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Send character on top of stack |
|||
; |
|||
H_SENDR: |
|||
POP AF ; get character to send from stack |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD E,A ; character to E |
|||
LD IY,0000H |
|||
H_SCDAT EQU $-2 |
|||
LD A,(H_BNKID) ; call into HBIOS bank |
|||
LD HL,0000H |
|||
H_SCFN EQU $-2 |
|||
CALL 0FFF9H ; HBIOS bank call |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test and report carrier status, Z set if carrier present |
|||
; |
|||
H_CAROK: |
|||
XOR A ; not used, always indicate present |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Get a character (assume character ready has already been tested) |
|||
; |
|||
; GETCHR must NOT block. |
|||
; |
|||
H_GETCHR: |
|||
CALL H_RCVRDY |
|||
RET NZ |
|||
|
|||
H_MDIN: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD IY,0000H |
|||
H_GCDAT EQU $-2 |
|||
LD A,(H_BNKID) ; call into HBIOS bank |
|||
LD HL,0000H |
|||
H_GCFN EQU $-2 |
|||
CALL 0FFF9H ; HBIOS bank call |
|||
LD A,E ; byte received to A |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test for character ready to receive, Z = ready |
|||
; Error code returned in A register |
|||
; *** Error code does not seem to be used *** |
|||
; |
|||
H_RCVRDY: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD IY,0000H |
|||
H_RRDAT EQU $-2 |
|||
LD A,(H_BNKID) ; call into HBIOS bank |
|||
LD HL,0000H |
|||
H_RRFN EQU $-2 |
|||
CALL 0FFF9H ; HBIOS bank call |
|||
SUB 1 ; CF set IFF zero |
|||
RL A ; CF to bit 0 of A |
|||
AND 01H ; set Z flag as needed |
|||
LD A,0 ; report no line errors |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test for ready to send a character, Z = ready |
|||
; |
|||
H_SNDRDY: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD IY,0000H |
|||
H_SRDAT EQU $-2 |
|||
LD A,(H_BNKID) ; call into HBIOS bank |
|||
LD HL,0000H |
|||
H_SRFN EQU $-2 |
|||
CALL 0FFF9H ; HBIOS bank call |
|||
SUB 1 ; CF set IFF zero |
|||
RL A ; CF to bit 0 of A |
|||
AND 01H ; set Z flag as needed |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Report baud rate (index into SPTBL returned in register A) |
|||
; |
|||
H_SPEED: |
|||
LD A,8 ; arbitrarily return 9600 baud |
|||
RET |
|||
; |
|||
; |
|||
; |
|||
H_BNKID DB 0 ; HBIOS bank id |
|||
H_UNIT DB 80H ; HBIOS unit id |
|||
; |
|||
; |
|||
;======================================================================= |
|||
;======================================================================= |
|||
; |
|||
; UNA UBIOS Interface |
|||
; |
|||
;======================================================================= |
|||
;======================================================================= |
|||
; |
|||
; Following jump table is dynamically patched over initial jump |
|||
; table at program startup. See MINIT above. Note that only a |
|||
; subset of the jump table is overlaid (SENDR to SPEED). |
|||
; |
|||
U_JPTBL: |
|||
JP U_SENDR ; send character (via pop psw) |
|||
JP U_CAROK ; test for carrier |
|||
JP U_MDIN ; receive data byte |
|||
JP U_GETCHR ; get character from modem |
|||
JP U_RCVRDY ; check receive ready |
|||
JP U_SNDRDY ; check send ready |
|||
JP U_SPEED ; get speed value for file transfer time |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; UBIOS initialization |
|||
; |
|||
U_INIT: |
|||
; |
|||
; TODO: |
|||
; - TEST!!! |
|||
; - ADJUST RCVSCL? |
|||
; |
|||
LD HL,3000 ; Smaller receive loop timeout scalar |
|||
LD (RCVSCL),HL ; ... to compensate for BIOS overhead |
|||
; |
|||
LD HL,U_JPTBL |
|||
LD DE,COM_LBL |
|||
JP MINIT_RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Send character on top of stack |
|||
; |
|||
U_SENDR: |
|||
POP AF ; get character to send from stack |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD BC,0012H ; unit 0, func 12h (write char) |
|||
LD E,A ; character to E |
|||
RST 08 |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test and report carrier status, Z set if carrier present |
|||
; |
|||
U_CAROK: |
|||
XOR A ; not used, always indicate present |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Get a character (assume character ready has already been tested) |
|||
; |
|||
; GETCHR must NOT block. |
|||
; |
|||
U_GETCHR: |
|||
CALL U_RCVRDY |
|||
RET NZ |
|||
|
|||
U_MDIN: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD BC,0011H ; unit 0, func 12h (write char) |
|||
RST 08 |
|||
LD A,E ; byte received to A |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test for character ready to receive, Z = ready |
|||
; Error code returned in A register |
|||
; *** Error code does not seem to be used *** |
|||
; |
|||
U_RCVRDY: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD BC,0013H ; unit 0, func 13h (input stat) |
|||
LD A,E ; # chars waiting to A |
|||
SUB 1 ; CF set IFF zero |
|||
RL A ; CF to bit 0 of A |
|||
AND 01H ; set Z flag as needed |
|||
LD A,0 ; report no line errors |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Test for ready to send a character, Z = ready |
|||
; |
|||
U_SNDRDY: |
|||
PUSH BC |
|||
PUSH DE |
|||
PUSH HL |
|||
LD BC,0014H ; unit 0, func 14h (output stat) |
|||
LD A,E ; # chars space in output buf |
|||
SUB 1 ; CF set IFF zero |
|||
RL A ; CF to bit 0 of A |
|||
AND 01H ; set Z flag as needed |
|||
POP HL |
|||
POP DE |
|||
POP BC |
|||
RET |
|||
; |
|||
;----------------------------------------------------------------------- |
|||
; |
|||
; Report baud rate (index into SPTBL returned in register A) |
|||
; |
|||
U_SPEED: |
|||
LD A,8 ; arbitrarily return 9600 baud |
|||
RET |
|||
; |
|||
END |
|||
Loading…
Reference in new issue