mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4776 lines
115 KiB
4776 lines
115 KiB
;
|
|
;==================================================================================================
|
|
; 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 (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
|
|
;
|
|
; 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 VAILIDITY
|
|
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
|
|
;
|
|
; 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_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_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
|
|
|