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.
3317 lines
80 KiB
3317 lines
80 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 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 ((PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180))
|
|
#DEFINE DIAGP $00
|
|
#ENDIF
|
|
;
|
|
#IFDEF DIAGP
|
|
#DEFINE DIAG(N) PUSH AF
|
|
#DEFCONT \ LD A,N
|
|
#DEFCONT \ OUT (DIAGP),A
|
|
#DEFCONT \ POP AF
|
|
#ELSE
|
|
#DEFINE DIAG(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
|
|
;
|
|
;
|
|
;
|
|
#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) 2015, 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
|
|
;
|
|
; 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 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
|
|
;==================================================================================================
|
|
;
|
|
HBX_INVOKE:
|
|
LD (HBX_INVSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
LD (HB_INVBNK),A ; SAVE INVOCATION BANK
|
|
|
|
LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH
|
|
LD A,BID_BIOS ; HBIOS BANK
|
|
CALL HBX_BNKSEL ; SELECT IT
|
|
LD SP,HB_STACK ; NOW USE FULL HBIOS STACK IN HBIOS BANK
|
|
|
|
CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER
|
|
|
|
LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM FOR BANK SWITCH
|
|
PUSH AF ; SAVE AF (FUNCTION RETURN)
|
|
|
|
LD A,(HB_INVBNK) ; LOAD ORIGINAL BANK
|
|
CALL HBX_BNKSEL ; SELECT IT
|
|
POP AF ; RESTORE AF
|
|
LD SP,0 ; RESTORE ORIGINAL STACK FRAME
|
|
HBX_INVSP .EQU $ - 2
|
|
|
|
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 ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA))
|
|
#IF (INTMODE == 1)
|
|
; THIS BIT OF ABSURDITY HANDLES A RARE (BUT FATAL) SITUATION
|
|
; WHERE AN IM1 INTERRUPT OCCURS BETWEEN SETTING THE RAM AND
|
|
; ROM SELECTORS. BRACKETING THE INSTRUCTIONS WITH DI/EI
|
|
; IS CONTRAINDICATED BECAUSE THIS ROUTINE IS CALLED BY
|
|
; OTHER ROUTINES THAT MUST CONTROL INT ENABLE AT A HIGHER
|
|
; LEVEL. THE FOLLOWING TECHNIQUE ENSURES THAT YOU ALWAYS
|
|
; SWITCH DIRECTLY FROM THE PREVIOUS BANK TO THE TARGET BANK
|
|
; WITHOUT AN "ERRANT" BANK BEING ACTIVE BETWEEN THE TWO
|
|
; BANK SELECTION I/O INSTRUCTIONS. THE TECHNIQUE IS ONLY
|
|
; NEEDED WHEN USING INT MODE 1 BECAUSE THAT MODE REQUIRES
|
|
; PAGE ONE TO HAVE A VALID INT HANDLER WHENEVER INTS ARE
|
|
; ENABLED.
|
|
;BIT 7,A ; [8] TEST RAM BIT
|
|
;JR Z,HBX_ROM ; [12/7] IF NOT SET, JUST DO ROM
|
|
OR A ; [4] SET FLAGS
|
|
JP P,HBX_ROM ; [10] BIT 7 INDICATES RAM
|
|
#ENDIF
|
|
OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR
|
|
HBX_ROM:
|
|
OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR
|
|
RET ; DONE
|
|
#ENDIF
|
|
#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80))
|
|
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
|
|
;OUT (DIAGP),A ; *DEBUG*
|
|
INC A ;
|
|
OUT (MPGSEL_1),A ; BANK_1: 16K - 32K
|
|
RET ; DONE
|
|
#ENDIF
|
|
#IF (PLATFORM == PLT_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 (PLATFORM == PLT_MK4)
|
|
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
|
|
;
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Copy Data - Possibly between banks. This resembles CP/M 3, but
|
|
; usage of the HL and DE registers is reversed.
|
|
; Caller MUST ensure stack is already in high memory.
|
|
; Caller MUST preset HBX_SRCBNK and HBX_DSTBNK.
|
|
; Caller MUST disable ints if IM1 active
|
|
; Enter:
|
|
; HL = Source Address
|
|
; DE = Destination Address
|
|
; BC = Number of bytes to copy
|
|
; Exit : None
|
|
; Uses : AF,BC,DE,HL
|
|
;
|
|
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
;
|
|
HBX_BNKCPY:
|
|
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
|
|
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 TARGTET BANK IS PREPARED FOR THEM.
|
|
; ON INPUT A=TARGET BANK, HL=TARGET ADDRESS
|
|
;
|
|
HBX_BNKCALL:
|
|
LD (HBX_TGTBNK),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW
|
|
LD (HBX_TGTADR),HL ; STUFF ADDRESS TO CALL INTO CODE BELOW
|
|
LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
PUSH AF ; SAVE FOR RETURN
|
|
HBX_TGTBNK .EQU $ + 1
|
|
LD A,$FF ; LOAD BANK TO CALL ($FF OVERLAID AT ENTRY)
|
|
CALL HBX_BNKSEL ; ACTIVATE THE NEW BANK
|
|
|
|
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
|
|
; CALLER MUST DISABLE INTS IF IM1 AND ACCESSING PAGE W/O IM1 INT VECTOR
|
|
;
|
|
HBX_PEEK:
|
|
LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM
|
|
LD A,(HB_CURBNK)
|
|
PUSH AF
|
|
LD A,D
|
|
CALL HBX_BNKSEL
|
|
LD E,(HL)
|
|
JR HBX_PPRET
|
|
;
|
|
HBX_POKE:
|
|
LD (HBX_PPSP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_TMPSTK ; USE SMALL TEMP STACK FRAME IN HI MEM
|
|
LD A,(HB_CURBNK)
|
|
PUSH AF
|
|
LD A,D
|
|
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
|
|
;
|
|
; SMALL TEMPORARY STACK FOR USE BY INVOKE, PEEK, AND POKE
|
|
;
|
|
.FILL 20,$CC ; 10 LEVEL STACK
|
|
HBX_TMPSTK .EQU $
|
|
;
|
|
; PRIVATE STACK AT END OF HBIOS CODE
|
|
; OCCUPIES SPACE BEFORE IVT
|
|
;
|
|
HBX_STKSIZ .EQU $FF00 - $
|
|
.ECHO "HBIOS PROXY STACK space: "
|
|
.ECHO HBX_STKSIZ
|
|
.ECHO " bytes.\n"
|
|
.FILL HBX_STKSIZ,$FF
|
|
HBX_STACK .EQU $
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
; HBIOS INTERRUPT VECTOR TABLE (16 ENTRIES)
|
|
;
|
|
HBX_IVT:
|
|
.DW INT_BAD ; IVT_INT1
|
|
.DW INT_BAD ; IVT_INT2
|
|
.DW INT_BAD ; IVT_TIM0
|
|
.DW INT_BAD ; IVT_TIM1
|
|
.DW INT_BAD ; IVT_DMA0
|
|
.DW INT_BAD ; IVT_DMA1
|
|
.DW INT_BAD ; IVT_CSIO
|
|
.DW INT_BAD ; IVT_SER0
|
|
.DW INT_BAD ; IVT_SER1
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
.DW INT_BAD ;
|
|
;
|
|
HBX_IVTCNT .EQU ($ - HBX_IVT) / 2
|
|
;
|
|
HBX_ITBL:
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
.DW HB_BADINT
|
|
#ENDIF
|
|
;
|
|
; INTERRUPT HANDLER STUBS
|
|
;
|
|
; THE FOLLOWING INTERRUPT STUBS RECEIVE CONTROL FROM THE
|
|
; INTERRUPT, SETUP A HANDLER VECTOR IN HBIOS AND THEN
|
|
; BRANCH TO THE COMMON INTERRUPT DISPATCHER
|
|
;
|
|
;
|
|
INT_IM1:
|
|
#IF (INTMODE == 1)
|
|
PUSH HL ; SAVE HL
|
|
LD HL,HB_IM1INT ; HL := IM1 INT HANDLER IN BIOS BANK
|
|
JR HBX_INT ; TO TO ROUTING CODE
|
|
#ELSE
|
|
RETI ; UNEXPECTED INT, RET W/ INTS LEFT DISABLED
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
INT_BAD: ; BAD INTERRUPT HANDLER
|
|
PUSH HL ; SAVE HL
|
|
LD HL,HB_BADINT ; HL := INT HANDLER IN BIOS BANK
|
|
JR HBX_INT ; GO TO ROUTING CODE
|
|
;
|
|
INT_TIMER: ; TIMER INTERRUPT HANDLER
|
|
PUSH HL ; SAVE HL
|
|
LD HL,HB_TIMINT ; HL := INT ADR IN BIOS
|
|
JR HBX_INT ; GO TO ROUTING CODE
|
|
;
|
|
#IF (SIOENABLE)
|
|
INT_SIO: ; SIO INTERRUPT HANDLER
|
|
PUSH HL ; SAVE HL
|
|
LD HL,SIO_INT ; HL := SIO INT HANDLER IN BIOS BANK
|
|
JR HBX_INT ; GO TO ROUTING CODE
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE > 0)
|
|
;
|
|
; COMMON INTERRUPT DISPATCHING CODE
|
|
; SETUP AND CALL HANDLER IN BIOS BANK
|
|
;
|
|
HBX_INT: ; COMMON INTERRUPT ROUTING CODE
|
|
;
|
|
LD (HBX_INT_SP),SP ; SAVE ORIGINAL STACK FRAME
|
|
LD SP,HBX_STACK ; USE 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
|
|
|
|
CALL JPHL ; CALL INTERRUPT ROUTINE
|
|
|
|
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
|
|
;
|
|
; FILL TO START OF BOUNCE BUFFER
|
|
;
|
|
HBX_INTFILL .EQU (HBX_XFC - HBX_BUFSIZ - $)
|
|
.ECHO "HBIOS INT space remaining: "
|
|
.ECHO HBX_INTFILL
|
|
.ECHO " bytes.\n"
|
|
.FILL HBX_INTFILL,$FF
|
|
;
|
|
; INTERBANK COPY BUFFER (64 BYTES)
|
|
;
|
|
HBX_BUF .FILL HBX_BUFSIZ,0
|
|
;
|
|
; HBIOS PROXY MGMT BLOCK (TOP 32 BYTES)
|
|
;
|
|
#IFDEF ROMBOOT
|
|
.DB BID_BOOT ; CURRENTLY ACTIVE LOW MEMORY BANK ID
|
|
#ELSE
|
|
.DB BID_USR ; CURRENTLY ACTIVE LOW MEMORY BANK ID
|
|
#ENDIF
|
|
.DB 0 ; BANK ACTIVE AT TIME OF HBIOS CALL INVOCATION
|
|
.DW 0 ; BNKCPY SOURCE ADDRESS
|
|
.DB BID_USR ; BNKCPY SOURCE BANK ID
|
|
.DW 0 ; BNKCPY DESTINATION ADDRESS
|
|
.DB BID_USR ; BNKCPY DESTINATION BANK ID
|
|
.DW 0 ; BNKCPY LENGTH
|
|
.FILL 6,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE
|
|
JP HBX_INVOKE ; FIXED ADR ENTRY FOR HBX_INVOKE (ALT FOR RST 08)
|
|
JP HBX_BNKSEL ; FIXED ADR ENTRY FOR HBX_BNKSEL
|
|
JP HBX_BNKCPY ; FIXED ADR ENTRY FOR HBX_BNKCPY
|
|
JP HBX_BNKCALL ; FIXED ADR ENTRY FOR HBX_BNKCALL
|
|
.DW HBX_IDENT ; ADDRESS OF HBIOS PROXY START (DEPRECATED)
|
|
.DW HBX_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
|
|
|
|
;
|
|
;==================================================================================================
|
|
; SYSTEM INITIALIZATION
|
|
;==================================================================================================
|
|
;
|
|
HB_START:
|
|
DI ; NO INTERRUPTS
|
|
IM 1 ; INTERRUPT MODE 1
|
|
;
|
|
#IFDEF DIAGP
|
|
LD A,%00000001
|
|
OUT (DIAGP),A
|
|
#ENDIF
|
|
;
|
|
LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY
|
|
;
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
; SET BASE FOR CPU IO REGISTERS
|
|
LD A,Z180_BASE
|
|
OUT0 (Z180_ICR),A
|
|
|
|
DIAG(%00000010)
|
|
|
|
; DISABLE REFRESH
|
|
XOR A
|
|
OUT0 (Z180_RCR),A
|
|
|
|
; MASK OFF TIMER INTERRUPTS
|
|
XOR A
|
|
OUT0 (Z180_TCR),A
|
|
|
|
; SET DEFAULT CPU CLOCK MULTIPLIERS (XTAL / 2)
|
|
XOR A
|
|
OUT0 (Z180_CCR),A
|
|
OUT0 (Z180_CMR),A
|
|
|
|
; SET DEFAULT WAIT STATES
|
|
LD A,$F0
|
|
OUT0 (Z180_DCNTL),A
|
|
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4))
|
|
; 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
|
|
|
|
#IF (Z180_CLKDIV >= 1)
|
|
; SET CLOCK DIVIDE TO 1 RESULTING IN FULL XTAL SPEED
|
|
LD A,$80
|
|
OUT0 (Z180_CCR),A
|
|
#ENDIF
|
|
|
|
#IF (Z180_CLKDIV >= 2)
|
|
; SET CPU MULTIPLIER TO 1 RESULTING IN XTAL * 2 SPEED
|
|
LD A,$80
|
|
OUT0 (Z180_CMR),A
|
|
#ENDIF
|
|
|
|
#ENDIF
|
|
;
|
|
#IF ((PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_RC180) | (PLATFORM == PLT_EZZ80))
|
|
; 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)
|
|
;
|
|
; INSTALL PROXY IN UPPER MEMORY
|
|
;
|
|
|
|
;X1 .EQU $8000
|
|
;X2 .EQU X1 + 2
|
|
;X3 .EQU X2 + 2
|
|
;X4 .EQU X3 + 2
|
|
|
|
; LD HL,(HBX_IMG)
|
|
; LD (X1),HL
|
|
|
|
; LD HL,(HBX_IMG)
|
|
; LD (X2),HL
|
|
|
|
LD HL,HBX_IMG
|
|
LD DE,HBX_LOC
|
|
LD BC,HBX_SIZ
|
|
LDIR
|
|
|
|
; LD HL,(HBX_IMG)
|
|
; LD (X3),HL
|
|
|
|
; LD HL,(HBX_LOC)
|
|
; LD (X4),HL
|
|
|
|
;
|
|
; 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
|
|
;
|
|
; TRANSITION TO HBIOS IN RAM BANK
|
|
;
|
|
LD A,BID_BIOS ; BIOS BANK ID
|
|
LD HL,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 SP,HBX_LOC ; RESET STACK SINCE WE DO NOT RETURN
|
|
LD A,TRUE ; ACCUM := TRUE
|
|
LD (HB_RAMFLAG),A ; SET RAMFLAG
|
|
;
|
|
; IF APPBOOT, WE NEED TO FIX UP A FEW THINGS IN PAGE ZERO
|
|
;
|
|
#IFDEF APPBOOT
|
|
; MAKE SURE RST 08 VECTOR IS RIGHT
|
|
LD A,$C3
|
|
LD ($0008),A
|
|
LD HL,HB_INVOKE
|
|
LD ($0009),HL
|
|
;
|
|
; MAKE SURE IM1 INT VECTOR IS RIGHT
|
|
#IF (INTMODE == 1)
|
|
; JP INT_IM1 IF INTERRUPT MODE ACTIVE
|
|
LD A,$C3
|
|
LD ($0038),A
|
|
LD HL,INT_IM1
|
|
LD ($0039),HL
|
|
#ELSE
|
|
; RETI ($ED, $4D) IF NON-INTERRUPT MODE
|
|
LD HL,($0038)
|
|
LD (HL),$ED
|
|
INC HL
|
|
LD (HL),$4D
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
DIAG(%00001111)
|
|
;
|
|
#IF (DSKYENABLE)
|
|
LD HL,MSG_HBVER
|
|
CALL DSKY_SHOWSEG
|
|
#ENDIF
|
|
;
|
|
; PERFORM DYNAMIC CPU SPEED DERIVATION
|
|
;
|
|
CALL HB_CPUSPD ; CPU SPEED DETECTION
|
|
;
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
;
|
|
; SET DESIRED WAIT STATES
|
|
LD A,0 + (Z180_MEMWAIT << 6) | (Z180_IOWAIT << 4)
|
|
OUT0 (Z180_DCNTL),A
|
|
;
|
|
#ENDIF
|
|
;
|
|
CALL DELAY_INIT ; INITIALIZE SPEED COMPENSATED DELAY FUNCTIONS
|
|
;
|
|
DIAG(%00011111)
|
|
;
|
|
; 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)
|
|
;
|
|
; PRE-CONSOLE INITIALIZATION
|
|
;
|
|
#IF (ASCIENABLE)
|
|
CALL ASCI_PREINIT
|
|
#ENDIF
|
|
#IF (UARTENABLE)
|
|
CALL UART_PREINIT
|
|
#ENDIF
|
|
#IF (SIOENABLE)
|
|
CALL SIO_PREINIT
|
|
#ENDIF
|
|
#IF (ACIAENABLE)
|
|
CALL ACIA_PREINIT
|
|
#ENDIF
|
|
;
|
|
DIAG(%01111111)
|
|
;
|
|
; PRIOR TO THIS POINT, CONSOLE I/O WAS DIRECTED TO HARDWARE (XIO.ASM).
|
|
; 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
|
|
;
|
|
; ANNOUNCE HBIOS
|
|
;
|
|
CALL NEWLINE2
|
|
PRTX(STR_BANNER)
|
|
;
|
|
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
|
|
;
|
|
; SETUP INTERRUPT VECTORS, AS APPROPRIATE
|
|
;
|
|
;#IF (INTMODE == 1)
|
|
; ; OVERLAY $0038 WITH JP INT_IM1
|
|
; LD A,$C3 ; JP INSTRUCTION
|
|
; LD ($0038),A ; INSTALL IT
|
|
; LD HL,INT_IM1 ; DESTINATION ADDRESS
|
|
; LD ($0039),HL ; INSTALL IT
|
|
;#ENDIF
|
|
;
|
|
#IF (INTMODE == 2)
|
|
; SETUP Z80 IVT AND INT MODE 2
|
|
LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS
|
|
LD I,A ; ... AND PLACE IT IN I REGISTER
|
|
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
; 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
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;LD HL,INT_TIMER
|
|
;LD (HBX_IVT),HL
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
;
|
|
#IF (INTMODE == 2)
|
|
;
|
|
; MASK ALL EXTERNAL INTERRUPTS FOR NOW
|
|
;XOR A ; INT0-2 DISABLED
|
|
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,INT_TIMER
|
|
LD (HBX_IVT + IVT_TIM0),HL
|
|
|
|
; SETUP PERIODIC TIMER INTERRUPT ON TIMER 0
|
|
LD HL,(CB_CPUKHZ) ; 50HZ = 18432000 / 20 / 50 / X, SO X = CPU KHZ
|
|
LD B,0
|
|
LD C,Z180_RLDR0L ; INITIALIZE TIMER 0 RELOAD REGISTER
|
|
OUT (C),L
|
|
INC C
|
|
OUT (C),H
|
|
LD C,Z180_TMDR0L ; INITIALIZE TIMER 0 DATA REGISTER
|
|
OUT (C),L
|
|
INC C
|
|
OUT (C),H
|
|
LD A,%00010001 ; ENABLE TIMER0 INT AND DOWN COUNTING
|
|
OUT0 (Z180_TCR),A
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
HB_EI ; INTERRUPTS SHOULD BE OK NOW
|
|
;
|
|
; DISPLAY PLATFORM INFORMATION
|
|
;
|
|
CALL NEWLINE2
|
|
PRTX(STR_PLATFORM)
|
|
PRTS(" @ $")
|
|
LD HL,(CB_CPUKHZ)
|
|
CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA
|
|
PRTS("MHz$")
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
CALL PC_COMMA
|
|
PRTS(" IO=0x$")
|
|
LD A,Z180_BASE
|
|
CALL PRTHEXBYTE
|
|
#ENDIF
|
|
;
|
|
; DISPLAY CPU CONFIG
|
|
;
|
|
;CALL PRTSTRD
|
|
;.TEXT ", $"
|
|
CALL NEWLINE
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
LD A,Z180_MEMWAIT
|
|
#ELSE
|
|
LD A,0
|
|
#ENDIF
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " MEM W/S, $"
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
LD A,Z180_IOWAIT + 1
|
|
#ELSE
|
|
LD A,1
|
|
#ENDIF
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " I/O W/S$"
|
|
#IF (INTMODE > 0)
|
|
CALL PRTSTRD
|
|
.TEXT ", INT MODE $"
|
|
LD A,INTMODE
|
|
CALL PRTDECB
|
|
#ENDIF
|
|
;
|
|
; DISPLAY MEMORY CONFIG
|
|
;
|
|
CALL NEWLINE
|
|
;CALL PRTSTRD
|
|
;.TEXT "MEMORY CONFIG: $"
|
|
LD HL,ROMSIZE
|
|
CALL PRTDEC
|
|
CALL PRTSTRD
|
|
.TEXT "KB ROM, $"
|
|
LD HL,RAMSIZE
|
|
CALL PRTDEC
|
|
CALL PRTSTRD
|
|
.TEXT "KB RAM$"
|
|
;
|
|
; PERFORM DEVICE INITIALIZATION
|
|
;
|
|
CALL NEWLINE
|
|
LD B,HB_INITTBLLEN
|
|
LD DE,HB_INITTBL
|
|
INITSYS1:
|
|
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 INITSYS1
|
|
;
|
|
; 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_N8) & (PLATFORM != PLT_MK4) & (PLATFORM != PLT_RC) & (PLATFORM != PLT_RC180) & (PLATFORM != PLT_EZZ80))
|
|
IN A,(RTC) ; 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 HL,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 HL,$8000 ; HL = COPY LEN = ENTIRE BANK
|
|
RST 08 ; DO IT
|
|
LD B,BF_SYSBNKCPY ; HBIOS FUNC: PERFORM BANK COPY
|
|
LD HL,HB_END ; COPY FROM END OF OF HBIOS
|
|
LD DE,0 ; TO USER ADDRESS 0
|
|
RST 08 ; DO IT
|
|
;
|
|
; PERFORM BANK CALL TO USER BANK
|
|
LD A,BID_USR ; CHAIN TO OS IMAGES BANK
|
|
LD HL,0 ; ENTER AT ADDRESS 0
|
|
CALL HBX_BNKCALL ; GO THERE
|
|
HALT ; WE SHOULD NEVER COME BACK!
|
|
;
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; TABLE OF INITIALIZATION ENTRY POINTS
|
|
;==================================================================================================
|
|
;
|
|
HB_INITTBL:
|
|
#IF (SPKENABLE)
|
|
.DW SPK_INIT ; AUDIBLE INDICATOR OF BOOT START
|
|
#ENDIF
|
|
#IF (AYENABLE)
|
|
.DW AY_INIT ; AUDIBLE INDICATOR OF BOOT START
|
|
#ENDIF
|
|
#IF (ASCIENABLE)
|
|
.DW ASCI_INIT
|
|
#ENDIF
|
|
#IF (UARTENABLE)
|
|
.DW UART_INIT
|
|
#ENDIF
|
|
#IF (SIOENABLE)
|
|
.DW SIO_INIT
|
|
#ENDIF
|
|
#IF (ACIAENABLE)
|
|
.DW ACIA_INIT
|
|
#ENDIF
|
|
#IF (SIMRTCENABLE)
|
|
.DW SIMRTC_INIT
|
|
#ENDIF
|
|
#IF (DSRTCENABLE)
|
|
.DW DSRTC_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
|
|
;
|
|
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_DISPCALL ; DO THE WORK
|
|
;
|
|
; CHECK STACK INTEGRITY
|
|
PUSH AF
|
|
LD A,(HB_STACK - HB_STKSIZ + $08)
|
|
CP $FF
|
|
CALL NZ,PANIC
|
|
LD A,$FF
|
|
LD (HB_STACK - HB_STKSIZ + $08),A
|
|
POP AF
|
|
RET
|
|
HB_DISPCALL:
|
|
;
|
|
#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
|
|
CALL C,PANIC ; OBSOLETE!
|
|
CP BF_VDA + $10 ; $40-$4F: VIDEO DISPLAY ADAPTER
|
|
JP C,VDA_DISPATCH
|
|
CP BF_SYS ; SKIP TO BF_SYS VALUE AT $F0
|
|
CALL C,PANIC ; PANIC IF LESS THAN BF_SYS
|
|
JP SYS_DISPATCH ; OTHERWISE SYS CALL
|
|
CALL PANIC ; THIS SHOULD NEVER BE REACHED
|
|
RET
|
|
;
|
|
;==================================================================================================
|
|
; CHARACTER I/O DEVICE 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 DIO 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
|
|
;
|
|
;==================================================================================================
|
|
; REAL TIME CLOCK DEVICE DISPATCHER
|
|
;==================================================================================================
|
|
;
|
|
; ROUTE CALL TO REAL TIME CLOCK DRIVER
|
|
; B: FUNCTION
|
|
;
|
|
RTC_DISPATCH:
|
|
#IF (SIMRTCENABLE)
|
|
JP SIMRTC_DISPATCH
|
|
#ENDIF
|
|
#IF (DSRTCENABLE)
|
|
JP DSRTC_DISPATCH
|
|
#ENDIF
|
|
CALL PANIC
|
|
;
|
|
;==================================================================================================
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; 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
|
|
CALL PANIC ; INVALID
|
|
;
|
|
; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS
|
|
;
|
|
SYS_RESET:
|
|
LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD
|
|
LD (CB_HEAPTOP),HL ; RESTORE HEAP TOP
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET THE CURRENT HBIOS VERSION
|
|
; ON INPUT, C=0
|
|
; RETURNS VERSION IN DE AS BCD
|
|
; D: MAJOR VERION IN TOP 4 BITS, MINOR VERSION IN LOW 4 BITS
|
|
; E: UPDATE VERION IN TOP 4 BITS, PATCH VERSION IN LOW 4 BITS
|
|
; L: PLATFORM ID
|
|
;
|
|
SYS_VER:
|
|
LD DE,0 | (RMJ << 12) | (RMN << 8) | (RUP << 4) | RTP
|
|
LD L,PLATFORM
|
|
XOR A
|
|
RET
|
|
;
|
|
; SET ACTIVE MEMORY BANK AND RETURN PREVIOUSLY ACTIVE MEMORY BANK
|
|
; NOTE THAT IT GOES INTO EFFECT AS HBIOS FUNCTION IS EXITED
|
|
; HERE, WE JUST SET THE CURRENT BANK
|
|
; 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
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HB_BNKCPY
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
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 PANIC ; NOT YET IMPLEMENTED
|
|
OR $FF
|
|
RET
|
|
;
|
|
; GET SYSTEM INFORMATION
|
|
; ITEM TO RETURN INDICATED IN C
|
|
;
|
|
SYS_GET:
|
|
LD A,C ; GET REQUESTED SUB-FUNCTION
|
|
CP BF_SYSGET_CIOCNT
|
|
JR Z,SYS_GETCIOCNT
|
|
CP BF_SYSGET_DIOCNT
|
|
JR Z,SYS_GETDIOCNT
|
|
CP BF_SYSGET_VDACNT
|
|
JR Z,SYS_GETVDACNT
|
|
CP BF_SYSGET_TIMER
|
|
JR Z,SYS_GETTIMER
|
|
CP BF_SYSGET_BOOTINFO
|
|
JR Z,SYS_GETBOOTINFO
|
|
CP BF_SYSGET_CPUINFO
|
|
JR Z,SYS_GETCPUINFO
|
|
CP BF_SYSGET_MEMINFO
|
|
JR Z,SYS_GETMEMINFO
|
|
CP BF_SYSGET_BNKINFO
|
|
JR Z,SYS_GETBNKINFO
|
|
OR $FF ; SIGNAL ERROR
|
|
RET
|
|
;
|
|
; GET TIMER
|
|
; RETURNS:
|
|
; DE:HL: TIMER VALUE (32 BIT)
|
|
;
|
|
SYS_GETTIMER:
|
|
LD HL,HB_TICKS
|
|
HB_DI
|
|
CALL LD32
|
|
HB_EI
|
|
XOR A
|
|
RET
|
|
;
|
|
; GET BOOT INFORMATION
|
|
; RETURNS:
|
|
; L: BOOT BANK ID
|
|
; 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 H,0 ; NOT YET DEFINED
|
|
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 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 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
|
|
;
|
|
; 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_BOOTINFO
|
|
JR Z,SYS_SETBOOTINFO
|
|
OR $FF ; SIGNAL ERROR
|
|
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
|
|
;
|
|
; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK
|
|
; ENTRY: D=BANK ID, HL=ADDRESS
|
|
; RETURN: E=BYTE VALUE
|
|
;
|
|
SYS_PEEK:
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HBX_PEEK ; IMPLEMENTED IN PROXY
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#ENDIF
|
|
XOR A
|
|
RET
|
|
;
|
|
; WRITE A BYTE OF MEMORY TO SPECIFIED BANK
|
|
; ENTRY: D=BANK ID, HL=ADDRESS IN HBIOS BANK, E=BYTE VALUE
|
|
;
|
|
SYS_POKE:
|
|
#IF (INTMODE == 1)
|
|
DI
|
|
#ENDIF
|
|
CALL HBX_POKE ; IMPLEMENTED IN PROXY
|
|
#IF (INTMODE == 1)
|
|
EI
|
|
#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
|
|
OR $FF ; SIGNAL ERROR
|
|
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 PANIC ; INVALID FOR INT MODE 0
|
|
OR $FF
|
|
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 PANIC ; ELSE ERROR
|
|
OR $FF
|
|
RET
|
|
SYS_INTGET1:
|
|
OR A
|
|
RLA ; HL := (A * 2) FOR IM2
|
|
#IF (INTMODE == 1)
|
|
RLA ; ... HL := (A * 4) + 1 FOR IM1
|
|
INC A
|
|
#ENDIF
|
|
LD H,0
|
|
LD L,A
|
|
#IF (INTMODE == 1)
|
|
LD DE,HB_IM1INT ; DE := START OF CALL LIST
|
|
#ENDIF
|
|
#IF (INTMODE == 2)
|
|
LD DE,HBX_IVT ; DE := START OF VECTOR TABLE
|
|
#ENDIF
|
|
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
|
|
#IF (INTMODE == 2)
|
|
LD DE,HBX_INT ; DE := IM2 INT ROUTING ENGINE
|
|
#ENDIF
|
|
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)
|
|
;
|
|
; 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.
|
|
;
|
|
HB_IM1INT: ; IM1 DEVICE INTERRUPT HANDLER CALL LIST
|
|
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
|
|
;
|
|
; 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_IM1INT ; POINTER FOR NEXT IM1 ENTRY
|
|
;
|
|
#ENDIF
|
|
;
|
|
; TIMER INTERRUPT
|
|
;
|
|
HB_TIMINT:
|
|
; INCREMENT TICK COUNTER (32 BIT)
|
|
LD HL,HB_TICKS ; POINT TO TICK COUNTER
|
|
INC (HL)
|
|
JR NZ,HB_TIMINT1
|
|
INC HL
|
|
INC (HL)
|
|
JR NZ,HB_TIMINT1
|
|
INC HL
|
|
INC (HL)
|
|
JR NZ,HB_TIMINT1
|
|
INC HL
|
|
INC (HL)
|
|
;
|
|
HB_TIMINT1:
|
|
;
|
|
#IF 0
|
|
;
|
|
LD HL,TEMPCNT
|
|
DEC (HL)
|
|
JR NZ,HB_TIMINT2
|
|
LD (HL),250
|
|
;
|
|
LD A,'*'
|
|
CALL COUT
|
|
JR HB_TIMINT2
|
|
;
|
|
TEMPCNT .DB 250
|
|
;
|
|
#ENDIF
|
|
;
|
|
HB_TIMINT2:
|
|
;
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
; ACK/RESET Z180 TIMER INTERRUPT
|
|
IN0 A,(Z180_TCR)
|
|
IN0 A,(Z180_TMDR0L)
|
|
#ENDIF
|
|
;
|
|
OR $FF ; NZ SET TO INDICATE INT HANDLED
|
|
RET
|
|
;
|
|
; BAD INTERRUPT HANDLER
|
|
;
|
|
HB_BADINT:
|
|
|
|
#IF 0 ; *DEBUG*
|
|
LD HL,HB_BADINTCNT
|
|
INC (HL)
|
|
LD A,(HL)
|
|
OUT (DIAGP),A
|
|
OR $FF
|
|
RET
|
|
HB_BADINTCNT .DB 0
|
|
#ENDIF ; *DEBUG*
|
|
|
|
CALL NEWLINE2
|
|
PRTS("+++ BAD INT: $")
|
|
CALL _REGDMP
|
|
;CALL CONTINUE
|
|
OR $FF ; SIGNAL INTERRUPT HANDLED
|
|
RET
|
|
;
|
|
; COMMON API FUNCTION DISPATCH CODE
|
|
;
|
|
; ON ENTRY C IS UNIT # (INDEX INTO XXX_TBL OF UNITS)
|
|
; AND IY POINTS TO START OF UNIT TABLE.
|
|
; USE UNIT # IN C TO LOOKUP XXX_TBL ENTRY. THE XXX_TBL
|
|
; ENTRY CONTAINS THE START OF THE DRIVER FUNCTION TABLE AND
|
|
; THE DEVICE SPECIFIC INSTANCE DATA (BLOB). SET IY TO BLOB ADDRESS
|
|
; AND CALL THE SPECIFIC FUNCTION REQUESTED IN THE DRIVER.
|
|
;
|
|
HB_DISPCALL:
|
|
; CHECK INCOMING UNIT INDEX IN C FOR VAILIDITY
|
|
LD A,C ; A := INCOMING DISK UNIT INDEX
|
|
CP (IY-1) ; COMPARE TO COUNT
|
|
JR NC,HB_DISPERR ; HANDLE INVALID UNIT INDEX
|
|
|
|
; CHECK FUNCTION INDEX FOR VALIDITY
|
|
LD A,B ; A := INCOMING FUNCTION NUMBER
|
|
AND $0F ; LOW NIBBLE ONLY FOR FUNC INDEX
|
|
CP (IY-3) ; CHECK FN NUM AGAINST MAX
|
|
JR NC,HB_DISPERR ; HANDLE FN NUM OUT OF RANGE ERROR
|
|
|
|
; BUMP IY TO ACTUAL XXX_TBL ENTRY FOR INCOMING UNIT INDEX
|
|
LD B,0 ; MSB IS ALWAYS ZERO
|
|
RLC C ; MULTIPLY UNIT INDEX
|
|
RLC C ; ... BY 4 FOR TABLE ENTRY OFFSET
|
|
ADD IY,BC ; SET IY TO ENTRY ADDRESS
|
|
|
|
; DERIVE DRIVER FUNC ADR TO CALL
|
|
PUSH HL ; SAVE INCOMING HL
|
|
LD L,(IY+0) ; COPY DRIVER FUNC TABLE
|
|
LD H,(IY+1) ; ... START TO HL
|
|
RLCA ; CONV UNIT (STILL IN A) TO FN ADR OFFSET
|
|
CALL ADDHLA ; HL NOW HAS DRIVER FUNC TBL START ADR
|
|
LD A,(HL) ; DEREFERENCE HL
|
|
INC HL ; ... TO GET
|
|
LD H,(HL) ; ... ACTUAL
|
|
LD L,A ; ... TARGET FUNCTION ADDRESS
|
|
EX (SP),HL ; RESTORE HL, FUNC ADR ON STACK
|
|
|
|
; GET UNIT INSTANCE DATA BLOB ADDRESS TO IY
|
|
PUSH HL ; SAVE INCOMING HL
|
|
LD L,(IY+2) ; HL := DATA BLOB ADDRESS
|
|
LD H,(IY+3) ; ...
|
|
EX (SP),HL ; RESTORE HL, BLOB ADR ON TOS
|
|
POP IY ; IY := BLOB ADR
|
|
|
|
RET ; JUMP TO DRIVER FUNC ADR ON TOS
|
|
;
|
|
HB_DISPERR:
|
|
CALL PANIC ; PANIC
|
|
OR $FF ; SIGNAL ERROR
|
|
RET ; AND RETURN VIA DISPEXIT
|
|
;
|
|
; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL
|
|
; 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
|
|
OR $FF ; SIGNAL ERROR
|
|
RET ; AND RETURN
|
|
;
|
|
HB_TMPSZ .DW 0
|
|
HB_TMPREF .DW 0
|
|
;
|
|
;==================================================================================================
|
|
; DEVICE DRIVERS
|
|
;==================================================================================================
|
|
;
|
|
#IF (SIMRTCENABLE)
|
|
ORG_SIMRTC .EQU $
|
|
#INCLUDE "simrtc.asm"
|
|
SIZ_SIMRTC .EQU $ - ORG_SIMRTC
|
|
.ECHO "SIMRTC occupies "
|
|
.ECHO SIZ_SIMRTC
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (DSRTCENABLE)
|
|
ORG_DSRTC .EQU $
|
|
#INCLUDE "dsrtc.asm"
|
|
SIZ_DSRTC .EQU $ - ORG_DSRTC
|
|
.ECHO "DSRTC occupies "
|
|
.ECHO SIZ_DSRTC
|
|
.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 (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
|
|
;
|
|
#IF (CVDUENABLE | VGAENABLE)
|
|
ORG_FONTHI .EQU $
|
|
#INCLUDE "font_hi.asm"
|
|
SIZ_FONTHI .EQU $ - ORG_FONTHI
|
|
.ECHO "FONTHI occupies "
|
|
.ECHO SIZ_FONTHI
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (TMSENABLE)
|
|
ORG_FONTTMS .EQU $
|
|
#INCLUDE "font_tms.asm"
|
|
SIZ_FONTTMS .EQU $ - ORG_FONTTMS
|
|
.ECHO "FONTTMS occupies "
|
|
.ECHO SIZ_FONTTMS
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#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)
|
|
ORG_SPK .EQU $
|
|
#INCLUDE "spk.asm"
|
|
SIZ_SPK .EQU $ - ORG_SPK
|
|
.ECHO "SPK occupies "
|
|
.ECHO SIZ_SPK
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#IF (AYENABLE)
|
|
ORG_AY .EQU $
|
|
#INCLUDE "ay.asm"
|
|
SIZ_AY .EQU $ - ORG_AY
|
|
.ECHO "AY occupies "
|
|
.ECHO SIZ_AY
|
|
.ECHO " bytes.\n"
|
|
#ENDIF
|
|
;
|
|
#DEFINE USEDELAY
|
|
#INCLUDE "util.asm"
|
|
#INCLUDE "time.asm"
|
|
#INCLUDE "bcd.asm"
|
|
#INCLUDE "decode.asm"
|
|
;#INCLUDE "xio.asm"
|
|
;
|
|
#IF (DSKYENABLE)
|
|
#DEFINE DSKY_KBD
|
|
#INCLUDE "dsky.asm"
|
|
#ENDIF
|
|
;
|
|
; DETECT CPU SPEED USING DS-1302 RTC
|
|
;
|
|
HB_CPUSPD:
|
|
;
|
|
#IF (DSRTCENABLE)
|
|
;
|
|
CALL DSRTC_TSTCLK ; IS CLOCK RUNNING?
|
|
JR Z,HB_CPUSPD1 ; YES, CONTINUE
|
|
; MAKE SURE CLOCK IS RUNNING
|
|
LD HL,DSRTC_TIMDEF
|
|
CALL DSRTC_TIM2CLK
|
|
LD HL,DSRTC_BUF
|
|
CALL DSRTC_WRCLK
|
|
CALL DSRTC_TSTCLK ; NOW IS CLOCK RUNNING?
|
|
RET NZ
|
|
;
|
|
HB_CPUSPD1:
|
|
; LD B,8
|
|
;HB_CPUSPDX:
|
|
; PUSH BC
|
|
|
|
; 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
|
|
|
|
; PUSH DE
|
|
; POP BC
|
|
; CALL NEWLINE
|
|
; CALL PRTHEXWORD
|
|
|
|
; POP BC
|
|
; DJNZ HB_CPUSPDX
|
|
;
|
|
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
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
SLA L
|
|
RL H
|
|
#ENDIF
|
|
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 ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2) | (PLATFORM == PLT_RC) | (PLATFORM == PLT_EZZ80))
|
|
; LOOP TARGET IS 4000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4
|
|
CALL DLY32
|
|
CALL DLY8
|
|
CALL DLY2
|
|
JP $ + 3 ; 10 TSTATES
|
|
JP $ + 3 ; 10 TSTATES
|
|
JP $ + 3 ; 10 TSTATES
|
|
JP $ + 3 ; 10 TSTATES
|
|
;LD A,R ; 9 TSTATES
|
|
INC BC ; 6 TSTATES
|
|
;LD A,(BC) ; 7 TSTATES
|
|
;NOP ; 4 TSTATES
|
|
NOP ; 4 TSTATES
|
|
#ENDIF
|
|
|
|
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4) | (PLATFORM == PLT_RC180))
|
|
; LOOP TARGET IS 8000 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 8
|
|
;CALL DLY64
|
|
CALL DLY32
|
|
CALL DLY16
|
|
CALL DLY8
|
|
CALL DLY4
|
|
CALL DLY2
|
|
CALL DLY1 ; CALL (25TS) & RET (18TS) = 43TS
|
|
OR A ; 7 TSTATES
|
|
OR A ; 7 TSTATES
|
|
;OR A ; 7 TSTATES
|
|
;OR A ; 7 TSTATES
|
|
NOP ; 6 TSTATES
|
|
;NOP ; 6 TSTATES
|
|
;NOP ; 6 TSTATES
|
|
;NOP ; 6 TSTATES
|
|
;NOP ; 6 TSTATES
|
|
#ENDIF
|
|
;
|
|
PUSH DE
|
|
CALL HB_RDSEC ; GET SECONDS
|
|
POP DE
|
|
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 HL
|
|
OR E ; ... FOR OVERFLOW
|
|
RET Z ; TIMEOUT, SOMETHING IS WRONG
|
|
JR HB_WAITSEC1 ; LOOP
|
|
;
|
|
HB_RDSEC:
|
|
; READ SECONDS BYTE INTO A
|
|
LD C,$81 ; SECONDS REGISTER
|
|
CALL DSRTC_CMD ; SEND THE COMMAND
|
|
CALL DSRTC_GET ; READ THE REGISTER
|
|
CALL DSRTC_END ; FINISH IT
|
|
RET
|
|
;
|
|
#ELSE
|
|
;
|
|
RET ; NO RTC, ABORT
|
|
;
|
|
#ENDIF
|
|
;
|
|
; 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
|
|
;
|
|
; PRINT DISK DEVICES
|
|
LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET
|
|
LD C,BF_SYSGET_DIOCNT ; SUBFUNC: DISK UNIT COUNT
|
|
RST 08 ; E := DISK UNIT COUNT
|
|
LD B,E ; MOVE TO B FOR LOOP COUNT
|
|
LD A,E ; MOVE TO ACCUM
|
|
OR A ; SET FLAGS
|
|
JR Z,PRTSUM1A ; IF NONE, BYPASS
|
|
LD C,0 ; C WILL BE UNIT INDEX
|
|
PRTSUM1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL PS_DISK ; PRINT DISK INFO
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; BUMP DISK UNIT INDEX
|
|
DJNZ PRTSUM1 ; LOOP THRU ALL DISK DEVICES
|
|
;
|
|
PRTSUM1A:
|
|
; PRINT SERIAL DEVICES
|
|
LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET
|
|
LD C,BF_SYSGET_CIOCNT ; SUBFUNC: SERIAL UNIT COUNT
|
|
RST 08 ; E := SERIAL UNIT COUNT
|
|
LD B,E ; MOVE TO B FOR LOOP COUNT
|
|
LD A,E ; MOVE TO ACCUM
|
|
OR A ; SET FLAGS
|
|
JR Z,PRTSUM2A ; IF NONE, BYPASS
|
|
LD C,0 ; C WILL BE UNIT INDEX
|
|
PRTSUM2:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL PS_SERIAL ; PRINT SERIAL INFO
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; BUMP SERIAL UNIT INDEX
|
|
DJNZ PRTSUM2 ; LOOP THRU ALL SERIAL DEVICES
|
|
;
|
|
PRTSUM2A:
|
|
; PRINT VIDEO DEVICES
|
|
LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET
|
|
LD C,BF_SYSGET_VDACNT ; SUBFUNC: VIDEO UNIT COUNT
|
|
RST 08 ; E := SERIAL UNIT COUNT
|
|
LD B,E ; MOVE TO B FOR LOOP COUNT
|
|
LD A,E ; MOVE TO ACCUM
|
|
OR A ; SET FLAGS
|
|
JR Z,PRTSUM3A ; IF NONE, BYPASS
|
|
LD C,0 ; C WILL BE UNIT INDEX
|
|
PRTSUM3:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL PS_VIDEO ; PRINT VIDEO INFO
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; BUMP VIDEO UNIT INDEX
|
|
DJNZ PRTSUM3 ; LOOP THRU ALL VIDEO DEVICES
|
|
;
|
|
PRTSUM3A:
|
|
RET ; DONE
|
|
;
|
|
; 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, ASSUME SINGLE DIGIT
|
|
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
|
|
; PRINT FLOPPY TYPE
|
|
LD A,C ; ATTRIBUTE TO ACCUM
|
|
RLCA ; ISOLATE FORM FACTOR BITS
|
|
RLCA
|
|
RLCA
|
|
AND $03
|
|
LD DE,PS_FLP8 ; ASSUME 8"
|
|
CP 0
|
|
JR Z,PS_PRTDC2A
|
|
LD DE,PS_FLP5 ; ASSUME 5.25"
|
|
CP 1
|
|
JR Z,PS_PRTDC2A
|
|
LD DE,PS_FLP3 ; ASSUME 3.5"
|
|
CP 2
|
|
JR Z,PS_PRTDC2A
|
|
LD DE,PS_FLPN ; ASSUME OTHER"
|
|
PS_PRTDC2A:
|
|
CALL WRITESTR
|
|
; PRINT FLOPPY SIDES
|
|
LD A,C ; ATTRIBUTE TO ACCUM
|
|
LD DE,PS_FLPSS ; ASSUME SINGLE SIDED
|
|
BIT 4,A ; DS?
|
|
JR Z,PS_PRTDC2B
|
|
LD DE,PS_FLPDS ; DOUBLE SIDED
|
|
PS_PRTDC2B:
|
|
CALL WRITESTR
|
|
; PRINT FLOPPY DENSITY
|
|
LD A,C ; ATTRIBUTE TO ACCUM
|
|
RRCA ; ISOLATE DENSITY BITS
|
|
RRCA
|
|
AND $03
|
|
LD DE,PS_FLPSD ; SINGLE DENSITY
|
|
CP 0
|
|
JR Z,PS_PRTDC2C
|
|
LD DE,PS_FLPDD ; DOUBLE DENSITY
|
|
CP 1
|
|
JR Z,PS_PRTDC2C
|
|
LD DE,PS_FLPHD ; HIGH DENSITY
|
|
CP 2
|
|
JR Z,PS_PRTDC2C
|
|
LD DE,PS_FLPED ; EXTENDED DENSITY
|
|
CP 3
|
|
JR Z,PS_PRTDC2C
|
|
PS_PRTDC2C:
|
|
CALL WRITESTR
|
|
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("Serial $")
|
|
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 SERIAL TYPE (SERIAL ATTRIBUTE IN E)
|
|
;
|
|
PS_PRTST:
|
|
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 7,C ; 0=RS-232, 1=TERMINAL
|
|
JR 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
|
|
;
|
|
PS_PRTSC1:
|
|
; PRINT TERMINAL CONFIG
|
|
LD A,C ; GET ATTRIBUTE VALUE
|
|
CP $FF ; 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 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
|
|
;
|
|
;
|
|
;
|
|
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_FLP8 .TEXT "8\",$"
|
|
PS_FLP5 .TEXT "5.25\",$"
|
|
PS_FLP3 .TEXT "3.5\",$"
|
|
PS_FLPN .TEXT "???\",$"
|
|
;
|
|
PS_FLPSS .TEXT "SS/$"
|
|
PS_FLPDS .TEXT "DS/$"
|
|
;
|
|
PS_FLPSD .TEXT "SD$"
|
|
PS_FLPDD .TEXT "DD$"
|
|
PS_FLPHD .TEXT "HD$"
|
|
PS_FLPED .TEXT "ED$"
|
|
;
|
|
; SERIAL DEVICE STRINGS
|
|
;
|
|
PS_SDSTRREF:
|
|
.DW PS_SDUART, PS_SDASCI, PS_SDTERM,
|
|
.DW PS_SDPRPCON, PS_SDPPPCON, PS_SDSIO, PS_SDACIA
|
|
;
|
|
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$"
|
|
;
|
|
; SERIAL TYPE STRINGS
|
|
;
|
|
PS_STRS232 .TEXT "RS-232$"
|
|
PS_STTERM .TEXT "Terminal$"
|
|
;
|
|
PS_STPARMAP .DB "NONENMNS"
|
|
|
|
;
|
|
; SERIAL TYPE STRINGS
|
|
;
|
|
;
|
|
; 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$"
|
|
;
|
|
; VIDEO CONFIG STRINGS
|
|
;
|
|
;
|
|
;
|
|
; 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, USE XIO
|
|
;
|
|
; 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:
|
|
;; USE XIO
|
|
;LD A,E ; GET OUTPUT CHAR BACK TO ACCUM
|
|
;CALL XIO_OUTC ; OUTPUT VIA XIO
|
|
;
|
|
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, USE XIO
|
|
;
|
|
; 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:
|
|
;; USE XIO
|
|
;CALL XIO_INC ; GET CHAR
|
|
;
|
|
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 ; IF NOT READY, USE XIO
|
|
;
|
|
; 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:
|
|
;; USE XIO
|
|
;CALL XIO_IST ; GET STATUS
|
|
;
|
|
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
|
|
;
|
|
STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$"
|
|
STR_PLATFORM .DB PLATFORM_NAME, "$"
|
|
STR_SWITCH .DB "*** Activating CRT Console ***$"
|
|
STR_BADINT .DB "\r\n*** BAD INT ***\r\n$"
|
|
;
|
|
#IF (DSKYENABLE)
|
|
MSG_HBVER .DB $BE,$FF,$8A,$FB,$D7,$6D,$77,$B0 ; "HBIOS291"
|
|
#ENDIF
|
|
;
|
|
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
|
|
|