TITLE DIGITAL GROUP/BIG BOARD Z-80 MONITOR 'DGMON' LIST NOCOND ;************************************************************* ; ; SYSTEM MONITOR FOR Z80 ; (c) 1982,1983 GRH ELECTRONICS, CUPERTINO, CA ; ;************************************************************* ; ; This Monitor program resides at the top of memory & ; allows memory modification & testing, program breakpoints, ; console, printer, punch & reader I/O drivers and transfer to ; system boot ROM residing in same memory area as this ROM. ; ;************************************************************* ; ; Revision status: ; ; 1.0 - Release ; ; 1.1 - 14 JUL 85 GRH ; Changed variable initialization philosophy to constants, assuming ; 64k system ram is allways present. Old version dynamically allocated ; variable space depending on top of available ram. ; Fix bug in 'G'oto command which transposed IX & IY register images. ; Added tests for 'F'ill & 'M'ove commands to abort operation if ; monitor area is about to be compromised. 'S'ubstitute will still ; allow monitor area to be modified if needed. Old version assumed ; monitor was in rom and not alterable, so didn't bother to check. ; Changed examine & change register table to reflect constant location ; for variables philosophy. ; Changed exit routine to enable interrupts before executing program ; to allow for keyboard abort. ; Change sign-on message to a constant memory value. ; Fix bug in e'X'amine register command which did not treat the 'M' ; register correctly. 'M' or ''M' now allows setting (HL). ; ; 1.2 - 18 AUG 85 GRH ; Implement overlay approach for commands to make more room for ; features & I/O drivers. Overlays reside in the 2nd 2k of the ROM in ; the base page of ROM area. Implement the real time clock & cassette ; 'L'oad / 'U'nload commands. ; ; 1.3 - 8 OCT 85 GRH ; Add disk read, write & boot commands. ; Add help command ; VERSN EQU '13' ; ;************************************************************* FORM FALSE EQU 0 TRUE EQU NOT FALSE ;INCLUDE BB.DEF ;INCLUDE BBDISK.DEF LIST OFF *INCLUDE BB.DEF *INCLUDE BBDISK.DEF LIST ON ;============================ ; ; COMPILE TIME VARS ; ;============================ ROM EQU 0F800H ;ROM START ADDR NBKPTS EQU 2 ;MAX NUMBER OF BREAKPOINTS ALLOWED OVLSIZ EQU 512 ;MAX SIZE OF OVERLAYS ;============================ ; ; I/O ROM ENTRY VECTORS ; ;============================ ORG IOROM VIDINIT DS 3 ;VIDEO OUTPUT INITIALIZATION VIDOUT DS 3 ;OUTPUT CHAR IN C FUNCTION KBINIT DS 3 ;KEYBOARD INIT FUNCTION, LOW INTVEC IN C KBDIN DS 3 ;RETURN NEXT KEYBOARD CHAR IN A FUNCTION KBDST DS 3 ;RETURN 0: NOT READY, FFH: CHAR WAITING IN A KBDINT DS 3 ;KEYBOARD INTERRUPT ROUTINE ; DKBOOTV DS 3 ;DISK BOOT XCUTE DS 3 ;EXECUTE IOPB FUNCTION RETIOPB DS 3 ;RETURN IOPB PTR IN HL FUNCTION ;============================ ; ; MEMORY LOCATIONS ; ;============================ WSVEC EQU 0000H ;VECTOR NUMBER FOR WARM RESTART ;============================ ; ; CONSTANTS ; ;============================ BELL EQU 7 LF EQU 0AH CR EQU 0DH CTRLS EQU 13H ;ASCII DC3 ;============================ ; ; VARIABLE AREA ; ;============================ ORG ROM - 256 USRSTK EQU $ ;START OF USER STACK UPON GOTO MONVARS EQU $ ;START OF MONITOR VARIABLE AREA STKTRAP DS 2 ;LOCATION FOR RS9 VECTOR UPON GOTO MONSTK EQU $ ;MONITOR STACK START ; ; REGISTER IMAGES ; RLOC DS 1 ;REFRESH ILOC DS 1 ;INTERRUPT YLOC DS 2 ;IY XLOC DS 2 ;IX FPLOC DS 1 ;FLAGS' APLOC DS 1 ;A' CPLOC DS 1 ;C' BPLOC DS 1 ;B' EPLOC DS 1 ;E' DPLOC DS 1 ;D' LPLOC DS 1 ;L' HPLOC DS 1 ;H' ELOC DS 1 ;E DLOC DS 1 ;D CLOC DS 1 ;C BLOC DS 1 ;B FLOC DS 1 ;FLAGS ALOC DS 1 ;A SLOC DS 2 ;SP ; ; BREAKPOINTS ; TLOC: REPT NBKPTS DS 2 ;BREAKPOINT ADDRESS DS 1 ;BREAKPOINT DATA (INSTRUCTION REPLACED BY RST8) ENDM ; ; ALL THE FOLLOWING IS NOT INITIALIZED TO 0 ; SPSV DS 2 ;STACK PTR SAVE LOCATION ; ; INTERRUPT STACK ; DS 24 ISTACK EQU $ ISPSAV DS 2 ; ; I/O LOCAL STACK ; IOSTACK EQU AUXMEM + 2048 ;PUT STACK IN AUX RAM SINCE AVAILABLE IOSPSAV DS 2 ;PUT STACK PTR HERE SO ACCESSIBLE FOR RETURN ; VALUE STORAGE AS WELL. ; ; MONITOR STATUS BITS ; MONSTAT DS 1 ; 7 0 ; |IES| 0 | 0 | 0 |RAS| 0 | 0 | 0 | ; ^ ^________________ 0: ROM ENABLED, 1: RAM ENABLED ; |________________________________ INTERRUPTS 0: DISABLED, 1: ENABLED ; RAMSTAT EQU 3 ;RAM ENABLED BIT INTSTAT EQU 7 ;INTERRUPTS ENABLED BIT ; TEMP DS 2 ;TEMPORARY STORAGE TICKS DS 2 ;CLOCK TICKS ACCUMULATED TIKCNT DS 1 ;CLOCK SECONDS COUNT TOD DS 7 ;CLOCK ARRAY BYTC DS 2 ;CASSETTE BYTE COUNT BYTSR DS 2 ;CASSETTE BYTES READ ; ; DISK IOPB ; IOPB: PBCMD DS 1 ;COMMAND BYTE PBDRV DS 1 ;DRIVE NUMBER BYTE PBTRK DS 2 ;TRACK WORD PBSEC DS 2 ;SECTOR WORD PBFLG DS 1 ;FLAG BYTE PBDMA DS 2 ;XFER ADDRESS START WORD PBDMAX DS 1 ;XFER ADDRESS EXTENDED (NOT USED) PBSTAT DS 1 ;STATUS RETURNED (0: NO ERRORS) DS PBCMD + IOPBSZ - $ ;SPARES TO FILL 16 BYTES OF IOPB IF $ >= (ROM - 128) CONMSG **** Variables run into disk buffer **** ENDIF DS ROM - 128 DBUFF DS 128 ;DISK I/O DATA BUFFER SUBTTL MACROS ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; ; SAVE REGISTERS ; ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ SAVE MACRO PUSH HL PUSH DE PUSH BC ENDM ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; ; RESTORE REGISTERS ; ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ RESTORE MACRO POP BC ;RESTORE USER ENVIRONMENT POP DE POP HL ENDM ;@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; ; INTERRUPT SAVE ; ;@@@@@@@@@@@@@@@@@@@@@@@@@@@ ISAVE MACRO LD (ISPSAV),SP LD SP,ISTACK PUSH HL PUSH DE PUSH BC PUSH AF ENDM ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ; ; INTERRUPT RESTORE ; ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IRESTORE MACRO POP AF POP BC POP DE POP HL LD SP,(ISPSAV) ENDM SUBTTL MAIN PROGRAM ORG ROM ;-------------------------------------- ; ; JUMP TARGETS FOR BASIC I/O ; ;-------------------------------------- CBOOT JP CINIT - ROM ;COLD START CONIN JP CI ;RETURN CHAR FROM CONSOLE IN A FUNCTION JP SUDI ;SUDING FORMAT CASSETTE INPUT FUNCTION CONOUT JP CO ;OUTPUT CHAR IN C TO CONSOLE FUNCTION JP SUDO ;SUDING FORMAT CASSETTE OUTPUT FUNCTION LIST JP LO ;OUTPUT CHAR IN C TO LIST DEVICE FUNCTION CONST JP CSTS ;RETURN CONSOLE STATUS IN A FUNCTION JP SELRAM ;SELECT RAM FUNCTION JP CHKINT ;SET INTERRUPTS TO FLAG FUNCTION JP MEMCK ;RETURN MEMORY LIMIT FUNCTION JP CALLROM ;CALL ROM VECTOR IN HL FUNCTION JP DISPATCH ;CALL INTERRUPT ROM VECTOR IN HL FUNCTION JP REST ;BREAKPOINT ENTRY LPSTAT: JP LSTAT ;RETURN LINE PRINTER STATUS IN A FUNCTION JP SETBACK ;SET & RETURN BACKGROUND VECTOR FUNCTION JP GETTICK ;RETURN TICK COUNT IN HL FUNCTION JP GETCLKP ;RETURN CLOCK ARRAY PTR IN HL FUNCTION ;-------------------------------------- ; ; THE COLD INITIALIZATION CODE ; ;-------------------------------------- INIT: DI LD A,DYSTAT + ON ;DISABLE ROMS, ENABLE RAM OUT (PORT0),A LD (MONSTAT),A ;INTERRUPTS = FALSE TOO LD SP,3FH ;USE STACK TO INIT RESTARTS LD HL,0C300H LD DE,RSTER LD B,16 ;64 BYTES INIT1: PUSH DE PUSH HL DJNZ INIT1 LD SP,MONSTK ;SET UP STACK LD HL,USRMSG ;OUTPUT 'MEMORY= ' CALL PRTWD ; ; CONTINUATION OF THE SCS MONITOR ; LD (SPSV),SP ;SAVE STACK FOR LATER LD B,SPSV - MONVARS LD HL,MONVARS VINITL: LD (HL),0 INC HL DJNZ VINITL LD A,4 ;INIT TICK COUNT LD (TIKCNT),A LD HL,0 ;INIT GOTO JUMP & HL REG IMAGE LD (LLOC),HL LD (PLOC),HL LD HL,USRSTK ;INIT SP REG LD (SLOC),HL ;-------------------------------------- ; ; INSERT I/O INIT CODE HERE ; ;-------------------------------------- LD HL,IOTABL ;INIT PROGRAMMABLE DEVICES INIT3 LD B,(HL) ;FETCH BYTE COUNT INC HL LD C,(HL) ;FETCH PORT # INC HL OTIR BIT 7,(HL) ;IF COUNT > 127 THEN DONE JR Z,INIT3 LD C,CTCAV ;ENABLE KEYBOARD LD HL,KBINIT CALL CALLROM LD A,HIGH INTTBL ;INIT INTERRUPTS LD I,A LD (ILOC),A ;DEFAULT I REGISTER IM 2 LD HL,MONSTAT ;INTERRUPTS ON SET INTSTAT,(HL) EI LD HL,LOGMSG ;OUTPUT SIGN-ON CALL PRTWD ;---------------------------- ; ; THE WARM START CODE ; ;---------------------------- WINIT: LD SP,(SPSV) ;RESTORE THE STACK WINITA: LD HL,WINIT ;PUT RETURN ADDRESS ON STACK PUSH HL LD (WSVEC + 1),HL ;RETURN HERE IF REBOOT LD A,0C3H LD (WSVEC),A CALL CRLF ;NEW LINE CALL DECHO ;GET COMMAND SUB 'A' ;IF CHAR <> 'A' -> 'F' THEN ERR JP C,QPRT CP 'Z' - 'A' + 1 JR NC,QPRT LD B,2 ;PASS IN 2 PARAMS TO HANDLER LD E,A ;SET UP FOR TABLE LOOKUP LD D,0 LD HL,TBL ;OVERLAY_# = (TABLE + OFFSET) ADD HL,DE LD A,(HL) INC A ;IF -1 THEN UNSUPPORTED COMMAND JR Z,QPRT DEC A LD C,A LD HL,OVERLAY ;IF OVERLAY ALREADY INSTALLED THEN EXIT CP (HL) JP Z,OVERLAY + 1 ADD A,A ;COMPUTE OVERLAY ADDRESS LD E,A LD HL,0800H ;2ND HALF OF 4K EPROM ADD HL,DE PUSH BC DI ;NO INTERRUPTS WHILE ACCESSING ROM XOR A,A ;ENABLE ROM OUT (PORT0),A LD A,(HL) ;FETCH PTR TO OVERLAY INC HL LD H,(HL) LD L,A LD DE,OVERLAY ;DEST = OVERLAY AREA LD BC,OVLSIZ LDIR ;MOVE OVERLAY TO BUFFER POP BC LD A,DYSTAT + ON ;TURN OFF ROM OUT (PORT0),A EI LD A,(OVERLAY) ;IF OVERLAY CORRECT THEN EXECUTE IT CP C JP Z,OVERLAY + 1 LD HL,OVLERRM ;ELSE ERROR JP PRTWA ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; MEMCHK FUNCTION RETURNS THE TOP OF AVAILABLE ; MEMORY (LESS 60 BYTES FOR THE MONITOR STACK) ; EXIT - B= HIGH BYTE OF RAM ; A= LOW BYTE OF RAM ; ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MEMCK: LD A,LOW (MONVARS - 60) LD B,HIGH (MONVARS - 60) RET ;++++++++++++++++++++++++++++++++++++++ ; ; EXF SUBR. READS 1 PARAMETER. ; ENTRY- A= PARAMETER 1ST CHAR ; EXIT - STACK= PARAMETER ; ;++++++++++++++++++++++++++++++++++++++ EXF: LD B,1 ;SET 1 PARAM LD HL,0 JR EX1 ;1ST CHAR IN A ALREADY ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; EXPR SUBR. READS PARAMETERS FROM THE CONSOLE & DEVELOPS A 16 ; BIT HEX VALUE FOR EACH ONE. ; A CARRIAGE RETURN WILL TERMINATE THE ENTRY SEQUENCE. ; A BLANK OR COMMA WILL END THE CURRENT PARAMETER ENTRY. ; EACH PARAMETER ONLY TAKES THE LAST 4 DIGITS TYPED IN, ANY EXCESS IS ; DISCARDED. A NON-HEX DIGIT WILL TERMINATE THE ENTRY SEQUENCE & ; CAUSE A WARM BOOT OF THE MONITOR. ; ENTRY- B= # OF PARAMETERS NEEDED ; EXIT - STACK= PARAMETERS ; ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EX3: JR NZ,QPRT ;NON 0 IS ERR EXPR1: DEC B ;IF NO PARAMS THEN RETURN RET Z EXPR: LD HL,0 ;PARAM = 0 EX0: CALL ECHO ;GET NEXT # EX1: LD C,A ;SAVE CHAR FOR LATER CALL NIBBLE JR C,EX2 ;IF NOT NUMBER THEN EXIT ADD HL,HL ;PARAM = PARAM * 16 ADD HL,HL ADD HL,HL ADD HL,HL OR L ;ADD IN NEW DIGIT LD L,A JR EX0 ;GET NEXT ; EX2: EX (SP),HL ;PUT UNDER RETURN ADDR ON STACK PUSH HL LD A,C ;IF LAST CHAR = DELIM THEN EXIT CALL P2C JR NC,EX3 DJNZ QPRT ;ELSE IF MORE REQ'D THEN ERR RET ;ELSE RETURN ;**************************** ; ; OUTPUT QUERY MESSAGE ; ;**************************** QPRT: LD HL,QMSG ;OUTPUT ? MESSAGE JP PRTWD SUBTTL GENERAL PURPOSE SUBROUTINES ;*************************************************************** ; ; CONV ROUTINE CONVERTS THE LOW ORDER NIBBLE OF THE ; ACCUMULATOR TO ITS ASCII EQUIVALENT. ; EXIT - C= 'N' ; ;*************************************************************** CONV: AND 0FH ADD A,90H ;PUT INTO ASCII ZONE DAA ;AH, THE UBIQUITOUS DAA CONVERT ADC A,40H DAA LD C,A RET ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; ECHO ROUTINE READS A BYTE FROM CONSOLE DEVICE & ECHOS ; THE CHAR BACK TO THE CONSOLE DEVICE. ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ DECHO: CALL DASH ;OUTPUT A '-' ECHO: CALL CONI ECH1: PUSH BC LD C,A ;OUTPUT CHAR CALL CONOUT LD A,C ;RESTORE CHAR IN A POP BC RET ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; EXPR3 ROUTINE GETS 3 PARAMETERS, THEN DOES A CR-LF ; EXIT - DE= P1 ; BC= P2 ; HL= P3 ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EXPR3: INC B ;B HAS 2 ALREADY CALL EXPR POP BC POP DE JP CRLFA ;GO DO CRLF ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; HILO ROUTINE INCREMENTS HL. IT THEN CHECKS FOR (& ; DISALLOWS) A WRAP-AROUND SITUATION. ; EXIT - CF= HL + 1 == 0 (WRAP AROUND) ; F= HL - DE ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HILO: INC HL LD A,H ;IF HL = 0 THEN RETURN CF OR L SCF RET Z LD A,E ;ELSE COMPARE HL TO DE SUB L LD A,D SBC A,H RET ;********************************************************** ; ; HILOX ROUTINE INCREMENTS HL, COMPARES IT TO DE & IF ; EQUAL, RETURNS CONTROL TO THE MONITOR EXEC. OTHERWISE, ; CONTROL RETURNS TO THE CALLING ROUTINE. ; ;********************************************************** HILOD: POP DE ;GET RID OF RETURN ADDR RET ;RETURN TO MONITOR HILOXB: INC BC HILOX: CALL HILO JR C,HILOD ;DONE IF CF CALL CONST ;IF NO CONSOLE BREAK THEN OR A ; RETURN RET Z CALL CONI ;IF CHAR <> CTRL-S THEN BREAK CP CTRLS JR NZ,HILOD JP CONI ;ELSE WAIT FOR NEXT CHAR ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; NIBBLE ROUTINE CONVERTS THE ASCII CHARACTERS 0-9 & A-F ; TO THEIR EQUIVALENT HEX VALUE. IF THE CHARACTER IS NOT IN ; RANGE, THE CARRY BIT IS SET TO FLAG THE ERR. ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ NIBBLE: SUB '0' RET C CP 'G' - '0' CCF RET C CP '9' - '0' + 1 CCF RET NC SUB 'A' - '9' - 1 CP 10 RET ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; PCHK ROUTINE READS A CHARACTER FROM THE CONSOLE, THEN ; CHECKS IT FOR A DELIMITER. IF IT IS NOT A DELIMITER, A NON- ; ZERO CONDITION IS RETURNED. IF IT IS A DELIMITER, A ZERO ; CONDITION IS RETURNED. FURTHER, IF THE DELIMITER IS A CR, ; THE CARRY FLAG IS SET. A BLANK OR A COMMA RESETS THE CARRY ; FLAG. ; EXIT - Z CF ; 1 0 : DELIMITER ; 1 1 : CR ; 0 0 : CHARACTER ; 0 1 : NEVER RETURNED ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ PCHK: CALL ECHO P2C: CP ' ' ;IF CHAR = ' ' THEN RETURN RET Z CP ',' ;IF CHAR = ',' THEN RETURN RET Z CP CR ;IF CHAR = CR THEN RETURN CF SCF RET Z CCF ;ELSE RETURN NC RET ;*************************************************************** ; ; REST ROUTINE TRAPS ALL OF THE REGISTER CONTENTS ; WHENEVER A RESTART 1 INSTRUCTION IS EXECUTED. THE TRAPPED ; CONTENTS ARE STORED IN THE SYSTEM STACK AREA FOR LATER ACCESS ; AND USE BY THE GOTO & THE EXAMINE REGISTERS COMMANDS. ; ; ;*************************************************************** REST: DI ;INSERT INTERRUPT DISABLE HERE PUSH HL ;SAVE ALL REGS PUSH DE PUSH BC PUSH AF LD DE,SLOC + 2 ;SET UP PTR TO REGISTER IMAGES LD HL,10 ;GO UP 10 BYTES IN STACK TO RETURN ADDRESS ADD HL,SP ;COMPUTE SP AT TIME OF BREAKPOINT LD B,4 ;DO SP..DE EX DE,HL ;BPSP -> DE, .SP_REG -> HL RS1: DEC HL LD (HL),D ;SAVE REGS IN WORK AREA [SP,AF,BC,DE] DEC HL LD (HL),E POP DE ;NEXT REG DJNZ RS1 ;FALLS OUT WITH HL REG VALUE IN DE LD (LLOC),DE ;SAVE HL VALUE POP BC ;GET BREAKPOINT LOCATION + 1 DEC BC ;BACK UP TO RESTART INSTRUCTION LD SP,MONSTK ;SET THE MONITOR STACK ; ; CHECK FOR BREAKPOINTS ; LD D,NBKPTS LD HL,TLOC RS2: LD A,(HL) SUB C ;SEE IF SOFTWARE TRAP INC HL LD A,(HL) SBC A,B ;MAYBE, TRY REST OF ADDR JR Z,RS5 ;FOUND 1, RESET IT RS3: INC HL ;NOT FOUND, TRY NEXT 1 INC HL DEC D JR NZ,RS2 ; ; UNSET BREAKPOINT ENCOUNTERED ; INC BC ;NONE FOUND ; ; BREAKPOINT FOUND IN TABLE ; RS5: PUSH BC ;BREAK ADDR LD C,'*' ;OUTPUT BREAK INDICATION CALL CONOUT POP HL ;BP LOCATION LD A,HIGH RS9 ;IF A RETURN BREAK THEN SKIP OUTPUT CP H JR Z,RS6 LD (PLOC),HL ;SAVE FOR GOTO CALL LADR ;OUTPUT BP ADDRESS ; ; REMOVE BREAKPOINTS ; RS6: LD HL,TLOC LD BC,NBKPTS * 256 RS7: LD E,(HL) ;FETCH BP ADDR IN DE LD (HL),C ;NULL BP ADDRESS INC HL LD D,(HL) LD (HL),C INC HL LD A,E ;IF LOC = 0 THEN SKIP RESTORE OR D JR Z,RS8 LD A,(HL) ;ELSE RESTORE ORIGINAL INSTR. LD (DE),A RS8: INC HL ;DO NEXT BP DJNZ RS7 ; ; BREAKPOINTS REMOVED, SAVE REMAINING REGS ; LD SP,HPLOC + 1 EX AF,AF' ;NOW SAVE THE Z80 UNIQUES EXX PUSH HL PUSH DE PUSH BC PUSH AF PUSH IX PUSH IY LD A,I LD B,A LD A,R LD C,A PUSH BC LD A,HIGH INTTBL ;RESTORE INTERRUPT VECTORS LD I,A IM 2 EI LD HL,ACTBL ;DISPLAY REGS CALL XG JP WINIT ;RETURN TO MONITOR ; ; IF GOTO EXECUTION ADDRESS IS A SUBROUTINE THEN EXECUTION MAY ; RETURN HERE ; RS9: PUSH HL RST 8 ;FORCE BP ; ; THE GOTO ROUTINE USES THE EXIT ROUTINE TO SET CPU REGISTERS TO THE ; REGISTER VALUES & EXECUTES THE GOTO ADDRESS ; EXIT: POP BC LD A,C LD R,A LD A,B LD I,A POP IY POP IX POP AF POP BC POP DE POP HL EX AF,AF' EXX POP DE POP BC POP AF POP HL LD SP,HL LLOC EQU $ + 1 HLOC EQU $ + 2 LD HL,0 GIE EI ;ENABLE INTERRUPTS ON EXECUTION HERE PLOC EQU $ + 1 JP 0 ;************************************** ; ; NO ARGS, DISPLAY ALL REGS SUBR ; ENTRY- HL= REGISTER TABLE PTR ; ;************************************** XG: LD A,(HL) LD C,A INC A ;IF AT END OF TABLE THEN RETURN RET Z CALL M,CRLF ;NEW LINE IF BIT 7 SET CALL CONOUT CALL DASH CALL PRTVAL CALL BLK INC HL ;NEXT ENTRY JR XG ;************************************************ ; ; PRINT REGISTER VALUE SUBR ; ENTRY- HL= TABLE PTR TO CHAR ; EXIT - DE= PTR TO REG VALUE LOW BYTE ; HL= PTR TO ATTRIB. BYTE ; ;************************************************ PRTVAL: INC HL ;FETCH TABLE POINTER LD E,(HL) INC HL LD A,(HL) ;GET OFFSET & ATTRIBUTES FROM HIGH BYTE OR HIGH (ROM AND 0F000H) LD D,A LD A,(HL) ;NOW FIND ATTRIBUTES LD B,1 ;SINGLE REG VALUE RLCA JR NC,PV1 ;IF SINGLE REG THEN EXIT INC B ;ELSE REG PAIR INC DE ;DO HIGH BYTE 1ST RLCA ;IF NOT (HL) THEN EXIT JR NC,PV1 ; ; INDIRECT, GET VALUE OF PTR TO VALUE ; PUSH HL ;BUILD ADDR IN HL LD A,(DE) LD H,A DEC DE LD A,(DE) LD L,A LD A,(HL) ;GET (HL) VALUE POP HL DJNZ PV2 ;ALLWAYS JUMP PV1: LD A,(DE) ;GET REG CONTENTS PV2: CALL HEX1 ;OUTPUT VALUE DEC DE ;MEM PTR DJNZ PV1 INC DE ;REPOINT TO LOW BYTE OF REGISTER VALUE RET ;--------------------------------------------------------------- ; ; 2 TYPES OF ERRORS ARE DETECTED: A RESTART ERROR; ; & CERTAIN PROGRAM ERRORS (DETERMINED BY ; PARTICULAR ROUTINE WHERE THE ERROR CONDITION WAS ENCOUNTERED) ; EACH CAUSES A UNIQUE MESSAGE TO BE PRINTED, THEN DOES A WARM ; INIT OF THE MONITOR. ; ;--------------------------------------------------------------- ;------------------------------------------- ; ; UNINITIALIZED RESTART ERROR HANDLER ; ;------------------------------------------- RSTER: LD HL,RSTMSG ;--------------------------------- ; ; COMMON ERROR HANDLER ; ENTRY- HL= MESSAGE PTR ; ;--------------------------------- COMERR: CALL PRTWD JP WSVEC ;******************************************************************** ; ; CONI ROUTINE READS THE CONSOLE & STRIPS OFF THE PARITY BIT. ; ;******************************************************************** CONI: CALL CI AND 7FH RTS: RET ;*************************************************************** ; ; PRTWD ROUTINE OUTPUTS AN ASCII STRING ONTO THE CONSOLE. ; THE STRING MUST BE TERMINATED BY BIT 7 SET IN THE LAST CHAR ; OF THE STRING. THE STRING WILL START A NEW LNE (PRTWD) OR ; CONTINUE ON THE SAME LINE (PRTWA). ; ;*************************************************************** PRTWD: CALL CRLF PRTWA: PUSH BC PRTA: LD C,(HL) RES 7,C ;MAKE SURE BIT 7 = 0 CALL CO BIT 7,(HL) ;IF BIT 7 = 1 THEN STOP INC HL JR Z,PRTA PRTB: POP BC RET ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ; EXLF ROUTINE READS 2 PARAMETERS, PUTS THEM INTO THE DE ; & HL REGS, THEN DOES A CR-LF. ; ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EXLF: CALL EXPR POP DE POP HL ;*************************************************************** ; ; CRLF ROUTINE OUTPUTS A CR-LF ON THE CONSOLE DEVICE TO ; START A NEW LINE. ; ;*************************************************************** CRLF: PUSH HL CRLFA: LD HL,CRMSG CALL PRTWA POP HL RET ;*************************************************************** ; ; LADR ROUTINE OUTPUTS THE CONTENTS OF HL ON THE CONSOLE ; EITHER AT THE START OF A NEW LINE (LADRA) OR AT THE CURRENT ; CURSOR LOCATION (LADR). ; ;*************************************************************** LADRA: CALL CRLF LADR: LD A,H CALL HEX1 LD A,L HEX1: PUSH AF RRCA RRCA RRCA RRCA CALL HEX2 POP AF HEX2: CALL CONV JP CO ;********************************************************** ; ; DASH ROUTINE OUTPUTS A '-' TO THE CONSOLE DEVICE ; ;********************************************************** DASH1: CALL HEX1 ;OUTPUT A AS HEX DASH: LD C,'-' JP CO ;*********************** ; ; PRINT ADDR SUBR ; ;*********************** LADRB: CALL LADRA BLK: LD C,' ' ;OUTPUT A SPACE JP CO ;******************************************* ; ; ROM CALLER ; ROM CODE MUST HANDLE INTERRUPT ENABLES ; ENTRY- HL= ROM VECTOR ADDRESS ; EXIT - AF, HL= RETURN VALUES (?) ; ;******************************************* CALLROM: ; ; DISABLE INTERRUPTS WHILE SWAPPING STACKS ; DI ; ; SAVE THIS STACK ; LD (IOSPSAV),SP ;SAVE THIS STACK ; ; SELECT ROM ; LD A,(MONSTAT) ;TELL INTERRUPT ROUTINES WE'RE IN ROM RES RAMSTAT,A LD (MONSTAT),A ; XOR A,A ;DISABLE RAM, ENABLE ROMS & STACK OUT (PORT0),A ; ; SET UP NEW STACK ; LD SP,IOSTACK ; ; NOW ABLE TO INTERRUPT AGAIN ; CALL CHKINT ; ; SAVE ENVIRONMENT ; PUSH DE PUSH BC PUSH HL ;VECTOR -> STACK ; ; EXECUTE ROM VECTOR ; LD HL,ROMRET ;PUT RET ADDRESS ON STACK & FETCH VECTOR EX (SP),HL JP (HL) ;EXECUTE ROM CODE ; ; ROM RETURNS HERE ; ROMRET: ; ; RESTORE CALLER'S ENVIRONMENT ; POP BC ;RESTORE ENVIRONMENT POP DE ; ; NO INTERRUPTS WHILE SWAPPING STACKS ; DI ;DISABLE INTERRUPTS WHILE SWAPPING ENVIRONMENT ; ; RESTORE CALLER'S STACK ; LD SP,(IOSPSAV) ; ; FALL THROUGH TO SELECTING RAM ; ;**************************** ; ; SELECT RAM SUBROUTINE ; (NEEDED FOR BOOTED ROUTINE) ; ;**************************** SELRAM: ; ; SAVE POSSIBLE RETURN VALUE ; LD (IOSPSAV),A ;SAVE RETURN VALUE ; ; SELECT RAM ; LD A,(MONSTAT) ;DO INTERRUPT ROUTINE 1ST SET RAMSTAT,A LD (MONSTAT),A LD A,DYSTAT + ON OUT (PORT0),A ;******************************************* ; ; SELECTIVELY ENABLE INTERRUPTS FUNCTION ; EXIT - ZF= INTERRUPTS DISABLED ; NZ= INTERRUPTS ENABLED ; A= (IOSPSAV) ; ;******************************************* CHKINT: DI ;ASSUME DISABLED LD A,(MONSTAT) BIT INTSTAT,A ;IF INTERRUPTS NOT ENABLED THEN LD A,(IOSPSAV) ; RESTORE RETURN VALUE RET Z ; RETURN ; EI ;ELSE ENABLE INTERRUPTS RET ;******************************************* ; ; DISPATCH TO ROM INTERRUPT VECTOR SUBR ; ENTRY- HL= VECTOR ; ;******************************************* DISPATCH: ISAVE XOR A,A ;SELECT ROM OUT (PORT0),A PUSH HL ;SAVE VECTOR LD HL,DISPATR ;PUT RETURN ADDRESS ON STACK EX (SP),HL JP (HL) ;EXECUTE VECTOR DISPATR: LD A,(MONSTAT) ;IF ROM INTERRUPTED THEN SKIP RAM SELECT OUT (PORT0),A IRESTORE RET SUBTTL CLOCK ROUTINES ;++++++++++++++++++++++++++++++++++++++ ; ; SET BACKGROUND TASK VECTOR FUNCTION ; ENTRY- HL= VECTOR (-1= NONE) ; EXIT - HL= VECTOR ON ENTRY ; ;++++++++++++++++++++++++++++++++++++++ SETBACK: LD A,00000001B ;DISABLE INTERRUPT WHILE CHANGING VECTOR OUT (CTCB2),A PUSH DE LD DE,(MSVEC) LD (MSVEC),HL INC HL ;IF VECTOR != -1 THEN LD A,L OR H JR Z,SETBAK1 LD A,10000001B ; ENABLE INTERRUPT OUT (CTCB2),A SETBAK1: EX DE,HL POP DE RET ;************************************** ; ; MILLISECOND INTERRUPT HANDLER ; USES 2 STACK WORDS ; ;************************************** MSVEC DW -1 ;INITIAL VECTOR = NONE MILISEC: PUSH HL PUSH AF LD HL,(MSVEC) ;IF VECTOR == -1 THEN INC HL LD A,L OR H DEC HL JR NZ,DOMSVEC POP AF ; IGNORE INTERRUPT POP HL JR MSRET DOMSVEC: POP AF CALL DISPATCH ;EXECUTE VECTOR POP HL MSRET: EI RETI ;************************************** ; ; CLOCK 250MS INTERRUPT HANDLER ; ;************************************** TIMER: ISAVE PUSH HL ;HL TOO LD HL,(TICKS) ;BUMP FREE RUNNING CLOCK TICK COUNT INC HL LD (TICKS),HL LD HL,TIKCNT ;IF --TICK_CNT == 0 THEN DEC (HL) JR NZ,TIMER2 LD A,4 ; RESET TICK_CNT TO 4 (1 SECOND) LD (HL),A CALL CLOCK ; DO CLOCK TIMEKEEPING TIMER2: POP HL IRESTORE EI RETI ;**************************** ; ; CLOCK TIME KEEPER ; ;**************************** CLOCK: LD DE,TOD ;POINT TO TIME OF DAY ARRAY LD HL,TODTAB ;MAX COUNT TABLE LD B,4 ;ELEMENT COUNT CLOCK2: LD A,(DE) ;INCREMENT TIME WITH ADD INSTRUCTION ADD A,1 DAA ;CONVERT TO BCD CP (HL) ;IF ROLLOVER THEN JR C,CLOCK3 XOR A ;THIS ARRAY = 0 CLOCK3: LD (DE),A ;STORE NEW VALUE RET C ;IF NO ROLLOVER THEN RETURN INC HL ;ELSE NEXT ARRAY INC DE DJNZ CLOCK2 ;IF NOT DONE THEN REPEAT RET ;ELSE RETURN TODTAB: DB 60H ;SECONDS PER MINUTE DB 60H ;MINUTES PER HOUR DB 24H ;HOURS PER DAY DB 99H ;OVERFLOW FROM DAYS ;++++++++++++++++++++++++++++++++++++++ ; ; RETURN CLOCK TICK COUNT FUNCTION ; EXIT - HL= TICK COUNT ; ;++++++++++++++++++++++++++++++++++++++ GETTICK: LD HL,(TICKS) RET ;++++++++++++++++++++++++++++++++++++++ ; ; RETURN CLOCK ARRAY PTR FUNCTION ; EXIT - HL= ARRAY PTR ; ;++++++++++++++++++++++++++++++++++++++ GETCLKP: LD HL,TOD RET SUBTTL MESSAGES LOGMSG: DB 'DGMON V ',HIGH VERSN,'.',LOW VERSN CRMSG: DM CR,LF USRMSG: DB 'MEMORY = ' DB (MONVARS / 10000) + '0', ((MONVARS MOD 10000) / 1000) + '0' DM 'K',CR,LF QMSG: DM '????' RSTMSG: DM 'RST ERR' OVLERRM DM CR,LF,'OVERLAY ERR' SUBTTL PRIMITIVE I/O DRIVERS ;************************************** ; ; CONSOLE DEVICE ; ;************************************** CI: ;RETURN NEXT AVAILABLE CHAR IN A PUSH HL LD HL,KBDIN CALL CALLROM POP HL RET CO: ;OUTPUT CHAR IN C TO CONSOLE PUSH HL LD HL,VIDOUT CALL CALLROM POP HL RET CSTS: ;RETURN CONSOLE STATUS IN A (0: NOT READY, -1: READY) PUSH HL LD HL,KBDST ;IF NOT CHAR NOT READY THEN RETURN 0 CALL CALLROM POP HL RET ; ; KEYBOARD INTERRUPT ROUTINE ; KEYSRV: PUSH HL LD HL,KBDINT CALL DISPATCH POP HL IRET: EI RETI ;************************************** ; ; LIST DEVICE ; ;************************************** LO: ;OUTPUT CHAR IN C TO LINE PRINTER CALL LSTAT ;IF BUSY THEN WAIT JR Z,LO LD A,CENTDST + ON ;INSURE STROBE IS FALSE (HIGH) OUT (IOSTBS),A LD A,C ;FETCH & OUTPUT DATA OUT (CENTOUT),A LD A,CENTDST + OFF ;OUTPUT DATA STROBE OUT (IOSTBS),A LD A,CENTDST + ON ;TURN OFF DATA STROBE OUT (IOSTBS),A RET LSTAT: ;RETURN LINE PRINTER STATUS IN A (0:BUSY, -1:NOT) IN A,(IOSTAT) ;FETCH I/O STATUS CPL ;REVERSE SENSE AND A,1 SHL CENTBSY ;IF BUSY THEN RETURN 0 RET Z LD A,-1 ;ELSE RETURN -1 RET ;************************************************************************** ; ; SUDING CASSETTE READ ; IMPLEMENTED AS A 'C' FUNCTION AS FOLLOWS: ;static unsigned bytsr, bytc; ;unsigned casi(count, staddr) unsigned count; char *staddr;{ ; return bytsr; ; } ; ENTRY- (SP+2)= LOAD START ADDRESS PTR ; (SP+4)= BYTE COUNT (0: ENTIRE FILE) ; ;************************************************************************** SUDI: CALL GET2VAR ;FETCH PARAMETERS FROM STACK PUSH HL LD HL,0 ;BYTES_READ = 0 LD (BYTSR),HL POP HL ;START ADDRESS SKLEAD: IN A,(IOSTAT) ;WAIT FOR END OF LEADER AND 1 SHL CASDATI JR NZ,SKLEAD MORE: LD B,0 ;TIMOUT = 256 TIMOUT: INC B JR Z,SRDONE ;TIMED OUT, NO MORE DATA IN A,(IOSTAT) ;IF DATUM == MARK THEN LOOP AND 1 SHL CASDATI JP NZ,TIMOUT LD DE,8 ;SET BIT COUNT WTSTRT: IN A,(IOSTAT) ;WAIT FOR SPACE AND 1 SHL CASDATI JP NZ,WTSTRT LD C,3 ;WAIT 1.5 BITS BEFORE TESTING CALL DELAY NXTBIT: IN A,(IOSTAT) ;GET DATUM AND 1 SHL CASDATI RLCA ;PUT IN BIT 0 RLCA ADD D ;ADD TO PREVIOUS BITS RRCA LD D,A LD C,2 ;WAIT FOR 1 BIT CELL CALL DELAY DEC E ;BIT_COUNT-- JP NZ,NXTBIT LD (HL),D ;STORE IN MEMORY LD DE,(BYTSR) ;BYTES_READ++ INC DE LD (BYTSR),DE INC HL ;MEM_PTR++ LD DE,(BYTC) ;IF --BYTE_COUNT == 0 THEN DONE DEC DE LD A,E OR D LD (BYTC),DE JR NZ,MORE SRDONE: LD HL,(BYTSR) ;RETURN BYTES_READ LD A,L ;SET FLAGS TO RETURN VALUE OR H RET ;************************************** ; ; FETCH 2 PARAMETERS FROM STACK SUBR ; ENTRY- (SP+4)= P1 ; (SP+6)= COUNT ; EXIT - HL= P1 ; ;************************************** GET2VAR: LD HL,4 ;FETCH PARAMETERS ADD HL,SP LD E,(HL) ;FETCH START ADDRESS INC HL LD D,(HL) INC HL PUSH DE LD E,(HL) ;FETCH COUNT INC HL LD D,(HL) LD (BYTC),DE POP HL ;P1 RET ;************************************** ; ; DELAY SUBR DETERMINES BAUD RATE ; ENTRY- C= NUMBER OF 436US ; EXIT - BC= 0 ; ;************************************** DELAY: LD B,122 ;DELAY CONSTANT (76 FOR 2.5 MHZ) DELOOP: DEC B JP NZ,DELOOP DEC C ;IF --MULTIPLIER != 0 THEN LOOP JP NZ,DELAY RET ;************************************************************************** ; ; SUDING CASSETTE WRITE ; IMPLEMENTED LIKE A 'C' FUNCTION AS: ;static unsigned bytc; ;caso(count, staddr) unsigned count; char *staddr;{ ; } ; ; ENTRY- (SP+2)= START ADDRESS PTR ; (SP+4)= BYTES TO WRITE COUNT ; ;************************************************************************** SUDO: CALL GET2VAR ;FETCH PARAMETERS FROM STACK CALL LEADER ;WRITE LEADER WMORE: LD E,9 ;BIT COUNT + 1 XOR A,A ;CLEAR CARRY LD A,(HL) ;GET BYTE RLA ;START BY WRITING START BIT (0) WNXTBT: PUSH AF ;SAVE AND 1 ;OUTPUT BIT RLCA ;SHIFT DATA TO BIT 3 FOR ADDRESSABLE LATCH RLCA RLCA ADD A,CASDATO OUT (IOSTBS),A POP AF ;RESTORE DATA LD C,2 ;HOLD FOR 1 BIT CELL CALL DELAY RRA ;NEXT BIT DEC E ;IF --BIT_COUNT != 0 THEN LOOP JP NZ,WNXTBT LD A,CASDATO + ON ;ELSE WRITE 2 STOP BITS (1) OUT (IOSTBS),A LD C,4 CALL DELAY INC HL ;MEM_PTR++ LD DE,(BYTC) ;IF --BYTE_COUNT != 0 THEN LOOP DEC DE LD (BYTC),DE LD A,E OR D JR NZ,WMORE CALL LEADER ;ELSE WRITE TRAILER & RETURN XOR A RET ;**************************** ; ; WRITE LEADER SUBR ; EXIT - BC, D= 0 ; ;**************************** LEADER: LD C,0 ;5.4 SEC LD D,48 LEADLP: CALL DELAY DEC D JR NZ,LEADLP RET IF ($ >= (0FF00H - OVLSIZ)) OR ($ <= 7FFFH) CONMSG **** Error - Code Collides With Overlay area (Too Big) **** ENDIF SUBTTL OVERLAY AREA ORG 0FF00H - OVLSIZ ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ; ; OVERLAY BUFFER HAS COLD START CODE ON RESET ;EXECUTES DIAGNOSTICS UPON COLD RESET FROM PAGE 0 OF ROM, ALL ABSOLUTE ;REFERENCES MUST BE REFERENCED BY 'NAME - ROM'. ;MOVES TO HIGH MEMORY, CHANGES COLD START VECTOR TO WARM START, THEN ;EXECUTES WARM START. ; ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! OVERLAY: ;OVERLAY GETS LOADED IN HERE DB -2 ;DUMMY OVERLAY # FORCES 1ST LOAD CINIT: LD HL,AUXMEM ;TEST AUXILIARY RAM FOR STACK LOCATION LD BC,2048 LD SP,XRAMDON - ROM - 2 ;DUMMY STACK FOR NOW JP RAMTST - ROM DW XRAMDON - ROM XRAMDON: JR Z,AUXOK LD SP,STOP - ROM - 2 ;BEEP BUZZER JP BEEP - ROM DW STOP - ROM STOP: JR $ AUXOK: LD SP,AUXMEM + 2048 ;USE AUXILLIARY RAM FOR STACK LD HL,CHRMEM ;TEST CHARACTER RAM LD BC,2048 CALL RAMTST - ROM JR Z,CHROK LD B,2 ;2 BEEPS = VIDEO CHARACTER RAM ERROR CALL BEEPS - ROM CHROK: LD HL,ATTMEM ;TEST ATTRIBUTE MEMORY LD BC,2048 CALL RAMTST - ROM JR Z,ATTOK LD B,3 CALL BEEPS - ROM ATTOK: LD A,(VIDINIT) ;IF I/O ROM NOT THERE THEN ERROR CP 0C3H JR Z,IOROMOK LD B,4 CALL BEEPS - ROM JR $ IOROMOK: CALL VIDINIT ;INIT VIDEO OUTPUT IN A,(SENSE) ;IF SW1 SET THEN FILL DISPLAY WITH CHARS BIT SW1,A JR NZ,NOCHRS ; ; FILL SCREEN WITH INCREMENTING CHARS ; LD DE,80 * 23 LD C,' ' VIDTLP: PUSH BC PUSH DE CALL VIDOUT POP DE POP BC INC C ;NEXT CHAR LD A,7EH ;IF NEW CHAR > PRINTABLE THEN RE-INIT TO ' ' CP C JR NC,VIDLP1 LD C,' ' VIDLP1: DEC DE ;COUNT-- LD A,E OR D JR NZ,VIDTLP ; ; TEST RAM ; NOCHRS: LD HL,8000H ;START WITH UPPER 32K LD BC,8000H CALL RAMTST - ROM JR Z,URAMOK RAMERR: PUSH HL ;SAVE RAM FAILURE ADDRESS LD HL,RAMMSG - ROM CALL POUT - ROM POP HL ;ADDRESS CALL OUTW - ROM JR $ ;FATAL ERROR, GO NO FURTHER URAMOK: LD SP,0 ;TEST UPPER RAM CALL TSTLOW - ROM JR NZ,RAMERR LD C,BELL ;ANNOUNCE FINISH CALL VIDOUT IN A,(SENSE) ;IF SW1 SET THEN CONTINUOUS DIAGNOSTIC BIT SW1,A JP Z,0 ; ; DIAGNOSTICS OVER, MOVE MONITOR TO HIGH MEMORY & EXECUTE ; LD SP,ROM - 100H ;PUT STACK BELOW MONITOR TEMPORARILY LD HL,0 LD DE,ROM ;PUT MONITOR AT F800 LD BC,2048 ;2K ZMON LDIR LD HL,0 ;TEST LOAD LD DE,ROM LD BC,2048 MONTST: LD A,(DE) CP (HL) JR NZ,MONERR INC HL INC DE DEC BC LD A,C OR B JR NZ,MONTST CALL VIDINIT ;CLEAR SCREEN FOR MONITOR LD HL,INIT ;CHANGE ENTRY FROM COLD TO WARM START LD (ROM + 1),HL JP ROM MONERR: PUSH HL ;OUTPUT ERROR ADDRESS PUSH DE PUSH HL LD HL,MONERM - ROM CALL POUT - ROM POP HL CALL OUTW - ROM CALL OUTSPC - ROM POP DE POP HL LD A,(DE) XOR (HL) CALL OUTBH - ROM JR $ ;************************************** ; ; BEEP SUBR ; ;************************************** BEEPS: PUSH BC ;SAVE COUNT CALL BEEP - ROM ;DO 1 BEEP POP BC ;IF --COUNT != 0 THEN REPEAT DJNZ BEEPS RET BEEP: LD A,BUZZER + ON ;TURN ON BUZZER OUT (PORT0),A LD BC,0 ;DELAY ON TIME BEEP2: DEC C JR NZ,BEEP2 DJNZ BEEP2 LD A,BUZZER + OFF ;TURN OFF BUZZER OUT (PORT0),A LD A,2 ;DELAY OFF TIME BEEP3: DEC C ;BC NOW = 0 JR NZ,BEEP3 DJNZ BEEP3 DEC A JR NZ,BEEP3 RET ;************************************** ; ; PRIMITIVE OUTPUT SUBR ; ENTRY- HL= TXT PTR (>127=LAST) ; ;************************************** POUT: LD C,(HL) PUSH HL RES 7,C CALL VIDOUT POP HL BIT 7,(HL) ;IF CHAR > 127 THEN DONE RET NZ INC HL JR POUT ;************************************** ; ; TEST LOW RAM SUBR ; ;************************************** TSTLOW: LD HL,TSTLOW - ROM ;MOVE THIS CODE TO HIGH MEMORY LD DE,TSTLOW LD BC,TLSIZ LDIR JP TSTLO1 ;EXECUTES NEXT INSTRUCTION IN HIGH MEMORY TSTLO1: LD A,DYSTAT + ON ;TURN ON RAM OUT (PORT0),A LD HL,0 ;TEST LOW RAM LD BC,2048 CALL RAMTST LD A,DYSTAT + OFF ;TURN ON ROM OUT (PORT0),A RET ;************************************** ; ; NON DESTRUCTIVE RAM TEST SUBR ; ENTRY- HL= RAM PTR ; BC= COUNT ; EXIT - ZF= OK, NZ= BAD RAM ; HL= BAD RAM PTR ; ;************************************** RAMTST: LD A,(HL) ;FETCH BYTE CPL ;COMPLEMENT IT LD (HL),A ;STORE IT CP (HL) ;TEST IT CPL ;RESTORE IT LD (HL),A RET NZ ;IF BAD THEN RETURN INC HL ;NEXT LOCATION DEC BC LD A,C OR B JR NZ,RAMTST RET TLSIZ EQU $ - TSTLOW ;SIZE OF CODE NEEDED TO TEST LOW BANK ;************************************** ; ; OUTPUT HEX WORD SUBR ; ENTRY- HL= WORD ; ;************************************** OUTW: LD A,H ;START WITH HIGH BYTE PUSH HL CALL OUTB - ROM POP HL LD A,L ;FALL THROUGH WITH LOW BYTE CALL OUTB - ROM OUTH: LD C,'H' JP VIDOUT ;**************************** ; ; OUTPUT HEX BYTE SUBR ; ENTRY- A= BYTE ; ;**************************** OUTBH: CALL OUTB - ROM JR OUTH OUTB: CALL PRDIG - ROM PRDIG: RLCA ;START WITH UPPER NIBBLE RLCA RLCA RLCA PUSH AF ;SAVE VALUE AND 0FH ;MASK OFF OTHER NIBBLE CP 10 ;IF > 9 THEN CONVERT TO A..F JR C,NTALPH ADD 7 NTALPH: ADD '0' ;CONVERT TO ASCII LD C,A CALL VIDOUT POP AF ;RESTORE DATA RET ;**************************** ; ; OUTPUT SPACE SUBR ; ;**************************** OUTSPC: LD C,' ' JP VIDOUT RAMMSG: DM CR,LF,'RAM ERROR AT ' MONERM: DM CR,LF,'MONITOR LOAD ERROR AT ' IF ($ >= 0FF00H) OR ($ < 7FFFH) CONMSG **** COLD BOOT CODE RUNS INTO INTERRUPT TABLE **** ENDIF ORG 0FF00H ;###################################### ; ; INTERRUPT VECTOR TABLE ; ;###################################### INTTBL: DW IRET ;SIOB TX DW IRET ;SIOB EXTERNAL/STATUS DW IRET ;SIOB RX DW IRET ;SIOB SPECIAL RX CONDITION DW IRET ;SIOA TX DW IRET ;SIOA EXTERNAL/STATUS DW IRET ;SIOA RX DW IRET ;SIOA SPECIAL RX CONDITION CTCAV: DW KEYSRV ;KEYBOARD DW IRET ;INDEX PULSE DW IRET ;SIOA SYNC DW IRET ;VERTICAL SYNC INTERVAL CTCBV: DW IRET ;SIOB BAUD RATE (NOT USED) DW IRET ;SIOA BAUD RATE (NOT USED) DW MILISEC ;REAL TIME CLOCK MILLISECOND TIMER DW TIMER ;REAL TIME CLOCK TICK DMAVEC: DW IRET ;DMA READY DW IRET ;DMA MATCH DW IRET ;DMA END_OF_BLOCK DW IRET ;DMA MATCH/END SUBTTL CONSTANTS DS 0FF30H - $ ;********************************************************** ; ; TBL CONTAINS THE OVERLAY NUMBERS OF THE COMMANDS. ; THE EXECUTIVE USES IT TO LOOK UP THE DESIRED OVERLAY. ; ;********************************************************** TBL: DB -1 ;A DB BOOTCO ;Boot DB CLOCKCO ;Clock set/display DB DISPO ;Display DB -1 ;E DB FILLO ;Fill memory DB GOTOO ;Goto address DB HELPCO ;Help DB INPTO ;Input DB -1 ;J DB -1 ;K DB LOADCO ;Load cassette (read) DB MOVEO ;Move memory DB -1 ;N DB OUPTO ;Output DB -1 ;P DB -1 ;Q DB READCO ;Read disk DB SUBSO ;Substitute memory DB MTESTO ;Test memory DB UNLDCO ;Unload cassette (write) DB COMPO ;Verify memory DB WRITCO ;Write disk DB XMNEO ;Xamine registers DB -1 ;Y DB BYEO ;Zleep ;--------------------------------------------------------------- ; ; Z80 REGISTER OFFSET TABLE ; STRUCTURE- BYTE= REGISTER CHAR ; BIT 7= NEW LINE IF PRINTOUT ; WORD= ADDRESS OF VALUE ; BIT 7= 0: BYTE, 1: WORD VALUE ; BIT 6= 0: DIRECT, 1: INDIRECT VALUE ; ;--------------------------------------------------------------- TB MACRO #REG,#M,#ADDR,#AM DB #REG + (#M * 80H), LOW #ADDR, (HIGH (#ADDR AND 0FFFH)) + #AM ENDM ACTBL: TB 'A',1,ALOC,0 TB 'B',0,BLOC,0 TB 'C',0,CLOC,0 TB 'D',0,DLOC,0 TB 'E',0,ELOC,0 TB 'F',0,FLOC,0 TB 'H',0,HLOC,0 TB 'L',0,LLOC,0 TB 'M',1,LLOC,11000000B TB 'P',0,PLOC,10000000B TB 'S',0,SLOC,10000000B TB 'I',0,ILOC,0 ; ; PRIME Z80 REGISTER OFFSETS ; PRMTB: TB 'A',1,APLOC,0 TB 'B',0,BPLOC,0 TB 'C',0,CPLOC,0 TB 'D',0,DPLOC,0 TB 'E',0,EPLOC,0 TB 'F',0,FPLOC,0 TB 'H',0,HPLOC,0 TB 'L',0,LPLOC,0 TB 'M',1,LPLOC,11000000B TB 'X',0,XLOC,10000000B TB 'Y',0,YLOC,10000000B TB 'R',0,RLOC,0 DB -1 ;############################ ; ; I/O DEVICE INIT TABLE ; ;############################ IOTABL: DB 2,PORT3 ;TTL BIT LATCHES DB ATTEN + ON DB FDCRST + ON DB 1,SELMUX DB 00001010B ;DRIVES OFF, TEST= FALSE, RDY SELECT= DRQ DB 6,DMA ;RESET OF DMA PER ZILOG REPT 6 DB 11000011B ENDM DB 1,CTCA0 ;KEYBOARD DB (LOW CTCAV) AND 11111000B DB 2,CTCA1 ;INDEX PULSES DB 01000111B ;COUNT INDEX PULSES MOD 256 DB 0 DB 3,CTCB0 ;CTC B DB (LOW CTCBV) AND 11111000B DB 01000111B ;COUNTER MODE DB 128 ;/128 = 300 BAUD DB 2,CTCB1 ;CTC B1 IN COUNTER MODE & 300 BAUD DB 01000111B DB 128 DB 2,CTCB2 ;RTC DIVISOR = 1MS DB 00000111B DB 250 DB 2,CTCB3 ;RTC TICK, INTERRUPT EVERY 250MS DB 11000111B DB 250 DB -1 IF $ < 7FFFH CONMSG **** Error - Code Exceeds FFFFH **** ENDIF SUBTTL MONITOR OVERLAYS ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ; ; THE FOLLOWING CODE RESIDES IN THE 2ND HALF OF THE 32K EPROM. ;IT STARTS WITH A TABLE OF POINTERS TO EACH OVERLAY, (FOLLOWED BY ;AN EQUATE TO THE OFFSET OF THE POINTER TO LINK TO THE COMMAND ;LOOKUP TABLE), FOLLOWED BY THE COMMAND OVERLAY ITSELF. OVERLAYS ;WILL NOT BE LONGER THAN 512 BYTES AT THIS TIME. THE OVERLAYS ;MUST START WITH A BYTE CONTAINING THE OVERLAY OFFSET NUMBER AND THE ;CODE MUST START AT THE 2ND BYTE OF THE OVERLAY. ; ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ORG 0800H ;REALLY 0800H OBASE EQU $ ;###################################### ; ; TABLE OF POINTERS TO THE OVERLAYS ; ;###################################### DW OERROR ;0= ERROR OVERLAY (-2 FOR OVERLAY #) ERRORO EQU 0 DW FILL FILLO EQU 1 DW BYE BYEO EQU 2 DW COMP COMPO EQU 3 DW DISP DISPO EQU 4 DW GOTO GOTOO EQU 5 DW INPT INPTO EQU 6 DW OUPT OUPTO EQU 7 DW MOVE MOVEO EQU 8 DW BOOTC BOOTCO EQU 9 DW SUBS SUBSO EQU 10 DW MTEST MTESTO EQU 11 DW XMNE XMNEO EQU 12 DW LOADC LOADCO EQU 13 DW UNLDC UNLDCO EQU 14 DW CLOCKC CLOCKCO EQU 15 DW READC READCO EQU 16 DW WRITC WRITCO EQU 17 DW HELPC HELPCO EQU 18 ;--------------------------------------------------------------- ; ; ERROR OVERLAY ; ;--------------------------------------------------------------- OERROR: DB ERRORO ;OVERLAY # ;--------------------------------------------------------------- ; ; FILL MEMORY COMMAND ; ; THIS ROUTINE FILLS A BLOCK OF MEMORY WITH A USER ; DEFINED CONSTANT. IT EXPECTS 3 PARAMETERS TO BE ENTERED IN ; THE FOLLOWING ORDER: ; START ADDR, FINISH ADDR, FILL VALUE ; ; F ; ;--------------------------------------------------------------- FILL: DB FILLO CALL EXPR3 ;GET 3 PARAMS FIO: LD A,H ;PROTECT MONITOR CODE CP HIGH MONVARS JR NC,FIOC LD (HL),C ;PUT DOWN THE FILL VALUE CALL HILO ;INC & CHECK THE PTR JR NC,FIO FIOC: POP DE ;RESTORE SP IN CASE STACK JP WINIT ; WAS OVERWRITTEN ;--------------------------------------------------------------- ; ; SLEEP COMMAND ; ; THE BYE ROUTINE IS USED TO PREVENT UNAUTHORIZED USAGE ; OF THE SYSTEM. THE SYSTEM LOCKS UP & WILL NOT RESPOND TO ; ANYTHING OTHER THAN 2 ASCII BELL CHARACTERS. WHEN IT SEES ; THEN CONSECUTIVELY, CONTROL IS RETURNED TO THE MONITOR ; WITHOUT ALTERING ANYTHING. ; ; Z ; ;--------------------------------------------------------------- BYE: DB BYEO BYE2: LD B,2 ;SET UP FOR 2 CHARS BYE1: CALL CONI CP BELL ;IF NOT BELL THEN RESTART JR NZ,BYE2 CALL ECH1 ;ECHO THE BELL DJNZ BYE1 RET ;--------------------------------------------------------------- ; ; VERIFY MEMORY COMMAND ; ; THIS ROUTINE COMPARES 2 BLOCKS OF MEMORY AGAINST EACH ; OTHER. IF A DIFFERENCE IN THE RELATIVE ADDRESS CONTENTS IS ; DETECTED, THE ADDRESS OF THE 1ST BLOCK IS DISPLAYED, ALONG ; WITH IT'S CONTENTS & THE CONTENTS OF THE OTHER BLOCK'S SAME ; RELATIVE ADDRESS. ; ; V ; ;--------------------------------------------------------------- COMP: DB COMPO CALL EXPR3 CMPA: LD A,(BC) ;GET SOURCE 2 DATA PUSH BC ;SAVE SOURCE 2 PTR LD B,(HL) ;GET SOURCE 1 DATA CP B ;IF S2=S1 THEN EXIT JR Z,CMPB PUSH AF ;SAVE S2 DATA CALL LADRB ;OUTPUT ADDR LD A,B CALL DASH1 ;FORMAT POP AF CALL HEX1 ;OUTPUT S2 CMPB: POP BC CALL HILOXB JR CMPA ;--------------------------------------------------------------- ; ; DISPLAY MEMORY COMMAND ; ; THIS ROUTINE DISPLAYS A BLOCK OF MEMORY ON THE ; CONSOLE DEVICE. THE USER MUST SPECIFY THE START & FINISH ; ADDRESSES. THE DISPLAY IS ORGANIZED TO DISPLAY UP TO 16 ; BYTES PER DISPLAY LINE, WITH ALL COLUMNS ALIGNED SO EACH ; COLUMN HAS THE SAME LAST HEX DIGIT IN IT'S ADDR. ; ; D[ ] ; ;--------------------------------------------------------------- DISP: DB DISPO CALL EXLF ;GET BLOCK LIMITS DIS1: CALL LADRB ;DISPLAY START ADDR LD A,L ;SEE IF ON 16 BYTE BOUNDARY CALL TRPLSP - DISP + OVERLAY ;SKIP OVER TO RIGHT COLUMN PUSH HL DIS2: LD A,(HL) ;GET CONTENTS CALL HEX1 CALL HILO ;INC & CHECK PTR JR C,DIS7 ;DONE IF CARRY CALL BLK ;MAKE COLUMNS LD A,L ;READY FOR NEW LINE? AND 0FH JR NZ,DIS2 DIS3: POP HL ;RESTORE START OF LINE LD A,L ;SKIP OVER TO RIGHT SPACE AND 0FH CALL TRPL2 - DISP + OVERLAY DIS4: LD A,(HL) ;OUTPUT MEMORY IN ASCII AND 7FH ;IF PRINTABLE THEN OUTPUT LD C,A CP ' ' JR C,DIS5 CP 7EH JR C,DIS6 DIS5: LD C,'.' ;ELSE OUTPUT '.' DIS6: CALL CONOUT CALL HILOX LD A,L ;READY FOR NEW LINE? AND 0FH JR NZ,DIS4 ;NO JR DIS1 ;YES ; DIS7: SUB A,E ;SKIP OVER TO START ASCII CALL TRPLSP - DISP + OVERLAY JR DIS3 ;**************************** ; ; COMPUTE COLUMN SUBR ; ENTRY- A=COLUMN ; ;**************************** TRPLSP: AND 0FH ;ISOLATE LOW NIBBLE LD B,A ;PREPARE TO SPACE OVER TO RIGHT ADD A,A ; COLUMN ADD B ;**************************** ; ; OUTPUT N SPACES SUBR ; ENTRY- A= #_SPACES ; EXIT - B= 0 ; ;**************************** TRPL2: LD B,A INC B TRPL1: CALL BLK ;DO SPACING DJNZ TRPL1 RET ;---------------------------------------------------------------------------- ; ; GOTO COMMAND ; ; GOTO COMMAND TRANSFERS CONTROL TO A SPECIFIED ADDRESS ; IT ALLOWS THE SELECTIVE SETTING OF UP TO 2 BREAKPOINTS AS ; WELL AS ALLOWING ANY CONSOLE INPUT TO BREAKPONT THE RUN, AS ; LONG AS INTERRUPT 1 IS ACTIVE. ; ; G ;START EXECUTION AT WHATEVER IS IN PC REG (NO BPS) ; G ;START EXECUTION AT START_ADDR (NO BPS) ; G,[,] ;START EXECUTION AT START_ADDR WITH ; BREAKPOINT AT BP1 AND OPTIONAL BREAKPOINT AT BP2 ; G,[,] ;START EXECUTION AT PC VALUE WITH BREAKPOINT(S) AT ; BP1 & OPTIONAL BP2. ; ;---------------------------------------------------------------------------- GOTO: DB GOTOO CALL PCHK ;IF NO ARGS THEN EXIT JR C,GO3 JR Z,GO0 ;ELSE IF DELIM. (NO START ADDR) THEN EXIT ; ; EXECUTION ADDRESS SPECIFIED ; CALL EXF ;GET NEW GOTO ADDR POP HL LD (PLOC),HL ;PUT ADDR IN PC LOCATION LD A,C ;IF LAST = CR THEN EXIT CP CR JR Z,GO3 ; ; BREAKPOINTS SPECIFIED ; GO0: LD B,NBKPTS LD HL,TLOC ;POINT TO TRAP STORAGE GO1: PUSH BC ;# BPS PUSH HL ;STORAGE PTR LD B,2 CALL EXPR1 ;GET TRAP ADDRESS FROM USER POP DE POP HL ;PTR LD A,D ;IF BREAKPOINT SPECIFIED AS 0 THEN IGNORE OR E JR Z,GO2 LD (HL),E ;SAVE BP ADDR INC HL LD (HL),D INC HL LD A,(DE) ;SAVE BP ADDR INSTRUCTION LD (HL),A INC HL LD A,0CFH ;INSERT THE BP LD (DE),A GO2: LD A,C ;IF CHAR = CR THEN DONE BPING CP CR POP BC ;COUNT JR Z,GO3 DJNZ GO1 ;ELSE IF <2 BPS THEN LOOP ; ; GOTO ADDRESS & BREAKPOINTS TAKEN CARE OF ; GO3: CALL CRLF ;NEW LINE FOR PGM DI ;DISABLE INTERRUPTS WHILE MESSING WITH REGS POP HL ;COMMAND RETURN ADDRESS LD HL,RS9 ;PUT TRAP FOR STACK UNDERRUN ON STACK PUSH HL LD HL,REST ;PUT BREAKPOINT ENTRY PTR INTO TRAP VECTOR LD (9),HL POP DE ;ADJUST STACK JP EXIT ;GO DO REG RESTORE & EXECUTE GOTO ;--------------------------------------------------------------- ; ; INPUT FROM PORT COMMAND ; ; THESE ROUTINES ALLOW BYTE-BY-BYTE INPUT OR OUTPUT FROM ; THE CURRENT CONSOLE DEVICE. ; ; I ; ;--------------------------------------------------------------- INPT: DB INPTO CALL EXPR1 ;GET INPUT PORT # INTO C CALL CRLF ;PUT DATA ON NEW LINE POP BC IN E,(C) ;FETCH DATA LD B,8 ;BIT COUNT INPT1: LD A,E ;OUTPUT BINARY BITS RLCA LD E,A LD A,'0' / 2 RLA LD C,A CALL CONOUT DJNZ INPT1 RET ;-------------------------------------- ; ; OUTPUT DATA TO PORT COMMAND ; ; O ; ;-------------------------------------- OUPT: DB OUPTO CALL EXPR ;GET DATA INTO E, PORT # INTO C POP DE POP BC OUT (C),E RET ;---------------------------------------------------------- ; ; MOVE COMMAND ; ; THIS ROUTINE EXPECTS 3 PARAMETERS, ENTERED IN THE ; FOLLOWING SEQUENCE: ; SOURCE 1ST BYTE ADDR, SOURCE LAST BYTE ADDR & ; DESTINATION 1ST BYTE ADDR. ; ; M ; ;---------------------------------------------------------- MOVE: DB MOVEO CALL EXPR3 MOV1: LD A,B ;PROTECT MONITOR ENVIRONMENT CP HIGH MONVARS RET NC LD A,(HL) ;MOVE 1 BYTE LD (BC),A CALL HILOXB ;RETURNS TO COMMAND INPUT IF DONE JR MOV1 ;------------------------------------------------ ; ; BOOT COMMAND ; ALLOWS EXECUTION OF A BOOT PROM ; ; B {0..255} ; ;------------------------------------------------ BOOTC: DB BOOTCO ; ; CHECK FOR DRIVE NUMBER ; CALL PCHK ;IF NO FURTHER INPUT THEN USE DEFAULT LD C,0 ;DEFAULT TO 0 JR C,BOOTCD ; ; GET DRIVE NUMBER ; CALL EXF ;GET USER BOOT # POP BC ; ; PASS DRIVE NUMBER TO COLD BOOT ROUTINE IN ROM ; BOOTCD: LD HL,DKBOOTV CALL CALLROM ; ; CURRENTLY, IF ROM RETURNS THEN A != 0, SO ALLWAYS ERROR. HOOKS ARE HERE ; NOW FOR USER TO CODE UP A RETURN WITHOUT ERROR. ; OR A RET Z ; ; ERROR RETURNED, OUTPUT MESSAGE & STATUS WORD ; PUSH AF LD HL,BOOTM - BOOTC + OVERLAY CALL PRTWD POP AF CALL HEX1 JP CRLF ; ; BOOT LOAD ERROR MESSAGE ; BOOTM: DM CR,LF,'Boot Load Error - ' ;--------------------------------------------------------------- ; ; SUBSTITUTE MEMORY COMMAND ; ; THIS ROUTINE ALLOWS THE USER TO INSPECT ANY MEMORY ; LOCATION & ALTER THE CONTENTS, IF DESIRED & IF THE ADDRESS ; IS IN RAM. THE CONTENTS MAY BE LEFT UNALTERED BY ENTERING A ; SPACE, COMMA OR RETURN. IF A RETURN IS ENTERED, THE ROUTINE ; IS TERMINATED. IF A SPACE OR COMMA IS ENTERED, THE ROUTINE ; PROCEEDS TO THE NEXT LOCATION & PRESENTS THE USER WITH AN ; OPPORTUNITY TO ALTER IT. ; ; S ; ;--------------------------------------------------------------- SUBS: DB SUBSO CALL EXPR1 ;GET ADDR CALL CRLF ;START ON NEW LINE POP HL SUB1: LD A,(HL) ;OUTPUT EXISTING CONTENTS CALL DASH1 CALL PCHK ;GET NEW VALUE RET C ;IF CHAR = CR THEN RETURN JR Z,SUB2 ;IF CHAR = ' ' OR ',' THEN SKIP STORE CP LF ;IF CHAR = LF THEN BACK UP JR Z,SUB3 PUSH HL ;PTR CALL EXF ;CONTINUE HEX INPUT POP DE ;NEW VALUE POP HL ;PTR LD (HL),E ;LOAD VALUE LD A,C ;IF DELIM = CR THEN DONE CP CR RET Z SUB2: INC HL ;PTR = PTR + 2 INC HL SUB3: DEC HL ;PTR = PTR - 1 LD A,L ;IF ON MOD 8 BOUNDARY THEN AND 7 ; OUTPUT ADDR CALL Z,LADRB JR SUB1 ;--------------------------------------------------------------- ; ; MTEST COMMAND TESTS A SPECIFIED BLOCK OF MEMORY TO SEE ; IF ANY HARD DATA BIT FAILURES EXIST. IT IS NOT AN EXHAUSTIVE ; TEST, BUT JUST A QUICK INDICATION OF THE MEMORY'S ; OPERATIVENESS. ; ; T ; ;--------------------------------------------------------------- MTEST: DB MTESTO CALL EXLF MTEST1: LD A,(HL) LD B,A ;SAVE ORIGINAL CPL LD (HL),A XOR (HL) ;RESULT SHOULD BE 0 LD (HL),B ;RESTORE ORIGINAL DATA CALL NZ,BITS - MTEST + OVERLAY ;LOG ERR IF NOT MTEST2: CALL HILOX JR MTEST1 ;******************************************* ; ; BITS SUBR OUTPUTS ADDRESS & BINARY DATA ; ENTRY- E= DATA ; HL= ADDRESS ; ;******************************************* BITS: PUSH DE LD E,A CALL LADRB ;OUTPUT ADDR LD B,8 ;BIT COUNT BITS1: LD A,E RLCA LD E,A LD A,'0' / 2 ;BUILD ASCII 1 OR 0 RLA LD C,A CALL CONOUT DJNZ BITS1 POP DE RET ;------------------------------------------------------------------------- ; ; EXAMINE REGISTERS COMMAND INSPECTS THE VALUES OF THE ; REGISTERS STORED BY THE LAST ENCOUNTERED BREAKPOINT. THE ; VALUES MAY BE MODIFIED IF DESIRED. ; ; X ;DISPLAY ALL REGISTER VALUES ; ;r= A,B,C,D,E,F,H,L,M,P,S,I,'A,'B,'C,'D,'E,'H,'L,'M,X,Y,R ; ;d= HEX NUMBER TO PLACE INTO REGISTER r ; ;------------------------------------------------------------------------- XMNE: DB XMNEO JR XMNE0 ;VECTOR ; ; GOT ARGS: DISPLAY CURRENT VALUE & ACCEPT & SET NEW VALUE ; XA: LD B,A ;SAVE ARG CHAR XAA: LD A,(HL) ;FETCH TABLE CHAR INC A ;IF END OF TABLE (-1) THEN ERROR JP Z,QPRT DEC A AND 7FH ;REMOVE NEWLINE BIT CP B ;IF CHAR == ARG THEN FOUND JR Z,XAC INC HL ;NOT THIS ENTRY, SKIP TO NEXT ENTRY. CHAR INC HL ;ADDRL INC HL ;ADDRH JR XAA ; ; FOUND REGISTER REQUESTED IN TABLE ; XAC: PUSH BC ;CHAR IN B CALL BLK ;OUTPUT SPACE CALL PRTVAL ;OUTPUT CURRENT VALUE CALL DASH ;OUTPUT '-' CALL PCHK ;GET NEW INPUT POP BC ;CHAR IN B RET C ;IF CHAR = CR THEN RETURN JR Z,XF ;IF NO CHANGE THEN EXIT PUSH HL ;PTR LD C,A ;SAVE 1ST DIGIT LD A,B ;TEST FOR 'M' CP 'M' PUSH AF LD A,C ;RESTORE 1ST DIGIT CALL EXF ;GET NEW VALUE ON STACK POP HL ;FETCH NEW VALUE FROM STACK POP AF ;IF NOT 'M' THEN NO REDIRECTION JR NZ,NOREDIR ; ; 'M' SPECIFIED, USE CURRENT VALUE AS POINTER TO VALUE ; PUSH HL ;NEW VALUE LD A,(DE) ;FETCH PTR VALUE LD L,A INC DE LD A,(DE) LD H,A POP DE LD (HL),E ;STORE NEW VALUE JR XE NOREDIR: LD A,L ;STORE NEW VALUE LD (DE),A EX (SP),HL ;RECOVER TABLE PTR LD A,(HL) ;GET THE ATTRIBUTES EX (SP),HL RLCA ;IF 8 BIT REG THEN EXIT JR NC,XE INC DE ;ELSE REG PAIR, DO OTHER 8 BITS LD A,H ;STORE HIGH BYTE LD (DE),A XE: POP HL ;TABLE PTR XF: LD A,C ;IF LAST = CR THEN RETURN CP CR RET Z ; ; THIS IS THE ACTUAL COMMAND ENTRY POINT ; XMNE0: LD HL,ACTBL ;ADDR OF REG LOOK-UP TABLE XMNE1: CALL PCHK JP C,XG ;IF CHAR = CR THEN SHOW ALL JR Z,XMNE1 ;IF CHAR = ' ' OR ',' THEN LOOP CP '''' ;IF NOT PRIMES THEN EXIT JR NZ,XA LD HL,PRMTB JR XMNE1 ;---------------------------------------------------------- ; ; LOAD COMMAND READS THE SUDING CASSETTE TAPE ; ;L(START_ADDRESS) ; ;---------------------------------------------------------- LOADC: DB LOADCO CALL EXPR1 ;GET LOAD ADDRESS LD HL,0 ;0 LOADS THE ENTIRE FILE (<=65,536 BYTES) EX (SP),HL ;SHOVE UNDER STACK RETURN ADDRESS PUSH HL CALL SUDI ;READ IT POP DE ;BALANCE STACK EX (SP),HL ;SAVE ACTUAL COUNT LD HL,RDMSG - LOADC + OVERLAY ;OUTPUT BYTES READ CALL PRTWD POP HL ;OUTPUT ACTUAL BYTES READ JP LADR RDMSG: DM 'READ= ' ;---------------------------------------------------------- ; ; UNLOAD (WRITE) CASSETTE TAPE COMMAND ; ;U(COUNT) (START_ADDRESS) ; ;---------------------------------------------------------- UNLDC: DB UNLDCO CALL EXPR ;GET COUNT & ADDRESS CALL CRLF CALL SUDO POP HL ;BALANCE STACK POP HL RET ;-------------------------------------------------------------------- ; ; DISPLAY & SET REAL TIME CLOCK COMMAND ; ;C ;DISPLAY TIME ;Chours minutes [seconds] ;SET TIME (SECONDS OPTIONAL) ; ;-------------------------------------------------------------------- CLOCKC: DB CLOCKCO DI ;DISABLE INTERRUPTS TO PREVENT SKEW LD A,(MONSTAT) LD (TEMP),A RES INTSTAT,A LD (MONSTAT),A CALL GETCLKP ;FETCH ARRAY PTR NOW INC HL ;POINT TO HOURS INC HL PUSH HL CALL PCHK ;IF NO INPUT THEN DISPLAY JR NC,CLKSET ;ELSE SET CALL CRLF ;DISPLAY TIME ON NEW LINE POP HL ;HOURS PTR LD A,(HL) ;OUTPUT HOURS (HEX IS OK) CALL HEX1 LD C,':' ;OUTPUT DELIMITER CALL CO DEC HL ;OUTPUT MINUTES LD A,(HL) CALL HEX1 LD C,':' CALL CO DEC HL ;OUTPUT SECONDS LD A,(HL) CALL HEX1 CALL CLKEI - CLOCKC + OVERLAY JP CRLF CLKSET: CALL EXF ;GET HOURS FROM USER POP BC POP HL LD (HL),C DEC HL PUSH HL CALL PCHK ;IF NO MINUTES THEN ERROR POP HL JR C,CLKQ PUSH HL ;GET MINUTES CALL EXF POP BC POP HL LD (HL),C DEC HL PUSH HL CALL PCHK ;IF NO SECONDS THEN ASSUME 0 LD C,0 JR C,CLKSEC CALL EXF ;ELSE GET SECONDS POP BC CLKSEC: POP HL LD (HL),C JR CLKEI CLKQ: CALL CLKEI - CLOCKC + OVERLAY JP QPRT ;************************************** ; ; RESTORE INTERRUPT STATUS SUBR ; ;************************************** CLKEI: LD A,(TEMP) ;RESTORE INTERRUPT STATUS LD (MONSTAT),A BIT INTSTAT,A RET Z EI RET ;-------------------------------------- ; ; READ SECTOR COMMAND ; ;Raddress drive track sector ; ;-------------------------------------- READC: DB READCO ; ; GET REQUIRED USER COMMANDS ; LD B,4 CALL EXPR ; ; SET UP THE IOPB ; LD A,RDSCMD ;READ COMMAND LD (PBCMD),A ; XOR A,A ;INIT FLAGS LD (PBFLG),A ; LD (PBSTAT),A ;CLEAR ERRORS ; POP HL ;SECTOR LD (PBSEC),HL ; POP HL ;TRACK LD (PBTRK),HL ; POP HL ;DRIVE LD A,L LD (PBDRV),A ; LD HL,DBUFF ;XFER ADDRESS LD (PBDMA),HL ; ; EXECUTE THE IOPB ; LD DE,IOPB ;PASS PARAMETERS LD HL,XCUTE CALL CALLROM ; ; IF NO ERRORS THEN GO XFER DATA ; POP DE ;DMA DESTINATION STILL ON STACK OR A JR Z,DKOPOK ; ; ELSE OUTPUT ERROR ; PUSH AF ;SAVE ERROR STATUS LD HL,DKERM - READC + OVERLAY CALL PRTWD POP AF ;OUTPUT ERROR CODE CALL HEX1 JP CRLF ; ; MOVE DATA TO USER REQUESTED AREA ; DKOPOK: LD HL,DBUFF ;MOVE SECTOR DATA TO REQUESTED AREA LD BC,128 LDIR RET ;-------------------------------------- ; ; WRITE SECTOR COMMAND ; ;Waddress drive track sector ; ;-------------------------------------- WRITC: DB WRITCO ; ; GET REQUIRED PARAMETERS FROM USER ; LD B,4 ;GET PARAMETERS FROM USER CALL EXPR ; ; SET UP IOPB ; LD A,WRSCMD ;WRITE SECTOR COMMAND LD (PBCMD),A ; XOR A,A ;CLEAR FLAGS LD (PBFLG),A ; LD (PBSTAT),A ;CLEAR ERRORS ; POP HL ;SECTOR LD (PBSEC),HL ; POP HL ;TRACK LD (PBTRK),HL ; POP HL ;DRIVE LD A,L LD (PBDRV),A ; LD HL,DBUFF ;XFER ADDRESS LD (PBDMA),HL ; ; MOVE REQUESTED DATA TO BUFFER WHERE ROM CAN ACCESS IT ; POP HL ;SOURCE ADDRESS LD DE,DBUFF ;MOVE REQUESTED DATA TO BUFFER LD BC,128 LDIR ; ; EXECUTE THE IOPB ; LD DE,IOPB ;PASS THE IOPB PTR LD HL,XCUTE ;PASS THE EXECUTION VECTOR CALL CALLROM ; ; IF NO ERRORS THEN RETURN ; OR A RET Z ; ; ELSE OUTPUT WRITE ERROR ; PUSH AF ;SAVE ERROR STATUS LD HL,DKERM - WRITC + OVERLAY CALL PRTWD POP AF ;OUTPUT ERROR CODE CALL HEX1 JP CRLF ; DKERM: DM 'Disk Error: ' ;-------------------------------------- ; ; HELP COMMAND ; ;H ; ;-------------------------------------- HELPC DB HELPCO LD HL,HELPM - HELPC + OVERLAY JP PRTWD HELPM: DB 'Clock[HH MM[ SS]]' DB CR,LF,'Display(first) (last) Substitute(address)[ ]' DB CR,LF,'Fill(first) (last) (data) Move(first) (last) (destination)' DB CR,LF,'Test(first) (last) Verify(first) (last) (other first)' DB CR,LF,'Input(port) Output(port) (data)' DB CR,LF,'Load(address) Unload(address)' DB CR,LF,'Boot[drive]' DB CR,LF,'Read(address) (drive) (track) (sector)' DB CR,LF,'Write(address) (drive) (track) (sector)' DB CR,LF,'Goto[(address)][ (breakpoint1)[ (breakpoint2)]]' DB CR,LF,'Xamine[(register)[ (data)]] | [''(register)[ (data)]] | []' DM CR,LF,'Zleep' END