Z80 softwareSee below for the printer driver I wrote for a simple wordprocessor.The text is in a big buffer in memory. The paragraphs are seperated by a CR (#D) and pages by a FF (#C). Because the printer need CR/LF sequences there is taken care of this: see lines 179-182. Escape sequences to control the printer are embedded in the text buffer. Because these are not printed the line width is increased by the average length (=3) of these sequences: see lines 153-157. The line width specified is the maximum line width so the word which is in excess of this width is not to be printed on the current line: see line 159. When there is just one word on the line which is in excess nothing would be printed. To take care of this there is a check on zero or negative width: see lines 160-168. Page length is stored in MAXLIN and is set to the running value on lines 83-84 (init) and 176-177. The line width is passed from Basic through call (#F7F8) and is set to running value on lines 147-171 (this includes line width calculation). Indent space can only be set to 3 or 10: see lines 205-210 and for controling the indent and the left margin see lines 185-190 and 202-203. Initialization is done in two parts. The first part initializes the textpointer: see lines 240-248. This routine uses the cursor group as also the main wordprocessor does. The return from the cursor group brings the control to the second part: see lines 81-89. This part takes care that the text pointer gets a legal value.
The nice thing about this routine and that's why I choose to publish it is the way the
routines are called. The routine addresses are moved to the stack and RET will execute
the routines. On line 94-95 LOOPPRT is first moved onto the stack. This takes care that
after all the other routines are called there will be a return to here. Secondly LPTOUT
is moved onto the stack. This is a BIOS routine that sends the character in register A to
the printer. Graphics characters are stored in the text buffer with a value lower than
#20: see lines 125-126. They have to be printed as <1><value+#40>: see lines 98-102 and
125-129. On lines 111-112 PRTCH is pushed onto the stack: this routine checks if a jump
to a new line is ncessary. |
*F PRTPEN 000 ; 001 ; P R T P E N 002 ; 003 ; PRINT ROUTINES FOR MSXPEN-2 004 005 ; AUTHOR: 006 ; F. SEMPLONIUS 007 ; JESSICAGANG 18 008 ; 2719 CA ZOETERMEER 009 ; 010 ; FUNCTION: 011 ; THIS ROUTINE WHICH CAN BE ASSEMBLED STAND-ALONE OR INCLUDED 012 ; BY MTPEN TAKES CARE OF PRINTING OF THE TEXT 013 ; 014 ; NOTES: 015 ; IN STAND-ALONE MODE USE A TABEL SIZE OF 1000 016 ; 017 ; LAYOUT FILES: 018 ; 019 ; 020 ; DEFINITIONS AND MACRO'S 021 ; 0001 022 INCPRT1: EQV 1 023 ; 00A5 024 LPTOUT EQU #A5 000A 025 LF: EQU #A 000C 026 FF: EQU #C 000D 027 CR: EQU #D 028 ; 029 IF INCPRT1!1 030 ; 00AB 031 CNVCHR: EQU #AB FCA6 032 GRPHED: EQU #FCA6 033 ; 034 ; LOCAL DEFINITONS 035 ; 0001 036 HDLINE: EQU 1 000F 037 NLINE: EQU 15 038 ; 039 ; VARIABLES TO BE ACCESSED BY BASIC 040 ; 8A00 041 MA: EQU #8A00 8A01 042 ENDTEXT: EQU #8A01 8A03 043 MAXLIN: EQU #8A03 044 ; 045 ; SYMBOL ADDRESSES IN MTPEN 046 ; 961D 047 PT: EQU #961D 9C40 048 TEXT: EQU #9C40 049 ; 050 ; CHECK IF CURSOR IS WITHIN LIMITS 051 ; INPUT/OUTPUT: 052 ; HL - ADDRESS TO CHECK 053 ; 9461 EB 059 CHKCUR: EX DE,HL ; CURSOR POINTER -> DE 9462 2A0091 060 LD HL,(ENDTEXT) ; END OF TEXT POINTER 9465 0100FE 061 LD BC,-NLINE-1*32 9468 09 062 ADD HL,BC 9469 3620 063 LD (HL)," " ; BE SURE LAST CHAR. IS BLANK 946B E7 064 RST #20 ; HL-DE 946C 3801 065 JR C,CHKC1 ; IF C WITHIN HIGH LIMIT 946E EB 066 EX DE,HL ; ELSE HIGH LIMIT TO HL 946F ED5B9E96 067 CHKC1: LD DE,(STTEXT) ; START OF TEXT 9473 E7 068 RST #20 ; HL-DE 9474 D0 069 RET NC ; IF NC WITHIN LIMITS 9475 E8 070 EX DE,HL ; ELSE LOW LIMIT TO HL 9476 C9 071 RET [PART DELETED] 074 ; 075 ; PRINTER ROUTINES 076 ; 077 ; SECOND PART OF INIT 078 ; INPUTS: 079 ; HL - START ADDRESS FOR PRINT TEXT 080 ; 949F CD6194 081 PRTDR: CALL CHKCUR ; CHECK CURSOR (SEE ABOVE) 94A2 EB 082 EX DE,HL ; TEXT POINTER -> DE 94A3 3A0291 083 LD A,(MAXLIN) ; LINES PER PAGE 94A6 32A395 084 LD (CURLIN),A ; TO COUNTER 94A9 21B294 085 LD HL,LOOPPRT 94AC E5 086 PUSH HL ; DUMMY MOVED FROM STACK AT END OF PRTCH 94AD E5 087 PUSH HL ; RETURN TO LOOPPRT AFTER CHAR. IS PRINTED 94AE 0600 088 LD B,0 ; ROUTINES ASSUME B=0 94B0 184B 089 JR PRTF ; SET LINE WIDTH 090 ; 091 ; MAIN LOOP FOR PRINT TEXT 092 ; NOTE: DE IS USED AS TEXTPOINTER 093 ; 94B2 21B294 094 LOOPPRT: LD HL,LOOPPRT ; RETURN TO LOOPPRT TO 94B5 E5 095 PUSH HL ; TO DO LOOP PER CHAR. 94B6 21A500 096 LD HL,LPTOUT ; PRINT CHAR. IN A 94B9 E5 097 PUSH HL ; DO THIS BEFORE RETURN TO LOOPPRT 94BA 21A6FC 098 LD HL,GRPHED ; GET GRAPHICS CHAR. 94BD 7E 099 LD A,(HL) ; AND CLEAR IT 94BE 3600 100 LD (HL),0 94C0 B7 101 OR A ; WAS THERE A GRAPHICS CHAR.? 94C1 C0 102 RET NZ ; IF NZ YES -> PRINT IT 94C2 1A 103 LD A,(DE) ; GET CHAR. FROM TEXT BUFFER 94C3 13 104 INC DE ; POINT TO NEXT CHAR. 94C4 FE0C 105 CP FF ; IS IT FORMFEED? 94C6 2009 106 JR NZ,PRT1 ; IF NZ NO 94C8 3AA095 107 LD A,(CMD) 94CB FE02 108 CP 2 ; COMMAND PRINT CURRENT PAGE? 94CD 2824 109 JR Z,PRTEXITA ; IF Z YES -> EXIT 94CF 3E0C 110 LD A,FF ; RESTORE FORMFEED 94D1 21F894 111 PRT1: LD HL,PRTCH ; ROUTINE ADDRESS PRTCH 94D4 E5 112 PUSH HL ; ON STACK 94D5 21F894 113 LD HL,SRVTAB ; SPECIAL CHAR. JUMP TABLE 94D8 010800 114 LD BC,NUMSRV ; NUMBER OF ENTRIES IN TABLE 94DB EDB1 115 CPIR ; SPEC. CHAR. FOUND? 94DD 2008 116 JR NZ,PRT5 ; IF NZ NO 94DF 09 117 ADD HL,BC ; CALC. ADDRESS THAT 94E0 09 118 ADD HL,BC ; POINTS TO ROUTINE ADDRESS 94E1 09 119 ADD HL,BC 94E2 4E 120 LD C,(HL) 94E3 23 121 INC HL 94E4 66 122 LD H,(HL) ; ROUTINE ADDRESS TO HL 94E5 69 123 LD L,C ; ... 94E6 E9 124 JP (HL) ; JUMP TO IT 94E7 FE20 125 PRT5: CP #20 ; GRAPHICS CHAR.? 94E9 D0 126 RET NC ; IF NC NO 94EA C640 127 ADD A,#40 94EC 32A6FC 128 LD (GRPHED),A ; IF YES -> STORE WITH OFFSET 94EF 3E01 129 LD A,1 ; GRAPHICS HEADER TO PRINTER 94F1 130 PRTTAB: ; TAB AND ESC ARE IN SPEC. TABLE 94F1 C9 131 PRTESC: RET ; AS NOT TO BE RECOGNIZED AS GRAPHICS 132 ; 133 ; RETURN TO BASIC 134 ; 94F2 E1 135 PRTEXIT: POP HL ; PRTCH FROM STACK 94F3 136 PRTEXITA: 94F3 E1 137 POP HL ; LPTOUT -> HL 94F4 E3 138 EX (SP),HL ; ON STACK (REPLACES LOOPPRT) 94F5 3E0C 139 LD A,FF ; TO PRINT FF 94F7 C9 140 RET 141 ; 142 ; GO TO NEW LINE OR PAGE IF NECESSARY 143 ; 94F8 21A495 144 PRTCH: LD HL,CURPOS ; ALREADY AT END OF LINE (EOL) ? 94FB 35 145 DEC (HL) ; ... 94FC C0 146 RET NZ ; IF NZ NO 94FD 3AF8F7 147 PRTF: LD A,(#F7F8) ; LINE WIDTH 9500 219F95 148 LD HL,IS ; POINT TO INDENT SPACE 9503 96 149 SUB (HL) ; SUBSTRACT FROM LINE WIDTH 9504 4F 150 LD C,A ; -> BC 9505 EB 151 EX DE,HL ; TEXTPOINTER -> HL 9506 E5 152 PUSH HL ; SAVE ON STACK 9507 3E1B 153 LD A,#1B ; ESC 9509 EDB1 154 PRT20: CPIR ; SEARCH IT 950B 03 155 INC BC ; INCREASE LINE WIDTH BY 950C 03 156 INC BC ; 3 EVERY TIME ESC IS FOUND 950D 03 157 INC BC 950E EA0995 158 JP PE,PRT20 ; IF PE ESC FOUND -> REPEAT SEARCH 9511 CDBD95 159 CALL WRDREV ; GO BACK ONE WORD (IN EXCESS OF MARGIN) 9514 D1 160 POP DE ; RESTORE TEXT POINTER 9515 E5 161 PRT25: PUSH HL ; SAVE END OF LINE 9516 B7 162 OR A ; CLEAR C-BIT 9517 ED52 163 SBC HL,DE ; CALCULATE LINE WIDTH 9519 2802 164 JR Z,PRT30 ; IF Z ZERO WIDTH 951B 3006 165 JR NC,PRT35 ; IF NC POS WIDTH 951D E1 166 PRT30: POP HL ; ON NEG. OR ZERO WIDTH 951E CD5596 167 CALL WRDFWD ; GO FORWARD ONE WORD 9521 18F2 168 JR PRT25 ; AND CHECK FOR NEG. WIDTH AGAIN 9523 7D 169 PRT35: LD A,L ; WIDTH -> A 9524 E1 170 POP HL ; CLEAN STACK - PRPT END 9525 32A495 171 LD (CURPOS),A ; STORE WIDTH 9528 21A395 172 LD HL,CURLIN ; GO TO NEXT PAGE? 952B 35 173 DEC (HL) 952C 060A 174 LD B,LF ; ASSUME NO -> DO ONLY LINEFEED 952E 2006 175 JR NZ,PRT40 ; IF NZ GOOD ASSUMPTION 9530 3A0291 176 LD A,(MAXLIN) ; NUMBER OF LINES ON A PAGE 9533 77 177 LD (HL),A ; STORE THIS FOR RUNNING PAGE LENGTH 9534 060C 178 LD B,FF ; PRINT FORMFEED 9536 3E0D 179 PRT40: LD A,CR 9538 CDA500 180 CALL LPTOUT ; PRINT CARR. RETURN 953B 78 181 LD A,B ; FF OR CR 953C CDA500 182 CALL LPTOUT ; PRINT IT 953F 3A0391 183 LD A,(MA) ; MARGIN WIDTH 9542 219F95 184 LD HL,IS 9445 86 185 ADD A,(HL) ; ADD INDENT SPACE 9546 47 186 LD B,A 9547 3E20 187 PRT43: LD A,#20 9549 CDA500 188 PRT45: CALL LPTOUT ; PRINT SPACE 954C 10FB 189 DJNZ PRT45 ; LOOP FOR MARGIN AND IS WIDTH 954E E1 190 POP HL ; LPTOUT FROM STACK 954F C9 191 RET 192 ; 193 ; SERVICE ROUTINES FOR PRINTING SPECIAL CHARACTERS 194 ; 9550 3AA095 195 PRTFF: LD A,(CMD) ; ENTER HERE ON FORMFEED 9553 FE03 196 CP 3 ; COMMAND 3; PRINT ONE PAGE ONLY? 9555 289B 197 JR Z,PRTEXIT ; IF Z YES -> EXIT 9557 289B 198 LD A,1 ; NO 9559 32A395 199 LD (CURLIN),A ; FORCE FORM FEED 955C 3E01 200 PRTCR: LD A,1 ; ENTER HERE ON CARR. RETURN 955E 32A495 201 LD (CURPOS),A ; FORCE NEW LINE 9561 AF 202 XOR A ; ON FF OR CR 9562 329F95 203 LD (IS),A ; SET INDENT SPACE TO ZERO 9565 C9 204 RET 9566 3E0A 205 GRAPHI: LD A,3 ; SET INDENT SPACE TO 3 9568 21 206 DEFB #21 ; SKIP NEXT INSTR. 9569 3E0A 207 GRAPHJ: LD A,10 ; SET INDENT SPACE TO 10 956B 329F95 208 LD (IS),A ; STORE IT 956E 3E20 209 LD A,#20 ; PRINT SPACE FOR INDENT SET CMD 9570 C9 210 RET 211 ; 9571 EB 212 CENTER: EX DE,HL ; ENTER HERE ON CENTER COMMAND 9572 E5 213 PUSH HL ; TEXT POINTER ON STACK 9573 3E0D 214 LD A,#D 9575 CD6196 215 CALL WRDFWDA ; SEARCH FORWARD FOR CARR. RETURN 9578 D1 216 POP DE ; RESTORE TEXTPOINTER 9579 B7 217 OR A ; CLEAR C-BIT 957A ED52 218 SBC HL,DE ; CALCULATE LINE WIDTH 957C 7D 219 LD A,L ; -> A 957D 1F 220 RRA ; DIVIDE BY 2 957E 329F95 221 LD (IS),A ; STORE THIS VALUE AS INDENT SPACE 9581 3E01 222 LD A,1 9583 32A495 223 LD (CURPOS),A ; FORCE CARR. RETURN 9586 C9 224 RET 225 ; 226 ; JUMP TABLE FOR SPECIAL CHARACTERS 227 ; 9587 0C0D1B 228 SRVTAB: DEFB #C,#D,#1B,#9,188,198,220,0 0008 229 NUMSRV EQU $-SRVTAB 958F F29466 230 DEFW PRTEXIT,GRAPHI,GRAPJ,CENTER,PRTTAB,PRTESC,PRTCR,PRTFF 959F 00 231 IS: DEFB 0 95A0 00 232 CMD: DEFB 0 95A1 0000 233 PRPT: DEFW 0 95A3 00 234 CURLIN: DEFB 0 95A4 00 235 CURPOS: DEFB 0 236 ; 237 ; INITIALIZE FOR PRINTER - FIRST PART 238 ; 95A5 219F94 239 INITPR: LD HL,PRTDR ; ENTER VIA JUMP TABLE HERE FROM BASIC 95A8 E5 240 PUSH HL ; ADDRESS SECOND PART OF INIT 95A9 2A3B97 241 LD HL,(PT) ; CURSOR LOCATION IN TEXT 95AC 0600 242 LD B,0 ; REQUIRED FOR CURSOR ROUTINES 95AE 3AF9F7 243 LD A,(#F7F9) 95B1 32A095 244 LD (CMD),A ; GET COMMAND 95B4 3D 245 DEC A ; DECREMENT BY 1 95B5 2813 246 JR Z,BEGIN ; IF ZERO PRINT ALL TEXT -> CURSOR TO BEGIN 95B7 3D 247 DEC A ; COMMAND = 2 ? 95B8 201B 248 JR NZ,SCRUP ; IF NZ NO (=3) -> PRINT SCREEN 370 ; 371 ; CURSOR GROUP (ON ENTRY B = 0) 372 ; 95BA 3E0C 373 PAGEUP: LD A,#C ; DO PAGE UP (SEARCH FORM FEED) 95BC 11 374 DEFB #11 95BD 3E20 375 WRDREV: LD A," " ; WORD BACKWARD (SEARCH SPACE) 95BF 48 376 LD C,B ; BC = 0 (SEARCH ON 256 BYTES) 95C0 2B 377 WRDREVA: DEC HL 95C1 2B 378 WRDREV1: DEC HL ; GO BACKWARD UNTIL NO SPACE FOUND 95C2 BE 379 CP (HL) ; ... 95C3 28FC 380 JR Z,WRDREV1 ; 95C5 EDB9 381 CPDR ; SEARCH BACKWARD 95C7 23 382 INC HL ; SET POINTER NOT TO POINT AT LAST CHAR. 95C8 23 383 INC HL ; OF PREVIOUS WORD BUT START OF CURRENT 95C9 C9 384 RET 95CA 60 385 BEGIN: LD H,B ; BEGIN OF TEXT CHKCUR WILL MAKE 95CB 68 386 LD L,B ; POINTER RIGHT 95CC C9 387 RET 95CD 2A0091 388 ENDT: LD HL,(ENDTEXT) ; POINT TO END OF TEXT 95D0 C9 389 RET 95D1 014003 390 SCRDOWN: LD BC,32*10+512 ; SCREEN DOWN 95D4 11 391 BEFB #11 ; SKIP NEXT INSTR. 95D5 0EC0 392 SCRUP: LD C,-32*10+256 ; SCREEN UP 95D7 05 393 DEC B ; PROPAGATE CARRY 95D8 11 394 DEFB #11 ; SKIP NEXT INSTR. 95D9 0EFF 395 LEFT: LD C,-1 ; CURSOR LEFT 95DB 11 396 DEFB #11 ; SKIP NEXT INSTR. 95DC 0EF0 397 UP: LD C,-16 ; CURSOR UP 95DE 05 398 DEC B ; PROPAGATE CARRY 95DF 11 399 DEFB #11 ; SKIP NEXT INSTR. 95E0 0E01 400 RIGHT: LD C,1 ; CURSOR RIGHT 95E2 11 401 DEFB #11 ; SKIP NEXT INSTR. 95E3 0E10 402 DOWN: LD C,16 ; CURSOR DOWN 95E5 09 403 ADD HL,BC ; CALCULATE NEW POINTER 95E6 C9 404 RET |
|