* * File Name: SPINWR:S * * Spinwriter 5510/20 * Multi-purpose Driver * 2.0 (mod 1) * * Written by Steve and Joe Maguire July, 1979 * P.O. Box 3742 DT * Anchorage, AK 99510 * * *** NEW IMPROVED VERSION! (updated Aug 1980) *** * * * with bi-directional printing * * * includes word processor mode * * * with space averaging * * * Equates: * * Conditions * TRUE EQU 00001H FALSE EQU 0FFFFH * BUSY EQU 0FFFFH DONE EQU 00000H * * Characters * CHNULL EQU 0 Null character CHDEL EQU 7FH Delete character CHCR EQU 0DH Carriage return CHLF EQU 0AH Linefeed CHFF EQU 0CH Formfeed CHFLE EQU 1 Forced-line-end (no space averaging) CHNOLF EQU 0FFH No linefeed character CHESC EQU 1BH Escape character CHSP EQU 20H A space CHBS EQU 8 Backspace on the Spinwriter CHWS EQU 7EH A tilde ("~") CHCRT EQU 5EH A caret ("^") CHBEL EQU 7 Printer alarm (bell) * * Control/Status Codes * CSDS EQU 007 device status request CSWPM EQU 100 word processor mode CSCPS EQU 101 multiple form feeds CSSPS EQU 102 set page size CSSHI EQU 103 set horz. inc. CSSVI EQU 104 set vert. inc. CSCB EQU 105 cancel buffer * * I/O Port Assignments * IOSSP - serial status port * IOSDP - serial data port * IOSSP EQU 0F8H IOSDP EQU 0F9H IOSCS EQU 020H clear to send (when 1) See note: IOSBE EQU 080H transmitter buffer empty (when 1) * * Note: Spinwriter connected to Reverse Channel * * Initial Settings * IVI EQU 08 init. vert. inc. (6 lpi) IHI EQU 12 init. horz. inc. (10 cpi) IPZ EQU 60 init. page size IFZ EQU 66 init. form size * * The program origin * ORG 07800H * * The Device Header * DTRB DW 0 no reads DTRNB DW 0 DTRLB DW 0 DTWBR DW WBLOCK write a block of 1 DTWB DW WBLOCK write a block of 1 DTREW DW DUMMY rewind supported for BASIC DTEOF DW EOF end-file DTCLO DW CLOSE the close operation DTSEK DW 0 seek not supported DTCTL DW CTRL control/status call DTBLK DW 1 block size must be 1 DTITO DB 1 must be 1 DTINI DW INIT DUMMY RET . * * CTRL process the Control/Status calls * 7= Special Status Read (see 9-3 PTDOS manual) * * CSDS return: DE=0 ==> printer driver BUSY * DE=1 ==> printer driver DONE * A = non zero always * If: A =0 ==> printer not turned on * (not used in this driver) * * 100 - Word Processor Mode * * CSWPM - entry: E =1 ==> word processor mode * E =0 ==> not word processor mode * return: A =1 ==> was in word processor mode * A =0 ==> was not in WPM mode * * (when the driver is initialized, the WPM is off) * * 101 - Multiple form-feeds * * CSCPS - entry: E = new formfeed count * return: A = old value * * 102 - Set Page Size * * CSSPS - entry: D = new page size * E = new form size * return: D = old page size * E = old form size * * 103 - Set Horizontal increment * * CSSHI - entry: E = ew horizontal increment in 1/120 in. * return: A = the old increment * * (the initial value is set to 12, i.e., to 10 chars./inch) * * 104 - Set Vertical increment * * CSSVI - entry: E = new vertical increment in 1/48 in. * return: A = the old increment * * (the initial value is set to 8, i.e., 6 lines/inch) * * 105 - Driver Reset * * CSCB - entry: none * return: none * CTRL CPI CSDS Are we checking the device status? JNZ CTRL1 CALL TASK Let's see what drivers' doing CALL TI Is the print driver's task done? MVI A,1 JZ CTRL0 Zero says print task is DONE LXI D,0 Print driver is not done RET * CTRL0 LXI D,1 Print driver is ready RET * CTRL1 CPI CSWPM Change WPM mode? JNZ CTRL2 LXI H,MODE Get mode byte MOV A,M Old mode value MOV M,E Store the new value RET * CTRL2 CPI CSCPS Changing formfeeds? JNZ CTRL3 LXI H,PERFS MOV A,M Save old value MOV M,E Move in the new RET * CTRL3 CPI CSSPS Changing the page size? JNZ CTRL4 MOV A,E Move new form size to A CMP D Page size cannot exceed form size JC CTRLE LXI H,FORM MOV A,M MOV M,E Move in new form size MOV E,A Save old form size LXI H,PAGE MOV A,M MOV M,D Move in new page size MOV D,A Save old page size RET * CTRL4 CPI CSSHI Resetting the Horizontal Increment? JNZ CTRL5 MOV A,E Test for largest HMI CPI 16 JNC CTRLE Oops! too high for the Spinwriter LXI H,NHI Point to HMI byte JMP CMI * CTRL5 CPI CSSVI Resetting the Vertical increment? JNZ CTRL6 MOV A,E Check for illegal value CPI 17 JNC CTRLE Error if illegal LXI H,NVI Point to the VMI byte * CMI MOV A,M A must have the old increment value MOV M,E Set flag with new value INX H MOV M,E Replace old value with new RET * CTRL6 CPI CSCB Cancel printing? JNZ CTRLE Anything else is an error MVI A,TRUE STA CANCEL Set cancel-buffer flag RET * CTRLE CALL TOD See if printer ready JNZ CTRLE MVI A,CHBEL Move in beep character CALL SOB CALL 0BCA7H PTDOS error routine DB 17H * * EOF -- write and end-file on the printer * Entry: HL = block address * DE = block size * EOF CALL CANTST If buffers are cleared, exit RZ CALL WBLOCK Else, write end-of-file mark RET * * CLOSE -- close the printer driver * Write kut entire buffer if it is not canceled * CLOSE MVI A,FALSE Be sure buffer is completely printed STA CANCEL CALL WAIT Now, print it MVI A,CHCR Put an extra CR to make it look pretty CALL SIB BUSY says a character is ready CALL WAIT Print it now RET * * Task and Yield -- A Software interrupt: * * When operating in the Word Processing Mode, the * driver must periodically give up control. It must * keep track of what it was doing. It does this by * switching stacks with the calling program through the * Task and Yield routines. When called again, * it does just the opposite. (This process is sometimes * called Spooling) * * Task - this saves the state of the calling program and * restores the driver to EXACTLY as it was when it * last exited. * TASK PUSH B Save the state of the calling program PUSH D PUSH H PUSH PSW LXI H,0 Compute the stack address DAD SP SHLD PTSTK Now, save the value for future use * LHLD TSKSTK Restore the print driver registers SPHL . Get the stack address POP PSW POP H POP D POP B RET . Continue where the driver was last interrupted * * Yield - this saves the state of the print driver and * restores the calling program to EXACTLY as it * was when it called. * YIELD PUSH B Save the integrity of the driver PUSH D PUSH H PUSH PSW LXI H,0 Compute the stack address DAD SP SHLD TSKSTK We mustn't lose it * LHLD PTSTK Restore the state of the calling program SPHL . Get the stack address POP PSW Now, do the restoring POP H POP D POP B RET . Go to where "TASK" was called originally * * WBLOCK -- write a block of 1 character * HL = address of block * DE = block size * * There are two modes of operation. They are: * * 1) Word processing mode (mainly for WordWizard) * In this mode, the driver returns to the calling * program in 1/10 of a second whether or not it has * finished a print operation. * * * A C/R automatically issues a line feed. * * Line feeds are absorbed. * * Space-averaging is done. * * In the word processing mode, all lines except those * ending with a 01H (an inverted "L") are space- * averaged. A tilde (~) is used to indicate a * mandatory double space. A caret ("^") is used to * indicate a mandatory absolute space. * * * Efficient logic-seeking bi-directional printing. * * The driver prints all non-special control codes * as question marks. * * 2) Non-Word processing mode (default operation) * * In this mode, the driver finishes the complete * print operation before returning to the calling * program. * * A tilde (~) is printed as a tilde - not a blank. * * A C/R is not automatically followed by a LF. * * Line feeds are not absorbed. * * Efficient logic-seeking bi-directional printing. * WBLOCK CALL TMODE Are we in the word processing mode? JNZ WBLK1 Yes, so go process accordingly * * Here, we are in the NON Word Processing Mode. * WBLK0 CALL TI Wait for printer task to finish JZ WBLK2 DONE, send next character CALL TASK Keep printing JMP WBLK0 Loop back * * Here, we are in the Word Processing Mode. * WBLK1 CALL TI Test the input status JNZ WBLRET Return if status is BUSY * WBLK2 MOV A,M Get a character CALL SIB Set input busy for printing CALL TASK Go do it now * * Return to WBLOCK caller with a normal return * WBLRET XTHL INX H INX H INX H XTHL LXI H,0 No read RET * * SERVER this is the main loop of the driver, It * waits for PTDOS code to set the 'STATUS' * to BUSY indicating that there is a character * ready to be processed. It then processes * the character and sends the proper info to the * printing mechanism. * SERVER MVI A,CHCR Send out a CR to reset the printer CALL PUTC MVI A,TRUE Set the line feed flag to TRUE STA LFFG * SERV0 CALL GETC Get a character from PTDOS CALL PROCESS Print the character JMP SERV0 Loop forever * * PROCESS This processes the character. Some characters * are not sent to the printer mechanism; they * are handled specially * A = character to be processed * PROCESS MOV B,A Save character for later CPI CHCR A carriage return? * JZ PRINT If so, print out the buffer * CPI CHLF A line feed? JZ LFEED Process the line feed CPI CHFF A form feed? JZ FFEED Do the form feed CPI CHNOLF No linefeed next time? JZ NOLFD If not, go say so CPI CHFLE Forced end of line? JZ SPCAV Go process if so CPI CHDEL No deletes please! RZ CPI CHNULL Ignore nulls RZ CPI 20H Any control characters? JNC PRO2 No, put character in buffer MVI B,'?' Oddballs get a ? * PRO2 LDA EOLINE Increment end of line INR A STA EOLINE LHLD TXTPT Get text pointer positinn MOV M,B *** Character in B *** INX H Increment it MVI M,0 Store end mark SHLD TXTPT Store pointer RET . Go back now * LFEED CALL TMODE Are we in WPM? RNZ . Yes, so ignore linefeed * LFD1 LDA LFFG Do we print the linefeed? CPI CHNOLF Let's check MVI A,0 Only one LF skip per CHNOLF STA LFFG Next time, we print it RZ . Z=0 says no, so exit MVI A,CHLF Now, print 1 linefeed CALL PUTC LDA PAGE How many lines left on current page? DCR A Let's see STA PAGE RNZ . If there is a line left we're okay LDA FORM Oops! No more lines left STA PAGE Set number of lines to a full page RET * * FFEED In the WPM mode, the remaining lines in the current * page are printed out. If the driver is in the non- * WPM a simple formfeed is printed. * FFEED CALL TMODE Word processing mode? JNZ FFWPM Sure enough * MVI A,CHFF Get formfeed character CALL PUTC Print it JMP FFBOTH * * We are in the WPM, therefore we print the formfeed line by * line. If already at top of form, don't do anything. * FFWPM LDA PAGE Lines left on page MOV B,A LDA FORM Lines per page CMP B JZ FFBOTH If the're the same, formfeed complete CALL LFD1 Print a blank line JMP FFWPM Do it * FFBOTH LDA FORM Set for top of form STA PAGE XRA A Clear No linefeed flag STA LFFG RET * * NOLFD set printing so that no linefeed occurs. This lets * us do over-striking and underlining. * NOLFD STA LFFG RET * * SPCAV this routine informs the word processing mode about * space averaging. * Entry: A = 0 ==> space average * A = anything else ==> don't space average * SPCAV STA SPACE RET * * PRINT This routine prints the entire buffer. * * The next routine strips leading and lagging blanks from the * buffer before sending them out the serial port. This speeds * throughput and is especially noticed with low baud rates. * * Set the new horizontal/vertical motion indexes if necessary * before stripping blanks * PRINT LDA NHI See if new Horizontal motion index ORA A If zero, no change JZ SVMI * CALL NEWMI Let's change it XRA A Re-initialize these bytes STA NHI New Horizontal motion index STA HDPOS We must print forward * MVI A,CHCR Carriage return ensures proper head position CALL PUTC * * Check vertical motion index * SVMI LDA NVI See if new Vertical motion index ORA A Same as above JZ P0 ADI 0FH Add bias for VMI CALL NEWMI Go process it XRA A STA NVI * * Strip all leading blanks * P0 LXI H,BUFFER+1 Point to 1st char positinn * MVI D,0 Blanks counter MVI A,CHSP This is a blank * P1 CMP M Is the character a blank? JNZ P2 No, so stop counting INR D Keep counting, maybe more INX H JMP P1 * P2 DCX H MVI M,0 Put in the marker MOV A,D STA BOLINE Store the beginning of line * * Strip the lagging blanks * LHLD TXTPT Point to last buffer item LDA EOLINE get character count MOV D,A MVI A,CHSP * P3 DCX H DCR D D is the blank counter CMP M Is the character a blank? JZ P3 Yes, keep counting * XRA A Is the line only blanks and/or ? CMP M If so, exit right away with an LF if necessary JZ PRLN4 * P4 INX H Back up the pointer MVI M,0 Store end marker MOV A,D STA EOLINE Store new count SHLD TXTPT Store new buffer end * * * Now, calculate the number of blanks and gaps. * Next, calculate the space average and store it * in an array behind the buffer. * * Upon completion: HL = old line pointer * DE = new line pointer * B = number of spaces * C = number of gaps * AVG CALL TMODE Word processing mode? JZ DRCTN LDA SPACE Do we space average? ORA A JNZ DRCTN Non-zero say no! * SPCGAP LDA BOLINE Get location of 1st non-blank MOV E,A Calculate the offset XRA A MOV D,A LXI H,BUFFER Point to the character buffer DAD D Add offset to get address of the old line INX H MOV E,L Set new-line pointer equal to the old MOV D,H MOV B,A Set number of spaces to zero MOV C,A Set number of gaps, also * * Start counting the gaps and spaces * SPC0 MOV A,M Get the character CPI CHSP Is it a blank? JNZ SPC2 No, go check for something else * SPC1 INR B Yes, add one to blank count INX H Bump buffer pointer MOV A,M We must skip over extra blanks * * Skipping over extra blanks "squeezes" the line * CPI CHSP Is this character a blank? JZ SPC1 Yes, so skip it DCX H Bump pointer back to last space INR C Add one to the GAP count MVI A,CHSP Put in the blank * SPC2 CPI CHWS Is it a tilde? JNZ SPC3 No INR B Yes, increment the blank count INR C It also counts as a gap MVI A,CHSP It is printed as a blank * SPC3 STAX D Store character in the new line INX D Bump the new line pointer INX H Bump the old line pointer ORA A Are we done, a NOP says yes JNZ SPC0 No, keep counting XCHG DCX H Back up over the NOP SHLD TXTPT Save this location CALL YIELD Break for lunch * * The new line has been made; the gaps counted; spaces too * MOV A,C Store the number of gaps STA GAPS CMP B If spaces & gaps are equal JZ NOAVG no averaging required * * Calculate the total number of 1/120" increments per blank * Number = No. spaces * HMI * INCRMT LXI H,0 Initialize the answer LDA HMI Get the HMI MOV E,A MVI D,0 MOV A,B Get number of spaces * INC0 DAD D Multiple add DCR A Done? JNZ INC0 Nope, keep going * * Number of increments is in HL * INC1 XCHG . Now it's in DE LHLD TXTPT Get the array address INX H LDA GAPS Dimension Array(Gaps) * INC2 MVI M,0 Zero the array INX H DCR A Done zeroing? JNZ INC2 Not yet, keep going * * Fill the array with space-averaging data * FILL LDA GAPS Get length of array MOV B,A Save it LHLD TXTPT Get array address minus 1 * FL1 INX H Add 1 to get to proper element MOV A,M Add 1 increment to the element INR A MOV M,A Store new value DCX D Array filled? MOV A,E ORA D Let's see JZ DRCTN Yes, done. Go calculate direction DCR B At end of array? JNZ FL1 No, go to next element JMP FILL At end. Re-start at the beginning * * Determine whether to print forward or backward * * Calculate most efficient direction to print (logic-seeking) * (NOTE: because of a bug in the internal tabbing routine * of the Spinwriter, direct tabbing is not allowed if you * change the horizontal motion index. Since this driver * is capable of motion index changes, it MUST print blanks * to offset the columns properly. The bug with the Spinwriter * is that it reads its panel switches when calculating the * proper column. It does not use the setting sent by the * driver) (G9CUR software package) * DRCTN LDA HDPOS Get print head position PUSH PSW Save it LXI H,BOLINE Point to beginning of line SUB M Find the difference CM ABSVAL Take the absolute value MOV B,A Save it in B INX H Now, get the end of line POP PSW Get head position back SUB M Find the difference CM ABSVAL Take the absolute value SUB B Compare distance to BOL and EOL JP MFWRD If plus, forward is faster * * Print backwards * MBWRD MVI H,CHSP A space to offset the column MVI L,CHBS A backspace to offset the column MVI D,'<' Print backwards LDA EOLINE Get end of line CALL ALIGN Go process the data LDA BOLINE Position of 1st buffer character ORA A Is it in the zero position? JZ MB2 We can't TAB left of margin DCR A * MB2 STA HDPOS Update head position LHLD TXTPT Point the end of buffer * PUSH H Save this character pointer MVI D,0 Now, calculate the end of location ARRAY LDA GAPS Get the number of elements MOV E,A INX H DAD D Add add it to the location of the first element SHLD TXTPT POP H * LXI D,-1 Set up to read buffer backwards JMP PRLINE Print the buffer * * Print forward * MFWRD MVI H,CHBS Set the data MVI L,CHSP MVI D,'>' Print forward LDA BOLINE Get beginning of line CALL ALIGN LDA EOLINE Get last character position INR A STA HDPOS Save new head position * LXI H,BUFFER Point to buffer start LDA BOLINE Compute location of 1st non-blank character MVI D,0 MOV E,A DAD D LXI D,1 Set up to read buffer forward * * Print the buffer * PRLINE DAD D Bump HL MOV A,M Move character in buffer to A ORA A End of buffer? JZ PRLN4 Yes, so go clean up * CPI CHWS Is it a tilde? JNZ PRLN No, so print as is * CALL TMODE Yes it is a tilde JZ PRLN If in the word processing mode, * MVI A,CHSP it must be changed to a blank * PRLN CPI CHCRT If it is a caret, JNZ PRLN0 * CALL TMODE Check and see it space-averaging is switched on MVI A,CHCRT If not, print the caret, JZ PRLN0 * MVI A,CHSP Otherwise, print a non-spreaded blank. JMP PRLN3 Bypass the space-averager * PRLN0 CPI CHSP Is it a blank? JNZ PRLN3 LDA SPACE Is space averaging switched off? ORA A Zero says no MVI A,CHSP JNZ PRLN3 Averaging switched off * CALL TMODE In the word processing mode? MVI A,CHSP Z flag set means no JZ PRLN3 * * This routine prints a "spreaded" blank or, in other words, * it prints an average space. It gets its data from an array * of pre-calculated values. These values are the number of * 1/120" increments for the current space. If the current line * is being printed forward, then these values are read from the * start of the array to the end. If the current line is being * printed backwards, the array will be read from end to start. * This allows for correct overstriking, etc. Doing the space- * averaging by this method results in shorter and faster code * plus fewer storage bytes. * PUSH H Save these values LHLD TXTPT Point to the array DAD D Add the offset SHLD TXTPT Bump pointer for next time LDA HMI Get the current HMI value MOV C,A MOV A,M Get the data from the array * * This routine prints whole blanks as whole blanks. That is, * if there are 12 increments for the current space and the * Horizontal motion index is 11, there is one whole blank and * one remainder. * PRLN1 SUB C Are we out of whole blanks? JM PRCDE Negative result say Yes PUSH PSW No, print a blank MVI A,CHSP CALL PUTC POP PSW JZ PREXT No partial blanks either, so exit JMP PRLN1 Keep blanking * PRCDE ADD C Get correct remainder * * Now, print the partial blank * CALL NEWMI Change the HMI MVI A,CHSP Now, print the partial space CALL PUTC LDA HMI Get normal pitch spacing back CALL NEWMI * PREXT POP H Get the values back JMP PRLINE * PRLN3 CALL PUTC Print the character JMP PRLINE * PRLN4 CALL TMODE Are we in the WPM? JZ CLRBUF No, so no linefeed CALL LFD1 Yes, print a linefeed JMP CLRBUF Go clean up the buffer * * ALIGN This simulates tabbing buy printing out blanks * to the proper column. * Entry: H = BACKSPACE or SPACE (depends on print direction) * L = SPACE or BACKSPACE ( " " " " ) * D = Direction of printing * A = BOLINE or EOLINE (depends on print direction) * ALIGN MOV E,A Save BOLINE/EOLINE MVI A,CHESC Send out "direction" command CALL PUTC MOV A,D D has the direction. (i.e., "<" or ">") CALL PUTC * * Calculate which way to go to reach the column * LDA HDPOS Get last head position SUB E Calculate the direction to print RZ MOV E,A MOV C,H Move in the char to space properly JP AL1 Go print offset blanks * CMA . Get the absolute value INR A The twos complement MOV E,A MOV C,L Move in the correct character * AL1 MOV A,C Print the character CALL PUTC MOV A,E Are we done? DCR A RZ . Yes, return to caller MOV E,A Nope, keep going JMP AL1 * CLRBUF LXI H,BUFFER+1 Clear buffer SHLD TXTPT XRA A STA EOLINE Reset counters STA BOLINE STA SPACE STA BUFFER+1 RET * * Used only for setting vertical and horizontal movement * NEWMI ADI 40H Add bias for Spinwriter PUSH PSW Save index MVI A,CHESC Send the escape code CALL PUTC MVI A,']' Send the operation code CALL PUTC POP PSW Send the index CALL PUTC Go do it RET . All done * * Twos complement routine * ABSVAL CMA . Take the absolute value INR A RET * * WAIT wait for the printer driver to completely finish ALL * of its printing. This routine is used only in the * non-word processing mode and in closing the driver. * WAIT CALL TI Test the input status RZ . Return when the driver is DONE CALL TASK BUSY now, let it get DONE JMP WAIT keep trying * * PUTC put a character out to the printer mechanism * Entry: A = the character to be sent * PUTC PUSH PSW Save the character CALL CANTST Character canceled? JNZ PUTC0 Nope, so go print it POP PSW Afraid so, ignore it RET * PUTC0 CALL TOD Is the printer ready? JZ PUTC1 Yes, it is CALL YIELD Not yet, let PTDOS run JMP PUTC0 * PUTC1 POP PSW Get the character ANI 07FH Mask off the parity CALL SOB Set BUSY and send the character RET * * GETC get a character from the PTDOS task * Return: A = the character sent * GETC CALL SID First set input DONE * GETC0 CALL TI Test input status JNZ GETC1 Yes, the character is ready CALL YIELD Let PTDOS run awhile JMP GETC0 * GETC1 LDA DATA Get character that was passed RET * * CANTST - test the cancel flag * CANTST LDA CANCEL CPI TRUE RET * * TMODE - test Word Processor mode * set Z if false * TMODE MOV B,A LDA MODE ORA A MOV A,B RET * * SID set input DONE. This sets the input (to the printer * driver) status semaphore to the DONE state. This * indicates to the PTDOS task that the printer driver * is ready to process another character. * SID MVI A,DONE STA STATUS RET * * SIB set input BUSY. This sets the input (to the printer * driver) status semaphore to the BUSY state. This * tells the PTDOS task that it cannot send the printer * driver a character. PTDOS code must wait for the * semaphore to go DONE. * SIB STA DATA Store character for driver MVI A,BUSY STA STATUS make the printer driver BUSY RET * * SOB set output BUSY. This sets the hardware semaphore * to its BUSY state and starts the printer mechanism * going. There is no software complement (sod-set * output DONE) because the printer hardware dose this. * SOB OUT IOSDP send out character RET * * TI test input status. This tests the input (from the * PTDOS task) status for DONE and sets the Z flag * to 1 for DONE, 0 for BUSY. Carry flag is always 0. * TI LDA STATUS CPI DONE RET * * TOD test output for DONE. This tests the printer * mechanism status semaphore for a DONE condition. * The Z flag is set to 1 if DONE, 0 if not * TOD IN IOSSP read in status port ANI 0A0H This is the Sol CTS & TBE CPI 0A0H JNZ TOD1 NZ=DONE * XRA A Printer ready RET * TOD1 ORI 1 Printer not ready RET * NOAVG MVI A,0FFH STA SPACE JMP DRCTN * * INIT initialize the driver * INIT LXI H,SERVER Get server's start address SHLD IRETADR LXI H,ISTKPTR Get server's stack address SHLD TSKSTK * XRA A Clear A for initializing variables STA MODE Set to non-word processing mode STA CANCEL Cancel mode is false STA STATUS Set input status to DONE STA HDPOS Set initial head pos to left margin STA BOLINE Initialize beginning byte STA EOLINE Initialize end byte * LXI H,0 Clear HL SHLD BUFFER Clean up the buffer * MVI A,IPZ Set initial page size STA PAGE * MVI A,IFZ Set initial form size STA FORM * MVI A,IVI Set initial vert increment STA VMI STA NVI Set flag for change * MVI A,IHI Set initial horiz increment STA HMI STA NHI Set Flag for change * LXI H,BUFFER+1 Set the text pointer SHLD TXTPT * CALL TASK * RET * * Storage area * STATUS DS 1 print driver BUSY/DONE flag PTSTK DS 2 PTDOS stack address TSKSTK DS 2 Driver stack address MODE DS 1 Mode flag: WPM or non WPM LFFG DS 1 linefeed-after-CR flag DATA DS 1 the character storage buffer CANCEL DS 1 cancel flag NVI DS 1 VMI DS 1 Vetical Motion Index NHI DS 1 HMI DS 1 Horizontal Motion Index HDPOS DS 1 current head position BOLINE DS 1 beginning of line pointer EOLINE DS 1 end of line pointer TXTPT DS 2 buffer pointer SPACE DS 1 space average on/off GAPS DS 1 number of gaps in a line PAGE DS 1 lines on current page FORM DS 1 lines per page PERFS DB 0 * * STACKS * DS 45 Stack area ISTKPTR DS 8 init stack address IRETADR DS 2 init RET addr * BUFFER DS 2 DS 250 Space for character buffer and array * MARK EQU $ to see the driver end address * END