From 231239f43fe512e0e8da8261de02744cb881de0f Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Tue, 16 Jan 2018 16:30:37 -0800 Subject: [PATCH] Finalize v2.9.0 Prerelease 0 - New function dispatching logic - Refactored interrupt management --- Doc/ChangeLog.txt | 4 +- ReadMe.txt | 2 +- Source/Apps/Assign.asm | 2 +- Source/Apps/Build.cmd | 1 + Source/Apps/Format.asm | 2 +- Source/Apps/Mode.asm | 2 +- Source/Apps/OSLdr.asm | 4 +- Source/Apps/Startup.asm | 2 +- Source/Apps/Timer.asm | 411 ++++++++++++++++ Source/Build.cmd | 2 +- Source/HBIOS/API.txt | 8 + Source/HBIOS/Config/SBC_simh.asm | 3 + Source/HBIOS/acia.asm | 32 +- Source/HBIOS/ansi.asm | 87 ++-- Source/HBIOS/asci.asm | 90 ++-- Source/HBIOS/cfg_mk4.asm | 3 +- Source/HBIOS/cfg_n8.asm | 3 +- Source/HBIOS/cfg_rc.asm | 3 +- Source/HBIOS/cfg_sbc.asm | 3 +- Source/HBIOS/cfg_zeta.asm | 3 +- Source/HBIOS/cfg_zeta2.asm | 2 - Source/HBIOS/cvdu.asm | 59 +-- Source/HBIOS/hbios.asm | 783 ++++++++++++++++-------------- Source/HBIOS/hbios.inc | 2 + Source/HBIOS/ppp.asm | 51 +- Source/HBIOS/prp.asm | 53 +- Source/HBIOS/romldr.asm | 10 +- Source/HBIOS/sio.asm | 40 +- Source/HBIOS/std.asm | 13 - Source/HBIOS/term.asm | 12 +- Source/HBIOS/tms.asm | 75 +-- Source/HBIOS/tty.asm | 57 ++- Source/HBIOS/uart.asm | 24 +- Source/HBIOS/vdu.asm | 59 +-- Source/HBIOS/vga.asm | 61 +-- Source/Images/hd0/s1/u0/pmarc.com | Bin 0 -> 10368 bytes Source/Images/hd0/s1/u0/pmext.com | Bin 0 -> 12928 bytes 37 files changed, 1177 insertions(+), 791 deletions(-) create mode 100644 Source/Apps/Timer.asm create mode 100644 Source/Images/hd0/s1/u0/pmarc.com create mode 100644 Source/Images/hd0/s1/u0/pmext.com diff --git a/Doc/ChangeLog.txt b/Doc/ChangeLog.txt index 8ece0606..197a75ef 100644 --- a/Doc/ChangeLog.txt +++ b/Doc/ChangeLog.txt @@ -2,8 +2,10 @@ Version 2.9.0 ------------- - WBW: Implemented multi-sector I/O in all disk drivers - WBW: Added support for RC2014 SMB Floppy controller modules (SMC and WDC) -- WBW: New function dispatching for disk drivers +- WBW: New function dispatching for character/disk/video drivers - WBW: Updated FDU app to support RC2014 floppy controllers +- WBW: Added TIMER app to display system timer value +- WBW: Refactored interrupt management code Version 2.8.6 ------------- diff --git a/ReadMe.txt b/ReadMe.txt index e15b86cf..3d935c72 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -7,7 +7,7 @@ *********************************************************************** Wayne Warthen (wwarthen@gmail.com) -Version 2.9.0, 2018-01-08 +Version 2.9.0 (prerelease), 2018-01-16 https://www.retrobrewcomputers.org/ RomWBW is a ROM-based implementation of CP/M-80 2.2 and Z-System for diff --git a/Source/Apps/Assign.asm b/Source/Apps/Assign.asm index dae8fc47..adb53a13 100644 --- a/Source/Apps/Assign.asm +++ b/Source/Apps/Assign.asm @@ -39,7 +39,7 @@ bdos .equ $0005 ; BDOS invocation vector stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp ; rmj .equ 2 ; CBIOS version - major -rmn .equ 8 ; CBIOS version - minor +rmn .equ 9 ; CBIOS version - minor ; ;=============================================================================== ; Code Section diff --git a/Source/Apps/Build.cmd b/Source/Apps/Build.cmd index c308521a..fd2ad1ce 100644 --- a/Source/Apps/Build.cmd +++ b/Source/Apps/Build.cmd @@ -18,6 +18,7 @@ call :asm Talk || goto :eof call :asm OSLdr || goto :eof call :asm Mode || goto :eof call :asm RTC || goto :eof +call :asm Timer || goto :eof zx Z80ASM -SYSGEN/F diff --git a/Source/Apps/Format.asm b/Source/Apps/Format.asm index f7b78e2b..ecb048c4 100644 --- a/Source/Apps/Format.asm +++ b/Source/Apps/Format.asm @@ -31,7 +31,7 @@ bdos .equ $0005 ; BDOS invocation vector ;stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp ; rmj .equ 2 ; CBIOS version - major -rmn .equ 8 ; CBIOS version - minor +rmn .equ 9 ; CBIOS version - minor ; ;=============================================================================== ; Code Section diff --git a/Source/Apps/Mode.asm b/Source/Apps/Mode.asm index c9fa6383..604b0511 100644 --- a/Source/Apps/Mode.asm +++ b/Source/Apps/Mode.asm @@ -48,7 +48,7 @@ bdos .equ $0005 ; BDOS invocation vector ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr ; rmj .equ 2 ; intended CBIOS version - major -rmn .equ 8 ; intended CBIOS version - minor +rmn .equ 9 ; intended CBIOS version - minor ; bf_cioinit .equ $04 ; HBIOS: CIOINIT function bf_cioquery .equ $05 ; HBIOS: CIOQUERY function diff --git a/Source/Apps/OSLdr.asm b/Source/Apps/OSLdr.asm index 98ea8070..4ca2973f 100644 --- a/Source/Apps/OSLdr.asm +++ b/Source/Apps/OSLdr.asm @@ -115,7 +115,7 @@ hbxcpy .equ $FFF6 ; Bank copy function entry address ; relocate ourselves to upper memory ld hl,$0000 ; from startup location ld de,runloc ; to running location - ld bc,$1000 ; assume we are no more that $3000 bytes + ld bc,$0800 ; assume we are no more that 2048 bytes ldir ; copy ourselves jp phase2 ; jump to new location @@ -991,7 +991,7 @@ bufptr .dw 0 ; active pointer into buffer ; ; Messages ; -msgban .db "OSLDR v1.0 for RomWBW, 08-Oct-2014",0 +msgban .db "OSLDR v1.1 for RomWBW, 16-Jan-2018",0 msghb .db " (HBIOS Mode)",0 msgub .db " (UBIOS Mode)",0 msguse .db "Usage: OSLDR [/F] []\r\n" diff --git a/Source/Apps/Startup.asm b/Source/Apps/Startup.asm index 6e283f30..2e902fa6 100644 --- a/Source/Apps/Startup.asm +++ b/Source/Apps/Startup.asm @@ -34,7 +34,7 @@ bdos .equ $0005 ; BDOS invocation vector ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr ; rmj .equ 2 ; intended CBIOS version - major -rmn .equ 8 ; intended CBIOS version - minor +rmn .equ 9 ; intended CBIOS version - minor ; bf_cioinit .equ $04 ; HBIOS: CIOINIT function bf_cioquery .equ $05 ; HBIOS: CIOQUERY function diff --git a/Source/Apps/Timer.asm b/Source/Apps/Timer.asm new file mode 100644 index 00000000..8d925216 --- /dev/null +++ b/Source/Apps/Timer.asm @@ -0,0 +1,411 @@ +;=============================================================================== +; SIMER - Display system timer value +; +;=============================================================================== +; +; Author: Wayne Warthen (wwarthen@gmail.com) +;_______________________________________________________________________________ +; +; Usage: +; TIMER [/C] [/?] +; ex: TIMER (display current timer value) +; TIMER /? (display version and usage) +; TIMER /C (display timer value continuously) +; +; Operation: +; Reads and displays system timer value. +;_______________________________________________________________________________ +; +; Change Log: +; 2018-01-14 [WBW] Initial release +;_______________________________________________________________________________ +; +; ToDo: +;_______________________________________________________________________________ +; +;=============================================================================== +; Definitions +;=============================================================================== +; +stksiz .equ $40 ; Working stack size +; +restart .equ $0000 ; CP/M restart vector +bdos .equ $0005 ; BDOS invocation vector +; +ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr +; +rmj .equ 2 ; intended CBIOS version - major +rmn .equ 9 ; intended CBIOS version - minor +; +bf_sysget .equ $F8 ; HBIOS: SYSGET function +bf_sysgettimer .equ $D0 ; TIMER subfunction +; +;=============================================================================== +; Code Section +;=============================================================================== +; + .org $100 +; + ; setup stack (save old value) + ld (stksav),sp ; save stack + ld sp,stack ; set new stack +; + ; initialization + call init ; initialize + jr nz,exit ; abort if init fails +; + ; process + call process ; do main processing + jr nz,exit ; abort on error +; +exit: ; clean up and return to command processor + call crlf ; formatting + ld sp,(stksav) ; restore stack + ;jp restart ; return to CP/M via restart + ret ; return to CP/M w/o restart +; +; Initialization +; +init: + call crlf ; formatting + ld de,msgban ; point to version message part 1 + call prtstr ; print it +; +initx + ; initialization complete + xor a ; signal success + ret ; return +; +; Process +; +process: + ; look for start of parms + ld hl,$81 ; point to start of parm area (past len byte) + call nonblank ; skip to next non-blank char + jp z,process0 ; no parms, go to display +; + ; check for special option, introduced by a "/" + cp '/' ; start of options? + jp nz,usage ; yes, handle option + call option ; do option processing + ret nz ; done if non-zero reture +; +process0: + call crlf2 ; formatting +; +process1: + ld b,bf_sysget ; HBIOS SYSGET function + ld c,bf_sysgettimer ; TIMER subfunction + rst 08 ; call HBIOS, DE:HL := timer value + + ld a,(first) + or a + ld a,0 + ld (first),a + jr nz,process1a + + ; test for new value + ld a,(last) ; last LSB value to A + cp l ; compare to current LSB + jr z,process2 ; if equal, bypass display + +process1a: + ; save and print new value + ld a,l ; new LSB value to A + ld (last),a ; save as last value + call prtcr ; back to start of line + call nz,prthex32 ; display it +; +process2: + ld a,(cont) ; continuous display? + or a ; test for true/false + jr z,process3 ; if false, get out +; + ld c,6 ; BDOS: direct console I/O + ld e,$FF ; input char + call bdos ; call BDOS, A := char + or a ; test for zero + jr z,process1 ; loop until char pressed +; +process3: + xor a ; signal success + ret +; +; Handle special options +; +option: +; + inc hl ; next char + ld a,(hl) ; get it + cp '?' ; is it a '?'? + jp z,usage ; yes, display usage + cp 'C' ; is it a 'C', continuous? + jp z,setcont ; yes, set continuous display + jp errprm ; anything else is an error +; +usage: +; + call crlf2 ; blank line + ld de,msguse ; point to usage message + call prtstr ; print it + or $FF ; signal no action performed + ret ; and return +; +setcont: +; + or $FF ; set A to true + ld (cont),a ; and save it + xor a ; signal success + ret ; and done +; +; Print character in A without destroying any registers +; +prtchr: + push bc ; save registers + push de + push hl + ld e,a ; character to print in E + ld c,$02 ; BDOS function to output a character + call bdos ; do it + pop hl ; restore registers + pop de + pop bc + ret +; +prtdot: +; + ; shortcut to print a dot preserving all regs + push af ; save af + ld a,'.' ; load dot char + call prtchr ; print it + pop af ; restore af + ret ; done +; +prtcr: +; + ; shortcut to print a dot preserving all regs + push af ; save af + ld a,13 ; load CR value + call prtchr ; print it + pop af ; restore af + ret ; done +; +; Print a zero terminated string at (DE) without destroying any registers +; +prtstr: + push de +; +prtstr1: + ld a,(de) ; get next char + or a + jr z,prtstr2 + call prtchr + inc de + jr prtstr1 +; +prtstr2: + pop de ; restore registers + ret +; +; Print the value in A in hex without destroying any registers +; +prthex: + push af ; save AF + push de ; save DE + call hexascii ; convert value in A to hex chars in DE + ld a,d ; get the high order hex char + call prtchr ; print it + ld a,e ; get the low order hex char + call prtchr ; print it + pop de ; restore DE + pop af ; restore AF + ret ; done +; +; print the hex word value in bc +; +prthexword: + push af + ld a,b + call prthex + ld a,c + call prthex + pop af + ret +; +; print the hex dword value in de:hl +; +prthex32: + push bc + push de + pop bc + call prthexword + push hl + pop bc + call prthexword + pop bc + ret +; +; Convert binary value in A to ascii hex characters in DE +; +hexascii: + ld d,a ; save A in D + call hexconv ; convert low nibble of A to hex + ld e,a ; save it in E + ld a,d ; get original value back + rlca ; rotate high order nibble to low bits + rlca + rlca + rlca + call hexconv ; convert nibble + ld d,a ; save it in D + ret ; done +; +; Convert low nibble of A to ascii hex +; +hexconv: + and $0F ; low nibble only + add a,$90 + daa + adc a,$40 + daa + ret +; +; Print value of A or HL in decimal with leading zero suppression +; Use prtdecb for A or prtdecw for HL +; +prtdecb: + push hl + ld h,0 + ld l,a + call prtdecw ; print it + pop hl + ret +; +prtdecw: + push af + push bc + push de + push hl + call prtdec0 + pop hl + pop de + pop bc + pop af + ret +; +prtdec0: + ld e,'0' + ld bc,-10000 + call prtdec1 + ld bc,-1000 + call prtdec1 + ld bc,-100 + call prtdec1 + ld c,-10 + call prtdec1 + ld e,0 + ld c,-1 +prtdec1: + ld a,'0' - 1 +prtdec2: + inc a + add hl,bc + jr c,prtdec2 + sbc hl,bc + cp e + ret z + ld e,0 + call prtchr + ret +; +; Start a new line +; +crlf2: + call crlf ; two of them +crlf: + push af ; preserve AF + ld a,13 ; + call prtchr ; print it + ld a,10 ; + call prtchr ; print it + pop af ; restore AF + ret +; +; Get the next non-blank character from (HL). +; +nonblank: + ld a,(hl) ; load next character + or a ; string ends with a null + ret z ; if null, return pointing to null + cp ' ' ; check for blank + ret nz ; return if not blank + inc hl ; if blank, increment character pointer + jr nonblank ; and loop +; +; Convert character in A to uppercase +; +ucase: + cp 'a' ; if below 'a' + ret c ; ... do nothing and return + cp 'z' + 1 ; if above 'z' + ret nc ; ... do nothing and return + res 5,a ; clear bit 5 to make lower case -> upper case + ret ; and return +; +; Add the value in A to HL (HL := HL + A) +; +addhl: + add a,l ; A := A + L + ld l,a ; Put result back in L + ret nc ; if no carry, we are done + inc h ; if carry, increment H + ret ; and return +; +; Jump indirect to address in HL +; +jphl: + jp (hl) +; +; Errors +; +erruse: ; command usage error (syntax) + ld de,msguse + jr err +; +errprm: ; command parameter error (syntax) + ld de,msgprm + jr err +err: ; print error string and return error signal + call crlf ; print newline +; +err1: ; without the leading crlf + call prtstr ; print error string +; +err2: ; without the string +; call crlf ; print newline + or $FF ; signal error + ret ; done +; +;=============================================================================== +; Storage Section +;=============================================================================== +; +last .db 0 ; last LSB of timer value +cont .db 0 ; non-zero indicates continuous display +first .db $FF ; first pass flag (true at start) +; +stksav .dw 0 ; stack pointer saved at start + .fill stksiz,0 ; stack +stack .equ $ ; stack top +; +; Messages +; +msgban .db "TIMER v1.0, 14-Jan-2018",13,10 + .db "Copyright (C) 2018, Wayne Warthen, GNU GPL v3",0 +msguse .db "Usage: TIMER [/C] [/?]",13,10 + .db " ex. TIMER (display current timer value)",13,10 + .db " TIMER /? (display version and usage)",13,10 + .db " TIMER /C (display timer value continuously)",0 +msgprm .db "Parameter error (TIMER /? for usage)",0 +; + .end diff --git a/Source/Build.cmd b/Source/Build.cmd index 2493a5a0..28b4c1a5 100644 --- a/Source/Build.cmd +++ b/Source/Build.cmd @@ -5,5 +5,5 @@ REM setlocal & call BuildDoc || exit /b 1 & endlocal setlocal & call BuildHardware || exit /b 1 & endlocal setlocal & call BuildImages || exit /b 1 & endlocal setlocal & call BuildShared || exit /b 1 & endlocal -setlocal & call BuildBP || exit /b 1 & endlocal +REM setlocal & call BuildBP || exit /b 1 & endlocal setlocal & call BuildROM %* || exit /b 1 & endlocal \ No newline at end of file diff --git a/Source/HBIOS/API.txt b/Source/HBIOS/API.txt index f329d1b6..5463890d 100644 --- a/Source/HBIOS/API.txt +++ b/Source/HBIOS/API.txt @@ -52,6 +52,10 @@ GET ($F8): VDACNT ($40): BC=Function/Subfunction A=Result E=Video Unit Count + + TIMER ($D0): + BC=Function/Subfunction A=Result + DE:HL=Timer Value (32 bit) BOOTINFO ($E0): BC=Function/Subfunction A=Result @@ -77,6 +81,10 @@ GET ($F8): SET ($F9): BC=Function/Subfunction A=Result + TIMER ($D0): + BC=Function/Subfunction A=Result + DE:HL=Timer Value (32 bit) + BOOTINFO ($E0): BC=Function/Subfunction A=Result DE=Boot Volume (Disk Unit/Slice) diff --git a/Source/HBIOS/Config/SBC_simh.asm b/Source/HBIOS/Config/SBC_simh.asm index 06ac2b65..4c31742e 100644 --- a/Source/HBIOS/Config/SBC_simh.asm +++ b/Source/HBIOS/Config/SBC_simh.asm @@ -5,6 +5,9 @@ ; #include "cfg_sbc.asm" ; +INTMODE .SET 1 ; INT MODE 1 +HTIMENABLE .SET TRUE ; SIMH TIMER +; DSRTCENABLE .SET FALSE ; DS-1302 CLOCK DRIVER SIMRTCENABLE .SET TRUE ; SIMH CLOCK DRIVER ; diff --git a/Source/HBIOS/acia.asm b/Source/HBIOS/acia.asm index 0b6e939c..58d6ec0d 100644 --- a/Source/HBIOS/acia.asm +++ b/Source/HBIOS/acia.asm @@ -60,7 +60,7 @@ ACIA_PREINIT0: JR Z,ACIA_PREINIT2 ; SKIP IT IF NOTHING FOUND ; PUSH BC ; SAVE LOOP CONTROL - LD BC,ACIA_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,ACIA_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL NZ,CIO_ADDENT ; ADD ENTRY IF ACIA FOUND, BC:DE POP BC ; RESTORE LOOP CONTROL ; @@ -216,24 +216,9 @@ ACIAB_INT1: OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; AND RETURN ; +; DRIVER FUNCTION TABLE ; -; -ACIA_DISPATCH: - ; DISPATCH TO FUNCTION HANDLER - PUSH HL ; SAVE HL FOR NOW - LD A,B ; GET FUNCTION - AND $0F ; ISOLATE LOW NIBBLE - RLCA ; X 2 FOR WORD OFFSET INTO FUNCTION TABLE - LD HL,ACIA_FTBL ; START OF FUNC TABLE - CALL ADDHLA ; HL := ADDRESS OF ADDRESS OF FUNCTION - LD A,(HL) ; DEREF HL - INC HL ; ... - LD H,(HL) ; ... - LD L,A ; ... TO GET ADDRESS OF FUNCTION - EX (SP),HL ; RESTORE HL & PUT FUNC ADDRESS -> (SP) - RET ; EFFECTIVELY A JP TO TGT ADDRESS - -ACIA_FTBL: +ACIA_FNTBL: .DW ACIA_IN .DW ACIA_OUT .DW ACIA_IST @@ -241,6 +226,9 @@ ACIA_FTBL: .DW ACIA_INITDEV .DW ACIA_QUERY .DW ACIA_DEVICE +#IF (($ - ACIA_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID ACIA FUNCTION TABLE ***\n" +#ENDIF ; ; ; @@ -256,7 +244,7 @@ ACIA_IN: ACIAA_IN: CALL ACIAA_IST ; RECEIVED CHAR READY? JR Z,ACIAA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER - DI ; AVOID COLLIACIAN WITH INT HANDLER + HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(ACIAA_BUFCNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (ACIAA_BUFCNT),A ; SAVE SAVE IT @@ -276,14 +264,14 @@ ACIAA_IN0: LD HL,ACIAA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER ACIAA_IN1: LD (ACIAA_TL),HL ; SAVE UPDATED TAIL POINTER - EI ; INTERRUPTS OK AGAIN + HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; ACIAB_IN: CALL ACIAB_IST ; RECEIVED CHAR READY? JR Z,ACIAB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER - DI ; AVOID COLLIACIAN WITH INT HANDLER + HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(ACIAB_BUFCNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (ACIAB_BUFCNT),A ; SAVE SAVE IT @@ -303,7 +291,7 @@ ACIAB_IN0: LD HL,ACIAB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER ACIAB_IN1: LD (ACIAB_TL),HL ; SAVE UPDATED TAIL POINTER - EI ; INTERRUPTS OK AGAIN + HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; diff --git a/Source/HBIOS/ansi.asm b/Source/HBIOS/ansi.asm index be63fabb..77435b24 100644 --- a/Source/HBIOS/ansi.asm +++ b/Source/HBIOS/ansi.asm @@ -22,7 +22,7 @@ ANSI_DEFCOLOR .EQU 7 ; WHITE ON BLACK ; ON ENTRY: ; DE: DISPATCH ADDRESS OF CALLING VDA DRIVER ; RETURNS: -; DE: OUR CIO DISPATCH ADDRESS +; DE: OUR CIO FUNC TBL ADDRESS ; ANSI_INIT: ; PREVENT ATTEMPTS TO INIT MULTIPLE INSTANCES FOR NOW @@ -35,13 +35,13 @@ ANSI_INIT: LD (ANSI_DEVNUM),A ; SAVE IT LD A,C ; VDA UNIT NUMBER PASSED IN C LD (ANSI_VDAUNIT),A ; SAVE IT - LD (ANSI_VDADISPADR),DE ; RECORD VDA DISPATCH ADDRESS + ;LD (ANSI_VDADISPADR),DE ; RECORD VDA DISPATCH ADDRESS ; ; INIT/RESET OUR INTERNAL STATE CALL ANSI_RESET ; FULL RESET OF EMULATOR INTERNAL STATE RET NZ ; BAIL OUT ON ERROR ; - LD DE,ANSI_DISPATCH ; RETURN OUR DISPATCH ADDRESS + LD DE,ANSI_FNTBL ; RETURN OUR FUNC TBL ADDRESS XOR A ; SIGNAL SUCCESS RET ; RETURN ; @@ -86,28 +86,25 @@ ANSI_RESET1: ; LOOP TO RESET TAB STOPS ; ; ANSI_VDADISP: - JP PANIC -ANSI_VDADISPADR .EQU $ - 2 -; -; -; -ANSI_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JR Z,ANSI_CIOIN ; $30 - DEC A - JR Z,ANSI_CIOOUT ; $31 - DEC A - JR Z,ANSI_CIOIST ; $32 - DEC A - JR Z,ANSI_CIOOST ; $33 - DEC A - JR Z,ANSI_CIOINIT ; $34 - DEC A - JP Z,ANSI_CIOQUERY ; $35 - DEC A - JP Z,ANSI_CIODEVICE ; $36 - CALL PANIC +; JP PANIC +;ANSI_VDADISPADR .EQU $ - 2 + LD A,(ANSI_VDAUNIT) + LD C,A + JP VDA_DISPATCH +; +; FUNCTION TABLE +; +ANSI_FNTBL: + .DW ANSI_IN + .DW ANSI_OUT + .DW ANSI_IST + .DW ANSI_OST + .DW ANSI_INITDEV + .DW ANSI_QUERY + .DW ANSI_DEVICE +#IF (($ - ANSI_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID ANSI FUNCTION TABLE ***\n" +#ENDIF ; ;================================================================================================== ; ANSI EMULATION MODULE BIOS FUNCTION ENTRY POINTS @@ -115,12 +112,12 @@ ANSI_DISPATCH: ; ; READ A CHARACTER ; -ANSI_CIOIN: ; HANDLE INPUT REQUEST +ANSI_IN: ; HANDLE INPUT REQUEST ; ; RETURN QUEUED DATA IF WE HAVE ANY LD A,(ANSI_QLEN) ; GET THE CURRENT QUEUE LENGTH OR A ; SET FLAGS - JR Z,ANSI_CIOIN1 ; NOTHING THERE, GO TO KEYBOARD READ + JR Z,ANSI_IN1 ; NOTHING THERE, GO TO KEYBOARD READ DEC A ; DECREMENT THE QUEUE LENGTH LD (ANSI_QLEN),A ; AND SAVE IT LD HL,(ANSI_QPTR) ; GET THE QUEUE POINTER @@ -131,44 +128,44 @@ ANSI_CIOIN: ; HANDLE INPUT REQUEST XOR A ; SIGNAL SUCCESS RET ; DONE ; -ANSI_CIOIN1: ; PERFORM ACTUAL KEYBOARD INPUT +ANSI_IN1: ; PERFORM ACTUAL KEYBOARD INPUT LD B,BF_VDAKRD ; SET FUNCTION TO KEYBOARD READ CALL ANSI_VDADISP ; CALL VDA DISPATCHER LD A,E ; CHARACTER READ INTO A BIT 7,A ; TEST HIGH BIT - JR NZ,ANSI_CIOIN2 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR + JR NZ,ANSI_IN2 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR XOR A ; OTHERWISE, SIGNAL SUCCESS RET ; AND RETURN THE KEY ; -ANSI_CIOIN2: ; HANDLE SPECIAL KEY +ANSI_IN2: ; HANDLE SPECIAL KEY CALL ANSI_KDISP ; IF $80 OR HIGHER, DISPATCH - JR ANSI_CIOIN ; AND LOOP + JR ANSI_IN ; AND LOOP ; ; WRITE A CHARACTER W/ EMULATION ; -ANSI_CIOOUT: - LD HL,ANSI_CIOOUT2 ; RETURN ADDRESS +ANSI_OUT: + LD HL,ANSI_OUT2 ; RETURN ADDRESS PUSH HL ; PUT IT ON STACK LD A,E ; GET THE INCOMING CHARACTER CP $20 ; $00-$1F IS C0 JP C,ANSI_C0DISP ; IF C0, DO C0 DISPATCH CP $80 ; $20-$7F - JR C,ANSI_CIOOUT1 ; HANDLE VIA STATE MACHINE + JR C,ANSI_OUT1 ; HANDLE VIA STATE MACHINE CP $A0 ; $80-$9F IS C1 JP C,ANSI_C1DISP ; IF C1, DO C1 DISPATCH ; -ANSI_CIOOUT1: ; PROCESS OTHER CHARS VIA STATE MACHINE +ANSI_OUT1: ; PROCESS OTHER CHARS VIA STATE MACHINE LD HL,(ANSI_STATE) ; LOAD THE CURRENT STATE JP (HL) ; DO IT ; CALL JPHL ; DO IT ; -ANSI_CIOOUT2: ; SET RESULT AND RETURN +ANSI_OUT2: ; SET RESULT AND RETURN XOR A ; SIGNAL SUCCESS RET ; ; CHECK INPUT STATUS ; -ANSI_CIOIST: ; CHECK QUEUE FIRST +ANSI_IST: ; CHECK QUEUE FIRST LD A,(ANSI_QLEN) ; GET CURRENT QUEUE LENGTH OR A ; SET FLAGS RET NZ ; RETURN IF CHAR(S) WAITING @@ -184,7 +181,7 @@ ANSI_CIOIST: ; CHECK QUEUE FIRST CALL ANSI_VDADISP ; DO IT LD A,E ; CHARACTER READ TO A BIT 7,A ; TEST HIGH BIT - JR NZ,ANSI_CIOIST1 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR + JR NZ,ANSI_IST1 ; HANDLE $80 OR HIGHER AS SPECIAL CHAR ; ; REGULAR CHARACTER RECEIVED, QUEUE IT AND RETURN CHARS WAITING STATUS LD HL,ANSI_QUEUE ; SET HL TO START OF QUEUE @@ -194,22 +191,22 @@ ANSI_CIOIST: ; CHECK QUEUE FIRST XOR A ; ZERO ACCUM INC A ; ASSUM := 1 (NUM CHARS IN QUEUE) LD (ANSI_QLEN),A ; SAVE NEW QUEUE LEN - JR ANSI_CIOIST ; REPEAT + JR ANSI_IST ; REPEAT ; -ANSI_CIOIST1: ; HANDLE SPECIAL KEY +ANSI_IST1: ; HANDLE SPECIAL KEY CALL ANSI_KDISP ; DO SPECIAL KEY HANDLING - JR ANSI_CIOIST ; REPEAT + JR ANSI_IST ; REPEAT ; ; CHECK OUTPUT STATUS ; -ANSI_CIOOST: ; VIDEO OUTPUT IS *ALWAYS* READY +ANSI_OST: ; VIDEO OUTPUT IS *ALWAYS* READY XOR A ; ZERO ACCUM INC A ; A := $FF TO SIGNAL OUTPUT BUFFER READY RET ; ; INITIALIZE ; -ANSI_CIOINIT: +ANSI_INITDEV: ; RESET THE ATTACHED VDA DEVICE LD B,BF_VDAINI ; FUNC: INIT LD E,-1 ; DO NOT CHANGE VIDEO MODE @@ -220,7 +217,7 @@ ANSI_CIOINIT: ; ; QUERY STATUS ; -ANSI_CIOQUERY: +ANSI_QUERY: LD DE,$FFFF LD HL,$FFFF XOR A @@ -228,7 +225,7 @@ ANSI_CIOQUERY: ; ; REPORT DEVICE ; -ANSI_CIODEVICE: +ANSI_DEVICE: LD D,CIODEV_TERM ; TYPE IS TERMINAL LD A,(ANSI_DEVNUM) ; GET DEVICE NUMBER LD E,A ; PUT IT IN E diff --git a/Source/HBIOS/asci.asm b/Source/HBIOS/asci.asm index 2524f288..d3ef04c7 100644 --- a/Source/HBIOS/asci.asm +++ b/Source/HBIOS/asci.asm @@ -68,21 +68,31 @@ ASCI_PREINIT: ; ; SETUP THE DISPATCH TABLE ENTRIES ; - LD B,2 ; ALWAYS 2 ASCI UNITS ON Z180 - LD C,0 ; PHYSICAL UNIT INDEX -ASCI_PREINIT1: - PUSH BC ; SAVE LOOP CONTROL - LD D,C ; PHYSICAL UNIT +; LD B,2 ; ALWAYS 2 ASCI UNITS ON Z180 +; LD C,0 ; PHYSICAL UNIT INDEX +;ASCI_PREINIT1: +; PUSH BC ; SAVE LOOP CONTROL +; LD D,C ; PHYSICAL UNIT +; LD E,CIODEV_ASCI ; DEVICE TYPE +; LD BC,ASCI_FNTBL ; BC := FUNCTION TABLE ADDRESS +; CALL CIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED +; POP BC ; RESTORE LOOP CONTROL +; INC C ; NEXT PHYSICAL UNIT +; DJNZ ASCI_PREINIT1 ; LOOP UNTIL DONE +; + ; ASCI0 CHANNEL + LD D,0 ; DEVICE ID LD E,CIODEV_ASCI ; DEVICE TYPE - LD BC,ASCI_DISPATCH ; BC := DISPATCH ADDRESS - CALL CIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED - POP BC ; RESTORE LOOP CONTROL - INC C ; NEXT PHYSICAL UNIT - DJNZ ASCI_PREINIT1 ; LOOP UNTIL DONE -; + LD BC,ASCI0_FNTBL ; ASCI0 FUNCTION TABLE PTR + CALL CIO_ADDENT LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG CALL ASCI0_INITDEV ; INIT DEVICE -; +; + ; ASCI1 CHANNEL + LD D,1 ; DEVICE ID + LD E,CIODEV_ASCI ; DEVICE TYPE + LD BC,ASCI1_FNTBL ; ASCI1 FUNCTION TABLE PTR + CALL CIO_ADDENT LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG CALL ASCI1_INITDEV ; INIT DEVICE ; @@ -124,36 +134,19 @@ ASCI_INIT: XOR A RET ; -; DISPATCH TO SPECIFIC ASCI UNIT +; DRIVER ASCI0 FUNCTION TABLE ; -ASCI_DISPATCH: - PUSH IY ; PUSH UNIT DATA WORD - POP AF ; POP TO AF, A := DEVICE NUM - OR A ; SET FLAGS - JP Z,ASCI0 - DEC A - JP Z,ASCI1 - CALL PANIC -; -; ASCI 0 FUNCTIONS -; -ASCI0: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JP Z,ASCI0_IN - DEC A - JP Z,ASCI0_OUT - DEC A - JP Z,ASCI0_IST - DEC A - JP Z,ASCI0_OST - DEC A - JP Z,ASCI0_INITDEV - DEC A - JP Z,ASCI0_QUERY - DEC A - JP Z,ASCI0_DEVICE - CALL PANIC +ASCI0_FNTBL: + .DW ASCI0_IN + .DW ASCI0_OUT + .DW ASCI0_IST + .DW ASCI0_OST + .DW ASCI0_INITDEV + .DW ASCI0_QUERY + .DW ASCI0_DEVICE +#IF (($ - ASCI0_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID ASCI0 FUNCTION TABLE ***\n" +#ENDIF ; ASCI0_IN: CALL ASCI0_IST @@ -269,8 +262,19 @@ ASCI0_DEVICE: XOR A ; SIGNAL SUCCESS RET ; -; ASCI 1 FUNCTIONS -; +; DRIVER ASCI1 FUNCTION TABLE +; +ASCI1_FNTBL: + .DW ASCI1_IN + .DW ASCI1_OUT + .DW ASCI1_IST + .DW ASCI1_OST + .DW ASCI1_INITDEV + .DW ASCI1_QUERY + .DW ASCI1_DEVICE +#IF (($ - ASCI1_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID ASCI1 FUNCTION TABLE ***\n" +#ENDIF ASCI1: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION diff --git a/Source/HBIOS/cfg_mk4.asm b/Source/HBIOS/cfg_mk4.asm index 6be5bdf5..5a777cde 100644 --- a/Source/HBIOS/cfg_mk4.asm +++ b/Source/HBIOS/cfg_mk4.asm @@ -8,13 +8,14 @@ CPUOSC .EQU 18432000 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_Z180 ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTMODE .EQU 2 ; 0=NONE, 1=INT MODE 1, 2=INT MODE 2 ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) ; DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) ; +HTIMENABLE .EQU FALSE ; TRUE FOR SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER DSRTCENABLE .EQU TRUE ; DS-1302 CLOCK DRIVER DSRTCMODE .EQU DSRTCMODE_STD ; DSRTCMODE_STD, DSRTCMODE_MFPIC diff --git a/Source/HBIOS/cfg_n8.asm b/Source/HBIOS/cfg_n8.asm index 061ceae1..fb9eea28 100644 --- a/Source/HBIOS/cfg_n8.asm +++ b/Source/HBIOS/cfg_n8.asm @@ -8,13 +8,14 @@ CPUOSC .EQU 18432000 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_Z180 ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTMODE .EQU 2 ; 0=NONE, 1=INT MODE 1, 2=INT MODE 2 ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) ; DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) ; +HTIMENABLE .EQU FALSE ; TRUE FOR SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER DSRTCENABLE .EQU TRUE ; DS-1302 CLOCK DRIVER DSRTCMODE .EQU DSRTCMODE_STD ; DSRTCMODE_STD, DSRTCMODE_MFPIC diff --git a/Source/HBIOS/cfg_rc.asm b/Source/HBIOS/cfg_rc.asm index a914b4b2..148a3f42 100644 --- a/Source/HBIOS/cfg_rc.asm +++ b/Source/HBIOS/cfg_rc.asm @@ -8,13 +8,14 @@ CPUOSC .EQU 7372800 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_115200_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_RC ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTMODE .EQU 1 ; 0=NONE, 1=INT MODE 1, 2=INT MODE 2 ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) ; DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) ; +HTIMENABLE .EQU FALSE ; TRUE FOR SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER DSRTCENABLE .EQU FALSE ; DS-1302 CLOCK DRIVER DSRTCMODE .EQU DSRTCMODE_STD ; DSRTCMODE_STD, DSRTCMODE_MFPIC diff --git a/Source/HBIOS/cfg_sbc.asm b/Source/HBIOS/cfg_sbc.asm index 8fd6624a..2e0750fa 100644 --- a/Source/HBIOS/cfg_sbc.asm +++ b/Source/HBIOS/cfg_sbc.asm @@ -8,13 +8,14 @@ CPUOSC .EQU 8000000 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_NONE ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTMODE .EQU 0 ; 0=NONE, 1=INT MODE 1, 2=INT MODE 2 ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) ; DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) ; +HTIMENABLE .EQU FALSE ; TRUE FOR SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER DSRTCENABLE .EQU TRUE ; DS-1302 CLOCK DRIVER DSRTCMODE .EQU DSRTCMODE_STD ; DSRTCMODE_STD, DSRTCMODE_MFPIC diff --git a/Source/HBIOS/cfg_zeta.asm b/Source/HBIOS/cfg_zeta.asm index 0e9cb1f2..73102395 100644 --- a/Source/HBIOS/cfg_zeta.asm +++ b/Source/HBIOS/cfg_zeta.asm @@ -8,13 +8,14 @@ CPUOSC .EQU 20000000 ; CPU OSC FREQ RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!! DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE) -INTTYPE .EQU IT_NONE ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) +INTMODE .EQU 0 ; 0=NONE, 1=INT MODE 1, 2=INT MODE 2 ; CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP VDAEMU .EQU EMUTYP_ANSI ; DEFAULT VDA EMULATION (EMUTYP_TTY, EMUTYP_ANSI, ...) ; DSKYENABLE .EQU FALSE ; TRUE FOR DSKY SUPPORT (DO NOT COMBINE WITH PPIDE) ; +HTIMENABLE .EQU FALSE ; TRUE FOR SIMH TIMER SUPPORT SIMRTCENABLE .EQU FALSE ; SIMH CLOCK DRIVER DSRTCENABLE .EQU TRUE ; DS-1302 CLOCK DRIVER DSRTCMODE .EQU DSRTCMODE_STD ; DSRTCMODE_STD, DSRTCMODE_MFPIC diff --git a/Source/HBIOS/cfg_zeta2.asm b/Source/HBIOS/cfg_zeta2.asm index f0bda1ee..753f6755 100644 --- a/Source/HBIOS/cfg_zeta2.asm +++ b/Source/HBIOS/cfg_zeta2.asm @@ -7,6 +7,4 @@ ; #INCLUDE "cfg_zeta.asm" ; USE ZETA CONFIG TO START ; -INTTYPE .SET IT_CTC ; INTERRUPT HANDLING TYPE (IT_NONE, IT_SIMH, IT_Z180, IT_CTC, ...) -; FDMODE .SET FDMODE_ZETA2 ; FDMODE_DIO, FDMODE_ZETA, FDMODE_DIDE, FDMODE_N8, FDMODE_DIO3 diff --git a/Source/HBIOS/cvdu.asm b/Source/HBIOS/cvdu.asm index bc6eafa7..29277d78 100644 --- a/Source/HBIOS/cvdu.asm +++ b/Source/HBIOS/cvdu.asm @@ -57,13 +57,13 @@ CVDU_INIT1: CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER ; ADD OURSELVES TO VDA DISPATCH TABLE - LD BC,CVDU_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,CVDU_FNTBL ; BC := FUNCTION TABLE ADDRESS LD DE,CVDU_IDAT ; DE := VGA INSTANCE DATA PTR CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; INITIALIZE EMULATION LD C,A ; C := ASSIGNED VIDEO DEVICE NUM - LD DE,CVDU_DISPATCH ; DE := DISPATCH ADDRESS + LD DE,VGA_FNTBL ; DE := FUNCTION TABLE ADDRESS LD HL,CVDU_IDAT ; HL := CVDU INSTANCE DATA PTR CALL TERM_ATTACH ; DO IT @@ -71,43 +71,28 @@ CVDU_INIT1: RET ; ;====================================================================== -; CVDU DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS +; CVDU DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS ;====================================================================== ; -CVDU_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - - JP Z,CVDU_VDAINI ; $40 - DEC A - JP Z,CVDU_VDAQRY ; $41 - DEC A - JP Z,CVDU_VDARES ; $42 - DEC A - JP Z,CVDU_VDADEV ; $43 - DEC A - JP Z,CVDU_VDASCS ; $44 - DEC A - JP Z,CVDU_VDASCP ; $45 - DEC A - JP Z,CVDU_VDASAT ; $46 - DEC A - JP Z,CVDU_VDASCO ; $47 - DEC A - JP Z,CVDU_VDAWRC ; $48 - DEC A - JP Z,CVDU_VDAFIL ; $49 - DEC A - JP Z,CVDU_VDACPY ; $4A - DEC A - JP Z,CVDU_VDASCR ; $4B - DEC A - JP Z,KBD_STAT ; $4C - DEC A - JP Z,KBD_FLUSH ; $4D - DEC A - JP Z,KBD_READ ; $4E - CALL PANIC +CVDU_FNTBL: + .DW CVDU_VDAINI + .DW CVDU_VDAQRY + .DW CVDU_VDARES + .DW CVDU_VDADEV + .DW CVDU_VDASCS + .DW CVDU_VDASCP + .DW CVDU_VDASAT + .DW CVDU_VDASCO + .DW CVDU_VDAWRC + .DW CVDU_VDAFIL + .DW CVDU_VDACPY + .DW CVDU_VDASCR + .DW KBD_STAT + .DW KBD_FLUSH + .DW KBD_READ +#IF (($ - CVDU_FNTBL) != (VDA_FNCNT * 2)) + .ECHO "*** INVALID CVDU FUNCTION TABLE ***\n" +#ENDIF CVDU_VDAINI: ; RESET VDA diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 5ac6cd98..519b9440 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -67,14 +67,18 @@ MODCNT .SET MODCNT + 1 ; ; ; -#IF (INTTYPE != IT_NONE) -#DEFINE HB_EI EI +#IF (INTMODE == 0) +; NO INTERRUPT HANDLING #DEFINE HB_DI DI -#ELSE #DEFINE HB_EI ; -#DEFINE HB_DI ; +#ELSE +; MODE 1 OR 2 INTERRUPT HANDLING +#DEFINE HB_DI DI +#DEFINE HB_EI EI #ENDIF ; +; +; #IFNDEF APPBOOT ; .ORG 0 @@ -99,7 +103,11 @@ MODCNT .SET MODCNT + 1 .FILL (030H - $),0FFH ; RST 30 RET .FILL (038H - $),0FFH ; RST 38 / IM1 INT - RETI +#IF (INTMODE == 1) + JP INT_IM1 ; JP TO INTERRUPT HANDLER IN HI MEM +#ELSE + RETI ; RETURN W/ INTS DISABLED +#ENDIF .FILL (066H - $),0FFH ; NMI RETN ; @@ -209,11 +217,12 @@ HBX_INVOKE: LD A,BID_BIOS ; HBIOS BANK CALL HBX_BNKSEL ; SELECT IT LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK - + CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH PUSH AF ; SAVE AF (FUNCTION RETURN) + LD A,(HB_INVBNK) ; LOAD ORIGINAL BANK CALL HBX_BNKSEL ; SELECT IT POP AF ; RESTORE AF @@ -238,8 +247,27 @@ HBX_BNKSEL: HBX_BNKSEL_INT: ; #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) - OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR + #IF (INTMODE == 1) + ; THIS BIT OF ABSURDITY HANDLES A RARE (BUT FATAL) SITUATION + ; WHERE AN IM1 INTERRUPT OCCURS BETWEEN SETTING THE RAM AND + ; ROM SELECTORS. BRACKETING THE INSTRUCTIONS WITH DI/EI + ; IS CONTRAINDICATED BECAUSE THIS ROUTINE IS CALLED BY + ; OTHER ROUTINES THAT MUST CONTROL INT ENABLE AT A HIGHER + ; LEVEL. THE FOLLOWING TECHNIQUE ENSURES THAT YOU ALWAYS + ; SWITCH DIRECTLY FROM THE PREVIOUS BANK TO THE TARGET BANK + ; WITHOUT AN "ERRANT" BANK BEING ACTIVE BETWEEN THE TWO + ; BANK SELECTION I/O INSTRUCTIONS. THE TECHNIQUE IS ONLY + ; NEEDED WHEN USING INT MODE 1 BECAUSE THAT MODE REQUIRES + ; PAGE ONE TO HAVE A VALID INT HANDLER WHENEVER INTS ARE + ; ENABLED. + ;BIT 7,A ; [8] TEST RAM BIT + ;JR Z,HBX_ROM ; [12/7] IF NOT SET, JUST DO ROM + OR A ; [4] SET FLAGS + JP P,HBX_ROM ; [10] BIT 7 INDICATES RAM + #ENDIF OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR +HBX_ROM: + OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR RET ; DONE #ENDIF #IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC)) @@ -294,6 +322,7 @@ HBX_BNKSEL1: ; usage of the HL and DE registers is reversed. ; Caller MUST ensure stack is already in high memory. ; Caller MUST preset HBX_SRCBNK and HBX_DSTBNK. +; Caller MUST disable ints if IM1 active ; Enter: ; HL = Source Address ; DE = Destination Address @@ -304,9 +333,9 @@ HBX_BNKSEL1: ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; HBX_BNKCPY: -#IF (INTTYPE == IT_SIMH) - HB_DI -#ENDIF +;#IF (INTMODE < 2) +; DI +;#ENDIF LD (HBX_BC_SP),SP ; PUT STACK LD SP,HBX_TMPSTK ; ... IN HI MEM @@ -338,9 +367,9 @@ HBX_BC_LAST: LD SP,$FFFF ; RESTORE STACK HBX_BC_SP .EQU $ - 2 ; ... TO ORIGINAL VALUE -#IF (INTTYPE == IT_SIMH) - HB_EI -#ENDIF +;#IF (INTMODE == 1) +; EI +;#ENDIF RET ; HBX_BC_ITER: @@ -364,6 +393,8 @@ HBX_BC_ITER: ; ; CALL A ROUTINE IN ANOTHER BANK. ; CALLER MUST ENSURE STACK IS ALREADY IN HIGH MEMORY AND HAS ADEQUATE SPACE. +; IF IM1 INTERRUPTS ARE POSSIBLE, CALLER MUST EITHER DISABLE THEM PRIOR TO +; BNKCALL OR MAKE SURE THAT PAGE ZERO IN TARGTET BANK IS PREPARED FOR THEM. ; ON INPUT A=TARGET BANK, HL=TARGET ADDRESS ; HBX_BNKCALL: @@ -388,11 +419,12 @@ HBX_TGTADR .EQU $ + 1 ; ; PEEK & POKE ROUTINES ; ADDRESS IN HL, BANK IN D, VALUE IN/OUT IN E, A IS TRASHED +; CALLER MUST DISABLE INTS IF IM1 AND ACCESSING PAGE W/O IM1 INT VECTOR ; HBX_PEEK: -#IF (INTTYPE == IT_SIMH) - HB_DI -#ENDIF +;#IF (INTMODE < 2) +; DI +;#ENDIF LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM LD A,(HB_CURBNK) @@ -403,9 +435,9 @@ HBX_PEEK: JR HBX_PPRET ; HBX_POKE: -#IF (INTTYPE == IT_SIMH) - HB_DI -#ENDIF +;#IF (INTMODE < 2) +; DI +;#ENDIF LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM LD A,(HB_CURBNK) @@ -419,12 +451,12 @@ HBX_PPRET: CALL HBX_BNKSEL LD SP,0 ; RESTORE ORIGINAL STACK FRAME HBX_PPSP .EQU $ - 2 -#IF (INTTYPE == IT_SIMH) - HB_EI -#ENDIF +;#IF (INTMODE == 1) +; EI +;#ENDIF RET ; -; SMALL TEMPORARY STACK FOR USE BY HB_INVOKE +; SMALL TEMPORARY STACK FOR USE BY INVOKE, PEEK, AND POKE ; .FILL 20,$CC ; 10 LEVEL STACK HBX_TMPSTK .EQU $ @@ -439,6 +471,8 @@ HBX_STKSIZ .EQU $FF00 - $ .FILL HBX_STKSIZ,$FF HBX_STACK .EQU $ ; +#IF (INTMODE == 2) +; ; HBIOS INTERRUPT VECTOR TABLE (16 ENTRIES) ; HBX_IVT: @@ -459,6 +493,8 @@ HBX_IVT: .DW INT_BAD ; .DW INT_BAD ; ; +#ENDIF +; ; INTERRUPT HANDLER STUBS ; ; THE FOLLOWING INTERRUPT STUBS RECEIVE CONTROL FROM THE @@ -467,27 +503,37 @@ HBX_IVT: ; ; INT_IM1: +#IF (INTMODE == 1) PUSH HL ; SAVE HL LD HL,HB_IM1INT ; HL := IM1 INT HANDLER IN BIOS BANK JR HBX_INT ; TO TO ROUTING CODE +#ELSE + RETI ; UNEXPECTED INT, RET W/ INTS LEFT DISABLED +#ENDIF ; -INT_TIMER: ; TIMER INTERRUPT HANDLER - PUSH HL ; SAVE HL - LD HL,HB_TIMINT ; HL := INT ADR IN BIOS - JR HBX_INT ; GO TO ROUTING CODE +#IF (INTMODE == 2) ; INT_BAD: ; BAD INTERRUPT HANDLER PUSH HL ; SAVE HL LD HL,HB_BADINT ; HL := INT HANDLER IN BIOS BANK - JR HBX_INT ; TO TO ROUTING CODE + JR HBX_INT ; GO TO ROUTING CODE ; -#IF (SIOENABLE) +INT_TIMER: ; TIMER INTERRUPT HANDLER + PUSH HL ; SAVE HL + LD HL,HB_TIMINT ; HL := INT ADR IN BIOS + JR HBX_INT ; GO TO ROUTING CODE +; + #IF (SIOENABLE) INT_SIO: ; SIO INTERRUPT HANDLER PUSH HL ; SAVE HL LD HL,SIO_INT ; HL := SIO INT HANDLER IN BIOS BANK - JR HBX_INT ; TO TO ROUTING CODE + JR HBX_INT ; GO TO ROUTING CODE + #ENDIF +; #ENDIF ; +#IF (INTMODE > 0) +; ; COMMON INTERRUPT DISPATCHING CODE ; SETUP AND CALL HANDLER IN BIOS BANK ; @@ -501,7 +547,7 @@ HBX_INT: ; COMMON INTERRUPT ROUTING CODE PUSH BC ; SAVE BC PUSH DE ; SAVE DE PUSH IY ; SAVE IY - + LD A,BID_BIOS ; HBIOS BANK CALL HBX_BNKSEL_INT ; SELECT IT @@ -509,7 +555,7 @@ HBX_INT: ; COMMON INTERRUPT ROUTING CODE LD A,(HB_CURBNK) ; GET PRE-INT BANK CALL HBX_BNKSEL ; SELECT IT - + ; RESTORE STATE POP IY ; RESTORE IY POP DE ; RESTORE DE @@ -524,6 +570,8 @@ HBX_INT_SP .EQU $ - 2 EI ; ENABLE INTERRUPTS RETI ; AND RETURN ; +#ENDIF +; ; FILL TO START OF BOUNCE BUFFER ; HBX_INTFILL .EQU (HBX_XFC - HBX_BUFSIZ - $) @@ -605,12 +653,10 @@ HB_START: XOR A OUT0 (Z180_CCR),A OUT0 (Z180_CMR),A - CALL DLY8 ; SETTLE ; SET DEFAULT WAIT STATES LD A,$F0 OUT0 (Z180_DCNTL),A - CALL DLY8 ; SETTLE ; MMU SETUP LD A,$80 @@ -626,14 +672,12 @@ HB_START: ; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED LD A,$80 OUT0 (Z180_CCR),A - CALL DLY8 ; SETTLE #ENDIF #IF (Z180_CLKDIV >= 2) ; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED LD A,$80 OUT0 (Z180_CMR),A - CALL DLY8 ; SETTLE #ENDIF #ENDIF @@ -697,9 +741,6 @@ HB_START: LD DE,0 LD BC,$8000 CALL HBX_BNKCPY -; - ; INTERRUPTS ARE ENABLED BY BNKCPY!!! - DI ; RE-DISABLE INTERRUPTS ; ; TRANSITION TO HBIOS IN RAM BANK ; @@ -708,19 +749,41 @@ HB_START: CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN HALT ; WE SHOULD NOT COME BACK HERE! ; -HB_RAMFLAG .DB FALSE ; ASSUME FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION +HB_RAMFLAG .DB FALSE ; INITIALLY FALSE, SET TO TRUE BELOW AFTER RAM TRANSITION ; ; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK ; HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK -; - ; INTERRUPTS ARE ENABLED BY BNKCALL!!! - DI ; RE-DISABLE INTERRUTPS ; LD SP,HBX_LOC ; RESET STACK SINCE WE DO NOT RETURN LD A,TRUE ; ACCUM := TRUE LD (HB_RAMFLAG),A ; SET RAMFLAG ; +; IF APPBOOT, WE NEED TO FIX UP A FEW THINGS IN PAGE ZERO +; +#IFDEF APPBOOT + ; MAKE SURE RST 08 VECTOR IS RIGHT + LD A,$C3 + LD ($0008),A + LD HL,HB_INVOKE + LD ($0009),HL +; + ; MAKE SURE IM1 INT VECTOR IS RIGHT + #IF (INTMODE == 1) + ; JP INT_IM1 IF INTERRUPT MODE ACTIVE + LD A,$C3 + LD ($0038),A + LD HL,INT_IM1 + LD ($0039),HL + #ELSE + ; RETI ($ED, $4D) IF NON-INTERRUPT MODE + LD HL,($0038) + LD (HL),$ED + INC HL + LD (HL),$4D + #ENDIF +#ENDIF +; ; PERFORM DYNAMIC CPU SPEED DERIVATION ; CALL HB_CPUSPD ; CPU SPEED DETECTION @@ -765,12 +828,13 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; NOW THAT HBIOS IS READY, SET THE CONSOLE UNIT TO ACTIVATE CONSOLE I/O ; VIA HBIOS. ; - XOR A ; CONSOLE DEVICE IS UNIT #0 BY FIAT + XOR A ; INITIALLY, FIRST SERIAL UNIT IS CONSOLE LD (CB_CONDEV),A ; SAVE IT, ACTIVATES CONSOLE ON HBIOS ; ; ANNOUNCE HBIOS ; - + CALL NEWLINE2 + PRTX(STR_BANNER) ; ; IO PORT SCAN ; @@ -803,32 +867,49 @@ PSCNX .EQU $ + 1 ; ; SETUP INTERRUPT VECTORS, AS APPROPRIATE ; - HB_DI ; START OF CRITICAL SECTION - -#IF (INTTYPE == IT_SIMH) -; - ; SETUP TIMER INT VECTOR VIA INT MODE 1 IN PAGE ZERO - LD A,$C3 ; JP OPCODE - ;LD ($38),A ; ... AT INT VECTOR ADDRESS - LD ($30),A ; ... AT INT VECTOR ADDRESS - LD HL,INT_TIMER ; ADDRESS OF TIMER INT HANDLER - ;LD ($39),HL ; ... IS TARGET OF JP - LD ($31),HL ; ... IS TARGET OF JP - - LD HL,INT_TIMER - LD (HBX_IVT),HL -; -#ENDIF -; -#IF (INTTYPE == IT_Z180) +;#IF (INTMODE == 1) +; ; OVERLAY $0038 WITH JP INT_IM1 +; LD A,$C3 ; JP INSTRUCTION +; LD ($0038),A ; INSTALL IT +; LD HL,INT_IM1 ; DESTINATION ADDRESS +; LD ($0039),HL ; INSTALL IT +;#ENDIF ; +#IF (INTMODE == 2) + ; SETUP Z80 IVT AND INT MODE 2 ; SETUP Z180 IVT LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS LD I,A ; ... AND PLACE IT IN I REGISTER + + #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) XOR A ; SETUP LO BYTE OF IVT ADDRESS OUT0 (Z180_IL),A ; ... AND PLACE IN Z180 IL REGISTER -; + #ENDIF + IM 2 ; SWITCH TO INT MODE 2 +#ENDIF + +#IF (PLATFORM == PLT_SBC) +; + #IF (HTIMENABLE) +; + #IF (INTMODE == 1) + LD HL,HB_TIMINT + CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST + #ENDIF +; + #IF (INTMODE == 2) + ;LD HL,INT_TIMER + ;LD (HBX_IVT),HL + #ENDIF +; + #ENDIF +; +#ENDIF +; +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) +; + #IF (INTMODE == 2) ; ; MASK ALL EXTERNAL INTERRUPTS FOR NOW XOR A ; INT0-2 DISABLED @@ -851,42 +932,12 @@ PSCNX .EQU $ + 1 OUT (C),H LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING OUT0 (Z180_TCR),A -; -#ENDIF -; -#IF (INTTYPE == IT_RC) -; - #IF 0 - ; SETUP Z80 IVT AND INT MODE 2 - LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS - LD I,A ; ... AND PLACE IT IN I REGISTER - IM 2 ; SWITCH TO INT MODE 2 -; - #IF (SIOENABLE) - ; SETUP SIO INTERRUPT VECTOR IN IVT - LD HL,INT_SIO - LD (HBX_IVT + IVT_SER0),HL - #ENDIF -; - #ENDIF -; - #IF 1 - ; SET INT MODE 1 - IM 1 -; - #IF (SIOENABLE | ACIAENABLE) - ; SETUP IM1 INT VECTOR VIA INT MODE 1 IN PAGE ZERO - LD A,$C3 ; JP OPCODE - LD ($38),A ; ... AT INT VECTOR ADDRESS - LD HL,INT_IM1 ; ADDRESS OF SIO INT HANDLER - LD ($39),HL ; ... IS TARGET OF JP - #ENDIF ; #ENDIF ; #ENDIF ; - HB_EI ; END OF CRITICAL SECTION + HB_EI ; INTERRUPTS SHOULD BE OK NOW ; ; DISPLAY PLATFORM INFORMATION ; @@ -899,26 +950,37 @@ PSCNX .EQU $ + 1 ; ; DISPLAY CPU CONFIG ; + ;CALL PRTSTRD + ;.TEXT ", $" + CALL NEWLINE #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) -; - CALL PRTSTRD - .TEXT ", $" LD A,Z180_MEMWAIT +#ELSE + LD A,0 +#ENDIF CALL PRTDECB CALL PRTSTRD .TEXT " MEM W/S, $" - LD A,Z180_IOWAIT +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) + LD A,Z180_IOWAIT + 1 +#ELSE + LD A,1 +#ENDIF CALL PRTDECB CALL PRTSTRD .TEXT " I/O W/S$" -; +#IF (INTMODE > 0) + CALL PRTSTRD + .TEXT ", INT MODE $" + LD A,INTMODE + CALL PRTDECB #ENDIF ; ; DISPLAY MEMORY CONFIG ; CALL NEWLINE - CALL PRTSTRD - .TEXT "MEMORY LAYOUT $" + ;CALL PRTSTRD + ;.TEXT "MEMORY CONFIG: $" LD HL,ROMSIZE CALL PRTDEC CALL PRTSTRD @@ -994,22 +1056,31 @@ INITSYS3: ; CHAIN TO OS LOADER ; #IFDEF ROMBOOT - ; PERFORM BANK CALL TO OS IMAGES BANK + ; PERFORM BANK CALL TO OS IMAGES BANK IN ROM LD A,BID_OSIMG ; CHAIN TO OS IMAGES BANK LD HL,0 ; ENTER AT ADDRESS 0 CALL HBX_BNKCALL ; GO THERE HALT ; WE SHOULD NEVER COME BACK! #ELSE ; COPY OS IMAGE: BID_USR: --> BID_USR:0 - LD A,BID_USR - LD (HB_SRCBNK),A - LD (HB_DSTBNK),A - LD HL,HB_END - LD DE,0 - LD BC,$8000 - CALL HBX_BNKCPY -; - ; PERFORM BANK CALL TO OS IMAGES BANK + ;LD A,BID_USR + ;LD (HB_SRCBNK),A + ;LD (HB_DSTBNK),A + ;LD HL,HB_END + ;LD DE,0 + ;LD BC,$8000 + ;CALL HBX_BNKCPY + LD B,BF_SYSSETCPY ; HBIOS FUNC: SETUP BANK COPY + LD D,BID_USR ; D = DEST BANK = USER BANK + LD E,BID_USR ; E = SRC BANK = USER BANK + LD HL,$8000 ; HL = COPY LEN = ENTIRE BANK + RST 08 ; DO IT + LD B,BF_SYSBNKCPY ; HBIOS FUNC: PERFORM BANK COPY + LD HL,HB_END ; COPY FROM END OF OF HBIOS + LD DE,0 ; TO USER ADDRESS 0 + RST 08 ; DO IT +; + ; PERFORM BANK CALL TO USER BANK LD A,BID_USR ; CHAIN TO OS IMAGES BANK LD HL,0 ; ENTER AT ADDRESS 0 CALL HBX_BNKCALL ; GO THERE @@ -1101,9 +1172,11 @@ IDLE: PUSH BC PUSH DE PUSH HL + PUSH IY #IF (FDENABLE) CALL FD_IDLE #ENDIF + POP IY POP HL POP DE POP BC @@ -1148,14 +1221,14 @@ HB_DISPCALL: CALL C,PANIC ; OBSOLETE! CP BF_VDA + $10 ; $40-$4F: VIDEO DISPLAY ADAPTER JP C,VDA_DISPATCH - CP BF_SYS ; SKIP TO BF_SYS VALUE AT $F0 CALL C,PANIC ; PANIC IF LESS THAN BF_SYS JP SYS_DISPATCH ; OTHERWISE SYS CALL CALL PANIC ; THIS SHOULD NEVER BE REACHED + RET ; ;================================================================================================== -; CHARACTER I/O DEVICE DISPATCHER +; CHARACTER I/O DEVICE FUNCTION DISPATCHER ;================================================================================================== ; ; ROUTE CALL TO SPECIFIED CHARACTER I/O DRIVER @@ -1163,86 +1236,54 @@ HB_DISPCALL: ; C: UNIT NUMBER ; CIO_DISPATCH: -; -; ON ENTRY C IS HBIOS UNIT # (INDEX INTO CIO_TBL OF CHARACTER DEVICES) -; USE UNIT # IN C TO LOOKUP CIO_TBL ENTRY, THEN -; CONVERT C TO THE DEVICE/DRIVER SPECIFIC UNIT ID -; AND GET THE DEVICE TYPE TO A FOR DRIVER DISPATCHING -; + BIT 7,C ; CHECK FOR SPECIAL UNIT CODE + CALL NZ,CIO_SPECIAL ; IF SO, HANDLE IT + PUSH IY ; SAVE INCOMING IY - LD A,C ; INCOMING UNIT INDEX TO A - PUSH HL ; SAVE INCOMING HL - LD HL,CIO_CNT ; HL := ADDRESS OF TABLE ENTRY COUNT PREFIX - CP (HL) ; COMPARE TO INCOMING ENTRY INDEX - JR C,CIO_DISPATCH1 ; UNIT OK, PROCEED - CP CIODEV_CONSOLE ; CHECK FOR SPECIAL VALUE - CONSOLE OUTPUT - JR Z,CIO_DISPATCH_CON ; DO IT -; - ; NOT GOOD, INCOMING UNIT IS OUT OF RANGE - POP HL ; RESTORE HL/STACK - CALL PANIC ; PANIC - OR $FF ; SIGNAL ERROR - RET ; AND RETURN -; -CIO_DISPATCH_CON: - LD A,(CB_CONDEV) ; PUT CONSOLE UNIT NUMBER IN A - ; FALL THRU + + LD IY,CIO_TBL ; POINT IY TO START OF DIO TABLE + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE ; -CIO_DISPATCH1: +; SPECIAL HANDLING FOR DEDICATED UNIT CODES ; - ; SET HL := TABLE ENTRY ADDRESS - INC HL ; BUMP PAST COUNT PREFIX TO START OF TABLE ENTRIES - RLCA ; MULTIPLY UNIT # BY 4 TO - RLCA ; ... TO CALC ENTRY OFFSET - CALL ADDHLA ; HL := ADDRESS OF ENTRY IN TABLE +CIO_SPECIAL: + ; FOR NOW, ONLY SPECIAL CODE IS A CONSOLE REQUEST + ; SO JUST SWAP IN ACTIVE CONSOLE UNIT + LD A,(CB_CONDEV) ; GET ACTIVE CONSOLE + LD C,A ; OVERLAY UNIT CODE IN C + RET ; AND REJOIN MAIN DISPATCH FLOW ; - ; GET FIRST WORD OF TABLE ENTRY AND SAVE FOR DRIVER CALL - LD A,(HL) - LD (CIO_TGTADR+0),A - INC HL - LD A,(HL) - LD (CIO_TGTADR+1),A - INC HL +; ADD AN ENTRY TO THE CIO UNIT TABLE (SEE HB_ADDENT FOR DETAILS) ; - ; GET SECOND WORD OF TABLE ENTRY AND PUT IN IY FOR DRIVER CALL - LD A,(HL) ; GET DATA WORD - INC HL ; ... - LD H,(HL) ; ... - LD L,A ; ... INTO HL - EX (SP),HL ; RESTORE HL & MOVE BLOB ADR TO (SP) - POP IY ; BLOB ADR TO IY - - ; CALL DRIVER (ADDRESS BYTES OF CALL INSTRUCTION UPDATED ABOVE) - CALL PANIC ; CALL DRIVER DISPATCH ENTRY -CIO_TGTADR .EQU $ - 2 ; REFERENCE TO ADDRESS OF CALL INSTRUCTION - POP IY ; RESTORE ORIGINAL IY - RET ; AND RETURN +CIO_ADDENT: + LD HL,CIO_TBL ; POINT TO CIO TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE ; ; HBIOS CHARACTER DEVICE UNIT TABLE ; ; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. ; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT ; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS ; EACH ENTRY IS DEFINED AS: ; -; WORD DRIVER DISPATCH ENTRY ADDRESS +; WORD DRIVER FUNCTION TABLE ADDRESS ; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) ; -CIO_MAX .EQU 16 ; UP TO 16 UNITS -CIO_SIZ .EQU CIO_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB CIO_MAX ; MAX ENTRY COUNT TABLE PREFIX -CIO_CNT .DB 0 ; ENTRY COUNT PREFIX -CIO_TBL .FILL CIO_SIZ,0 ; SPACE FOR ENTRIES -; -; ADD AN ENTRY TO THE CIO UNIT TABLE (SEE HB_ADDENT FOR DETAILS) -; -CIO_ADDENT: - LD HL,CIO_TBL ; POINT TO CIO TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE +CIO_FNCNT .EQU 7 ; NUMBER OF CIO FUNCS (FOR RANGE CHECK) +CIO_MAX .EQU 16 ; UP TO 16 UNITS +CIO_SIZ .EQU CIO_MAX * 4 ; EACH ENTRY IS 4 BYTES +; + .DB CIO_FNCNT ; CIO FUNCTION COUNT (FOR RANGE CHECK) + .DB CIO_MAX ; MAX ENTRY COUNT TABLE PREFIX +CIO_CNT .DB 0 ; ENTRY COUNT PREFIX +CIO_TBL .FILL CIO_SIZ,0 ; SPACE FOR ENTRIES ; ;================================================================================================== -; DISK I/O DEVICE DISPATCHER +; DISK I/O DEVICE FUNCTION DISPATCHER ;================================================================================================== ; ; ROUTE CALL TO SPECIFIED DISK I/O DRIVER @@ -1269,113 +1310,40 @@ DIO_DISPATCH: ; #ENDIF ; *DEBUG* END ; -; ON ENTRY C IS HBIOS UNIT # (INDEX INTO DIO_TBL OF DISK DEVICES) -; USE UNIT # IN C TO LOOKUP DIO_TBL ENTRY. THE DIO_TBL -; ENTRY CONTAINS THE START OF THE DRIVER FUNCTION TABLE AND -; THE DEVICE SPECIFIC INSTANCE DATA (BLOB). SET IY TO BLOB ADDRESS -; AND CALL THE SPECIFIC FUNCTION REQUESTED IN THE DRIVER. -; DIO_DISPCALL: PUSH IY ; SAVE INCOMING IY - ; SETUP TO RESTORE IY AT EXIT - LD IY,DIO_DISPEXIT ; PRIME STACK WITH - PUSH IY ; ... RETURN VECTOR - - ; START WITH IY POINTING TO START OF DIO_TBL LD IY,DIO_TBL ; POINT IY TO START OF DIO TABLE - - ; CHECK INCOMING UNIT INDEX IN C FOR VAILIDITY - LD A,C ; A := INCOMING DISK UNIT INDEX - CP (IY-1) ; COMPARE TO COUNT - JR NC,DIO_DISPERR ; HANDLE INVALID UNIT INDEX - - ; CHECK FUNCTION INDEX FOR VALIDITY - LD A,B ; A := INCOMING FUNCTION NUMBER - AND $0F ; LOW NIBBLE ONLY FOR FUNC INDEX - CP DIO_FNCNT ; COMPARE TO DIO FUNCTION COUNT IN A - JR NC,DIO_DISPERR ; HANDLED INVALID FUNCTION NUMBER - - ; BUMP IY TO ACTUAL DIO_TBL ENTRY FOR INCOMING UNIT INDEX - LD B,0 ; MSB IS ALWAYS ZERO - RLC C ; MULTIPLY UNIT INDEX - RLC C ; ... BY 4 FOR TABLE ENTRY OFFSET - ADD IY,BC ; SET IY TO ENTRY ADDRESS - - ; DERIVE DRIVER FUNC ADR TO CALL - PUSH HL ; SAVE INCOMING HL - LD L,(IY+0) ; COPY DRIVER FUNC TABLE - LD H,(IY+1) ; ... START TO HL - RLCA ; CONV UNIT (STILL IN A) TO FN ADR OFFSET - CALL ADDHLA ; HL NOW HAS DRIVER FUNC TBL START ADR - LD A,(HL) ; DEREFERENCE HL - INC HL ; ... TO GET - LD H,(HL) ; ... ACTUAL - LD L,A ; ... TARGET FUNCTION ADDRESS - EX (SP),HL ; RESTORE HL, FUNC ADR ON STACK - - ; GET UNIT INSTANCE DATA BLOB ADDRESS TO IY - PUSH HL ; SAVE INCOMING HL - LD L,(IY+2) ; HL := DATA BLOB ADDRESS - LD H,(IY+3) ; ... - EX (SP),HL ; RESTORE HL, BLOB ADR ON TOS - POP IY ; IY := BLOB ADR - - RET ; JUMP TO DRIVER FUNC ADR ON TOS + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE ; -DIO_DISPEXIT: - POP IY ; RECOVER ORIGINAL INCOMING IY - RET ; AND RETURN TO CALLER +; ADD AN ENTRY TO THE DIO UNIT TABLE ; -DIO_DISPERR: - CALL PANIC ; PANIC - OR $FF ; SIGNAL ERROR - RET ; AND RETURN VIA DISPEXIT +DIO_ADDENT: + LD HL,DIO_TBL ; POINT TO DIO TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE ; ; HBIOS DISK DEVICE UNIT TABLE ; ; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. ; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT ; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF DIO FUNCTION IDS ; EACH ENTRY IS DEFINED AS: ; -; WORD DRIVER DISPATCH ENTRY ADDRESS +; WORD DRIVER FUNCTION TABLE ADDRESS ; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) ; -DIO_MAX .EQU 16 ; UP TO 16 UNITS -DIO_SIZ .EQU DIO_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB DIO_MAX ; MAX ENTRY COUNT TABLE PREFIX -DIO_CNT .DB 0 ; ENTRY COUNT PREFIX -DIO_TBL .FILL DIO_SIZ,0 ; SPACE FOR ENTRIES -; -; ADD AN ENTRY TO THE DIO UNIT TABLE -; -DIO_ADDENT: - LD HL,DIO_TBL ; POINT TO DIO TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE -; -; CONVERT AN HBIOS STANDARD HARD DISK CHS ADDRESS TO -; AN LBA ADDRESS. A STANDARD HBIOS HARD DISK IS ASSUMED -; TO HAVE 16 SECTORS PER TRACK AND 16 HEADS PER CYLINDER. -; -; INPUT: HL=TRACK, D=HEAD, E=SECTOR -; OUTPUT: DE:HL=32 BIT LBA ADDRESS (D:7 IS NOT SET IN THE RESULT) -; -HB_CHS2LBA: -; - LD A,D ; HEAD TO A - RLCA ; LEFT SHIFT TO HIGH NIBBLE - RLCA ; ... DEPENDS ON HIGH - RLCA ; ... NIBBLE BEING 0 SINCE - RLCA ; ... IT ROTATES INTO LOW NIBBLE - OR E ; COMBINE WITH SECTOR (HIGH NIBBLE MUST BE ZERO) - LD D,0 - LD E,H - LD H,L - LD L,A - XOR A - RET +DIO_FNCNT .EQU 12 ; NUMBER OF DIO FUNCS (FOR RANGE CHECK) +DIO_MAX .EQU 16 ; UP TO 16 UNITS +DIO_SIZ .EQU DIO_MAX * 4 ; EACH ENTRY IS 4 BYTES +; + .DB DIO_FNCNT ; DIO FUNCTION COUNT (FOR RANGE CHECK) + .DB DIO_MAX ; MAX ENTRY COUNT TABLE PREFIX +DIO_CNT .DB 0 ; ENTRY COUNT PREFIX +DIO_TBL .FILL DIO_SIZ,0 ; SPACE FOR ENTRIES ; ;================================================================================================== ; REAL TIME CLOCK DEVICE DISPATCHER @@ -1402,80 +1370,39 @@ RTC_DISPATCH: ; C: UNIT NUMBER ; VDA_DISPATCH: -; -; ON ENTRY C IS HBIOS UNIT # (INDEX INTO VDA_TBL OF VIDEO DEVICES) -; USE UNIT # IN C TO LOOKUP VDA_TBL ENTRY, THEN -; CONVERT C TO THE DEVICE/DRIVER SPECIFIC UNIT ID -; AND GET THE DEVICE TYPE TO A FOR DRIVER DISPATCHING -; PUSH IY ; SAVE INCOMING IY - LD A,C ; INCOMING UNIT INDEX TO A - PUSH HL ; SAVE INCOMING HL - LD HL,VDA_CNT ; HL := ADDRESS OF TABLE ENTRY COUNT - CP (HL) ; COMPARE TO INCOMING ENTRY INDEX - JR C,VDA_DISPATCH1 ; UNIT OK, PROCEED -; - ; NOT GOOD, INCOMING UNIT IS OUT OF RANGE - POP HL ; RESTORE HL/STACK - CALL PANIC ; PANIC - OR $FF ; SIGNAL ERROR - RET ; AND RETURN -; -VDA_DISPATCH1: + + LD IY,VDA_TBL ; POINT IY TO START OF DIO TABLE + CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE + + POP IY ; RESTORE IY + RET ; AND DONE ; - ; SET HL := TABLE ENTRY ADDRESS - INC HL ; BUMP PAST COUNT PREFIX TO START OF TABLE ENTRIES - RLCA ; MULTIPLY UNIT # BY 4 TO - RLCA ; ... TO CALC ENTRY OFFSET - CALL ADDHLA ; HL := ADDRESS OF ENTRY IN TABLE +; ADD AN ENTRY TO THE VDA UNIT TABLE (SEE HB_ADDENT FOR DETAILS) ; - ; GET FIRST WORD OF TABLE ENTRY AND SAVE FOR DRIVER CALL - LD A,(HL) ; DEREFERENCE - INC HL ; ... - PUSH HL ; SAVE IT FOR BELOW - LD H,(HL) ; ... - LD L,A ; ... SO HL HAS ADDRESS OF DRIVER DISPATCH - LD (VDA_TGTADR),HL ; SAVE THE TARGET ADDRESS TO CALL LATER -; - ; GET SECOND WORD OF TABLE ENTRY AND PUT IN IY FOR DRIVER CALL - POP HL ; GET TABLE ENTRY ADDRESS BACK - INC HL ; INCREMENT TO DATA WORD - LD A,(HL) ; GET DATA WORD - INC HL ; ... - LD H,(HL) ; ... - LD L,A ; ... INTO HL - PUSH HL ; AND COPY IT - POP IY ; ... TO IY -; - ; CALL DRIVER (ADDRESS BYTES OF CALL INSTRUCTION UPDATED ABOVE) - POP HL ; GET ORIGINAL HL BACK (10) - CALL PANIC ; CALL DRIVER DISPATCH ENTRY -VDA_TGTADR .EQU $ - 2 ; REFERENCE TO ADDRESS OF CALL INSTRUCTION - POP IY ; RESTORE ORIGINAL IY - RET ; AND RETURN +VDA_ADDENT: + LD HL,VDA_TBL ; POINT TO VDA TABLE + JP HB_ADDENT ; ... AND GO TO COMMON CODE ; ; HBIOS VIDEO DEVICE UNIT TABLE ; ; TABLE IS BUILT DYNAMICALLY BY EACH DRIVER DURING INITIALIZATION. ; THE TABLE IS PREFIXED BY TWO BYTES. TABLE - 1 CONTAINS THE CURRENT ; NUMBER OF ENTRIES. TABLE - 2 CONTAINS THE MAXIMUM NUMBER OF ENTRIES. +; TABLE - 3 CONTAINS THE NUMBER OF CIO FUNCTION IDS ; EACH ENTRY IS DEFINED AS: ; -; WORD DRIVER DISPATCH ADDRESS -; WORD UNIT DATA ADDRESS -; -VDA_MAX .EQU 16 ; UP TO 16 UNITS -VDA_SIZ .EQU VDA_MAX * 4 ; EACH ENTRY IS 4 BYTES -; - .DB VDA_MAX ; MAX ENTRY COUNT TABLE PREFIX -VDA_CNT .DB 0 ; ENTRY COUNT PREFIX -VDA_TBL .FILL VDA_SIZ,0 ; SPACE FOR ENTRIES +; WORD DRIVER FUNCTION TABLE ADDRESS +; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) ; -; ADD AN ENTRY TO THE VDA UNIT TABLE (SEE HB_ADDENT FOR DETAILS) +VDA_FNCNT .EQU 15 ; NUMBER OF VDA FUNCS (FOR RANGE CHECK) +VDA_MAX .EQU 16 ; UP TO 16 UNITS +VDA_SIZ .EQU VDA_MAX * 4 ; EACH ENTRY IS 4 BYTES ; -VDA_ADDENT: - LD HL,VDA_TBL ; POINT TO VDA TABLE - JP HB_ADDENT ; ... AND GO TO COMMON CODE + .DB VDA_FNCNT ; VDA FUNCTION COUNT (FOR RANGE CHECK) + .DB VDA_MAX ; MAX ENTRY COUNT TABLE PREFIX +VDA_CNT .DB 0 ; ENTRY COUNT PREFIX +VDA_TBL .FILL VDA_SIZ,0 ; SPACE FOR ENTRIES ; ;================================================================================================== ; SYSTEM FUNCTION DISPATCHER @@ -1511,6 +1438,27 @@ SYS_DISPATCH: JP Z,SYS_POKE ; $FB CALL PANIC ; INVALID ; +; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS +; +SYS_RESET: + LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD + LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP + XOR A + RET +; +; GET THE CURRENT HBIOS VERSION +; ON INPUT, C=0 +; RETURNS VERSION IN DE AS BCD +; D: MAJOR VERION IN TOP 4 BITS, MINOR VERSION IN LOW 4 BITS +; E: UPDATE VERION IN TOP 4 BITS, PATCH VERSION IN LOW 4 BITS +; L: PLATFORM ID +; +SYS_VER: + LD DE,0 | (RMJ << 12) | (RMN << 8) | (RUP << 4) | RTP + LD L,PLATFORM + XOR A + RET +; ; SET ACTIVE MEMORY BANK AND RETURN PREVIOUSLY ACTIVE MEMORY BANK ; NOTE THAT IT GOES INTO EFFECT AS HBIOS FUNCTION IS EXITED ; HERE, WE JUST SET THE CURRENT BANK @@ -1558,7 +1506,13 @@ SYS_BNKCPY: LD HL,(HB_CPYLEN) ; HL := COPY LEN (SAVED IN SETCPY) EX (SP),HL ; RESTORE HL & SET (SP) TO COPY LEN POP BC ; BC := COPY LEN +#IF (INTMODE == 1) + DI +#ENDIF CALL HB_BNKCPY +#IF (INTMODE == 1) + EI +#ENDIF XOR A RET ; @@ -1582,19 +1536,6 @@ SYS_FREE: OR $FF RET ; -; GET THE CURRENT HBIOS VERSION -; ON INPUT, C=0 -; RETURNS VERSION IN DE AS BCD -; D: MAJOR VERION IN TOP 4 BITS, MINOR VERSION IN LOW 4 BITS -; E: UPDATE VERION IN TOP 4 BITS, PATCH VERSION IN LOW 4 BITS -; L: PLATFORM ID -; -SYS_VER: - LD DE,0 | (RMJ << 12) | (RMN << 8) | (RUP << 4) | RTP - LD L,PLATFORM - XOR A - RET -; ; GET SYSTEM INFORMATION ; ITEM TO RETURN INDICATED IN C ; @@ -1606,6 +1547,8 @@ SYS_GET: JR Z,SYS_GETDIOCNT CP BF_SYSGET_VDACNT JR Z,SYS_GETVDACNT + CP BF_SYSGET_TIMER + JR Z,SYS_GETTIMER CP BF_SYSGET_BOOTINFO JR Z,SYS_GETBOOTINFO CP BF_SYSGET_CPUINFO @@ -1617,6 +1560,18 @@ SYS_GET: OR $FF ; SIGNAL ERROR RET ; +; GET TIMER +; RETURNS: +; DE:HL: TIMER VALUE (32 BIT) +; +SYS_GETTIMER: + LD HL,HB_TICKS + HB_DI + CALL LD32 + HB_EI + XOR A + RET +; ; GET BOOT INFORMATION ; RETURNS: ; L: BOOT BANK ID @@ -1696,6 +1651,8 @@ SYS_GETVDACNT: ; SYS_SET: LD A,C ; GET REQUESTED SUB-FUNCTION + CP BF_SYSSET_TIMER + JR Z,SYS_SETTIMER CP BF_SYSSET_BOOTINFO JR Z,SYS_SETBOOTINFO OR $FF ; SIGNAL ERROR @@ -1713,12 +1670,30 @@ SYS_SETBOOTINFO: XOR A RET ; +; SET TIMER +; ON ENTRY: +; DE:HL: TIMER VALUE (32 BIT) +; +SYS_SETTIMER: + LD BC,HB_TICKS + HB_DI + CALL ST32 + HB_EI + XOR A + RET +; ; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK ; ENTRY: D=BANK ID, HL=ADDRESS ; RETURN: E=BYTE VALUE ; SYS_PEEK: +#IF (INTMODE == 1) + DI +#ENDIF CALL HBX_PEEK ; IMPLEMENTED IN PROXY +#IF (INTMODE == 1) + EI +#ENDIF XOR A RET ; @@ -1726,15 +1701,13 @@ SYS_PEEK: ; ENTRY: D=BANK ID, HL=ADDRESS IN HBIOS BANK, E=BYTE VALUE ; SYS_POKE: +#IF (INTMODE == 1) + DI +#ENDIF CALL HBX_POKE ; IMPLEMENTED IN PROXY - XOR A - RET -; -; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS -; -SYS_RESET: - LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD - LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP +#IF (INTMODE == 1) + EI +#ENDIF XOR A RET ; @@ -1754,6 +1727,8 @@ CIO_IDLE: POP AF ; RECOVER AF RET ; +#IF (INTMODE == 1) +; ; IM1 INTERRUPTS ARRIVE HERE AFTER BANK SWITCH TO HBIOS BANK ; LIST OF IM1 INT CALLS IS BUILT DYNAMICALLY BELOW ; SEE HB_ADDIM1 ROUTINE @@ -1762,6 +1737,7 @@ CIO_IDLE: ; RET NZ ; RETURN IF HANDLED ; HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER + JP HB_BADINT RET ; START WITH NO ENTRIES .FILL 4 * 8,$C9 ; ROOM FOR 8 ENTRIES ; @@ -1783,7 +1759,9 @@ HB_ADDIM1: LD (HB_IM1P),HL ; SAVE POINTER RET ; DONE ; -HB_IM1P .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY +HB_IM1P .DW HB_IM1INT ; POINTER FOR NEXT IM1 ENTRY +; +#ENDIF ; ; TIMER INTERRUPT ; @@ -1820,12 +1798,13 @@ TEMPCNT .DB 250 ; HB_TIMINT2: ; -#IF (INTTYPE == IT_Z180) - ; ACK/RESET INTERRUPT +#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) + ; ACK/RESET Z180 TIMER INTERRUPT IN0 A,(Z180_TCR) IN0 A,(Z180_TMDR0L) #ENDIF ; + OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; ; BAD INTERRUPT HANDLER @@ -1837,10 +1816,62 @@ HB_BADINT: CALL CONTINUE RET ; +; COMMON API FUNCTION DISPATCH CODE +; +; ON ENTRY C IS UNIT # (INDEX INTO XXX_TBL OF UNITS) +; AND IY POINTS TO START OF UNIT TABLE. +; USE UNIT # IN C TO LOOKUP XXX_TBL ENTRY. THE XXX_TBL +; ENTRY CONTAINS THE START OF THE DRIVER FUNCTION TABLE AND +; THE DEVICE SPECIFIC INSTANCE DATA (BLOB). SET IY TO BLOB ADDRESS +; AND CALL THE SPECIFIC FUNCTION REQUESTED IN THE DRIVER. +; +HB_DISPCALL: + ; CHECK INCOMING UNIT INDEX IN C FOR VAILIDITY + LD A,C ; A := INCOMING DISK UNIT INDEX + CP (IY-1) ; COMPARE TO COUNT + JR NC,HB_DISPERR ; HANDLE INVALID UNIT INDEX + + ; CHECK FUNCTION INDEX FOR VALIDITY + LD A,B ; A := INCOMING FUNCTION NUMBER + AND $0F ; LOW NIBBLE ONLY FOR FUNC INDEX + CP (IY-3) ; CHECK FN NUM AGAINST MAX + JR NC,HB_DISPERR ; HANDLE FN NUM OUT OF RANGE ERROR + + ; BUMP IY TO ACTUAL XXX_TBL ENTRY FOR INCOMING UNIT INDEX + LD B,0 ; MSB IS ALWAYS ZERO + RLC C ; MULTIPLY UNIT INDEX + RLC C ; ... BY 4 FOR TABLE ENTRY OFFSET + ADD IY,BC ; SET IY TO ENTRY ADDRESS + + ; DERIVE DRIVER FUNC ADR TO CALL + PUSH HL ; SAVE INCOMING HL + LD L,(IY+0) ; COPY DRIVER FUNC TABLE + LD H,(IY+1) ; ... START TO HL + RLCA ; CONV UNIT (STILL IN A) TO FN ADR OFFSET + CALL ADDHLA ; HL NOW HAS DRIVER FUNC TBL START ADR + LD A,(HL) ; DEREFERENCE HL + INC HL ; ... TO GET + LD H,(HL) ; ... ACTUAL + LD L,A ; ... TARGET FUNCTION ADDRESS + EX (SP),HL ; RESTORE HL, FUNC ADR ON STACK + + ; GET UNIT INSTANCE DATA BLOB ADDRESS TO IY + PUSH HL ; SAVE INCOMING HL + LD L,(IY+2) ; HL := DATA BLOB ADDRESS + LD H,(IY+3) ; ... + EX (SP),HL ; RESTORE HL, BLOB ADR ON TOS + POP IY ; IY := BLOB ADR + + RET ; JUMP TO DRIVER FUNC ADR ON TOS +; +HB_DISPERR: + CALL PANIC ; PANIC + OR $FF ; SIGNAL ERROR + RET ; AND RETURN VIA DISPEXIT +; ; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL -; C: DEVICE TYPE ID -; B: UNIT INDEX -; DE: ADDRESS OF UNIT DATA +; BC: DRIVER FUNCTION TABLE +; DE: ADDRESS OF UNIT INSTANCE DATA ; RETURN ; A: UNIT NUMBER ASSIGNED ; @@ -1863,7 +1894,7 @@ HB_ADDENT: EX (SP),HL ; ... AND DISPATCH ADDRESS TO HL POP BC ; ... SO THAT DE:HL HAS 32 BIT ENTRY CALL ST32 ; LD (BC),DE:HL STORES THE ENTRY - POP AF ; RETURN ENTRY INDEX + POP AF ; RETURN ENTRY INDEX (UNIT NUMBER ASSIGNED) RET ; ; ALLOCATE HL BYTES OF MEMORY ON THE HEAP @@ -2410,7 +2441,7 @@ PS_DISK: PRTS("Disk $") LD A,C ; MOVE UNIT NUM TO A CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN + PRTS(" $") ; PAD TO NEXT COLUMN ; ; DEVICE COLUMN LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C @@ -2562,7 +2593,7 @@ PS_SERIAL: ; ; DEVICE COLUMN LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, C:=DISK ATTRIBUTES + RST 08 ; DE:=DEVTYP/NUM, C:=DEVICE ATTRIBUTES PUSH BC ; SAVE ATTRIBUTES LD HL,PS_SDSTRREF ; POINT TO SERIAL DEVICE TYPE NAME TABLE CALL PS_PRTDEV ; PRINT SERIAL DEVICE NMEMONIC PADDED TO FIELD WIDTH @@ -2570,7 +2601,7 @@ PS_SERIAL: PUSH BC ; SAVE ATTRIBUTES AGAIN CALL PS_PRTST ; PRINT SERIAL TYPE POP BC ; RESTORE ATTRIBUTES - POP DE ; RESTORE UNIT NUM + POP DE ; RESTORE UNIT NUM TO E CALL PS_PRTSC ; PRINT SERIAL CONFIG ; CALL NEWLINE @@ -2591,7 +2622,7 @@ PS_PRTST1: CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) RET ; -; PRINT SERIAL CONFIG (UNIT IN C, ATTRIBUTE IN E) +; PRINT SERIAL CONFIG (UNIT IN E, ATTRIBUTE IN C) ; PS_PRTSC: BIT 7,C ; 0=RS-232, 1=TERMINAL @@ -2599,6 +2630,7 @@ PS_PRTSC: ; ; PRINT RS-232 CONFIG LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG + LD C,E ; SET SERIAL UNIT NUM RST 08 ; DE:HL := BAUD RATE LD A,D ; TEST FOR $FF AND E @@ -2685,7 +2717,7 @@ PS_VIDEO: PRTS("Video $") LD A,C ; MOVE UNIT NUM TO A CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN + PRTS(" $") ; PAD TO NEXT COLUMN ; ; DEVICE COLUMN LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C @@ -2880,8 +2912,8 @@ PS_VTCRT .TEXT "CRT$" ; ; 0 1 2 3 4 5 6 7 ; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 -PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" - .TEXT "---------- ---------- ---------------- --------------------\r\n$" +PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" + .TEXT "---------- ---------- ---------------- --------------------\r\n$" ; ;================================================================================================== ; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED) @@ -2997,6 +3029,28 @@ LDHLIYA: INC H ; IF CF SET, BUMP MSB RET ; ... AND RETURN ; +; CONVERT AN HBIOS STANDARD HARD DISK CHS ADDRESS TO +; AN LBA ADDRESS. A STANDARD HBIOS HARD DISK IS ASSUMED +; TO HAVE 16 SECTORS PER TRACK AND 16 HEADS PER CYLINDER. +; +; INPUT: HL=TRACK, D=HEAD, E=SECTOR +; OUTPUT: DE:HL=32 BIT LBA ADDRESS (D:7 IS NOT SET IN THE RESULT) +; +HB_CHS2LBA: +; + LD A,D ; HEAD TO A + RLCA ; LEFT SHIFT TO HIGH NIBBLE + RLCA ; ... DEPENDS ON HIGH + RLCA ; ... NIBBLE BEING 0 SINCE + RLCA ; ... IT ROTATES INTO LOW NIBBLE + OR E ; COMBINE WITH SECTOR (HIGH NIBBLE MUST BE ZERO) + LD D,0 + LD E,H + LD H,L + LD L,A + XOR A + RET +; ;================================================================================================== ; HBIOS GLOBAL DATA ;================================================================================================== @@ -3010,6 +3064,7 @@ HB_TICKS .FILL 4,0 ; 32 BIT TICK COUNTER STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$" STR_PLATFORM .DB PLATFORM_NAME, "$" STR_SWITCH .DB "*** Activating CRT Console ***$" +STR_BADINT .DB "\r\n*** BAD INT ***\r\n$" ; HB_CURSEC .DB 0 ; CURRENT SECOND (TEMP) ; diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index f68e170d..9e565e6f 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -69,11 +69,13 @@ BF_SYSPOKE .EQU BF_SYS + 11 ; SET A BYTE VALUE IN ALT BANK BF_SYSGET_CIOCNT .EQU $00 ; GET CHAR UNIT COUNT BF_SYSGET_DIOCNT .EQU $10 ; GET DISK UNIT COUNT BF_SYSGET_VDACNT .EQU $40 ; GET VDA UNIT COUNT +BF_SYSGET_TIMER .EQU $D0 ; GET CURRENT TIMER VALUE BF_SYSGET_BOOTINFO .EQU $E0 ; GET BOOT INFORMATION BF_SYSGET_CPUINFO .EQU $F0 ; GET CPU INFORMATION BF_SYSGET_MEMINFO .EQU $F1 ; GET MEMORY CAPACTITY INFO BF_SYSGET_BNKINFO .EQU $F2 ; GET BANK ASSIGNMENT INFO ; +BF_SYSSET_TIMER .EQU $D0 ; SET TIMER VALUE BF_SYSSET_BOOTINFO .EQU $E0 ; SET BOOT INFORMATION ; ; SERIAL DEVICE IDS diff --git a/Source/HBIOS/ppp.asm b/Source/HBIOS/ppp.asm index 5d2e595c..ec4782a6 100644 --- a/Source/HBIOS/ppp.asm +++ b/Source/HBIOS/ppp.asm @@ -247,43 +247,48 @@ PPP_FWVER .DB $00, $00, $00, $00 ; MMNNBBB (M=MAJOR, N=MINOR, B=BUILD) ; PARPORTPROP CONSOLE DRIVER ;================================================================================================== ; +PPPCON_ROWS .EQU 37 ; PROPELLER VGA DISPLAY ROWS (40 - 3 STATUS LINES) +PPPCON_COLS .EQU 80 ; PROPELLER VGA DISPLAY COLS +; PPPCON_INIT: CALL NEWLINE PRTS("PPPCON:$") +; + ; DISPLAY CONSOLE DIMENSIONS + CALL PC_SPACE + LD A,PPPCON_COLS + CALL PRTDECB + LD A,'X' + CALL COUT + LD A,PPPCON_ROWS + CALL PRTDECB + CALL PRTSTRD + .TEXT " TEXT (ANSI)$" ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; - ;LD B,0 ; PHYSICAL UNIT IS ZERO - ;LD C,CIODEV_PPPCON ; DEVICE TYPE - ;LD DE,0 ; UNIT DATA BLOB ADDRESS LD D,0 ; PHYSICAL UNIT IS ZERO LD E,CIODEV_PPPCON ; DEVICE TYPE - LD BC,PPPCON_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,PPPCON_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED LD (HCB + HCB_CRTDEV),A ; SET OURSELVES AS THE CRT DEVICE ; XOR A RET ; -; DISPATCH FOR CONSOLE SUBFUNCTIONS -; -PPPCON_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JR Z,PPPCON_IN ; JUMP IF CHARACTER IN - DEC A ; NEXT SUBFUNCTION - JR Z,PPPCON_OUT ; JUMP IF CHARACTER OUT - DEC A ; NEXT SUBFUCNTION - JR Z,PPPCON_IST ; JUMP IF INPUT STATUS - DEC A ; NEXT SUBFUNCTION - JR Z,PPPCON_OST ; JUMP IF OUTPUT STATUS - DEC A ; NEXT SUBFUNCTION - JR Z,PPPCON_INITDEV ; JUMP IF INIT DEVICE - DEC A ; NEXT SUBFUNCTION - JR Z,PPPCON_QUERY ; JUMP IF QUERY - DEC A ; NEXT SUBFUNCTION - JR Z,PPPCON_DEVICE ; JUMP IF DEVICE REPORT - CALL PANIC ; OTHERWISE SOMETHING IS BADLY BROKEN +; DRIVER FUNCTION TABLE +; +PPPCON_FNTBL: + .DW PPPCON_IN + .DW PPPCON_OUT + .DW PPPCON_IST + .DW PPPCON_OST + .DW PPPCON_INITDEV + .DW PPPCON_QUERY + .DW PPPCON_DEVICE +#IF (($ - PPPCON_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PPPCON FUNCTION TABLE ***\n" +#ENDIF ; ; CHARACTER INPUT ; WAIT FOR A CHARACTER AND RETURN IT IN E diff --git a/Source/HBIOS/prp.asm b/Source/HBIOS/prp.asm index 57c159d5..9444eafd 100644 --- a/Source/HBIOS/prp.asm +++ b/Source/HBIOS/prp.asm @@ -118,46 +118,51 @@ PRPCON_ERR .EQU $40 ; BIT SET WHEN PROPIO CONSOLE ERROR HAS OCCURRED PRPCON_KBDRDY .EQU $20 ; BIT SET WHEN KEYBOARD BUF HAS A BYTE READY (BUF FULL) PRPCON_DSPRDY .EQU $10 ; BIT SET WHEN DISPLAY BUF IS READY FOR A BYTE (BUF EMPTY) ; +PRPCON_ROWS .EQU 37 ; PROPELLER VGA DISPLAY ROWS (40 - 3 STATUS LINES) +PRPCON_COLS .EQU 80 ; PROPELLER VGA DISPLAY COLS +; ; ; PRPCON_INIT: ; CALL NEWLINE - PRTS("PRPCON:$") + PRTS("PRPCON: $") +; + ; DISPLAY CONSOLE DIMENSIONS + CALL PC_SPACE + LD A,PRPCON_COLS + CALL PRTDECB + LD A,'X' + CALL COUT + LD A,PRPCON_ROWS + CALL PRTDECB + CALL PRTSTRD + .TEXT " TEXT (ANSI)$" ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; - ;LD B,0 ; PHYSICAL UNIT IS ZERO - ;LD C,CIODEV_PRPCON ; DEVICE TYPE - ;LD DE,0 ; UNIT DATA BLOB ADDRESS LD D,0 ; PHYSICAL UNIT IS ZERO LD E,CIODEV_PRPCON ; DEVICE TYPE - LD BC,PRPCON_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,PRPCON_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED LD (HCB + HCB_CRTDEV),A ; SET OURSELVES AS THE CRT DEVICE ; XOR A ; SIGNAL SUCCESS RET ; -; -; -PRPCON_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JR Z,PRPCON_IN - DEC A - JR Z,PRPCON_OUT - DEC A - JR Z,PRPCON_IST - DEC A - JR Z,PRPCON_OST - DEC A - JR Z,PRPCON_INITDEV - DEC A - JR Z,PRPCON_QUERY - DEC A - JR Z,PRPCON_DEVICE - CALL PANIC +; DRIVER FUNCTION TABLE +; +PRPCON_FNTBL: + .DW PRPCON_IN + .DW PRPCON_OUT + .DW PRPCON_IST + .DW PRPCON_OST + .DW PRPCON_INITDEV + .DW PRPCON_QUERY + .DW PRPCON_DEVICE +#IF (($ - PRPCON_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID PRPCON FUNCTION TABLE ***\n" +#ENDIF ; ; ; diff --git a/Source/HBIOS/romldr.asm b/Source/HBIOS/romldr.asm index b2f368cf..c2a0fdc5 100644 --- a/Source/HBIOS/romldr.asm +++ b/Source/HBIOS/romldr.asm @@ -11,7 +11,7 @@ MONIMG .EQU $1000 CPMIMG .EQU $2000 ZSYSIMG .EQU $5000 ; -INT_IM1 .EQU $FF20 +INT_IM1 .EQU $FF00 ; .ORG 0 ; @@ -38,9 +38,13 @@ INT_IM1 .EQU $FF20 RET ; RST 30 .FILL (038H - $),0FFH #IF (PLATFORM == PLT_UNA) - RETI ; INT + RETI ; RETURN W/ INTS DISABLED #ELSE - JP INT_IM1 ; GO TO HBIOS IM1 INT HANDLER + #IF (INTMODE == 1) + JP INT_IM1 ; JP TO INTERRUPT HANDLER IN HI MEM + #ELSE + RETI ; RETURN W/ INTS DISABLED + #ENDIF #ENDIF .FILL (066H - $),0FFH RETN ; NMI diff --git a/Source/HBIOS/sio.asm b/Source/HBIOS/sio.asm index 6d424e3f..842b54b7 100644 --- a/Source/HBIOS/sio.asm +++ b/Source/HBIOS/sio.asm @@ -59,7 +59,7 @@ SIO_PREINIT0: JR Z,SIO_PREINIT2 ; SKIP IT IF NOTHING FOUND ; PUSH BC ; SAVE LOOP CONTROL - LD BC,SIO_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,SIO_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL NZ,CIO_ADDENT ; ADD ENTRY IF SIO FOUND, BC:DE POP BC ; RESTORE LOOP CONTROL ; @@ -67,12 +67,20 @@ SIO_PREINIT2: INC C ; NEXT PHYSICAL UNIT DJNZ SIO_PREINIT0 ; LOOP UNTIL DONE ; +#IF (INTMODE == 1) ; ADD IM1 INT CALL LIST ENTRY IF APPROPRIATE LD A,(SIO_DEV) ; GET NEXT DEVICE NUM OR A ; SET FLAGS JR Z,SIO_PREINIT3 ; IF ZERO, NO SIO DEVICES LD HL,SIO_INT ; GET INT VECTOR CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST +#ENDIF +; +#IF (INTMODE == 2) + ; SETUP SIO INTERRUPT VECTOR IN IVT + LD HL,INT_SIO + LD (HBX_IVT + IVT_SER0),HL +#ENDIF ; SIO_PREINIT3: XOR A ; SIGNAL SUCCESS @@ -215,24 +223,9 @@ SIOB_INT1: OR $FF ; NZ SET TO INDICATE INT HANDLED RET ; AND RETURN ; +; DRIVER FUNCTION TABLE ; -; -SIO_DISPATCH: - ; DISPATCH TO FUNCTION HANDLER - PUSH HL ; SAVE HL FOR NOW - LD A,B ; GET FUNCTION - AND $0F ; ISOLATE LOW NIBBLE - RLCA ; X 2 FOR WORD OFFSET INTO FUNCTION TABLE - LD HL,SIO_FTBL ; START OF FUNC TABLE - CALL ADDHLA ; HL := ADDRESS OF ADDRESS OF FUNCTION - LD A,(HL) ; DEREF HL - INC HL ; ... - LD H,(HL) ; ... - LD L,A ; ... TO GET ADDRESS OF FUNCTION - EX (SP),HL ; RESTORE HL & PUT FUNC ADDRESS -> (SP) - RET ; EFFECTIVELY A JP TO TGT ADDRESS - -SIO_FTBL: +SIO_FNTBL: .DW SIO_IN .DW SIO_OUT .DW SIO_IST @@ -240,6 +233,9 @@ SIO_FTBL: .DW SIO_INITDEV .DW SIO_QUERY .DW SIO_DEVICE +#IF (($ - SIO_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID SIO FUNCTION TABLE ***\n" +#ENDIF ; ; ; @@ -255,7 +251,7 @@ SIO_IN: SIOA_IN: CALL SIOA_IST ; RECEIVED CHAR READY? JR Z,SIOA_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER - DI ; AVOID COLLISION WITH INT HANDLER + HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(SIOA_CNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (SIOA_CNT),A ; SAVE SAVE IT @@ -275,14 +271,14 @@ SIOA_IN0: LD HL,SIOA_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOA_IN1: LD (SIOA_TL),HL ; SAVE UPDATED TAIL POINTER - EI ; INTERRUPTS OK AGAIN + HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; SIOB_IN: CALL SIOB_IST ; RECEIVED CHAR READY? JR Z,SIOB_IN ; LOOP TILL WE HAVE SOMETHING IN BUFFER - DI ; AVOID COLLISION WITH INT HANDLER + HB_DI ; AVOID COLLISION WITH INT HANDLER LD A,(SIOB_CNT) ; GET COUNT DEC A ; DECREMENT COUNT LD (SIOB_CNT),A ; SAVE SAVE IT @@ -302,7 +298,7 @@ SIOB_IN0: LD HL,SIOB_BUF ; ... OTHERWISE, RESET TO START OF BUFFER SIOB_IN1: LD (SIOB_TL),HL ; SAVE UPDATED TAIL POINTER - EI ; INTERRUPTS OK AGAIN + HB_EI ; INTERRUPTS OK AGAIN XOR A ; SIGNAL SUCCESS RET ; AND DONE ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index a4c1095f..62827ef0 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -35,11 +35,6 @@ PLT_MK4 .EQU 5 ; MARK IV PLT_UNA .EQU 6 ; UNA BIOS PLT_RC .EQU 7 ; RC2014 ; -; FOUNCTION GROUP FUNCTION COUNTS -; -CIO_FNCNT .EQU 7 -DIO_FNCNT .EQU 12 -; #IF (PLATFORM != PLT_UNA) #INCLUDE "hbios.inc" #ENDIF @@ -173,14 +168,6 @@ SER_115200_8N1 .EQU SER_BAUD115200 | SER_DATA8 | SER_PARNONE | SER_STOP1 SER_230400_8N1 .EQU SER_BAUD230400 | SER_DATA8 | SER_PARNONE | SER_STOP1 SER_460800_8N1 .EQU SER_BAUD460800 | SER_DATA8 | SER_PARNONE | SER_STOP1 ; -; INTERRUPT TYPE OPTIONS -; -IT_NONE .EQU 0 -IT_SIMH .EQU 1 -IT_Z180 .EQU 2 -IT_CTC .EQU 3 -IT_RC .EQU 4 -; ; INTERRUPT VECTOR TABLE ENTRY OFFSETS (Z180 COMPATIBLE) ; IVT_INT1 .EQU 0 diff --git a/Source/HBIOS/term.asm b/Source/HBIOS/term.asm index 9214924b..40931e47 100644 --- a/Source/HBIOS/term.asm +++ b/Source/HBIOS/term.asm @@ -37,20 +37,20 @@ TERM_ATTACH: LD B,A ; PUT IT IN B PUSH HL ; SAVE VDA INSTANCE DATA PTR ; - ; SETUP EMULATOR MODULE DISPATCH ADDRESS BASED ON DESIRED EMULATION - ; EMULATOR PASSES BACK IT'S DISPATCH ADDRESS IN DE + ; SETUP EMULATOR MODULE FUNC TBL ADDRESS BASED ON DESIRED EMULATION + ; EMULATOR PASSES BACK IT'S FUNC TBL ADDRESS IN DE OR $FF ; PRESET FAILURE #IF (VDAEMU == EMUTYP_TTY) - CALL TTY_INIT ; INIT TTY, DE := TTY_DISPATCH + CALL TTY_INIT ; INIT TTY, DE := TTY_FNTBL #ENDIF #IF (VDAEMU == EMUTYP_ANSI) - CALL ANSI_INIT ; INIT ANSI, DE := ANSI_DISPATCH + CALL ANSI_INIT ; INIT ANSI, DE := ANSI_FNTBL #ENDIF POP HL ; RECOVER VDA INSTANCE DATA PTR RET NZ ; BAIL OUT ON ERROR ; ; ADD OURSELVES TO CIO DISPATCH TABLE - PUSH DE ; COPY EMULATOR DISPATCH ADDRESS + PUSH DE ; COPY EMULATOR FUNC TBL ADDRESS POP BC ; ... TO BC PUSH HL ; COPY VDA INSTANCE DATA PTR POP DE ; ... TO DE @@ -68,7 +68,7 @@ TERM_ATTACH: ; TERMINAL DRIVER PRIVATE DATA ;====================================================================== ; -TERM_DEVCNT .DB 0 ; TERMINAL DEVICE COUNT +TERM_DEVCNT .DB 0 ; TERMINAL DEVICE COUNT ; ;====================================================================== ; EMULATION MODULES diff --git a/Source/HBIOS/tms.asm b/Source/HBIOS/tms.asm index e29533a3..49d317b7 100644 --- a/Source/HBIOS/tms.asm +++ b/Source/HBIOS/tms.asm @@ -88,13 +88,13 @@ TMS_INIT1: #ENDIF ; ; ADD OURSELVES TO VDA DISPATCH TABLE - LD BC,TMS_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,TMS_FNTBL ; BC := FUNCTION TABLE ADDRESS LD DE,TMS_IDAT ; DE := TMS INSTANCE DATA PTR CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; ; INITIALIZE EMULATION LD C,A ; C := ASSIGNED VIDEO DEVICE NUM - LD DE,TMS_DISPATCH ; DE := DISPATCH ADDRESS + LD DE,TMS_FNTBL ; DE := FUNCTION TABLE ADDRESS LD HL,TMS_IDAT ; HL := TMS INSTANCE DATA PTR CALL TERM_ATTACH ; DO IT ; @@ -102,59 +102,34 @@ TMS_INIT1: RET ; ;====================================================================== -; TMS DRIVER - CHARACTER I/O (CIO) DISPATCHER AND FUNCTIONS +; TMS DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS ;====================================================================== ; -TMS_DISPCIO: - JP PANIC -TMS_CIODISPADR .EQU $ - 2 -; -;====================================================================== -; TMS DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS -;====================================================================== -; -TMS_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - - JP Z,TMS_VDAINI ; $40 - DEC A - JP Z,TMS_VDAQRY ; $41 - DEC A - JP Z,TMS_VDARES ; $42 - DEC A - JP Z,TMS_VDADEV ; $43 - DEC A - JP Z,TMS_VDASCS ; $44 - DEC A - JP Z,TMS_VDASCP ; $45 - DEC A - JP Z,TMS_VDASAT ; $46 - DEC A - JP Z,TMS_VDASCO ; $47 - DEC A - JP Z,TMS_VDAWRC ; $48 - DEC A - JP Z,TMS_VDAFIL ; $49 - DEC A - JP Z,TMS_VDACPY ; $4A - DEC A - JP Z,TMS_VDASCR ; $4B - DEC A +TMS_FNTBL: + .DW TMS_VDAINI + .DW TMS_VDAQRY + .DW TMS_VDARES + .DW TMS_VDADEV + .DW TMS_VDASCS + .DW TMS_VDASCP + .DW TMS_VDASAT + .DW TMS_VDASCO + .DW TMS_VDAWRC + .DW TMS_VDAFIL + .DW TMS_VDACPY + .DW TMS_VDASCR #IF (PLATFORM == PLT_N8) - JP Z,PPK_STAT ; $4C - DEC A - JP Z,PPK_FLUSH ; $4D - DEC A - JP Z,PPK_READ ; $4E + .DW PPK_STAT + .DW PPK_FLUSH + .DW PPK_READ #ELSE - JP Z,TMS_STAT ; $4C - DEC A - JP Z,TMS_FLUSH ; $4D - DEC A - JP Z,TMS_READ ; $4E + .DW TMS_STAT + .DW TMS_FLUSH + .DW TMS_READ +#ENDIF +#IF (($ - TMS_FNTBL) != (VDA_FNCNT * 2)) + .ECHO "*** INVALID TMS FUNCTION TABLE ***\n" #ENDIF - CALL PANIC TMS_VDAINI: ; RESET VDA diff --git a/Source/HBIOS/tty.asm b/Source/HBIOS/tty.asm index 47eda688..8571af88 100644 --- a/Source/HBIOS/tty.asm +++ b/Source/HBIOS/tty.asm @@ -11,7 +11,7 @@ ; C: CIO UNIT NUMBER OF CALLING VDA DRIVER ; DE: DISPATCH ADDRESS OF CALLING VDA DRIVER ; RETURNS: -; DE: OUR CIO DISPATCH ADDRESS +; DE: OUR CIO FUNC TBL ADDRESS ; TTY_INIT: ; PREVENT ATTEMPTS TO INIT MULTIPLE INSTANCES FOR NOW @@ -24,13 +24,13 @@ TTY_INIT: LD (TTY_DEVNUM),A ; SAVE IT LD A,C ; VDA UNIT NUMBER PASSED IN C LD (TTY_VDAUNIT),A ; SAVE IT - LD (TTY_VDADISPADR),DE ; RECORD VDA DISPATCH ADDRESS + ;LD (TTY_VDADISPADR),DE ; RECORD VDA DISPATCH ADDRESS ; ; INIT/RESET OUR INTERNAL STATE CALL TTY_RESET ; FULL RESET OF EMULATOR INTERNAL STATE RET NZ ; BAIL OUT ON ERROR ; - LD DE,TTY_DISPATCH ; RETURN OUR DISPATCH ADDRESS + LD DE,TTY_FNTBL ; RETURN OUR FUNC TBL ADDRESS XOR A ; SIGNAL SUCCESS RET ; RETURN ; @@ -50,58 +50,55 @@ TTY_RESET: ; ; TTY_VDADISP: - JP PANIC -TTY_VDADISPADR .EQU $ - 2 +; JP PANIC +;TTY_VDADISPADR .EQU $ - 2 + LD A,(TTY_VDAUNIT) + LD C,A + JP VDA_DISPATCH ; +; FUNCTION TABLE ; +TTY_FNTBL: + .DW TTY_IN + .DW TTY_OUT + .DW TTY_IST + .DW TTY_OST + .DW TTY_INITDEV + .DW TTY_QUERY + .DW TTY_DEVICE +#IF (($ - TTY_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID TTY FUNCTION TABLE ***\n" +#ENDIF ; -TTY_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - JR Z,TTY_CIOIN ; $30 - DEC A - JR Z,TTY_CIOOUT ; $31 - DEC A - JR Z,TTY_CIOIST ; $32 - DEC A - JR Z,TTY_CIOOST ; $33 - DEC A - JR Z,TTY_CIOINIT ; $34 - DEC A - JR Z,TTY_CIOQUERY ; $35 - DEC A - JR Z,TTY_CIODEVICE ; $36 - CALL PANIC ; ; -; -TTY_CIOIN: +TTY_IN: LD B,BF_VDAKRD ; SET FUNCTION TO KEYBOARD READ JP TTY_VDADISP ; CHAIN TO VDA DISPATCHER ; ; ; -TTY_CIOOUT: +TTY_OUT: CALL TTY_DOCHAR ; HANDLE THE CHARACTER (EMULATION ENGINE) XOR A ; SIGNAL SUCCESS RET ; ; ; -TTY_CIOIST: +TTY_IST: LD B,BF_VDAKST ; SET FUNCTION TO KEYBOARD STATUS JP TTY_VDADISP ; CHAIN TO VDA DISPATCHER ; ; ; -TTY_CIOOST: +TTY_OST: XOR A ; ZERO ACCUM INC A ; A := $FF TO SIGNAL OUTPUT BUFFER READY RET ; ; ; -TTY_CIOINIT: +TTY_INITDEV: ; RESET THE ATTACHED VDA DEVICE LD B,BF_VDAINI ; FUNC: INIT LD E,-1 ; DO NOT CHANGE VIDEO MODE @@ -112,7 +109,7 @@ TTY_CIOINIT: ; ; ; -TTY_CIOQUERY: +TTY_QUERY: LD DE,$FFFF LD HL,$FFFF XOR A @@ -120,7 +117,7 @@ TTY_CIOQUERY: ; ; ; -TTY_CIODEVICE: +TTY_DEVICE: LD D,CIODEV_TERM ; TYPE IS TERMINAL LD A,(TTY_DEVNUM) ; GET DEVICE NUMBER LD E,A ; PUT IT IN E diff --git a/Source/HBIOS/uart.asm b/Source/HBIOS/uart.asm index ad1dec81..2e8fdb8f 100644 --- a/Source/HBIOS/uart.asm +++ b/Source/HBIOS/uart.asm @@ -85,7 +85,7 @@ UART_PREINIT0: JR Z,UART_PREINIT2 ; SKIP IT IF NOTHING FOUND ; PUSH BC ; SAVE LOOP CONTROL - LD BC,UART_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,UART_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL NZ,CIO_ADDENT ; ADD ENTRY IF UART FOUND, BC:DE POP BC ; RESTORE LOOP CONTROL ; @@ -142,24 +142,9 @@ UART_INIT1: XOR A ; SIGNAL SUCCESS RET ; DONE ; +; DRIVER FUNCTION TABLE ; -; -UART_DISPATCH: - ; DISPATCH TO FUNCTION HANDLER - PUSH HL ; SAVE HL FOR NOW - LD A,B ; GET FUNCTION - AND $0F ; ISOLATE LOW NIBBLE - RLCA ; X 2 FOR WORD OFFSET INTO FUNCTION TABLE - LD HL,UART_FTBL ; START OF FUNC TABLE - CALL ADDHLA ; HL := ADDRESS OF ADDRESS OF FUNCTION - LD A,(HL) ; DEREF HL - INC HL ; ... - LD H,(HL) ; ... - LD L,A ; ... TO GET ADDRESS OF FUNCTION - EX (SP),HL ; RESTORE HL & PUT FUNC ADDRESS -> (SP) - RET ; EFFECTIVELY A JP TO TGT ADDRESS - -UART_FTBL: +UART_FNTBL: .DW UART_IN .DW UART_OUT .DW UART_IST @@ -167,6 +152,9 @@ UART_FTBL: .DW UART_INITDEV .DW UART_QUERY .DW UART_DEVICE +#IF (($ - UART_FNTBL) != (CIO_FNCNT * 2)) + .ECHO "*** INVALID UART FUNCTION TABLE ***\n" +#ENDIF ; ; ; diff --git a/Source/HBIOS/vdu.asm b/Source/HBIOS/vdu.asm index e1498d53..4175dab5 100644 --- a/Source/HBIOS/vdu.asm +++ b/Source/HBIOS/vdu.asm @@ -56,13 +56,13 @@ VDU_INIT1: CALL PPK_INIT ; INITIALIZE KEYBOARD DRIVER ; ; ADD OURSELVES TO VDA DISPATCH TABLE - LD BC,VDU_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,VDU_FNTBL ; BC := FUNCTION TABLE ADDRESS LD DE,VDU_IDAT ; DE := VDU INSTANCE DATA PTR CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; ; INITIALIZE EMULATION LD C,A ; ASSIGNED VIDEO UNIT IN C - LD DE,VDU_DISPATCH ; DE := DISPATCH ADDRESS + LD DE,VDU_FNTBL ; DE := FUNCTION TABLE ADDRESS LD HL,VDU_IDAT ; HL := VDU INSTANCE DATA PTR CALL TERM_ATTACH ; DO IT @@ -70,43 +70,28 @@ VDU_INIT1: RET ; ;====================================================================== -; VDU DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS +; VDU DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS ;====================================================================== ; -VDU_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - - JR Z,VDU_VDAINI ; $40 - DEC A - JR Z,VDU_VDAQRY ; $41 - DEC A - JR Z,VDU_VDARES ; $42 - DEC A - JR Z,VDU_VDADEV ; $43 - DEC A - JR Z,VDU_VDASCS ; $44 - DEC A - JR Z,VDU_VDASCP ; $45 - DEC A - JR Z,VDU_VDASAT ; $46 - DEC A - JR Z,VDU_VDASCO ; $47 - DEC A - JR Z,VDU_VDAWRC ; $48 - DEC A - JR Z,VDU_VDAFIL ; $49 - DEC A - JR Z,VDU_VDACPY ; $4A - DEC A - JR Z,VDU_VDASCR ; $4B - DEC A - JP Z,PPK_STAT ; $4C - DEC A - JP Z,PPK_FLUSH ; $4D - DEC A - JP Z,PPK_READ ; $4E - CALL PANIC +VDU_FNTBL: + .DW VDU_VDAINI + .DW VDU_VDAQRY + .DW VDU_VDARES + .DW VDU_VDADEV + .DW VDU_VDASCS + .DW VDU_VDASCP + .DW VDU_VDASAT + .DW VDU_VDASCO + .DW VDU_VDAWRC + .DW VDU_VDAFIL + .DW VDU_VDACPY + .DW VDU_VDASCR + .DW PPK_STAT + .DW PPK_FLUSH + .DW PPK_READ +#IF (($ - VDU_FNTBL) != (VDA_FNCNT * 2)) + .ECHO "*** INVALID VDU FUNCTION TABLE ***\n" +#ENDIF VDU_VDAINI: ; RESET VDA diff --git a/Source/HBIOS/vga.asm b/Source/HBIOS/vga.asm index 156bc529..420afccc 100644 --- a/Source/HBIOS/vga.asm +++ b/Source/HBIOS/vga.asm @@ -71,15 +71,15 @@ VGA_INIT1: CALL VGA_LOADFONT ; LOAD FONT DATA FROM ROM TO VGA STRORAGE CALL VGA_VDARES CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER - + ; ADD OURSELVES TO VDA DISPATCH TABLE - LD BC,VGA_DISPATCH ; BC := DISPATCH ADDRESS + LD BC,VGA_FNTBL ; BC := FUNCTION TABLE ADDRESS LD DE,VGA_IDAT ; DE := VGA INSTANCE DATA PTR CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; INITIALIZE EMULATION LD C,A ; C := ASSIGNED VIDEO DEVICE NUM - LD DE,VGA_DISPATCH ; DE := DISPATCH ADDRESS + LD DE,VGA_FNTBL ; DE := FUNCTION TABLE ADDRESS LD HL,VGA_IDAT ; HL := VGA INSTANCE DATA PTR CALL TERM_ATTACH ; DO IT @@ -87,43 +87,28 @@ VGA_INIT1: RET ; ;====================================================================== -; VGA DRIVER - VIDEO DISPLAY ADAPTER (VDA) DISPATCHER AND FUNCTIONS +; VGA DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS ;====================================================================== ; -VGA_DISPATCH: - LD A,B ; GET REQUESTED FUNCTION - AND $0F ; ISOLATE SUB-FUNCTION - - JP Z,VGA_VDAINI ; $40 - DEC A - JP Z,VGA_VDAQRY ; $41 - DEC A - JP Z,VGA_VDARES ; $42 - DEC A - JP Z,VGA_VDADEV ; $43 - DEC A - JP Z,VGA_VDASCS ; $44 - DEC A - JP Z,VGA_VDASCP ; $45 - DEC A - JP Z,VGA_VDASAT ; $46 - DEC A - JP Z,VGA_VDASCO ; $47 - DEC A - JP Z,VGA_VDAWRC ; $48 - DEC A - JP Z,VGA_VDAFIL ; $49 - DEC A - JP Z,VGA_VDACPY ; $4A - DEC A - JP Z,VGA_VDASCR ; $4B - DEC A - JP Z,KBD_STAT ; $4C - DEC A - JP Z,KBD_FLUSH ; $4D - DEC A - JP Z,KBD_READ ; $4E - CALL PANIC +VGA_FNTBL: + .DW VGA_VDAINI + .DW VGA_VDAQRY + .DW VGA_VDARES + .DW VGA_VDADEV + .DW VGA_VDASCS + .DW VGA_VDASCP + .DW VGA_VDASAT + .DW VGA_VDASCO + .DW VGA_VDAWRC + .DW VGA_VDAFIL + .DW VGA_VDACPY + .DW VGA_VDASCR + .DW KBD_STAT + .DW KBD_FLUSH + .DW KBD_READ +#IF (($ - VGA_FNTBL) != (VDA_FNCNT * 2)) + .ECHO "*** INVALID VGA FUNCTION TABLE ***\n" +#ENDIF VGA_VDAINI: ; RESET VDA diff --git a/Source/Images/hd0/s1/u0/pmarc.com b/Source/Images/hd0/s1/u0/pmarc.com new file mode 100644 index 0000000000000000000000000000000000000000..59bd3ef39a3e22311093d1ce6c21959b07a9aa1d GIT binary patch literal 10368 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 F{}0rIYy$uQ literal 0 HcmV?d00001 diff --git a/Source/Images/hd0/s1/u0/pmext.com b/Source/Images/hd0/s1/u0/pmext.com new file mode 100644 index 0000000000000000000000000000000000000000..d3a51ca314e15455fbb3a82c345e5dac63a83451 GIT binary patch literal 12928 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 literal 0 HcmV?d00001