; ;================================================================================================== ; HBIOS ;================================================================================================== ; ; INCLUDE GENERIC STUFF ; #INCLUDE "std.asm" ; .ORG 0 ; ;================================================================================================== ; NORMAL PAGE ZERO SETUP, RET/RETI/RETN AS APPROPRIATE ;================================================================================================== ; .FILL (000H - $),0FFH ; RST 0 JP HB_START .DW ROM_SIG .FILL (008H - $),0FFH ; RST 8 JP HB_DISPATCH .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 ; INT RETI .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 2015, Wayne Warthen, GNU GPL v3", 0 ; .FILL ($100 - $),$FF ; PAD REMAINDER OF PAGE ZERO ; HCB .FILL $100,$FF ; RESERVED FOR HBIOS CONTROL BLOCK ; ;================================================================================================== ; 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) ; HBIOS PROXY COPY BUFFER $FF20 (128 BYTES) ; HBIOS PROXY PRIVATE STACK $FFA0 (64 BYTES, 32 ENTRIES) ; HBIOS PROXY MGMT BLOCK $FFE0 (32 BYTES) ; ; DEFINITIONS ; HBX_CODSIZ .EQU $100 ; 256 BYTE CODE SPACE HBX_IVTSIZ .EQU $20 ; INT VECTOR TABLE SIZE (16 ENTRIES) HBX_BUFSIZ .EQU $80 ; INTERBANK COPY BUFFER HBX_STKSIZ .EQU $40 ; PRIVATE STACK 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_STKSAV),SP ; SAVE ORIGINAL STACK FRAME LD SP,HBX_STACK ; SETUP NEW STACK FRAME LD A,(HB_CURBNK) ; GET CURRENT BANK LD (HBX_INVBNK),A ; SETUP TO RESTORE AT EXIT LD A,BID_BIOS ; HBIOS BANK CALL HBX_BNKSEL ; SELECT IT CALL HB_DISPATCH ; CALL HBIOS FUNCTION DISPATCHER PUSH AF ; SAVE AF (FUNCTION RETURN) LD A,$FF ; LOAD ORIGINAL BANK ($FF IS REPLACED AT ENTRY) HBX_INVBNK .EQU $ - 1 CALL HBX_BNKSEL ; SELECT IT POP AF ; RESTORE AF LD SP,0 ; RESTORE ORIGINAL STACK FRAME HBX_STKSAV .EQU $ - 2 RET ; RETURN TO CALLER ; ;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;; SETBNK - Switch Memory Bank to Bank in A. ;; Preserve all Registers including Flags. ;; Does NOT update current bank. ;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; HBX_BNKSEL: LD (HB_CURBNK),A ; RECORD NEW CURRENT BANK ; #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR RET ; DONE #ENDIF #IF (PLATFORM == PLT_ZETA2) 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 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. ; Enter: ; HL = Source Address ; DE = Destination Address ; BC = Number of bytes to copy ; Exit : None ; Uses : AF,BC,DE,HL ; ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; HBX_BNKCPY: 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, BUT ONLY IF NOT ZERO BYTES POP AF ; RECOVER ORIGINAL BANK JP HBX_BNKSEL ; SWITCH TO CURRENT BANK AND EXIT ; HBX_BC_ITER: ; HL = SRC ADR, DE = DEST ADR, BC = LEN PUSH BC ; SAVE COPY LEN PUSH DE ; FINAL DEST ON STACK LD DE,HBX_BUF ; SET DEST TO BUF LD A,(HB_SRCBNK) ; GET SOURCE BANK CALL HBX_BNKSEL ; SWITCH TO SOURCE BANK LDIR ; HL -> BUF (DE), BC BYTES, HL UPDATED SRC ADR POP DE ; DE := FINAL DEST POP BC ; GET LEN BACK IN BC PUSH HL ; SAVE UPDATED SRC ADR LD HL,HBX_BUF ; SET SRC ADR TO BUF LD A,(HB_DSTBNK) ; GET DEST BANK CALL HBX_BNKSEL ; SWITCH TO DEST BANK LDIR ; BUF (HL) -> DE, BC BYTES, DE UPDATED DEST ADR POP HL ; RECOVER UPDATED SRC ADR ; HL = UPD SRC, DE = UPD DEST, BC = 0 RET ; ; Call a routine in another bank saving and restoring the original bank. ; Caller MUST ensure stack is already in high memory. ; On input A=target bank, HL=target address ; 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 ; ; INTERRUPT HANDLER DISPATCHING ; 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 ; INT_BAD: ; BAD INTERRUPT HANDLER PUSH HL ; SAVE HL LD HL,HB_BADINT JR HBX_INT ; ; COMMON INTERRUPT DISPATCHING CODE ; SETUP AND CALL HANDLER IN BIOS BANK ; HBX_INT: ; COMMON INTERRUPT ROUTING CODE ; ; SAVE STATE (ASSUMES HL SAVED PREVIOUSLY) PUSH AF ; SAVE AF PUSH BC ; SAVE BC PUSH DE ; SAVE DE ; ACTIVATE BIOS BANK #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) LD A,BID_BIOS ; BIOS PAGE INDEX TO ACCUM OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR #ENDIF #IF (PLATFORM == PLT_ZETA2) LD A,(BID_BIOS - $80 + $10) * 2 ; BIOS BID -> PAGE INDEX -> A OUT (MPGSEL_0),A ; BANK_0: 0K - 16K INC A ; OUT (MPGSEL_1),A ; BANK_1: 16K - 32K #ENDIF #IF (PLATFORM == PLT_N8) LD A,(BID_BIOS << 3) & $FF ; BIOS BID -> BBR VAL -> A OUT0 (Z180_BBR),A ; WRITE TO Z180 BANK BASE REG LD A,N8_DEFACR | $80 ; BIT 7 SET FOR RAM OUT0 (N8_ACR),A ; WRITE TO N8 ACR #ENDIF #IF (PLATFORM == PLT_MK4) LD A,(BID_BIOS << 3) & $FF | $80 ; BIOS BID -> PAGE INDEX -> A OUT0 (Z180_BBR),A ; WRITE TO Z180 BANK BASE REG #ENDIF ; SETUP INTERRUPT PROCESSING STACK IN HBIOS LD (HB_INTSTKSAV),SP ; SAVE STACK POINTER LD SP,HB_INTSTK ; SWITCH TO INTERRUPT STACK ; DO THE REAL WORK CALL JPHL ; CALL INTERRUPT ROUTINE ; RESTORE STACK LD SP,(HB_INTSTKSAV) ; RESTORE STACK ; RESTORE BANK LD A,(HB_CURBNK) ; GET PRE-INT BANK ; #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA)) OUT (MPCL_ROM),A ; SET ROM PAGE SELECTOR OUT (MPCL_RAM),A ; SET RAM PAGE SELECTOR #ENDIF #IF (PLATFORM == PLT_ZETA2) BIT 7,A ; BIT 7 SET REQUESTS RAM PAGE JR Z,HBX_INT1 ; 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_INT1: 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 #ENDIF #IF (PLATFORM == PLT_N8) BIT 7,A ; TEST BIT 7 FOR RAM VS. ROM JR Z,HBX_INT1 ; IF NOT SET, SELECT ROM PAGE ; RES 7,A ; CLEAR BIT 7 FOR RAM VS. ROM 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 JR HBX_INT2 ; CONTINUE ; HBX_INT1: ; SELECT ROM PAGE 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 ; HBX_INT2: #ENDIF #IF (PLATFORM == PLT_MK4) RLCA ; RAM FLAG TO CARRY AND BIT 0 JR NC,HBX_INT1 ; IF NC, ROM, SKIP AHEAD XOR %00100001 ; SET BIT FOR HI 512K, CLR BIT 0 HBX_INT1: RLCA ; ROTATE RLCA ; ... AGAIN OUT0 (Z180_BBR),A ; WRITE TO BANK REGISTER #ENDIF ; ; RESTORE STATE POP DE ; RESTORE DE POP BC ; RESTORE BC POP AF ; RESTORE AF POP HL ; RESTORE HL ; DONE RETI ; IMPLICITLY REENABLES INTERRUPTS! ; ; PEEK & POKE ROUTINES ; ADDRESS IN HL, BANK IN D, VALUE IN/OUT IN E, A IS TRASHED ; HBX_PEEK: LD A,(HB_CURBNK) PUSH AF LD A,D CALL HBX_BNKSEL LD E,(HL) POP AF JP HBX_BNKSEL ; HBX_POKE: LD A,(HB_CURBNK) PUSH AF LD A,D CALL HBX_BNKSEL LD (HL),E POP AF JP HBX_BNKSEL ; ; FILLER FOR UNUSED HBIOS PROXY CODE SPACE ; PAD TO START OF INTERRUPT VECTOR TABLE ; HBX_SLACK .EQU (HBX_LOC + HBX_CODSIZ - $) .ECHO "HBIOS PROXY space remaining: " .ECHO HBX_SLACK .ECHO " bytes.\n" .FILL HBX_SLACK,$FF ; ; HBIOS INTERRUPT VECTOR TABLE (16 ENTRIES) ; HBX_IVT: .DW INT_TIMER .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD .DW INT_BAD ; ; INTERBANK COPY BUFFER (128 BYTES) ; HBX_BUF .FILL HBX_BUFSIZ,0 ; ; PRIVATE STACK (64 BYTES, 32 ENTRIES) ; .FILL HBX_STKSIZ,$FF HBX_STACK .EQU $ ; ; HBIOS PROXY MGMT BLOCK (TOP 32 BYTES) ; .DB BID_BOOT ; CURRENTLY ACTIVE LOW MEMORY BANK ID .DB $FF ; DEPRECATED!!! .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) ;================================================================================================== ; JP HB_START ; HBIOS INITIALIZATION JP HB_DISPATCH ; VECTOR TO DISPATCHER ; ;================================================================================================== ; SYSTEM INITIALIZATION ;================================================================================================== ; HB_START: ; #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) ; SET BASE FOR CPU IO REGISTERS LD A,Z180_BASE OUT0 (Z180_ICR),A ; DISABLE REFRESH XOR A OUT0 (Z180_RCR),A ; SET DEFAULT WAIT STATES TO ACCURATELY MEASURE CPU SPEED LD A,$F0 OUT0 (Z180_DCNTL),A #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 ; CALL HB_CPUSPD ; CPU SPEED DETECTION ; #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) ; ; 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 ; ; ANNOUNCE HBIOS ; ; ; DISPLAY THE PRE-INITIALIZATION BANNER ; CALL NEWLINE CALL NEWLINE PRTX(STR_BANNER) CALL NEWLINE CALL NEWLINE PRTX(STR_PLATFORM) PRTS(" @ $") LD HL,(HCB + HCB_CPUKHZ) CALL PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA PRTS("MHz ROM=$") LD HL,ROMSIZE CALL PRTDEC PRTS("KB RAM=$") LD HL,RAMSIZE CALL PRTDEC PRTS("KB$") ; ; INITIALIZE HEAP STORAGE VARIABLES ; LD DE,HB_END ; GET ADDRESS OF START OF HEAP ; ; HEAP STARTS AT END OF HBIOS LD HL,HCB + HCB_HEAP ; POINT TO HEAP START ADDRESS VARIABLE LD (HL),E ; SAVE LSB INC HL ; BUMP LD (HL),D ; SAVE MSB ; ; INIT HEAP TOP TO HEAP START LD HL,HCB + HCB_HEAPTOP ; POINT TO HEAP TOP ADDRESS VARIABLE LD (HL),E ; SAVE LSB INC HL ; BUMP LD (HL),D ; SAVE MSB ; ; CLEAR HEAP LD HL,HB_END ; START OF HEAP LD BC,BNKTOP - HB_END ; MAX SIZE OF HEAP LD A,$FF ; FILL WITH $FF CALL FILL ; DO IT ; ; PERFORM DEVICE INITIALIZATION ; LD B,HB_INITTBLLEN LD DE,HB_INITTBL INITSYS1: ;CALL NEWLINE 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,(HCB + HCB_HEAPTOP) LD (HEAPCURB),HL ; ; 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 ; CONSOLE DEVICE IS UNIT #0 BY FIAT LD (HCB + HCB_CONDEV),A ; SAVE IT, ACTIVATES CONSOLE ON HBIOS ; ; NOW SWITCH TO CRT CONSOLE IF CONFIGURED ; #IF CRTACT ; ; 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)) IN A,(RTC) ; RTC PORT, BIT 6 HAS STATE OF CONFIG JUMPER BIT 6,A ; BIT 6 HAS CONFIG JUMPER STATE JR Z,INITSYS2 ; Z=SHORTED, BYPASS CONSOLE SWITCH #ENDIF ; ; NOTIFY USER OF CONSOLE SWITCH ON BOOT CONSOLE CALL NEWLINE CALL NEWLINE PRTX(STR_SWITCH) CALL NEWLINE ; ; SWITCH TO CRT CONSOLE LD A,(HCB + HCB_CRTDEV) ; GET CRT DISPLAY DEVICE LD (HCB + HCB_CONDEV),A ; SAVE IT AS ACTIVE CONSOLE DEVICE ; ; DISPLAY HBIOS BANNER ON NEW CONSOLE PRTX(STR_BANNER) #ENDIF ; INITSYS2: ; CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE ; RET ; ;================================================================================================== ; TABLE OF INITIALIZATION ENTRY POINTS ;================================================================================================== ; HB_INITTBL: #IF (ASCIENABLE) .DW ASCI_INIT #ENDIF #IF (UARTENABLE) .DW UART_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 (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 #IF (FDENABLE) CALL FD_IDLE #ENDIF 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,(HBX_STACK - HBX_STKSIZ + $08) CP $FF CALL NZ,PANIC LD A,$FF LD (HBX_STACK - HBX_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 ; ;================================================================================================== ; CHARACTER I/O DEVICE DISPATCHER ;================================================================================================== ; ; ROUTE CALL TO SPECIFIED CHARACTER I/O DRIVER ; B: FUNCTION ; C: UNIT NUMBER ; CIO_DISPATCH: ; ; ON ENTRY C IS HBIOS UNIT # (INDEX INTO CIO_TBL OF CHARACTER DEVICES) ; USE UNIT # IN C TO LOOKUP CIO_TBL ENTRY, THEN ; CONVERT C TO THE DEVICE/DRIVER SPECIFIC UNIT ID ; AND GET THE DEVICE TYPE TO A FOR DRIVER DISPATCHING ; PUSH IY ; SAVE INCOMING IY LD A,C ; INCOMING UNIT INDEX TO A PUSH HL ; SAVE INCOMING HL LD HL,CIO_CNT ; HL := ADDRESS OF TABLE ENTRY COUNT PREFIX CP (HL) ; COMPARE TO INCOMING ENTRY INDEX JR C,CIO_DISPATCH1 ; UNIT OK, PROCEED CP CIODEV_CONSOLE ; CHECK FOR SPECIAL VALUE - CONSOLE OUTPUT JR Z,CIO_DISPATCH_CON ; DO IT ; ; NOT GOOD, INCOMING UNIT IS OUT OF RANGE POP HL ; RESTORE HL/STACK CALL PANIC ; PANIC OR $FF ; SIGNAL ERROR RET ; AND RETURN ; CIO_DISPATCH_CON: LD A,(HCB + HCB_CONDEV) ; PUT CONSOLE UNIT NUMBER IN A ; FALL THRU ; CIO_DISPATCH1: ; ; SET HL := TABLE ENTRY ADDRESS INC HL ; BUMP PAST COUNT PREFIX TO START OF TABLE ENTRIES RLCA ; MULTIPLY UNIT # BY 4 TO RLCA ; ... TO CALC ENTRY OFFSET CALL ADDHLA ; HL := ADDRESS OF ENTRY IN TABLE ; ; GET FIRST WORD OF TABLE ENTRY AND SAVE FOR DRIVER CALL LD A,(HL) ; DEREFERENCE INC HL ; ... PUSH HL ; SAVE IT FOR BELOW LD H,(HL) ; ... LD L,A ; ... SO HL HAS ADDRESS OF DRIVER DISPATCH LD (CIO_TGTADR),HL ; SAVE THE TARGET ADDRESS TO CALL LATER ; ; GET SECOND WORD OF TABLE ENTRY AND PUT IN IY FOR DRIVER CALL POP HL ; GET TABLE ENTRY ADDRESS BACK INC HL ; INCREMENT TO DATA WORD LD A,(HL) ; GET DATA WORD INC HL ; ... LD H,(HL) ; ... LD L,A ; ... INTO HL PUSH HL ; AND COPY IT POP IY ; ... TO IY ; ; CALL DRIVER (ADDRESS BYTES OF CALL INSTRUCTION UPDATED ABOVE) POP HL ; GET ORIGINAL HL BACK (10) CALL PANIC ; CALL DRIVER DISPATCH ENTRY CIO_TGTADR .EQU $ - 2 ; REFERENCE TO ADDRESS OF CALL INSTRUCTION POP IY ; RESTORE ORIGINAL IY RET ; AND RETURN ; ; 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. ; EACH ENTRY IS DEFINED AS: ; ; WORD DRIVER DISPATCH ENTRY ADDRESS ; WORD UNIT SPECIFIC DATA (MAY BE AN ADDRESS) ; CIO_MAX .EQU 16 ; UP TO 16 UNITS CIO_SIZ .EQU CIO_MAX * 4 ; EACH ENTRY IS 4 BYTES ; .DB CIO_MAX ; MAX ENTRY COUNT TABLE PREFIX CIO_CNT .DB 0 ; ENTRY COUNT PREFIX CIO_TBL .FILL CIO_SIZ,0 ; SPACE FOR ENTRIES ; ; 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 ; ;================================================================================================== ; DISK I/O DEVICE DISPATCHER ;================================================================================================== ; ; ROUTE CALL TO SPECIFIED DISK I/O DRIVER ; B: FUNCTION ; C: UNIT NUMBER ; ;NDIO_NEWDISP: ; ; START OF THE ACTUAL DRIVER DISPATCHING LOGIC ; PUSH IY ; SAVE ORIGINAL IY ; PUSH HL ; SAVE HL ; LD HL,NDIO_RET ; GET RETURN VECTOR ; EX (SP),HL ; RECOVER HL & PUT RETURN VECTOR ON TOS ; PUSH HL ; SAVE HL ; LD HL,DIO_TBL ; POINT TO DISPATCH TABLE ; LD A,C ; GET REQUESTED UNIT FROM C ; RLCA ; MULTIPLY UNIT BY 4 ; RLCA ; ... TO GET BYTE OFFSET OF ENTRY ; CALL ADDHLA ; HL -> ENTRY ADDRESS ; LD A,(HL) ; DRIVER ID TO A ; PUSH AF ; SAVE IT FOR NOW ; INC HL ; POINT TO UNIT ; LD C,(HL) ; PUT IT IN C FOR DRIVER ; INC HL ; POINT TO LSB OF UNIT DATA ADDRESS ; LD A,(HL) ; HL := UNIT DATA ADDRESS ; INC HL ; ... ; LD H,(HL) ; ... ; LD L,A ; ... ; POP AF ; RECOVER DRIVER ID ; EX (SP),HL ; RECOVER ORIG HL & PUT UNIT DATA ADDRESS TO TOS ; POP IY ; IY := UNIT DATA ADDRESS ; JP NDIO_DISPATCH2 ; USE LEGACY DISPATCHER ;; ;NDIO_RET: ; POP IY ; RECOVER IY ; OR A ; MAKE SURE FLAGS ARE SET ; RET ; AND RETURN 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 DIO_DISPCALL: ; #ENDIF ; *DEBUG* END ; ; ON ENTRY C IS HBIOS UNIT # (INDEX INTO DIO_TBL OF DISK DEVICES) ; USE UNIT # IN C TO LOOKUP DIO_TBL ENTRY, THEN ; CONVERT C TO THE DEVICE/DRIVER SPECIFIC UNIT ID ; AND GET THE DEVICE TYPE TO A FOR DRIVER DISPATCHING ; LD A,C ; INCOMING UNIT INDEX TO A PUSH HL ; SAVE INCOMING HL LD HL,DIO_CNT ; HL := ADDRESS OF TABLE ENTRY COUNT CP (HL) ; COMPARE TO INCOMING ENTRY INDEX JR C,DIO_DISPATCH1 ; UNIT OK, PROCEED ; ; NOT GOOD, INCOMING UNIT IS OUT OF RANGE POP HL ; RESTORE HL/STACK CALL PANIC ; PANIC OR $FF ; SIGNAL ERROR RET ; AND RETURN ; DIO_DISPATCH1: INC HL ; BUMP PAST COUNT PREFIX TO START OF TABLE RLCA ; MULTIPLY BY 4 TO RLCA ; ... TO CALC ENTRY OFFSET CALL ADDHLA ; HL := ENTRY OFFSET LD A,(HL) ; GET DEVICE TYPE BYTE INC HL ; BUMP TO DEVICE UNIT INDEX BYTE LD C,(HL) ; DEVICE UNIT INDEX TO C POP HL ; RECOVER INCOMING HL VALUE ; ; DISPATCH TO DRIVER BASED ON DEVICE TYPE IN A ; #IF (MDENABLE) CP DIODEV_MD JP Z,MD_DISPATCH #ENDIF #IF (FDENABLE) CP DIODEV_FD JP Z,FD_DISPATCH #ENDIF #IF (RFENABLE) CP DIODEV_RF JP Z,RF_DISPATCH #ENDIF #IF (IDEENABLE) CP DIODEV_IDE JP Z,IDE_DISPATCH #ENDIF #IF (PPIDEENABLE) CP DIODEV_PPIDE JP Z,PPIDE_DISPATCH #ENDIF #IF (SDENABLE) CP DIODEV_SD JP Z,SD_DISPATCH #ENDIF #IF (PRPENABLE) #IF (PRPSDENABLE) CP DIODEV_PRPSD JP Z,PRPSD_DISPATCH #ENDIF #ENDIF #IF (PPPENABLE) #IF (PPPSDENABLE) CP DIODEV_PPPSD JP Z,PPPSD_DISPATCH #ENDIF #ENDIF #IF (HDSKENABLE) CP DIODEV_HDSK JP Z,HDSK_DISPATCH #ENDIF CALL PANIC RET ; ; 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: ; ;; DEBUG: DUMP INCOMING TRACK:HEAD/SEC ;CALL NEWLINE ;PUSH BC ;PUSH HL ;POP BC ;CALL PRTHEXWORD ;CALL PC_COLON ;PUSH DE ;POP BC ;CALL PRTHEXWORD ;POP BC ; ; WE HAVE INCOMING HARDDISK CHS, CONVERT TO LBA ; HL=TRACK (0..N), D=HEAD (0..15), E=SECTOR (0..15) ; XLAT HL:DE (TT:HS) --> 32 BIT LBA (LBAHI:LBALO) ; ; D/E -> A (COMBINE HEAD/SEC AND SAVE IN A) ; 0 -> D ; H -> E ; L -> H ; A -> L ; 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 ; ;; DEBUG: DUMP RESULTING LBA (32 BIT) ;PRTS("-->$") ;PUSH BC ;PUSH DE ;POP BC ;CALL PRTHEXWORD ;PUSH HL ;POP BC ;CALL PRTHEXWORD ;POP BC ; XOR A RET ; ; 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. ; EACH ENTRY IS DEFINED AS: ; ; BYTE DEVICE TYPE ID ; BYTE DEVICE/DRIVER UNIT NUMBER ; WORD UNIT DATA ADDRESS ; DIO_MAX .EQU 16 ; UP TO 16 UNITS DIO_SIZ .EQU DIO_MAX * 4 ; EACH ENTRY IS 4 BYTES ; .DB DIO_MAX ; MAX ENTRY COUNT TABLE PREFIX DIO_CNT .DB 0 ; ENTRY COUNT PREFIX DIO_TBL .FILL DIO_SIZ,0 ; SPACE FOR ENTRIES ; ; 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 ; ;================================================================================================== ; 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: ; LD A,C ; REQUESTED DEVICE/UNIT IS IN C ; AND $F0 ; ISOLATE THE DEVICE PORTION ; ; ON ENTRY C IS HBIOS UNIT # (INDEX INTO VDA_TBL OF VIDEO DEVICES) ; USE UNIT # IN C TO LOOKUP VDA_TBL ENTRY, THEN ; CONVERT C TO THE DEVICE/DRIVER SPECIFIC UNIT ID ; AND GET THE DEVICE TYPE TO A FOR DRIVER DISPATCHING ; LD A,C ; INCOMING UNIT INDEX TO A PUSH HL ; SAVE INCOMING HL LD HL,VDA_CNT ; HL := ADDRESS OF TABLE ENTRY COUNT CP (HL) ; COMPARE TO INCOMING ENTRY INDEX JR C,VDA_DISPATCH1 ; UNIT OK, PROCEED ; ; NOT GOOD, INCOMING UNIT IS OUT OF RANGE POP HL ; RESTORE HL/STACK CALL PANIC ; PANIC OR $FF ; SIGNAL ERROR RET ; AND RETURN ; VDA_DISPATCH1: INC HL ; BUMP PAST COUNT PREFIX TO START OF TABLE RLCA ; MULTIPLY BY 4 TO RLCA ; ... TO CALC ENTRY OFFSET CALL ADDHLA ; HL := ENTRY OFFSET LD A,(HL) ; GET DEVICE TYPE BYTE INC HL ; BUMP TO DEVICE UNIT INDEX BYTE LD C,(HL) ; DEVICE UNIT INDEX TO C POP HL ; RECOVER INCOMING HL VALUE ; ; DISPATCH TO DRIVER BASED ON DEVICE TYPE IN A ; #IF (VDUENABLE) CP VDADEV_VDU JP Z,VDU_DISPATCH #ENDIF #IF (CVDUENABLE) CP VDADEV_CVDU JP Z,CVDU_DISPATCH #ENDIF #IF (NECENABLE) CP VDADEV_7220 JP Z,NEC_DISPATCH #ENDIF #IF (TMSENABLE) CP VDADEV_TMS JP Z,TMS_DISPATCH #ENDIF CALL PANIC ; ; 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. ; EACH ENTRY IS DEFINED AS: ; ; BYTE DEVICE TYPE ID ; BYTE DEVICE/DRIVER UNIT NUMBER ; WORD UNIT DATA ADDRESS ; VDA_MAX .EQU 16 ; UP TO 16 UNITS VDA_SIZ .EQU VDA_MAX * 4 ; EACH ENTRY IS 4 BYTES ; .DB VDA_MAX ; MAX ENTRY COUNT TABLE PREFIX VDA_CNT .DB 0 ; ENTRY COUNT PREFIX VDA_TBL .FILL VDA_SIZ,0 ; SPACE FOR ENTRIES ; ; 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 ; ;================================================================================================== ; 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 CALL PANIC ; INVALID ; ; 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,HBX_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,(HBX_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 ;; *DEBUG* START ;PUSH AF ;PUSH BC ;PUSH DE ;PUSH HL ; ;CALL NEWLINE ; ;LD A,(HB_SRCBNK) ;CALL PRTHEXBYTE ;CALL PC_COLON ;PUSH BC ;PUSH HL ;POP BC ;CALL PRTHEXWORD ;POP BC ;CALL PC_SPACE ;LD A,(HB_DSTBNK) ;CALL PRTHEXBYTE ;CALL PC_COLON ;PUSH BC ;PUSH DE ;POP BC ;CALL PRTHEXWORD ;POP BC ;CALL PC_SPACE ;CALL PRTHEXWORD ;POP HL ;POP DE ;POP BC ;POP AF ; *DEBUG* END CALL BNKCPY XOR A RET ; ; ALLOCATE HL BYTES OF MEMORY FROM HBIOS HEAP ; RETURNS POINTER TO ALLOCATED MEMORY IN HL ; ON SUCCESS RETURN A == 0, AND Z SET ; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED ; ALL OTHER REGISTERS PRESERVED ; SYS_ALLOC: JP HB_ALLOC ; ; FREE HEAP MEMORY BY SIMPLY RELEASING ALL ; MEMORY BEYOND POINTER IN HL. ; ON SUCCESS RETURN A == 0, AND Z SET ; ON FAILURE A <> 0 AND NZ SET AND HL TRASHED ; ALL OTHER REGISTERS PRESERVED ; SYS_FREE: CALL PANIC ; NOT YET IMPLEMENTED OR $FF 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 ; ; 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_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 BOOT INFORMATION ; RETURNS: ; L: BOOT BANK ID ; DE: BOOT DISK VOLUME (UNIT/SLICE) ; SYS_GETBOOTINFO: LD A,(HCB + HCB_BOOTBID) LD L,A LD DE,(HCB + HCB_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,(HCB + HCB_CPUMHZ) LD L,A LD DE,(HCB + HCB_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,(HCB + HCB_BIDBIOS) LD D,A LD A,(HCB + HCB_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_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 (HCB + HCB_BOOTBID),A LD (HCB + HCB_BOOTVOL),DE XOR A RET ; ; RETURN A BYTE OF MEMORY FROM SPECIFIED BANK ; ENTRY: D=BANK ID, HL=ADDRESS ; RETURN: E=BYTE VALUE ; SYS_PEEK: CALL HBX_PEEK ; IMPLEMENTED IN PROXY 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: CALL HBX_POKE ; IMPLEMENTED IN PROXY XOR A RET ; ; SOFT RESET HBIOS, RELEASE HEAP MEMORY NOT USED BY HBIOS ; SYS_RESET: LD HL,(HEAPCURB) ; GET HBIOS HEAP THRESHOLD LD (HCB + HCB_HEAPTOP),HL ; RESTORE HEAP TOP XOR A RET ;; ;; GET HCB VALUE BYTE ;; C: HCB INDEX (OFFSET INTO HCB) ;; RETURN BYTE VALUE IN E ;; ;SYS_HCBGETB: ; CALL SYS_HCBPTR ; LOAD HL WITH PTR ; LD E,(HL) ; GET BYTE VALUE ; RET ; DONE ;; ;; PUT HCB VALUE BYTE ;; C: HCB INDEX (OFFSET INTO HCB) ;; E: VALUE TO WRITE ;; ;SYS_HCBPUTB: ; CALL SYS_HCBPTR ; LOAD HL WITH PTR ; LD (HL),E ; PUT BYTE VALUE ; RET ;; ;; GET HCB VALUE WORD ;; C: HCB INDEX (OFFSET INTO HCB) ;; RETURN WORD VALUE IN DE ;; ;SYS_HCBGETW: ; CALL SYS_HCBPTR ; LOAD HL WITH PTR ; LD E,(HL) ; GET BYTE VALUE ; INC HL ; LD D,(HL) ; GET BYTE VALUE ; RET ; DONE ;; ;; PUT HCB VALUE WORD ;; C: HCB INDEX (OFFSET INTO HCB) ;; DE: VALUE TO WRITE ;; ;SYS_HCBPUTW: ; CALL SYS_HCBPTR ; LOAD HL WITH PTR ; LD (HL),E ; PUT BYTE VALUE ; INC HL ; LD (HL),D ; PUT BYTE VALUE ; RET ; ;; CALCULATE REAL ADDRESS OF HCB VALUE FROM HCB OFFSET ;; ;SYS_HCBPTR: ; LD A,C ; LOAD INDEX (HCB OFFSET) ; LD HL,HCB ; GET HCB ADDRESS ; JP ADDHLA ; CALC REAL ADDRESS AND RET ; ;================================================================================================== ; 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 ; ; TIMER INTERRUPT ; HB_TIMINT: RET ; ; BAD INTERRUPT HANDLER ; HB_BADINT: RET ; ; WRAPPER FOR CALL TO HB_BNKCPY FOR USE BY INTERNAL HBIOS FUNCTIONS ; BNKCPY .EQU HB_BNKCPY ; ; ADD AN ENTRY TO THE UNIT TABLE AT ADDRESS IN HL ; C: DEVICE TYPE ID ; B: UNIT INDEX ; DE: ADDRESS OF UNIT 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 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,(HCB + HCB_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,(HCB + HCB_HEAPTOP) ; GET ORIGINAL HEAP TOP LD (HCB + HCB_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 (UARTENABLE) ORG_UART .EQU $ #INCLUDE "uart.asm" SIZ_UART .EQU $ - ORG_UART .ECHO "UART occupies " .ECHO SIZ_UART .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 (VDUENABLE) ORG_VDU .EQU $ #INCLUDE "vdu.asm" SIZ_VDU .EQU $ - ORG_VDU .ECHO "VDU occupies " .ECHO SIZ_VDU .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 (NECENABLE) ORG_NEC .EQU $ ;#INCLUDE "nec.asm" SIZ_NEC .EQU $ - ORG_NEC .ECHO "NEC occupies " .ECHO SIZ_NEC .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 (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 ; #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 ; #IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2)) ; ; DETECT Z80 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: ; WATT FOR AN INITIAL TICK TO ALIGN, THEN WAIT ; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT CALL HB_WAITSECS ; WAIT FOR INITIAL SECS TICK CALL HB_WAITSECS ; WAIT FOR SECS TICK AGAIN, COUNT INDE ; LD A,H OR L RET Z ; FAILURE, USE DEFAULT CPU SPEED ; ; TIMES 4 (W/ ROUNDING) FOR CPU SPEED IN KHZ INC HL SRL H RR L SLA L RL H SLA L RL H SLA L RL H ; LD (HCB + HCB_CPUKHZ),HL LD DE,1000 CALL DIV16 LD A,C LD (HCB + HCB_CPUMHZ),A ; RET ; HB_WAITSECS: ; WAIT FOR SECONDS TICK ; RETURN SECS VALUE IN A, LOOP COUNT IN DE ; LOOP TARGET IS 250 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4 LD HL,0 ; INIT LOOP COUNTER CALL HB_RDSEC ; GET SECONDS LD E,A ; SAVE IT HB_WAITSECS1: CALL DLY32 CALL DLY8 CALL DLY4 JP $ + 3 ; 10 TSTATES ; LD A,R ; 9 TSTATES ; INC BC ; 6 TSTATES NOP ; 4 TSTATES NOP ; 4 TSTATES NOP ; 4 TSTATES NOP ; 4 TSTATES NOP ; 4 TSTATES ; CALL HB_RDSEC ; GET SECONDS INC HL ; BUMP COUNTER CP E ; EQUAL? RET NZ ; DONE IF TICK OCCURRED LD A,H ; CHECK HL OR L ; ... FOR OVERFLOW RET Z ; TIMEOUT, SOMETHING IS WRONG JR HB_WAITSECS1 ; LOOP ; HB_RDSEC: ; READ SECONDS BYTE INTO A LD C,$81 ; SECONDS REGISTER HAS CLOCK HALT FLAG CALL DSRTC_CMD ; SEND THE COMMAND CALL DSRTC_GET ; READ THE REGISTER CALL DSRTC_END ; FINISH IT RET ; #ELSE ; RET ; NO RTC, ABORT ; #ENDIF ; #ENDIF ; ; #IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4)) ; ; DETECT Z180 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: ; WATT FOR AN INITIAL TICK TO ALIGN, THEN WAIT ; FOR SECOND TICK AND TO GET A FULL ONE SECOND LOOP COUNT CALL HB_WAITSECS ; WAIT FOR INITIAL SECS TICK CALL HB_WAITSECS ; WAIT FOR SECS TICK AGAIN, COUNT INDE ; LD A,H OR L RET Z ; FAILURE, USE DEFAULT CPU SPEED ; ; TIMES 8 FOR CPU SPEED IN KHZ SLA L RL H SLA L RL H SLA L RL H ; LD (HCB + HCB_CPUKHZ),HL LD DE,1000 CALL DIV16 LD A,C LD (HCB + HCB_CPUMHZ),A ; RET ; HB_WAITSECS: ; WAIT FOR SECONDS TICK ; RETURN SECS VALUE IN A, LOOP COUNT IN DE ; LOOP TARGET IS 250 T-STATES, SO CPU FREQ IN KHZ = LOOP COUNT * 4 LD HL,0 ; INIT LOOP COUNTER CALL HB_RDSEC ; GET SECONDS LD E,A ; SAVE IT HB_WAITSECS1: CALL DLY64 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 ; CALL HB_RDSEC ; GET SECONDS INC HL ; BUMP COUNTER CP E ; EQUAL? RET NZ ; DONE IF TICK OCCURRED LD A,H ; CHECK HL OR L ; ... FOR OVERFLOW RET Z ; TIMEOUT, SOMETHING IS WRONG JR HB_WAITSECS1 ; LOOP ; HB_RDSEC: ; READ SECONDS BYTE INTO A LD C,$81 ; SECONDS REGISTER HAS CLOCK HALT FLAG CALL DSRTC_CMD ; SEND THE COMMAND CALL DSRTC_GET ; READ THE REGISTER CALL DSRTC_END ; FINISH IT RET ; #ELSE ; RET ; NO RTC, ABORT ; #ENDIF ; #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 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 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:=DISK 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 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 C, ATTRIBUTE IN E) ; 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 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 RLCA ; SHIFT RELEVANT BITS RLCA ; ... RLCA ; ... 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 RLCA ; SHIFT RELEVANT BITS RLCA ; ... 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 CALL PC_SPACE 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_SDUART .TEXT "UART$" PS_SDASCI .TEXT "ASCI$" PS_SDTERM .TEXT "TERM$" PS_SDPRPCON .TEXT "PRPCON$" PS_SDPPPCON .TEXT "PPPCON$" ; ; 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_VDVDU .TEXT "VDU$" PS_VDCVDU .TEXT "CVDU$" PS_VDNEC .TEXT "NEC$" PS_VDTMS .TEXT "TMS$" ; ; 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 ; OUTPUT CHAR TO E LD A,(HCB + HCB_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,(HCB + HCB_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 PANIC ; NOT YET SUPPORTED ; 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,(HCB + HCB_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 PANIC ; NOT YET SUPPORTED ; CST2: ; RESTORE REGISTERS (AF IS OUTPUT) POP HL POP DE POP BC RET ; ;================================================================================================== ; HBIOS GLOBAL DATA ;================================================================================================== ; IDLECOUNT .DB 0 ; ; THE HOST (HST) VALUES BELOW INDICATE THE DISK AND BLOCK CURRENTLY ; ADDRESSED FOR READ/WRITE OPERATIONS. ; THE 32-BIT BLOCK ADDRESS CAN BE TREADED AS EITHER CHS OR LBA, HIGH ORDER BIT ON SIGNIFIES LBA ; CHS: ; .DW 0 ; TRACK (0-65535) ; .DB 0 ; SECTOR (0-255) ; .DB 0 ; HEAD (0-127) ; ; LBA: ; .DW 0 ; LBA LOW WORD ; .DW 0 ; LBA HIGH WORD ; ; FULL 32 BIT LBA HSTLBA .EQU $ ; REFERS TO START OF 32-BIT LBA ; LBA LOW WORD -OR- TRACK HSTLBALO .EQU $ ; BLOCK ADDRESS LBA LOW WORD HSTTRK .DW 0 ; CYLINDER (0-65535) ; LBA HIGH WORD -OR- HEAD/SECTOR HSTLBAHI .EQU $ ; BLOCK ADDRESS LBA HIGH WORD HSTSEC .DB 0 ; SECTOR (0-255) HSTHEAD .DB 0 ; HEAD (0-255) ; HEAPCURB .DW 0 ; MARK HEAP ADDRESS AFTER INITIALIZATION ; HB_INTSTKSAV .DW 0 ; SAVED STACK POINTER DURING INT PROCESSING .FILL $40,$FF ; 32 ENTRY STACK FOR INTERRUPT PROCESSING HB_INTSTK .EQU $ ; TOP OF INTERRUPT PROCESSING STACK ; STR_BANNER .DB "RetroBrew HBIOS v", BIOSVER, ", ", TIMESTAMP, "$" STR_PLATFORM .DB PLATFORM_NAME, "$" STR_SWITCH .DB "*** Activating CRT Console ***$" ; HB_BCDTMP .FILL 5,0 ; TEMPORARY BCD NUMBER STORAGE ; HB_WRKBUF .FILL 512,0 ; INTERNAL DISK BUFFER ; HB_END .EXPORT HB_END ; EXPORT ENDING ADDRESS ; SLACK .EQU BNKTOP - $ .ECHO "HBIOS space remaining: " .ECHO SLACK .ECHO " bytes.\n" ; .END