; ******************************************************** ; File: Hexmon.asm ; provided to Herb Johnson by Greg "Pete" Peterson on Aug 27 2013 ; HEXMON: A monitor to dump, load, and verify Intel hex ; checksum paper tapes with tape label for leadin header. ; ; This code from: "8080 / Z80 assembly language, Techniques ; for improved programming" by Alan R. Miller PP 189 - 200 ; ISBN 0 471 08124-8 Copyright 1981 ; ; My impetus for entering this code was a need for ; Intel hex upload and download for a monitor. I could have ; translated 8051 code, but found this first. It occured ; to me that it might be a nice tool to have on CP/M. ; So I entered the whole thing. Not sure this will actually ; run on CP/M yet, probably will need some changes. ; ; The code assembles without error using the Zilog assembler. ; A beautiful tool for free at www.zilog.com in exchange for ; a minimal quantity of contact information. But this great ; assembler does not accept Intel mnemonics. Hence the ; translation to Zilog mnemonics (they are better anyway). ; ; This code: ; Assembles without error. ; Is the exact length of the original code. ; Verifies byte for byte against the original listing. ; Does not use Z-80 extensions, so an 8080 will run it. ; ; Note: I have not actually run this code on a CPU. ; I have added to some comments, but have left the labels ; alone. ; ; The hex tape routines are easily extracted from the ; support code that makes this a stand alone program. ; See comments at end. The code assumes RAM, but may ; run in ROM using registers for working storage. ; ; An interesting feature is the ability to punch a ; human readable message into the paper tape to identify ; it. I can't imagine where I would use that code, but it ; is interesting. ; ; Check the use of DB 1H as a skip instruction at MERROR. ; ; You can Read, Write, or Verify a tape with this code. ; You can also Read & Execute, or just Go to an address. ; ; ******************************************************** ; ******************************************************** ; Ports in I/O Space - modify for your configuration CSTAT EQU 10H ; CONSOLE STATUS CDATA EQU CSTAT+1 ; 8 bit CONSOLE DATA (AKA KBD) PSTAT EQU 6 ; PUNCH STATUS PDATA EQU PSTAT+1 ; PUNCH DATA ; ******************************************************** ; Masks - for the port status bytes CIMSK EQU 1 ; Console IN MASK: 1 for Rx DAV COMSK EQU 2 ; Console OUT MASK: 1 for Tx MTY PIMSK EQU 1 ; PUNCH IN MASK PDMSK EQU 80H ; PUNCH OUT MASK ; ******************************************************** ; Magic numbers RLEN EQU 16 ; Default RECORD LENGTH NNULS EQU 0 ; CONSOLE NULLS ; ******************************************************** ; Handy ASCII CR EQU 13 ; LF EQU 10 ; DEL EQU 127 ; CTRH EQU 8 ; ^H CONSOLE BACKUP DC1 EQU 11H ; Turns tape reader ON DC3 EQU 13H ; Turns tape reader OFF ; ******************************************************** ; CP/M compatible origin ORG 100H START: ; 0100H JP CONTIN ; Start here ; ******************************************************** ; INPUT an ASCII char FROM THE CONSOLE, returned in reg A INPUTT: ; 0103H IN A,(CSTAT) ; Wait for data AND CIMSK ; JP Z,INPUTT ; IN A,(CDATA) ; AND 7FH ; STRIP PARITY RET ; Exit IMPUTT ; ******************************************************** ; OUTPUT an ASCII CHAR TO THE CONSOLE ; Char passed in reg A. OUTT: ; 010FH PUSH AF ; OUTW: ; 0110H IN A,(CSTAT) ; AND COMSK ; JP Z,OUTW ; POP AF ; OUT (CDATA),A ; RET ; Exit OUTT ; ******************************************************** ; OUTPUT 16 bit binary in HL TO CONSOLE as hex ascii; ; 16 BIT BINARY TO HEX ; Uses Reg C, A OUTHL: ; 011BH LD C,H ; FETCH H CALL OUTHX ; PRINT LD C,L ; FETCH ; Fall thru ; ******************************************************** ; CONVERT 8 bit BINARY # in Reg C TO TWO HEX CHARS & ; PRINT THEM on the console ; # passed in reg C. OUTHX: ; 0120H LD A,C ; RRA ; ROTATE UPPER RRA ; TO LOWER RRA ; RRA ; CALL HEX1 ; OUTPUT UPPER LD A,C ; OUTPUT LOWER ; ******************************************************** ; OUTPUT HEX CHAR FROM LOWER FOUR BITS to Console ; # passed in Reg A HEX1: ; 0129H AND 0FH ; TAKE 4 BITS ADD A,144 ; DAA ; DAA TRICK ADC A,64 ; DAA ; AGAIN JP OUTT ; Exit thru OUTT ; ******************************************************** ; CONVERT ASCII CHAR in A TO 4 BINARY BITS. ; Nibble returned in A. NIB: ; 0134H SUB A,'0' ; ASII BIAS RET C ; < '0' CP A,'F'-'0'+1 ; CCF ; INVERT RET C ; ERROR, > 'F' CP A,10 ; CCF ; INVERT RET NC ; NUMBER IS 0 .. 9 SUB A,'A'-'9'-1 ; CP A,10 ; RET ; CHAR IS A .. F ; ******************************************************** ; Parse a 16 bit binary # to HL FROM ASCII in the buffer ; A comma, space, or CR ends the fetch. READHL: ; 0144H PUSH DE ; PUSH BC ; LD HL,0000H ; START WITH 0 RDHL2: ; 0149 CALL GETCH ; ASCII ch from buffer JP C,RDHL5 ; Exit, END OF LINE CALL NIB ; CONVERT TO BINARY JP C,RDHL4 ; Exit Error: NOT HEX ADD HL,HL ; 16 BIT SHIFT LEFT ADD HL,HL ; 4 bits == 1 nibble ADD HL,HL ; ADD HL,HL ; OR L ; COMBINE NEW LD L,A ; JP RDHL2 ; NEXT ; ******************************************************** ; CHECK FOR COMMA OR BLANK AT END OF ADDRESS ; Return HL with value when a comma or space is scanned. ; Delimiter passed in Reg A. RDHL4: ; 015EH CP A,','-'0' ; COMMA ? JP Z,RDHL5 ; YES, OK CP A,' '-'0' ; BLANK ? JP NZ,ERROR ; NO RDHL5: ; 0168H POP BC ; POP DE ; RET ; ; ******************************************************** ; Handle syntax errors: Print ? on console & restart. ERROR: ; 016BH LD A,'?' ; IMPROPER INPUT CALL OUTT ; Pass char in Reg A JP START ; ; ******************************************************** ; SEND CHARACTERS POINTED TO BY DE UNTIL A BINARY ZERO IS FOUND ; Pointer to characters passed in DE. ; Chars passed to OUTT one at a time in Reg A. SENDM: ; 0173H LD A,(DE) ; NEXT BYTE OR A ; SEE IF ZERO RET Z ; DONE, Exit CALL OUTT ; Console print INC DE ; JP SENDM ; ; ******************************************************** ; Begin executing code here CONTIN: ; 017DH LD SP,STACK ; LD DE,SIGN ; Sign on msg CALL SENDM ; ; ******************************************************** ; Commands come here when done running RSTRT: ; 0186H LD SP,STACK ; CALL INPLN ; GET A LINE CALL GETCH ; INPUT THE TASK ; Decode the desired task CP A,'W' ; DUMP JP Z,PDUMP ; CP A,'R' ; READ, NOAUTOSTART JP Z,PLOAD ; CP A,'E' ; LOAD & EXECUTE JP Z,PLOAD CP A,'V' ; VERIFY JP Z,PLOAD ; CP A,'G' ; GO SOMEWHERE JP NZ,ERROR ; Error if not found ; JUMP (Go to) ANOTHER PROGRAM CALL READHL ; JUMP ADDRESS JPCHL: ; 01ABH JP (HL) ; OK, GOODBYE ; ******************************************************** ; INPUT A LINE FROM THE CONSOLE AND PUT IT INTO A BUFFER ; Exit on a CR entry. Handle backspace & deletes. Maintain ; buffer count & pointer. Buffer is 20 chars long. INPLN: ; 01ACH CALL CRLF ; LD A,'>' ; COMMAND PROMPT CALL OUTT ; To console INPL2: ; 01B4H LD HL,IBUFF ; BUFFER ADDRESS LD (IBUFP),HL ; INIT POINTER LD C,0 ; INIT COUNT INPLI: ; 01BCH CALL INPUTT ; CHAR FROM CONSOLE CP A,' ' ; CONTROL CHAR JP C,INPLC ; YES, GO PROCESS CP A,DEL ; DELETE CHAR? JP Z,INPLB ; YES CP A,'Z'+1 ; UPPER CASE ? JP C,INPL3 ; NO AND A,5FH ; MAKE UPPER INPL3: ; 01D0H LD (HL),A ; PUT IN BUFFER LD A,32 ; GET BUFFER SIZE CP A,C ; TEST IF FULL JP Z,INPLI ; YES, LOOP ; No, fall thru ; Buffer not full, insert char LD A,(HL) ; RECALL CHAR INC HL ; BUMP POINTER INC C ; INC COUNT INPLE: ; 01DAH CALL OUTT ; ECHO CHAR to CON JP INPLI ; GET NEXT CHAR ; PROCESS CONTROL CHAR INPLC: ; 01E0H CP A,CTRH ; ^H ? JP Z,INPLB ; YES CP A,CR ; TEST IF RETURN JP NZ,INPLI ; NO, IGNORE CHAR ; END OF INPUT LINE LD A,C ; LINE COUNT LD (IBUFC),A ; SAVE ; ******************************************************** ; Send CR, LF to CONsole. CRLF: ; 01EEH LD A,CR ; CALL OUTT ; LD A,LF ; ; IF NULLS REQUIRED AFTER CR, LF ; USE REPEAT MACRO ; IF NNULS > 0 ; ASSEMBLE ; CALL OUTT ; ; ; XRA A ; GET A NULL ; REPT NNULS-1 ; ; CALL OUTT ; ; ENDM ; ; ENDIF ; NULLS JP OUTT ; Exit through OUTT ; ******************************************************** ; DELETE ANY PRIOR CHARACTER INPLB: ; 01F8H LD A,C ; CHAR COUNT OR A ; ZERO ? JP Z,INPLI ; YES DEC HL ; BACK POINTER DEC C ; AND COUNT LD A,CTRH ; BACK CURSOR JP INPLE ; PRINT IT ; ******************************************************** ; OBTAIN A CHAR FROM THE CONSOLE BUFFER. SET CARRY IF EMPTY ; Char returned in A GETCH: ; 0204H PUSH HL ; SAVE REGS LD HL,(IBUFP) ; GET POINTER GETC2: ; 0208H LD A,(IBUFC) ; GET COUNT SUB 1 ; DECR WITH CARRY JP C,GETC4 ; NO CHARS LD (IBUFC),A ; REPLACE COUNT LD A,(HL) ; GET CHAR GETC3: ; 0214H INC HL ; INCR POINTER LD (IBUFP),HL ; REPLACE POINTER GETC4: ; 0218H POP HL ; RET ; Exit GETCH ; ******************************************************** ; PUNCH A PAPER TAPE PDUMP: ; 021AH CALL READHL ; START ADDRESS JP C,ERROR ; TOO FEW PARAM EX DE,HL ; CALL READHL ; STOP ADDRESS EX DE,HL ; DE = Stop, HL = Start INC DE ; Include last byte PUSH HL ; CALL READHL ; AUTOSTART ADDRESS EX (SP),HL ; PUT ON STACK CALL LEADR ; PUNCH LEADER CALL LABEL ; PUNCH LABEL ; START A NEW RECORD, ZERO THE CHECKSUM ; PUNCH CR, LF, 2 NULLS AND COLON NEWREC: ; 0231H CALL PCRLF ; CR, LF, NULLS ; FIND RECORD LENGTH LD A,E ; COMPARE LOW STOP SUB L ; TO LOW POINTER LD C,A ; DIFF IN C LD A,D ; COMPARE HIGH STOP SBC A,H ; TO HIGH POINTER LD B,A ; DIFF TO B JP C,ERROR ; IMPROPER, HL > DE LD A,RLEN ; FULL RECORD JP NZ,NEW2 ; CP C ; COMPARE TO E-L JP C,NEW2 ; FULL RECORD LENGTH LD A,B ; ARE BOTH E-L AND OR C ; D-E ZERO ? JP Z,DONE ; YES, REC LENGTH = 0 LD A,C ; SHORT RECORD NEW2: ; 024CH LD C,A ; REC LEN TO C LD B,0 ; ZERO THE CHECKSUM CALL PNHEX ; PUNCH REC LEN CALL PUNHL ; PUNCH HL XOR A ; CALL PNHEX ; PUNCH REC TYPE 0 PMEM: ; 0259H LD A,(HL) ; CALL PNHEX ; PUNCH MEMORY BYTE INC HL ; INC MEM POINTER DEC C ; DEC REC LEN JP NZ,PMEM ; CALL CSUM ; PUNCH CHECKSUM JP NEWREC ; NEXT RECORD ; FINISHED, PUNCH LAST RECORD, RECORD LENGTH 00, ; THE START ADDRESS, AND A RECORD TYPE OF 01 DONE: ; 0268H XOR A ; LD B,A ; ZERO CHECKSUM CALL PNHEX ; ZERO REC LEN POP HL ; Autostart from stack CALL PUNHL ; To HL LD A,H ; CHECK FOR OR L ; AUTOSTART LD A,0 ; 0 WITH CY JP Z,DON2 ; NO AUTOSTART INC A ; A <= 1 DON2: ; 0279H CALL PNHEX ; RECORD TYPE 1 CALL CSUM ; PUNCH CHECKSUM CALL LEADR ; PUNCH TRAILER JP RSTRT ; NEXT JOB ; ******************************************************** ; PUNCH BLANK HEADER AND TRAILER LEADR: ; 0285H XOR A ; LD B,60 ; TAPE NULLS NLDR: ; 0288H CALL POUT ; DEC B ; JP NZ,NLDR ; RET ; ; ******************************************************** ; PUNCH THE 16 bit binary # in HL as 4 ASCII Hex digits PUNHL: ; 0290H LD A,H ; CALL PNHEX ; PUNCH H LD A,L ; ; CONVERT A BINARY NUMBER TO 2 HEX CHARS ; PUNCH THEM, ADD TO CHECKSUM PNHEX: ; 0295H PUSH AF ; SAVE ON STACK ADD B ; ADD TO CHECKSUM LD B,A ; SAVE IN B POP AF ; GET BYTE BACK PUSH AF ; RRA ; ROTATE UPPER RRA ; RRA ; RRA ; CALL PHEX1 ; LEFT CHAR POP AF ; RIGHT CHAR ; ******************************************************** ; PUNCH 1 ASCII HEX digit FROM 4 LOWER BITS of Reg A PHEX1: ; 02A2H AND 0FH ; MASK ADD A,144 ; DAA ; ADC A,64 ; DAA ; JP POUT ; Exit through POUT ; ******************************************************** ; INPUT A HEX CHAR FROM TAPE, return in Reg A HEX: ; 02ADH CALL PIN ; SUB '0' ; CP 10 ; RET C ; 0 .. 9 SUB 7 ; A .. F RET ; Exit HEX ; ******************************************************** ; OUTPUT A binary BYTE TO THE PUNCH ; Byte passed in Reg A POUT: ; 02B8H PUSH AF ; POUTW: ; 02B9H IN A,(PSTAT) ; AND PDMSK ; JP NZ,POUTW ; POP AF ; OUT (PDATA),A ; RET ; Exit POUT ; ******************************************************** ; INPUT An ASCII char FROM PAPER TAPE ; Byte returned in A PIN: ; 02C4H IN A,(PSTAT) ; AND PIMSK ; JP NZ,PIN ; IN A,(PDATA) ; AND 7FH ; STRIP PARITY RET ; Exit PIN ; ******************************************************** ; PUNCH CR, LF, NULLS AND COLON ; Uses Reg A PCRLF: ; 02D0H LD A,CR ; CALL POUT ; LD A,LF ; CALL POUT ; XOR A ; CALL POUT ; TWO NULLS CALL POUT ; LD A,':' ; COLON JP POUT ; Exit thru POUT ; ******************************************************** ; ENTRY FOR LOAD, EXECUTE AND VERIFY ; Enter with task code in Reg A ('V' for verify, else load). PLOAD: ; 02E6H LD (TASK),A ; LD A,DC1 ; TAPE READER ON CALL POUT ; CALL READHL ; OFFSET LD (OFSET),HL ; SAVE IT ; PROCESS THE RECORD HEADING ON INPUT ; Note: This code ignores the record type. HEAD: ; 02F4H CALL PIN ; INPUT FROM TAPE CP ':' ; COLON (record start) ? JP NZ,HEAD ; NO, WAIT FOR IT LD B,0 ; INIT CHECKSUM CALL PHEX ; A <= REC LEN OR A ; ZERO ? JP Z,ENDFL ; YES, DONE LD C,A ; SAVE REC LEN CALL TAPEHL ; HL <= load addr EX DE,HL ; ADDR TO DE LD HL,(OFSET) ; GET OFFSET ADD HL,DE ; ADD LOOP: ; 030EH CALL PHEX ; INPUT DATA BYTE LD E,A ; SAVE BYTE LD A,(TASK) ; GET TASK CP 'V' ; SEE IF VERIFYING LD A,E ; MOVE BACK JP Z,SKIP ; JUMP IF VERIFYING LD (HL),A ; DATA TO MEMORY SKIP: ; 031CH CP (HL) ; CHECK MEMORY JP NZ,MERROR ; BAD MEMORY INC HL ; BUMP POINTER DEC C ; DEC REC LEN JP NZ,LOOP ; PROCESS MORE CALL CHECK ; PROCESS CHECKSUM JP HEAD ; START NEXT RECORD ; ******************************************************** ; INPUT HL (load address) AND REC TYPE FROM TAPE ; Return HL == Load address, E == record type ; Checksum maintained in B TAPEHL: ; 032BH CALL PHEX ; READ H LD H,A ; CALL PHEX ; READ L LD L,A ; READ RECORD TYPE ; HL holds the load address for the code. ; CONVERT 2 CHAR FROM TAPE TO ONE BINARY ; byte, STORE IN A AND ADD TO CHECKSUM PHEX: ; 0333H CALL HEX ; UPPER CHAR (MS nibble) RLCA ; RLA ; MOVE TO UPPER HALF RLA ; RLA ; LD E,A ; SAVE IT CALL HEX ; LOWER CHAR (LS nibble) ADD E ; COMBINE LD E,A ; SAVE data ADD A,B ; ADDTO CHECKSUM LD B,A ; SAVE LD A,E ; Restore DATA RET ; ; ******************************************************** ; ROUTINE TO CHECK FOR AUTOSTART ENDFL: ; 0344H CALL TAPEHL ; AUTOSTART ADDRESS PUSH AF ; SAVE REC TYPE CALL PHEX ; INPUT CHECKSUM CALL TOFF ; READER OFF POP AF ; GET REC TYPE CP 1 ; AUTOSTART ? JP NZ,RSTRT ; NO LD A,(TASK) ; CHECK TASK CP 'E' ; EXECUTE ? JP Z,JPCHL ; YES, GO CALL OUTHL ; NO, PRINT HL JP RSTRT ; NEXT TASK ; ******************************************************** ; TURN OFF paper TAPE READER TOFF: ; 0362H LD A,DC3 ; JP POUT ; ; ******************************************************** ; CALCULATE AND PUNCH THE CHECKSUM CSUM: ; 0367H LD A,B ; CHECKSUM TO A CPL ; ONE'S COMPLEMENT INC A ; TWO'S COMPLEMENT JP PNHEX ; PUNCH CHECKSUM ; ******************************************************** ; SEE IF CHECKSUM IS CORRECT (ZERO) CHECK: ; 03D6H CALL PHEX ; INPUT CHECKSUM XOR A ; ADD A,B ; IS CHECKSUM 0 ? RET Z ; YES, RETURN ; ******************************************************** ; ERROR MESSAGES - This entry for a checksum error. LD A,'C' ; CHECKSUM ERROR DB 1 ; DB TRICK TO SKIP ; Very tricky code here. 01H is the opcode for LD BC,nnnn. ; The LD A,'M' below has the opcodes 3EH & 4DH. The effect ; is to load 3EH to C and 4DH to B. We ignore this number ; in the following code. It has the effect of skipping over ; the LD A,'M' instruction however, leaving 'C' in Reg A ; and BC set to a useless number. Very clever ! ; ******************************************************** ; This entry for a memory error. MERROR: ; 0376H LD A,'M' ; M FOR BAD MEMORY PUSH AF ; CALL TOFF ; TAPE READER OFF POP AF ; CALL OUTT ; PRINT ERROR TYPE CALL OUTHL ; PRINT HL JP RSTRT ; ; ******************************************************** ; Signon message - also the HELP text SIGN: ; 0386H DB CR,LF ; 0386H DB "Hex paper-tape program" DB CR,LF,LF ; 039EH DB "E - load and execute" DB CR,LF ; 03B5H DB "G - go to addresses given" DB CR,LF ; 03D0H DB "R - read tape into memory" DB CR,LF ; 03EBH DB " (with optional offset)" DB CR,LF ; 0407H DB "V - verify tape against" DB " memory",CR,LF ; 0420H DB "W - write paper tape" ; 0429H DB " (and label)",CR,LF," " DB "(with optional autostart)" ; 044FH DB CR,LF,0 ; ******************************************************** ; Prompt for text to punch into tape LMESG: ; 046BH DB CR,LF,"Enter leader message" DB CR,LF,0 ; ******************************************************** ; PUNCH READABLE LABELS ON PAPER TAPE leader LABEL: ; 0484H PUSH HL ; PUSH DE ; LD DE,LMESG ; LABEL MSG. CALL SENDM ; SEND IT CALL INPLN ; GET A LINE LABL1: ; 048FH CALL GETCH ; GET CHAR JP C,LABL2 ; DONE ON CARRY, exit SBC A,20H ; ASCII BIAS JP C,LABL1 ; < SPACE CP 63 ; JP NC,LABL1 ; TOO BIG LD L,A ; Setup LD E,A ; LD H,0 ; LD D,0 ; ADD HL,HL ; DOUBLE HL ADD HL,HL ; TIMES 4 ADD HL,DE ; TIMES 5 EX DE,HL ; DE = index LD HL,TABL ; HL = base ADD HL,DE ; Point to char LD C,5 ; 5 bytes / char NEXTC: ; 04AFH LD A,(HL) ; Print all 5 bytes CALL POUT ; INC HL ; DEC C ; JP NZ,NEXTC ; XOR A ; Print NULL CALL POUT ; JP LABL1 ; NEXT CH ; Exit LABEL, cleaning up stack LABL2: ; 04BFH CALL LEADR ; POP DE ; POP HL ; RET ; Exit LABEL ; ******************************************************** ; Table of human readable characters to punch into the ; paper tape leader for ID purposes. TABL: ; 04C5H DB 0,0,0,0,0 ; SPACE DB 0,0,207,207,0 ; ! DB 0,7,0,7,0 ; " DB 40,254,40,254,40 ; # DB 70,137,255,137,114 ; $ DB 70,38,16,200,196 ; % DB 108,146,172,64,160 ; & DB 0,4,3,3,0 ; ' DB 0,60,66,129,0 ; ( DB 0,129,66,60,0 ; ) DB 136,80,248,80,136 ; * DB 8,8,126,8,8 ; + DB 0,128,112,48,0 ; , DB 8,8,8,8,8 ; - DB 0,192,192,0,0 ; . DB 64,32,16,8,4 ; / DB 126,161,137,133,126 ; 0 DB 132,130,255,128,128 ; 1 DB 194,161,145,137,134 ; 2 DB 66,137,137,137,118 ; 3 DB 12,10,137,255,136 ; 4 DB 103,137,137,137,113 ; 5 DB 126,137,137,137,114 ; 6 DB 1,1,249,5,3 ; 7 DB 118,137,137,137,118 ; 8 DB 70,137,137,137,126 ; 9 DB 0,216,216,0,0 ; : DB 0,128,118,54,0 ; ; DB 16,40,68,130,0 ; < DB 40,40,40,40,40 ; = DB 130,68,40,16,0 ; > DB 6,1,185,9,6 ; ? DB 126,129,157,145,14 ; @ DB 254,9,9,9,254 ; A DB 129,255,137,137,118 ; B DB 126,129,129,129,66 ; C DB 129,255,129,129,126 ; D DB 255,137,137,137,137 ; E DB 255,9,9,9,1 ; F DB 126,129,145,145,114 ; G DB 255,8,8,8,255 ; H DB 0,129,255,129,0 ; I DB 96,128,129,127,1 ; J DB 255,8,20,34,193 ; K DB 255,128,128,128,128 ; L DB 255,2,12,2,255 ; M DB 255,2,60,64,255 ; N DB 255,129,129,129,255 ; O DB 5,9,9,9,6 ; P DB 126,129,161,65,190 ; Q DB 255,25,41,73,134 ; R DB 70,137,137,137,114 ; S DB 1,1,255,1,1 ; T DB 127,128,128,128,127 ; U DB 15,48,192,48,15 ; V DB 127,128,112,128,127 ; W DB 195,36,24,36,195 ; X DB 3,4,248,4,3 ; Y DB 193,161,145,137,135 ; Z DB 0,255,129,129,129 ; [ DB 4,8,16,32,64 ; \ DB 129,129,129,255,0 ; ] DB 12,2,1,2,12 ; ^ ; ; ******************************************************** ; Various storage locations in RAM TASK: DS 1 ; 0600H Task is Execute, Verify else Load OFSET: DW 0 ; 0601H LOAD OFFSET stored here DS 30 ; STACK SPACE STACK: ; 0620H IBUFP: DS 2 ; 0621H BUFFER POINTER IBUFC: DS 1 ; 0623H BUFFER COUNT IBUFF: DS 20 ; 0624H INPUT BUFFER FINIS: EQU $ ; 0638H ; ******************************************************** ; To extract the HEX FILE routines: ; First, I am assuming you are not actually using a paper ; tape punch, but some kind of serial link to get/put hex ; files. ; ; To create & send send a hex file from a Z-80 you need: ; ; PDUMP ; PCRLF ; PNHEX ; PHEX1 ; POUT ; PUNHL ; PMEM ; CSUM ; DONE ; DON2 ; ; The code needs to know the start address, stop address, ; and autostart address. You can pass them in, push them ; on the stack, or set up a task control block. I favor ; the latter, at least initially. Massage the initial ; code to set up these values. ; ; ;;;;; ; ; To receive a hex file with a Z-80 you need: ; ; PLOAD ; PIN ; PHEX ; HEX ; ENDFL ; TAPEHL ; MERROR ; CHECK ; OUTHL ; ; The code needs to know the offset to use in loading ; the code and the task code (load or verify). ; As above, use registers, stack, or a TCB. Massage ; initial code to set up these values. ; ; You will also need to massage the status and data port ; code to reflect your own hardware, and remove paper-tape ; specific code. ; ; ******************************************************** END