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.
2543 lines
63 KiB
2543 lines
63 KiB
;
|
|
;==================================================================================================
|
|
; HDIAG
|
|
;==================================================================================================
|
|
;
|
|
; THIS FILE CONTAINS A FRAMEWORK FOR A DIAGNOTIC ENVIRONMENT. IT IS ESSENTIALLY A STRIPPED DOWN
|
|
; VERSION OF HBIOS. IT DOES NO BANK SWITCHING, BUT THE INTERRUPT MANAGEMENT FRAMEWORK IS
|
|
; RETAINED. UPON STARTUP, IT RELOCATES TO UPPER (COMMON) RAM AS QUICKLY AS POSSIBLE.
|
|
;
|
|
; THERE IS NO HBIOS API. MINIMAL SERIAL PORT ACCESS IS PROVIDED BY INCLUDING THE PLATFORM
|
|
; APPROPRIATE MIN_XXX.ASM SERIAL DRIVER. SERIAL PORT SPEEDS ARE FIXED AND THERE IS NO
|
|
; FLOW CONTROL. NONE OF THE TYPICAL DRIVER MODULES (CHARACTER, DISK, VIDEO, ETC.) ARE INCLUDED
|
|
; AND THERE IS NO DISPATCHING MECHANISM.
|
|
;
|
|
; IN ORDER TO BUILD PLATFORM APPROPRIATE VERSIONS, THE FULL HBIOS INCLUDE FILE STRUCTURE
|
|
; IS USED SO THAT ALL OF THE HBIOS CONFIG SETTINGS CAN BE USED.
|
|
;
|
|
; THIS FILE CAN BE COMPILED TO BOOT IN ONE OF 2 MODES (ROM OR APPLICATION) 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.
|
|
;
|
|
; - 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.
|
|
;
|
|
; INCLUDE FILE NESTING:
|
|
;
|
|
; hdiag.asm
|
|
; - std.asm
|
|
; - ver.inc
|
|
; - hbios.inc
|
|
; - build.inc
|
|
; - config/<plt>_<cfg>.asm
|
|
; - cfg_<plt>.asm
|
|
; - util.asm
|
|
; - min_[uart|asci|sio|acia].asm
|
|
; - dsky.asm ???
|
|
; - diagnostic modules...
|
|
;
|
|
; INCLUDE GENERIC STUFF
|
|
;
|
|
#INCLUDE "std.asm"
|
|
;
|
|
#DEFINE HDIAG
|
|
;
|
|
; MAKE SURE EXACTLY ONE OF ROMBOOT, APPBOOT IS DEFINED.
|
|
;
|
|
MODCNT .EQU 0
|
|
#IFDEF ROMBOOT
|
|
MODCNT .SET MODCNT + 1
|
|
#ENDIF
|
|
#IFDEF APPBOOT
|
|
MODCNT .SET MODCNT + 1
|
|
#ENDIF
|
|
#IF (MODCNT != 1)
|
|
.ECHO "*** ERROR: PLEASE DEFINE ONE AND ONLY ONE OF ROMBOOT, APPBOOT!!!\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)
|
|
#IF (LEDMODE == LEDMODE_STD)
|
|
#DEFINE LED(N) PUSH AF
|
|
#DEFCONT \ LD A,~N
|
|
#DEFCONT \ OUT (LEDPORT),A
|
|
#DEFCONT \ POP AF
|
|
#ENDIF
|
|
#IF (LEDMODE == LEDMODE_RTC)
|
|
#DEFINE LED(N) PUSH AF
|
|
#DEFCONT \ LD A,(HB_RTCVAL)
|
|
#DEFCONT \ AND %11111100
|
|
#DEFCONT \ OR (N & %00000011)
|
|
#DEFCONT \ LD (HB_RTCVAL),A
|
|
#DEFCONT \ OUT (LEDPORT),A
|
|
#DEFCONT \ POP AF
|
|
#ENDIF
|
|
#ELSE
|
|
#DEFINE LED(N) \;
|
|
#ENDIF
|
|
;
|
|
;
|
|
;
|
|
#IF (INTMODE == 0)
|
|
; NO INTERRUPT HANDLING
|
|
#DEFINE HB_DI ;
|
|
#DEFINE HB_EI ;
|
|
#ELSE
|
|
#IF (CPUFAM == CPU_Z280)
|
|
#IF (INTMODE == 3)
|
|
; Z280 MODE 3 INTERRUPT HANDLING (INTA, C/T 0, & UART RCVR ENABLED)
|
|
#DEFINE HB_DI DI
|
|
#DEFINE HB_EI .DB $ED,$7F,$0B
|
|
#ELSE
|
|
; Z280 MODE 1/2 INTERRUPT HANDLING
|
|
#DEFINE HB_DI DI
|
|
#DEFINE HB_EI EI
|
|
#ENDIF
|
|
#ELSE
|
|
#DEFINE HB_DI DI
|
|
#DEFINE HB_EI EI
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE > 3)
|
|
.ECHO "*** ERROR: INVALID INTMODE SETTING!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
#IF (INTMODE == 3)
|
|
#IF (CPUFAM != CPU_Z280)
|
|
.ECHO "*** ERROR: INTMODE 3 REQUIRES Z280 FAMILY CPU!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
#IF (MEMMGR != MM_Z280)
|
|
.ECHO "*** ERROR: INTMODE 3 REQUIRES Z280 MEMORY MANAGER!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
#IF (INTMODE != 3)
|
|
.ECHO "*** ERROR: Z280 MEMORY MANAGER REQUIRES INTMODE 3!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
#IF (CPUFAM != CPU_Z280)
|
|
.ECHO "*** ERROR: Z280 MEMORY MANAGER REQUIRES Z280 FAMILY CPU!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
#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
|
|
;
|
|
#IF (PLATFORM == PLT_SCZ180)
|
|
RTCDEF .SET RTCDEF | %00000001 ; SC128 I2C SCL BIT
|
|
#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
|
|
RET
|
|
.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
|
|
RET ; 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
|
|
;
|
|
;
|
|
;
|
|
.ORG $100
|
|
JP HB_START
|
|
;
|
|
;==================================================================================================
|
|
; 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
|
|
HBX_IMG .SET $
|
|
.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.
|
|
;;;;
|
|
;;;; WARNING: HBX_INVOKE IS *NOT* REENTRANT!
|
|
;;;;
|
|
;;;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
|
|
;;;;
|
|
;;;#IF (MEMMGR == MM_Z280)
|
|
;;;;
|
|
;;; LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
;;; LD (HB_INVBNK),A ; SAVE INVOCATION BANK
|
|
;;;;
|
|
;;; LD A,BID_BIOS ; HBIOS BANK
|
|
;;; LD (HB_CURBNK),A ; SET AS CURRENT BANK
|
|
;;;;
|
|
;;; .DB $ED,$71 ; SC
|
|
;;; .DW HB_DISPATCH ; SC PARAMETER
|
|
;;;;
|
|
;;; PUSH AF
|
|
;;; LD A,(HB_INVBNK)
|
|
;;; LD (HB_CURBNK),A
|
|
;;; POP AF
|
|
;;;;
|
|
;;;#ELSE
|
|
;;;;
|
|
;;; 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
|
|
;;;;
|
|
;;;#ENDIF
|
|
;;;;
|
|
;;;#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
|
|
#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)
|
|
PUSH BC ; SAVE BC
|
|
PUSH HL ; SAVE HL
|
|
LD B,$00 ; FIRST USER PDR
|
|
.DB $ED,$71 ; SC
|
|
.DW Z280_BNKSEL ; SC PARAMETER
|
|
POP HL ; RESTORE HL
|
|
POP BC ; RESTORE BC
|
|
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
|
|
;
|
|
#IF (MEMMGR == MM_MBC)
|
|
;
|
|
#IF (INTMODE == 1)
|
|
LD (HBX_MMA),A ; SAVE ACCUM
|
|
LD A,I ; GET INT CTL REG
|
|
HB_DI ; DISABLE INTS
|
|
PUSH AF ; SAVE INT CTL REG
|
|
LD A,(HBX_MMA) ; RESTORE ACCUM
|
|
#ENDIF
|
|
;
|
|
OR A ; SET FLAGS
|
|
JP P,HBX_ROM ; BIT 7 INDICATES RAM
|
|
OUT (MPCL_ROM),A ; ENSURE ROM PAGE OUT OF MEMORY BEFORE SWITCH
|
|
|
|
#IF (RAMSIZE == 256)
|
|
XOR %00000100 ; TOP 32K IS ALWAYS IN FIRST CHIP
|
|
#ENDIF
|
|
|
|
#IF (RAMSIZE == 1024)
|
|
XOR %00010000 ; TOP 32K IS ALWAYS IN FIRST CHIP
|
|
#ENDIF
|
|
|
|
OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR
|
|
JR HBX_RAMX
|
|
HBX_ROM:
|
|
OUT (MPCL_RAM),A ; ENSURE RAM PAGE OUT OF MEMORY BEFORE SWITCH
|
|
OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR
|
|
|
|
HBX_RAMX:
|
|
;
|
|
#IF (INTMODE == 1)
|
|
POP AF ; RESTORE INT CTL REG
|
|
JP PO,$+4 ; WERE INTS DISABLED AT ENTRY?
|
|
EI ; *** DO NOT USE HB_EI HERE ***
|
|
LD A,(HBX_MMA) ; RESTORE INCOMING ACCUM
|
|
#ENDIF
|
|
;
|
|
RET
|
|
;
|
|
HBX_MMA .DB 0 ; TEMPORARY STORAGE FOR REG A
|
|
#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 (MEMMGR == MM_Z280)
|
|
.DB $ED,$71 ; SC
|
|
.DW Z280_BNKCPY ; SC PARAMETER
|
|
RET
|
|
#ELSE
|
|
#IF (CPUFAM == CPU_Z280)
|
|
PUSH HL
|
|
PUSH BC
|
|
LD C,Z280_MSR
|
|
LDCTL HL,(C)
|
|
POP BC
|
|
EX (SP),HL
|
|
HB_DI
|
|
#ELSE
|
|
LD A,I
|
|
HB_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)
|
|
EX (SP),HL ; SAVE HL, RECOVER MSR
|
|
PUSH BC ; SAVE BC
|
|
LD C,Z280_MSR
|
|
LDCTL (C),HL
|
|
POP BC ; RECOVER BC
|
|
POP HL ; RECOVER HL
|
|
#ELSE
|
|
POP AF
|
|
JP PO,$+4
|
|
EI ; *** DO NOT USE HB_EI HERE ***
|
|
#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
|
|
#ENDIF
|
|
;
|
|
; 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:
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
CP BID_BIOS ; CALLING HBIOS?
|
|
JR NZ,HBX_BNKCALL3 ; NOPE, DO NORMAL PROCESSING
|
|
.DB $ED,$71 ; SC
|
|
.DW HBX_BNKCALL2 ; CALL HERE IN SYSTEM MODE
|
|
RET ; THEN RETURN
|
|
;
|
|
HBX_BNKCALL2:
|
|
HB_EI ; INTS ARE OK
|
|
LD (HBX_BNKCALL_GO+1),IX ; SETUP DEST ADR
|
|
PCACHE ; CRITICAL!!!
|
|
HBX_BNKCALL_GO:
|
|
JP $FFFF ; DO THE REAL WORK AND RETURN
|
|
#ENDIF
|
|
;
|
|
HBX_BNKCALL3:
|
|
LD (HBX_BNKCALL_BNK+1),A ; STUFF TARGET BANK TO CALL INTO CODE BELOW
|
|
LD (HBX_BNKCALL_ADR+1),IX ; STUFF ADDRESS TO CALL INTO CODE BELOW
|
|
LD A,(HB_CURBNK) ; GET CURRENT BANK
|
|
PUSH AF ; SAVE FOR RETURN
|
|
HBX_BNKCALL_BNK:
|
|
LD A,$FF ; LOAD BANK TO CALL ($FF OVERLAID AT ENTRY)
|
|
CALL HBX_BNKSEL ; ACTIVATE THE NEW BANK
|
|
HBX_BNKCALL_ADR:
|
|
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
|
|
#IF (MEMMGR == MM_Z280)
|
|
LD A,(HB_INVBNK) ; SPECIAL CASE FOR Z280 MEM MGR
|
|
#ENDIF
|
|
CALL HBX_BNKSEL
|
|
LD SP,0 ; RESTORE ORIGINAL STACK FRAME
|
|
HBX_PPSP .EQU $ - 2
|
|
RET
|
|
;
|
|
; SPECIAL ROUTINE IN HIGH MEMORY TO PERFORM A COLD START ON Z280
|
|
; THIS REQUIRES US TO REMAP LOW MEMORY, THEN JUMP TO ZERO
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
Z280_RESTART:
|
|
DI ; KILL INTERRUPTS
|
|
LD SP,HBX_LOC ; STACK IN HIGH MEMORY
|
|
;
|
|
; COPY Z280 BANK SELECT ROUTINE TO HIGH MEMORY
|
|
LD HL,Z280_BNKSEL
|
|
LD DE,$8000
|
|
LD BC,Z280_BNKSEL_LEN
|
|
LDIR
|
|
;
|
|
; MAKE ROM BOOT BANK ACTIVE IN LOW SYS MEM
|
|
LD A,BID_BOOT
|
|
LD B,$10 ; FIRST SYS PDR
|
|
CALL $8000 ; DO IT
|
|
;
|
|
; NOW JUST JUMP TO START OF ROM BOOT CODE
|
|
JP 0
|
|
#ENDIF
|
|
;
|
|
; 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)
|
|
#IF (HBX_INTSTKSIZ < 22)
|
|
.ECHO "*** ERROR: INTERRUPT STACK IS TOO SMALL!!!\n"
|
|
!!! ; FORCE AN ASSEMBLY ERROR
|
|
#ENDIF
|
|
;
|
|
#IF ((INTMODE == 2) | (INTMODE == 3))
|
|
;
|
|
; HBIOS INTERRUPT SLOT ASSIGNMENTS
|
|
;
|
|
; # Z80 Z180
|
|
; --- -------------- --------------
|
|
; 0 CTC0A INT1 -+
|
|
; 1 CTC0B INT2 |
|
|
; 2 CTC0C TIM0 |
|
|
; 3 CTC0D TIM1 |
|
|
; 4 UART0 DMA0 +- Z180 INTERNAL
|
|
; 5 UART1 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)
|
|
;
|
|
HBX_INT: ; COMMON INTERRUPT ROUTING CODE
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
; THIS CODE ASSUMES Z280 IM 3. IM 1 AND IM 2 ON Z280
|
|
; DO NOT SAVE MSR AT INTERRUPT MAKING IT VIRTUALLY IMPOSSIBLE
|
|
; TO RETURN FROM THE INTERRUPT TO THE CORRECT MODE (SYSTEM
|
|
; OR USER). THIS IS BECAUSE THERE IS NO WAY TO KNOW WHETHER
|
|
; SYSTEM OR USER MODE WAS ACTIVE AT THE TIME OF THE INTERRUPT.
|
|
;
|
|
EX (SP),HL ; SAVE HL AND GET INT JP TABLE OFFSET
|
|
|
|
; 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
|
|
;
|
|
; HANDLE INT VIA JP TABLE IN HBIOS
|
|
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
|
|
;
|
|
; RESTORE STATE
|
|
POP IY ; RESTORE IY
|
|
POP DE ; RESTORE DE
|
|
POP BC ; RESTORE BC
|
|
POP AF ; RESTORE AF
|
|
POP HL ; RESTORE HL
|
|
;
|
|
; BURN THE REASON CODE
|
|
EX (SP),HL ; HL TO STK, RC TO HL
|
|
POP HL ; RESTORE HL
|
|
;
|
|
CALL HBX_RETI ; RETI FOR Z80 PERIPHERALS
|
|
RETIL
|
|
;
|
|
HBX_RETI:
|
|
RETI
|
|
;
|
|
#ELSE
|
|
;
|
|
; COMMON INTERRUPT DISPATCHING CODE
|
|
; SETUP AND CALL HANDLER IN BIOS BANK
|
|
;
|
|
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
|
|
|
|
#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 4,0 ; FILLER, RESERVED FOR FUTURE HBIOS USE
|
|
.DB RTCDEF ; SHADOW VALUE FOR RTC LATCH PORT
|
|
.DB $FE ; HB_LOCK: HBIOS MUTEX LOCK
|
|
JP 0 ; 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
|
|
;
|
|
;==================================================================================================
|
|
; HDIAG CORE
|
|
;==================================================================================================
|
|
;
|
|
;==================================================================================================
|
|
; SYSTEM INITIALIZATION
|
|
;==================================================================================================
|
|
;
|
|
HB_START:
|
|
#IFDEF APPBOOT
|
|
#IF (MEMMGR == MM_Z280)
|
|
LD A,%00000001
|
|
OUT (DIAGPORT),A
|
|
LD DE,Z280_BOOTERR
|
|
LD C,9
|
|
LD A,%00000010
|
|
OUT (DIAGPORT),A
|
|
CALL $0005
|
|
LD A,%00001000
|
|
OUT (DIAGPORT),A
|
|
RET
|
|
;
|
|
Z280_BOOTERR .TEXT "\r\n\r\n*** Application mode boot not supported under Z280 native memory management!!!\r\n\r\n$"
|
|
#ENDIF
|
|
#ENDIF
|
|
|
|
DI ; NO INTERRUPTS
|
|
IM 1 ; INTERRUPT MODE 1
|
|
;
|
|
#IF (DIAGENABLE)
|
|
LD A,%00000001
|
|
OUT (DIAGPORT),A
|
|
#ENDIF
|
|
#IF (LEDENABLE)
|
|
#IF (LEDMODE == LEDMODE_STD)
|
|
XOR A ; LED IS INVERTED, TURN IT ON
|
|
#ENDIF
|
|
#IF (LEDMODE == LEDMODE_RTC)
|
|
LD A,%00000001 ; LED 0
|
|
LD (HB_RTCVAL),A ; SAVE TO SHADOW REGISTER
|
|
#ENDIF
|
|
OUT (LEDPORT),A
|
|
#ENDIF
|
|
;
|
|
LD SP,HBX_LOC ; SETUP INITIAL STACK JUST BELOW HBIOS PROXY
|
|
;
|
|
#IF (CPUFAM == CPU_Z280)
|
|
; SET MAXIMUM I/O WAIT STATES FOR NOW
|
|
LD C,Z280_BTCR ; BUS TIMING AND CONTROL REGISTER
|
|
LD HL,$0033 ; 3 I/O WAIT STATES ADDED
|
|
LDCTL (C),HL
|
|
;
|
|
; START BY SELECTING I/O PAGE $FF
|
|
LD L,$FF ; MMU AND DMA PAGE I/O REG IS $FF
|
|
LD C,Z280_IOPR ; REG C POINTS TO I/O PAGE REGISTER
|
|
LDCTL (C),HL
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
; INITIALIZE ALL OF THE SYSTEM PAGE DESCRIPTORS WITH BLOCK MOVE
|
|
XOR A ; FIRST USER PDR
|
|
OUT (Z280_MMUPDRPTR),A ; SET THE PDR POINTER
|
|
LD HL,Z280_BOOTPDRTBL ; START OF PDR VALUES TABLE
|
|
LD C,Z280_MMUBLKMOV ; PDR BLOCK MOVE PORT
|
|
LD B,16 ; PROGRAM 16 PDRS
|
|
.DB $ED,$93 ; OTIRW
|
|
;
|
|
; INITIALIZE ALL OF THE USER PAGE DESCRIPTORS WITH BLOCK MOVE
|
|
LD A,$10 ; FIRST SYSTEM PDR
|
|
OUT (Z280_MMUPDRPTR),A ; SET THE PDR POINTER
|
|
LD HL,Z280_BOOTPDRTBL ; START OF PDR VALUES TABLE
|
|
LD C,Z280_MMUBLKMOV ; PDR BLOCK MOVE PORT
|
|
LD B,16 ; PROGRAM 16 PDRS
|
|
.DB $ED,$93 ; OTIRW
|
|
;
|
|
; ENABLE MMU (SYSTEM AND USER TRANSLATION)
|
|
LD C,Z280_MMUMCR ; MMU MASTER CONTROL REGISTER
|
|
LD HL,$BBFF ; ENABLE USER & SYSTEM TRANSLATE
|
|
OUTW (C),HL
|
|
;
|
|
; DISABLE MEMORY REFRESH CYCLES
|
|
LD A,$08 ; DISABLED
|
|
OUT (Z280_RRR),A ; SET REFRESH RATE REGISTER
|
|
;
|
|
; CONFIGURE Z280 INT/TRAP VECTOR TABLE POINTER REGISTER
|
|
; WILL POINT TO ROM COPY FOR NOW, UPDATED TO RAM LATER ON
|
|
LD C,Z280_VPR
|
|
LD HL,Z280_IVT >> 8 ; TOP 16 BITS OF PHYSICAL ADR OF IVT
|
|
LDCTL (C),HL
|
|
;
|
|
JR Z280_INITZ ; JUMP TO CODE CONTINUATION
|
|
;
|
|
#IF (($ % 2) == 1)
|
|
; WORD ALIGN THE TABLE
|
|
.DB 0
|
|
#ENDIF
|
|
;
|
|
Z280_BOOTPDRTBL:
|
|
; LOWER 32 K (BANKED)
|
|
.DW ($000 << 4) | $A
|
|
.DW ($001 << 4) | $A
|
|
.DW ($002 << 4) | $A
|
|
.DW ($003 << 4) | $A
|
|
.DW ($004 << 4) | $A
|
|
.DW ($005 << 4) | $A
|
|
.DW ($006 << 4) | $A
|
|
.DW ($007 << 4) | $A
|
|
; UPPER 32 K (COMMON)
|
|
.DW (((((BID_COM & $7F) * 8) + 0) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 1) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 2) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 3) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 4) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 5) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 6) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
.DW (((((BID_COM & $7F) * 8) + 7) + (1 << (RAMLOC - 12))) << 4) | $A
|
|
;
|
|
Z280_INITZ:
|
|
;
|
|
#ENDIF
|
|
;
|
|
; RESTORE I/O PAGE TO $00
|
|
LD L,$00 ; NORMAL I/O REG IS $00
|
|
LD C,Z280_IOPR ; REG C POINTS TO I/O PAGE REGISTER
|
|
LDCTL (C),HL
|
|
;
|
|
#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
|
|
; WHEN USING AN INPUT FREQUENCY THAT IS XTAL / 2.
|
|
; 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
|
|
;
|
|
; SET DEFAULT CSIO SPEED (INTERNAL CLOCK, SLOW AS POSSIBLE)
|
|
LD A,Z180_CNTR_DEF ; DIV 1280, 14KHZ @ 18MHZ CLK
|
|
OUT0 (Z180_CNTR),A
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (EIPCENABLE)
|
|
LD A,(EIPC_WDT_CONST | EIPC_HALT_RUN | EIPC_WDT_P2_22)
|
|
OUT (EIPC_WDTMR),A ; CLEAR WDTE BIT (DISABLE WATCHDOG)
|
|
LD A,EIPC_DIS_WDT ; DISABLE WDT - SECOND KEY
|
|
OUT (EIPC_WDTCR),A
|
|
LD A,EIPC_WCR ; SET SYSTEM CONTROL REGISTER POINTER
|
|
; (SCRP) TO POINT TO WAIT STATE
|
|
OUT (EIPC_SCRP),A ; CONTROL REGISTER (WCR)
|
|
LD A,(EIPC_IO_0WS | EIPC_MEM_OWS | EIPC_OCF_0WS | EIPC_INT_0WS | EIPC_CHAIN_0WS)
|
|
OUT (EIPC_SCDP),A ; NO WAIT STATES
|
|
LD A,EIPC_MCR ; SET SCRP TO POINT TO MISCELLANEOUS
|
|
OUT (EIPC_SCRP),A ; CONTROL REGISTER (MCR)
|
|
LD A,EIPC_CLKDIV1 ; DIVIDE CLOCK BY 1, /CS0 DISABLE
|
|
OUT (EIPC_SCDP),A ; SET SYSTEM CONTROL DATA PORT (SCDP)
|
|
#ENDIF
|
|
;
|
|
#IF ((MEMMGR == MM_SBC) | (MEMMGR == MM_MBC))
|
|
; SET PAGING REGISTERS
|
|
#IFDEF ROMBOOT
|
|
XOR A
|
|
OUT (MPCL_RAM),A ; REMOVE RAM FIRST!
|
|
OUT (MPCL_ROM),A ; SELECT ROM PAGE 0
|
|
#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)
|
|
;
|
|
; 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
|
|
;
|
|
; TRANSITION TO UPPER (COMMON) RAM
|
|
;
|
|
LD HL,0 ; FROM START OF CURRENT BANK
|
|
LD DE,$8000 ; TO START OF COMMON RAM
|
|
LD BC,$8000-$200-1 ; EVERYTHING BUT THE PROXY AND BATCOND
|
|
LDIR
|
|
JP HB_START1
|
|
;
|
|
; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK
|
|
;
|
|
.ORG $8000 + $
|
|
;
|
|
HB_START1: ; BNKCALL ARRIVES HERE, BUT NOW RUNNING IN RAM BANK
|
|
;
|
|
DIAG(%00000111)
|
|
LED(%00000010)
|
|
;
|
|
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
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
; NOW POINT TO RAM COPY OF Z280 INT/TRAP TABLE
|
|
; HL IS TOP 16 BITS OF PHYSICAL ADDRESS OF IVT
|
|
; IVT *MUST* BE ON A 4K BOUNDARY
|
|
LD C,Z280_VPR
|
|
LD HL,0 + ((((BID_BIOS & $7F) * 8) + (1 << (RAMLOC - 12))) << 4) + (Z280_IVT >> 8)
|
|
LDCTL (C),HL
|
|
#ENDIF
|
|
;
|
|
; 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
|
|
;
|
|
DIAG(%00001111)
|
|
;
|
|
#IF FALSE
|
|
;
|
|
; 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 (SKZENABLE)
|
|
;
|
|
; SET THE SK Z80-512K UART CLK2 DIVIDER AS
|
|
; CONFIGURED. NOTE THAT THIS IMPLICITLY
|
|
; CLEARS THE WATCHDOG BIT. THE WATCHDOG
|
|
; WILL BE ENABLED LATER IF CONFIGURED.
|
|
LD A,SKZDIV ; GET DIVIDER CODE
|
|
OUT ($6D),A ; IMPLEMENT IT
|
|
;
|
|
#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
|
|
LD A,C
|
|
LD (CB_CPUMHZ),A
|
|
LD (CB_CPUKHZ),DE
|
|
;
|
|
#ENDIF
|
|
;
|
|
DIAG(%00011111)
|
|
;
|
|
LD A,(CPUMHZ) ; CPU SPEED TO ACCUM AND INIT
|
|
CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY
|
|
;
|
|
#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)
|
|
LD A,L ; PUT IN A
|
|
AND %00111100 ; CLEAR DC,HM, AND IO FIELDS
|
|
OR Z280_INTWAIT << 6 ; SET INT ACK WAIT STATE BITS (DC)
|
|
OR Z280_MEMHIWAIT << 2 ; SET HIGH 8MB WAIT STATE BITS (HM)
|
|
OR Z280_IOWAIT ; SET I/O WAIT STATE BITS
|
|
LD L,A ; BACK TO L
|
|
LDCTL (C),HL
|
|
;
|
|
LD C,Z280_BTIR ; BUS TIMING AND INIT REG
|
|
LDCTL HL,(C)
|
|
LD A,L ; PUT IN A
|
|
AND %11110011 ; CLEAR LM FIELD
|
|
OR Z280_MEMLOWAIT << 2 ; SET LOW 8MB WAIT STATE BITS
|
|
LD L,A ; BACK TO L
|
|
LDCTL (C),HL
|
|
;
|
|
#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 (INTMODE == 3)
|
|
;
|
|
; SETUP Z280 INT A FOR VECTORED INTERRUPTS
|
|
LD HL,%0010000000000000
|
|
LD C,Z280_ISR
|
|
LDCTL (C),HL
|
|
;
|
|
IM 3
|
|
;
|
|
#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
|
|
;
|
|
#ENDIF
|
|
;
|
|
#ENDIF
|
|
;
|
|
DIAG(%00111111)
|
|
#IF FALSE
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE
|
|
CALL REGDMP
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
#IF (DSKYENABLE)
|
|
CALL DSKY_PREINIT
|
|
;
|
|
LD HL,MSG_HBVER + 5
|
|
LD A,(DSKY_HEXMAP + RMJ)
|
|
OR $80
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(DSKY_HEXMAP + RMN)
|
|
OR $80
|
|
LD (HL),A
|
|
INC HL
|
|
LD A,(DSKY_HEXMAP + RUP)
|
|
LD (HL),A
|
|
LD HL,MSG_HBVER
|
|
CALL DSKY_SHOW
|
|
#ENDIF
|
|
;
|
|
; INITIALIZE SERIAL PORT
|
|
CALL CINIT
|
|
;
|
|
#IF FALSE
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE
|
|
CALL REGDMP
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
DIAG(%01111111)
|
|
LED(%00000011)
|
|
;
|
|
#IF FALSE
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
CALL NEWLINE2
|
|
PRTS("DEBUG+IVT$")
|
|
LD DE,HB_IVT
|
|
CALL DUMP_BUFFER
|
|
;
|
|
; TEST DEBUG ***************************************************************************************
|
|
;
|
|
#ENDIF
|
|
;
|
|
; ANNOUNCE HBIOS
|
|
;
|
|
CALL NEWLINE2
|
|
PRTX(STR_BANNER)
|
|
;
|
|
DIAG(%11111111)
|
|
;
|
|
; IO PORT SCAN
|
|
;
|
|
#IF FALSE
|
|
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
|
|
;
|
|
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)
|
|
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
|
|
|
|
#IF (CPUFAM == CPU_Z280)
|
|
LD A,Z280_MEMLOWAIT
|
|
CALL PRTDECB
|
|
LD A,'/'
|
|
CALL COUT
|
|
LD A,Z280_MEMHIWAIT
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " MEM W/S, $"
|
|
#ELSE
|
|
XOR A
|
|
#IF (CPUFAM == CPU_Z180)
|
|
LD A,Z180_MEMWAIT
|
|
#ENDIF
|
|
CALL PRTDECB
|
|
CALL PRTSTRD
|
|
.TEXT " MEM W/S, $"
|
|
#ENDIF
|
|
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
|
|
;
|
|
CALL PRTSTRD
|
|
.TEXT ", $"
|
|
CALL PRTSTRD
|
|
#IF (MEMMGR == MM_NONE)
|
|
.TEXT "NONE$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_SBC)
|
|
.TEXT "SBC$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_Z2)
|
|
.TEXT "Z2$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_N8)
|
|
.TEXT "N8$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_Z180)
|
|
.TEXT "Z180$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_Z280)
|
|
.TEXT "Z280$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_ZRC)
|
|
.TEXT "ZRC$"
|
|
#ENDIF
|
|
#IF (MEMMGR == MM_MBC)
|
|
.TEXT "MBC$"
|
|
#ENDIF
|
|
CALL PRTSTRD
|
|
.TEXT " MMU$"
|
|
;
|
|
; 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
|
|
LDCTL HL,(C)
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("BTCR=$")
|
|
LD C,Z280_BTCR ; BUS TIMING AND CONTROL REGISTER
|
|
LDCTL HL,(C)
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("BTIR=$")
|
|
LD C,Z280_BTIR ; BUS TIMING AND CONTROL REGISTER
|
|
LDCTL HL,(C)
|
|
CALL PRTHEXWORDHL
|
|
CALL PC_SPACE
|
|
PRTS("CCR=$")
|
|
LD C,Z280_CCR ; CACHE CONTROL REGISTER
|
|
LDCTL HL,(C)
|
|
CALL PRTHEXWORDHL
|
|
#ENDIF
|
|
;
|
|
#IFDEF ROMBOOT
|
|
;
|
|
; ROM CHECKSUM VERIFICATION
|
|
; THE FIRST ROM BANK HAS A CHECKSUM INJECTED SUCH THAT
|
|
; A COMPUTED CHECKSUM ACROSS THE ENTIRE BANK SHOLD ALWAYS BE ZERO
|
|
;
|
|
HB_ROMCK:
|
|
CALL NEWLINE
|
|
PRTS("ROM VERIFY:$")
|
|
;
|
|
; TEST FIRST 4 BANKS OF ROM
|
|
LD B,1 ; 1 BANK
|
|
LD C,0 ; STARTING AT BANK 0
|
|
HB_ROMCK1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
CALL HB_CKBNK ; TEST THE BANK
|
|
CALL PC_SPACE ; FORMATTING
|
|
CALL PRTHEXBYTE ; PRINT RESULT
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
OR A ; SET FLAGS
|
|
JR NZ,HB_ROMCK2 ; HANDLE FAILURE
|
|
INC C ; NEXT BANK
|
|
DJNZ HB_ROMCK1 ; LOOP FOR BANKS
|
|
PRTS(" PASS$") ; DISPLAY SUCCESS
|
|
JR HB_ROMCKZ ; CONTINUE BOOT
|
|
HB_ROMCK2:
|
|
PRTS(" FAIL$") ; DISPLAY ERROR
|
|
JR HB_ROMCKZ ; CONTINUE BOOT
|
|
;
|
|
; VERIFY ROM CHECKSUM BANK SPECIFIED IN REG C
|
|
; THIS MUST BE COPIED TO UPPER RAM TO RUN
|
|
; INTERRUPTS ARE DISABLED SINCE PAGE ZERO VECTOR WILL BE
|
|
; SWAPPED OUT. ASSUMES THAT INTERRUPTS ARE ENABLED AT ENTRY.
|
|
;
|
|
HB_CKBNK:
|
|
HB_DI ; SUPPRESS INTERRUPTS
|
|
LD HL,$7FFF ; START AT BANK END
|
|
LD BC,1 ; DECREMENT VALUE
|
|
XOR A ; ZERO ACCUM
|
|
HB_CKBNK1:
|
|
ADD A,(HL) ; ADD NEXT BYTE
|
|
OR A ; CLEAR CARRY
|
|
SBC HL,BC ; DECREMENT
|
|
JR NC,HB_CKBNK1 ; LOOP TILL DONE
|
|
HB_EI ; ALLOW INTERRUPTS AGAIN
|
|
RET ; AND DONE
|
|
;
|
|
HB_CKBNKSIZ .EQU $-HB_CKBNK ; SIZE OF ROUTINE
|
|
;
|
|
HB_ROMCKZ:
|
|
;
|
|
#ENDIF
|
|
;
|
|
; LOW BATTERY DIAGNOSTIC MESSAGE
|
|
;
|
|
#IF (BATCOND)
|
|
LD A,(HB_BATCOND)
|
|
OR A
|
|
LD DE,STR_LOWBAT
|
|
CALL Z,WRITESTR
|
|
#ENDIF
|
|
;
|
|
LD DE,STR_SYSHALT
|
|
CALL WRITESTR
|
|
JR $
|
|
DI
|
|
HALT
|
|
;
|
|
;==================================================================================================
|
|
; INTERRUPT VECTOR TABLE (MUST START AT PAGE BOUNDARY!!!)
|
|
;==================================================================================================
|
|
;
|
|
.FILL $100 - ($ & $FF)
|
|
;
|
|
;
|
|
; 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) | (INTMODE == 3))
|
|
;
|
|
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
|
|
;
|
|
#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
|
|
;
|
|
; BAD INTERRUPT HANDLER
|
|
;
|
|
HB_BADINT:
|
|
|
|
#IF FALSE ; *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
|
|
;
|
|
; Z280 BAD INT HANDLER
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
Z280_BADINT:
|
|
; SAVE REASON CODE FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_RCSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
; SAVE MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_BADINTSTR
|
|
CALL NEWLINE2
|
|
PRTS("+++ $")
|
|
CALL WRITESTR
|
|
POP DE
|
|
CALL XREGDMP
|
|
;
|
|
; RECOVER MSR, THEN RETURN VIA RETIL
|
|
PUSH HL ; SAVE HL
|
|
LD HL,(HB_RCSAV) ; GET SAVED REASON CODE
|
|
PRTS(" RC=$")
|
|
CALL PRTHEXWORDHL ; DUMP MSR
|
|
LD HL,(HB_MSRSAV) ; GET SAVED MSR
|
|
PRTS(" MSR=$")
|
|
CALL PRTHEXWORDHL ; DUMP MSR
|
|
EX (SP),HL ; MSR TO STK, RECOVER HL
|
|
;
|
|
.DB $ED,$55 ; RETIL
|
|
;
|
|
Z280_SSTEP:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_SSTEPSTR
|
|
JP Z280_DIAG
|
|
;
|
|
Z280_BRKHLT:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_BRKHLTSTR
|
|
JP Z280_DIAG
|
|
;
|
|
Z280_DIVEXC:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_DIVEXCSTR
|
|
JP Z280_DIAG
|
|
;
|
|
Z280_STKOVR:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_STKOVRSTR
|
|
JP Z280_DIAG
|
|
;
|
|
Z280_ACCVIO:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
;
|
|
PUSH DE
|
|
LD DE,Z280_ACCVIOSTR
|
|
JP Z280_DIAG
|
|
;
|
|
Z280_DIAG:
|
|
CALL NEWLINE2
|
|
PRTS("+++ $")
|
|
CALL WRITESTR
|
|
POP DE
|
|
CALL XREGDMP
|
|
;
|
|
; RECOVER MSR, THEN RETURN VIA RETIL
|
|
PUSH HL ; SAVE HL
|
|
LD HL,(HB_MSRSAV) ; GET SAVED MSR
|
|
PRTS(" MSR=$")
|
|
CALL PRTHEXWORDHL ; DUMP MSR
|
|
EX (SP),HL ; MSR TO STK, RECOVER HL
|
|
;
|
|
;RETIL
|
|
DI
|
|
HALT
|
|
;
|
|
Z280_BADINTSTR .TEXT "BAD INT $"
|
|
Z280_SSTEPSTR .TEXT "SINGLE STEP $"
|
|
Z280_BRKHLTSTR .TEXT "BREAK HALT $"
|
|
Z280_DIVEXCSTR .TEXT "DIVISION EXCEPTION $"
|
|
Z280_STKOVRSTR .TEXT "STACK OVERFLOW $"
|
|
Z280_ACCVIOSTR .TEXT "ACCESS VIOLATION $"
|
|
;
|
|
#ENDIF
|
|
;
|
|
; Z280 PRIVILEGED INSTRUCTION HANDLER
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
Z280_PRIVINST:
|
|
; SAVE HL AND MSR FOR POSSIBLE RETURN VIA RETIL
|
|
EX (SP),HL ; GET MSR, SAVE HL
|
|
LD (HB_MSRSAV),HL ; SAVE IT
|
|
POP HL ; RECOVER HL, POP STACK
|
|
EX (SP),HL ; GET ADR, SAVE HL
|
|
;
|
|
PUSH AF
|
|
PUSH BC
|
|
PUSH DE
|
|
;
|
|
.DB $ED,$96 ; LDUP A,(HL)
|
|
;
|
|
; HANDLE DI
|
|
CP $F3 ; DI?
|
|
JR NZ,Z280_PRIVINST2
|
|
HB_DI ; DO THE DI
|
|
INC HL ; BUMP PAST IT
|
|
JR Z280_PRIVINSTX
|
|
;
|
|
Z280_PRIVINST2:
|
|
; HANDLE EI
|
|
CP $FB ; EI?
|
|
JR NZ,Z280_PRIVINST3
|
|
HB_EI ; DO THE EI
|
|
INC HL ; BUMP PAST IT
|
|
JR Z280_PRIVINSTX
|
|
;
|
|
Z280_PRIVINST3:
|
|
; SOMETHING ELSE, DIAGNOSE & HALT SYSTEM
|
|
LD DE,Z280_PRIVSTR
|
|
CALL WRITESTR
|
|
CALL PRTHEXWORDHL
|
|
;
|
|
; DUMP 16 BYTES OF USER ADDRESS SPACE
|
|
CALL PC_SPACE
|
|
CALL PC_LBKT
|
|
LD B,$10
|
|
Z280_PRIVINST4:
|
|
.DB $ED,$96 ; LDUP A,(HL)
|
|
CALL PRTHEXBYTE
|
|
INC HL
|
|
DJNZ Z280_PRIVINST4
|
|
CALL PC_RBKT
|
|
;
|
|
; GO NO FURTHER
|
|
DI
|
|
HALT
|
|
;
|
|
Z280_PRIVINSTX:
|
|
; RESTORE REGISTERS
|
|
POP DE
|
|
POP BC
|
|
POP AF
|
|
;
|
|
; RECOVER HL AND MSR, THEN RETURN VIA RETIL
|
|
EX (SP),HL ; RECOVER HL, ADR TO STK
|
|
PUSH HL ; SAVE HL
|
|
LD HL,(HB_MSRSAV) ; GET SAVED MSR
|
|
EX (SP),HL ; MSR TO STK, RECOVER HL
|
|
.DB $ED,$55 ; RETIL
|
|
;
|
|
HB_MSRSAV .DW 0 ; SAVED MSR
|
|
HB_RCSAV .DW 0 ; SAVED REASON CODE
|
|
;
|
|
Z280_PRIVSTR .TEXT "\r\n\r\n*** Privileged Instruction @$"
|
|
;
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; Z280 INTERRUPT VECTOR TABLE
|
|
;==================================================================================================
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
; THE Z280 IVT MUST BE ON A 4K BOUNDARY. IT HAS BEEN LOCATED
|
|
; HERE IN AN EFFORT TO MINIMIZE WASTED SPACE. THERE SHOULD BE
|
|
; A LITTLE LESS THAN 4K OF CODE ABOVE.
|
|
;
|
|
.FILL $1000 - ($ & $FFF) ; MUST BE 4K ALIGNED!
|
|
;
|
|
Z280_IVT:
|
|
.DW 0, 0 ; RESERVED
|
|
.DW 0 ; NMI MSR
|
|
.DW 0 ; NMI VECTOR
|
|
.DW $0000 ; INT A MSR
|
|
.DW Z280_BADINT ; INT A VECTOR
|
|
.DW $0000 ; INT B MSR
|
|
.DW Z280_BADINT ; INT B VECTOR
|
|
.DW $0000 ; INT C MSR
|
|
.DW Z280_BADINT ; INT C VECTOR
|
|
.DW $0000 ; COUNTER/TIMER 0 MSR
|
|
.DW Z280_BADINT ; COUNTER/TIMER 0 VECTOR
|
|
.DW $0000 ; COUNTER/TIMER 1 MSR
|
|
.DW Z280_BADINT ; COUNTER/TIMER 1 VECTOR
|
|
.DW 0, 0 ; RESERVED
|
|
.DW $0000 ; COUNTER/TIMER 2 MSR
|
|
.DW Z280_BADINT ; COUNTER/TIMER 2 VECTOR
|
|
.DW $0000 ; DMA CHANNEL 0 MSR
|
|
.DW Z280_BADINT ; DMA CHANNEL 0 VECTOR
|
|
.DW $0000 ; DMA CHANNEL 1 MSR
|
|
.DW Z280_BADINT ; DMA CHANNEL 1 VECTOR
|
|
.DW $0000 ; DMA CHANNEL 2 MSR
|
|
.DW Z280_BADINT ; DMA CHANNEL 2 VECTOR
|
|
.DW $0000 ; DMA CHANNEL 3 MSR
|
|
.DW Z280_BADINT ; DMA CHANNEL 3 VECTOR
|
|
.DW $0000 ; UART RECEIVER MSR
|
|
.DW Z280_BADINT ; UART RECEIVER VECTOR
|
|
.DW $0000 ; UART TRANSMITTER MSR
|
|
.DW Z280_BADINT ; UART TRANSMITTER VECTOR
|
|
.DW $0000 ; SINGLE STEP TRAP MSR
|
|
.DW Z280_SSTEP ; SINGLE STEP TRAP VECTOR
|
|
.DW $0000 ; BREAK ON HALT TRAP MSR
|
|
.DW Z280_BRKHLT ; BREAK ON HALT TRAP VECTOR
|
|
.DW $0000 ; DIVISION EXCEPTION TRAP MSR
|
|
.DW Z280_DIVEXC ; DIVISION EXCEPTION TRAP VECTOR
|
|
.DW $0000 ; STACK OVERFLOW WARNING TRAP MSR
|
|
.DW Z280_STKOVR ; STACK OVERFLOW WARNING TRAP VECTOR
|
|
.DW $0000 ; ACCESS VIOLATION TRAP MSR
|
|
.DW Z280_ACCVIO ; ACCESS VIOLATION TRAP VECTOR
|
|
.DW $0000 ; SYSTEM CALL TRAP MSR
|
|
.DW Z280_SYSCALL ; SYSTEM CALL TRAP VECTOR
|
|
.DW $0000 ; PRIVILEGED INSTRUCTION TRAP MSR
|
|
.DW Z280_PRIVINST ; PRIVILEGED INSTRUCTION TRAP VECTOR
|
|
.DW $0000 ; EPU <- MEMORY EXTENDED INSTRUCTION TRAP MSR
|
|
.DW $0000 ; EPU <- MEMORY EXTENDED INSTRUCTION TRAP VECTOR
|
|
.DW $0000 ; MEMORY <- EPU EXTENDED INSTRUCTION TRAP MSR
|
|
.DW $0000 ; MEMORY <- EPU EXTENDED INSTRUCTION TRAP VECTOR
|
|
.DW $0000 ; A <- EPU EXTENDED INSTRUCTION TRAP MSR
|
|
.DW $0000 ; A <- EPU EXTENDED INSTRUCTION TRAP VECTOR
|
|
.DW $0000 ; EPU INTERNAL OPERATION EXTENDED INSTRUCTION TRAP MSR
|
|
.DW $0000 ; EPU INTERNAL OPERATION EXTENDED INSTRUCTION TRAP VECTOR
|
|
.DW 0, 0 ; RESERVED
|
|
.DW 0, 0 ; RESERVED
|
|
; PROGRAM COUNTER VALUES FOR NMI/INTA (16)
|
|
.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
|
|
; THE REMAINDER OF THE Z280 IVT IS TRUNCATED HERE BECAUSE IT
|
|
; TAKES A BUNCH OF SPACE AND IS NOT USED. WE SUPPORT ONLY
|
|
; 16 VECTORED INTERRUPTS AND THEY MUST BE CONNECTED TO INTA.
|
|
;
|
|
#ENDIF
|
|
;
|
|
; Z280 BANK SELECTION (CALLED FROM PROXY)
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
; REG A HAS BANK ID, REG B HAS INITIAL PDR TO PROGRAM
|
|
; REGISTERS AF, BC, HL DESTROYED
|
|
;
|
|
; THIS ROUTINE MAY BE RELOCATED TO RUN IN HIGH MEMORY IN CERTAIN CASES
|
|
; LIKE A SYSTEM RESTART. IT MUST BE KEPT ENTIRELY RELOCATABLE.
|
|
;
|
|
Z280_BNKSEL:
|
|
;; *DEBUG*
|
|
;CALL PC_LBKT
|
|
;CALL PRTHEXBYTE
|
|
;CALL PC_RBKT
|
|
|
|
; SELECT I/O PAGE $FE (SAVING PREVIOUS VALUE)
|
|
LD C,Z280_IOPR ; REG C POINTS TO I/O PAGE REGISTER
|
|
LDCTL HL,(C) ; GET CURRENT I/O PAGE
|
|
PUSH HL ; SAVE IT
|
|
LD L,$FF ; NEW I/O PAGE
|
|
LDCTL (C),HL
|
|
;
|
|
; CONVERT BANK ID TO TOP 12 BITS OF PHYSICAL ADDRESS
|
|
; WITH $0A IN THE LOW ORDER NIBBLE:
|
|
; BANK ID: R000 BBBB
|
|
; PDR: R000 0BBB B000 1010 (RC2014)
|
|
; PDR: 0000 RBBB B000 1010 (ZZ80MB)
|
|
;
|
|
MULTU A,$80 ; HL=0R00 0BBB B000 0000
|
|
BIT 6,H ; RAM BIT SET?
|
|
JR Z,Z280_BNKSEL2 ; IF NOT, ALL DONE
|
|
RES 6,H ; OTHERWISE, MOVE RAM BIT
|
|
SET RAMLOC-16,H ; HL=0000 RBBB B000 0000
|
|
;
|
|
Z280_BNKSEL2:
|
|
;
|
|
; SET LOW NIBBLE
|
|
LD A,$0A ; VALUE FOR LOW NIBBLE
|
|
.DB $ED,$6D ; ADD HL,A ; HL=0000 RBBB B000 1010
|
|
;
|
|
; POINT TO FIRST PDR TO PROGRAM
|
|
LD A,B ; INITIAL PDR TO PROG
|
|
OUT (Z280_MMUPDRPTR),A ; SET THE PDR POINTER
|
|
;
|
|
; PROGRAM 8 PDRS
|
|
LD C,Z280_MMUBLKMOV ; PDR BLOCK MOVE PORT
|
|
;LD B,8 ; PROGRAM 8 PDRS
|
|
LD A,$10 ; PDR VALUE INCREMENT
|
|
Z280_BNKSEL3:
|
|
; PROGRAM 8 PDR VALUES
|
|
; LOOP UNROLLED FOR SPEED
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
OUTW (C),HL ; WRITE VALUE
|
|
ADD HL,A ; BUMP VALUE
|
|
;DJNZ Z280_BNKSEL3 ; DO ALL PDRS
|
|
;
|
|
; RESTORE I/O PAGE
|
|
LD C,Z280_IOPR ; REG C POINTS TO I/O PAGE REGISTER
|
|
POP HL ; RECOVER ORIGINAL I/O PAGE
|
|
LDCTL (C),HL
|
|
;
|
|
RET
|
|
;
|
|
Z280_BNKSEL_LEN .EQU $ - Z280_BNKSEL
|
|
;
|
|
#ENDIF
|
|
;
|
|
; Z280 BANK COPY (CALLED FROM PROXY)
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
;
|
|
Z280_BNKCPY:
|
|
; Z280 MEMORY TO MEMORY DMA
|
|
; USE FLOW THROUGH MODE
|
|
; SINGLE BYTE TRANSFER
|
|
; TRANSACTION DESCRIPTION REGISTER (TDR)
|
|
; %0000 0000 0000 0000
|
|
; - AUTO INCREMENT MEMORY
|
|
; - FLOWTHROUGH OPERATION
|
|
; - SINGLE TRANSACTION (CAN WE USE CONTINUOUS???)
|
|
; - 1 BYTE XFER SIZE
|
|
;
|
|
; SAVE INCOMING REGISTERS
|
|
PUSH HL
|
|
PUSH DE
|
|
PUSH BC
|
|
;
|
|
PUSH BC ; SAVE COUNT
|
|
PUSH HL ; SAVE SOURCE ADDRESS
|
|
;
|
|
; SELECT I/O PAGE $FF
|
|
LD C,Z280_IOPR ; I/O PAGE REGISTER
|
|
LDCTL HL,(C) ; GET CURRENT I/O PAGE
|
|
LD (IOPRVAL),HL ; SAVE IT
|
|
LD L,$FF ; I/O PAGE $FF
|
|
LDCTL (C),HL
|
|
;
|
|
LD C,Z280_DMA0_DSTL ; START WITH DEST REG LO
|
|
;
|
|
LD A,(HB_DSTBNK) ; DEST BANK TO ACCUM
|
|
CALL Z2DMAADR ; SETUP DEST ADR REGS
|
|
;
|
|
POP DE ; SRC ADR TO DE
|
|
LD A,(HB_SRCBNK) ; DEST BANK TO ACCUM
|
|
CALL Z2DMAADR ; SETUP SOURCE ADR REGS
|
|
;
|
|
POP HL ; COUNT TO HL
|
|
OUTW (C),HL
|
|
INC C ; BUMP TO TDR
|
|
;
|
|
LD HL,$8000 ; ENABLE DMA0 TO RUN!
|
|
OUTW (C),HL
|
|
;
|
|
; WAIT FOR XFER TO COMPLETE
|
|
Z2DMALOOP:
|
|
.DB $ED,$B7 ; INW HL,(C)
|
|
BIT 7,H ; CHECK EN BIT OF TDR
|
|
JR NZ,Z2DMALOOP ; LOOP WHILE ACTIVE
|
|
;
|
|
; RESTORE I/O PAGE
|
|
LD C,Z280_IOPR ; I/O PAGE REGISTER
|
|
LD HL,(IOPRVAL) ; RESTORE I/O PAGE
|
|
LDCTL (C),HL
|
|
;
|
|
; SETUP RETURN VALUES
|
|
POP BC ; RECOVER ORIGINAL BC
|
|
POP DE ; RECOVER ORIGINAL DE
|
|
POP HL ; RECOVER ORIGINAL HL
|
|
ADD HL,BC ; INCREMENT SRC ADR BY COUNT
|
|
EX DE,HL ; SWAP
|
|
ADD HL,BC ; INCREMENT DST ADR BY COUNT
|
|
EX DE,HL ; SWAP BACK
|
|
LD BC,0 ; COUNT IS NOW ZERO
|
|
;
|
|
RET
|
|
;
|
|
Z2DMAADR:
|
|
; SET ADDRESS REGISTERS, BANK IN A, ADDRESS IN DE
|
|
; C POINTS TO FIRST DMA ADR PORT TO SET
|
|
; A=R000 BBBB, DE=0AAA AAAA AAAA AAAA
|
|
; RC: DMA HI=0000 RBBB BAAA 1111 LO=1111 AAAA AAAA AAAA
|
|
; ZZ: DMA HI=R000 0BBB BAAA 1111 LO=1111 AAAA AAAA AAAA
|
|
BIT 7,D ; HIGH RAM?
|
|
JR Z,Z2DMAADR1 ; NO, SKIP
|
|
LD A,$8F ; SUBSTITUTE COMMON RAM BANK ID
|
|
;
|
|
Z2DMAADR1:
|
|
; ADR HI FROM A:DE
|
|
LD L,D ; L=?AAA AAAA
|
|
LD H,A ; H=R000 BBBB
|
|
SLA L ; L=AAAA AAA0 ?
|
|
SRL H ; H=0R00 0BBB B
|
|
RR L ; L=BAAA AAAA 0
|
|
LD A,$0F ; A=0000 1111
|
|
OR L ; A=BAAA 1111
|
|
LD L,A ; L=BAAA 1111
|
|
;
|
|
; MOVE THE RAM/ROM BIT.
|
|
; RC2014 DMA HI=0000 RBBB BAAA 1111 LO=1111 AAAA AAAA AAAA
|
|
; ZZ80MB DMA HI=R000 0BBB BAAA 1111 LO=1111 AAAA AAAA AAAA
|
|
BIT 6,H
|
|
JR Z,Z2DMAADR2
|
|
RES 6,H
|
|
SET RAMLOC-16,H
|
|
;
|
|
Z2DMAADR2:
|
|
PUSH HL ; SAVE IT FOR NOW
|
|
|
|
; ADR LO FROM DE:
|
|
LD L,E ; L=AAAA AAAA
|
|
LD A,$F0 ; A=1111 0000
|
|
OR D ; A=1111 AAAA
|
|
LD H,A ; HL=1111 AAAA AAAA AAAA
|
|
;
|
|
; SET ADR LO REG
|
|
OUTW (C),HL
|
|
INC C ; BUMP TO ADR HI REG
|
|
;
|
|
; SET ADR HI REG
|
|
POP HL ; RECOVER THE HI VAL
|
|
OUTW (C),HL
|
|
INC C ; BUMP TO NEXT REG
|
|
;
|
|
RET
|
|
#ENDIF
|
|
;
|
|
; Z280 SYSCALL VECTOR ENTRY POINT. TAKES STACK PARAMETER AS A BRANCH
|
|
; ADDRESS AND CALLS IT. ALLOWS ANY USER MODE CODE TO CALL INTO AN
|
|
; ARBITRARY LOCATION OF SYSTEM MODE CODE.
|
|
;
|
|
#IF (MEMMGR == MM_Z280)
|
|
Z280_SYSCALL:
|
|
EX (SP),HL
|
|
LD (Z280_SYSCALL_GO+1),HL
|
|
POP HL
|
|
Z280_SYSCALL_GO:
|
|
CALL $FFFF ; PARM SET ABOVE
|
|
.DB $ED,$55 ; RETIL
|
|
#ENDIF
|
|
;
|
|
#DEFINE USEDELAY
|
|
#INCLUDE "util.asm"
|
|
;
|
|
#IF (DSKYENABLE)
|
|
#DEFINE DSKY_KBD
|
|
#IF (DSKYMODE == DSKYMODE_V1)
|
|
#INCLUDE "dsky.asm"
|
|
#ENDIF
|
|
#IF (DSKYMODE == DSKYMODE_NG)
|
|
#INCLUDE "dskyng.asm"
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
; 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
|
|
;
|
|
HB_CPU_STR: .TEXT " Z80$"
|
|
.TEXT " Z80180$"
|
|
.TEXT " Z8S180-K$"
|
|
.TEXT " Z8S180-N$"
|
|
.TEXT " Z80280$"
|
|
;
|
|
;==================================================================================================
|
|
; CONSOLE CHARACTER I/O HELPER ROUTINES (REGISTERS PRESERVED)
|
|
;==================================================================================================
|
|
;
|
|
#IF (MINIO == MINIO_UART)
|
|
#INCLUDE "min_uart.asm"
|
|
#ENDIF
|
|
;
|
|
#IF (MINIO == MINIO_ASCI)
|
|
#INCLUDE "min_asci.asm"
|
|
#ENDIF
|
|
;
|
|
#IF (MINIO == MINIO_ACIA)
|
|
#INCLUDE "min_acia.asm"
|
|
#ENDIF
|
|
;
|
|
#IF (MINIO == MINIO_SIO)
|
|
#INCLUDE "min_sio.asm"
|
|
#ENDIF
|
|
;
|
|
#IF (MINIO == MINIO_Z2U)
|
|
#INCLUDE "min_z2u.asm"
|
|
#ENDIF
|
|
;
|
|
;==================================================================================================
|
|
; 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
|
|
;
|
|
;==================================================================================================
|
|
; HBIOS GLOBAL DATA
|
|
;==================================================================================================
|
|
;
|
|
HB_CPUTYPE .DB 0 ; 0=Z80, 1=80180, 2=SL1960, 3=ASCI BRG
|
|
;
|
|
CB_CPUMHZ .DB CPUMHZ
|
|
CB_CPUKHZ .DW CPUKHZ
|
|
;
|
|
IOPRVAL .DW 0 ; TEMP STORAGE FOR IOPR
|
|
;
|
|
HB_BATCOND .DB 0 ; BATTERY CONDITION (0=LOW, 1=OK)
|
|
;
|
|
STR_BANNER .DB "RomWBW HDIAG 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)? $"
|
|
STR_SYSHALT .TEXT "\r\n\r\n*** SYSTEM HALTED ***$"
|
|
;
|
|
#IF (DSKYENABLE) ; 'H','B','I','O',' ',' ',' ',' '
|
|
#IF (DSKYMODE == DSKYMODE_V1)
|
|
MSG_HBVER .DB $3E,$7F,$0A,$7B,$00,$00,$00,$00 ; "HBIO "
|
|
#ENDIF
|
|
#IF (DSKYMODE == DSKYMODE_NG)
|
|
MSG_HBVER .DB $76,$7F,$30,$3F,$00,$00,$00,$00 ; "HBIO "
|
|
#ENDIF
|
|
#ENDIF
|
|
;
|
|
HB_APPBNK .DB 0 ; START BANK WHEN RUN IN APP MODE
|
|
;
|
|
HB_BCDTMP .FILL 5,0 ; BCD NUMBER STORAGE (TEMP)
|
|
;
|
|
HB_END .EQU $
|
|
;
|
|
SLACK .EQU HBX_LOC - $
|
|
.ECHO "HDIAG space remaining: "
|
|
.ECHO SLACK
|
|
.ECHO " bytes.\n"
|
|
;
|
|
#IFDEF ROMBOOT
|
|
.FILL SLACK
|
|
#ENDIF
|
|
;
|
|
.END
|
|
|