;************************************************************** ; BIG Z MONITOR (2K VERSION 4.0) 9/10/79 AB ;************************************************************** ; LAST MODIFICATION: MARCH 3, 2017 - changed menu and disk boot ROM location to F000H ; LAST MODICICATION: MARCH 7, 2017 - changed monitor org to F800H ; ASSUMPTIONS: ; SERIAL PORT ON BIGZ IS SET TO 10 AND 11H ; TARBELL TAPE USING STANDARD TARBELL PORTS ; OR KC STANDARD VIA JADE SERIAL/PARALLEL CARD 2S1P ; WITH AY51013 UART SET TO PORTS 0 & 80 HEX ; NO MEMORY SIZE IS ASSUMED ; ASSUME A VT-100 SERIAL TERMINAL CONNECTED TO JGZ80 8251 USART ; ; PROGRAMMING THE JGZ80 8251 UART ; Asynchronous Communication Mode ; Reset ; Mode Instruction (Asych or Synch, Baud Rate, Word Length, Stop Bits, Parity) ; Mode Word (Write): D7+D6=Stop Bits,D5=Even Parity,D4=Parity Enable,D3+D2=Char Length,D1+D0=Baud ; *Note: a different Mode Word for Synchronous Communication is used ; Command Instruction (DTR, RTS, Hunt Mode, Xmt Enable, Rxv Enable) ; Cmd Word (Write): D7=Hunt,D6=Int Rst,D5=RTS,D4=Err Rst,D3=Snd Brk,D3=Rx Enable,D1=DTR,D0=Tx Enable ; Status Word (Read): D7=DSR,D6=Syn Det,D5=Frame Err,D4=Overrun Err,D3=Parity Err,D2=Tx Empty,D1=Rx Rdy,D0=Tx Rdy ; ; SLR SYSTEMS ASSEMBLER USED TO GENERATE HEX CODE FOR USE...Z80ASM JADE FH... ; UPDATED August 4, 2016 by AD ; ; CONDITIONAL ASSEMBLY PARAMETERS ; DEFINE VALUES OF TRUE/FALSE TRUE: EQU 0FFFFH FALSE: EQU 0 ; SERIAL: EQU FALSE ; I/O IS ROUTED TO PROPELLER CONSOLE ***** NOT TO SERIAL PORT **** ; ; SET CONDITIONAL ASSEMBLY VALUES TARBEL: EQU FALSE KCTAPE: EQU TRUE ; ; SYSTEM EQUATES ; MON: ORG 0F800H ; ASSUME MONITOR ASSEMBLED FROM (F800H)-(FFFFH) 2K 2716 EPROM/EEPROM ; ; ; ASSUME VERSAFLOPPY II BIOS ROM AT (F000)H TAPE: EQU 00H ; JADE 2S1P BOARD SELECT PORT B KC CASSETTE 'CURRENTLY SET TO PORT 0H' TAPST: EQU 80H ; JADE 2S1P BOARD ADDRESS UART B I/O (80H + SELECT PORT) 'CURRENTLY PORT O & PORT 80' ; JADE 2S1P: TO PROGRAM THE UART OPERATION MODE LOAD THE SELECT PORT + 80 ; AS THE I/O ADDRESS THEN OUTPUT THE CONTROL WORD TO THAT ADDRESS...BAUD,PARITY,ETC ; THE INPUT & OUTPUT ADDRESS IS THE SAME. THE CONTROL WORD IS AN OUTPUT WHILE THE ; STATUS SENSE IN AN INPUT. ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA ; JADE 2S1P STATUS SENSE (1xxxxxxx)B = 80H => TRANSMITTER BUFFER IS EMPTY (TBMT)=1 ; JADE 2S1P STATUS SENSE (xxx1xxxx)B = 10H => CHARACTER READY TO TRANSMIT (DAV)=1 ; ; Note: WWW.S100COMPUTERS.CON Console I/O board uses (KBDST=00H) & (KBDDT=01H) ; the XMT & RCV are (KBDIN=02H) & (KBDOT=04H) ; ; ############# MODIFY PORTS AND PROTOCOL TO MATCH CONSOLE DEVICE BELOW ################## ; KBDST: EQU 00H ; Console I/O (00H)/8251 Command port (11H) KBDDT: EQU 01H ; Console I/O (01H)/8251 Data port (10H) KBDIN: EQU 02H ; Console I/O DATA RDY = (02H)/8251 RECEIVE READY = (0000 0002)B or (02)H KBDOT: EQU 04H ; Console I/O HOST BUSY = (04H)/8251 TRANSMIT READY = (0000 0001)B or (01)H ; TARBS: EQU 06EH ; TARBELL STATUS PORT TARBD: EQU 06FH ; TARBELL DATA PORT TLEAD: EQU 014H ; TAPE LEADER LENGTH OF (FF)H WRITTEN TO TAPE BOTH KC & TARBELL TTRAL: EQU 0AH ; TAPE TRAILER LENGTH OF (FF)H WRITTEN TO TAPE BOTH KC & TARBELL ; JP INIT JP EXEC JP CONIN JP CONOUT JP HEXIN JP HEXOUT JP DHXOT JP CRLF JP SPACE JP TREAD JP TWRIT ; MSG3: DEFM '(A)MMOD (D)MDUMP (G)RUN (P)PORT (C)MMOVE (T)MTEST (F)MFILL (M)MMAP (L)MWRT' DEFB 0DH,0AH ; 0DH=CARRIAGE RTN 0AH=LINE FEED DEFB 03H ; O3H=END OF TEXT MSG4: DEFM '(S)CSAVE (R)CLOAD (V)CVER (U)USER (X)CSYNC (Y)CADJ (B)TAPE (E)DISK (K)MENU' DEFB 0DH,0AH ; 0DH=CARRIAGE RTN 0AH=LINE FEED DEFB 03H ; O3H=END OF TEXT ; INIT: LD B,1 ; SET THE RAM FLAG ; IF SERIAL ; START OF SERIAL PORT INITIALIZATION ******** ; LD A,00H ; Initialize USART send 00H three times to guarantee device in "Command Instruction" OUT (KBDST),A LD A,00H ; INITIALIZE USART OUT (KBDST),A LD A,00H ; INITIALIZE USART OUT (KBDST),A LD A,40H ; Send internal reset "Command Instruction" (0100 0000) or 40H and ready 8251 to recieve a "Mode Instruction" OUT (KBDST),A ; Mode word:(01)-1 stop bits (00)-parity disabled (11)-char length 8 bit (10)-baud 16X ; Mode word: (01001110) or (4E)Hex...1xBaud = 153,600 1/16xBaud = 9,600 1/64xBaud = 2,400 LD A,4EH ; Mode register 8,1,n,9600 or 4EH OUT (KBDST),A ; Command word:(0)-disable hunt mode (0)-do not return to mode word (1)-reset output 0 ; Command word:(1)-reset all error flags (0)-normal operations (1)-receive enable ; Command word:(1)-DTR will output "0" (1)-transmit enable ; Command word: (0011 0111)Binary or (37)Hex LD A,37H ; Command register 37H essentially enables both transmit & recieve modes OUT (KBDST),A ; INITIALIZE THE ONBOARD UART ; ENDIF ; END SERIAL PORT INITIALIZATION ******** ; LD HL,TRUE ; PRELOAD MEMORY ADDRESS ; FTOP: INC HL ; ROUTINE TO FIND THE TOP OF MEMORY & DISPLAY IT (NOT USED) LD A,(HL) CPL LD (HL),A CP (HL) CPL LD (HL),A JP NZ,FTOP1 LD B,0 JR FTOP FTOP1: LD A,B OR A JP NZ,FTOP ; FIND TOP OF CONTIGIOUS RAM DEC HL ; AND SET STACK TO THIS VALUE DEC HL LD SP,HL PUSH HL POP IY ; SAVE STACK ADDRESS IN IY LD HL,1 ADD HL,SP ; CALL CRLF ; 1 CR/LF CALL DHXOT ; DISPLAY TOP OF MEMORY (SP) - HEX OUT TO CONSOL CALL CRLF ; 1 CR/LF ; FTOP2: LD HL,MSG1 INIT1: LD A,(HL) ; MESSAGE PRINT ROUTINE CALL CONOUT ; PRINT MESSAGE AT HL UNTIL INC HL ; END OF ENTRY IS FOUND (03H) CP 03H ; THEN GO TO MONITOR MAIN ENTRY JP NZ,INIT1 ; POINT EXEC JR EXEC IF TARBEL MSG1: DEFM 'JADE COMPUTER SYSTEMS BIG Z MONITOR 4.0B' ENDIF IF KCTAPE MSG1: DEFM 'JADE COMPUTER SYSTEMS BIG Z MONITOR 4.0A' ENDIF DEFB 03H ; 03H=END OF TEXT EXEC: CALL CRLF CALL CRLF LD SP,IY IF TARBEL SUB A OUT (TARBS),A ENDIF EXEC3: ; ROUTINE TO PRINT THE TWO LINES OF MENU COMMANDS LD HL,MSG3 KM2: LD A,(HL) ; MESSAGE PRINT ROUTINE CALL CONOUT ; PRINT MESSAGE AT HL UNTIL INC HL ; END OF ENTRY IS FOUND (03H) CP 03H ; THEN WAIT FOR KEYBOARD ENTRY JP NZ,KM2 ; OR NEXT MESSAGE LD HL,MSG4 KM3: LD A,(HL) ; MESSAGE PRINT ROUTINE CALL CONOUT ; PRINT MESSAGE AT HL UNTIL INC HL ; END OF ENTRY IS FOUND (03H) CP 03H ; THEN WAIT FOR KEYBOARD ENTRY JP NZ,KM3 ; CALL CRLF LD A,'#' ; MONITOR PROMPT: # SIGN CALL CONOUT CALL SPACE ; + + + MENU TABLE ENTRIES + + + EXEC4: CALL CONIN CP 21H JP M,EXEC4 ; LOOP ON CONTROL CHARACTERS CP 'A' JP Z,ALTER ; MODIFY MEMORY ROUTINE = A CP 'D' JP Z,DUMP ; DUMP MEMORY ROUTINE = D CP 'G' JP Z,GO ; JUMP TO ADDRESS AND RUN = G CP 'K' JP Z,KMENU ; PRINT THE MENU CHOICES = K CP 'C' JP Z,COPY ; MOVE MEMORY ROUTINE = C CP 'T' JP Z,MTEST ; TEST MEMORY ROUTINE = T CP 'F' JP Z,FILL ; FILL MEMORY ROUTINE = F CP 'M' JP Z,MEMMAP ; MAP RAM AREAS = M CP 'L' JP Z,MLOAD ; WRITE DIRECT INTO MEMORY = L CP 'P' JP Z,PORTS ; DISPLAY AVAILABLE PORTS CP 'S' JP Z,TSAVE ; SAVE MEMORY ON CASSETTE = S CP 'R' JP Z,TLOAD ; LOAD MEMORY FROM CASSETTE = R CP 'V' JP Z,VERIFY ; VERIFY TAPE WRITE = V CP 'X' JP Z,STRM ; DO A SYNC STREAM OUTPUT = X CP 'Y' JP Z,TUNE ; ADJUST CASSETTE ROUTINE = Y CP 'B' JP Z,BOOT ; TARBELL BOOT ROUTINE = B CP 'E' JP Z,0F000H ; VERSAFLOPPY II FLOPPY BOOT ROM OR OTHER BOOT ROM AT (F000H) = E CP 'U' JP Z,USER ; USER ROUTINE ; JP KMENU ; IF INCORRECT SELECTION IS MADE, CLEAR SCREEN & START AGAIN ; GO: ; JUMP TO A MEMORY LOCATION AND RUN A PROGRAM THERE CALL SPHIN CALL CRLF JP (HL) ; EXECUTE A PROGRAM AT '(HL)' NO RETURN NEED RE-BOOT ; ALTER: ; MODIFY OR EXAMINE MEMORY ROUTINE ; # A _ _ _ _ # A 0100 ; 0100 00 _ _ ; 0100 00 FF. ; 0101 00 _ _ ; 0101 00 / ; 0101 00 ; 0100 FF _ _ CALL SPHIN ALT1: CALL CRLF CALL DHXOT CALL SPACE LD A,(HL) CALL HEXOUT PUSH HL CALL SPHIN LD E,L POP HL CP 0DH ; ODH=CR MEANS DON'T CHANGE BUT DECREMENT TO THE NEXT LOCATION JP Z,ALT3 CP '/' ; THE '/' IS THE EXIT CHARACTER W/O CHANGE JP Z,EXEC CP '.' ; THE '.' IS THE MODIFY CHARACTER AS IN '0100 00 12.' JP NZ,ALT2 ; IF THE '.' IS DETECTED LD (HL),E ; LOAD THE VALUE IN 'E' TO MEMORY LOCATION '(HL)' ALT2: INC HL ; INCREMENT THE MEMORY LOCATION '(HL)' JR ALT1 ; START AGAIN AT ALT1 ALT3: DEC HL ; DECREMENT THE MEMORY LOCATION AND START AGAIN AT ALT1 JR ALT1 ; DUMP: ; DUMP MEMORY ROUTINE ; # D _ _ _ _ , _ _ _ _ # D 0100 ; 0100 D3 ; # D _ _ _ _ , _ _ _ _ # D 0100,0110 ; 0100 D3 D3 D3 D3 D3... ; 0110 D3 D3 D3 D3 D3... CALL DHXIN DUMP1: CALL CRLF CALL DHXOT LD B,16 DUMP2: CALL SPACE LD A,(HL) CALL HEXOUT CALL CMPDH JP C,EXEC ; EXIT THE ROUTINE INC HL ; INCREMENT THE PC 'HL' DEC B JP NZ,DUMP2 JR DUMP1 ; MEMMAP: CALL CRLF ; MEMORY MAP PROGRAM CF.DR.DOBBS VOL 31 P40 AND JOHN MONAHAN S-100.COM LD HL,0 ; IT WILL SHOW ON CONSOL TOTAL MEMORY SUMMARY OF RAM, PROM, AND NO MEMORY LD B,1 MAP1A: LD E,'R' ; PRINT R FOR RAM LD A,(HL) CPL LD (HL),A CP (HL) CPL LD (HL),A JP NZ,MAP2A CP (HL) JP Z,PRINTA MAP2A: LD E,'p' MAP3A: LD A,0FFH CP (HL) JP NZ,PRINTA INC L XOR A CP L JP NZ,MAP3A LD E,'.' PRINTA: LD L,0 DEC B JP NZ,NLINEA LD B,16 CALL CRLF CALL HXOT4 ; 16 HEX CONSOL OUT ROUTINE NLINEA: LD A,20H ; LOAD REG A WITH 'SPACE' (20H) CALL OTA ; SEND TO CONSOL WHAT'S IN REG A LD A,E CALL OTA ; SEND TO CONSOL WHAT'S IN REG A INC H JP NZ,MAP1A CALL CRLF CALL CRLF JP EXEC ; MLOAD: ; WRITE DIRECTLY INTO MEMORY ROUTINE: ; THIS ROUTINE WILL ACCEPT A STARTING ADDRESS FOLLOWED BY HEX DATA THAT IS ; PLACED CONSECUTIVELY INTO MEMORY. ENTERING AN '/' WILL EXIT THE ROUTINE. ; THIS COULD BE USED TO ENTER SHORT PROGRAMS INTO MEMORY TO BE RUN WITH THE ; 'GO' COMMAND. ; ; ENTER HEX VALUES STARTING AT SPECIFIC MEMORY LOCATION ; # L _ _ _ _ # L 0100 ; 0100 _ _ ; 0100 AF ; 0101 _ _ ; 0101 _ _ / ; ML1: CALL SPHIN ; GET A MEMORY ADDRESS TO PLACE THE CODE CALL CRLF ; GOTO A NEW LINE ML2: CALL DHXOT ; DISPLAY THE MEMORY ADDRESS CALL SPACE ; ADD A SPACE PUSH HL ; REG PAIR 'HL' CONTAINS ADDRESS OF DATA LOCATION IS PUSHED ONTO STACK CALL SPHIN ; ENTER SOME HEX DATA, A OR A '/' LD E,L POP HL CP '/' ; THE '/' IS THE EXIT CHARACTER W/O CHANGE JP Z,ML4 ; EXIT TO EXEC CP 0DH ; = 0DH JP NZ,ML3 ; IF THE '.' IS DETECTED LD (HL),E ; LOAD THE VALUE IN 'E' TO MEMORY LOCATION '(HL)' ML3: INC HL ; INCREMENT THE MEMORY LOCATION '(HL)' CALL CRLF JR ML2 ; START AGAIN AT ML2 ML4: CALL CRLF CALL CRLF LD A,'D' CALL CONOUT LD A,'O' CALL CONOUT LD A,'N' CALL CONOUT LD A,'E' CALL CONOUT JP EXEC ; KMENU: ; ROUTINE USING VT100 ESC COMMANDS TO CLR SCREEN 'ESC[2J' & HOME POSITION 'ESC[;H' LD A,1BH ; 1BH=ESC CALL CONOUT LD A,5BH ; 5BH=[ CALL CONOUT LD A,32H ; 32H=2 CALL CONOUT LD A,4AH ; 4AH=J CALL CONOUT ; NOW MOVE CURSOR TO HOME POSITION LD A,1BH ; 1BH=ESC CALL CONOUT LD A,5BH ; 5BH=[ CALL CONOUT LD A,48H ; 48H=H CALL CONOUT CALL CRLF JP FTOP2 ; JUMP TO FTOP2 ; FILL: ; MEMORY FILL ROUTINE ; # F _ _ _ _ , _ _ _ _ , _ _ ; # F 0100,0150,DE ; This will write "DE" into all memory locations ; between 0100 - 0150 ; Only one byte "_ _" entered is valid as the fill CALL DHXIN SUB 0DH JP Z,FILL0 PUSH HL CALL HEXIN LD A,L POP HL FILL0: DEC HL FILL1: INC HL LD (HL),A CALL CMPDH JP NC,FILL1 JP EXEC ; COPY: ; COPY MEMORY FROM ONE LOCATION TO ANOTHER LOCATION ; # C _ _ _ _ , _ _ _ _ , _ _ _ _ ; # C 0100,0150,0200 ; Copies Memory Block between 0100 - 0150 to Memory ; starting at 0200 This will over-write what is ; at Memory Location 0200 leaving 0100-0150 unchanged ; CALL TRPIN ; TRPIN: INPUT 3 WORDS...PLACE IN [HL],[DE],[BC]...ex: (hhll),(ddee),(bbcc) ; [HL]=END [DE]=BEG [BC]=DEST...WANT TO INC DE AND BC UNTIL DE=HL CALL CRLF COPY0: LD A,(DE) LD (BC),A CALL CMPDH ; COMPARES [DE] TO [HL] IF EQUAL [CARRY FLAG] = 1 JP C,EXEC ; EXIT THE ROUTINE IF [CARRY FLAG] = 1 INC DE INC BC JP COPY0 ; ; MEMORY TEST ROUTINE: (64K OR LESS) ; # T _ _ _ _ , _ _ _ _ ; # T 0100,0200 ; - WILL TEST MEMORY FROM 0100H TO 0200H ; - WILL RETURN NOTHING IF MEMORY IS OK OR ; - ADDRESS OF BAD MEMORY WITH BAD BITS ; ; THIS IS A 'QUICKIE' MEMORY TEST TO SPOT ; HARD MEMORY FAILURES, OR ACCIDENTLY ; PROTECTED MEMORY LOCATIONS. IT IS NOT ; MEANT TO BE THE DEFINITIVE MEMORY DIAGNOSTIC. ; IT IS, HOWEVER, NON-DESTRUCTIVE. ERRORS ARE ; PRINTED ON THE CONSOLE AS FOLLOWS- ; 00000100 WHERE <1> IS THE BAD BIT. ; BIT LOCATION OF THE FAILURE IS EASILY ; DETERMINED. NON-R/W MEMORY WILL RETURN ; WITH- 11111111 ; ; INPUT TWO HEX NUMBERS IN REGISTER PAIR 'HL' AND 'DE' (XXh XXh) AND (XXh XXh) MTEST: LD HL,0 ; INITIALIZE HL TO ZERO CALL DHXIN ; GET TWO PARAMETERS FROM THE CONSOL HL=(START ADDR) DE=(END ADDR) CALL CRLF MT1: LD A,(HL) ; LOAD 'REG A' WITH BYTE (HL) LD B,A ; STORE ORIGINAL BYTE (HL) TO 'REG B' CPL ; COMPLEMENT A...(INVERT A)...if 'REG A'=[11110001] => 'REG A'=[00001110] LD (HL),A ; LOAD (COMPLEMENT'd) A TO (HL) XOR (HL) ; XOR: (both bits same, then make '0')...IF NOT '0' THEN BITS ARE STUCK, BAD OR ROM JP Z,MT2 ; IF JUMP TO MT2, NO BAD MEMORY FOUND ; BAD MEMORY FOUND, DISPLAY IT ON CONSOL PUSH DE ; SAVE END POINTER 'DE' ON STACK SO 'REG D' AND 'REG E' ARE AVAILABLE FOR USE LD D,B ; LOAD 'REG D' WITH ORIGINAL BYTE (HL) THAT IS BAD LD E,A ; LOAD 'REG E' WITH CMP AND XOR BYTE (HL) ??? CALL BAD ; PRINT 'BAD: ' TO THE CONSOL (AF AND HL ARE UNCHANGED IN ROUTINE 'BAD') LD A,E ; MAKE SURE 'REG A' IS UNCHANGED AFTER MSG CALL HLSP ; PRINT 'HL' TO CONSOL FOLLOWED BY A SPACE LD A,' ' ; SEND ' ' BLANK TO CONSOL OUT CALL CONOUT LD A,E CALL BITS1 ; CONVERT HEX TO BINARY BITS AND DISPLAY CALL CRLF LD B,D POP DE MT2: LD (HL),B ; RESTORE SAVED BYTE (HL) ; NOW SEE IF WE REACHED THE END MND1: LD A,H ; COMPARE H[XXXX]L TO D[XXXX]E LD C,D CP C ; DOES H=D JP Z,MND2 ; IF H=D GOTO MND2 JR INCR1 ; H<>D GOTO INCR1 MND2: LD A,L ; COMPARE H[XXXX]L TO D[XXXX]E LD C,E ; DOES L=E CP C ; IF L=E WE ARE ALL DONE SO GOTO MND3 JP Z,MND3 ; IF L<>E CONTINUE TO INCR1 ; INCR1: INC HL ; INC HL, THIS MOVES HL (START) CLOSER TO DE (END) JR MT1 ; NOT THERE YET SO GO BACK FOR MORE ; MND3: CALL CRLF ; REACHED THE END LD A,'E' CALL CONOUT LD A,'N' CALL CONOUT LD A,'D' CALL CONOUT JP EXEC ; PORTS: ; PORTS ROUTINE TO DISPLAY DETECTED PORTS - FROM JOHN MONAHAN S100.COM ; CALL CRLF LD B,0 ; LOOP THROUGH ALL PORTS (0-FF) LD D,6 ;Display 6 ports across LD E,0FFH ;Will contain port number ; LOOPIO: LD C,E ; LOAD 'REG C' WITH 0FFH LD A,E ; LOAD 'REG A' WITH 0FFH ; IN A,(C) ; Remember [ZASMB does not work with this opcode,SLR is OK] CP 0FFH ; JR Z,SKIP ; IF DATA PORT C CONTAINS (FF)H, SKIP IT LD H,A ; DATA PORT C HAS SOMETHING SO STORE IN 'H' FOR BELOW LD A,E ; LOAD CURRENT PORT NUMBER TO 'REG A' CALL LBYTE ; PRINT PORT NUMBER LD A,'-' CALL CONOUT LD A,'>' CALL CONOUT LD A,H ; GET PORT DATA STORED IN 'H' CALL LBYTE ; PRINT TO CONSOL LD A,09H ; 09H = TAB CALL CONOUT DEC D ; 6 PORTS PER LINE JR NZ,SKIP LD D,6 CALL CRLF SKIP: DEC E ; NEXT PORT DJNZ LOOPIO CALL CRLF JP EXEC ; USER: ; ; ; ****** USER ROUTINE HERE ****** ; JP EXEC ; ;***********************MESSAGE ROUTINE************************************* ;MSG6: DEFM 'YOUR MESSAGE HERE' ; DEFB 03H ; END OF TEXT '03H' ; LD HL,MSG6 ;KX6: LD A,(HL) ; MESSAGE PRINT ROUTINE [DO NOT USE COMMA AS PUNCTUATION!!!] ; CALL CONOUT ; PRINT MESSAGE AT HL UNTIL ; INC HL ; END OF ENTRY IS FOUND (03H) ; CP 03H ; JP NZ,KX6 ; JP EXEC ; EXIT TO MENU ;***********************MESSAGE ROUTINE************************************* ; ;***********************EXIT ROUTINE**************************************** ;EXIT: ; HL CONTAINED THE 'START BYTE' THAT IS BEING INCREMENTED TO MATCH DE THE 'END BYTE' ; ; 'REG H' COMPARED TO 'REG D' THEN 'REG L' COMPARED TO 'REG E' IF ZERO, END ;END1: LD A,H ; LOAD 'REG H' FROM HL PAIR ; LD C,D ; LOAD 'REG D' FROM DE PAIR ; CP C ; NOW COMPARE 'REG H' TO 'REG D' ; JP Z,END2 ; IF AT ZERO, GO CHECK 'L' AND 'E' ; JR INCR1 ;END2: LD A,L ; LOAD 'REG L' FROM HL PAIR ; LD C,E ; LOAD 'REG E' FROM DE PAIR ; CP C ; NOW COMPARE 'REG L' TO 'REG E' ; JP Z,END3 ; IF ZERO WE ARE AT END SO GO TO 'END3' ;INCR1: INC HL ; WE ARE NOT AT THE END, SO INCREMENT HL ; RET ; ;END3: JP EXEC ; ALL FINISHED NOW EXIT ;***********************EXIT ROUTINE*************************************** ; IF KCTAPE ; BEGIN BLOCK FOR KCTAPE ROUTINES ======================================= ; *RULES FOR WRITING/READING SOFTWARE FROM CASSETTE TAPE- ; *1) 1ST BYTE MUST BE 'START BYTE' = (3C)H ; *2) 2ND BYTE MUST BE 'SYNC BYTE' = (E6)H ; *3) 'DATA BYTES' ARE SENT NEXT AS SEQUENTIAL DATA ; *4) 'STOP BYTE' = (1A)H IDENTIFIED AS SUCH BY IMMEDIATELY FOLLOWING WITH (FF)H ; *5) 'CKSUM BYTE' WILL FOLLOW IF USED, OTHERWISE THERE WILL BE (FF)H ; ; * EXAMPLE: FF FF FF FF [3C] [E6] [DD DD DD DD DD DD] [1A] [FF] [CKSUM] FF FF FF ; ; DATA PORT = (TAPE) STATUS PORT = (TAPST) ; READY TO SEND DATA FROM JADE 2S1P = TBMT = 1 ==> (80)H or (1000 0000)B ; READY TO RECV DATA TO JADE 2S1P = DAV = 1 ==> (10)H OR (0001 0000)B ; TLOAD: ; ROUTINE TO LOAD DATA FROM CASSETTE TAPE TO COMPUTER MEMORY ; INPUT REQUIRED WILL BE MEMORY LOCATION IN COMPUTER TO PLACE DATA ; # R _ _ _ _ ; # R 0100 ... WILL START THE ROUTINE SO TAPE PLAYER SHOULD BE READY ; NOTE THAT THIS IS A CRUDE SYSTEM AND OPERATOR IS RESPONSIBLE FOR DATA ; THAT IS OVER-WRITTEN BY MISTAKE. ; CALL SPHIN ; GET A MEMORY ADDRESS TO PLACE THE CODE, STORE IN HL CALL CRLF ; GOTO A NEW LINE ; TREAD: LD A,0B0H ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA OUT (TAPST),A ; SEND CNTL WORD TO PROGRAM AY51013 UART ON JADE 2S1P PORT (TAPST) TRDA: LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM TRDB: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0FFH ; IS THIS A LEADER (FF)H (SEE ABOVE) JP NZ,TRDB ; NOPE, TRY AGAIN UNTIL (FF)H RECEIVED ; TRDC: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 03CH ; LOOK FOR 'START BYTE' DISCARD LEADER (FF)H JP NZ,TRDC ; FOUND THE 'START BYTE', 'SYNC BYTE' SHOULD BE NEXT CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0E6H JP NZ,ER1 ; DIDN'T FIND A 'SYNC BYTE' SO GOTO ERROR MESSAGE #1 ; FOUND THE 'SYNC BYTE', SO DATA SHOULD COME NEXT TRDD: CALL CIN ; GET 'CHR_A' FROM TAPE, STORE IN 'REG A' LD D,A ; LOAD 'CHR_A' TO 'REG D' LD A,1AH ; LOAD A WITH THE 'STOP BYTE' CP D JP NZ,TRDE ; DID NOT FIND 'STOP BYTE' SO GOTO TRDE ; DID FIND A 'STOP BYTE' SEE IF IT HAS AN (FF)H NEXT CALL CIN ; GET 'CHR_B' FROM TAPE, STORE IN 'REG A' LD E,A ; LOAD 'CHR_B' TO 'REG E' LD A,0FFH CP E ; IF 'E' WAS (FF)H THEN YES WE ARE AT THE END OF THE TAPE JP Z,TREND ; IF 'E' WAS NOT (FF)H THEN WE JUST READ TWO VALID CHARACTERS THAT NEED TO GO TO MEMORY LD A,D ; LOAD 'CHR_A' TO 'A' CALL TRPUT ; GO PUT IT LD A,E ; LOAD 'CHR_B' TO 'A' ; TRDE: CALL TRPUT ; GO PUT IT JP TRDD ; GO BACK FOR MORE DATA ; TREND: ; THE 'STOP BYTE' AND FOLLOWING (FF)H BYTE HAVE BEEN FOUND SO WE ARE AT END OF TAPE ; IF A CHECKSUM WAS USED FOR THIS TAPE IT SHOULD BE THE FOLLOWING BYTE, ; IF NOTE, THE CHECKSUM WILL BE (FF)H SO THAT'S OKAY TOO CALL CIN ; GET 'CKSUM' FROM TAPE, STORE IN 'REG A' LD C,A ; STORE THE TAPE CHECKSUM INTO 'C' CALL END1 ; GOTO END MESSAGE AND EXIT ; TRPUT: LD A,D ; NO 'STOP BYTE' SO LOAD TO MEMORY BY MOVING D BACK TO A LD (HL),A ; LOAD CHARACTER READ TO MEMORY LOCATION HL CALL DHXOT ; SEND HL MEMORY ADDRESS TO CONSOL - USER CAN SEE IF TAPE OVER-WRITES GOOD MEMORY LD A,(HL) ; MOVE CONTENTS (HL) BACK TO 'A', SOULD BE THE SAME ADD B ; ADD 'B' TO 'A' AND STORE IN 'A' LD B,A ; LOAD 'A' BACK TO 'B' AS A CHECKSUM INC HL ; INCREMENT THE MEMORY POINTER RET ; GO GET MORE DATA ; END1: CALL CRLF ; WE GOT HERE BY FINDING THE 'STOP BYTE' FOLLOWED BY 'FF' LD HL,MSG5 ; PRINT OUT MESSAGE LISTING BLOCKS READ VS BLOCKS STORED TO MEMORY KX5: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX5 LD A,B ; 'REG B' FINAL CALCULATED CHECKSUM CALL HEXOUT LD A,02FH ; SEND A '/' TO THE CONSOL CALL CONOUT LD A,C ; 'REG C' CHECKSUM READ FROM TAPE...IF IT'S (FF)H THERE WAS NO CHECKSUM CALL HEXOUT MSG5: DEFM 'END LOAD...CHECKSUM/TAPE CHECKSUM: ' DEFB 03H ; END OF TEXT '03H' JP KEXIT ; EXIT TO MENU ; ER1: CALL CRLF ; WE GOT HERE BY NOT FINDING THE 'SYNC BYTE' AT START OF TAPE LD HL,MSG6 ; PRINT OUT ERROR MESSAGE KX6: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX6 MSG6: DEFM 'ERROR - SYNC NOT FOUND' DEFB 03H ; END OF TEXT '03H' JP KEXIT ; EXIT TO MENU ; TSAVE: ; ROUTINE TO SAVE COMPUTER MEMORY TO A CASSETTE TAPE FILE ; INPUT REQUIRED WILL BE 'START' MEMORY LOCATION AND 'END' MEMORY LOCATION ; IN COMPUTER TO DEFINE MEMORY TO BE WRITTEN TO TAPE. ; # S _ _ _ _ , _ _ _ _ ; # S 0100,0150 ... THIS WILL SAVE (0100)H - (0150)H TO TAPE ; WILL START THE ROUTINE SO TAPE PLAYER SHOULD BE READY. ; CALL DHXIN ; GET TWO PARAMETERS FROM THE CONSOL HL=(START ADDR) DE=(END ADDR) CALL CRLF TWRIT: LD A,0B0H ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA OUT (TAPST),A ; SEND CNTL WORD TO PROGRAM AY51013 UART ON JADE 2S1P PORT (TAPST) ; ; ; TLEAD = LENGTH OF LEADER BYTES (FF)H SPECIFIED IN EQUATES LD B,(TLEAD) ; LOAD 'REG B' WITH TLEAD...COUNTER TWRT0: LD A,0FFH ; LOAD 'REG A' WITH (FF)H CALL COUT ; WRITE AN (FF)H TO TAPE DEC B JP NZ,TWRT0 ; WRITE LEADER OF (FF)H TO TAPE ; LD A,03CH ; LOAD 'REG A' WITH (3C)H THE 'START BYTE' CALL COUT ; WRITE (3C)H TO TAPE ; LD A,0E6H ; LOAD 'REG A' WITH (E6)H THE 'SYNC BYTE' CALL COUT ; WRITE (E6)H TO TAPE ; ; NOW, READY TO WRITE DATA FROM MEMORY TO TAPE LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM CALCULATION TWRT1: LD A,(HL) ; LOAD 'REG A' WITH (HL) CALL COUT ; WRITE IT TO TAPE CALL CMPDH ; COMPARES [DE] TO [HL] IF EQUAL [CARRY FLAG] = 1 'DOES NOT INC ANYTHING' JP C,END2 ; EXIT THE ROUTINE IF [CARRY FLAG] = 1 LD A,(HL) ; LOAD 'REG A' WITH (HL) ADD B ; ADD 'B' TO 'A' AND STORE IN 'A' LD B,A ; LOAD 'A' BACK TO 'B' AS A CHECKSUM INC HL JP TWRT1 ; GO SEND MORE DATA TO TAPE ; ; ARRIVED HERE BECAUSE HL = DE. NOW SEND 'STOP BYTE',(FF)H,'CKSUM', AND LEADER END2: LD A,1AH ; LOAD 'A' WITH THE 'STOP BYTE' (1A)H CALL COUT ; SEND TO TAPE LD A,0FFH ; LOAD 'A' WITH THE FOLLOWING (FF)H CALL COUT ; SEND TO TAPE LD A,B ; LOAD 'A' WITH THE 'CKSUM' BYTE CALL COUT ; SEND TO TAPE ; LD C,(TTRAL) ; TTRAL = NUMBER OF TRAILING (FF)H AFTER ALL THE DATA AND CHECKSUM XRV: LD A,0FFH ; TRAILER (FF)H CALL COUT ; SEND TO TAPE DEC C JP NZ,XRV ; ALL (FF)H TRAILERS HAVE BEEN SENT ; END3: CALL CRLF ; WE GOT HERE BY SENDING ALL THE DATA SO WE ARE DONE MSG7: DEFM 'SAVE DONE - STOP TAPE - CHECKSUM: ' DEFB 03H ; END OF TEXT '03H' LD HL,MSG7 ; PRINT OUT MESSAGE KX7: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX7 LD A,B ; LOAD 'A' WITH THE CALCULATED CHKSUM CALL HEXOUT ; SEND HEX VALUES TO CONSOL JP KEXIT ; EXIT TO MENU ; STRM: CALL SPACE ; SYNC STREAM OUTPUT ROUTINE - WILL SEND A STREAM OF (E6)H BYTES TO TAPE...'FF [E6] FF [E6] FF' LD B,080H ; USE 'REG B' AS A COUNTER LD A,0B0H ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA OUT (TAPST),A ; SEND CNTL WORD TO PROGRAM AY51013 UART ON JADE 2S1P PORT (TAPST) STRM1: LD A,0FFH ; LOAD 'REG A' WITH (FF)H CALL COUT ; WRITE TO CASSETTE TAPE LD A,0E6H ; LOAD 'SYNC BYTE' (E6)H TO 'REG A' CALL COUT ; WRITE TO CASSETTE TAPE DEC B JP NZ,STRM1 ; LOOP 128 TIMES JP KEXIT ; JUMP TO EXIT ; CIN: IN A,(TAPST) ; INPUT 'STATUS SENSE' (xxx1xxxx)B = 10H => CHARACTER READY TO TRANSMIT AND 10H ; IF 'STATUS SENSE' = 10H, GET A CHARACTER OR LOOP UNTIL READY JP Z,CIN ; (DAV) BIT IS NOT '1' SO NO CHARACTER IN A,(TAPE) ; CHARACTER IS READY SO 'IN' FROM PORT (TAPE) TO 'REG A' RET ; COUT: IN A,(TAPST) ; JADE 2S1P STATUS SENSE (1xxxxxxx)B = 80H => TRANSMITTER BUFFER IS EMPTY (TBMT)=1 AND 80H ; IF 'STATUS SENSE' = 80H, SEND A CHARACTER OR LOOP UNTIL READY JP Z,COUT ; IF (TBMT) IS NOT EMPTY, TRY AGAIN OUT (TAPE),A ; BUFFER IS EMPTY SO 'OUT' FROM 'REG A' TO PORT (TAPE) RET ; TUNE: ; TUNE ROUTINE - TO ADJUST CASSETTE VOLUME AND TONE CONTROLS FOR BEST RESULTS ; IT WILL ALSO DISPLAY ON THE CONSOL WHATEVER IS READ IN FROM THE TAPE CASSETTE ; ; FORMAT: FF FF FF FF [3C] [E6] DD DD DD DD DD DD [1A] FF [CKSUM] FF FF FF FF ; CONSOL: LL LL LL LL (ST) (SY) (data) (SP) LL (data) LL LL LL LL ; CALL SPACE LD A,0B0H ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA OUT (TAPST),A ; SEND CNTL WORD TO PROGRAM AY51013 UART ON JADE 2S1P PORT (TAPST) TUN0: CALL CRLF CALL CRLF CALL SPACE LD B,04BH ; B = CHARACTERS PER LINE = (75)D TUN1: CALL CIN ; CHECK FOR LEADER OF (FF)H CP 0FFH JP NZ,TUN1 ; KEEP LOOPING UNTIL THE LEADER OF (FF)H HAS BEEN FOUND JR TL ; TUN2: CALL CIN ; LOAD THE CHARACTER READ IN TO 'C' LD C,A ; BECAUSE 'A' WILL BE CHANGED BY THE CP INSTRUCTION CP 0FFH ; COMPARE A TO LEADER OF (FF)H JP Z,TL LD A,C CP 03CH ; COMPARE A TO START OF (3C)H JP Z,TST LD A,C CP 0E6H ; COMPARE A TO SYNC OF (E6)H JP Z,TSY LD A,C CP 01AH ; COMPARE A TO STOP OF (1A)H JP Z,TSP ; PASSED THROUGH ALL THE FILTERS SO IT MUST BE DATA OR CHECKSUM LD A,C CALL HEXOUT ; SEND TO CONSOL AS HEX CALL SPACE DEC B ; DEC THREE TIMES FOR 'CH'+'CH'+'SPACE' DEC B DEC B JP NZ,TUN2 LD B,04BH ; RESET THE CHARACTERS PER LINE COUNTER CALL CRLF CALL SPACE JR TUN2 TL: LD D,'L' LD E,'L' JR TUN3 TST: LD D,'S' LD E,'T' JR TUN3 TSY: LD D,'S' LD E,'Y' JR TUN3 TSP: LD D,'S' LD E,'P' TUN3: LD A,D ; SEND TO CONSOL THE TWO LETTERS IN DE CALL CONOUT LD A,E ; SEND TO CONSOL THE TWO LETTERS IN DE CALL CONOUT CALL SPACE DEC B DEC B DEC B JP NZ,TUN2 LD B,04BH ; RESET THE CHARACTERS PER LINE CALL CRLF CALL SPACE JR TUN2 ; VERIFY: ; VERIFY CASSETTE TAPE TO MEMORY ROUTINE ; THIS ROUTINE WILL ACCEPT A STARTING MEMORY ADDRESS AND AN ENDING ; MEMORY ADDRESS (BLOCK WRITTEN TO TAPE) AND VERIFY THE SAME DATA ; IS ON THE CASSETTE TAPE AS A WAY TO VERIFY PROGRAM/DATA STORAGE. ; ; # V _ _ _ _ , _ _ _ _ ; # V 0100,0150 ... THIS WILL COMPARE MEMORY (0100)H - (0150)H ; TO THE PROGRAM ON CASSETTE TAPE. WILL START THE ROUTINE SO ; TAPE PLAYER SHOULD BE READY. ; ; REG HL = [START ADDRESS] ; REG DE = [END ADDRESS] ; REG B = CALCULATED CHECKSUM ; REG C = MEMORY <> TAPE COUNTER ; FORMAT: FF FF FF [3C] [E6] DD DD DD DD DD DD [1A] FF [CKSUM] FF FF FF ; CALL DHXIN ; GET TWO PARAMETERS FROM THE CONSOL HL=(START ADDR) DE=(END ADDR) CALL CRLF VRFY1: LD A,0B0H ; JADE 2S1P CNTL WORD (10110000)B = B0H => NOP,1STOP,8DATA OUT (TAPST),A ; SEND CNTL WORD TO PROGRAM AY51013 UART ON JADE 2S1P PORT (TAPST) ; VRFA: LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM LD C,0H ; LOAD 'REG C' WITH (00)H FOR ERROR COUNT PUSH DE ; SAVE 'DE' ON STACK SO 'D' AND 'E' ARE AVAILABLE FOR USE VRFB: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0FFH ; IS THIS A LEADER (FF)H JP NZ,VRFB ; NOPE, TRY AGAIN UNTIL (FF)H RECEIVED ; VRFC: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 03CH ; LOOK FOR 'START BYTE' DISCARD LEADER (FF)H JP NZ,VRFC ; FOUND THE 'START BYTE', 'SYNC BYTE' SHOULD BE NEXT CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0E6H JP NZ,VX6 ; DIDN'T FIND A 'SYNC BYTE' SO GOTO ERROR MESSAGE ; FOUND THE 'SYNC BYTE', SO DATA SHOULD COME NEXT ; VRFD: CALL CIN ; GET DATA FROM TAPE, STORE IN 'REG A' LD D,A ; STORE TAPE DATA IN 'REG D' VRFE: LD A,(HL) ; STORE MEMORY DATA IN 'REG A' CP C ; COMPARE 'D' TO 'A' JP Z,VRFF ; IF MEMORY=TAPE CONTINUE AT VRFF INC C ; FOUND A BAD MATCH, UPDATE BAD COUNTER VRFF: LD A,(HL) ; UPDATE THE CHECKSUM ADD B ; ADD 'REG A' = 'REG B' LD B,A ; STORE BACK IN 'REG B' ; VRFG: POP DE ; 'REG H' CP TO 'REG D' THEN 'REG L' CP TO 'REG E' IF ZERO, END VRFH: LD A,H ; LOAD 'REG H' FROM HL PAIR LD C,D ; LOAD 'REG D' FROM DE PAIR CP C ; NOW COMPARE 'REG H' TO 'REG D' JP Z,VRFI ; IF AT ZERO, GO CHECK 'L' AND 'E' JP VRFJ ; H <> D SO NO NEED TO CHECK MORE, GET MORE DATA VRFI: LD A,L ; LOAD 'REG L' FROM HL PAIR LD C,E ; LOAD 'REG E' FROM DE PAIR CP C ; NOW COMPARE 'REG L' TO 'REG E' JP Z,VRFK ; IF ZERO WE ARE AT END VRFJ: PUSH DE ; SAVE 'DE' INC HL ; NOT DONE SO INC HL JR VRFD ; GO BACK AND GET MORE DATA ; VRFK: ; WE GOT HERE BECAUSE HL=DE VX4: CALL CRLF LD HL,MSG8 ; PRINT OUT MESSAGE KX8: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX8 LD A,B ; 'REG B' FINAL CALCULATED CHECKSUM CALL HEXOUT LD A,02FH ; SEND A '/' TO THE CONSOL CALL CONOUT LD A,C ; 'REG C' ERRORS WHERE TAPE <> MEMORY CALL HEXOUT ; VX5: CALL CRLF ; PRINT OUT LAST TAPE BYTES TO ENSURE [1A] FF [CKSUM] FF... LD HL,MSG9 ; PRINT OUT MESSAGE KX9: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX9 ; END OF MESSAGE PRINT ROUTINE LD C,04H ; SET 'C' COUNTER TO 4 LZ1: CALL CIN ; READ THE NEXT FOUR BYTES FROM TAPE CALL HEXOUT CALL SPACE DEC C JP Z,KEXIT JR LZ1 ; VX6: CALL CRLF ; PRINT OUT ERROR MESSAGE 'SYNC BYTE' NOT FOUND LD HL,MSG6 ; PRINT OUT MESSAGE KX10: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX10 ; END OF MESSAGE PRINT ROUTINE JP KEXIT ; MSG8: DEFM 'LOAD COMPLETE...CALCULATED CHECKSUM/TOTAL TAPE ERRORS: ' DEFB 03H ; END OF TEXT '03H' JR KEXIT ; EXIT TO MENU ; MSG9: DEFM 'NEXT FOUR BYTES - [1A] [FF] [CKSUM] [FF]: ' DEFB 03H ; END OF TEXT '03H' JR KEXIT ; EXIT TO MENU ; ENDIF ; END BLOCK FOR KCTAPE ROUTINES ==================================== KEXIT: JP EXEC ; EXIT AND GO BACK TO MENU ; ; ; IF TARBEL ; BEGIN BLOCK FOR TARBELL ROUTINES ================================= ; *RULES FOR WRITING/READING SOFTWARE FROM CASSETTE TAPE- ; *1) 1ST BYTE MUST BE 'START BYTE' = (3C)H ; *2) 2ND BYTE MUST BE 'SYNC BYTE' = (E6)H ; *3) 'DATA BYTES' ARE SENT NEXT AS SEQUENTIAL DATA ; *4) 'STOP BYTE' = (1A)H IDENTIFIED AS SUCH BY IMMEDIATELY FOLLOWING WITH (FF)H ; *5) 'CKSUM BYTE' WILL FOLLOW IF USED, OTHERWISE THERE WILL BE (FF)H ; ; * EXAMPLE: FF FF FF FF [3C] [E6] [DD DD DD DD DD DD] [1A] [FF] [CKSUM] FF FF FF ; ; DATA PORT = (TARBD) STATUS PORT = (TARBS) ; READY TO SEND DATA FROM TARBELL = 1 ==> (20)H or (0010 0000)B ; READY TO RECV DATA TO TARBELL = 1 ==> (10)H OR (0001 0000)B ; TLOAD: ; ROUTINE TO LOAD DATA FROM CASSETTE TAPE TO COMPUTER MEMORY ; INPUT REQUIRED WILL BE MEMORY LOCATION IN COMPUTER TO PLACE DATA ; # R _ _ _ _ ; # R 0100 ... WILL START THE ROUTINE SO TAPE PLAYER SHOULD BE READY ; NOTE THAT THIS IS A CRUDE SYSTEM AND OPERATOR IS RESPONSIBLE FOR DATA ; THAT IS OVER-WRITTEN BY MISTAKE. ; CALL SPHIN ; GET A MEMORY ADDRESS TO PLACE THE CODE, STORE IN HL CALL CRLF ; GOTO A NEW LINE ; TREAD: ; READ DATA TRDA: LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM TRDB: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0FFH ; IS THIS A LEADER (FF)H (SEE ABOVE) JP NZ,TRDB ; NOPE, TRY AGAIN UNTIL (FF)H RECEIVED ; TRDC: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 03CH ; LOOK FOR 'START BYTE' DISCARD LEADER (FF)H JP NZ,TRDC ; FOUND THE 'START BYTE', 'SYNC BYTE' SHOULD BE NEXT CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0E6H JP NZ,ER1 ; DIDN'T FIND A 'SYNC BYTE' SO GOTO ERROR MESSAGE #1 ; FOUND THE 'SYNC BYTE', SO DATA SHOULD COME NEXT TRDD: CALL CIN ; GET 'CHR_A' FROM TAPE, STORE IN 'REG A' LD D,A ; LOAD 'CHR_A' TO 'REG D' LD A,1AH ; LOAD A WITH THE 'STOP BYTE' CP D JP NZ,TRDE ; DID NOT FIND 'STOP BYTE' SO GOTO TRDE ; DID FIND A 'STOP BYTE' SEE IF IT HAS AN (FF)H NEXT CALL CIN ; GET 'CHR_B' FROM TAPE, STORE IN 'REG A' LD E,A ; LOAD 'CHR_B' TO 'REG E' LD A,0FFH CP E ; IF 'E' WAS (FF)H THEN YES WE ARE AT THE END OF THE TAPE JP Z,TREND ; IF 'E' WAS NOT (FF)H THEN WE JUST READ TWO VALID CHARACTERS THAT NEED TO GO TO MEMORY LD A,D ; LOAD 'CHR_A' TO 'A' CALL TRPUT ; GO PUT IT LD A,E ; LOAD 'CHR_B' TO 'A' ; TRDE: CALL TRPUT ; GO PUT IT JP TRDD ; GO BACK FOR MORE DATA ; TREND: ; THE 'STOP BYTE' AND FOLLOWING (FF)H BYTE HAVE BEEN FOUND SO WE ARE AT END OF TAPE ; IF A CHECKSUM WAS USED FOR THIS TAPE IT SHOULD BE THE FOLLOWING BYTE, ; IF NOTE, THE CHECKSUM WILL BE (FF)H SO THAT'S OKAY TOO CALL CIN ; GET 'CKSUM' FROM TAPE, STORE IN 'REG A' LD C,A ; STORE THE TAPE CHECKSUM INTO 'C' CALL END1 ; GOTO END MESSAGE AND EXIT ; TRPUT: LD A,D ; NO 'STOP BYTE' SO LOAD TO MEMORY BY MOVING D BACK TO A LD (HL),A ; LOAD CHARACTER READ TO MEMORY LOCATION HL CALL DHXOT ; SEND HL MEMORY ADDRESS TO CONSOL - USER CAN SEE IF TAPE OVER-WRITES GOOD MEMORY LD A,(HL) ; MOVE CONTENTS (HL) BACK TO 'A', SOULD BE THE SAME ADD B ; ADD 'B' TO 'A' AND STORE IN 'A' LD B,A ; LOAD 'A' BACK TO 'B' AS A CHECKSUM INC HL ; INCREMENT THE MEMORY POINTER RET ; GO GET MORE DATA ; END1: CALL CRLF ; WE GOT HERE BY FINDING THE 'STOP BYTE' FOLLOWED BY 'FF' LD HL,MSG5 ; PRINT OUT MESSAGE LISTING BLOCKS READ VS BLOCKS STORED TO MEMORY KX5: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX5 LD A,B ; 'REG B' FINAL CALCULATED CHECKSUM CALL HEXOUT LD A,02FH ; SEND A '/' TO THE CONSOL CALL CONOUT LD A,C ; 'REG C' CHECKSUM READ FROM TAPE...IF IT'S (FF)H THERE WAS NO CHECKSUM CALL HEXOUT MSG5: DEFM 'END LOAD...CHECKSUM/TAPE CHECKSUM: ' DEFB 03H ; END OF TEXT '03H' JP TEXIT ; EXIT TO MENU ; ER1: CALL CRLF ; WE GOT HERE BY NOT FINDING THE 'SYNC BYTE' AT START OF TAPE LD HL,MSG6 ; PRINT OUT ERROR MESSAGE KX6: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX6 MSG6: DEFM 'ERROR - SYNC NOT FOUND' DEFB 03H ; END OF TEXT '03H' JP TEXIT ; EXIT TO MENU ; TSAVE: ; ROUTINE TO SAVE COMPUTER MEMORY TO A CASSETTE TAPE FILE ; INPUT REQUIRED WILL BE 'START' MEMORY LOCATION AND 'END' MEMORY LOCATION ; IN COMPUTER TO DEFINE MEMORY TO BE WRITTEN TO TAPE. ; # S _ _ _ _ , _ _ _ _ ; # S 0100,0150 ... THIS WILL SAVE (0100)H - (0150)H TO TAPE ; WILL START THE ROUTINE SO TAPE PLAYER SHOULD BE READY. ; CALL DHXIN ; GET TWO PARAMETERS FROM THE CONSOL HL=(START ADDR) DE=(END ADDR) CALL CRLF ; TWRIT: ; TLEAD = LENGTH OF LEADER BYTES (FF)H SPECIFIED IN EQUATES LD B,(TLEAD) ; LOAD 'REG B' WITH TLEAD...COUNTER TWRT0: LD A,0FFH ; LOAD 'REG A' WITH (FF)H CALL COUT ; WRITE AN (FF)H TO TAPE DEC B JP NZ,TWRT0 ; WRITE LEADER OF (FF)H TO TAPE ; LD A,03CH ; LOAD 'REG A' WITH (3C)H THE 'START BYTE' CALL COUT ; WRITE (3C)H TO TAPE ; LD A,0E6H ; LOAD 'REG A' WITH (E6)H THE 'SYNC BYTE' CALL COUT ; WRITE (E6)H TO TAPE ; ; NOW, READY TO WRITE DATA FROM MEMORY TO TAPE LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM CALCULATION TWRT1: LD A,(HL) ; LOAD 'REG A' WITH (HL) CALL COUT ; WRITE IT TO TAPE CALL CMPDH ; COMPARES [DE] TO [HL] IF EQUAL [CARRY FLAG] = 1 'DOES NOT INC ANYTHING' JP C,END2 ; EXIT THE ROUTINE IF [CARRY FLAG] = 1 LD A,(HL) ; LOAD 'REG A' WITH (HL) ADD B ; ADD 'B' TO 'A' AND STORE IN 'A' LD B,A ; LOAD 'A' BACK TO 'B' AS A CHECKSUM INC HL JP TWRT1 ; GO SEND MORE DATA TO TAPE ; ; ARRIVED HERE BECAUSE HL = DE. NOW SEND 'STOP BYTE',(FF)H,'CKSUM', AND LEADER END2: LD A,1AH ; LOAD 'A' WITH THE 'STOP BYTE' (1A)H CALL COUT ; SEND TO TAPE LD A,0FFH ; LOAD 'A' WITH THE FOLLOWING (FF)H CALL COUT ; SEND TO TAPE LD A,B ; LOAD 'A' WITH THE 'CKSUM' BYTE CALL COUT ; SEND TO TAPE ; LD C,(TTRAL) ; TTRAL = NUMBER OF TRAILING (FF)H AFTER ALL THE DATA AND CHECKSUM XRV: LD A,0FFH ; TRAILER (FF)H CALL COUT ; SEND TO TAPE DEC C JP NZ,XRV ; ALL (FF)H TRAILERS HAVE BEEN SENT ; END3: CALL CRLF ; WE GOT HERE BY SENDING ALL THE DATA SO WE ARE DONE MSG7: DEFM 'SAVE DONE - STOP TAPE - CHECKSUM: ' DEFB 03H ; END OF TEXT '03H' LD HL,MSG7 ; PRINT OUT MESSAGE KX7: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX7 LD A,B ; LOAD 'A' WITH THE CALCULATED CHKSUM CALL HEXOUT ; SEND HEX VALUES TO CONSOL JP TEXIT ; EXIT TO MENU ; STRM: CALL SPACE ; SYNC STREAM OUTPUT ROUTINE - WILL SEND A STREAM OF (E6)H BYTES TO TAPE...'FF [E6] FF [E6] FF' LD B,080H ; USE 'REG B' AS A COUNTER STRM1: LD A,0FFH ; LOAD 'REG A' WITH (FF)H CALL COUT ; WRITE TO CASSETTE TAPE LD A,0E6H ; LOAD 'SYNC BYTE' (E6)H TO 'REG A' CALL COUT ; WRITE TO CASSETTE TAPE DEC B JP NZ,STRM1 ; LOOP 128 TIMES JP TEXIT ; JUMP TO EXIT ; CIN: IN A,(TARBS) ; INPUT 'STATUS' (xxx1 xxxx)B = 10H => READY TO RECEIVE DATA AND 10H ; IF 'STATUS' = 10H, RECEIVE A CHARACTER OR LOOP UNTIL READY JP Z,CIN ; BIT IS NOT '1' SO NOT READY TO RECEIVE DATA IN A,(TARBD) ; CHARACTER IS READY SO 'IN' FROM PORT (TARBD) FROM TAPE RET ; COUT: IN A,(TARBS) ; OUTPUT 'STATUS' (xx1x xxxx)B = 20H => READY TO TRANSMITTER DATA AND 20H ; IF 'STATUS' = 20H, TRANSMIT A CHARACTER OR LOOP UNTIL READY JP Z,COUT ; BIT IS NOT '1' SO NOT READY TO TRANSMIT, TRY AGAIN OUT (TARBD),A ; CHARACTER IS READY, SO 'OUT' FROM PORT (TARBD) TO TAPE RET ; TUNE: ; TUNE ROUTINE - TO ADJUST CASSETTE VOLUME AND TONE CONTROLS FOR BEST RESULTS ; IT WILL ALSO DISPLAY ON THE CONSOL WHATEVER IS READ IN FROM THE TAPE CASSETTE ; ; FORMAT: FF FF FF FF [3C] [E6] DD DD DD DD DD DD [1A] FF [CKSUM] FF FF FF FF ; CONSOL: LL LL LL LL (ST) (SY) (data) (SP) LL (data) LL LL LL LL ; CALL SPACE TUN0: CALL CRLF CALL CRLF CALL SPACE LD B,04BH ; B = CHARACTERS PER LINE = (75)D TUN1: CALL CIN ; CHECK FOR LEADER OF (FF)H CP 0FFH JP NZ,TUN1 ; KEEP LOOPING UNTIL THE LEADER OF (FF)H HAS BEEN FOUND JR TL ; TUN2: CALL CIN ; LOAD THE CHARACTER READ IN TO 'C' LD C,A ; BECAUSE 'A' WILL BE CHANGED BY THE CP INSTRUCTION CP 0FFH ; COMPARE A TO LEADER OF (FF)H JP Z,TL LD A,C CP 03CH ; COMPARE A TO START OF (3C)H JP Z,TST LD A,C CP 0E6H ; COMPARE A TO SYNC OF (E6)H JP Z,TSY LD A,C CP 01AH ; COMPARE A TO STOP OF (1A)H JP Z,TSP ; PASSED THROUGH ALL THE FILTERS SO IT MUST BE DATA OR CHECKSUM LD A,C CALL HEXOUT ; SEND TO CONSOL AS HEX CALL SPACE DEC B ; DEC THREE TIMES FOR 'CH'+'CH'+'SPACE' DEC B DEC B JP NZ,TUN2 LD B,04BH ; RESET THE CHARACTERS PER LINE COUNTER CALL CRLF CALL SPACE JR TUN2 TL: LD D,'L' LD E,'L' JR TUN3 TST: LD D,'S' LD E,'T' JR TUN3 TSY: LD D,'S' LD E,'Y' JR TUN3 TSP: LD D,'S' LD E,'P' TUN3: LD A,D ; SEND TO CONSOL THE TWO LETTERS IN DE CALL CONOUT LD A,E ; SEND TO CONSOL THE TWO LETTERS IN DE CALL CONOUT CALL SPACE DEC B DEC B DEC B JP NZ,TUN2 LD B,04BH ; RESET THE CHARACTERS PER LINE CALL CRLF CALL SPACE JR TUN2 ; VERIFY: ; VERIFY CASSETTE TAPE TO MEMORY ROUTINE ; THIS ROUTINE WILL ACCEPT A STARTING MEMORY ADDRESS AND AN ENDING ; MEMORY ADDRESS (BLOCK WRITTEN TO TAPE) AND VERIFY THE SAME DATA ; IS ON THE CASSETTE TAPE AS A WAY TO VERIFY PROGRAM/DATA STORAGE. ; ; # V _ _ _ _ , _ _ _ _ ; # V 0100,0150 ... THIS WILL COMPARE MEMORY (0100)H - (0150)H ; TO THE PROGRAM ON CASSETTE TAPE. WILL START THE ROUTINE SO ; TAPE PLAYER SHOULD BE READY. ; ; REG HL = [START ADDRESS] ; REG DE = [END ADDRESS] ; REG B = CALCULATED CHECKSUM ; REG C = MEMORY <> TAPE COUNTER ; FORMAT: FF FF FF [3C] [E6] DD DD DD DD DD DD [1A] FF [CKSUM] FF FF FF ; CALL DHXIN ; GET TWO PARAMETERS FROM THE CONSOL HL=(START ADDR) DE=(END ADDR) CALL CRLF ; VRFY1: ; VERIFY VRFA: LD B,0H ; LOAD 'REG B' WITH (00)H FOR CHECKSUM LD C,0H ; LOAD 'REG C' WITH (00)H FOR ERROR COUNT PUSH DE ; SAVE 'DE' ON STACK SO 'D' AND 'E' ARE AVAILABLE FOR USE VRFB: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0FFH ; IS THIS A LEADER (FF)H JP NZ,VRFB ; NOPE, TRY AGAIN UNTIL (FF)H RECEIVED ; VRFC: CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 03CH ; LOOK FOR 'START BYTE' DISCARD LEADER (FF)H JP NZ,VRFC ; FOUND THE 'START BYTE', 'SYNC BYTE' SHOULD BE NEXT CALL CIN ; GET A CHARACTER FROM TAPE, STORE IN 'REG A' CP 0E6H JP NZ,VX6 ; DIDN'T FIND A 'SYNC BYTE' SO GOTO ERROR MESSAGE ; FOUND THE 'SYNC BYTE', SO DATA SHOULD COME NEXT ; VRFD: CALL CIN ; GET DATA FROM TAPE, STORE IN 'REG A' LD D,A ; STORE TAPE DATA IN 'REG D' VRFE: LD A,(HL) ; STORE MEMORY DATA IN 'REG A' CP C ; COMPARE 'D' TO 'A' JP Z,VRFF ; IF MEMORY=TAPE CONTINUE AT VRFF INC C ; FOUND A BAD MATCH, UPDATE BAD COUNTER VRFF: LD A,(HL) ; UPDATE THE CHECKSUM ADD B ; ADD 'REG A' = 'REG B' LD B,A ; STORE BACK IN 'REG B' ; VRFG: POP DE ; 'REG H' CP TO 'REG D' THEN 'REG L' CP TO 'REG E' IF ZERO, END VRFH: LD A,H ; LOAD 'REG H' FROM HL PAIR LD C,D ; LOAD 'REG D' FROM DE PAIR CP C ; NOW COMPARE 'REG H' TO 'REG D' JP Z,VRFI ; IF AT ZERO, GO CHECK 'L' AND 'E' JP VRFJ ; H <> D SO NO NEED TO CHECK MORE, GET MORE DATA VRFI: LD A,L ; LOAD 'REG L' FROM HL PAIR LD C,E ; LOAD 'REG E' FROM DE PAIR CP C ; NOW COMPARE 'REG L' TO 'REG E' JP Z,VRFK ; IF ZERO WE ARE AT END VRFJ: PUSH DE ; SAVE 'DE' INC HL ; NOT DONE SO INC HL JR VRFD ; GO BACK AND GET MORE DATA ; VRFK: ; WE GOT HERE BECAUSE HL=DE VX4: CALL CRLF LD HL,MSG8 ; PRINT OUT MESSAGE KX8: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX8 LD A,B ; 'REG B' FINAL CALCULATED CHECKSUM CALL HEXOUT LD A,02FH ; SEND A '/' TO THE CONSOL CALL CONOUT LD A,C ; 'REG C' ERRORS WHERE TAPE <> MEMORY CALL HEXOUT ; VX5: CALL CRLF ; PRINT OUT LAST TAPE BYTES TO ENSURE [1A] FF [CKSUM] FF... LD HL,MSG9 ; PRINT OUT MESSAGE KX9: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX9 ; END OF MESSAGE PRINT ROUTINE LD C,04H ; SET 'C' COUNTER TO 4 LZ1: CALL CIN ; READ THE NEXT FOUR BYTES FROM TAPE CALL HEXOUT CALL SPACE DEC C JP Z,TEXIT JR LZ1 ; VX6: CALL CRLF ; PRINT OUT ERROR MESSAGE 'SYNC BYTE' NOT FOUND LD HL,MSG6 ; PRINT OUT MESSAGE KX10: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,KX10 ; END OF MESSAGE PRINT ROUTINE JP TEXIT ; MSG8: DEFM 'LOAD COMPLETE...CALCULATED CHECKSUM/TOTAL TAPE ERRORS: ' DEFB 03H ; END OF TEXT '03H' JP TEXIT ; EXIT TO MENU ; MSG9: DEFM 'NEXT FOUR BYTES - [1A] [FF] [CKSUM] [FF]: ' DEFB 03H ; END OF TEXT '03H' JP TEXIT ; EXIT TO MENU ; ENDIF ; END BLOCK FOR TARBELL ROUTINES ================================= TEXIT: JP EXEC ; JUMP TO MENU ; CMPDH: PUSH AF ; COMPARE 'D' TO 'H'...H[XX XX]L AND D[XX XX]E LD A,D CP H JP NZ,CMP1 ; IF D <> H THEN GOTO CMP1, [CLEAR CARRY] AND RETURN LD A,E CP L JP NZ,CMP1 ; IF E <> H THEN GOTO CMP1, [CLEAR CARRY] AND RETURN POP AF SCF ; H=D AND L=E [SET CARRY] AND RETURN RET CMP1: POP AF ; POP WHAT WAS SAVED IN AF SCF ; SET CARRY FLAG CCF ; CLEAR CARRY FLAG RET ; DHXIN: CALL SPHIN ; OUTPUT A SPACE AND GET SOME CONSOL INPUT PUSH HL ; PUSH 'HL' ONTO THE STACK CP 0DH ; COMPARE...subtract - <0D> = NZ...IS IT '0DH' A CALL NZ,HEXIN ; IF 'NOT ZERO' ... NOT ... GO GET MORE EX DE,HL ; DETECTED SO EXCHANGE THE 'DE' AND 'HL' REGISTERS POP HL RET ; ; THIS IS THE MAIN "PARAMETER-GETTING" ROUTINE. ; THIS ROUTINE WILL ABORT ON A NON-HEX CHARACTER. ; IT TAKES THE MOST RECENTELY TYPED FOUR VALID ; HEX CHARACTERS, AND PLACES THEM UP ON THE STACK. ; (AS ONE 16 BIT VALUE, CONTAINED IN TWO ; 8-BIT BYTES.) IF A CARRIAGE RETURN IS ENTERED, ; IT WILL PLACE THE VALUE OF "0000" IN THE STACK. ; SPHIN: CALL SPACE ; LOAD 'REG A' WITH 20H 'SPACE' AND SEND TO CONSOL OUTPUT HEXIN: LD HL,0 ; LOAD HL WITH '0' HXIN1: CALL CONIN ; GET CONSOL INPUT AND RETURN IN 'REG A' CAN BE '00H TO 7FH' CP '0' ; COMPARE...subtract - <0> = M...IF NOT '0' OR LARGER RETURN RET M ; IF 'SIGN NEG' RETURN CP 'F'+1 ; COMPARE...subtract - = P...IF IT IS LARGER THAN 'F' IE NOT HEX RETURN RET P ; IF 'SIGN POS' CP '9'+1 ; COMPARE...subtract - <9 + 1> = M...IF IT IS LARGER THAN '9' JP M,HXIN2 ; IF 'SIGN NEG' GOTO HXIN2 CP 'A' ; COMPARE...subtract - = M...IF IT IS NOT 'A' THEN RETURN RET M ; IF 'SIGN NEG' ADC A,9 HXIN2: AND 0FH ADD HL,HL ; MULTIPLY BY 16 ADD HL,HL ADD HL,HL ADD HL,HL OR L ; 'OR' IN THE SINGLE NIBBLE LD L,A JR HXIN1 ; GET SOME MORE FROM CONSOL IN ; TRPIN: CALL SPHIN ; TRPIN: INPUT 3 WORDS...PLACE IN [HL],[DE],[BC]...ex: (hhll),(ddee),(bbcc) EX DE,HL ; EXCHANGE THE DE AND HL REGISTERS - LOAD ALL THREE PAIRS WITH HEX CALL HEXIN ; ENTRIES PUSH HL CALL HEXIN PUSH HL POP BC POP HL RET ; DHXOT: LD A,H ; DISPLAY CURRENT HL VALUE CALL HEXOUT LD A,L ; HEXOUT: PUSH AF RRCA RRCA RRCA RRCA CALL HXOT1 POP AF HXOT1: AND 0FH ADD A,30H CP '9'+1 JP M,CONOUT ADD A,7 JP CONOUT ; CRLF: PUSH AF LD A,0DH CALL CONOUT LD A,0AH CALL CONOUT POP AF RET ; SPACE: PUSH AF ; PUSH CONTENTS OF AF ONTO THE STACK LD A,20H ; A IS LOADED WITH 20H = 'SPACE' CALL CONOUT ; A 'SPACE' IS SENT TO THE CONSOL OUTPUT POP AF ; POP FROM THE STACK BACK TO AF RET ; CONOUT: PUSH AF IN A,(KBDST) AND KBDOT JP Z,CONOUT+1 POP AF OUT (KBDDT),A RET ; CONIN: IN A,(KBDST) AND KBDIN JP Z,CONIN IN A,(KBDDT) AND 7FH ; only chars up to 7F CP 61H ; 'a' to '|' ? If so, A-=20H for capitalization JP C,ECHO CP 7CH JP NC,ECHO SUB 20H ECHO: CP 18H ; cancel character JP Z,EXEC JR CONOUT PTXT: LD A,(HL) CP 03H ; PRINT A MESSAGE BEGINNING AT RET Z ; AODENDING WITH A CONTC CALL CONOUT INC HL JR PTXT ; HXOT4: LD C,H ; 16 HEX OUTPUT ROUTINE CALL HXO2 LD C,L HXO2: LD A,C RRA RRA RRA RRA CALL HXO3 LD A,C HXO3: AND 0FH CP 10 JP C,HADJ ADD A,7 HADJ: ADD A,30H OTA: PUSH BC LD C,A CALL CONOUT ; SEND TO CONSOL WHAT'S IN REGISTER A POP BC RET ; ; PRINT [HL] AND A SPACE HLSP: PUSH HL PUSH BC CALL LADR LD A,20H CALL CONOUT POP BC POP HL RET ; ; PRINT [HL] ON CONSOL LADR: LD A,H CALL LBYTE LD A,L LBYTE: PUSH AF RRCA RRCA RRCA RRCA CALL SF598 POP AF SF598: CALL CONV LD A,C JP CONOUT ; ; CONVERT HEX TO ASCII CONV: AND 0FH ADD A,90H DAA ADC A,40H DAA LD C,A RET ; BITS1: PUSH DE ; DISPLAY 8 BITS OF [A] PUSH BC LD E,A CALL BITS POP BC POP DE RET ; BITS: LD B,08H ; DISPLAY 8 BITS OF [E] CALL SPACE SF76E: SLA E LD A,18H ADC A,A LD C,A CALL CONOUT DJNZ SF76E RET ; BAD: PUSH AF ; PRINT BAD PUSH HL ; SAVE ORIGINAL 'AF' AND 'HL' LD HL,MSG11 ; PRINT 'BAD: ' TO CONSOL BAD1: LD A,(HL) CALL CONOUT INC HL CP 03H JP NZ,BAD1 MSG11: DEFM 'BAD: ' DEFB 03H ; END OF TEXT '03H' POP HL ; RESTORE HL POP AF ; RESTORE AF RET ; ; TARBELL BOOT LOADER ROUTINE: ; THIS PROGRAM LOADS DATA FROM A CASSETTE TAPE STARTING AT ADDRESS 0000H ; AND KEEPS ON GOING. THERE IS NO COUNT OF BYTES NOR CHECKSUM. ABOUT 45 SEC ; TO LOAD AN 8K BLOCK OF DATA. STOP TAPE AFTER AN ADEQUATE TIME AND RESET THE ; COMPUTER. IT WILL START AT ADDRESS 0000H AND RUN WHAT WAS ENTERED. ; TARBELL CASSETTE STATUS PORT AT (06EH) ; TARBELL CASSETTE DATA PORT AT (06FH) ; ALL CONTROL OF CASSETTE TAPE PLAYER IS ASSUMED TO BE MANUAL ; BOOT: CALL CRLF ; ROUTINE IS A BOOT LOADER FOR TARBELL LD A,10H ; SET BIT 4 OR 'REG A' TO 1 OUT (TARBS),A ; RESET CASSETTE INTERFACE LD HL,0000H ; PUT STARTING ADDRESS IN HL LOOPA: IN A,(TARBS) ; READ CASSETTE STATUS PORT AND 10H ; CLEAR ALL BUT BIT 4 OF STATUS PORT JP NZ,LOOPA ; WAIT IN LOOP UNTIL READY IN A,(TARBD) ; READ A DATA BYTE INTO 'REG A' EI ; SIGNAL OPERATOR (ENABLE INTERUPT) ??? LD (HL),A ; PUT DATA INTO MEMORY INC HL ; INCREMENT MEMORY POINTER JP LOOPA ; REPEAT THE OPERATION ; DON'T KNOW THAT I AM DONE, SO I WILL LOOP FOREVER...RESET ME JP EXEC ; WILL NEVER GET HERE ; HALT ; END