mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
Trim flash portions of driver. with flash filesystem enabled, rad routine now used flash drive code to read 4k secctors. Twice as slow as normal rom read routine.
4797 lines
116 KiB
NASM
4797 lines
116 KiB
NASM
;
|
|
;==================================================================================================
|
|
; HBIOS
|
|
;==================================================================================================
|
|
;
|
|
; THIS FILE CONTAINS THE HBIOS IMAGE THAT IS INTENDED TO RUN IN A DEDICATED RAM BANK. THE CODE IS
|
|
; CONSTRUCTED SUCH THAT IT CAN BE LAUNCHED IN A VARIETY OF MODES AND INSTALL ITSELF. A SMALL 512
|
|
; BYTE PROXY IS PLACED AT THE TOP OF CPU MEMORY (FE00H-FFFFH). THIS PROXY CODE ALLOWS CODE
|
|
; RUNNING FROM ANY BANK TO INVOKE HBIOS FUNCTIONS. NORMALLY, ANY BANK THAT RUNS CODE WOULD SETUP
|
|
; THE RST 8 VECTOR TO POINT TO THE PROXY INVOKE ENTRY POINT AT FFF0H. CALLS VIA THE PROXY INVOKE
|
|
; ENTRY POINT TRANSPARENTLY SWAP IN THE HBIOS BANK, PERFORM THE REQUESTED FUNCTION, AND RETURN
|
|
; WITH THE ORIGINAL BANK ACTIVE. THE CODE USING HBIOS FUNCTIONS DOES NOT NEED TO BE AWARE OF
|
|
; THE BANK SWITCHING THAT OCCURS.
|
|
;
|
|
; THIS FILE CAN BE COMPILED TO BOOT IN ONE OF 3 MODES (ROM, APPLICATION, OR IMAGE) AS DESCRIBED
|
|
; BELOW. WHEN COMPILED, YOU MUST DEFINE EXACTLY ONE OF THE FOLLOWING MACROS:
|
|
;
|
|
; - ROMBOOT: BOOT FROM A ROM BANK
|
|
;
|
|
; WHEN ROMBOOT IS DEFINED, THE FILE IS ASSEMBLED TO BE IMBEDDED AT THE START OF A ROM
|
|
; ASSUMING THAT THE CPU WILL START EXECUTION AT ADDRESS 0. AFTER PERFORMING MINIMAL
|
|
; SYSTEM INITIALIZATION, THE IMAGE OF THE RUNNING ROM BANK IS COPIED TO A RAM BANK
|
|
; CREATING A SHADOW COPY IN RAM. EXECUTION IS THAN TRANSFERRED TO THE RAM SHADOW COPY.
|
|
; THIS IS ESSENTIAL BECAUSE THE HBIOS CODE DOES NOT SUPPORT RUNNING IN READ ONLY MEMORY
|
|
; (EXCEPT FOR THE INITIAL LAUNCHING CODE). IN THIS MODE, THE HBIOS INITIALIZATION WILL
|
|
; ALSO COPY THE OS IMAGES BANK IN ROM TO THE USER RAM BANK AND LAUNCH IT AFTER HBIOS
|
|
; IS INSTALLED.
|
|
;
|
|
; - APPBOOT: BOOT FROM A CP/M STYLE APPLICATION FILE
|
|
;
|
|
; WHEN APPBOOT IS DEFINED, THE FILE IS ASSEMBLED AS A CP/M APPLICATION ASSUMING
|
|
; THAT IT WILL BE LOADED AT 100H BY THE CP/M (OR COMPATIBLE) OS. NOTE THAT IN
|
|
; THIS CASE IT IS ASSUMED THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE
|
|
; HBIOS APPLICATION BINARY. THE APPENDED OS IMAGES ARE COPIED TO THE USER RAM
|
|
; BANK AND LAUNCHED AFTER HBIOS HAS INSTALLED ITSELF.
|
|
;
|
|
; - IMGBOOT: BOOT FROM AN IMAGE FILE THAT HAS BEEN PLACED IN THE USER BANK
|
|
;
|
|
; WHEN IMGBOOT IS DEFINED, THE FILE IS ASSEMBLED SUCH THAT IT CAN BE PRELOADED
|
|
; INTO THE RAM USER BANK BY AN EXTERNAL PROCESS THAT SUBSEQUENTLY LAUNCHES
|
|
; THE CODE AT ADDRESS 0. THE MOST COMMON EXAMPLE OF THIS IS THE UNA FSFAT
|
|
; TOOL WHICH CAN LOAD AN IMAGE FROM A DOS FAT FILESYSTEM PROVIDING A SIMPLE
|
|
; WAY TO LOAD A TEST COPY OF HBIOS. AS IS THE CASE WITH APPBOOT, IT IS ASSUMED
|
|
; THAT AN OS IMAGES FILE IS APPENDED TO THE END OF THE IMAGE AND IS LAUNCHED
|
|
; AFTER HBIOS IS INSTALLED.
|
|
;
|
|
; INCLUDE FILE NESTING:
|
|
;
|
|
; hbios.asm
|
|
; - std.asm
|
|
; - ver.inc
|
|
; - hbios.inc
|
|
; - build.inc
|
|
; - config/<plt>_<cfg>.asm
|
|
; - cfg_<plt>.asm
|
|
; - <drivers>.asm
|
|
; - <fonts>.asm
|
|
; - util.asm
|
|
; - time.asm
|
|
; - bcd.asm
|
|
; - decode.asm
|
|
; - encode.asm
|
|
; - [xio|mio].asm
|
|
; - dsky.asm
|
|
; - unlzsa2s.asm
|
|
;
|
|
;
|
|
; INCLUDE GENERIC STUFF
|
|
;
|
|
#INCLUDE "std.asm"
|
|
;
|
|
; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT, IMGBOOT IS DEFINED.
|
|
;
|
|
MODCNT .EQU 0
|
|
#IFDEF ROMBOOT
|
|
MODCNT .SET MODCNT + 1
|
|
#ENDIF
|
|
#IFDEF APPBOOT
|
|
MODCNT .SET MODCNT + 1
|
|
#ENDIF
|
|
#IFDEF IMGBOOT
|
|
MODCNT .SET MODCNT + 1
|
|
#ENDIF
|
|
#IF (MODCNT != 1)
|
|
.ECHO "*** ERROR: PLEASE DEFINE ONE AND ONLY ONE OF ROMBOOT, APPBOOT, IMGBOOT!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
#IF (DIAGENABLE)
|
|
#DEFINE DIAG(N) PUSH AF
|
|
#DEFCONT \ LD A,N
|
|
#DEFCONT \ OUT (DIAGPORT),A
|
|
#DEFCONT \ POP AF
|
|
#ELSE
|
|
#DEFINE DIAG(N) \;
|
|
#ENDIF
|
|
;
|
|
#IF (LEDENABLE)
|
|
#DEFINE LED(N) PUSH AF
|
|
#DEFCONT \ LD A,~N
|
|
#DEFCONT \ OUT (LEDPORT),A
|
|
#DEFCONT \ POP AF
|
|
#ELSE
|
|
#DEFINE LED(N) \;
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
#IF (INTMODE == 0)
|
|
; NO INTERRUPT HANDLING
|
|
#DEFINE HB_DI ;
|
|
#DEFINE HB_EI ;
|
|
#ENDIF
|
|
#IF ((INTMODE == 1) | (INTMODE == 2))
|
|
; MODE 1 OR 2 INTERRUPT HANDLING
|
|
#DEFINE HB_DI DI
|
|
#DEFINE HB_EI EI
|
|
#ENDIF
|
|
#IF (INTMODE > 2)
|
|
.ECHO "*** ERROR: INVALID INTMODE SETTING!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
#IF (CTCENABLE)
|
|
CTCA .EQU CTCBASE + 0 ; CTC: CHANNEL A REGISTER ADR
|
|
CTCB .EQU CTCBASE + 1 ; CTC: CHANNEL B REGISTER ADR
|
|
CTCC .EQU CTCBASE + 2 ; CTC: CHANNEL C REGISTER ADR
|
|
CTCD .EQU CTCBASE + 3 ; CTC: CHANNEL D REGISTER ADR
|
|
#ENDIF
|
|
;
|
|
; THIS EQUATE IS UPDATED BY DRIVER INCLUDES THAT SHARE THE RTC LATCH.
|
|
; AS DRIVER IS INCLUDED, IT WILL USE .SET TO SET ANY BITS THEY OWN
|
|
; AND WANT TO SET AS DEFAULT.
|
|
;
|
|
RTCDEF .EQU 0 ; ALLOWS DRIVERS TO SET BITS
|
|
;
|
|
;
|
|
;
|
|
#IFNDEF APPBOOT
|
|
;
|
|
.ORG 0
|
|
;
|
|
;==================================================================================================
|
|
; NORMAL PAGE ZERO SETUP, RET/RETI/RETN AS APPROPRIATE, LEAVE INTERRUPTS DISABLED
|
|
;==================================================================================================
|
|
;
|
|
.FILL (000H - $),0FFH ; RST 0
|
|
JP HB_START
|
|
.DW ROM_SIG
|
|
.FILL (008H - $),0FFH ; RST 8
|
|
JP HB_INVOKE ; INVOKE HBIOS FUNCTION
|
|
.FILL (010H - $),0FFH ; RST 10
|
|
RET
|
|
.FILL (018H - $),0FFH ; RST 18
|
|
RET
|
|
.FILL (020H - $),0FFH ; RST 20
|
|
RET
|
|
.FILL (028H - $),0FFH ; RST 28
|
|
RET
|
|
.FILL (030H - $),0FFH ; RST 30
|
|
RET
|
|
.FILL (038H - $),0FFH ; RST 38 / IM1 INT
|
|
#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
|
|
;
|
|
.FILL (070H - $),0FFH ; SIG STARTS AT $80
|
|
;
|
|
ROM_SIG:
|
|
.DB $76, $B5 ; 2 SIGNATURE BYTES
|
|
.DB 1 ; STRUCTURE VERSION NUMBER
|
|
.DB 7 ; ROM SIZE (IN MULTIPLES OF 4KB, MINUS ONE)
|
|
.DW NAME ; POINTER TO HUMAN-READABLE ROM NAME
|
|
.DW AUTH ; POINTER TO AUTHOR INITIALS
|
|
.DW DESC ; POINTER TO LONGER DESCRIPTION OF ROM
|
|
.DB 0, 0, 0, 0, 0, 0 ; RESERVED FOR FUTURE USE; MUST BE ZERO
|
|
;
|
|
NAME .DB "ROMWBW v", BIOSVER, ", ", TIMESTAMP, 0
|
|
AUTH .DB "WBW",0
|
|
DESC .DB "ROMWBW v", BIOSVER, ", Copyright (C) 2020, Wayne Warthen, GNU GPL v3", 0
|
|
;
|
|
.FILL ($100 - $),$FF ; PAD REMAINDER OF PAGE ZERO
|
|
;
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; HBIOS CONFIGURATION BLOCK (HCB)
|
|
;==================================================================================================
|
|
;
|
|
.ORG HCB_LOC
|
|
HCB:
|
|
JP HB_START
|
|
;
|
|
CB_MARKER .DB 'W',~'W' ; MARKER
|
|
CB_VERSION .DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO
|
|
.DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO
|
|
;
|
|
CB_PLATFORM .DB PLATFORM
|
|
CB_CPUMHZ .DB CPUMHZ
|
|
CB_CPUKHZ .DW CPUKHZ
|
|
CB_RAMBANKS .DB RAMSIZE / 32
|
|
CB_ROMBANKS .DB ROMSIZE / 32
|
|
;
|
|
CB_BOOTVOL .DW 0 ; BOOT VOLUME IS UNIT/SLICE, SET BY LOADER
|
|
CB_BOOTBID .DB 0 ; BOOT BANK ID, SET BY LOADER
|
|
CB_SERDEV .DB 0 ; PRIMARY SERIAL UNIT IS UNIT #0 BY FIAT
|
|
CB_CRTDEV .DB $FF ; PRIMARY CRT UNIT, $FF UNTIL AFTER HBIOS INIT
|
|
CB_CONDEV .DB $FF ; CONSOLE UNIT, $FF UNTIL AFTER HBIOS INIT
|
|
;
|
|
CB_DIAGLVL .DB DIAGLVL ; ROMWBW HBIOS DIAGNOSTIC LEVEL
|
|
;
|
|
; MEMORY MANAGEMENT VARIABLES START AT $20
|
|
;
|
|
.FILL (HCB + $20 - $),0
|
|
;
|
|
CB_HEAP .DW 0
|
|
CB_HEAPTOP .DW 0
|
|
;
|
|
; STANDARD BANK ID'S START AT $D8
|
|
;
|
|
.FILL (HCB + $D8 - $),0
|
|
;
|
|
CB_BIDCOM .DB BID_COM
|
|
CB_BIDUSR .DB BID_USR
|
|
CB_BIDBIOS .DB BID_BIOS
|
|
CB_BIDAUX .DB BID_AUX
|
|
CB_BIDRAMD0 .DB BID_RAMD0
|
|
CB_BIDRAMDN .DB BID_RAMDN
|
|
CB_BIDROMD0 .DB BID_ROMD0
|
|
CB_BIDROMDN .DB BID_ROMDN
|
|
;
|
|
.FILL (HCB + HCB_SIZ - $),0 ; PAD REMAINDER OF HCB
|
|
;
|
|
;==================================================================================================
|
|
; HBIOS UPPER MEMORY PROXY (RELOCATED TO RUN IN TOP 2 PAGES OF CPU RAM)
|
|
;==================================================================================================
|
|
;
|
|
; THE FOLLOWING CODE IS RELOCATED TO THE TOP OF MEMORY TO HANDLE INVOCATION DISPATCHING
|
|
;
|
|
.FILL (HBX_IMG - $) ; FILL TO START OF PROXY IMAGE START
|
|
.ORG HBX_LOC ; ADJUST FOR RELOCATION
|
|
;
|
|
; MEMORY LAYOUT:
|
|
;
|
|
; HBIOS PROXY CODE $FE00 (256 BYTES)
|
|
; INTERRUPT VECTORS $FF00 (32 BYTES, 16 ENTRIES)
|
|
; INTERRUPT HANDLER STUBS $FF20 (128 BYTES)
|
|
; HBIOS PROXY COPY BUFFER $FF80 (64 BYTES)
|
|
; HBIOS PROXY MGMT BLOCK $FFE0 (32 BYTES)
|
|
;
|
|
; DEFINITIONS
|
|
;
|
|
HBX_BUFSIZ .EQU $40 ; INTERBANK COPY BOUNCE BUFFER SIZE
|
|
;
|
|
; HBIOS IDENTIFICATION DATA BLOCK
|
|
;
|
|
HBX_IDENT:
|
|
.DB 'W',~'W' ; MARKER
|
|
.DB RMJ << 4 | RMN ; FIRST BYTE OF VERSION INFO
|
|
.DB RUP << 4 | RTP ; SECOND BYTE OF VERSION INFO
|
|
;
|
|
;==================================================================================================
|
|
; HBIOS ENTRY FOR RST 08 PROCESSING
|
|
;==================================================================================================
|
|
;
|
|
; NOTE: THE SIZE OF HBX_TMPSTK (TYPICALLY 20 BYTES) IS INSUFFICIENT FOR
|
|
; FREERTOS IF AN INTERRUPT STRIKES WHILE THE TEMPORARY STACK IS ACTIVE.
|
|
; BELOW, HBX_BUF HAS BEEN USURPED TO PROVIDE A LARGER TEMP STACK TO
|
|
; ACCOMMODATE FREERTOS. HBX_BUF IS ONLY USED AS A BOUNCE BUFFER, SO IT'S
|
|
; USE WILL NEVER OVERLAP WITH BELOW.
|
|
;
|
|
; HBX_INVOKE IS NOT RE-ENTRANT! HB_INVBNK CAN BE USED GLOBALLY TO DETERMINE
|
|
; IF HBIOS IS ALREADY ACTIVE. HB_INVBNK WILL HAVE A VALUE != $FF WHEN HBIOS
|
|
; IS ACTIVE. ON RETURN, HB_INVBNK IS SET TO $FF TO INDICATE HBIOS IS NOT
|
|
; ACTIVE.
|
|
;
|
|
HBX_INVOKE:
|
|
|
|
#IF (HBIOS_MUTEX == TRUE)
|
|
PUSH HL ; SAVE HL
|
|
LD HL,HB_LOCK ; POINT TO LOCK
|
|
SRA (HL) ; TEST/ACQUIRE MUTEX LOCK
|
|
JR C,$-2 ; KEEP TRYING ON FAILURE
|
|
POP HL ; RESTORE HL
|
|
#ENDIF
|
|
|
|
LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_BUF_END ; BORROW HBX_BUF FOR TEMP STACK
|
|
|
|
LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
LD (HB_INVBNK),A ; SAVE INVOCATION BANK
|
|
|
|
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_BUF_END ; BORROW HBX_BUF FOR TEMP STACK
|
|
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_INVSP .EQU $ - 2
|
|
|
|
#IF (HBIOS_MUTEX == TRUE)
|
|
PUSH HL ; SAVE HL
|
|
LD HL,HB_LOCK ; POINT TO LOCK
|
|
LD (HL),$FE ; RELEASE MUTEX LOCK
|
|
POP HL ; RESTORE HL
|
|
#ENDIF
|
|
|
|
RET ; RETURN TO CALLER
|
|
;
|
|
;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;; BNKSEL - Switch Memory Bank to Bank in A.
|
|
;; Preserve all Registers including Flags.
|
|
;;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;
|
|
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:
|
|
;
|
|
#IF (MEMMGR == MM_SBC)
|
|
#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 (MEMMGR == MM_Z2)
|
|
BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE
|
|
JR Z,HBX_ROM ; NOT SET, SELECT ROM PAGE
|
|
RES 7,A ; RAM PAGE REQUESTED: CLEAR ROM BIT
|
|
ADD A,16 ; ADD 16 x 32K - RAM STARTS FROM 512K
|
|
;
|
|
HBX_ROM:
|
|
RLCA ; TIMES 2 - GET 16K PAGE INSTEAD OF 32K
|
|
OUT (MPGSEL_0),A ; BANK_0: 0K - 16K
|
|
INC A ;
|
|
OUT (MPGSEL_1),A ; BANK_1: 16K - 32K
|
|
#IF (CPUFAM == CPU_Z280)
|
|
;PCACHE ; PURGE CACHES
|
|
.DB $ED,$65
|
|
#ENDIF
|
|
RET ; DONE
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_N8)
|
|
BIT 7,A ; TEST BIT 7 FOR RAM VS. ROM
|
|
JR Z,HBX_ROM ; IF NOT SET, SELECT ROM PAGE
|
|
;
|
|
HBX_RAM:
|
|
RES 7,A ; CLEAR BIT 7 FROM ABOVE
|
|
RLCA ; SCALE SELECTOR TO
|
|
RLCA ; ... GO FROM Z180 4K PAGE SIZE
|
|
RLCA ; ... TO DESIRED 32K PAGE SIZE
|
|
OUT0 (Z180_BBR),A ; WRITE TO BANK BASE
|
|
LD A,N8_DEFACR | 80H ; SELECT RAM BY SETTING BIT 7
|
|
OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER
|
|
RET ; DONE
|
|
;
|
|
HBX_ROM:
|
|
OUT0 (N8_RMAP),A ; BANK INDEX TO N8 RMAP REGISTER
|
|
XOR A ; ZERO ACCUM
|
|
OUT0 (Z180_BBR),A ; ZERO BANK BASE
|
|
LD A,N8_DEFACR ; SELECT ROM BY CLEARING BIT 7
|
|
OUT0 (N8_ACR),A ; ... IN N8 ACR REGISTER
|
|
RET ; DONE
|
|
;
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_Z180)
|
|
RLCA ; RAM FLAG TO CARRY FLAG AND BIT 0
|
|
JR NC,HBX_BNKSEL1 ; IF NC, WANT ROM PAGE, SKIP AHEAD
|
|
XOR %00100001 ; SET BIT FOR HI 512K, CLR BIT 0
|
|
HBX_BNKSEL1:
|
|
RLCA ; CONTINUE SHIFTING TO SCALE SELECTOR
|
|
RLCA ; FOR Z180 4K PAGE -> DESIRED 32K PAGE
|
|
OUT0 (Z180_BBR),A ; WRITE TO BANK BASE
|
|
RET ; DONE
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_Z280)
|
|
; TBD
|
|
RET ; DONE
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_ZRC)
|
|
BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE
|
|
JR Z,HBX_ROM ; NOT SET, SELECT ROM PAGE
|
|
RES 7,A ; RAM PAGE REQUESTED: CLEAR ROM BIT
|
|
ADD A,$10 ; ADD 16 x 32K - RAM STARTS FROM 512K
|
|
;
|
|
HBX_ROM:
|
|
OUT ($1F),A ; HCS WRITE TO THE BANK CONTROL REGISTER
|
|
RET ; DONE
|
|
#ENDIF
|
|
;
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Copy Data - Possibly between banks. This resembles CP/M 3, but
|
|
; usage of the HL and DE registers is reversed.
|
|
; Caller MUST preset HBX_SRCBNK and HBX_DSTBNK.
|
|
; IM1/IM2 interrupts are disabled during HBX_BNKCPY.
|
|
; Enter:
|
|
; HL = Source Address
|
|
; DE = Destination Address
|
|
; BC = Number of bytes to copy
|
|
; Exit : None
|
|
; Uses : AF,BC,DE,HL
|
|
;
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;
|
|
HBX_BNKCPY:
|
|
#IF (CPUFAM == CPU_Z280)
|
|
PUSH IY
|
|
PUSH BC
|
|
;LD C,$00
|
|
LD C,Z280_MSR
|
|
;LDCTL IY,(C)
|
|
.DB $FD,$ED,$66
|
|
POP BC
|
|
PUSH IY
|
|
DI
|
|
#ELSE
|
|
LD A,I
|
|
DI
|
|
PUSH AF
|
|
#ENDIF
|
|
LD (HBX_BC_SP),SP ; PUT STACK
|
|
LD SP,HBX_TMPSTK ; ... IN HI MEM
|
|
|
|
LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
PUSH AF ; AND SAVE TO RESTORE LATER
|
|
PUSH BC ; CUR LEN -> (SP)
|
|
;
|
|
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_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, IFF > 0 BYTES
|
|
POP AF ; RECOVER ORIGINAL BANK
|
|
CALL HBX_BNKSEL ; SWITCH
|
|
|
|
LD SP,$FFFF ; RESTORE STACK
|
|
HBX_BC_SP .EQU $ - 2 ; ... TO ORIGINAL VALUE
|
|
#IF (CPUFAM == CPU_Z280)
|
|
POP IY
|
|
PUSH BC
|
|
LD C,Z280_MSR
|
|
;LDCTL (C),IY
|
|
.DB $FD,$ED,$6E
|
|
POP BC
|
|
POP IY
|
|
#ELSE
|
|
POP AF
|
|
JP PO,$+4
|
|
EI
|
|
#ENDIF
|
|
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 = UPDATED SRC, DE = UPDATED DEST, BC = 0
|
|
RET
|
|
;
|
|
; 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 TARGET BANK IS PREPARED FOR THEM.
|
|
; ON INPUT A=TARGET BANK, IX=TARGET ADDRESS
|
|
;
|
|
HBX_BNKCALL:
|
|
LD (HBX_TGTBNK),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW
|
|
LD (HBX_TGTADR),IX ; 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
|
|
HBX_TGTADR .EQU $ + 1
|
|
CALL $FFFF ; CALL ROUTINE ($FFFF IS OVERLAID ABOVE)
|
|
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
|
|
;
|
|
; THESE ROUTINES ARE NOT INTENDED TO BE CALLED DIRECTLY -- THEY ARE
|
|
; HELPERS FOR THE HBIOS API AND ARE CALLED BY HBIOS BANK CODE. THE
|
|
; HBIOS BANK CODE BRACKETS THE USE OF THESE ROUTINES WITH DI/EI IF
|
|
; NECESSARY FOR THE CURRENT INTERRUPT MODE.
|
|
;
|
|
; NOTE: THE SIZE OF HBX_TMPSTK (TYPICALLY 20 BYTES) IS INSUFFICIENT FOR
|
|
; FREERTOS IF AN INTERRUPT STRIKES WHILE THE TEMPORARY STACK IS ACTIVE.
|
|
; BELOW, HBX_BUF HAS BEEN USURPED TO PROVIDE A LARGER TEMP STACK TO
|
|
; ACCOMMODATE FREERTOS. HBX_BUF IS ONLY USED AS A BOUNCE BUFFER, SO IT'S
|
|
; USE WILL NEVER OVERLAP WITH BELOW.
|
|
;
|
|
HBX_PEEK:
|
|
LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_BUF_END ; BORROW HBX_BUF FOR TEMP STACK
|
|
LD A,(HB_CURBNK)
|
|
PUSH AF
|
|
LD A,D
|
|
CALL HBX_BNKSEL
|
|
LD E,(HL)
|
|
JR HBX_PPRET
|
|
;
|
|
HBX_POKE:
|
|
LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_BUF_END ; BORROW HBX_BUF FOR TEMP STACK
|
|
LD A,(HB_CURBNK)
|
|
PUSH AF
|
|
LD A,D
|
|
CALL HBX_BNKSEL
|
|
LD (HL),E
|
|
;
|
|
HBX_PPRET:
|
|
POP AF
|
|
CALL HBX_BNKSEL
|
|
LD SP,0 ; RESTORE ORIGINAL STACK FRAME
|
|
HBX_PPSP .EQU $ - 2
|
|
RET
|
|
;
|
|
; PRIVATE STACK AT END OF HBIOS CODE
|
|
; OCCUPIES SPACE BEFORE IVT
|
|
;
|
|
HBX_INTSTKSIZ .EQU $FF00 - $
|
|
.ECHO "HBIOS INT STACK space: "
|
|
.ECHO HBX_INTSTKSIZ
|
|
.ECHO " bytes.\n"
|
|
.FILL HBX_INTSTKSIZ,$FF
|
|
HBX_INTSTK .EQU $
|
|
;
|
|
#IF (HBX_INTSTKSIZ < 24)
|
|
.ECHO "*** ERROR: INTERRUPT STACK IS TOO SMALL!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
; HBIOS INTERRUPT SLOT ASSIGNMENTS
|
|
;
|
|
; # Z80 Z180
|
|
; --- -------------- --------------
|
|
; 0 CTC0A INT1 -+
|
|
; 1 CTC0B INT2 |
|
|
; 2 CTC0C TIM0 |
|
|
; 3 CTC0D TIM1 |
|
|
; 4 DMA0 +- Z180 INTERNAL
|
|
; 5 DMA1 |
|
|
; 6 CSIO |
|
|
; 7 SIO0 SER0 |
|
|
; 8 SIO1 SER1 -+
|
|
; 9 PIO0A PIO0A
|
|
; 10 PIO0B PIO0B
|
|
; 11 PIO1A PIO1A
|
|
; 12 PIO1B PIO1B
|
|
; 13 SIO0
|
|
; 14 SIO1
|
|
; 15
|
|
;
|
|
HBX_IVT:
|
|
.DW HBX_IV00
|
|
.DW HBX_IV01
|
|
.DW HBX_IV02
|
|
.DW HBX_IV03
|
|
.DW HBX_IV04
|
|
.DW HBX_IV05
|
|
.DW HBX_IV06
|
|
.DW HBX_IV07
|
|
.DW HBX_IV08
|
|
.DW HBX_IV09
|
|
.DW HBX_IV0A
|
|
.DW HBX_IV0B
|
|
.DW HBX_IV0C
|
|
.DW HBX_IV0D
|
|
.DW HBX_IV0E
|
|
.DW HBX_IV0F
|
|
;
|
|
HBX_IVTCNT .EQU ($ - HBX_IVT) / 2
|
|
;
|
|
HBX_IV00: CALL HBX_INT \ .DB $00 << 2
|
|
HBX_IV01: CALL HBX_INT \ .DB $01 << 2
|
|
HBX_IV02: CALL HBX_INT \ .DB $02 << 2
|
|
HBX_IV03: CALL HBX_INT \ .DB $03 << 2
|
|
HBX_IV04: CALL HBX_INT \ .DB $04 << 2
|
|
HBX_IV05: CALL HBX_INT \ .DB $05 << 2
|
|
HBX_IV06: CALL HBX_INT \ .DB $06 << 2
|
|
HBX_IV07: CALL HBX_INT \ .DB $07 << 2
|
|
HBX_IV08: CALL HBX_INT \ .DB $08 << 2
|
|
HBX_IV09: CALL HBX_INT \ .DB $09 << 2
|
|
HBX_IV0A: CALL HBX_INT \ .DB $0A << 2
|
|
HBX_IV0B: CALL HBX_INT \ .DB $0B << 2
|
|
HBX_IV0C: CALL HBX_INT \ .DB $0C << 2
|
|
HBX_IV0D: CALL HBX_INT \ .DB $0D << 2
|
|
HBX_IV0E: CALL HBX_INT \ .DB $0E << 2
|
|
HBX_IV0F: CALL HBX_INT \ .DB $0F << 2
|
|
;
|
|
#ENDIF
|
|
;
|
|
INT_IM1:
|
|
#IF (INTMODE == 1)
|
|
CALL HBX_INT
|
|
.DB $00
|
|
#ELSE
|
|
RETI ; UNEXPECTED INT, RET W/ INTS LEFT DISABLED
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE > 0)
|
|
;
|
|
; COMMON INTERRUPT DISPATCHING CODE
|
|
; SETUP AND CALL HANDLER IN BIOS BANK
|
|
;
|
|
HBX_INT: ; COMMON INTERRUPT ROUTING CODE
|
|
;
|
|
EX (SP),HL ; SAVE HL AND GET INT JP TABLE OFFSET
|
|
|
|
LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_INTSTK ; USE DEDICATED INT STACK FRAME IN HI MEM
|
|
|
|
; SAVE STATE (HL SAVED PREVIOUSLY ON ORIGINAL STACK FRAME)
|
|
PUSH AF ; SAVE AF
|
|
PUSH BC ; SAVE BC
|
|
PUSH DE ; SAVE DE
|
|
PUSH IY ; SAVE IY
|
|
|
|
LD A,BID_BIOS ; HBIOS BANK
|
|
CALL HBX_BNKSEL_INT ; SELECT IT
|
|
|
|
LD L,(HL) ; OFFSET INTO JP TABLE FOR THIS INT
|
|
LD H,HB_IVT >> 8 ; MSB OF HBIOS INT JP TABLE
|
|
|
|
CALL JPHL ; CALL HANDLER VIA INT JP TABLE
|
|
|
|
LD A,(HB_CURBNK) ; GET PRE-INT BANK
|
|
CALL HBX_BNKSEL ; SELECT IT
|
|
|
|
; RESTORE STATE
|
|
POP IY ; RESTORE IY
|
|
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
|
|
|
|
HB_EI ; ENABLE INTERRUPTS
|
|
RETI ; AND RETURN
|
|
;
|
|
#ENDIF
|
|
;
|
|
; SMALL TEMPORARY STACK FOR USE BY HBX_BNKCPY
|
|
;
|
|
HBX_TMPSTKSIZ .EQU (HBX_XFC - HBX_BUFSIZ - $)
|
|
.ECHO "HBIOS TEMP STACK space: "
|
|
.ECHO HBX_TMPSTKSIZ
|
|
.ECHO " bytes.\n"
|
|
.FILL HBX_TMPSTKSIZ,$CC
|
|
HBX_TMPSTK .EQU $
|
|
;
|
|
; INTERBANK COPY BOUNCE BUFFER (64 BYTES)
|
|
;
|
|
; N.B., THIS BUFFER IS ALSO USED AS A TEMPORARY STACK BY INVOKE, PEEK, AND POKE.
|
|
; THEREFORE, THIS BUFFER *CANNOT* BE USED TO PASS DATA OUTSIDE OF
|
|
; HBIOS FUNCTION CALLS.
|
|
;
|
|
HBX_BUF .FILL HBX_BUFSIZ,0
|
|
HBX_BUF_END .EQU $
|
|
;
|
|
; HBIOS PROXY MGMT BLOCK (TOP 32 BYTES)
|
|
;
|
|
#IFDEF ROMBOOT
|
|
.DB BID_BOOT ; HB_CURBNK: CURRENTLY ACTIVE LOW MEMORY BANK ID
|
|
#ELSE
|
|
.DB BID_USR ; HB_CURBNK: CURRENTLY ACTIVE LOW MEMORY BANK ID
|
|
#ENDIF
|
|
.DB $FF ; HB_INVBNK: BANK ACTIVE AT TIME OF HBIOS CALL INVOCATION
|
|
.DW 0 ; HB_SRCADR: BNKCPY SOURCE ADDRESS
|
|
.DB BID_USR ; HB_SRCBNK: BNKCPY SOURCE BANK ID
|
|
.DW 0 ; HB_DSTADR: BNKCPY DESTINATION ADDRESS
|
|
.DB BID_USR ; HB_DSTBNK: BNKCPY DESTINATION BANK ID
|
|
.DW 0 ; HB_CPYLEN: BNKCPY LENGTH
|
|
.FILL 5,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE
|
|
.DB $FE ; HB_LOCK: HBIOS MUTEX LOCK
|
|
JP HBX_INVOKE ; HB_INVOKE: FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08)
|
|
JP HBX_BNKSEL ; HB_BNKSEL: FIXED ADR ENTRY FOR HBX_BNKSEL
|
|
JP HBX_BNKCPY ; HB_BNKCPY: FIXED ADR ENTRY FOR HBX_BNKCPY
|
|
JP HBX_BNKCALL ; HB_BNKCALL: FIXED ADR ENTRY FOR HBX_BNKCALL
|
|
.DW HBX_IDENT ; ADDRESS OF HBIOS PROXY START (DEPRECATED)
|
|
.DW HBX_IDENT ; HB_IDENT: ADDRESS OF HBIOS IDENT INFO DATA BLOCK
|
|
;
|
|
.FILL MEMTOP - $ ; FILL TO END OF MEMORY (AS NEEDED)
|
|
.ORG HBX_IMG + HBX_SIZ ; RESET ORG
|
|
;
|
|
;==================================================================================================
|
|
; HBIOS CORE
|
|
;==================================================================================================
|
|
;
|
|
;==================================================================================================
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; INTERRUPT VECTOR TABLE (MUST START AT PAGE BOUNDARY!!!)
|
|
;==================================================================================================
|
|
;
|
|
; IM1 INTERRUPTS ARRIVE HERE AFTER BANK SWITCH TO HBIOS BANK
|
|
; LIST OF IM1 INT CALLS IS BUILT DYNAMICALLY BELOW
|
|
; SEE HB_ADDIM1 ROUTINE
|
|
; EACH ENTRY WILL LOOK LIKE:
|
|
; CALL XXXX ; CALL INT HANDLER
|
|
; RET NZ ; RETURN IF HANDLED
|
|
;
|
|
; NOTE THAT THE LIST IS INITIALLY FILLED WITH CALLS TO HB_BADINT.
|
|
; AS THE TABLE IS POPULATED, THE ADDRESS OF HB_BADINT IS OVERLAID
|
|
; WITH THE ADDRESS OF A REAL INTERRUPT HANDLER.
|
|
;
|
|
; THERE IS ROOM FOR 8 ENTRIES PLUS A FINAL CALL TO HB_BADINT.
|
|
;
|
|
#IF (INTMODE < 2)
|
|
;
|
|
HB_IVT:
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
CALL HB_BADINT \ RET NZ
|
|
;
|
|
#ENDIF
|
|
;
|
|
; IM2 INTERRUPTS ARRIVE HERE AFTER BANK SWITCH TO HBIOS BANK
|
|
; THE LIST OF JP TABLE ENTRIES MATCHES THE IM2 VECTORS ONE FOR
|
|
; ONE. ANY CALL TO THE PRIMARY IVT (HBX_IVT) WILL BE MAPPED TO
|
|
; THE CORRESPONDING JP TABLE ENTRY BELOW AFTER THE BANK SWITCH.
|
|
;
|
|
; NOTE THAT THE LIST IS INITIALLY FILLED WITH CALLS TO HB_BADINT.
|
|
; IT IS INTENDED THAT HARDWARE DRIVERS WILL DYNAMICALLY OVERLAY
|
|
; THE ADDRESS PORTION OF THE APPROPRIATE JP TO POINT TO THE
|
|
; DESIRED INTERRUPT HANDLER DURING THE DRIVERS INITIALIZATION.
|
|
;
|
|
; NOTE THAT EACH ENTRY HAS A FILLER BYTE OF VALUE ZERO. THIS BYTE
|
|
; HAS NO FUNCTION. IT IS JUST USED TO MAKE ENTRIES AN EVEN 4 BYTES.
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
HB_IVT:
|
|
HB_IVT00: JP HB_BADINT \ .DB 0
|
|
HB_IVT01: JP HB_BADINT \ .DB 0
|
|
HB_IVT02: JP HB_BADINT \ .DB 0
|
|
HB_IVT03: JP HB_BADINT \ .DB 0
|
|
HB_IVT04: JP HB_BADINT \ .DB 0
|
|
HB_IVT05: JP HB_BADINT \ .DB 0
|
|
HB_IVT06: JP HB_BADINT \ .DB 0
|
|
HB_IVT07: JP HB_BADINT \ .DB 0
|
|
HB_IVT08: JP HB_BADINT \ .DB 0
|
|
HB_IVT09: JP HB_BADINT \ .DB 0
|
|
HB_IVT0A: JP HB_BADINT \ .DB 0
|
|
HB_IVT0B: JP HB_BADINT \ .DB 0
|
|
HB_IVT0C: JP HB_BADINT \ .DB 0
|
|
HB_IVT0D: JP HB_BADINT \ .DB 0
|
|
HB_IVT0E: JP HB_BADINT \ .DB 0
|
|
HB_IVT0F: JP HB_BADINT \ .DB 0
|
|
;
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; SYSTEM INITIALIZATION
|
|
;==================================================================================================
|
|
;
|
|
HB_START:
|
|
DI ; NO INTERRUPTS
|
|
IM 1 ; INTERRUPT MODE 1
|
|
;
|
|
#IF (DIAGENABLE)
|
|
LD A,%00000001
|
|
OUT (DIAGPORT),A
|
|
#ENDIF
|
|
;
|
|
LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
;LD C,Z280_CCR ; CACHE CONTROL REGISTER
|
|
;LD HL,$0060 ; DISABLE INSTRUCTION CACHE
|
|
;;LDCTL (C),HL ; SET IT (8 BITS)
|
|
;.DB $ED,$6E
|
|
;;PCACHE ; PURGE ANY REMNANTS OF CACHE
|
|
;.DB $ED,$65
|
|
;
|
|
LD C,Z280_BTCR ; BUS TIMING AND CONTROL REGISTER
|
|
LD HL,$0033 ; 3 I/O WAIT STATES ADDED
|
|
;LD HL,$00F3 ; 3 I/O W/S & 3 INT ACK W/S
|
|
;LDCTL (C),HL ; SET IT (8 BITS)
|
|
.DB $ED,$6E
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; SET BASE FOR CPU IO REGISTERS
|
|
; DO NOT USE Z180_ICR FROM Z180.INC BECAUSE THE ICR
|
|
; IS NOT YET AT THE RUNNING LOCATION. AT RESET, THE Z180
|
|
; REGISTER BASE I/O ADDRESS IS ZERO, SO INITIALLY, ICR IS
|
|
; AT $3F.
|
|
LD A,Z180_BASE
|
|
OUT0 ($3F),A ; AT RESET, ICR IS AT $3F
|
|
|
|
DIAG(%00000010)
|
|
|
|
; DISABLE REFRESH
|
|
XOR A
|
|
OUT0 (Z180_RCR),A
|
|
|
|
; MASK OFF TIMER INTERRUPTS
|
|
XOR A
|
|
OUT0 (Z180_TCR),A
|
|
OUT0 (Z180_ITC),A
|
|
|
|
; SET DEFAULT CPU CLOCK MULTIPLIERS (XTAL / 2)
|
|
;
|
|
; IT HAS BEEN REPORTED THAT CMR NEEDS TO BE SET PRIOR TO CCR
|
|
; SEEMS COUNTER-INTUITIVE AND I NEVER EXPERIENCED A PROBLEM
|
|
; RELATED TO ORDER, BUT JUST FOR GOOD MEASURE, CMR
|
|
; IS SET PRIOR TO CCR BELOW.
|
|
; https://www.retrobrewcomputers.org/forum/index.php?t=msg&th=316&#msg_5045
|
|
XOR A
|
|
OUT0 (Z180_CMR),A
|
|
OUT0 (Z180_CCR),A
|
|
|
|
; SET DEFAULT WAIT STATES
|
|
LD A,$F0
|
|
OUT0 (Z180_DCNTL),A
|
|
|
|
#IF ((MEMMGR == MM_Z180) | (MEMMGR == MM_N8))
|
|
; Z180 MMU SETUP
|
|
LD A,$80
|
|
OUT0 (Z180_CBAR),A ; SETUP FOR 32K/32K BANK CONFIG
|
|
;#IFDEF ROMBOOT
|
|
; XOR A
|
|
; OUT0 (Z180_BBR),A ; BANK BASE = 0
|
|
;#ENDIF
|
|
LD A,(RAMSIZE + RAMBIAS - 64) >> 2
|
|
OUT0 (Z180_CBR),A ; COMMON BASE = LAST (TOP) BANK
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (EIPCENABLE)
|
|
LD A,(EIPC_WDT_CONST | EIPC_HALT_RUN | EIPC_WDT_P2_22)
|
|
OUT (EIPC_WDTMR),A ; CLEAR WDTE BIT (DISABLE WATCHDOG)
|
|
LD A,EIPC_DIS_WDT ; DISABLE WDT - SECOND KEY
|
|
OUT (EIPC_WDTCR),A
|
|
LD A,EIPC_WCR ; SET SYSTEM CONTROL REGISTER POINTER
|
|
; (SCRP) TO POINT TO WAIT STATE
|
|
OUT (EIPC_SCRP),A ; CONTROL REGISTER (WCR)
|
|
LD A,(EIPC_IO_0WS | EIPC_MEM_OWS | EIPC_OCF_0WS | EIPC_INT_0WS | EIPC_CHAIN_0WS)
|
|
OUT (EIPC_SCDP),A ; NO WAIT STATES
|
|
LD A,EIPC_MCR ; SET SCRP TO POINT TO MISCELLANEOUS
|
|
OUT (EIPC_SCRP),A ; CONTROL REGISTER (MCR)
|
|
LD A,EIPC_CLKDIV1 ; DIVIDE CLOCK BY 1, /CS0 DISABLE
|
|
OUT (EIPC_SCDP),A ; SET SYSTEM CONTROL DATA PORT (SCDP)
|
|
#ENDIF
|
|
;
|
|
#IF (MEMMGR == MM_Z2)
|
|
; SET PAGING REGISTERS
|
|
#IFDEF ROMBOOT
|
|
XOR A
|
|
OUT (MPGSEL_0),A
|
|
INC A
|
|
OUT (MPGSEL_1),A
|
|
#ENDIF
|
|
LD A,62
|
|
OUT (MPGSEL_2),A
|
|
INC A
|
|
OUT (MPGSEL_3),A
|
|
; ENABLE PAGING
|
|
LD A,1
|
|
OUT (MPGENA),A
|
|
#ENDIF
|
|
;
|
|
DIAG(%00000011)
|
|
LED($00)
|
|
;
|
|
; CHECK BATTERY BACKUP STATUS BEFORE WE COPY PROXY TO UPPER MEMORY
|
|
;
|
|
; IF A DS1210 POWER CONTROLLER IS INSTALLED AND BATTERY BACKUP IS NOT INSTALLED
|
|
; OR IS LESS THAN 2V THEN THE DS1210 WILL BLOCK THE SECOND RAM ACCESS.
|
|
; FAILURE TO COMPLETE TWO RAM ACCESSES BEFORE INSTALLING PROXY WILL RESULT
|
|
; IN THE ROM ID BYTES NOT BEING COPIED CORRECTLY AND CP/M APPLICATIONS
|
|
; WILL NOT START CORRECTLY WHEN THEY CHECK THE ROM ID VERSION BYTES.
|
|
; THE BATTERY CONDITION VALUE IS TEMPORARILY STORED AT HBX_LOC - 1.
|
|
; IF THERE IS NO DS1210 IN THE SYSTEM, THE CODE BELOW DOES NO HARM.
|
|
;
|
|
DEC SP ; RESERVE A STACK BYTE
|
|
XOR A ; ZERO MEANS LOW BAT
|
|
LD (HBX_LOC - 1),A ; WRITE IT (SHOULD ALWAYS WORK)
|
|
INC A ; 1 MEANS BAT OK
|
|
LD (HBX_LOC - 1),A ; OVERWRITE IF NVC ALLOWS IT
|
|
;
|
|
; IF APPBOOT, SAVE CURRENT BANKID
|
|
;
|
|
; THIS IS NOT GOING TO WORK IF THE APP BOOT IMAGE IS LOADED
|
|
; USING THE UNA FAT32 LOADER. SHOULD PROBABLY CHECK THAT THERE
|
|
; IS A VALID ROMWBW PROXY IN MEMORY BEFORE DOING THIS. HOWEVER,
|
|
; THIS USE CASE IS PROBABLY NON-EXISTENT. THE IMG BOOT IMAGE
|
|
; SHOULD WORK FINE WITH THE UNA FAT32 LOADER.
|
|
;
|
|
#IFDEF APPBOOT
|
|
LD A,(HB_CURBNK)
|
|
DEC SP ; RESERVE A STACK BYTE
|
|
LD (HBX_LOC - 2),A ; SAVE BANK
|
|
PUSH AF ; ALSO ON STACK
|
|
#ENDIF
|
|
;
|
|
; INSTALL PROXY IN UPPER MEMORY
|
|
;
|
|
LD DE,HBX_LOC ; AS PER ABOVE
|
|
LD HL,HBX_IMG
|
|
LD BC,HBX_SIZ
|
|
LDIR
|
|
;
|
|
; IF APPBOOT, RESTORE CURRENT BANK ID
|
|
;
|
|
#IFDEF APPBOOT
|
|
POP AF
|
|
LD (HB_CURBNK),A
|
|
#ENDIF
|
|
;
|
|
; IF ALREADY EXECUTING IN RAM, BYPASS RAM BANK INSTALLATION
|
|
;
|
|
LD A,(HB_RAMFLAG)
|
|
OR A
|
|
JR NZ,HB_START1
|
|
;
|
|
; INSTALL HBIOS IN RAM BANK
|
|
;
|
|
LD A,(HB_CURBNK)
|
|
LD (HB_SRCBNK),A
|
|
LD A,BID_BIOS
|
|
LD (HB_DSTBNK),A
|
|
LD HL,0
|
|
LD DE,0
|
|
LD BC,$8000
|
|
CALL HBX_BNKCPY
|
|
;DI
|
|
;
|
|
; TRANSITION TO HBIOS IN RAM BANK
|
|
;
|
|
LD A,BID_BIOS ; BIOS BANK ID
|
|
LD IX,HB_START1 ; EXECUTION RESUMES HERE
|
|
CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN
|
|
HALT ; WE SHOULD NOT COME BACK HERE!
|
|
;
|
|
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
|
|
;
|
|
DIAG(%00000111)
|
|
;
|
|
LD A,(HBX_LOC - 1) ; RECALL BATTERY STATE AND SAVE
|
|
LD (HB_BATCOND),A ; FOR FUTURE REFERENCE
|
|
;
|
|
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
|
|
;
|
|
; GET AND SAVE APP BOOT BANK ID
|
|
LD A,(HBX_LOC - 2)
|
|
LD (HB_APPBNK),A
|
|
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; RECOVERY MODE
|
|
;==================================================================================================
|
|
;
|
|
; PLATFORM SPECIFIC CODE FOR DETECTING RECOVERY MODE SWITCH
|
|
;
|
|
#IF (BT_REC_TYPE != BT_REC_NONE)
|
|
#IF (BT_REC_TYPE == BT_REC_FORCE)
|
|
LD A,1 ; SET FOR RECOVERY MODE
|
|
LD (HB_BOOT_REC),A ; SAVE FOR LATER
|
|
#ENDIF
|
|
#IF (PLATFORM == PLT_SBC)
|
|
#IF (BT_REC_TYPE == BT_REC_SBC01)
|
|
LD A,%00100000 ; DISABLE RTC AND
|
|
OUT (RTCIO),A ; DRQ DRIVER READ
|
|
IN A,(RTCIO) ; BIT 0 (DRQ).
|
|
CPL ; PULLED HIGH
|
|
AND 1 ; IS RECOVERY MODE
|
|
LD (HB_BOOT_REC),A ; SAVE FOR LATER
|
|
#ENDIF
|
|
#IF (BT_REC_TYPE == BT_REC_SBC1B)
|
|
IN A,(RTCIO) ; RTC PORT, BIT 6 HAS THE
|
|
BIT 6,A ; STATE OF CONFIG JUMPER
|
|
LD A,1 ; JUMPER INSTALLED
|
|
JR Z,SAVE_REC_M ; IS RECOVERY MODE
|
|
LD A,0
|
|
SAVE_REC_M:
|
|
LD (HB_BOOT_REC),A ; SAVE FOR LATER
|
|
#ENDIF
|
|
#IF (BT_REC_TYPE == BT_REC_SBCRI)
|
|
IN A,($68 + 6) ; UART_MSR MODEM
|
|
BIT 6,A ; STATUS REGISTER
|
|
LD A,0 ; BIT 6
|
|
JR Z,SAVE_REC_M ; IS RECOVERY MODE
|
|
LD A,1
|
|
SAVE_REC_M:
|
|
LD (HB_BOOT_REC),A ; SAVE FOR LATER
|
|
#ENDIF
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
DIAG(%00001111)
|
|
;
|
|
#IF (DSKYENABLE)
|
|
LD HL,MSG_HBVER + 5
|
|
LD A,(DSKY_NUMS + RMJ)
|
|
AND $7F
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(DSKY_NUMS + RMN)
|
|
AND $7F
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(DSKY_NUMS + RUP)
|
|
LD (HL),A
|
|
LD HL,MSG_HBVER
|
|
CALL DSKY_SHOWSEG
|
|
#ENDIF
|
|
;
|
|
#IF (WBWDEBUG == USEMIO) ; BUFFER OUTPUT UNTIL
|
|
CALL MIO_INIT ; WE GET TO BOOT MESSAGE
|
|
#ENDIF
|
|
;
|
|
#IF 0
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
PRTS("DEBUG-IVT$")
|
|
LD DE,HB_IVT
|
|
CALL DUMP_BUFFER
|
|
CALL NEWLINE
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
; DISCOVER CPU TYPE
|
|
;
|
|
; SOME OF THIS CODE IS DERIVED FROM UNA BY JOHN COFFMAN
|
|
;
|
|
; 0: Z80
|
|
; 1: Z80180 - ORIGINAL Z180 (EQUIVALENT TO HD64180)
|
|
; 2: Z8S180 - ORIGINAL S-CLASS, REV. K, AKA SL1960, NO ASCI BRG
|
|
; 3: Z8S180 - REVISED S-CLASS, REV. N, W/ ASCI BRG
|
|
; 4: Z8280
|
|
;
|
|
LD HL,0 ; L = 0 MEANS Z80
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
;
|
|
; TEST FOR ORIGINAL Z180 USING MLT
|
|
LD DE,$0506 ; 5 X 6
|
|
MLT DE ; DE = 30 IF Z180
|
|
LD A,E ; CHECK IF MULTIPLY HAPPENED
|
|
CP 30
|
|
JR NZ,HB_CPU1 ; IT IS A Z80 IF != 30
|
|
INC L ; FLAG Z80180 OR BETTER
|
|
;
|
|
; TEST FOR OLDER S-CLASS (REV K)
|
|
IN0 A,(Z180_CCR) ; SUPPOSEDLY ONLY ON S-CLASS
|
|
INC A ; FF -> 0
|
|
JR Z,HB_CPU1
|
|
INC L ; FLAG Z8S180 REV K (SL1960) OR BETTER
|
|
;
|
|
; TEST FOR NEWER S-CLASS (REV N)
|
|
; ON OLDER S-CLASS, ASCI TIME CONSTANT REG DOES NOT EXIST
|
|
; AND WILL ALWYAS READ BACK AS $FF
|
|
OUT0 (Z180_ASTC1L),D ; D = 0 AT THIS POINT
|
|
IN0 A,(Z180_ASTC1L) ; ASCI TIME CONSTANT REG
|
|
INC A ; FF -> 0
|
|
JR Z,HB_CPU1
|
|
INC L ; FLAG Z8S180 REV N W/ ASCI BRG
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
;
|
|
; TEST FOR Z280 PER ZILOG DOC
|
|
LD A,$40 ; INITIALIZE THE OPERAND
|
|
.DB $CB,$37 ; THIS INSTRUCTION WILL SET THE S FLAG
|
|
; ON THE Z80 CPU AND CLEAR THE S FLAG
|
|
; ON THE Z280 MPU.
|
|
JP M,HB_CPU1 ; IF Z80, SKIP AHEAD
|
|
LD L,4 ; WE ARE Z280
|
|
;
|
|
#ENDIF
|
|
;
|
|
HB_CPU1:
|
|
LD A,L
|
|
LD (HB_CPUTYPE),A
|
|
;
|
|
#IF (DSRTCENABLE)
|
|
CALL DSRTC_PREINIT
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
;
|
|
; AT BOOT, Z180 PHI IS OSC / 2
|
|
LD C,(CPUOSC / 2) / 1000000
|
|
LD DE,(CPUOSC / 2) / 1000
|
|
;
|
|
#IF (Z180_CLKDIV >= 1)
|
|
LD A,(HB_CPUTYPE) ; GET CPU TYPE
|
|
CP 2 ; Z8S180 REV K OR BETTER?
|
|
JR C,HB_CPU2 ; IF NOT, NOT POSSIBLE!
|
|
; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED
|
|
LD A,$80
|
|
OUT0 (Z180_CCR),A
|
|
; REFLECT SPEED CHANGE
|
|
LD C,CPUOSC / 1000000
|
|
LD DE,CPUOSC / 1000
|
|
#ENDIF
|
|
|
|
#IF (Z180_CLKDIV >= 2)
|
|
LD A,(HB_CPUTYPE) ; GET CPU TYPE
|
|
CP 3 ; Z8S180 REV N OR BETTER?
|
|
JR C,HB_CPU2 ; IF NOT, NOT POSSIBLE!
|
|
; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED
|
|
; ALSO SET CCR AGAIN BECAUSE OF REPORTS THAT CCR
|
|
; *MUST* BE SET AFTER CMR.
|
|
LD A,$80
|
|
OUT0 (Z180_CMR),A ; CPU MULTIPLIER
|
|
OUT0 (Z180_CCR),A ; CLOCK DIVIDE
|
|
; REFLECT SPEED CHANGE
|
|
LD C,(CPUOSC * 2) / 1000000
|
|
LD DE,(CPUOSC * 2) / 1000
|
|
#ENDIF
|
|
;
|
|
HB_CPU2:
|
|
; SAVE CPU SPEED IN CONFIG BLOCK
|
|
LD A,C
|
|
LD (CB_CPUMHZ),A
|
|
LD (CB_CPUKHZ),DE
|
|
;
|
|
#ENDIF
|
|
;
|
|
DIAG(%00011111)
|
|
;
|
|
; PERFORM DYNAMIC CPU SPEED DERIVATION
|
|
;
|
|
CALL HB_CPUSPD ; CPU SPEED DETECTION
|
|
;
|
|
CALL DELAY_INIT ; INITIALIZE SPEED COMPENSATED DELAY FUNCTIONS
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
;
|
|
; SET FINAL DESIRED WAIT STATES
|
|
LD A,0 + (Z180_MEMWAIT << 6) | (Z180_IOWAIT << 4)
|
|
OUT0 (Z180_DCNTL),A
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
;
|
|
LD C,Z280_BTCR ; BUS TIMING AND CONTROL REG
|
|
;LDCTL HL,(C) ; GET IT
|
|
.DB $ED,$66
|
|
LD A,L ; PUT IN A
|
|
AND %00111100 ; CLEAR DC AND I/O FIELDS
|
|
OR Z280_INTWAIT << 6 ; SET INT ACK WAIT STATES
|
|
OR Z280_IOWAIT ; SET I/O WAIT STATES
|
|
LD L,A ; BACK TO L
|
|
;LDCTL (C),HL ; SET IT
|
|
.DB $ED,$6E
|
|
;
|
|
LD C,Z280_BTIR ; BUS TIMING AND INIT REG
|
|
;LDCTL HL,(C) ; GET IT
|
|
.DB $ED,$66
|
|
LD A,L ; PUT IN A
|
|
AND %11110011 ; CLEAR DC AND I/O FIELDS
|
|
OR Z280_MEMWAIT << 2 ; SET LOW MEM WAIT STATES
|
|
LD L,A ; BACK TO L
|
|
;LDCTL (C),HL ; SET IT
|
|
.DB $ED,$6E
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE == 2)
|
|
; 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
|
|
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; SETUP Z180 IVT
|
|
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) ; SIMH TIMER
|
|
;
|
|
#IF (INTMODE == 1)
|
|
LD HL,HB_TIMINT
|
|
CALL HB_ADDIM1 ; ADD TO IM1 CALL LIST
|
|
#ENDIF
|
|
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (KIOENABLE)
|
|
LD A,%11111001 ; RESET ALL DEVICES, SET DAISYCHAIN
|
|
OUT (KIOBASE+$0E),A ; DO IT
|
|
#ENDIF
|
|
;
|
|
#IF (CTCENABLE)
|
|
CALL CTC_PREINIT
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
; MASK ALL EXTERNAL INTERRUPTS FOR NOW
|
|
LD A,$01 ; INT0 ENABLED, INT1-2 DISABLED
|
|
OUT0 (Z180_ITC),A ; WRITE TO INT/TRAP CONTROL REGISTER
|
|
;
|
|
; SETUP Z180 TIMER0 INTERRUPT VECTOR IN IVT
|
|
LD HL,HB_TIMINT
|
|
LD (IVT(INT_TIM0)),HL ; Z180 TIMER 0
|
|
|
|
; SETUP PERIODIC TIMER INTERRUPT ON TIMER 0
|
|
; *** THIS ASSUMES A TICKFREQ OF 50HZ!!! ***
|
|
;
|
|
#IF (TICKFREQ != 50)
|
|
.ECHO "TICKFREQ *MUST* BE 50 FOR Z180 TIMER\n"
|
|
!!!
|
|
#ENDIF
|
|
;
|
|
; Z180 PRESCALES THE COUNTER BY 20 SO,
|
|
; RLDR = CPU CLK / 20 / TICKFREQ
|
|
; IF WE ASSUME TICKFREQ = 50, WE CAN SIMPIFY TO
|
|
; RLDR = CPU CLK / 1000
|
|
; NOW IF DIVIDE BOTH SIDES BY 1000, WE CAN USE
|
|
; CPUKHZ VALUE AND SIMPLIFY TO
|
|
; RLDR = CPUKHZ
|
|
LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ
|
|
OUT0 (Z180_TMDR0L),L ; INITIALIZE TIMER 0 DATA REGISTER
|
|
OUT0 (Z180_TMDR0H),H
|
|
DEC HL ; RELOAD OCCURS *AFTER* ZERO
|
|
OUT0 (Z180_RLDR0L),L ; INITIALIZE TIMER 0 RELOAD REGISTER
|
|
OUT0 (Z180_RLDR0H),H
|
|
LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING
|
|
OUT0 (Z180_TCR),A
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
; INITIALIZE HEAP STORAGE
|
|
;
|
|
; INITIALIZE POINTERS
|
|
LD HL,HB_END ; HEAP FOLLOWS HBIOS CODE
|
|
LD (CB_HEAP),HL ; INIT HEAP BASE ADDRESS
|
|
LD (CB_HEAPTOP),HL ; INIT HEAP TOP ADDRESS
|
|
; CLEAR HEAP
|
|
LD BC,BNKTOP - HB_END ; MAX SIZE OF HEAP
|
|
LD A,$FF ; FILL WITH $FF
|
|
CALL FILL ; DO IT
|
|
;
|
|
DIAG(%00111111)
|
|
#IF 0
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE
|
|
CALL REGDMP
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
; PRE-CONSOLE INITIALIZATION
|
|
;
|
|
LD A,FORCECON ; CALCULATE PRE-INIT TABLE ; A IS INDEX OF CONSOLE DEVICE ENTRY
|
|
RLCA ; ENTRY THAT WE WANT TO ; A IS OFFSET OF CONSOLE DEVICE ENTRY
|
|
LD DE,(HB_PCINITTBL) ; EXECUTE FIRST ; DE IS VALUE OF TOP ENTRY
|
|
LD HL,HB_PCINITTBL ; HL IS ADDRESS OF TOP OF TABLE
|
|
PUSH HL ; PUSH (1) TOP OF TABLE
|
|
PUSH DE ; PUSH (2) VALUE OF TOP ENTRY
|
|
PUSH HL ; PUSH (3) TOP OF TABLE
|
|
CALL ADDHLA ; HL IS ADDRESS OF DESIRED CONSOLE ENTRY
|
|
POP DE ; PLACE IT AT THE TOP OF THE ; POP (3) DE IS TOP OF TABLE
|
|
PUSH HL ; TABLE BY SWAPPING IT ; PUSH (3) ADDRESS OF DESIRED CONSOLE ENTRY
|
|
LDI ; WITH THE FIRST (DUMMY) ; COPY DESIRED ENTRY
|
|
LDI ; ENTRY ; ... TO TOP OF TABLE
|
|
POP HL ; POP (3) HL IS ADDRESS OF DESIRED CONSOLE ENTRY
|
|
POP DE ; POP (2) DE IS VALUE OF ORIGINAL TOP ENTRY
|
|
LD (HL),E ; SAVE DE OVER ORIGINAL ENTRY
|
|
INC HL
|
|
LD (HL),D
|
|
LD B,HB_PCINITTBLLEN
|
|
POP DE ; POP (1) DE IS ADDRESS OF TOP OF TABLE
|
|
|
|
#IF (BT_REC_TYPE != BT_REC_NONE)
|
|
LD A,(HB_BOOT_REC) ; IF WE ARE IN RECOVERY MODE
|
|
OR A ; POINT TO THE RECOVER MODE
|
|
JR Z,NOT_REC_M0 ; INITIALIZATION TABLE
|
|
LD B,HB_PCINITRLEN
|
|
LD DE,HB_PCINIT_REC
|
|
NOT_REC_M0:
|
|
|
|
#ENDIF
|
|
CALL CALLLIST ; PROCESS THE PRE-INIT CALL TABLE
|
|
;
|
|
#IF 0
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE
|
|
CALL REGDMP
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
DIAG(%01111111)
|
|
LED($FF)
|
|
;
|
|
; PRIOR TO THIS POINT, CONSOLE I/O WAS NOT AVAILABLE UNLESS DIRECTED TO DEBUG OUTPUT I.E. XIO
|
|
; NOW THAT HBIOS IS READY, SET THE CONSOLE UNIT TO ACTIVATE CONSOLE I/O
|
|
; VIA HBIOS.
|
|
;
|
|
XOR A ; INITIALLY, FIRST SERIAL UNIT IS CONSOLE
|
|
LD (CB_CONDEV),A ; SAVE IT, ACTIVATES CONSOLE ON HBIOS
|
|
|
|
#IF (WBWDEBUG == USEMIO) ; OUTPUT ANY CACHED DEBUG TEXT
|
|
LD HL,MIOOUTPTR
|
|
LD E,(HL)
|
|
INC HL
|
|
LD D,(HL)
|
|
INC HL
|
|
NXTMIO: LD A,(HL)
|
|
CALL COUT
|
|
INC HL
|
|
LD A,L
|
|
CP E
|
|
JR NZ,NXTMIO
|
|
LD A,H
|
|
CP D
|
|
JR NZ,NXTMIO
|
|
; CALL WRITESTR ; WRITESTR WILL WORK WILL ONLY PRINT UP TO FIRST $
|
|
#ENDIF
|
|
;
|
|
#IF 0
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE2
|
|
PRTS("DEBUG+IVT$")
|
|
LD DE,HB_IVT
|
|
CALL DUMP_BUFFER
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
; ANNOUNCE HBIOS
|
|
;
|
|
CALL NEWLINE2
|
|
PRTX(STR_BANNER)
|
|
;
|
|
; DISPLAY HBIOS MUTEX ENABLED MESSAGE
|
|
;
|
|
#IF (HBIOS_MUTEX == TRUE)
|
|
CALL NEWLINE
|
|
CALL PRTSTRD
|
|
.TEXT "HBIOS MUTEX ENABLED$"
|
|
#ENDIF
|
|
;
|
|
DIAG(%11111111)
|
|
;
|
|
; IO PORT SCAN
|
|
;
|
|
#IF 0
|
|
PSCN:
|
|
LD C,0 ; IO PORT NUMBER
|
|
LD B,0 ; LOOP COUNTER
|
|
CALL NEWLINE
|
|
PSCN1:
|
|
CALL NEWLINE
|
|
LD A,C
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COLON
|
|
CALL PC_SPACE
|
|
CALL DELAY
|
|
LD A,C
|
|
LD (PSCNX),A
|
|
PSCNX .EQU $ + 1
|
|
IN A,(0)
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COMMA
|
|
PUSH BC
|
|
LD B,0
|
|
IN A,(C)
|
|
POP BC
|
|
CALL PRTHEXBYTE
|
|
INC C
|
|
DJNZ PSCN1
|
|
#ENDIF
|
|
;
|
|
#IF 0
|
|
HB_SPDTST:
|
|
CALL HB_CPUSPD ; CPU SPEED DETECTION
|
|
CALL NEWLINE
|
|
LD HL,(CB_CPUKHZ)
|
|
CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA
|
|
JR HB_SPDTST
|
|
#ENDIF
|
|
;
|
|
HB_EI ; INTERRUPTS SHOULD BE OK NOW
|
|
;
|
|
; DISPLAY PLATFORM INFORMATION
|
|
;
|
|
CALL NEWLINE2
|
|
PRTX(STR_PLATFORM)
|
|
;
|
|
LD A,(HB_CPUTYPE) ; GET CPU TYPE
|
|
LD DE,HB_CPU_STR ; DISPLAY IT
|
|
CALL PRTIDXDEA
|
|
;
|
|
PRTS(" @ $")
|
|
LD HL,(CB_CPUKHZ)
|
|
CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA
|
|
PRTS("MHz$")
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
PRTS(" IO=0x$")
|
|
LD A,Z180_BASE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
CALL PRTSTRD
|
|
.TEXT ", BUS @ $"
|
|
LD C,Z280_BTIR ; BUS TIMING AND CTL REG
|
|
;LDCTL HL,(C) ; GET IT
|
|
.DB $ED,$66
|
|
LD A,L ; MOVE TO A
|
|
AND %00000011 ; ISOLATE CS FIELD
|
|
LD HL,(CB_CPUKHZ) ; GET CPU SPEED
|
|
CP %00000001 ; BUS @ 1/1
|
|
JR Z,HB_Z280BUS ; GOT IT, SHOW IT
|
|
SRL H ; DIVIDE
|
|
RR L ; ... BY 2
|
|
CP %00000000 ; BUS @ 1/2
|
|
JR Z,HB_Z280BUS ; GOT IT, SHOW IT
|
|
SRL H ; DIVIDE
|
|
RR L ; ... BY 2
|
|
CP %00000010 ; BUS @ 1/4
|
|
JR Z,HB_Z280BUS ; GOT IT, SHOW IT
|
|
PRTS("???$") ; INVALID VALUE
|
|
JR HB_Z280BUS1 ; CONTINUE
|
|
HB_Z280BUS:
|
|
CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA
|
|
HB_Z280BUS1:
|
|
PRTS("MHz$") ; SUFFIX
|
|
#ENDIF
|
|
;
|
|
; DISPLAY CPU CONFIG
|
|
;
|
|
CALL NEWLINE
|
|
XOR A
|
|
#IF (CPUFAM == CPU_Z180)
|
|
LD A,Z180_MEMWAIT
|
|
#ENDIF
|
|
#IF (CPUFAM == CPU_Z280)
|
|
LD A,Z280_MEMWAIT
|
|
#ENDIF
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " MEM W/S, $"
|
|
LD A,1
|
|
#IF (CPUFAM == CPU_Z180)
|
|
LD A,Z180_IOWAIT + 1
|
|
#ENDIF
|
|
#IF (CPUFAM == CPU_Z280)
|
|
LD A,Z280_IOWAIT + 1
|
|
#ENDIF
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " I/O W/S$"
|
|
#IF (CPUFAM == CPU_Z280)
|
|
CALL PRTSTRD
|
|
.TEXT ", $"
|
|
LD A,Z280_INTWAIT
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " INT W/S$"
|
|
#ENDIF
|
|
#IF (INTMODE > 0)
|
|
CALL PRTSTRD
|
|
.TEXT ", INT MODE $"
|
|
LD A,INTMODE
|
|
CALL PRTDECB
|
|
#ENDIF
|
|
|
|
;
|
|
; DISPLAY MEMORY CONFIG
|
|
;
|
|
CALL NEWLINE
|
|
LD HL,ROMSIZE
|
|
CALL PRTDEC
|
|
CALL PRTSTRD
|
|
.TEXT "KB ROM, $"
|
|
LD HL,RAMSIZE
|
|
CALL PRTDEC
|
|
CALL PRTSTRD
|
|
.TEXT "KB RAM$"
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
CALL NEWLINE
|
|
PRTS("Z280: $")
|
|
PRTS("MSR=$")
|
|
LD C,Z280_MSR ; MASTER STATUS REGISTER
|
|
;LDTCL HL,(C) ; GET VALUE
|
|
.DB $ED,$66
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("BTCR=$")
|
|
LD C,Z280_BTCR ; BUS TIMING AND CONTROL REGISTER
|
|
;LDTCL HL,(C) ; GET VALUE
|
|
.DB $ED,$66
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("BTIR=$")
|
|
LD C,Z280_BTIR ; BUS TIMING AND CONTROL REGISTER
|
|
;LDTCL HL,(C) ; GET VALUE
|
|
.DB $ED,$66
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("CCR=$")
|
|
LD C,Z280_CCR ; CACHE CONTROL REGISTER
|
|
;LDTCL HL,(C) ; GET VALUE
|
|
.DB $ED,$66
|
|
CALL PRTHEXWORDHL
|
|
#ENDIF
|
|
;
|
|
; LOW BATTERY DIAGNOSTIC MESSAGE
|
|
;
|
|
#IF (BATCOND)
|
|
LD A,(HB_BATCOND)
|
|
OR A
|
|
LD DE,STR_LOWBAT
|
|
CALL Z,WRITESTR
|
|
#ENDIF
|
|
;
|
|
; PERFORM DEVICE INITIALIZATION
|
|
;
|
|
CALL NEWLINE
|
|
|
|
#IF (BT_REC_TYPE != BT_REC_NONE)
|
|
LD A,(HB_BOOT_REC) ; IF WE ARE IN RECOVERY MODE
|
|
OR A ; POINT TO THE RECOVER MODE
|
|
JR Z,NOT_REC_M1 ; INITIALIZATION TABLE
|
|
LD B,HB_INITRLEN
|
|
LD DE,HB_INIT_REC
|
|
JR IS_REC_M1
|
|
#ENDIF
|
|
|
|
NOT_REC_M1:
|
|
LD B,HB_INITTBLLEN
|
|
LD DE,HB_INITTBL
|
|
IS_REC_M1:
|
|
CALL CALLLIST
|
|
;
|
|
; RECORD HEAP CURB AT THE CURRENT VALUE OF HEAP TOP. HEAP CURB
|
|
; MARKS THE POINT IN THE HEAP AFTER WHICH MEMORY IS RELEASED
|
|
; WHEN AN HBIOS RESET IS PEFORMED.
|
|
;
|
|
LD HL,(CB_HEAPTOP)
|
|
LD (HEAPCURB),HL
|
|
;
|
|
; NOW SWITCH TO CRT CONSOLE IF CONFIGURED
|
|
;
|
|
#IF CRTACT
|
|
;
|
|
; BIOS IS CONFIGURED TO AUTO ACTIVATE CRT DEVICE. FIRST,
|
|
; CHECK TO SEE IF WE HAVE A VALID CRT DEVICE TO USE.
|
|
;
|
|
LD A,(CB_CRTDEV) ; GET THE CRT DEVICE
|
|
INC A ; INCREMENT TO TEST FOR $FF
|
|
JR Z,INITSYS3 ; IF NO CRT DEVICE, BYPASS CONSOLE SWITCH
|
|
;
|
|
; IF PLATFORM HAS A CONFIG JUMPER, CHECK TO SEE IF IT IS JUMPERED.
|
|
; IF SO, BYPASS SWITCH TO CRT CONSOLE (FAILSAFE MODE)
|
|
;
|
|
#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2))
|
|
IN A,(RTCIO) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER
|
|
BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE
|
|
JR Z,INITSYS3 ; Z=SHORTED, BYPASS CONSOLE SWITCH
|
|
#ENDIF
|
|
;
|
|
; NOTIFY USER OF CONSOLE SWITCH ON BOOT CONSOLE
|
|
CALL NEWLINE2
|
|
PRTX(STR_SWITCH)
|
|
CALL NEWLINE
|
|
;
|
|
; SWITCH TO CRT CONSOLE
|
|
LD A,(CB_CRTDEV) ; GET CRT DISPLAY DEVICE
|
|
LD (CB_CONDEV),A ; SAVE IT AS ACTIVE CONSOLE DEVICE
|
|
;
|
|
; DISPLAY HBIOS BANNER ON NEW CONSOLE
|
|
PRTX(STR_BANNER)
|
|
#ENDIF
|
|
;
|
|
INITSYS3:
|
|
;
|
|
CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE
|
|
;
|
|
; CHAIN TO OS LOADER
|
|
;
|
|
#IFDEF ROMBOOT
|
|
; PERFORM BANK CALL TO OS IMAGES BANK IN ROM
|
|
LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK
|
|
LD IX,0 ; ENTER AT ADDRESS 0
|
|
CALL HBX_BNKCALL ; GO THERE
|
|
HALT ; WE SHOULD NEVER COME BACK!
|
|
#ELSE
|
|
; COPY OS IMAGE: BID_USR:<IMG START> --> 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
|
|
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 A,(HB_APPBNK) ; GET APP LOAD BANK
|
|
LD E,A ; USE AS SOURCE
|
|
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 IX,0 ; ENTER AT ADDRESS 0
|
|
CALL HBX_BNKCALL ; GO THERE
|
|
HALT ; WE SHOULD NEVER COME BACK!
|
|
;
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
; CALL A LIST OF ROUTINES POINTED TO BY DE OF LENGTH B.
|
|
;
|
|
CALLLIST:
|
|
LD A,(DE)
|
|
LD L,A
|
|
INC DE
|
|
LD A,(DE)
|
|
LD H,A
|
|
INC DE
|
|
PUSH DE
|
|
PUSH BC
|
|
CALL JPHL
|
|
POP BC
|
|
POP DE
|
|
DJNZ CALLLIST
|
|
CALLDUMMY:
|
|
RET
|
|
|
|
;
|
|
;==================================================================================================
|
|
; TABLE OF RECOVERY MODE INITIALIZATION ENTRY POINTS
|
|
;==================================================================================================
|
|
;
|
|
; USE "CALLDUMMY" IF NO ENTRY REQUIRED
|
|
;
|
|
#IF (BT_REC_TYPE != BT_REC_NONE)
|
|
;
|
|
HB_PCINIT_REC:
|
|
#IF (PLATFORM == PLT_SBC)
|
|
.DW UART_PREINIT
|
|
; .DW CALLDUMMY
|
|
#ENDIF
|
|
HB_PCINITRLEN .EQU (($ - HB_PCINIT_REC) / 2)
|
|
;
|
|
HB_INIT_REC:
|
|
#IF (PLATFORM == PLT_SBC)
|
|
.DW UART_INIT
|
|
.DW MD_INIT
|
|
.DW PPIDE_INIT
|
|
#ENDIF
|
|
HB_INITRLEN .EQU (($ - HB_INIT_REC) / 2)
|
|
;
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; TABLE OF PRE-CONSOLE INITIALIZATION ENTRY POINTS
|
|
;==================================================================================================
|
|
;
|
|
HB_PCINITTBL:
|
|
.DW CALLDUMMY ; RESERVED FOR FORCING PRIMARY CONSOLE
|
|
#IF (ASCIENABLE)
|
|
.DW ASCI_PREINIT
|
|
#ENDIF
|
|
#IF (UARTENABLE)
|
|
.DW UART_PREINIT
|
|
#ENDIF
|
|
#IF (DUARTENABLE)
|
|
.DW DUART_PREINIT
|
|
#ENDIF
|
|
#IF (SIOENABLE)
|
|
.DW SIO_PREINIT
|
|
#ENDIF
|
|
#IF (ACIAENABLE)
|
|
.DW ACIA_PREINIT
|
|
#ENDIF
|
|
#IF (PIO_4P | PIO_ZP)
|
|
.DW PIO_PREINIT
|
|
#ENDIF
|
|
#IF (UFENABLE)
|
|
.DW UF_PREINIT
|
|
#ENDIF
|
|
#IF (TMSENABLE)
|
|
.DW TMS_PREINIT
|
|
#ENDIF
|
|
HB_PCINITTBLLEN .EQU (($ - HB_PCINITTBL) / 2)
|
|
|
|
;==================================================================================================
|
|
; TABLE OF INITIALIZATION ENTRY POINTS
|
|
;==================================================================================================
|
|
;
|
|
HB_INITTBL:
|
|
#IF (CTCENABLE)
|
|
.DW CTC_INIT
|
|
#ENDIF
|
|
#IF (AY38910ENABLE)
|
|
.DW AY38910_INIT ; AUDIBLE INDICATOR OF BOOT START
|
|
#ENDIF
|
|
#IF (SN76489ENABLE)
|
|
.DW SN76489_INIT
|
|
#ENDIF
|
|
#IF (SPKENABLE)
|
|
.DW SP_INIT ; AUDIBLE INDICATOR OF BOOT START
|
|
#ENDIF
|
|
#IF (ASCIENABLE)
|
|
.DW ASCI_INIT
|
|
#ENDIF
|
|
#IF (UARTENABLE)
|
|
.DW UART_INIT
|
|
#ENDIF
|
|
#IF (DUARTENABLE)
|
|
.DW DUART_INIT
|
|
#ENDIF
|
|
#IF (SIOENABLE)
|
|
.DW SIO_INIT
|
|
#ENDIF
|
|
#IF (ACIAENABLE)
|
|
.DW ACIA_INIT
|
|
#ENDIF
|
|
#IF (DSRTCENABLE)
|
|
.DW DSRTC_INIT
|
|
#ENDIF
|
|
#IF (BQRTCENABLE)
|
|
.DW BQRTC_INIT
|
|
#ENDIF
|
|
#IF (SIMRTCENABLE)
|
|
.DW SIMRTC_INIT
|
|
#ENDIF
|
|
#IF (INTRTCENABLE)
|
|
.DW INTRTC_INIT
|
|
#ENDIF
|
|
#IF (VDUENABLE)
|
|
.DW VDU_INIT
|
|
#ENDIF
|
|
#IF (CVDUENABLE)
|
|
.DW CVDU_INIT
|
|
#ENDIF
|
|
#IF (VGAENABLE)
|
|
.DW VGA_INIT
|
|
#ENDIF
|
|
#IF (NECENABLE)
|
|
.DW NEC_INIT
|
|
#ENDIF
|
|
#IF (TMSENABLE)
|
|
.DW TMS_INIT
|
|
#ENDIF
|
|
#IF (DSKYENABLE)
|
|
.DW DSKY_INIT
|
|
#ENDIF
|
|
#IF (MDENABLE)
|
|
.DW MD_INIT
|
|
#ENDIF
|
|
#IF (FDENABLE)
|
|
.DW FD_INIT
|
|
#ENDIF
|
|
#IF (RFENABLE)
|
|
.DW RF_INIT
|
|
#ENDIF
|
|
#IF (IDEENABLE)
|
|
.DW IDE_INIT
|
|
#ENDIF
|
|
#IF (PPIDEENABLE)
|
|
.DW PPIDE_INIT
|
|
#ENDIF
|
|
#IF (SDENABLE)
|
|
.DW SD_INIT
|
|
#ENDIF
|
|
#IF (HDSKENABLE)
|
|
.DW HDSK_INIT
|
|
#ENDIF
|
|
#IF (PRPENABLE)
|
|
.DW PRP_INIT
|
|
#ENDIF
|
|
#IF (PPPENABLE)
|
|
.DW PPP_INIT
|
|
#ENDIF
|
|
#IF (PIO_4P | PIO_ZP)
|
|
.DW PIO_INIT
|
|
#ENDIF
|
|
#IF (UFENABLE)
|
|
.DW UF_INIT
|
|
#ENDIF
|
|
|
|
;
|
|
HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2)
|
|
;
|
|
;==================================================================================================
|
|
; IDLE
|
|
;==================================================================================================
|
|
;
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
IDLE:
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
PUSH IY
|
|
#IF (FDENABLE)
|
|
CALL FD_IDLE
|
|
#ENDIF
|
|
POP IY
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; BIOS FUNCTION DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; MAIN BIOS FUNCTION
|
|
; B: FUNCTION
|
|
;__________________________________________________________________________________________________
|
|
;
|
|
HB_DISPATCH:
|
|
;
|
|
#IF 0 ; *DEBUG* START
|
|
;
|
|
CALL HB_DISPATCH1 ; DO THE WORK
|
|
;
|
|
; CHECK STACK INTEGRITY
|
|
PUSH AF
|
|
LD A,(HB_STACK - HB_STKSIZ + $08)
|
|
CP $FF
|
|
CALL SYSCHK
|
|
LD A,$FF
|
|
LD (HB_STACK - HB_STKSIZ + $08),A
|
|
POP AF
|
|
RET
|
|
HB_DISPATCH1:
|
|
;
|
|
#ENDIF ; *DEBUG* END
|
|
;
|
|
LD A,B ; REQUESTED FUNCTION IS IN B
|
|
CP BF_CIO + $10 ; $00-$0F: CHARACTER I/O
|
|
JP C,CIO_DISPATCH
|
|
CP BF_DIO + $10 ; $10-$1F: DISK I/O
|
|
JP C,DIO_DISPATCH
|
|
CP BF_RTC + $10 ; $20-$2F: REAL TIME CLOCK (RTC)
|
|
JP C,RTC_DISPATCH
|
|
CP BF_EMU + $10 ; $30-$3F: EMULATION
|
|
JR C,HB_DISPERR
|
|
CP BF_VDA + $10 ; $40-$4F: VIDEO DISPLAY ADAPTER
|
|
JP C,VDA_DISPATCH
|
|
CP BF_SND + $08 ; $50-$58: SOUND DRIVERS
|
|
JP C,SND_DISPATCH
|
|
CP BF_SYS ; SKIP TO BF_SYS VALUE AT $F0
|
|
JR C,HB_DISPERR ; ERROR IF LESS THAN BF_SYS
|
|
JP SYS_DISPATCH ; OTHERWISE SYS CALL
|
|
; FALL THRU
|
|
;
|
|
HB_DISPERR:
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC
|
|
OR A
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER I/O DEVICE FUNCTION DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO SPECIFIED CHARACTER I/O DRIVER
|
|
; B: FUNCTION
|
|
; C: UNIT NUMBER
|
|
;
|
|
CIO_DISPATCH:
|
|
BIT 7,C ; CHECK FOR SPECIAL UNIT CODE
|
|
CALL NZ,CIO_SPECIAL ; IF SO, HANDLE IT
|
|
|
|
PUSH IY ; SAVE INCOMING IY
|
|
|
|
LD IY,CIO_TBL ; POINT IY TO START OF CIO TABLE
|
|
CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE
|
|
|
|
POP IY ; RESTORE IY
|
|
RET ; AND DONE
|
|
;
|
|
; SPECIAL HANDLING FOR DEDICATED UNIT CODES
|
|
;
|
|
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
|
|
;
|
|
; 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
|
|
;
|
|
; 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 FUNCTION TABLE ADDRESS
|
|
; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS)
|
|
;
|
|
CIO_FNCNT .EQU 7 ; NUMBER OF CIO FUNCS (FOR RANGE CHECK)
|
|
CIO_MAX .EQU 32 ; UP TO 32 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 FUNCTION DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO SPECIFIED DISK I/O DRIVER
|
|
; B: FUNCTION
|
|
; C: UNIT NUMBER
|
|
;
|
|
DIO_DISPATCH:
|
|
;
|
|
#IF 0 ; *DEBUG* START
|
|
;
|
|
; DUMP INCOMING CALL
|
|
CALL NEWLINE
|
|
PRTS("DIO>$")
|
|
CALL REGDMP ; DUMP REGS, NONE DESTROYED
|
|
;
|
|
; DO THE ACTUAL DISPATCH PROCESSING
|
|
CALL DIO_DISPCALL
|
|
;
|
|
; DUMP CALL RESULTS AND RETURN
|
|
CALL NEWLINE
|
|
PRTS("DIO<$")
|
|
CALL REGDMP ; DUMP REGS, NONE DESTROYED
|
|
RET
|
|
;
|
|
#ENDIF ; *DEBUG* END
|
|
;
|
|
DIO_DISPCALL:
|
|
PUSH IY ; SAVE INCOMING IY
|
|
|
|
LD IY,DIO_TBL ; POINT IY TO START OF DIO TABLE
|
|
CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE
|
|
|
|
POP IY ; RESTORE IY
|
|
RET ; AND DONE
|
|
;
|
|
; 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
|
|
;
|
|
; 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 FUNCTION TABLE ADDRESS
|
|
; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS)
|
|
;
|
|
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
|
|
;
|
|
;==================================================================================================
|
|
; DISK READ HELPER
|
|
;==================================================================================================
|
|
;
|
|
; IMPLEMENTS MULTI SECTOR READS AND I/O TO/FROM
|
|
; BANKED RAM VIA BOUNCE BUFFER
|
|
;
|
|
; ON ENTRY:
|
|
; TOS=READ FN ADR
|
|
; HL=BUF ADR
|
|
; E=SEC COUNT
|
|
; D=BUF BANK ID
|
|
;
|
|
HB_DSKREAD:
|
|
;
|
|
; THE ACTUAL SECTOR READ FUNCTION ADDRESS IS ON TOS, SAVE IT
|
|
EX (SP),HL ; SAVE HL TO TOS, HL := READ FN ADR
|
|
LD (HB_DSKFNADR),HL ; IMBED IN CALL OP BELOW
|
|
POP HL ; RECOVER HL
|
|
;
|
|
#IF (DIAGENABLE)
|
|
; SAVE DISK UNIT NUMBER BIT MASK
|
|
LD A,C ; GET DISK UNIT NUMBER
|
|
LD B,A ; PUT IN B FOR LOOP COUNTER
|
|
INC B ; LOOP ONE EXTRA TIME TO HANDLE UNIT=0
|
|
XOR A ; START WITH ACCUM ZERO
|
|
SCF ; ... AND CF SET
|
|
HB_DSKREAD0:
|
|
RLA ; ROTATE BIT
|
|
DJNZ HB_DSKREAD0 ; ... UNTIL IN PROPER LOCATION
|
|
LD (HB_DSKBIT),A ; SAVE IT FOR DIAGNOSTICS
|
|
#ENDIF
|
|
;
|
|
#IF 1
|
|
; CHECK TO SEE IF INTER-BANK I/O NEEDED.
|
|
BIT 7,H ; TGT BUF IN UPPER 32K?
|
|
JP NZ,HB_DSKIO ; IF SO, NON-BANKED
|
|
LD A,D ; GET TGT BANK
|
|
CP BID_BIOS ; BIOS BANK?
|
|
JP Z,HB_DSKIO ; IF SO, NON-BANKED
|
|
#ENDIF
|
|
;
|
|
#IF 1
|
|
; RAM BANK RANGE CHECK
|
|
LD A,D ; GET TGT BANK
|
|
CP BID_RAMN ; BANK IN RANGE 0-N?
|
|
CALL NC,PANIC ; IF >N, PANIC
|
|
#ENDIF
|
|
;
|
|
; SAVE TGT BUF BNK/ADR
|
|
LD (HB_IOBUF),HL
|
|
LD A,D
|
|
LD (HB_IOBNK),A
|
|
;
|
|
; SETUP READ AND LOOP COUNT
|
|
LD B,E ; SEC LOOP COUNTER
|
|
LD C,0 ; SEC COMPLETE COUNTER
|
|
;
|
|
HB_DSKREAD1:
|
|
LD HL,HB_WRKBUF ; USE WORK BUF REAL I/O
|
|
;
|
|
; CALL READ FN
|
|
CALL HB_DSKFN ; READ ONE SECTOR
|
|
;
|
|
; IF FAIL, RETURN ERR
|
|
JR NZ,HB_DSKREADX ; BAIL OUT ON ERROR
|
|
;
|
|
; BNKCPY SEC DATA TO REAL BANK/BUF & INC BUF ADR
|
|
PUSH BC ; SAVE COUNTERS
|
|
LD A,(HB_IOBNK) ; DEST BANK
|
|
LD (HB_DSTBNK),A ; ... TO PROXY
|
|
LD A,BID_BIOS ; SRC BANK
|
|
LD (HB_SRCBNK),A ; ... TO PROXY
|
|
LD BC,512 ; COPY 512 BYTES (1 SEC)
|
|
LD DE,(HB_IOBUF) ; TGT BUFFER ADR
|
|
LD HL,HB_WRKBUF ; SOURCE BUFFER
|
|
CALL HBX_BNKCPY ; DO BANK COPY
|
|
LD (HB_IOBUF),DE ; SAVE UPDATED TGT BUF ADR
|
|
POP BC ; RESTORE COUNTERS
|
|
;
|
|
; INC READ COUNT
|
|
INC C ; BUMP SEC READ COUNT
|
|
DJNZ HB_DSKREAD1 ; LOOP AS NEEDED
|
|
XOR A ; SIGNAL SUCCESS
|
|
;
|
|
HB_DSKREADX:
|
|
LD HL,(HB_IOBUF) ; NEXT BUF ADR
|
|
JR HB_DSKIOX ; DONE
|
|
;
|
|
;==================================================================================================
|
|
; DISK WRITE HELPER
|
|
;==================================================================================================
|
|
;
|
|
; IMPLEMENTS MULTI SECTOR WRITES AND I/O TO/FROM
|
|
; BANKED RAM VIA BOUNCE BUFFER
|
|
;
|
|
; TOS=WRITE FN ADR
|
|
; HL=BUF ADR
|
|
; E=SEC COUNT
|
|
; D=BUF BANK ID
|
|
;
|
|
HB_DSKWRITE:
|
|
;
|
|
; THE ACTUAL SECTOR READ FUNCTION ADDRESS IS ON TOS, SAVE IT
|
|
EX (SP),HL ; SAVE HL TO TOS, HL := READ FN ADR
|
|
LD (HB_DSKFNADR),HL ; IMBED IN CALL OP BELOW
|
|
POP HL ; RECOVER HL
|
|
;
|
|
#IF (DIAGENABLE)
|
|
; SAVE DISK UNIT NUMBER BIT MASK
|
|
LD A,C ; GET DISK UNIT NUMBER
|
|
LD B,A ; PUT IN B FOR LOOP COUNTER
|
|
INC B ; LOOP ONE EXTRA TIME TO HANDLE UNIT=0
|
|
XOR A ; START WITH ACCUM ZERO
|
|
SCF ; ... AND CF SET
|
|
HB_DSKWRITE0:
|
|
RLA ; ROTATE BIT
|
|
DJNZ HB_DSKWRITE0 ; ... UNTIL IN PROPER LOCATION
|
|
LD (HB_DSKBIT),A ; SAVE IT FOR DIAGNOSTICS
|
|
#ENDIF
|
|
;
|
|
#IF 1
|
|
; CHECK TO SEE IF INTER-BANK I/O NEEDED.
|
|
BIT 7,H ; TGT BUF IN UPPER 32K?
|
|
JP NZ,HB_DSKIO ; IF SO, NON-BANKED
|
|
LD A,D ; GET TGT BANK
|
|
CP BID_BIOS ; BIOS BANK?
|
|
JP Z,HB_DSKIO ; IF SO, NON-BANKED
|
|
#ENDIF
|
|
;
|
|
#IF 1
|
|
; RAM BANK RANGE CHECK
|
|
LD A,D ; GET TGT BANK
|
|
CP BID_RAMN ; BANK IN RANGE 0-N?
|
|
CALL NC,PANIC ; IF >N, PANIC
|
|
#ENDIF
|
|
;
|
|
; SAVE TGT BUF BNK/ADR
|
|
LD (HB_IOBUF),HL
|
|
LD A,D
|
|
LD (HB_IOBNK),A
|
|
;
|
|
; SETUP WRITE AND LOOP COUNT
|
|
LD B,E ; SEC LOOP COUNTER
|
|
LD C,0 ; SEC COMPLETE COUNTER
|
|
;
|
|
HB_DSKWRITE1:
|
|
; BNKCPY SEC DATA TO WORK BANK/BUF & INC BUF ADR
|
|
PUSH BC ; SAVE COUNTERS
|
|
LD A,BID_BIOS ; DEST BANK
|
|
LD (HB_DSTBNK),A ; ... TO PROXY
|
|
LD A,(HB_IOBNK) ; SRC BANK
|
|
LD (HB_SRCBNK),A ; ... TO PROXY
|
|
LD BC,512 ; COPY 512 BYTES (1 SEC)
|
|
LD DE,HB_WRKBUF ; TGT BUFFER ADR
|
|
LD HL,(HB_IOBUF) ; SOURCE BUFFER
|
|
CALL HBX_BNKCPY ; DO BANK COPY
|
|
LD (HB_IOBUF),HL ; SAVE UPDATED SRC BUF ADR
|
|
POP BC ; RESTORE COUNTERS
|
|
;
|
|
; CALL WRITE FN
|
|
LD HL,HB_WRKBUF ; WRITE FROM WORK BUFFER
|
|
CALL HB_DSKFN ; WRITE ONE SECTOR
|
|
;
|
|
; IF FAIL, RETURN ERR
|
|
JR NZ,HB_DSKWRITEX ; BAIL OUT ON ERROR
|
|
;
|
|
; INC WRITE COUNT
|
|
INC C ; BUMP SEC WRITE COUNT
|
|
DJNZ HB_DSKWRITE1 ; LOOP AS NEEDED
|
|
XOR A ; SIGNAL SUCCESS
|
|
;
|
|
HB_DSKWRITEX:
|
|
LD HL,(HB_IOBUF) ; NEXT BUF ADR
|
|
JR HB_DSKIOX ; DONE
|
|
;
|
|
;==================================================================================================
|
|
; NON-BANKED DISK READ/WRITE
|
|
;==================================================================================================
|
|
;
|
|
HB_DSKIO:
|
|
;
|
|
; SETUP LOOP COUNT
|
|
LD B,E ; SEC LOOP COUNTER
|
|
LD C,0 ; SEC COMPLETE COUNTER
|
|
;
|
|
HB_DSKIO1:
|
|
; CALL READ/WRITE FN
|
|
CALL HB_DSKFN ; READ/WRITE ONE SECTOR
|
|
;
|
|
; IF FAIL, RETURN ERR
|
|
JR NZ,HB_DSKIOX ; BAIL OUT ON ERROR
|
|
;
|
|
; INC SECTOR COUNT
|
|
INC C ; BUMP SEC READ/WRITE COUNT
|
|
DJNZ HB_DSKIO1 ; LOOP AS NEEDED
|
|
XOR A ; SIGNAL SUCCESS
|
|
;
|
|
HB_DSKIOX:
|
|
LD E,C ; WRITE COUNT TO E
|
|
OR A ; SET RESULT FLAGS
|
|
RET ; DONE
|
|
;
|
|
HB_DSKFN:
|
|
PUSH BC ; SAVE COUNTERS
|
|
#IF (DIAGENABLE & DIAGDISKIO)
|
|
LD A,(HB_DSKBIT) ; LOAD UNIT DISK BIT MASK
|
|
OUT (DIAGPORT),A ; DISPLAY ON DIAG LEDS
|
|
#ENDIF
|
|
#IF (LEDENABLE & LEDDISKIO)
|
|
LED($FF)
|
|
#ENDIF
|
|
LD E,1 ; ONE SECTOR
|
|
HB_DSKFNADR .EQU $+1
|
|
CALL PANIC ; READ ONE SECTOR
|
|
#IF (DIAGENABLE & DIAGDISKIO)
|
|
DIAG(0) ; CLEAR DIAG LEDS
|
|
#ENDIF
|
|
#IF (LEDENABLE & LEDDISKIO)
|
|
LED($00)
|
|
#ENDIF
|
|
POP BC ; RESTORE COUNTERS
|
|
RET ; RETURN
|
|
;
|
|
HB_DSKBIT .DB 0 ; ACTIVE DISK UNIT
|
|
HB_IOBUF .DW 0 ; CURRENT IO BUFFER ADR
|
|
HB_IOBNK .DB 0 ; CURRENT IO BUFFER BANK ID
|
|
;
|
|
;==================================================================================================
|
|
; REAL TIME CLOCK DEVICE DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO REAL TIME CLOCK DRIVER
|
|
; B: FUNCTION
|
|
;
|
|
RTC_DISPATCH:
|
|
PUSH HL ; SAVE INCOMING HL
|
|
LD HL,(RTC_DISPADR) ;
|
|
EX (SP),HL
|
|
RET
|
|
;
|
|
RTC_DISPERR:
|
|
CALL SYSCHK
|
|
LD A,ERR_NOHW
|
|
OR A
|
|
RET
|
|
;
|
|
; SET RTC DISPATCH ADDRESS, USED BY RTC DRIVERS DURING INIT
|
|
; BC HAS ADDRESS OF DISPATCH ADDRESS
|
|
; WILL ONLY SAVE THE FIRST ADDRESS SET
|
|
;
|
|
RTC_SETDISP:
|
|
LD (RTC_DISPADR),BC ; SAVE THE ADDRESS
|
|
OR $FF ; FLAG ACTIVE VALUE
|
|
LD (RTC_DISPACT),A ; SAVE IT
|
|
RET ; AND DONE
|
|
;
|
|
;
|
|
;
|
|
RTC_DISPADR .DW RTC_DISPERR ; RTC DISPATCH ADDRESS
|
|
RTC_DISPACT .DB 0 ; SET WHEN DISPADR SET
|
|
;
|
|
;==================================================================================================
|
|
; VIDEO DISPLAY ADAPTER DEVICE DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO SPECIFIED VDA DEVICE DRIVER
|
|
; B: FUNCTION
|
|
; C: UNIT NUMBER
|
|
;
|
|
VDA_DISPATCH:
|
|
PUSH IY ; SAVE INCOMING IY
|
|
|
|
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
|
|
;
|
|
; ADD AN ENTRY TO THE VDA UNIT TABLE (SEE HB_ADDENT FOR DETAILS)
|
|
;
|
|
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 FUNCTION TABLE ADDRESS
|
|
; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS)
|
|
;
|
|
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
|
|
;
|
|
.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
|
|
|
|
;
|
|
;
|
|
;==================================================================================================
|
|
; SOUND ADAPTER DEVICE DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO SPECIFIED SOUND DEVICE DRIVER
|
|
; B: FUNCTION
|
|
; C: UNIT NUMBER
|
|
;
|
|
SND_DISPATCH:
|
|
PUSH IY ; SAVE INCOMING IY
|
|
|
|
LD IY, SND_TBL ; POINT IY TO START OF DIO TABLE
|
|
CALL HB_DISPCALL ; GO TO GENERIC API CALL CODE
|
|
|
|
POP IY ; RESTORE IY
|
|
RET ; AND DONE
|
|
;
|
|
; ADD AN ENTRY TO THE SND UNIT TABLE (SEE HB_ADDENT FOR DETAILS)
|
|
;
|
|
SND_ADDENT:
|
|
LD HL, SND_TBL ; POINT TO SND 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 SND FUNCTION IDS
|
|
; EACH ENTRY IS DEFINED AS:
|
|
;
|
|
; WORD DRIVER FUNCTION TABLE ADDRESS
|
|
; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS)
|
|
;
|
|
SND_FNCNT .EQU 8 ; NUMBER OF SND FUNCS (FOR RANGE CHECK)
|
|
SND_MAX .EQU 3 ; UP TO 2 UNITS
|
|
SND_SIZ .EQU SND_MAX * 4 ; EACH ENTRY IS 4 BYTES
|
|
;
|
|
.DB SND_FNCNT ; SND FUNCTION COUNT (FOR RANGE CHECK)
|
|
.DB SND_MAX ; MAX ENTRY COUNT TABLE PREFIX
|
|
SND_CNT .DB 0 ; ENTRY COUNT PREFIX
|
|
SND_TBL .FILL SND_SIZ,0 ; SPACE FOR ENTRIES
|
|
;
|
|
;==================================================================================================
|
|
; SYSTEM FUNCTION DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; B: FUNCTION
|
|
;
|
|
SYS_DISPATCH:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JP Z,SYS_RESET ; $F0
|
|
DEC A
|
|
JP Z,SYS_VER ; $F1
|
|
DEC A
|
|
JP Z,SYS_SETBNK ; $F2
|
|
DEC A
|
|
JP Z,SYS_GETBNK ; $F3
|
|
DEC A
|
|
JP Z,SYS_SETCPY ; $F4
|
|
DEC A
|
|
JP Z,SYS_BNKCPY ; $F5
|
|
DEC A
|
|
JP Z,SYS_ALLOC ; $F6
|
|
DEC A
|
|
JP Z,SYS_FREE ; $F7
|
|
DEC A
|
|
JP Z,SYS_GET ; $F8
|
|
DEC A
|
|
JP Z,SYS_SET ; $F9
|
|
DEC A
|
|
JP Z,SYS_PEEK ; $FA
|
|
DEC A
|
|
JP Z,SYS_POKE ; $FB
|
|
DEC A
|
|
JP Z,SYS_INT ; $FC
|
|
DEC A
|
|
;
|
|
; RESTART SYSTEM
|
|
; SUBFUNCTION IN C
|
|
;
|
|
SYS_RESET:
|
|
LD A,C ; GET REQUESTED SUB-FUNCTION
|
|
CP BF_SYSRES_INT
|
|
JR Z,SYS_RESINT
|
|
CP BF_SYSRES_WARM
|
|
JR Z,SYS_RESWARM
|
|
CP BF_SYSRES_COLD
|
|
JR Z,SYS_RESCOLD
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC
|
|
OR A ; SIGNAL ERROR
|
|
RET
|
|
;
|
|
; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS
|
|
;
|
|
SYS_RESINT:
|
|
LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD
|
|
LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP
|
|
XOR A
|
|
RET
|
|
;
|
|
; GO BACK TO ROM BOOT LOADER
|
|
;
|
|
SYS_RESWARM:
|
|
CALL SYS_RESINT
|
|
; PERFORM BANK CALL TO OS IMAGES BANK IN ROM
|
|
LD SP,HBX_LOC ; STACK JUST BELOW HBIOS PROXY
|
|
LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK
|
|
LD IX,0 ; ENTER AT ADDRESS 0
|
|
CALL HBX_BNKCALL ; GO THERE
|
|
HALT ; WE SHOULD NEVER COME BACK!
|
|
;
|
|
; RESTART SYSTEM AS THOUGH POWER HAD JUST BEEN TURNED ON
|
|
;
|
|
SYS_RESCOLD:
|
|
DI
|
|
LD SP,HBX_LOC ; STACK JUST BELOW HBIOS PROXY
|
|
LD A,BID_BOOT ; BOOT BANK
|
|
LD IX,0 ; ADDRESS ZERO
|
|
CALL HB_BNKCALL ; DOES NOT RETURN
|
|
;
|
|
; 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
|
|
; CALLER MUST EXTABLISH UPPER MEMORY STACK BEFORE INVOKING THIS FUNCTION!
|
|
;
|
|
SYS_SETBNK:
|
|
PUSH HL ; SAVE INCOMING HL
|
|
LD HL,HB_INVBNK ; POINT TO HBIOS INVOKE BANK ID ADDRESS
|
|
LD A,(HL) ; GET EXISTING BANK ID TO A
|
|
LD (HL),C ; UPDATE INVOKE BANK TO NEW BANK ID
|
|
LD C,A ; PUT PREVIOUS BANK ID IN C FOR RETURN
|
|
POP HL ; RESTORE ORIGINAL HL
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; GET ACTIVE MEMORY BANK
|
|
;
|
|
SYS_GETBNK:
|
|
LD A,(HB_INVBNK) ; GET THE ACTIVE MEMORY BANK
|
|
LD C,A ; MOVE TO C
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; SET BANKS AND LENGTH FOR INTERBANK MEMORY COPY (BNKCPY)
|
|
; ENTRY: E=SOURCE BANK ID
|
|
; D=DEST BANK ID
|
|
; HL=COPY LENGTH (IN BYTES)
|
|
;
|
|
SYS_SETCPY:
|
|
LD A,E
|
|
LD (HB_SRCBNK),A ; RECORD THE SOURCE BANK
|
|
LD A,D
|
|
LD (HB_DSTBNK),A ; RECORD THE DESTINATION BANK
|
|
LD (HB_CPYLEN),HL ; RECORD THE COPY LENGTH
|
|
XOR A
|
|
RET
|
|
;
|
|
; PERFORM MEMORY COPY POTENTIALLY ACROSS BANKS
|
|
; ENTRY: HL=SOURCE ADDRESS
|
|
; DE=DESTINATION ADDRESS
|
|
; NOTE: SRC/DEST BANK & COPY LENGTH MUST BE SET VIA SETCPY
|
|
;
|
|
SYS_BNKCPY:
|
|
PUSH HL ; SAVE INCOMING HL
|
|
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
|
|
CALL HB_BNKCPY
|
|
XOR A
|
|
RET
|
|
;
|
|
; ALLOCATE HL BYTES OF MEMORY FROM HBIOS HEAP
|
|
; RETURNS POINTER TO ALLOCATED MEMORY IN HL
|
|
; ON SUCCESS RETURN A == 0, AND Z SET
|
|
; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED
|
|
; ALL OTHER REGISTERS PRESERVED
|
|
;
|
|
SYS_ALLOC:
|
|
JP HB_ALLOC
|
|
;
|
|
; FREE HEAP MEMORY BY SIMPLY RELEASING ALL
|
|
; MEMORY BEYOND POINTER IN HL.
|
|
; ON SUCCESS RETURN A == 0, AND Z SET
|
|
; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED
|
|
; ALL OTHER REGISTERS PRESERVED
|
|
;
|
|
SYS_FREE:
|
|
CALL SYSCHK ; NOT YET IMPLEMENTED
|
|
LD A,ERR_NOTIMPL ; NOT YET INMPLEMENTED
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; GET SYSTEM INFORMATION
|
|
; ITEM TO RETURN INDICATED IN C
|
|
;
|
|
SYS_GET:
|
|
LD A,C ; GET REQUESTED SUB-FUNCTION
|
|
CP BF_SYSGET_CIOCNT
|
|
JP Z,SYS_GETCIOCNT
|
|
CP BF_SYSGET_CIOFN
|
|
JP Z,SYS_GETCIOFN
|
|
CP BF_SYSGET_DIOCNT
|
|
JP Z,SYS_GETDIOCNT
|
|
CP BF_SYSGET_DIOFN
|
|
JP Z,SYS_GETDIOFN
|
|
CP BF_SYSGET_RTCCNT
|
|
JP Z,SYS_GETRTCCNT
|
|
CP BF_SYSGET_VDACNT
|
|
JP Z,SYS_GETVDACNT
|
|
CP BF_SYSGET_VDAFN
|
|
JP Z,SYS_GETVDAFN
|
|
CP BF_SYSGET_SNDCNT
|
|
JP Z, SYS_GETSNDCNT
|
|
CP BF_SYSGET_SNDFN
|
|
JP Z,SYS_GETSNDFN
|
|
CP BF_SYSGET_TIMER
|
|
JP Z,SYS_GETTIMER
|
|
CP BF_SYSGET_SECS
|
|
JP Z,SYS_GETSECS
|
|
CP BF_SYSGET_BOOTINFO
|
|
JP Z,SYS_GETBOOTINFO
|
|
CP BF_SYSGET_CPUINFO
|
|
JP Z,SYS_GETCPUINFO
|
|
CP BF_SYSGET_MEMINFO
|
|
JP Z,SYS_GETMEMINFO
|
|
CP BF_SYSGET_BNKINFO
|
|
JP Z,SYS_GETBNKINFO
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; GET TIMER
|
|
; RETURNS:
|
|
; DE:HL: TIMER VALUE (32 BIT)
|
|
;
|
|
SYS_GETTIMER:
|
|
LD HL,HB_TICKS
|
|
HB_DI
|
|
CALL LD32
|
|
HB_EI
|
|
LD C, TICKFREQ
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET SECONDS
|
|
; RETURNS:
|
|
; DE:HL: SECONDS VALUE (32 BIT)
|
|
; C: NUM TICKS WITHIN CURRENT SECOND
|
|
;
|
|
SYS_GETSECS:
|
|
LD HL,HB_SECS
|
|
HB_DI
|
|
CALL LD32
|
|
LD A,(HB_SECTCK)
|
|
HB_EI
|
|
NEG ; CONVERT DOWNCOUNTER TO UPCOUNTER
|
|
ADD A,TICKFREQ
|
|
LD C,A
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET BOOT INFORMATION
|
|
; RETURNS:
|
|
; L: BOOT BANK ID
|
|
; DE: BOOT DISK VOLUME (UNIT/SLICE)
|
|
;
|
|
SYS_GETBOOTINFO:
|
|
LD A,(CB_BOOTBID)
|
|
LD L,A
|
|
LD DE,(CB_BOOTVOL)
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET CPU INFORMATION
|
|
; RETURNS:
|
|
; H: Z80 CPU VARIANT
|
|
; L: CPU SPEED IN MHZ
|
|
; DE: CPU SPEED IN KHZ
|
|
;
|
|
SYS_GETCPUINFO:
|
|
LD A,(HB_CPUTYPE)
|
|
LD H,A
|
|
LD A,(CB_CPUMHZ)
|
|
LD L,A
|
|
LD DE,(CB_CPUKHZ)
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET MEMORY INFORMATION
|
|
; RETURNS:
|
|
; D: COUNT OF ROM BANKS
|
|
; E: COUNT OF RAM BANKS
|
|
;
|
|
SYS_GETMEMINFO:
|
|
LD D,ROMSIZE / 32
|
|
LD E,RAMSIZE / 32
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET BANK CONFIGURATION INFORMATION
|
|
; RETURNS:
|
|
; D: HBIOS BANK ID
|
|
; E: USER BANK ID
|
|
;
|
|
SYS_GETBNKINFO:
|
|
LD A,(CB_BIDBIOS)
|
|
LD D,A
|
|
LD A,(CB_BIDUSR)
|
|
LD E,A
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET SERIAL UNIT COUNT
|
|
;
|
|
SYS_GETCIOCNT:
|
|
LD A,(CIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST)
|
|
LD E,A ; PUT IT IN E
|
|
XOR A ; SIGNALS SUCCESS
|
|
RET
|
|
;
|
|
; GET SERIAL UNIT API FN ADR AND DATA ADR
|
|
; ENTRY:
|
|
; D: FUNCTION
|
|
; E: UNIT
|
|
; RETURNS:
|
|
; HL: FUNCTION ADDRESS
|
|
; DE: DATA BLOB ADDRESS
|
|
;
|
|
SYS_GETCIOFN:
|
|
BIT 7,E ; CHECK FOR SPECIAL UNIT CODE
|
|
CALL NZ,SYS_GETCIOFN1 ; IF SO, HANDLE IT
|
|
LD IY,CIO_TBL ; POINT TO UNIT TABLE
|
|
JP SYS_GETFN ; GO TO COMMON CODE
|
|
;
|
|
SYS_GETCIOFN1:
|
|
LD A,(CB_CONDEV) ; UNIT $80 -> CONSOLE UNIT
|
|
LD E,A ; REPLACE UNIT VALUE IN C
|
|
RET ; AND BACK TO REGULAR FLOW
|
|
;
|
|
;
|
|
; GET DISK UNIT COUNT
|
|
;
|
|
SYS_GETDIOCNT:
|
|
LD A,(DIO_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST)
|
|
LD E,A ; PUT IT IN E
|
|
XOR A ; SIGNALS SUCCESS
|
|
RET
|
|
;
|
|
; GET DISK UNIT API FN ADR AND DATA ADR
|
|
; ENTRY:
|
|
; D: FUNCTION
|
|
; E: UNIT
|
|
; RETURNS:
|
|
; HL: FUNCTION ADDRESS
|
|
; DE: DATA BLOB ADDRESS
|
|
;
|
|
SYS_GETDIOFN:
|
|
LD IY,DIO_TBL ; POINT TO UNIT TABLE
|
|
JP SYS_GETFN ; GO TO COMMON CODE
|
|
;
|
|
; GET RTC UNIT COUNT
|
|
;
|
|
SYS_GETRTCCNT:
|
|
LD E,0 ; ASSUME 0 RTC DEVICES
|
|
LD A,(RTC_DISPACT) ; IS RTC ACTIVE?
|
|
OR A ; SET FLAGS
|
|
JR Z,SYS_GETRTCCNT1 ; IF NONE, DONE
|
|
INC E ; SET ONE DEVICE
|
|
SYS_GETRTCCNT1:
|
|
XOR A ; SIGNALS SUCCESS
|
|
RET
|
|
;
|
|
; GET VIDEO UNIT COUNT
|
|
;
|
|
SYS_GETVDACNT:
|
|
LD A,(VDA_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST)
|
|
LD E,A ; PUT IT IN E
|
|
XOR A ; SIGNALS SUCCESS
|
|
RET
|
|
;
|
|
; GET VIDEO UNIT API FN ADR AND DATA ADR
|
|
; ENTRY:
|
|
; D: FUNCTION
|
|
; E: UNIT
|
|
; RETURNS:
|
|
; HL: FUNCTION ADDRESS
|
|
; DE: DATA BLOB ADDRESS
|
|
;
|
|
SYS_GETVDAFN:
|
|
LD IY,VDA_TBL ; POINT TO UNIT TABLE
|
|
JP SYS_GETFN ; GO TO COMMON CODE
|
|
;
|
|
; GET SOUND UNIT COUNT
|
|
;
|
|
SYS_GETSNDCNT:
|
|
LD A,(SND_CNT) ; GET DEVICE COUNT (FIRST BYTE OF LIST)
|
|
LD E,A ; PUT IT IN E
|
|
XOR A ; SIGNALS SUCCESS
|
|
RET
|
|
;
|
|
; GET SOUND UNIT API FN ADR AND DATA ADR
|
|
; ENTRY:
|
|
; D: FUNCTION
|
|
; E: UNIT
|
|
; RETURNS:
|
|
; HL: FUNCTION ADDRESS
|
|
; DE: DATA BLOB ADDRESS
|
|
;
|
|
SYS_GETSNDFN:
|
|
LD IY,SND_TBL ; POINT TO UNIT TABLE
|
|
JP SYS_GETFN ; GO TO COMMON CODE
|
|
;
|
|
; SHARED CODE TO COMPLETE A FUNCTION LOOKUP
|
|
; ENTRY:
|
|
; IY: DISPATCH FUNCTION TABLE
|
|
; D: FUNCTION ID
|
|
; E: UNIT NUMBER
|
|
; EXIT:
|
|
; HL: DRIVER FUNCTION ADDRESS
|
|
; DE: DRIVER UNIT DATA ADDRESS
|
|
;
|
|
SYS_GETFN:
|
|
LD A,D ; GET FUNC NUM FROM D
|
|
LD B,A ; AND PUT IN B
|
|
LD A,E ; GET UNIT NUM FROM E
|
|
LD C,A ; AND PUT IN C
|
|
CALL HB_DISPCALC ; CALC FN ADR & BLOB ADR
|
|
PUSH IY ; MOVE DATA ADR
|
|
POP DE ; ... TO DE
|
|
RET ; AF STILL HAS RESULT OF CALC
|
|
;
|
|
; SET SYSTEM PARAMETERS
|
|
; PARAMETER(S) TO SET INDICATED IN C
|
|
;
|
|
SYS_SET:
|
|
LD A,C ; GET REQUESTED SUB-FUNCTION
|
|
CP BF_SYSSET_TIMER
|
|
JR Z,SYS_SETTIMER
|
|
CP BF_SYSSET_SECS
|
|
JR Z,SYS_SETSECS
|
|
CP BF_SYSSET_BOOTINFO
|
|
JR Z,SYS_SETBOOTINFO
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; SET BOOT INFORMATION
|
|
; ON ENTRY:
|
|
; L: BOOT BANK ID
|
|
; DE: BOOT DISK VOLUME (UNIT/SLICE)
|
|
;
|
|
SYS_SETBOOTINFO:
|
|
LD A,L
|
|
LD (CB_BOOTBID),A
|
|
LD (CB_BOOTVOL),DE
|
|
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
|
|
;
|
|
; SET SECS
|
|
; ON ENTRY:
|
|
; DE:HL: SECONDS VALUE (32 BIT)
|
|
;
|
|
SYS_SETSECS:
|
|
LD BC,HB_SECS
|
|
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
|
|
;
|
|
; IF WE ARE USING INTERRUPT MODE 1, WE NEED TO PREVENT INTERRUPTS
|
|
; BECAUSE THE LOW MEMORY BANK CONTAINING THE IM1 VECTOR WILL PROBABLY
|
|
; GET BANKED OUT DURING THE PEEK PROCESSING.
|
|
;
|
|
SYS_PEEK:
|
|
#IF (INTMODE == 1)
|
|
#IF (CPUFAM == CPU_Z280)
|
|
PUSH IY
|
|
;LD C,$00
|
|
LD C,Z280_MSR
|
|
;LDCTL IY,(C)
|
|
.DB $FD,$ED,$66
|
|
PUSH IY
|
|
DI
|
|
#ELSE
|
|
LD A,I
|
|
DI
|
|
PUSH AF
|
|
#ENDIF
|
|
#ENDIF
|
|
CALL HBX_PEEK ; IMPLEMENTED IN PROXY
|
|
#IF (INTMODE == 1)
|
|
#IF (CPUFAM == CPU_Z280)
|
|
;LD C,$00
|
|
LD C,Z280_MSR
|
|
POP IY
|
|
;LDCTL (C),IY
|
|
.DB $FD,$ED,$6E
|
|
POP IY
|
|
#ELSE
|
|
POP AF
|
|
JP PO,$+4
|
|
EI
|
|
#ENDIF
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
; WRITE A BYTE OF MEMORY TO SPECIFIED BANK
|
|
; ENTRY: D=BANK ID, HL=ADDRESS IN HBIOS BANK, E=BYTE VALUE
|
|
;
|
|
; IF WE ARE USING INTERRUPT MODE 1, WE NEED TO PREVENT INTERRUPTS
|
|
; BECAUSE THE LOW MEMORY BANK CONTAINING THE IM1 VECTOR WILL PROBABLY
|
|
; GET BANKED OUT DURING THE POKE PROCESSING.
|
|
;
|
|
SYS_POKE:
|
|
#IF (INTMODE == 1)
|
|
#IF (CPUFAM == CPU_Z280)
|
|
PUSH IY
|
|
LD C,Z280_MSR
|
|
;LDCTL IY,(C)
|
|
.DB $FD,$ED,$66
|
|
PUSH IY
|
|
DI
|
|
#ELSE
|
|
LD A,I
|
|
DI
|
|
PUSH AF
|
|
#ENDIF
|
|
#ENDIF
|
|
CALL HBX_POKE ; IMPLEMENTED IN PROXY
|
|
#IF (INTMODE == 1)
|
|
#IF (CPUFAM == CPU_Z280)
|
|
LD C,Z280_MSR
|
|
POP IY
|
|
;LDCTL (C),IY
|
|
.DB $FD,$ED,$6E
|
|
POP IY
|
|
#ELSE
|
|
POP AF
|
|
JP PO,$+4
|
|
EI
|
|
#ENDIF
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
; INTERRUPT MANAGEMENT FUNCTIONS
|
|
; SUBFUNCTION IN C
|
|
;
|
|
SYS_INT:
|
|
LD A,C ; GET REQUESTED SUB-FUNCTION
|
|
CP BF_SYSINT_INFO
|
|
JR Z,SYS_INTINFO
|
|
CP BF_SYSINT_GET
|
|
JR Z,SYS_INTGET
|
|
CP BF_SYSINT_SET
|
|
JR Z,SYS_INTSET
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; GET INTERRUPT SYSTEM INFORMATION
|
|
; RETURN D:=INTERRUPT MODE, E:=INT VEC TABLE SIZE
|
|
;
|
|
SYS_INTINFO:
|
|
LD D,INTMODE ; D := ACTIVE INTERRUPT MODE
|
|
#IF (INTMODE == 0)
|
|
LD E,0 ; 0 ENTRIES IF INTERRUPTS DISABLED
|
|
#ENDIF
|
|
#IF (INTMODE == 1)
|
|
LD A,(HB_IM1CNT) ; RETURN IM1 CALL LIST SIZE
|
|
LD E,A
|
|
#ENDIF
|
|
#IF (INTMODE == 2)
|
|
LD E,HBX_IVTCNT ; RETURN INT VEC TABLE SIZE
|
|
#ENDIF
|
|
XOR A ; INDICATE SUCCESS
|
|
RET ; AND DONE
|
|
;
|
|
; ROUTINE SHARED BY INT GET/SET. RETURNS ADDRESS OF VECTOR FOR SPECIFIED LIST / TABLE
|
|
; POSITION. ZF SET ON RETURN FOR SUCCESS, ELSE ERROR.
|
|
;
|
|
SYS_INTVECADR:
|
|
#IF (INTMODE == 0)
|
|
CALL SYSCHK ; INVALID FOR INT MODE 0
|
|
LD A,ERR_BADCFG ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
#ENDIF
|
|
#IF (INTMODE == 1)
|
|
LD A,(HB_IM1CNT) ; GET CURRENT ENTRY COUNT
|
|
INC A ; ALLOW FOR EXTRA ENTRY TO APPEND AT END
|
|
LD C,A ; SAVE IN C FOR COMPARE
|
|
#ENDIF
|
|
#IF (INTMODE == 2)
|
|
LD C,HBX_IVTCNT ; GET CURRENT ENTRY COUNT
|
|
#ENDIF
|
|
LD A,E ; INCOMING INDEX POSITION TO A
|
|
CP C ; COMPARE TO VECTOR COUNT
|
|
JR C,SYS_INTGET1 ; CONTINUE IF POSITION IN RANGE
|
|
CALL SYSCHK ; ELSE ERROR
|
|
LD A,ERR_RANGE ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
SYS_INTGET1:
|
|
OR A ; CLEAR CARRY
|
|
RLA ; ADJUST FOR TABLE ENTRY
|
|
RLA ; SIZE OF 4 BYTES
|
|
INC A ; BUMP TO ADR FIELD
|
|
LD H,0
|
|
LD L,A
|
|
LD DE,HB_IVT ; DE := START OF VECTOR TABLE
|
|
ADD HL,DE ; HL := ADR OF VECTOR
|
|
XOR A ; INDICATE SUCCESS
|
|
RET
|
|
;
|
|
; RETURN THE INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE
|
|
; ENTRY: E=LIST/TABLE POSITION
|
|
; RETURN: HL=INTERRUPT VECTOR
|
|
;
|
|
SYS_INTGET:
|
|
CALL SYS_INTVECADR ; GET VECTOR ADDRESS
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
LD A,(HL) ; DEREF HL TO GET VECTOR
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
; SET AN INTERRUPT VECTOR FOR A SPECIFIED POSITION IN THE INT VECTOR LIST / TABLE
|
|
; ENTRY: E=LIST/TABLE POSITION, HL=NEW INTERRUPT VECTOR
|
|
; RETURN: HL=PREVIOUS INTERRUPT VECTOR, DE=ADR OF INT ROUTING ENGINE FOR IM2
|
|
;
|
|
SYS_INTSET:
|
|
PUSH HL ; SAVE NEW VECTOR
|
|
CALL SYS_INTVECADR ; GET VECTOR ADDRESS
|
|
JR Z,SYS_INTSET1 ; CONTINUE IF OK
|
|
POP HL ; FIX STACK
|
|
RET NZ ; BAIL OUT ON ERROR
|
|
SYS_INTSET1:
|
|
PUSH HL ; SAVE VECTOR ADDRESS
|
|
LD A,(HL) ; DEREF HL TO GET PREV VECTOR
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
EX (SP),HL ; (SP) := PREV VEC, HL := VEC ADR
|
|
POP DE ; DE := PREV VEC
|
|
POP BC ; BC := NEW VEC
|
|
LD (HL),C ; SAVE LSB
|
|
INC HL
|
|
LD (HL),B ; SAVE MSB
|
|
EX DE,HL ; HL := PREV VEC
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; DONE
|
|
;
|
|
;==================================================================================================
|
|
; GLOBAL HBIOS FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
; COMMON ROUTINE THAT IS CALLED BY CHARACTER IO DRIVERS WHEN
|
|
; AN IDLE CONDITION IS DETECTED (WAIT FOR INPUT/OUTPUT)
|
|
;
|
|
CIO_IDLE:
|
|
PUSH AF ; PRESERVE AF
|
|
LD A,(IDLECOUNT) ; GET CURRENT IDLE COUNT
|
|
DEC A ; DECREMENT
|
|
LD (IDLECOUNT),A ; SAVE UPDATED VALUE
|
|
CALL Z,IDLE ; IF ZERO, DO IDLE PROCESSING
|
|
POP AF ; RECOVER AF
|
|
RET
|
|
;
|
|
#IF (INTMODE == 1)
|
|
;
|
|
; ROUTINE BELOW IS USED TO ADD A NEW VECTOR TO THE IM1
|
|
; CALL LIST ABOVE. ENTER WITH HL=VECTOR ADDRESS IN HBIOS
|
|
;
|
|
HB_ADDIM1:
|
|
EX DE,HL ; VECTOR ADDRESS TO DE
|
|
LD HL,(HB_IM1PTR) ; GET PTR FOR NEXT ENTRY
|
|
INC HL ; BUMP PTR TO ADDRESS FIELD OF CALL OPCODE
|
|
LD (HL),E ; ADD VECTOR ADDRESS
|
|
INC HL ; ...
|
|
LD (HL),D ; ...
|
|
INC HL ; BUMP PTR
|
|
INC HL ; BUMP PTR
|
|
LD (HB_IM1PTR),HL ; SAVE UPDATED POINTER
|
|
LD HL,HB_IM1CNT ; POINT TO ENTRY COUNT
|
|
INC (HL) ; INCREMENT
|
|
RET ; DONE
|
|
;
|
|
HB_IM1CNT .DB 0 ; NUMBER OF ENTRIES IN CALL LIST
|
|
HB_IM1MAX .DB 8 ; MAX ENTRIES IN CALL LIST
|
|
HB_IM1PTR .DW HB_IVT ; POINTER FOR NEXT IM1 ENTRY
|
|
;
|
|
#ENDIF
|
|
;
|
|
; TIMER HANDLER VECTORS
|
|
; THESE CAN BE HOOKED AS DESIRED BY DRIVERS
|
|
;
|
|
HB_TIMINT:
|
|
VEC_TICK:
|
|
JP HB_TICK ; TICK PROCESSING VECTOR
|
|
VEC_SECOND:
|
|
JP HB_SECOND ; SECOND PROCESSING VECTOR
|
|
;
|
|
; TIMER HANDLERS
|
|
;
|
|
HB_TICK:
|
|
; INCREMENT TICK COUNTER (32 BIT)
|
|
LD HL,HB_TICKS ; POINT TO TICK COUNTER
|
|
CALL INC32HL
|
|
LD HL,HB_SECTCK ; POINT TO SECONDS TICK COUNTER
|
|
DEC (HL) ; COUNTDOWN ONE SECOND OF TICKS
|
|
JR NZ,HB_TICK1 ; NOT DONE, SKIP AHEAD
|
|
LD A,TICKFREQ ; TICKS PER SECOND
|
|
LD (HL),A ; RESET COUNTDOWN REGISTER
|
|
CALL VEC_SECOND ; DO SECONDS PROCESSING VIA VECTOR
|
|
;
|
|
HB_TICK1:
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; ACK/RESET Z180 TIMER INTERRUPT
|
|
IN0 A,(Z180_TCR)
|
|
IN0 A,(Z180_TMDR0L)
|
|
#ENDIF
|
|
;
|
|
#IF (PLATFORM == PLT_EZZ80)
|
|
; PULSE WATCHDOG
|
|
OUT (WDOGIO),A ; VALUE IS IRRELEVANT
|
|
#ENDIF
|
|
;
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED
|
|
RET
|
|
;
|
|
HB_SECOND:
|
|
; INCREMENT SECONDS COUNTER
|
|
LD HL,HB_SECS ; POINT TO SECONDS COUNTER
|
|
JP INC32HL ; INCREMENT AND RETURN
|
|
|
|
;
|
|
; BAD INTERRUPT HANDLER
|
|
;
|
|
HB_BADINT:
|
|
|
|
#IF 0 ; *DEBUG*
|
|
LD HL,HB_BADINTCNT
|
|
INC (HL)
|
|
LD A,(HL)
|
|
OUT (DIAGPORT),A
|
|
OR $FF
|
|
RET
|
|
HB_BADINTCNT .DB 0
|
|
#ENDIF ; *DEBUG*
|
|
|
|
CALL NEWLINE2
|
|
PRTS("+++ BAD INT $")
|
|
LD A,L
|
|
RRCA
|
|
RRCA
|
|
CALL PRTHEXBYTE
|
|
PRTS("H: $")
|
|
|
|
CALL XREGDMP
|
|
;CALL CONTINUE
|
|
OR $FF ; SIGNAL INTERRUPT HANDLED
|
|
RET
|
|
;
|
|
; COMMON API FUNCTION DISPATCH CODE
|
|
;
|
|
; ON ENTRY B IS API FUNCTION NUMBER AND 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:
|
|
PUSH HL ; SAVE INCOMING HL VALUE
|
|
CALL HB_DISPCALC ; IY = BLOB ADR, HL = FN ADR
|
|
JR NZ,HB_DISPCALL1 ; ABORT ON ERROR
|
|
EX (SP),HL ; RESTORE HL & FN ADR TO TOS
|
|
RET ; JUMP TO FN ADR
|
|
HB_DISPCALL1:
|
|
POP HL ; RECOVER HL
|
|
RET ; AND DONE
|
|
;
|
|
; ENTRY: BC=FUNC/UNIT, IY=DISPATCH TABLE
|
|
; EXIT: HL=FUNC ADR, IY=DATA BLOB ADR
|
|
;
|
|
HB_DISPCALC:
|
|
; CHECK INCOMING UNIT INDEX IN C FOR VALIDITY
|
|
LD A,C ; A := INCOMING DISK UNIT INDEX
|
|
CP (IY-1) ; COMPARE TO COUNT
|
|
JR NC,HB_UNITERR ; 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_FUNCERR ; HANDLE FN NUM OUT OF RANGE ERROR
|
|
|
|
; BUMP IY TO ACTUAL XXX_TBL ENTRY FOR INCOMING UNIT INDEX
|
|
PUSH BC ; SAVE BC
|
|
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
|
|
POP BC ; RESTORE BC
|
|
|
|
; 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
|
|
PUSH HL ; SAVE FUNC ADR
|
|
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
|
|
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; JUMP TO DRIVER FUNC ADR ON TOS
|
|
;
|
|
HB_FUNCERR:
|
|
CALL SYSCHK
|
|
LD A,ERR_NOFUNC ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
HB_UNITERR:
|
|
CALL SYSCHK
|
|
LD A,ERR_NOUNIT ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL
|
|
; BC: DRIVER FUNCTION TABLE
|
|
; DE: ADDRESS OF UNIT INSTANCE DATA
|
|
; RETURN
|
|
; A: UNIT NUMBER ASSIGNED
|
|
;
|
|
HB_ADDENT:
|
|
DEC HL ; POINT TO ENTRY COUNT
|
|
LD A,(HL) ; GET ENTRY COUNT
|
|
PUSH AF ; SAVE VALUE TO RETURN AS ENTRY NUM AT END
|
|
INC A ; INCREMENT TO ACCOUNT FOR NEW ENTRY
|
|
DEC HL ; POINT TO ENTRY MAX
|
|
CP (HL) ; COMPARE MAX TO CURRENT COUNT (COUNT - MAX)
|
|
CALL NC,PANIC ; OVERFLOW
|
|
INC HL ; POINT TO COUNT
|
|
LD (HL),A ; SAVE NEW COUNT
|
|
INC HL ; POINT TO START OF TABLE
|
|
DEC A ; CONVERT A FROM ENTRY COUNT TO ENTRY INDEX
|
|
RLCA ; MULTIPLY BY 4
|
|
RLCA ; ... TO GET BYTE OFFSET OF ENTRY
|
|
CALL ADDHLA ; MAKE HL POINT TO ACTUAL ENTRY ADDRESS
|
|
PUSH BC ; GET TABLE ENTRY ADDRESS TO BC
|
|
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 (UNIT NUMBER ASSIGNED)
|
|
RET
|
|
;
|
|
; ALLOCATE HL BYTES OF MEMORY ON THE HEAP
|
|
; RETURNS POINTER TO ALLOCATED SPACE IN HL
|
|
; ON SUCCESS RETURN A == 0, AND Z SET
|
|
; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED
|
|
; ALL OTHER REGISTERS PRESERVED
|
|
;
|
|
; A 4 BYTE HEADER IS PLACED IN FRONT OF THE ALLOCATED MEMORY
|
|
; - DWORD: SIZE OF MEMROY ALLOCATED (DOES NOT INCLUDE 4 BYTE HEADER)
|
|
; - DWORD: ADDRESS WHERE ALLOC WAS CALLED (VALUE ON TOP OF STACK AT CALL)
|
|
;
|
|
HB_ALLOC:
|
|
; SAVE ALLOC SIZE AND REFERENCE ADR FOR SUBSEQUENT HEADER CONSTRUCTION
|
|
LD (HB_TMPSZ),HL ; SAVE INCOMING SIZE REQUESTED
|
|
; USE EX (SP),HL INSTEAD????
|
|
POP HL ; GET RETURN ADDRESS
|
|
LD (HB_TMPREF),HL ; SAVE AS REFERENCE
|
|
; USE EX (SP),HL INSTEAD????
|
|
PUSH HL ; PUT IT BACK ON STACK
|
|
LD HL,(HB_TMPSZ) ; RECOVER INCOMING MEM SIZE PARM
|
|
;
|
|
; CALC NEW HEAP TOP AND HANDLE OUT-OF-SPACE ERROR
|
|
PUSH DE ; SAVE INCOMING DE
|
|
LD DE,4 ; SIZE OF HEADER
|
|
ADD HL,DE ; ADD IT IN
|
|
JR C,HB_ALLOC1 ; ERROR ON OVERFLOW
|
|
LD DE,(CB_HEAPTOP) ; CURRENT HEAP TOP
|
|
ADD HL,DE ; ADD IT IN, HL := NEW HEAP TOP
|
|
JR C,HB_ALLOC1 ; ERROR ON OVERFLOW
|
|
BIT 7,H ; TEST PAST END OF BANK (>= 32K)
|
|
JR NZ,HB_ALLOC1 ; ERROR IF PAST END
|
|
;
|
|
; SAVE NEW HEAP TOP
|
|
LD DE,(CB_HEAPTOP) ; GET ORIGINAL HEAP TOP
|
|
LD (CB_HEAPTOP),HL ; SAVE NEW HEAP TOP
|
|
;
|
|
; SET HEADER VALUES
|
|
EX DE,HL ; HEADER ADR TO HL
|
|
LD DE,(HB_TMPSZ) ; GET THE ORIG SIZE REQUESTED
|
|
LD (HL),E ; SAVE SIZE (LSB)
|
|
INC HL ; BUMP HEADER POINTER
|
|
LD (HL),D ; SAVE SIZE (MSB)
|
|
INC HL ; BUMP HEADER POINTER
|
|
LD DE,(HB_TMPREF) ; GET THE REFERENCE ADR
|
|
LD (HL),E ; SAVE REF ADR (LSB)
|
|
INC HL ; BUMP HEADER POINTER
|
|
LD (HL),D ; SAVE REF ADR (MSB)
|
|
INC HL ; BUMP HEADER POINTER
|
|
;
|
|
; RETURN SUCCESS, HL POINTS TO START OF ALLOCATED MEMORY (PAST HEADER)
|
|
POP DE ; RESTORE INCOMING DE
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND RETURN
|
|
;
|
|
HB_ALLOC1:
|
|
; ERROR RETURN
|
|
POP DE ; RESTORE INCOMING DE
|
|
CALL SYSCHK
|
|
LD A,ERR_NOMEM ; SIGNAL ERROR
|
|
OR A ; SET FLAGS
|
|
RET
|
|
;
|
|
HB_TMPSZ .DW 0
|
|
HB_TMPREF .DW 0
|
|
;
|
|
;==================================================================================================
|
|
; DEVICE DRIVERS
|
|
;==================================================================================================
|
|
;
|
|
#IF (DSRTCENABLE)
|
|
ORG_DSRTC .EQU $
|
|
#INCLUDE "dsrtc.asm"
|
|
SIZ_DSRTC .EQU $ - ORG_DSRTC
|
|
.ECHO "DSRTC occupies "
|
|
.ECHO SIZ_DSRTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (BQRTCENABLE)
|
|
ORG_BQRTC .EQU $
|
|
#INCLUDE "bqrtc.asm"
|
|
SIZ_BQRTC .EQU $ - ORG_BQRTC
|
|
.ECHO "BQRTC occupies "
|
|
.ECHO SIZ_BQRTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (SIMRTCENABLE)
|
|
ORG_SIMRTC .EQU $
|
|
#INCLUDE "simrtc.asm"
|
|
SIZ_SIMRTC .EQU $ - ORG_SIMRTC
|
|
.ECHO "SIMRTC occupies "
|
|
.ECHO SIZ_SIMRTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (INTRTCENABLE)
|
|
ORG_INTRTC .EQU $
|
|
#INCLUDE "intrtc.asm"
|
|
SIZ_INTRTC .EQU $ - ORG_INTRTC
|
|
.ECHO "INTRTC occupies "
|
|
.ECHO SIZ_INTRTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (ASCIENABLE)
|
|
ORG_ASCI .EQU $
|
|
#INCLUDE "asci.asm"
|
|
SIZ_ASCI .EQU $ - ORG_ASCI
|
|
.ECHO "ASCI occupies "
|
|
.ECHO SIZ_ASCI
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (UARTENABLE)
|
|
ORG_UART .EQU $
|
|
#INCLUDE "uart.asm"
|
|
SIZ_UART .EQU $ - ORG_UART
|
|
.ECHO "UART occupies "
|
|
.ECHO SIZ_UART
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (DUARTENABLE)
|
|
ORG_DUART .EQU $
|
|
#INCLUDE "duart.asm"
|
|
SIZ_DUART .EQU $ - ORG_DUART
|
|
.ECHO "DUART occupies "
|
|
.ECHO SIZ_DUART
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (SIOENABLE)
|
|
ORG_SIO .EQU $
|
|
#INCLUDE "sio.asm"
|
|
SIZ_SIO .EQU $ - ORG_SIO
|
|
.ECHO "SIO occupies "
|
|
.ECHO SIZ_SIO
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (ACIAENABLE)
|
|
ORG_ACIA .EQU $
|
|
#INCLUDE "acia.asm"
|
|
SIZ_ACIA .EQU $ - ORG_ACIA
|
|
.ECHO "ACIA occupies "
|
|
.ECHO SIZ_ACIA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (VGAENABLE)
|
|
ORG_VGA .EQU $
|
|
#INCLUDE "vga.asm"
|
|
SIZ_VGA .EQU $ - ORG_VGA
|
|
.ECHO "VGA occupies "
|
|
.ECHO SIZ_VGA
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (CVDUENABLE)
|
|
ORG_CVDU .EQU $
|
|
#INCLUDE "cvdu.asm"
|
|
SIZ_CVDU .EQU $ - ORG_CVDU
|
|
.ECHO "CVDU occupies "
|
|
.ECHO SIZ_CVDU
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (VDUENABLE)
|
|
ORG_VDU .EQU $
|
|
#INCLUDE "vdu.asm"
|
|
SIZ_VDU .EQU $ - ORG_VDU
|
|
.ECHO "VDU occupies "
|
|
.ECHO SIZ_VDU
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (TMSENABLE)
|
|
ORG_TMS .EQU $
|
|
#INCLUDE "tms.asm"
|
|
SIZ_TMS .EQU $ - ORG_TMS
|
|
.ECHO "TMS occupies "
|
|
.ECHO SIZ_TMS
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (NECENABLE)
|
|
ORG_NEC .EQU $
|
|
;#INCLUDE "nec.asm"
|
|
SIZ_NEC .EQU $ - ORG_NEC
|
|
.ECHO "NEC occupies "
|
|
.ECHO SIZ_NEC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
; FONTS AREA
|
|
;
|
|
ORG_FONTS .EQU $
|
|
;
|
|
.ECHO "FONTS"
|
|
;
|
|
#IFDEF USEFONT8X8
|
|
FONT8X8:
|
|
#IF USELZSA2
|
|
#INCLUDE "font8x8c.asm"
|
|
#ELSE
|
|
#INCLUDE "font8x8u.asm"
|
|
#ENDIF
|
|
.ECHO " 8X8"
|
|
#ENDIF
|
|
;
|
|
#IFDEF USEFONT8X11
|
|
FONT8X11:
|
|
#IF USELZSA2
|
|
#INCLUDE "font8x11c.asm"
|
|
#ELSE
|
|
#INCLUDE "font8x11u.asm"
|
|
#ENDIF
|
|
.ECHO " 8X11"
|
|
#ENDIF
|
|
;
|
|
#IFDEF USEFONT8X16
|
|
FONT8X16:
|
|
#IF USELZSA2
|
|
#INCLUDE "font8x16c.asm"
|
|
#ELSE
|
|
#INCLUDE "font8x16u.asm"
|
|
#ENDIF
|
|
.ECHO " 8X16"
|
|
#ENDIF
|
|
;
|
|
SIZ_FONTS .EQU $ - ORG_FONTS
|
|
.ECHO " occupy "
|
|
.ECHO SIZ_FONTS
|
|
.ECHO " bytes.\n"
|
|
;
|
|
#IF (CVDUENABLE | VGAENABLE)
|
|
ORG_KBD .EQU $
|
|
#INCLUDE "kbd.asm"
|
|
SIZ_KBD .EQU $ - ORG_KBD
|
|
.ECHO "KBD occupies "
|
|
.ECHO SIZ_KBD
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (VDUENABLE | (TMSENABLE & (PLATFORM == PLT_N8)))
|
|
ORG_PPK .EQU $
|
|
#INCLUDE "ppk.asm"
|
|
SIZ_PPK .EQU $ - ORG_PPK
|
|
.ECHO "PPK occupies "
|
|
.ECHO SIZ_PPK
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (PRPENABLE)
|
|
ORG_PRP .EQU $
|
|
#INCLUDE "prp.asm"
|
|
SIZ_PRP .EQU $ - ORG_PRP
|
|
.ECHO "PRP occupies "
|
|
.ECHO SIZ_PRP
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (PPPENABLE)
|
|
ORG_PPP .EQU $
|
|
#INCLUDE "ppp.asm"
|
|
SIZ_PPP .EQU $ - ORG_PPP
|
|
.ECHO "PPP occupies "
|
|
.ECHO SIZ_PPP
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (MDENABLE)
|
|
ORG_MD .EQU $
|
|
#INCLUDE "md.asm"
|
|
SIZ_MD .EQU $ - ORG_MD
|
|
.ECHO "MD occupies "
|
|
.ECHO SIZ_MD
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (FDENABLE)
|
|
ORG_FD .EQU $
|
|
#INCLUDE "fd.asm"
|
|
SIZ_FD .EQU $ - ORG_FD
|
|
.ECHO "FD occupies "
|
|
.ECHO SIZ_FD
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (RFENABLE)
|
|
ORG_RF .EQU $
|
|
#INCLUDE "rf.asm"
|
|
SIZ_RF .EQU $ - ORG_RF
|
|
.ECHO "RF occupies "
|
|
.ECHO SIZ_RF
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (IDEENABLE)
|
|
ORG_IDE .EQU $
|
|
#INCLUDE "ide.asm"
|
|
SIZ_IDE .EQU $ - ORG_IDE
|
|
.ECHO "IDE occupies "
|
|
.ECHO SIZ_IDE
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (PPIDEENABLE)
|
|
ORG_PPIDE .EQU $
|
|
#INCLUDE "ppide.asm"
|
|
SIZ_PPIDE .EQU $ - ORG_PPIDE
|
|
.ECHO "PPIDE occupies "
|
|
.ECHO SIZ_PPIDE
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (SDENABLE)
|
|
ORG_SD .EQU $
|
|
#INCLUDE "sd.asm"
|
|
SIZ_SD .EQU $ - ORG_SD
|
|
.ECHO "SD occupies "
|
|
.ECHO SIZ_SD
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (HDSKENABLE)
|
|
ORG_HDSK .EQU $
|
|
#INCLUDE "hdsk.asm"
|
|
SIZ_HDSK .EQU $ - ORG_HDSK
|
|
.ECHO "HDSK occupies "
|
|
.ECHO SIZ_HDSK
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (TERMENABLE)
|
|
ORG_TERM .EQU $
|
|
#INCLUDE "term.asm"
|
|
SIZ_TERM .EQU $ - ORG_TERM
|
|
.ECHO "TERM occupies "
|
|
.ECHO SIZ_TERM
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
;#IF (SPKENABLE & DSRTCENABLE)
|
|
#IF (SPKENABLE)
|
|
ORG_SPK .EQU $
|
|
#INCLUDE "spk.asm"
|
|
SIZ_SPK .EQU $ - ORG_SPK
|
|
.ECHO "SPK occupies "
|
|
.ECHO SIZ_SPK
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (PIO_4P | PIO_ZP | PPI_SBC)
|
|
ORG_PIO .EQU $
|
|
#INCLUDE "pio.asm"
|
|
SIZ_PIO .EQU $ - ORG_PIO
|
|
.ECHO "PIO occupies "
|
|
.ECHO SIZ_PIO
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (UFENABLE)
|
|
ORG_UF .EQU $
|
|
#INCLUDE "uf.asm"
|
|
SIZ_UF .EQU $ - ORG_UF
|
|
.ECHO "UF occupies "
|
|
.ECHO SIZ_UF
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (CTCENABLE)
|
|
ORG_CTC .EQU $
|
|
#INCLUDE "ctc.asm"
|
|
SIZ_CTC .EQU $ - ORG_CTC
|
|
.ECHO "CTC occupies "
|
|
.ECHO SIZ_CTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (SN76489ENABLE)
|
|
ORG_SN76489 .EQU $
|
|
#INCLUDE "sn76489.asm"
|
|
SIZ_SN76489 .EQU $ - ORG_SN76489
|
|
.ECHO "SN76489 occupies "
|
|
.ECHO SIZ_SN76489
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
#IF (AY38910ENABLE)
|
|
ORG_AY38910 .EQU $
|
|
#INCLUDE "ay38910.asm"
|
|
SIZ_AY38910 .EQU $ - ORG_AY38910
|
|
.ECHO "AY38910 occupies "
|
|
.ECHO SIZ_AY38910
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#DEFINE USEDELAY
|
|
#INCLUDE "util.asm"
|
|
#INCLUDE "time.asm"
|
|
#INCLUDE "bcd.asm"
|
|
#INCLUDE "decode.asm"
|
|
#INCLUDE "encode.asm"
|
|
;
|
|
#IF (WBWDEBUG == USEXIO)
|
|
#INCLUDE "xio.asm"
|
|
#ENDIF
|
|
#IF (WBWDEBUG == USEMIO)
|
|
#INCLUDE "mio.asm"
|
|
#ENDIF
|
|
;
|
|
#IF (DSKYENABLE)
|
|
#DEFINE DSKY_KBD
|
|
#INCLUDE "dsky.asm"
|
|
#ENDIF
|
|
;
|
|
; INCLUDE LZSA2 decompression engine if required.
|
|
;
|
|
#IF ((VGAENABLE | CVDUENABLE | TMSENABLE) & USELZSA2)
|
|
#INCLUDE "unlzsa2s.asm"
|
|
#ENDIF
|
|
;
|
|
; DETECT CPU SPEED USING DS-1302 RTC
|
|
;
|
|
HB_CPUSPD:
|
|
;
|
|
#IF (DSRTCENABLE & ((CPUFAM == CPU_Z80) | (CPUFAM == CPU_Z180)))
|
|
;
|
|
LD A,(DSRTC_STAT) ; GET RTC STATUS
|
|
OR A ; SET FLAGS
|
|
RET NZ ; NOT ZERO IS ERROR
|
|
;
|
|
HB_CPUSPD1:
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; USE MEM W/S = 2 AND I/O W/S = 3 FOR TEST
|
|
IN0 A,(Z180_DCNTL)
|
|
PUSH AF
|
|
LD A,$B0
|
|
;LD A,$F0
|
|
OUT0 (Z180_DCNTL),A
|
|
#ENDIF
|
|
|
|
; WAIT FOR AN INITIAL TICK TO ALIGN, THEN WAIT
|
|
; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT
|
|
CALL HB_RDSEC ; GET SECONDS
|
|
LD (HB_CURSEC),A ; AND INIT CURSEC
|
|
CALL HB_WAITSEC ; WAIT FOR SECONDS TICK
|
|
LD (HB_CURSEC),A ; SAVE NEW VALUE
|
|
CALL HB_WAITSEC ; WAIT FOR SECONDS TICK
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; RESTORE W/S SETTINGS FROM BEFORE TEST
|
|
POP AF
|
|
OUT0 (Z180_DCNTL),A
|
|
#ENDIF
|
|
;
|
|
LD A,H
|
|
OR L
|
|
RET Z ; FAILURE, USE DEFAULT CPU SPEED
|
|
;
|
|
; MOVE LOOP COUNT TO HL
|
|
PUSH DE
|
|
POP HL
|
|
;
|
|
; TIMES 4 FOR CPU SPEED IN KHZ
|
|
; RES 0,L ; GRANULARITY
|
|
SLA L
|
|
RL H
|
|
SLA L
|
|
RL H
|
|
;
|
|
LD (CB_CPUKHZ),HL
|
|
LD DE,1000
|
|
CALL DIV16
|
|
LD A,C
|
|
LD (CB_CPUMHZ),A
|
|
;
|
|
RET
|
|
;
|
|
HB_WAITSEC:
|
|
; WAIT FOR SECONDS TICK
|
|
; RETURN SECS VALUE IN A, LOOP COUNT IN DE
|
|
LD DE,0 ; INIT LOOP COUNTER
|
|
HB_WAITSEC1:
|
|
;
|
|
#IF (CPUFAM == CPU_Z80)
|
|
; LOOP TARGET IS 4000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4
|
|
CALL DLY32
|
|
CALL DLY16
|
|
CALL DLY1 ; 27 TSTATES
|
|
SBC HL,HL ; 15 TSTATES
|
|
SBC HL,HL ; 15 TSTATES
|
|
INC HL ; 6 TSTATES
|
|
INC HL ; 6 TSTATES
|
|
#ENDIF
|
|
;
|
|
#IF (CPUFAM == CPU_Z180)
|
|
; LOOP TARGET IS 4000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4
|
|
CALL DLY2
|
|
ADD IX,BC ; 10 + 4 = 14 TSTATES
|
|
NOP ; 5 TSTATES
|
|
NOP ; 5 TSTATES
|
|
NOP ; 5 TSTATES
|
|
NOP ; 5 TSTATES
|
|
#ENDIF
|
|
;
|
|
PUSH DE ; SAVE COUNTER
|
|
CALL HB_RDSEC ; GET SECONDS
|
|
POP DE ; RESTORE COUNTER
|
|
INC DE ; BUMP COUNTER
|
|
LD HL,HB_CURSEC ; POINT TO COMP VALUE
|
|
CP (HL) ; TEST FOR CHANGE
|
|
RET NZ ; DONE IF TICK OCCURRED
|
|
LD A,D ; CHECK DE
|
|
OR E ; ... FOR OVERFLOW
|
|
RET Z ; TIMEOUT, SOMETHING IS WRONG
|
|
JR HB_WAITSEC1 ; LOOP
|
|
;
|
|
HB_RDSEC:
|
|
; READ SECONDS BYTE INTO A
|
|
LD E,$81 ; SECONDS REGISTER
|
|
CALL DSRTC_CMD ; SEND THE COMMAND
|
|
CALL DSRTC_GET ; READ THE REGISTER
|
|
CALL DSRTC_END ; FINISH IT
|
|
LD A,E ; VALUE TO A
|
|
RET
|
|
;
|
|
#ELSE
|
|
;
|
|
RET ; NO RTC, ABORT
|
|
;
|
|
#ENDIF
|
|
;
|
|
; SYSTEM CHECK: DUMP MACHINE STATE AND CONTINUE?
|
|
;
|
|
SYSCHK:
|
|
; CHECK DIAG LEVEL TO SEE IF WE SHOULD DISPLAY
|
|
PUSH AF ; PRESERVE INCOMING AF VALUE
|
|
LD A,(CB_DIAGLVL) ; GET DIAGNOSTIC LEVEL
|
|
CP DL_ERROR ; >= ERROR LEVEL
|
|
JR C,SYSCHK1 ; IF NOT, GO HOME
|
|
POP AF ; RESTORE INCOMING AF VALUE
|
|
;
|
|
; DISPLAY SYSCHK MESSAGE
|
|
PUSH DE ; PRESERVE DE VALUE
|
|
LD DE,STR_SYSCHK ; POINT TO PREFIX STRING
|
|
CALL WRITESTR ; PRINT IT
|
|
POP DE ; RESTORE DE VALUE
|
|
CALL XREGDMP ; DUMP REGISTERS
|
|
JR CONTINUE ; CHECK W/ USER
|
|
;
|
|
SYSCHK1:
|
|
; RETURN IF MESSAGING BYPASSED BY DIAG LEVEL
|
|
POP AF
|
|
RET
|
|
;
|
|
; PANIC: DUMP MACHINE STATE AND HALT
|
|
;
|
|
PANIC:
|
|
PUSH DE
|
|
LD DE,STR_PANIC
|
|
CALL WRITESTR
|
|
POP DE
|
|
CALL XREGDMP ; DUMP REGISTERS
|
|
JR SYSHALT ; FULL STOP
|
|
;
|
|
;
|
|
;
|
|
CONTINUE:
|
|
PUSH AF
|
|
CONTINUE1:
|
|
PUSH DE
|
|
LD DE,STR_CONTINUE
|
|
CALL WRITESTR
|
|
POP DE
|
|
CALL CIN
|
|
RES 5,A ; FORCE UPPERCASE (IMPERFECTLY)
|
|
CALL COUT ; ECHO
|
|
CP 'Y'
|
|
JR Z,CONTINUE3
|
|
CP 'N'
|
|
JR Z,SYSHALT
|
|
JR CONTINUE1
|
|
CONTINUE3:
|
|
CALL NEWLINE
|
|
POP AF
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
SYSHALT:
|
|
LD DE,STR_HALT
|
|
CALL WRITESTR
|
|
DI
|
|
HALT
|
|
;
|
|
; PRINT VALUE OF HL AS THOUSANDTHS, IE. 0.000
|
|
;
|
|
PRTD3M:
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
LD E,'0'
|
|
LD BC,-10000
|
|
CALL PRTD3M1
|
|
LD E,0
|
|
LD BC,-1000
|
|
CALL PRTD3M1
|
|
CALL PC_PERIOD
|
|
LD BC,-100
|
|
CALL PRTD3M1
|
|
LD C,-10
|
|
CALL PRTD3M1
|
|
LD C,-1
|
|
CALL PRTD3M1
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
PRTD3M1:
|
|
LD A,'0' - 1
|
|
PRTD3M2:
|
|
INC A
|
|
ADD HL,BC
|
|
JR C,PRTD3M2
|
|
SBC HL,BC
|
|
CP E
|
|
JR Z,PRTD3M3
|
|
LD E,0
|
|
CALL COUT
|
|
PRTD3M3:
|
|
RET
|
|
;==================================================================================================
|
|
; DISPLAY SUMMARY OF ATTACHED UNITS/DEVICES
|
|
;==================================================================================================
|
|
;
|
|
PRTSUM:
|
|
CALL NEWLINE2 ; SKIP A LINE
|
|
LD DE,PS_STRHDR ; POINT TO HEADER
|
|
CALL WRITESTR ; PRINT IT
|
|
;
|
|
LD C,BF_SYSGET_CIOCNT ; CHARACTER DEVICES
|
|
LD HL,PS_SERIAL
|
|
CALL PRT_ALLD
|
|
;
|
|
LD C,BF_SYSGET_DIOCNT ; DISK DRIVES
|
|
LD HL,PS_DISK
|
|
CALL PRT_ALLD
|
|
;
|
|
LD C,BF_SYSGET_VDACNT ; VIDEO DEVICES
|
|
LD HL,PS_VIDEO
|
|
CALL PRT_ALLD
|
|
;
|
|
LD C,BF_SYSGET_SNDCNT ; SOUND DEVICES
|
|
LD HL,PS_SOUND
|
|
CALL PRT_ALLD
|
|
RET
|
|
;
|
|
PRT_ALLD:
|
|
LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET
|
|
RST 08 ; E := UNIT COUNT
|
|
LD B,E ; MOVE TO B FOR LOOP COUNT
|
|
LD A,E ; MOVE TO ACCUM
|
|
OR A ; SET FLAGS
|
|
RET Z ; IF NONE, JUST RETURN
|
|
LD C,0 ; C WILL BE UNIT INDEX
|
|
PRT_ALLD1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
PUSH DE
|
|
PUSH HL
|
|
CALL JPHL ; CALL THE ROUTINE PASSED IN HL
|
|
POP HL
|
|
POP DE
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; BUMP UNIT INDEX
|
|
DJNZ PRT_ALLD1 ; LOOP THRU ALL DEVICES
|
|
RET
|
|
;
|
|
; PRINT ONE LINE DISK UNIT/DEVICE INFO, DISK UNIT INDEX IN C
|
|
;
|
|
PS_DISK:
|
|
PUSH BC ; SAVE UNIT INDEX FOR LATER
|
|
;
|
|
; UNIT COLUMN
|
|
PRTS("Disk $")
|
|
LD A,C ; MOVE UNIT NUM TO A
|
|
CALL PRTDECB ; PRINT IT
|
|
CP 10 ; CHECK FOR MULTIPLE DIGITS
|
|
CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED
|
|
PRTS(" $") ; PAD TO NEXT COLUMN
|
|
;
|
|
; DEVICE COLUMN
|
|
LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C
|
|
RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES
|
|
PUSH BC ; SAVE ATTRIBUTES
|
|
LD HL,PS_DDSTRREF ; POINT TO DISK DEVICE TYPE NAME TABLE
|
|
CALL PS_PRTDEV ; PRINT DISK DEVICE NMEMONIC PADDED TO FIELD WIDTH
|
|
POP DE ; RECOVER ATTRIBUTES TO DE
|
|
PUSH DE ; SAVE ATTRIBUTES AGAIN
|
|
CALL PS_PRTDT ; PRINT DISK TYPE
|
|
POP DE ; RESTORE ATTRIBUTES
|
|
POP BC ; RESTORE UNIT NUM
|
|
CALL PS_PRTDC ; PRINT DISK CAPACITY
|
|
;
|
|
CALL NEWLINE
|
|
RET
|
|
;
|
|
; PRINT DISK TYPE (DISK ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTDT:
|
|
LD A,E ; ATTRIBUTES TO A
|
|
BIT 7,A ; FLOPPY BIT SET?
|
|
LD HL,PS_DTFLOP ; ASSUME FLOPPY
|
|
JR NZ,PS_PRTDT1 ; IF FLOPPY, JUMP AHEAD
|
|
RRCA ; SHIFT TYPE BITS
|
|
RRCA
|
|
RRCA
|
|
AND $07 ; AND ISOLATE THEM
|
|
RLCA ; X2 FOR WORD OFFSET IN STRING TABLE
|
|
LD HL,PS_DTSTRREF + 2 ; POINT TO STR REF TABLE (SKIP FLOPPY STRING)
|
|
CALL ADDHLA
|
|
LD A,(HL)
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
;
|
|
PS_PRTDT1:
|
|
CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED
|
|
LD A,18 ; 18 CHAR FIELD
|
|
SUB C
|
|
CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A)
|
|
RET
|
|
;
|
|
; PRINT DISK CAPACITY (UNIT IN C, ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTDC:
|
|
;
|
|
LD A,E ; ATTRIBUTE TO ACCUM
|
|
BIT 7,A ; TEST FOR FLOPPY
|
|
JR NZ,PS_PRTDC2 ; HANDLE FLOPPY
|
|
RRCA ; ISOLATE TYPE BITS
|
|
RRCA
|
|
RRCA
|
|
AND $07
|
|
CP 4 ; ROM DISK?
|
|
JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB
|
|
CP 5 ; RAM DISK?
|
|
JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB
|
|
CP 7 ; FLASH DISK?
|
|
JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB
|
|
;
|
|
; PRINT HARD DISK STORAGE SIZE IN MB
|
|
LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY
|
|
RST 08 ; DE:HL := BLOCKS
|
|
JP NZ,PS_PRTNUL ; MEDIA PROBLEM
|
|
RES 7,D ; CLEAR LBA BIT
|
|
LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
|
|
CALL SRL32 ; RIGHT SHIFT
|
|
CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED)
|
|
PRTS("MB$") ; PRINT SUFFIX
|
|
CALL PC_COMMA
|
|
PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA
|
|
RET ; DONE
|
|
;
|
|
PS_PRTDC1:
|
|
; PRINT ROM/ROM DISK CAPACITY IN KB
|
|
LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY
|
|
RST 08 ; DE:HL := BLOCKS
|
|
JP NZ,PS_PRTNUL ; MEDIA PROBLEM
|
|
RES 7,D ; CLEAR LBA BIT
|
|
LD B,1 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB
|
|
CALL SRL32 ; RIGHT SHIFT
|
|
CALL PRTDEC ; PRINT LOW WORD IN DECIMAL (HIGH WORD DISCARDED)
|
|
PRTS("KB$") ; PRINT SUFFIX
|
|
CALL PC_COMMA
|
|
PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA
|
|
RET ; DONE
|
|
;
|
|
PS_PRTDC2:
|
|
LD C,E ; ATTRIBUTE TO C FOR SAFE KEEPING
|
|
;
|
|
LD A,01100000B ; DISPLAY FORM FACTOR
|
|
LD DE,PS_FLP_FSTR ; WHICH IS DEFINED IN
|
|
CALL PRTIDXMSK ; BITS 5 AND 6.
|
|
;
|
|
LD A,00010000B ; DISPLAY SIDES
|
|
LD DE,PS_FLP_SSTR ; WHICH IS DEFINED
|
|
CALL PRTIDXMSK ; IN BIT 4
|
|
;
|
|
LD A,00001100B ; DISPLAY DENSITY
|
|
LD DE,PS_FLP_DSTR ; WHICH IS DEFINED IN
|
|
CALL PRTIDXMSK ; BITS 2 AND 3.
|
|
;
|
|
CALL PC_COMMA
|
|
PRTS("CHS$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA
|
|
;
|
|
RET ; DONE
|
|
;
|
|
; PRINT ONE LINE SERIAL UNIT/DEVICE INFO, SERIAL UNIT INDEX IN C
|
|
;
|
|
PS_SERIAL:
|
|
PUSH BC ; SAVE UNIT INDEX FOR LATER
|
|
;
|
|
; UNIT COLUMN
|
|
PRTS("Char $")
|
|
LD A,C ; MOVE UNIT NUM TO A
|
|
CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT
|
|
PRTS(" $") ; PAD TO NEXT COLUMN
|
|
;
|
|
; DEVICE COLUMN
|
|
LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C
|
|
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
|
|
POP BC ; RECOVER ATTRIBUTES
|
|
PUSH BC ; SAVE ATTRIBUTES AGAIN
|
|
CALL PS_PRTST ; PRINT SERIAL TYPE
|
|
POP BC ; RESTORE ATTRIBUTES
|
|
POP DE ; RESTORE UNIT NUM TO E
|
|
CALL PS_PRTSC ; PRINT SERIAL CONFIG
|
|
;
|
|
CALL NEWLINE
|
|
RET
|
|
;
|
|
; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTST:
|
|
LD HL,PS_STPPT
|
|
BIT 6,C
|
|
JR NZ,PS_PRTST1 ; PARALLEL TYPE?
|
|
LD HL,PS_STRS232 ; ASSUME RS-232
|
|
BIT 7,C ; 0=RS-232, 1=TERMINAL
|
|
JR Z,PS_PRTST1 ; HANDLE TERMINAL TYPE
|
|
LD HL,PS_STTERM ; TYPE IS TERMINAL
|
|
;
|
|
PS_PRTST1:
|
|
CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED
|
|
LD A,18 ; 18 CHAR FIELD
|
|
SUB C
|
|
CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A)
|
|
RET
|
|
;
|
|
; PRINT SERIAL CONFIG (UNIT IN E, ATTRIBUTE IN C)
|
|
;
|
|
PS_PRTSC:
|
|
BIT 6,C ; PARALLEL TYPE?
|
|
JR NZ,PSPRTPC0
|
|
|
|
BIT 7,C ; 0=RS-232, 1=TERMINAL
|
|
JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG
|
|
;
|
|
; 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
|
|
INC A ; SET Z IF DE == $FF
|
|
JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED
|
|
;
|
|
PS_PRTSC0:
|
|
; PRINT BAUD RATE
|
|
PUSH DE ; PRESERVE DE
|
|
LD A,D
|
|
AND $1F ; ISOLATE ENCODED BAUD RATE
|
|
LD L,A ; PUT IN L
|
|
LD H,0 ; H IS ALWAYS ZERO
|
|
LD DE,75 ; BAUD RATE DECODE CONSTANT
|
|
CALL DECODE ; DE:HL := BAUD RATE
|
|
LD BC,HB_BCDTMP ; POINT TO TEMP BCD BUF
|
|
CALL BIN2BCD ; CONVERT TO BCD
|
|
CALL PRTBCD ; AND PRINT IN DECIMAL
|
|
POP DE ; RESTORE DE
|
|
;
|
|
; PRINT DATA BITS
|
|
PUSH DE ; PRESERVE DE
|
|
CALL PC_COMMA ; FORMATTING
|
|
LD A,E ; GET CONFIG BYTE
|
|
AND $03 ; ISOLATE DATA BITS VALUE
|
|
ADD A,'5' ; CONVERT TO CHARACTER
|
|
CALL COUT ; AND PRINT
|
|
POP DE ; RESTORE DE
|
|
;
|
|
; PRINT PARITY
|
|
PUSH DE ; PRESERVE DE
|
|
CALL PC_COMMA ; FORMATTING
|
|
LD A,E ; GET CONFIG BYTE
|
|
RRCA ; SHIFT RELEVANT BITS
|
|
RRCA ; ...
|
|
RRCA ; ...
|
|
AND $07 ; AND ISOLATE DATA BITS VALUE
|
|
LD HL,PS_STPARMAP ; CHARACTER LOOKUP TABLE
|
|
CALL ADDHLA ; APPLY OFFSET
|
|
LD A,(HL) ; GET CHARACTER
|
|
CALL COUT ; AND PRINT
|
|
POP DE ; RESTORE DE
|
|
;
|
|
; PRINT STOP BITS
|
|
CALL PC_COMMA ; FORMATTING
|
|
LD A,E ; GET CONFIG BYTE
|
|
RRCA ; SHIFT RELEVANT BITS
|
|
RRCA ; ...
|
|
AND $01 ; AND ISOLATE DATA BITS VALUE
|
|
ADD A,'1' ; MAKE IT A CHARACTER
|
|
CALL COUT ; AND PRINT
|
|
;
|
|
RET
|
|
;
|
|
PSPRTPC0:
|
|
LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG
|
|
LD C,E ; SET PARALLEL UNIT NUM
|
|
RST 08 ; DE:HL := I/O SETTING
|
|
LD A,D ; TEST FOR $FF
|
|
AND E
|
|
INC A ; SET Z IF DE == $FF
|
|
JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED
|
|
;
|
|
PS_PRTPC0:
|
|
LD C,E ; DISPLAY PIO TYPE
|
|
LD A,11000000B ; WHICH IS DEFINE BY
|
|
LD DE,PIO_MODE_STR ; BITS 6 AND 7
|
|
JP PRTIDXMSK
|
|
; RET ; TRICK RETURN
|
|
;
|
|
PS_PRTSC1:
|
|
; PRINT TERMINAL CONFIG
|
|
LD A,C ; GET ATTRIBUTE VALUE
|
|
CP $BF ; NO ATTACHED VDA
|
|
JR Z,PS_PRTSC2
|
|
PRTS("Video $") ; FORMATTING
|
|
AND $0F ; ISOLATE VIDEO UNIT NUM
|
|
CALL PRTDECB ; PRINT IT
|
|
CALL PC_COMMA
|
|
#IF (VDAEMU == EMUTYP_TTY)
|
|
PRTS("TTY$")
|
|
#ENDIF
|
|
#IF (VDAEMU == EMUTYP_ANSI)
|
|
PRTS("ANSI$")
|
|
#ENDIF
|
|
RET
|
|
;
|
|
PS_PRTSC2:
|
|
PRTS("PropTerm$") ; ASSUME PROPELLER
|
|
CALL PC_COMMA
|
|
PRTS("ANSI$")
|
|
RET
|
|
;
|
|
; PRINT ONE LINE VIDEO UNIT/DEVICE INFO, VIDEO UNIT INDEX IN C
|
|
;
|
|
PS_VIDEO:
|
|
PUSH BC ; SAVE UNIT INDEX FOR LATER
|
|
;
|
|
; UNIT COLUMN
|
|
PRTS("Video $")
|
|
LD A,C ; MOVE UNIT NUM TO A
|
|
CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT
|
|
PRTS(" $") ; PAD TO NEXT COLUMN
|
|
;
|
|
; DEVICE COLUMN
|
|
LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C
|
|
RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES
|
|
PUSH BC ; SAVE ATTRIBUTES
|
|
LD HL,PS_VDSTRREF ; POINT TO VIDEO DEVICE TYPE NAME TABLE
|
|
CALL PS_PRTDEV ; PRINT VIDEO DEVICE NMEMONIC PADDED TO FIELD WIDTH
|
|
POP DE ; RECOVER ATTRIBUTES
|
|
PUSH DE ; SAVE ATTRIBUTES AGAIN
|
|
CALL PS_PRTVT ; PRINT VIDEO TYPE
|
|
POP DE ; RESTORE ATTRIBUTES
|
|
POP BC ; RESTORE UNIT NUM
|
|
CALL PS_PRTVC ; PRINT VIDEO CONFIG
|
|
;
|
|
CALL NEWLINE
|
|
RET
|
|
;
|
|
; PRINT VIDEO TYPE (VIDEO ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTVT:
|
|
LD HL,PS_VTCRT ; ASSUME CRT
|
|
CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED
|
|
LD A,18 ; 18 CHAR FIELD
|
|
SUB C
|
|
CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A)
|
|
RET
|
|
;
|
|
; PRINT VIDEO CONFIG (UNIT IN C, ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTVC:
|
|
PRTS("Text$")
|
|
CALL PC_COMMA
|
|
LD B,BF_VDAQRY ; FUNC: QUERY FOR VDA CONFIG
|
|
RST 08 ; D:=ROWS, E:=COLS
|
|
LD A,E
|
|
CALL PRTDECB
|
|
LD A,'x'
|
|
CALL COUT
|
|
LD A,D
|
|
CALL PRTDECB
|
|
RET
|
|
;
|
|
; PRINT SOUND CONFIG
|
|
;
|
|
PS_SOUND:
|
|
PUSH BC
|
|
|
|
; UNIT COLUMN
|
|
PRTS("Sound $")
|
|
LD A,C ; MOVE UNIT NUM TO A
|
|
CALL PRTDECB ; PRINT IT
|
|
CP 10 ; CHECK FOR MULTIPLE DIGITS
|
|
CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED
|
|
PRTS(" $") ; PAD TO NEXT COLUMN
|
|
|
|
; DEVICE COLUMN
|
|
|
|
PUSH BC ;
|
|
LD E,C
|
|
XOR A
|
|
LD DE,PS_SDSND ; POINT TO DEVICE TYPE NAME TABLE
|
|
CALL PRTIDXDEA ; PRINT DEVICE NMEMONIC PADDED TO FIELD WIDTH
|
|
LD A,C ; MOVE UNIT NUM TO A
|
|
CALL PRTDECB ; PRINT IT
|
|
CALL PC_COLON
|
|
CP 10 ; CHECK FOR MULTIPLE DIGITS
|
|
CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED
|
|
LD A,(PRTIDXCNT)
|
|
SUB 9+1
|
|
CPL
|
|
CALL PS_PAD
|
|
POP BC
|
|
|
|
; DEVICE TYPE
|
|
;
|
|
LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C
|
|
LD E,BF_SNDQ_DEV
|
|
RST 08
|
|
LD A,B
|
|
;DEC A
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
RLCA
|
|
AND $0F
|
|
LD DE,PS_SDSN76489
|
|
CALL PRTIDXDEA
|
|
LD A,(PRTIDXCNT)
|
|
SUB 18+1
|
|
CPL
|
|
CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A)
|
|
|
|
; DEVICE CHARACTERISTICS
|
|
;
|
|
LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C
|
|
LD E,BF_SNDQ_CHCNT
|
|
RST 08
|
|
LD A,B
|
|
CALL PRTDECB
|
|
LD A,'+'
|
|
CALL COUT
|
|
LD A,C
|
|
CALL PRTDECB
|
|
PRTS(" CHANNELS$")
|
|
CALL NEWLINE
|
|
;
|
|
POP BC
|
|
RET
|
|
;
|
|
; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE
|
|
;
|
|
PS_PRTDEV:
|
|
LD A,D
|
|
RRCA ; TYPE IS IN UPPER NIBBLE, MOVE TO LOWER NIBBLE
|
|
RRCA
|
|
RRCA
|
|
RRCA
|
|
RLCA ; X2 FOR WORD OFFSET IN STRING TABLE
|
|
CALL ADDHLA
|
|
LD A,(HL)
|
|
INC HL
|
|
LD H,(HL)
|
|
LD L,A
|
|
CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED
|
|
LD A,E ; NUM
|
|
CALL PRTDECB ; PRINT NUM, ASSUME 1 CHAR
|
|
CALL PC_COLON ; PRINT COLON
|
|
LD A,12 - 2 ; 12 CHAR FIELD - 1 POS FOR UNIT NUM AND 1 POS FOR COLON
|
|
SUB C
|
|
CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A)
|
|
RET
|
|
;
|
|
; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE
|
|
;
|
|
PS_PRTNUL:
|
|
LD HL,PS_STRNUL
|
|
; FALL THRU TO PS_PRT
|
|
;
|
|
;
|
|
;
|
|
PS_PRT:
|
|
; PRINT STRING AT (HL), $ TERM, RETURN CHARS PRINTED IN C
|
|
LD C,0 ; INIT CHAR COUNT
|
|
PS_PRT1:
|
|
LD A,(HL) ; GET CHAR
|
|
INC HL ; BUMP INDEX
|
|
CP '$' ; TERM?
|
|
RET Z ; IF SO, DONE
|
|
CALL COUT ; PRINT IT
|
|
INC C ; BUMP COUNTER
|
|
JR PS_PRT1 ; AND LOOP
|
|
;
|
|
;
|
|
;
|
|
PS_PAD:
|
|
; PAD N SPACES SPECIFIED IN A
|
|
LD B,A
|
|
LD A,' '
|
|
PS_PAD1:
|
|
CALL COUT
|
|
DJNZ PS_PAD1
|
|
RET
|
|
;
|
|
HB_CPU_STR: .TEXT " Z80$"
|
|
.TEXT " Z80180$"
|
|
.TEXT " Z8S180-K$"
|
|
.TEXT " Z8S180-N$"
|
|
.TEXT " Z80280$"
|
|
;
|
|
PS_STRNUL .TEXT "--$" ; DISPLAY STRING FOR NUL VALUE
|
|
;
|
|
; DISK DEVICE STRINGS
|
|
;
|
|
PS_DDSTRREF:
|
|
.DW PS_DDMD, PS_DDFD, PS_DDRF, PS_DDIDE, PS_DDATAPI, PS_DDPPIDE
|
|
.DW PS_DDSD, PS_DDPRPSD, PS_DDPPPSD, PS_DDHDSK
|
|
;
|
|
PS_DDMD .TEXT "MD$"
|
|
PS_DDFD .TEXT "FD$"
|
|
PS_DDRF .TEXT "RF$"
|
|
PS_DDIDE .TEXT "IDE$"
|
|
PS_DDATAPI .TEXT "ATAPI$"
|
|
PS_DDPPIDE .TEXT "PPIDE$"
|
|
PS_DDSD .TEXT "SD$"
|
|
PS_DDPRPSD .TEXT "PRPSD$"
|
|
PS_DDPPPSD .TEXT "PPPSD$"
|
|
PS_DDHDSK .TEXT "HDSK$"
|
|
;
|
|
; DISK TYPE STRINGS
|
|
;
|
|
PS_DTSTRREF:
|
|
.DW PS_DTFLOP, PS_DTHARD, PS_DTCF, PS_DTSD
|
|
.DW PS_DTUSB, PS_DTROM, PS_DTRAM, PS_DTRF, PS_DTFSH
|
|
;
|
|
PS_DTFLOP .TEXT "Floppy Disk$"
|
|
PS_DTHARD .TEXT "Hard Disk$"
|
|
PS_DTCF .TEXT "CompactFlash$"
|
|
PS_DTSD .TEXT "SD Card$"
|
|
PS_DTUSB .TEXT "USB Drive$"
|
|
PS_DTROM .TEXT "ROM Disk$"
|
|
PS_DTRAM .TEXT "RAM Disk$"
|
|
PS_DTRF .TEXT "RAM Floppy$"
|
|
PS_DTFSH .TEXT "Flash Drive$"
|
|
PS_DTOTHER .TEXT "???$"
|
|
;
|
|
; FLOPPY ATTRIBUTE STRINGS
|
|
;
|
|
PS_FLP_FSTR: .TEXT "8\",$" ; PS_FLP8
|
|
.TEXT "5.25\",$" ; PS_FLP5
|
|
.TEXT "3.5\",$" ; PS_FLP3
|
|
.TEXT "???\",$" ; PS_FLPN
|
|
;
|
|
PS_FLP_SSTR: .TEXT "SS/$" ; PS_FLPSS
|
|
.TEXT "DS/$" ; PS_FLPDS
|
|
;
|
|
PS_FLP_DSTR: .TEXT "SD$" ; PS_FLPSD
|
|
.TEXT "DD$" ; PS_FLPDD
|
|
.TEXT "HD$" ; PS_FLPHD
|
|
.TEXT "ED$" ; PS_FLPED
|
|
;
|
|
; CHARACTER DEVICE STRINGS
|
|
;
|
|
PS_SDSTRREF:
|
|
.DW PS_SDUART, PS_SDASCI, PS_SDTERM
|
|
.DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA, PS_SDPIO,PS_SDUF,PS_SDDUART
|
|
;
|
|
PS_SDUART .TEXT "UART$"
|
|
PS_SDASCI .TEXT "ASCI$"
|
|
PS_SDTERM .TEXT "TERM$"
|
|
PS_SDPRPCON .TEXT "PRPCON$"
|
|
PS_SDPPPCON .TEXT "PPPCON$"
|
|
PS_SDSIO .TEXT "SIO$"
|
|
PS_SDACIA .TEXT "ACIA$"
|
|
PS_SDPIO .TEXT "PORT$"
|
|
PS_SDUF .TEXT "UF$"
|
|
PS_SDDUART .TEXT "DUART$"
|
|
;
|
|
; CHARACTER SUB TYPE STRINGS
|
|
;
|
|
PS_STRS232 .TEXT "RS-232$"
|
|
PS_STTERM .TEXT "Terminal$"
|
|
PS_STPPT .TEXT "Parallel$"
|
|
;
|
|
PS_STPARMAP .DB "NONENMNS"
|
|
;
|
|
; PARALLEL TYPE STRINGS
|
|
;
|
|
PIO_MODE_STR: .TEXT "Output$"
|
|
.TEXT "Input$"
|
|
.TEXT "Bidirectional$"
|
|
.TEXT "BitCtrl$"
|
|
;
|
|
; VIDEO DEVICE STRINGS
|
|
;
|
|
PS_VDSTRREF:
|
|
.DW PS_VDVDU, PS_VDCVDU, PS_VDNEC, PS_VDTMS, PS_VDVGA
|
|
;
|
|
PS_VDVDU .TEXT "VDU$"
|
|
PS_VDCVDU .TEXT "CVDU$"
|
|
PS_VDNEC .TEXT "NEC$"
|
|
PS_VDTMS .TEXT "TMS$"
|
|
PS_VDVGA .TEXT "VGA$"
|
|
;
|
|
; VIDEO TYPE STRINGS
|
|
;
|
|
PS_VTCRT .TEXT "CRT$"
|
|
;
|
|
; SOUND DEVICE STRINGS
|
|
;
|
|
PS_SDSND .TEXT "SND$"
|
|
;
|
|
; SOUND TYPE STRINGS
|
|
;
|
|
PS_SDSN76489 .TEXT "SN76489$"
|
|
PS_SDAY38910 .TEXT "AY-3-8910$"
|
|
PS_SDBITMODE .TEXT "I/O PORT$"
|
|
;
|
|
; 0 1 2 3 4 5 6 7
|
|
; 01234567890123456789012345678901234567890123456789012345678901234567890123456789
|
|
PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n"
|
|
.TEXT "---------- ---------- ---------------- --------------------\r\n$"
|
|
;
|
|
;==================================================================================================
|
|
; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED)
|
|
;==================================================================================================
|
|
;
|
|
; OUTPUT CHARACTER FROM A
|
|
;
|
|
COUT:
|
|
; SAVE ALL INCOMING REGISTERS
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
;
|
|
; GET CURRENT CONSOLE UNIT
|
|
LD E,A ; TEMPORARILY STASH OUTPUT CHAR IN E
|
|
LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE
|
|
CP $FF ; TEST FOR $FF (HBIOS NOT READY)
|
|
JR Z,COUT1 ; IF NOT READY, TRY DEBUG OUTPUT
|
|
;
|
|
; USE HBIOS
|
|
LD C,A ; CONSOLE UNIT TO C
|
|
LD B,BF_CIOOUT ; HBIOS FUNC: OUTPUT CHAR
|
|
CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY
|
|
JR COUT2 ; CONTINUE
|
|
;
|
|
COUT1:
|
|
;
|
|
#IF (WBWDEBUG == USEXIO)
|
|
LD A,E ; GET OUTPUT CHAR BACK TO ACCUM
|
|
CALL XIO_OUTC ; OUTPUT VIA XIO
|
|
#ENDIF
|
|
;
|
|
#IF (WBWDEBUG == USEMIO)
|
|
LD A,E
|
|
CALL MIO_OUTC ; OUTPUT VIA MIO
|
|
#ENDIF
|
|
;
|
|
COUT2:
|
|
; RESTORE ALL REGISTERS
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
RET
|
|
;
|
|
; INPUT CHARACTER TO A
|
|
;
|
|
CIN:
|
|
; SAVE INCOMING REGISTERS (AF IS OUTPUT)
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
;
|
|
LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE
|
|
CP $FF ; TEST FOR $FF (HBIOS NOT READY)
|
|
JR Z,CIN1 ; IF NOT READY, TRY DEBUG INPUT
|
|
;
|
|
; USE HBIOS
|
|
LD C,A ; CONSOLE UNIT TO C
|
|
LD B,BF_CIOIN ; HBIOS FUNC: INPUT CHAR
|
|
CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY
|
|
LD A,E ; RESULTANT CHAR TO A
|
|
JR CIN2 ; CONTINUE
|
|
;
|
|
CIN1:
|
|
;
|
|
#IF (WBWDEBUG == USEXIO)
|
|
CALL XIO_INC ; GET CHAR
|
|
#ENDIF
|
|
;
|
|
#IF (WBWDEBUG == USEMIO)
|
|
CALL MIO_INC ; GET CHAR
|
|
#ENDIF
|
|
;
|
|
CIN2:
|
|
;
|
|
; RESTORE REGISTERS (AF IS OUTPUT)
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
; RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING)
|
|
;
|
|
CST:
|
|
; SAVE INCOMING REGISTERS (AF IS OUTPUT)
|
|
PUSH BC
|
|
PUSH DE
|
|
PUSH HL
|
|
;
|
|
LD A,(CB_CONDEV) ; GET CONSOLE UNIT BYTE
|
|
CP $FF ; TEST FOR $FF (HBIOS NOT READY)
|
|
JR Z,CST1 ; IIF NOT READY, TRY DEBUG DEBUG STATUS
|
|
;
|
|
; USE HBIOS
|
|
LD C,A ; CONSOLE UNIT TO C
|
|
LD B,BF_CIOIST ; HBIOS FUNC: INPUT STATUS
|
|
CALL CIO_DISPATCH ; CALL CIO DISPATCHER DIRECTLY
|
|
JR CST2 ; CONTINUE
|
|
;
|
|
CST1:
|
|
;
|
|
#IF (WBWDEBUG == USEXIO)
|
|
CALL XIO_IST ; GET STATUS
|
|
#ENDIF
|
|
;
|
|
#IF (WBWDEBUG == USEMIO)
|
|
CALL MIO_IST ; GET STATUS
|
|
#ENDIF
|
|
;
|
|
CST2:
|
|
; RESTORE REGISTERS (AF IS OUTPUT)
|
|
POP HL
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; MISCELLANEOUS UTILITY FUNCTIONS
|
|
;==================================================================================================
|
|
;
|
|
; SET HL TO IY+A, A IS TRASHED
|
|
;
|
|
LDHLIYA:
|
|
PUSH IY ; COPY INSTANCE DATA PTR
|
|
POP HL ; ... TO HL
|
|
;JP ADDHLA ; APPLY OFFSET TO HL AND RETURN
|
|
ADD A,L ; ADD OFFSET TO LSB
|
|
LD L,A ; ... PUT BACK IN L
|
|
RET NC ; DONE IF CF NOT SET
|
|
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
|
|
;==================================================================================================
|
|
;
|
|
IDLECOUNT .DB 0
|
|
;
|
|
HEAPCURB .DW 0 ; MARK HEAP ADDRESS AFTER INITIALIZATION
|
|
;
|
|
HB_TICKS .FILL 4,0 ; 32 BIT TICK COUNTER
|
|
HB_SECTCK .DB TICKFREQ ; TICK COUNTER FOR FRACTIONAL SECONDS
|
|
HB_SECS .FILL 4,0 ; 32 BIT SECONDS COUNTER
|
|
;
|
|
HB_CPUTYPE .DB 0 ; 0=Z80, 1=80180, 2=SL1960, 3=ASCI BRG
|
|
;
|
|
RTCVAL .DB RTCDEF ; SHADOW VALUE FOR RTC LATCH PORT
|
|
;
|
|
HB_BATCOND .DB 0 ; BATTERY CONDITION (0=LOW, 1=OK)
|
|
;
|
|
#IF (BT_REC_TYPE != BT_REC_NONE)
|
|
HB_BOOT_REC .DB 0 ; BOOT MODE (0=NORMAL, 1=RECOVERY MODE)
|
|
#ENDIF
|
|
;
|
|
STR_BANNER .DB "RomWBW HBIOS v", BIOSVER, ", ", TIMESTAMP, "$"
|
|
STR_PLATFORM .DB PLATFORM_NAME, "$"
|
|
STR_SWITCH .DB "*** Activating CRT Console ***$"
|
|
STR_BADINT .DB "\r\n*** BAD INT ***\r\n$"
|
|
STR_LOWBAT .DB "\r\n\r\n+++ LOW BATTERY +++$"
|
|
;
|
|
STR_PANIC .TEXT "\r\n>>> PANIC: $"
|
|
STR_SYSCHK .TEXT "\r\n>>> SYSCHK: $"
|
|
STR_CONTINUE .TEXT "\r\nContinue (Y/N)? $"
|
|
;
|
|
#IF (DSKYENABLE) ; 'H','B','I','O',' ',' ',' ',' '
|
|
MSG_HBVER .DB $BE,$FF,$8A,$FB,$80,$80,$80,$80 ; "HBIO "
|
|
#ENDIF
|
|
;
|
|
HB_APPBNK .DB 0 ; START BANK WHEN RUN IN APP MODE
|
|
;
|
|
HB_CURSEC .DB 0 ; CURRENT SECOND (TEMP)
|
|
;
|
|
HB_BCDTMP .FILL 5,0 ; BCD NUMBER STORAGE (TEMP)
|
|
;
|
|
HB_WRKBUF .FILL 512,0 ; INTERNAL DISK BUFFER
|
|
;
|
|
HB_END .EQU $
|
|
;
|
|
SLACK .EQU BNKTOP - $
|
|
.ECHO "HBIOS space remaining: "
|
|
.ECHO SLACK
|
|
.ECHO " bytes.\n"
|
|
;
|
|
#IFDEF ROMBOOT
|
|
.FILL SLACK
|
|
#ENDIF
|
|
;
|
|
.END
|