From 4ab1cadfad95aa73620a799e315d0f50ffe9eb36 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sun, 27 Nov 2016 20:15:12 -0800 Subject: [PATCH] BPBIOS and Date Stamping Cleanups - Improved BPBIOS compatibility - Enhanced STAMPS.DAT w/ NZT stamp --- Source/BPBIOS/Build.cmd | 4 +- Source/BPBIOS/hbios.z80 | 216 +++++++++++++++-------------- Source/BPBIOS/ibmv-ww.z80 | 12 +- Source/BPBIOS/romwbw.lib | 14 ++ Source/HBIOS/hbios.asm | 135 ++++++++++-------- Source/Images/hd0/s1/u0/LDNZT.COM | Bin 0 -> 3328 bytes Source/Images/hd0/s1/u0/STAMPS.DAT | Bin 11392 -> 15744 bytes Source/ZSDOS/Clock/LDNZT.COM | Bin 0 -> 3328 bytes Source/ZSDOS/Clock/ReadMe.txt | 2 + Source/ZSDOS/Clock/STAMPS.DAT | Bin 0 -> 15744 bytes Tools/simh/Sim.cfg | 5 +- 11 files changed, 215 insertions(+), 173 deletions(-) create mode 100644 Source/Images/hd0/s1/u0/LDNZT.COM create mode 100644 Source/ZSDOS/Clock/LDNZT.COM create mode 100644 Source/ZSDOS/Clock/STAMPS.DAT diff --git a/Source/BPBIOS/Build.cmd b/Source/BPBIOS/Build.cmd index 7b4f4607..7f06ca88 100644 --- a/Source/BPBIOS/Build.cmd +++ b/Source/BPBIOS/Build.cmd @@ -10,7 +10,7 @@ set ZXINCDIR=../../tools/cpm/include/ pushd ZCPR33 && call Build.cmd && popd -pause +rem pause call :makebp 33t call :makebp 33tbnk @@ -25,7 +25,7 @@ call :makebp 34nbnk call :makebp 41tbnk call :makebp 41nbnk -pause +rem pause cpmrm.exe -f wbw_hd0 ../../Binary/hd0.img 0:ws*.* diff --git a/Source/BPBIOS/hbios.z80 b/Source/BPBIOS/hbios.z80 index cfe8dadc..be63e92d 100644 --- a/Source/BPBIOS/hbios.z80 +++ b/Source/BPBIOS/hbios.z80 @@ -8,7 +8,8 @@ HB_DEFBNK EQU BID_USR ; Default bank number ; ; LOCATION OF DISPATCH ENTRY IN HBIOS BANK ; -HB_DISPATCH EQU 0403H +HB_DISPATCH EQU 403H +HB_STACK EQU 500H ; ; PLATFORM SPECIFIC CONSTANTS ; @@ -76,7 +77,7 @@ HBX_BNKCPY EQU 0FFF6H HBX_BNKCALL EQU 0FFF9H HB_CURBNK EQU 0FFE0H -;HB_PRVBNK EQU 0FFE1H +HB_INVBNK EQU 0FFE1H HB_SRCADR EQU 0FFE2H HB_SRCBNK EQU 0FFE4H HB_DSTADR EQU 0FFE5H @@ -114,6 +115,19 @@ HBX_INIT: LD (HB_SRCBNK),A LD (HB_DSTBNK),A + IF BANKED + + ; Copy vectors from TPA page zero to SYS page zero + LD BC,(TPABNK) ; C := TPABNK, B := SYSBNK + CALL XMOVE ; Set source/dest banks for copy + LD HL,0 ; Source address is zero + LD DE,0 ; Destination address is zero + LD BC,40H ; Copy 40H bytes + CALL MOVE ; Do it + LD A,(TPABNK) ; Set all Bank regs to TPA + + ENDIF + RET HBX_XCOPY: @@ -124,16 +138,14 @@ HBX_XCOPY: RET HBX_COPY: - LD (HBX_STKSAV),SP ; Save current stack - LD SP,HBX_STACK ; Activate our private stack - CALL HBX_BNKCPY ; Do the work with private stack active - LD SP,(HBX_STKSAV) ; Back to original stack - RET - - + JP HBX_BNKCPY IF INTPXY -; + +;================================================================================================== +; SELECT MEMORY BANK FOR LOWER 32K +;================================================================================================== + HBX_BNKSEL: LD (HB_CURBNK),A @@ -186,136 +198,131 @@ HBX_ROM: RLCA OUT0 (CPU_BBR),A RET + ENDIF + +;================================================================================================== +; INTERBANK MEMORY COPY +;================================================================================================== + +HBX_BNKCPY: + HB_DI ; NOTE: ONLY REQUIRED WHEN USING IM 1 + + LD (HBX_STKSAV),SP + LD SP,HBX_TMPSTK + LD A,(HB_CURBNK) ; GET CURRENT BANK + PUSH AF ; AND SAVE TO RESTORE LATER + PUSH BC ; CUR LEN -> (SP) ; -; Entry point HBX_BNKCPY is for use internally and -; assumes a valid stack already exists in upper 32K. +HBX_BC_LOOP: + EX (SP),HL ; HL := CUR LEN, (SP) := CUR SRC + LD BC,HBX_BUFSIZ ; SET BC TO BOUNCE BUFFER SIZE + OR A ; CLEAR CARRY FLAG + SBC HL,BC ; CUR LEN := CUR LEN - BBUF SIZE + JR C,HBX_BC_LAST ; END GAME, LESS THAN BBUF BYTES LEFT + EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN + CALL HBX_BC_ITER ; DO A FULL BBUF SIZE CHUNK + JR HBX_BC_LOOP ; AND REPEAT TILL DONE ; -HBX_BNKCPY: - ; Save current bank to restore at end - LD A,(HB_CURBNK) - LD (HBX_CPYBNK),A - - ; Setup for copy loop - LD (HB_SRCADR),HL ; Init working source adr - LD (HB_DSTADR),DE ; Init working dest adr - LD H,B ; Move bytes to copy from BC... - LD L,C ; to HL to use as byte counter - -HBX_COPY2: ; Copy loop - LD A,L ; Low byte of count to A - AND 7FH ; Isolate bits relevant to 128 byte buf - LD BC,80H ; Assume full buf copy - JR Z,HBX_COPY3 ; If full buf copy, go do it - LD C,A ; Otherwise, BC := bytes to copy - -HBX_COPY3: - PUSH HL ; Save bytes left to copy - CALL HBX_COPY4 ; Do it - POP HL ; Recover bytes left to copy - XOR A ; Clear CF - SBC HL,BC ; Reflect bytes copied in HL - JR NZ,HBX_COPY2 ; If any left, then loop - - ; FIX: this should be done elsewhere!!! - LD A,HB_DEFBNK ; Default bank id - LD (HB_SRCBNK),A ; ... to source bank id - LD (HB_DSTBNK),A ; ... and destination bank id - - LD A,0FFH ; Load original bank ($FF is replaced at entry) -HBX_CPYBNK EQU $ - 1 - - JR HBX_BNKSEL ; Return via bank set - -HBX_COPY4: - ; Switch to source bank - LD A,(HB_SRCBNK) ; Get source bank - CALL HBX_BNKSEL ; Set bank without making it current - - ; Copy BC bytes from HL -> BUF - ; Allow HL to increment - PUSH BC ; Save copy length - LD HL,(HB_SRCADR) ; Point to source adr - LD DE,HBX_BUF ; Setup buffer as interim destination - LDIR ; Copy BC bytes: src -> buffer - LD (HB_SRCADR),HL ; Update source adr - POP BC ; Recover copy length +HBX_BC_LAST: + ; HL IS BETWEEN -(BBUF SIZE) AND -1, BC = BBUF SIZE + OR A ; CLEAR CARRY + ADC HL,BC ; HL := REM LEN (0 - 127) + EX (SP),HL ; HL := CUR SRC, (SP) := REM LEN + POP BC ; BC := REM LEN + CALL NZ,HBX_BC_ITER ; DO FINAL CHUNK, BUT ONLY IF NOT ZERO BYTES + POP AF ; RECOVER ORIGINAL BANK + CALL HBX_BNKSEL ; SWITCH TO CURRENT BANK AND EXIT + LD SP,(HBX_STKSAV) - ; Switch to dest bank - LD A,(HB_DSTBNK) ; Get destination bank - CALL HBX_BNKSEL ; Set bank without making it current - - ; Copy BC bytes from BUF -> HL - ; Allow DE to increment - PUSH BC ; Save copy length - LD HL,HBX_BUF ; Use the buffer as source now - LD DE,(HB_DSTADR) ; Setup final destination for copy - LDIR ; Copy BC bytes: buffer -> dest - LD (HB_DSTADR),DE ; Update dest adr - POP BC ; Recover copy length - - RET ; Done + HB_EI ; NOTE: ONLY REQUIRED WHEN USING IM 1 + + RET ; +HBX_BC_ITER: + ; HL = SRC ADR, DE = DEST ADR, BC = LEN + PUSH BC ; SAVE COPY LEN + PUSH DE ; FINAL DEST ON STACK + LD DE,HBX_BUF ; SET DEST TO BUF + LD A,(HB_SRCBNK) ; GET SOURCE BANK + CALL HBX_BNKSEL ; SWITCH TO SOURCE BANK + LDIR ; HL -> BUF (DE), BC BYTES, HL UPDATED SRC ADR + POP DE ; DE := FINAL DEST + POP BC ; GET LEN BACK IN BC + PUSH HL ; SAVE UPDATED SRC ADR + LD HL,HBX_BUF ; SET SRC ADR TO BUF + LD A,(HB_DSTBNK) ; GET DEST BANK + CALL HBX_BNKSEL ; SWITCH TO DEST BANK + LDIR ; BUF (HL) -> DE, BC BYTES, DE UPDATED DEST ADR + POP HL ; RECOVER UPDATED SRC ADR + ; HL = UPD SRC, DE = UPD DEST, BC = 0 + RET + +;================================================================================================== ; ENTRY POINT FOR BIOS FUNCTIONS (TARGET OF RST 08) -; +;================================================================================================== + HBX_INVOKE: - LD (HBX_STKSAV),SP ; SAVE ORIGINAL STACK FRAME + LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME LD A,(HB_CURBNK) ; GET CURRENT BANK LD (HB_INVBNK),A ; SAVE INVOCATION BANK - ;DI - LD SP,HBX_STACK ; SETUP NEW STACK FRAME +; HB_DI + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH LD A,BID_HB ; HBIOS BANK CALL HBX_BNKSEL ; SELECT IT - ;EI + LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK +; HB_EI CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER - ;DI +; HB_DI + 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 - LD SP,(HBX_STKSAV) ; RESTORE ORIGINAL STACK FRAME - ;EI + LD SP,0 ; RESTORE ORIGINAL STACK FRAME +HBX_INVSP EQU $ - 2 +; HB_EI RET ; RETURN TO CALLER ENDIF ;================================================================================================== -; Load A,(HL) from Alternate Bank (in Reg C) +; LD A,(C:HL) ;================================================================================================== HBX_FRGETB: LD (HBX_STKSAV),SP ; Save current stack - LD SP,HBX_STACK ; Activate our private stack + LD SP,HBX_TMPSTK ; Activate our private stack LD A,(HB_CURBNK) ; Get current bank LD (HBX_BNKSAV),A ; Save current bank PUSH BC LD A,C - ;DI + HB_DI CALL HBX_BNKSEL LD C,(HL) LD A,(HBX_BNKSAV) CALL HBX_BNKSEL - ;EI + HB_EI LD A,C POP BC LD SP,(HBX_STKSAV) ; RESTORE ORIGINAL STACK FRAME RET ;================================================================================================== -; Load DE,(HL) from Alternate Bank +; LD DE,(C:HL) ;================================================================================================== HBX_FRGETW: LD (HBX_STKSAV),SP ; Save current stack - LD SP,HBX_STACK ; Activate our private stack + LD SP,HBX_TMPSTK ; Activate our private stack LD A,(HB_CURBNK) ; Get current bank LD (HBX_BNKSAV),A ; Save current bank LD A,C - ;DI + HB_DI CALL HBX_BNKSEL LD E,(HL) INC HL @@ -323,17 +330,17 @@ HBX_FRGETW: DEC HL LD A,(HBX_BNKSAV) CALL HBX_BNKSEL - ;EI + HB_EI LD SP,(HBX_STKSAV) ; RESTORE ORIGINAL STACK FRAME RET ;================================================================================================== -; Load (HL),A to Alternate Bank (in Reg C) +; LD (C:HL),A ;================================================================================================== HBX_FRPUTB: LD (HBX_STKSAV),SP ; Save current stack - LD SP,HBX_STACK ; Activate our private stack + LD SP,HBX_TMPSTK ; Activate our private stack PUSH AF LD A,(HB_CURBNK) ; Get current bank LD (HBX_BNKSAV),A ; Save current bank @@ -341,27 +348,27 @@ HBX_FRPUTB: PUSH BC LD B,A LD A,C - ;DI + HB_DI CALL HBX_BNKSEL LD (HL),B LD A,(HBX_BNKSAV) CALL HBX_BNKSEL - ;EI + HB_EI POP BC LD SP,(HBX_STKSAV) ; RESTORE ORIGINAL STACK FRAME RET ;================================================================================================== -; Load (HL),DE to Alternate Bank +; LD (C:HL),DE ;================================================================================================== HBX_FRPUTW: LD (HBX_STKSAV),SP ; Save current stack - LD SP,HBX_STACK ; Activate our private stack + LD SP,HBX_TMPSTK ; Activate our private stack LD A,(HB_CURBNK) ; Get current bank LD (HBX_BNKSAV),A ; Save current bank LD A,C - ;DI + HB_DI CALL HBX_BNKSEL LD (HL),E INC HL @@ -369,26 +376,25 @@ HBX_FRPUTW: DEC HL LD A,(HBX_BNKSAV) CALL HBX_BNKSEL - ;EI + HB_EI LD SP,(HBX_STKSAV) ; RESTORE ORIGINAL STACK FRAME RET ;================================================================================================== -; ; PRIVATE DATA -; +;================================================================================================== DSEG HB_DSKBUF DEFW 0 ; Address of physical disk buffer in HBIOS bank HBX_BNKSAV DEFB 0 ; Saved bank id during HBIOS calls HBX_STKSAV DEFW 0 ; Saved stack pointer during HBIOS calls - DEFS 64 ; Private stack for HBIOS -HBX_STACK EQU $ ; Top of private stack + DEFS 32 ; Private stack for HBIOS +HBX_TMPSTK EQU $ ; Top of private stack IF INTPXY -HBX_RETBNK DEFB 0 ; Bank to activate on return from BNKCPY -HBX_BUF DEFS 80H ; Interbank copy buffer +HBX_BUFSIZ EQU 40H +HBX_BUF DEFS HBX_BUFSIZ ; Interbank copy buffer ENDIF diff --git a/Source/BPBIOS/ibmv-ww.z80 b/Source/BPBIOS/ibmv-ww.z80 index 72a39f3a..540cf8a8 100644 --- a/Source/BPBIOS/ibmv-ww.z80 +++ b/Source/BPBIOS/ibmv-ww.z80 @@ -30,11 +30,11 @@ BIOSTK: DEFB 0 ; NOP if not currently in bank, LD (USP-7),HL ; Save entry HL POP HL ; Retrieve caller's return address from stack LD (USP-5),HL ; ..and set in our stack for local return - ;DI ; No interrupts while we play with the stack + HB_DI ; No interrupts while we play with the stack LD (USP),SP ; Save User's Stack Pointer LD SP,USP-1 ; ..and point locally, saving 1 byte for Bank PUSH AF ; Save entry A and Flags - LD A,(CURBNK) ; Get current bank + LD A,(HB_CURBNK) ; Get current bank LD (USP-1),A ; ..and save for exitting LD A,0C9H ; Disable other calls here LD (BIOSTK),A ; ..by poking a RETurn at entry @@ -43,7 +43,7 @@ BIOSTK: DEFB 0 ; NOP if not currently in bank, PUSH HL ; ..at USP-2 & 3 LD SP,USP-7 ; Point stack pointer to do local return POP HL ; .restoring entry HL - ;EI ; ..enabling interrupts + HB_EI ; ..enabling interrupts RET ; And return to caller ; Restore User Stack and Bank Routine @@ -51,7 +51,6 @@ BIOSTK: DEFB 0 ; NOP if not currently in bank, USRSTK: PUSH AF LD A,(USP-1) ; Get bank control byte from entry CALL HBX_BNKSEL - LD (CURBNK),A XOR A LD (BIOSTK),A ; Patch NOP back in at start of code POP AF @@ -65,7 +64,6 @@ USRSTK: PUSH AF FRCLR: PUSH AF ; Save any entry in AF LD A,(USP-1) ; Get bank control byte CALL HBX_BNKSEL - LD (CURBNK),A ; WW: I ADDED THIS, IS IT RIGHT??? XOR A LD (BIOSTK),A ; Patch NOP to enable stack switcher POP AF @@ -90,7 +88,7 @@ ABORT: LD SP,USP ; Insure stack is in Common Memory ; Uses : AF ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -RETMEM: LD A,(CURBNK) +RETMEM: LD A,(HB_CURBNK) RET ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -109,7 +107,6 @@ SELMEM: LD (USRBNK),A ; Update user bank SELBNK: PUSH AF ; Save regs SELBN0: CALL HBX_BNKSEL - LD (CURBNK),A ; Save as current bank # POP AF ; restore regs RET @@ -188,7 +185,6 @@ FRPUTW: JPBNK: DEFS 1 ; Bank # for Far Jump or Call USRBNK: DEFS 1 ; User's selected bank # -CURBNK: DEFS 1 ; Current bank # DMABNK: DEFS 1 ; Target bank # for disk xfers DEFS 64 ; 32 level stack USP: DEFS 2 ; User stack pointer diff --git a/Source/BPBIOS/romwbw.lib b/Source/BPBIOS/romwbw.lib index c6d9f83c..d666295f 100644 --- a/Source/BPBIOS/romwbw.lib +++ b/Source/BPBIOS/romwbw.lib @@ -66,3 +66,17 @@ MEMTOP EQU 0FFE0H - 1 ; Start of HBIOS 32 byte control block ELSE MEMTOP EQU HBLOC - 1 ; Start of HBIOS 512 byte proxy ENDIF + + IF INTPXY +HB_EI MACRO + ENDM +HB_DI MACRO + ENDM + ELSE +HB_EI MACRO + EI + ENDM +HB_DI MACRO + DI + ENDM + ENDIF diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 14245931..c112c4f0 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -98,7 +98,7 @@ MODCNT .SET MODCNT + 1 RET .FILL (030H - $),0FFH ; RST 30 RET - .FILL (038H - $),0FFH ; RST 38 / INT + .FILL (038H - $),0FFH ; RST 38 / IM1 INT RETI .FILL (066H - $),0FFH ; NMI RETN @@ -204,39 +204,42 @@ HBX_IDENT: ;================================================================================================== ; HBX_INVOKE: - LD (HBX_STKSAV),SP ; SAVE ORIGINAL STACK FRAME + LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME LD A,(HB_CURBNK) ; GET CURRENT BANK LD (HB_INVBNK),A ; SAVE INVOCATION BANK - HB_DI - LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM +; HB_DI + LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH LD A,BID_BIOS ; HBIOS BANK CALL HBX_BNKSEL ; SELECT IT LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK - HB_EI +; HB_EI CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER - HB_DI - LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM +; HB_DI + 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 LD SP,0 ; RESTORE ORIGINAL STACK FRAME -HBX_STKSAV .EQU $ - 2 - HB_EI +HBX_INVSP .EQU $ - 2 +; HB_EI RET ; RETURN TO CALLER ; ;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -;; SETBNK - Switch Memory Bank to Bank in A. +;; BNKSEL - Switch Memory Bank to Bank in A. ;; Preserve all Registers including Flags. -;; Does NOT update current bank. -;; Interrupts should be disabled by caller ;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; HBX_BNKSEL: + ; IF AN INTERRUPT OCCURS DURING THE BANK SWITCH CODE, + ; THE BANK WILL BE SET TO (CURBNK) AS THE INTERRUPT + ; RETURNS. SO, IT IS IMPORTANT THAT (HB_CURBNK) BE + ; SET AS THE FIRST STEP TO AVOID ISSUES IF AN INTERRUPT + ; OCCURS DURING PROCESSING. LD (HB_CURBNK),A ; RECORD NEW CURRENT BANK ; HBX_BNKSEL_INT: @@ -308,9 +311,11 @@ HBX_BNKSEL1: ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; HBX_BNKCPY: +#IF (INTTYPE == IT_SIMH) HB_DI +#ENDIF LD (HBX_BC_SP),SP - LD SP,HBX_STACK + LD SP,HBX_TMPSTK LD A,(HB_CURBNK) ; GET CURRENT BANK PUSH AF ; AND SAVE TO RESTORE LATER @@ -337,7 +342,9 @@ HBX_BC_LAST: CALL HBX_BNKSEL ; SWITCH TO CURRENT BANK AND EXIT LD SP,$FFFF HBX_BC_SP .EQU $ - 2 +#IF (INTTYPE == IT_SIMH) HB_EI +#ENDIF RET ; HBX_BC_ITER: @@ -359,39 +366,39 @@ HBX_BC_ITER: ; HL = UPD SRC, DE = UPD DEST, BC = 0 RET ; -; Call a routine in another bank saving and restoring the original bank. -; Caller MUST ensure stack is already in high memory. -; On input A=target bank, HL=target address +; CALL A ROUTINE IN ANOTHER BANK. +; CALLER MUST ENSURE STACK IS ALREADY IN HIGH MEMORY AND HAS ADEQUATE SPACE. +; ON INPUT A=TARGET BANK, HL=TARGET ADDRESS ; HBX_BNKCALL: - HB_DI - LD (HBX_TGTBNK),A ; stuff target bank to call into code below - LD (HBX_TGTADR),HL ; stuff address to call into code below - LD A,(HB_CURBNK) ; get current bank - PUSH AF ; save for return + LD (HBX_TGTBNK),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW + LD (HBX_TGTADR),HL ; STUFF ADDRESS TO CALL INTO CODE BELOW + LD A,(HB_CURBNK) ; GET CURRENT BANK + PUSH AF ; SAVE FOR RETURN HBX_TGTBNK .EQU $ + 1 - LD A,$FF ; load bank to call ($FF overlaid at entry) - CALL HBX_BNKSEL ; activate the new bank - HB_EI + LD A,$FF ; LOAD BANK TO CALL ($FF OVERLAID AT ENTRY) + CALL HBX_BNKSEL ; ACTIVATE THE NEW BANK HBX_TGTADR .EQU $ + 1 - CALL $FFFF ; call routine ($FFFF is overlaid above) + CALL $FFFF ; CALL ROUTINE ($FFFF IS OVERLAID ABOVE) - HB_DI - EX (SP),HL ; save hl and get bank to restore in hl - PUSH AF ; save af - LD A,H ; bank to restore to a - CALL HBX_BNKSEL ; restore it - POP AF ; recover af - POP HL ; recover hl - HB_EI + EX (SP),HL ; SAVE HL AND GET BANK TO RESTORE IN HL + PUSH AF ; SAVE AF + LD A,H ; BANK TO RESTORE TO A + CALL HBX_BNKSEL ; RESTORE IT + POP AF ; RECOVER AF + POP HL ; RECOVER HL RET ; ; PEEK & POKE ROUTINES ; ADDRESS IN HL, BANK IN D, VALUE IN/OUT IN E, A IS TRASHED ; HBX_PEEK: +#IF (INTTYPE == IT_SIMH) HB_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) PUSH AF LD A,D @@ -400,7 +407,11 @@ HBX_PEEK: JR HBX_PPRET ; HBX_POKE: +#IF (INTTYPE == IT_SIMH) HB_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) PUSH AF LD A,D @@ -410,14 +421,23 @@ HBX_POKE: HBX_PPRET: POP AF CALL HBX_BNKSEL + LD SP,0 ; RESTORE ORIGINAL STACK FRAME +HBX_PPSP .EQU $ - 2 +#IF (INTTYPE == IT_SIMH) HB_EI +#ENDIF RET ; +; SMALL TEMPORARY STACK FOR USE BY HB_INVOKE +; + .FILL 20,$CC ; 10 LEVEL STACK +HBX_TMPSTK .EQU $ +; ; PRIVATE STACK AT END OF HBIOS CODE ; OCCUPIES SPACE BEFORE IVT ; HBX_STKSIZ .EQU $FF00 - $ - .ECHO "HBIOS STACK space: " + .ECHO "HBIOS PROXY STACK space: " .ECHO HBX_STKSIZ .ECHO " bytes.\n" .FILL HBX_STKSIZ,$FF @@ -464,33 +484,30 @@ INT_BAD: ; BAD INTERRUPT HANDLER ; HBX_INT: ; COMMON INTERRUPT ROUTING CODE ; - ; SAVE STATE (ASSUMES HL SAVED PREVIOUSLY) + LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME + LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM + + ; SAVE STATE (HL SAVED PREVIOUSLY) PUSH AF ; SAVE AF PUSH BC ; SAVE BC PUSH DE ; SAVE DE - LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME - LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM - LD A,BID_BIOS ; HBIOS BANK CALL HBX_BNKSEL_INT ; SELECT IT - ;LD SP,HB_ISTACK ; NOW USE INT STACK IN HBIOS BANK - CALL JPHL ; CALL INTERRUPT ROUTINE - ;LD SP,HBX_STACK ; USE STACK FRAME IN HI MEM - LD A,(HB_CURBNK) ; GET PRE-INT BANK CALL HBX_BNKSEL ; SELECT IT - LD SP,$FFFF ; RESTORE ORIGINAL STACK FRAME -HBX_INT_SP .EQU $ - 2 - ; RESTORE STATE POP DE ; RESTORE DE POP BC ; RESTORE BC POP AF ; RESTORE AF + + LD SP,$FFFF ; RESTORE ORIGINAL STACK FRAME +HBX_INT_SP .EQU $ - 2 + POP HL ; RESTORE HL EI ; ENABLE INTERRUPTS @@ -536,15 +553,20 @@ HBX_BUF .FILL HBX_BUFSIZ,0 ; HBIOS CORE ;================================================================================================== ; -HB_STKSIZ .EQU $60 ; HBIOS PRIVATE STACK SIZE -HB_ISTKSIZ .EQU $40 ; HBIOS INTERRUPT STACK SIZE -; ;================================================================================================== -; ENTRY VECTORS (JUMP TABLE) +; ENTRY VECTORS (JUMP TABLE) AND INTERNAL PROCESSING STACK ;================================================================================================== +; +HB_ENTRYTBL .EQU $ ; JP HB_START ; HBIOS INITIALIZATION JP HB_DISPATCH ; VECTOR TO DISPATCHER +; +HB_STKSIZ .EQU HB_ENTRYTBL + 256 - $ +; + .FILL HB_STKSIZ,$FF ; USE REMAINDER OF PAGE FOR HBIOS STACK +HB_STACK .EQU $ ; TOP OF HBIOS STACK + ; ;================================================================================================== ; SYSTEM INITIALIZATION @@ -721,9 +743,14 @@ HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK ; ; SETUP TIMER INT VECTOR VIA INT MODE 1 IN PAGE ZERO LD A,$C3 ; JP OPCODE - LD ($38),A ; ... AT INT VECTOR ADDRESS + ;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 ($39),HL ; ... IS TARGET OF JP + LD ($31),HL ; ... IS TARGET OF JP + + LD HL,INT_TIMER + LD (HBX_IVT),HL ; #ENDIF ; @@ -2932,12 +2959,6 @@ HSTHEAD .DB 0 ; HEAD (0-255) HEAPCURB .DW 0 ; MARK HEAP ADDRESS AFTER INITIALIZATION ; HB_TICKS .FILL 4,0 ; 32 BIT TICK COUNTER -; - .FILL HB_STKSIZ,$FF ; 48 ENTRY STACK FOR HBIOS FUNCTION PROCESSING -HB_STACK .EQU $ ; TOP OF HBIOS STACK -;; -; .FILL HB_ISTKSIZ,$FF ; 32 ENTRY STACK FOR INTERRUPT PROCESSING -;HB_ISTACK .EQU $ ; TOP OF INTERRUPT PROCESSING STACK ; STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$" STR_PLATFORM .DB PLATFORM_NAME, "$" diff --git a/Source/Images/hd0/s1/u0/LDNZT.COM b/Source/Images/hd0/s1/u0/LDNZT.COM new file mode 100644 index 0000000000000000000000000000000000000000..535d8418c355fe68876d609dd8aa6174012d0b52 GIT binary patch literal 3328 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