home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols100 / vol194 / plot33.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  72.9 KB  |  2,588 lines

  1. ;-----------------------------------------------------------------------
  2. ;            PROGRAM PLOT
  3. ;-----------------------------------------------------------------------
  4. ;
  5. ;THIS PROGRAM READS A SEQUENTIAL PLOT COMMAND FILE, MAKES A MEMORY IMAGE
  6. ;OF THE PLOT, AND PRINTS THE PLOT ON THE PRINTER
  7. ;
  8. ;    COPYRIGHT (C) 1984 BY THOMAS E. SPEER. ALL RIGHTS RESERVED
  9. ;                          887 BRIDDLEWOOD LN.
  10. ;                          DAYTON, OHIO  45430
  11. ;    THIS PROGRAM IS RELEASED TO THE PUBLIC DOMAIN FOR 
  12. ;    NON-COMMERCIAL USE ONLY.
  13. ;
  14. ;
  15. ;REVISION HISTORY
  16. ;
  17. ;    VERSION 3.3    31 JUL 84    T. SPEER
  18. ;    FIXED BUG IN OKI VERSION OF PRESET ROUTINE.  EXTRANEOUS EXIT
  19. ;    GRAPHICS COMMAND WAS BEING SENT.  
  20. ;
  21. ;    VERSION 3.3     7 JUL 84    T. SPEER
  22. ;    ADDED TEXT COMAND.  ADDED QUIT TO PROPERLY CLOSE OUTPUT FILE.
  23. ;    MODIFIED GBUFOUT TO SKIP TOTALLY BLANK LINES.
  24. ;
  25. ;    VERSION 3.2B    27 JUN 84    T. SPEER
  26. ;    CROSS HATCHED COLOR PATTERNS FINE TUNED.  ADDED BLINKING 
  27. ;    STATUS MESSAGE.  SPECIAL PATTERNS CORRECTED.  ALL SUBROUTINES
  28. ;    PLACED IN ALPHABETICAL ORDER.
  29. ;
  30. ;    VERSION 3.2A    18 JUN 84    T. SPEER
  31. ;    COLOR PATTERNS CHANGED.  15 SPECIAL PATTERNS ADDED FROM
  32. ;    49 TO 63.  THESE MAKE IT EASIER TO MATCH PATTERNS FROM
  33. ;    OTHER SYSTEMS.  THE DEFAULT PATTERNS SUPPLIED ARE THE SAME
  34. ;    AS USED FOR NMOS AND CMOS VLSI CIF PLOTS.
  35. ;
  36. ;    VERSION 3.2    28 MAR 84    T. SPEER
  37. ;    CITOH MODIFICATIONS DEBUGGED. IDS MODS REMOVED (SAME AS OKI)
  38. ;    BASE2 MODS REMOVED (UNTESTED- NOT SUITABLE FOR RELEASE)
  39. ;
  40. ;    VERSION 3.2    3 FEB 84    T. SPEER
  41. ;    THIS VERSION ADDS THE PATTERNED ERASE, THE UPLOAD (COLOR 
  42. ;    CODES), AND EXTEND COMMANDS.
  43. ;
  44. ;    VERSION 3.1    10 DEC 83    T. SPEER
  45. ;    ADDED PATTERN FILLS AND LINES USING A CROSS-HATCHED METHOD AND
  46. ;    AN ORDERED DITHER MATRIX METHOD.
  47. ;
  48. ;    VERSION 3.0    5 NOV 83    T. SPEER
  49. ;    THIS VERSION READS ALL X AND Y COORDINATES AS 
  50. ;    2 BYTE FIXED POINT NUMBERS (16 BIT SIGNED VALUES BETWEEN 0 AND 1)
  51. ;
  52. ;    COORDINATES MUST BE BETWEEN 0.0 AND 1.0 TO LIE ON PLOT.  THIS 
  53. ;    MAKES THE PLOT DEVICE INDEPENDENT.  THE FIXED POINT VALUES ARE EASILY
  54. ;    CREATED BY THE HIGH LEVEL PROGRAM BY MULTIPLYING THE COORDINATES BY
  55. ;    32767 AND TRUNCATING TO AN INTEGER.
  56. ;
  57. ;    VERSION 2.0            T. SPEER
  58. ;    THIS VERSION USED 32 BIT FLOATING POINT INTEGERS WITH A FORTRAN
  59. ;    ROUTINE PATCHED IN TO DO THE CONVERSION TO INTEGER RASTER COORD.
  60. ;
  61. ;    VERSION 1.0            T. SPEER
  62. ;    THIS VERSION USED 16 BIT INTEGER COORDINATES THAT WERE TIED TO
  63. ;    THE EPSON MX-80 RESOLUTION.  NO CONVERSION WAS REQUIRED.
  64. ;
  65. ;-----------------------------------------------------------------------
  66. ;
  67.     ORG    100H        ;BEGINNING OF TPA
  68.     MVI    C,09H        ;SELECT PRINT FUNCTION
  69.     LXI    D,BANNER    ;PRINT BANNER MESSAGE
  70.     CALL    FDOS
  71. ;
  72.     JMP    ENTRY        ;JUMP AROUND VARIABLE STORAGE AREA
  73. BANNER:    DB    '         PLOT Version 3.3  31/7/84',0DH,0AH
  74.     DB    '            (c) by T. E. Speer',0DH,0AH,0AH,'$'
  75.     DB    '           All Rights Reserved',0DH,0AH,0DH,0AH,'$'
  76. ;
  77. ;
  78. ;
  79. ;========================= PRINTER FLAGS ==================================
  80. ;SET THE ONE THAT MATCHES YOUR PRINTER TO TRUE, AND SET THE OTHERS TO FALSE.
  81. ;
  82.     TRUE    EQU    0FFFFH
  83.     FALSE    EQU    NOT TRUE
  84. EPSON    EQU    TRUE        ;FLAG FOR EPSON MX-80 WITH GRAPHTRAX
  85. CITOH    EQU    FALSE        ;FLAG FOR CITOH, PROWRITER, ETC 
  86. OKI    EQU    FALSE        ;FLAG FOR OKIDATA
  87. ;IDS        SET OKI   FLAG TO TRUE- IDS PRINTERS ACT SAME AS OKI
  88. ;GEMINI    10    SET EPSON FLAG TO TRUE- GEMINI 10 ACTS SAME AS EPSON
  89. ;NEC        SET CITOH FLAG TO TRUE- NEC       ACTS SAME AS CITOH
  90. ;APPLE DOT MATRIX - ACTS SAME AS CITOH, BUT SOME <ESC> SEQUENCES DIFFER.
  91. ;        SET CITOH FLAG TO TRUE AND CHECK <ESC> SEQUENCES AT ESCK,
  92. ;        AND IN LN772 AND PRESET SUBROUTINES.
  93. ;
  94. ;====================== PRINTER PARAMETERS ===============================
  95. ; THIS SECTION SETS THE SPECIFIC CONSTANTS FOR YOUR PRINTER.
  96. ;
  97. ;***** NOTE ***** THE MAXIMUM VALUE FOR MAXX THAT CAN BE USED IS 1530.
  98. ; THE MAXIMUM VALUE FOR MAXY THAT CAN BE USED IS 1785. THESE LIMITS 
  99. ; ARE REQUIRED TO AVOID ARITHMETIC OVERFLOWS.
  100. ; THE SIZE OF THE MAP ( (MAXX+1)*(MAXY+1)/7 ) MUST FIT BETWEEN THE END OF
  101. ; THE PROGRAM AND THE END OF THE TPA.
  102. ;
  103. ;    PRINTERS SEEM TO HAVE TWO BASIC METHODS OF GOING INTO GRAPHICS
  104. ; MODE.  THE EPSON AND CITOH PRINTERS USE AN <ESC> SEQUENCE 
  105. ; FOLLOWED BY A SPECIFIED NUMBER OF GRAPHICS BYTES.  THE OKIDATA AND IDS
  106. ; PRINTERS USE AN <ETX> TO TOGGLE INTO GRAPHICS MODE, AND THEN REMAIN
  107. ; IN GRAPHICS UNTIL AN <ETX><SO> IS RECEIVED.  
  108. ;      THE BASIC PHILOSOPHY ADOPTED HERE IS TO APPEND THE <ESC> 
  109. ; SEQUENCE AND THE NUMBER OF BYTES (IF REQUIRED) TO THE HEAD OF THE 
  110. ; GRAPHICS OUTPUT BUFFER FOR THOSE PRINTERS IN THE FIRST GROUP. PRINTERS 
  111. ; IN THE SECOND GROUP ARE HANDLED BY PUTTING THE <ETX> COMMANDS IN THE 
  112. ; GBUFOUT ROUTINE.  ALL PRINTERS ARE KEPT IN NORMAL TEXT MODE, EXCEPT
  113. ; WHEN ACTUALLY PRINTING GRAPHICS.
  114. ;
  115.     IF    EPSON
  116. MAXX    EQU    479        ;SET MAXIMUM WIDTH TO EPSON LOW RES MODE
  117. MAXY    EQU    573        ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT
  118. MAPSIZE    EQU    39360D    ;TOTAL SIZE OF MAP
  119. CWIDTH    EQU    6        ;RASTER WIDTH OF A PRINTED CHARACTER
  120. NO8BIT    EQU    FALSE        ;SET TO FALSE IF YOUR INTERFACE CAN
  121. MSBTOP    EQU    TRUE        ;MOST SIG. BIT IS TOP OF STROKE
  122. ;    SET UP GRAPHIC OUTPUT BUFFER AREA
  123. ESCK    DB    1BH,'K'        ;DEFINE ESC "K" CHARACTER SEQUENCE
  124. NGRAPH    DW    0000H        ;INITIALIZE GRAPHIC COUNTER
  125. GBUFF    DS    MAXX+1        ;SET ASIDE AREA FOR GRAPHIC O/P BUFFER
  126.     ENDIF            ;(EPSON)
  127. ;
  128.     IF    CITOH
  129. MAXX    EQU    636        ;SET MAXIMUM WIDTH FOR 80 DOTS/INCH MODE
  130. MAXY    EQU    573        ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT
  131. MAPSIZE    EQU    52234D    ;TOTAL SIZE OF MAP
  132. CWIDTH    EQU    8        ;RASTER WIDTH OF A PRINTED CHARACTER
  133. NO8BIT    EQU    FALSE        ;SET TO FALSE EVEN IF 7 BIT INTERFACE
  134. MSBTOP    EQU    FALSE        ;LEAST SIG. BIT IS TOP DOT OF STROKE
  135. ;    SET UP GRAPHIC OUTPUT BUFFER AREA
  136. ESCK:    DB    1BH,'S',0,0,0,0    ;GRAPHIC MODE SELECT CODE
  137. GBUFF:    DS    MAXX+1        ;SET ASIDE AREA FOR GRAPHIC O/P BUFFER
  138. NGRAPH    DW    0000H        ;INITIALIZE GRAPHIC COUNTER
  139.     ENDIF            ;(CITOH)
  140. ;
  141.     IF    OKI
  142. MAXX    EQU    575        ;SET MAXIMUM WIDTH FOR 72 DOTS/INCH
  143. MAXY    EQU    573        ;SET MAXIMUM HEIGHT TO MAKE SQUARE PLOT
  144. MAPSIZE    EQU    47232D        ;TOTAL SIZE OF MAP
  145. CWIDTH    EQU    6        ;RASTER WIDTH OF CHARACTER
  146. NO8BIT    EQU    FALSE        ;SHOULD BE FALSE EVEN IF 7 BIT INTERFACE
  147. MSBTOP    EQU    FALSE        ;LEAST SIG. BIT IS TOP DOT OF STROKE
  148. ;    SET UP GRAPHIC OUTPUT BUFFER AREA
  149. GBUFF:    DS    MAXX+1
  150. NGRAPH    DW    0000H
  151.     ENDIF            ;(OKI)
  152. ;
  153. ;
  154. ;========================= DATA STORAGE SECTION ============================
  155. ;
  156. COLOR    DB    0
  157. XPOS    DW    0
  158. YPOS    DW    0
  159. X    DW    0
  160. Y    DW    0
  161. YFILL    DW    0
  162. NCHAR    DW    0
  163. ACHAR    DB    40H
  164. POINTER    DB    128D            ;POINTER IN FILE BUFFER
  165. POINTR2    DB    00H            ;POINTER IN OUTPUT FILE BUFFER
  166. OLDSTK    DW    0000H
  167. STACK    DS    80H            ;SET ASIDE 128 LEVEL STACK
  168. XDOT    DW    0000H            ;POSITION OF DOT TO BE PLOTTED
  169. YDOT    DW    0000H            ;POSITION OF DOT TO BE PLOTTED
  170. XYADDR    DW    ORIGIN            ;ADDRESS OF X,Y LOCATION
  171. XYBIT    DB    00H            ;BIT IN BYTE @ XYADDR FOR X,Y
  172. DIVDND    DW    0000H            ;2 BYTE DIVIDEND IN DIVIDE
  173. DIVSOR    DB    00H            ;1 BYTE DIVISOR IN DIVIDE
  174. QOTENT    DB    00H            ;1 BYTE QUOTIENT FROM DIVIDE
  175. RMANDR    DB    00H            ;1 BYTE REMAINDER FROM DIVIDE
  176. BLANK    EQU    ' '
  177. NOSPEC    DB    'No File Specified',0DH,0AH,'$'    ;ERROR MESSAGES
  178. NOFILE    DB    'File Not Found',0DH,0AH,'$'
  179. EOFMSG    DB    'End of File',0DH,0AH,'$'
  180. NODIR    DB    'No Directory Space Available',0DH,0AH,'$'
  181. NOROOM    DB    'Disk is Full',0DH,0AH,'$' 
  182. UNKNCH    DB    'Undefined Command Character Encountered',0DH,0AH,'$'
  183. STAT1    DB    '           Working ...              ',0DH,'$'
  184. STAT2    DB    '                   ... Working      ',0DH,'$'
  185. STAT3    DB    '           Printing Picture         ',07H,0DH,'$'
  186. STATNO    DB    00H
  187. DELTAX    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  188. DELTAY    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  189. EPSLNX    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  190. EPSLNY    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  191. SX    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  192. SY    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  193. DELTA3    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  194. NI    DW    0000H            ;LOCAL VARIABLES FOR INCPLT
  195. ;
  196. CMASK    DB    0FFH            ;COLOR MASK
  197. PATRN    DS    8            ;CELL STORAGE FOR CLRMAP (ERASE)
  198. PLAIDS    DB    00H,01H,71H,13H,05H,0FH,35H,11H    ; CROSS HATCHED PATTERNS
  199. ;
  200. CIFPAT    DB     00H, 03H, 48H, 03H, 00H, 30H, 84H, 30H    ;ND
  201.     DB     00H,0CCH, 00H,0CCH, 00H, 00H, 00H, 00H    ;NI  S
  202.     DB     08H, 04H, 02H, 01H, 80H, 40H, 20H, 10H    ;NT   P
  203.     DB     11H, 30H, 71H, 30H, 11H, 03H, 17H, 03H    ;NC    E
  204.     DB     22H, 00H, 88H, 00H, 22H, 00H, 88H, 00H    ;NM     C
  205.     DB    0C0H, 81H, 03H, 06H, 03H, 81H,0C0H, 60H    ;NB  P   I
  206.     DB     1CH, 3EH, 36H, 3EH, 1CH, 00H, 00H, 00H    ;NG   A   A
  207.     DB     00H, 00H, 00H, 00H, 00H, 00H, 00H, 01H    ;CW    T   L
  208.     DB     04H, 11H, 04H, 00H, 40H, 11H, 40H, 00H    ;CD     T
  209.     DB     02H, 04H, 08H, 10H, 20H, 40H, 80H, 01H    ;CP      E
  210.     DB     00H, 00H, 10H, 38H, 10H, 00H, 00H, 00H    ;CS       R
  211.     DB     66H, 99H, 99H, 66H, 66H, 99H, 99H, 66H    ;CC        N
  212.     DB     00H, 00H, 80H, 10H, 00H, 00H, 10H, 80H    ;CM         S
  213.     DB     81H,0C3H, 66H, 66H,0C3H, 81H, 00H, 00H    ;CG
  214.     DB     0FH, 0EH, 0CH, 08H, 00H, 00H, 00H, 00H    ;CE
  215. ;
  216. DITHARR    DB     63,  95,  71, 103,  65,  97,  73, 105    ;     ORDERED
  217.     DB    111,  79, 119,  87, 113,  81, 121,  89    ; 
  218.     DB     75, 107,  67,  99,  77, 109,  69, 101    ;     DITHER
  219.     DB    123,  91, 115,  83, 125,  93, 117,  85    ; 
  220.     DB     66,  98,  74, 106,  64,  96,  72, 104    ;     MATRIX
  221.     DB    114,  82, 122,  90, 112,  80, 120,  88    ; 
  222.     DB     78, 110,  70, 102,  76, 108,  68, 100    ; 
  223.     DB    126,  94, 118,  86, 124,  92, 116,  84    ; 
  224. ;
  225. ;
  226. ;
  227. ;
  228. BOOT    EQU    0000H            ;CP/M SYSTEM ENTRY POINT
  229. FCB    EQU    BOOT+005CH        ;LOCATION OF FILE CONTROL BLOCK
  230. DMA    EQU    BOOT+0080H        ;FILE BUFFER ADDRESS
  231. FDOS    EQU    BOOT+0005H        ;ENTRY POINT FOR CPM FUNCTIONS
  232. FCB2    DS    33D            ;OUTPUT FILE CONTROL BLOCK
  233. DMA2    DS    128D            ;OUTPUT FILE BUFFER
  234. OPDISK    DB    00H            ;OUTPUT TO DISK FLAG
  235. ;
  236. ;-----------------------------------------------------------------------
  237. ;
  238. ENTRY    LXI    SP,STACK+80H    ;SET NEW 128 LEVEL STACK
  239.     LDA    FCB+9        ;GET FIRST CHARACTER OF FILE TYPE
  240.     CPI    BLANK        ;IS TYPE BLANK?
  241.     JNZ    NAME            ;NO- TYPE HAS BEEN SPECIFIED
  242.     MVI    A,'V'        ;MAKE DEFAULT TYPE "VEC"
  243.     STA    FCB+9        ;STORE DEFAULT IN FILE TYPE AREA
  244.     MVI    A,'E'
  245.     STA    FCB+10        ;STORE DEFAULT IN FILE TYPE AREA
  246.     MVI    A,'C'
  247.     STA    FCB+11        ;DONE- DEFAULT IS SET
  248. NAME    LDA    FCB+1            ;GET FIRST CHAR FROM FCB
  249.     CPI    BLANK            ;IS NAME BLANK?
  250.     JNZ    OPENOP            ;JUMP IF A FILE NAME EXISTS
  251.     MVI    C,09H            ;SELECT PRINT STRING FUNCTION
  252.     LXI    D,NOSPEC        ;PASS ERROR MESSAGE
  253.     CALL    FDOS            ;PRINT IT
  254.     JMP    BOOT            ;RETURN TO CPM SYSTEM LEVEL
  255. OPENOP    LDA    FCB+17D            ;GET 1ST CHAR OF O/P FILE
  256.     CPI    BLANK            ;IS NAME BLANK?
  257.     JZ    OPENFIL            ;BLANK= NORMAL PRINT OUTPUT
  258.     MVI    A,01H            ;SET O/P FILE FLAG=1 (DISK O/P)
  259.     STA    OPDISK            ;STORE FLAG
  260. ;
  261. ;    MOVE O/P FILE NAME TO NEW FCB
  262. ;
  263.     MVI    C,16D            ;HALF OF FCB#1 IS O/P INFO
  264.     LXI    D,006CH            ;START OF O/P FILE NAME
  265.     LXI    H,FCB2            ;SET DESTINATION ADDRESS
  266. MOVFCB    LDAX    D            ;GET NAME CHARACTER
  267.     MOV    M,A            ;STORE NAME CHARACTER
  268.     INX    D            ;INCREMENT OLD NAME ADDRESS
  269.     INX    H            ;INCREMENT NEW NAME ADDRESS
  270.     DCR    C            ;DECREMENT COUNTER
  271.     JNZ    MOVFCB            ;LOOP BACK IF NOT DONE
  272. ;
  273.     MVI    A,0            ;CLEAR ACCUMULATOR
  274.     STA    FCB2+32D        ;ZERO CR FIELD IN O/P FCB
  275. ;
  276.     LDA    FCB2+9            ;GET 1ST CHAR IN O/P FILE TYPE
  277.     CPI    BLANK            ;IS FILE TYPE BLANK?
  278.     JNZ    DELETE            ;NOT BLANK- GO TO DELELTE OLD
  279.     MVI    A,'P'            ;MAKE DEFAULT 'PLT'
  280.     STA    FCB2+9            ;STORE DEFAULT 'P'
  281.     MVI    A,'L'
  282.     STA    FCB2+10            ;STORE DEFAULT 'L'
  283.     MVI    A,'T'
  284.     STA    FCB2+11            ;STORE DEFAULT 'T'
  285. ;
  286. DELETE    LXI    D,FCB2            ;PASS O/P FILE FCB
  287.     MVI    C,19D            ;SELECT DELETE FUNCTION
  288.     CALL    FDOS            ;DELETE OLD FILE
  289. ;
  290. ;    MAKE NEW O/P FILE
  291. ;
  292.     MVI    C,26D            ;SELECT SET DMA FUNCTION
  293.     LXI    D,DMA2            ;PASS O/P FILE BUFFER ADDRESS
  294.     CALL    FDOS            ;SET DMA ADDRESS
  295. ;
  296.     MVI    C,22D            ;SELECT MAKE FILE FUNCTION
  297.     LXI    D,FCB2            ;PASS FCB FOR O/P
  298.     CALL    FDOS            ;MAKE NEW FILE
  299.     CPI    0FFH            ;IS DIRECTORY FULL?
  300.     JNZ    OPENFIL            ;NO- GO ON WITH PROGRAM
  301. ;
  302.     MVI    C,09H            ;SELECT PRINT FUNCTION
  303.     LXI    D,NODIR            ;PASS NO DIRECTORY SPACE MSG
  304.     CALL    FDOS            ;PRINT ERROR MESSAGE
  305.     JMP    BOOT            ;FATAL ERROR- QUIT
  306. ;
  307. ;OPEN DISK FILE OF PLOT COMMANDS
  308. ;
  309. OPENFIL    MVI    C,26D            ;SELECT SET DMA FUNCTION
  310.     LXI    D,DMA            ;PASS I/P BUFFER LOCATION
  311.     CALL    FDOS            ;SET DMA TO I/P BUFFER
  312. ;
  313.     MVI    C,0FH            ;SELECT OPEN FILE FUNCION
  314.     MVI    A,00H            ;CLEAR ACCUMULATOR
  315.     STA    FCB+12            ;CLEAR EXTENT COUNTER
  316.     STA    FCB+14            ;CLEAR S2 PARAMETER IN FCB
  317.     LXI    D,FCB            ;PASS FCB
  318.     CALL    FDOS            ;OPEN FILE
  319.     CPI    0FFH            ;WAS FILE FOUND?
  320.     JNZ    REWIND            ;IF FILE EXITS, REWIND IT
  321.     MVI    C,09H            ;SELECT PRINT FUNCTION
  322.     LXI    D,NOFILE        ;PASS MESSAGE
  323.     CALL    FDOS            ;PRINT IT
  324.     JMP    BOOT            ;RETURN TO CPM COMMAND LEVEL
  325. ;
  326. REWIND    MVI    A,00H            ;CLEAR ACCUMULATOR
  327.     STA    FCB+32D            ;REWIND BY SETTING RECORD#=0
  328. ;
  329. PARSE    CALL    BYTE        ;GET COMMAND CHARACTER
  330.     CPI    60H        ;IS IT LOWER CASE?
  331.     JC    PARSE0        ;NO, SO SKIP SHIFTING IT
  332.     XRI    00100000B    ;SHIFT CHARACTER TO UPPER CASE
  333. ;
  334. PARSE0    CPI    'P'        ;IS IT A "P"?
  335.     PUSH    PSW        ;SAVE COMMAND CHARACTER
  336.     CZ    POINT        ;P COMMANDS PLOT POINT
  337.     POP    PSW
  338.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  339. ;
  340.     CALL    STAT        ;DISPLAY STATUS MESSAGE
  341. ;
  342. ;
  343.     CPI    'C'
  344.     PUSH    PSW
  345.     CZ    COLOUR        ;C COMMANDS SET COLOR
  346.     POP    PSW
  347.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  348. ;
  349.     CPI    'D'        ;IS IT A "D"?
  350.     PUSH    PSW        ;SAVE COMMAND CHARACTER
  351.     CZ    PLOTSEG        ;D COMMANDS PLOT SEGMENT
  352.     POP    PSW
  353.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  354. ;
  355.     CPI    'E'
  356.     PUSH    PSW
  357.     CZ    CLRMAP        ;E COMMANDS CLEAR MEMORY MAP TO COLOR
  358.     POP    PSW
  359.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  360. ;
  361.     CPI    'F'
  362.     PUSH    PSW
  363.     CZ    FILL        ;F COMMANDS FILL AREA TO COLOR
  364.     POP    PSW
  365.     JZ    PARSE            ;LOOP BACK FOR NEW CHARACTER
  366. ;
  367.     CPI    'I'
  368.     PUSH    PSW
  369.     CZ    INCPLT        ;I COMMANDS PLOT INCREMENTAL SEGMENT
  370.     POP    PSW
  371.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  372. ;
  373.     CPI    'M'        ;M COMMANDS MOVE TO COORD W/O PLOTTING
  374.     PUSH    PSW
  375.     CZ    MOVE
  376.     POP    PSW
  377.     JZ    PARSE
  378. ;
  379.     CPI    'N'
  380.     JZ    PARSE        ;N COMMANDS A NO OPERATION LOOP
  381. ;
  382.     CPI    'O'
  383.     PUSH    PSW
  384.     CZ    MAPOUT        ;O COMMANDS PRINTING OF PLOT
  385.     POP    PSW
  386.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  387. ;
  388.     CPI    'Q'
  389.     PUSH    PSW
  390.     CZ    QUIT        ;Q COMMANDS TERMINATION OF PROGRAM
  391.     POP    PSW
  392.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  393. ;
  394.     CPI    'S'
  395.     PUSH    PSW
  396.     CZ    STRING        ;S COMMANDS CHARACTER STRING PLOTTING
  397.     POP    PSW
  398.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  399. ;
  400.     CPI    'T'
  401.     PUSH    PSW
  402.     CZ    TEXT        ;T COMMANDS RAW TEXT OUTPUT
  403.     POP    PSW
  404.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  405. ;
  406.     CPI    'U'
  407.     PUSH    PSW
  408.     CZ    UPLOAD        ;U COMMANDS UPLOAD OF COLOR PATERNS
  409.     POP    PSW
  410.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  411. ;
  412.     CPI    'X'
  413.     PUSH    PSW
  414.     CZ    XTEND        ;PROVISION FOR NON-STANDARD COMMANDS
  415.     POP    PSW
  416.     JZ    PARSE            ;LOOP BACK FOR NEW CHAR
  417. ;
  418.     CPI    0DH            ;IGNORE CARRIAGE RETURNS
  419.     JZ    PARSE
  420. ;
  421.     CPI    0AH
  422.     JZ    PARSE            ;IGNORE LINE FEEDS
  423. ;
  424. ;    COMMAND CHARACTER DOES NOT MATCH ANY DEFINED COMMAND
  425. ;
  426.     MVI    C,09H        ;SELECT PRINT STRING FUNCTION
  427.     LXI    D,UNKNCH    ;PASS UNDEFINED CHARACTER MESSAGE
  428.     CALL    FDOS        ;PRINT IT
  429.     JMP    PARSE        ;LOOP UP TO TOP TO GET NEW CHARACTER
  430. ;
  431. ;-----------------------------------------------------------------------
  432. ;                 DEFINE SUBROUTINES
  433. ;-----------------------------------------------------------------------
  434. ;
  435. ;    CONVERT BINARY INTEGER TO DECIMAL ASCII NUMBER
  436. ;
  437. ;    INPUTS:
  438. ;        N (BINARY NUMBER) IN [DE]
  439. ;        ADDRESS TO STORE LOW DIGIT IN [HL]
  440. ;    OUTPUTS:
  441. ;        ASCII NUMBER STORED IN MEMORY, HIGH BYTE FIRST.
  442. ;             NOTE: THE ADDRESS IS DECREMENTED FOR EACH CHAR.
  443. ;    REGISTER STATUS:
  444. ;        ALL REGISTER VALUES PRESERVED
  445. ;    ERROR CONDITIONS:
  446. ;        NONE
  447. ;
  448.     IF    CITOH
  449. BINDEC:    PUSH    H        ;SAVE REGISTERS
  450.     PUSH    D
  451.     PUSH    B
  452.     PUSH    PSW
  453. ;
  454.     MVI    A,10D        ;GET A TEN
  455.     STA    DIVSOR        ;DIVISIONS WILL BE BY BASE 10
  456. ;
  457. BDECLP:    PUSH    H        ;SAVE ADDRESS FOR FUTURE USE
  458.     MOV    A,D
  459.     STA    DIVDND        ;FIRST DIVIDE HIGH BYTE
  460.     MVI    A,00H
  461.     STA    DIVDND+1    ;16 BIT DIVIDEND NOW = 8 BIT N HIGH BYTE
  462.     CALL    DIVIDE        ;DIVIDE BY 10
  463.     LDA    QOTENT
  464.     MOV    D,A        ;RESULT IS HIGH BYTE OF NEW N
  465.     LXI    H,RMANDR
  466.     MOV    H,M        ;DIVIDE REMAINDER WITH LOW BYTE OF N
  467.     MOV    L,E        ;ADD LOW BYTE OF N TO REMAINDER
  468.     SHLD    DIVDND
  469.     CALL    DIVIDE        ;DIVIDE LOW BYTES BY 10
  470.     POP    H        ;RETRIEVE ADDRESS TO RECEIVE CHARACTER
  471.     LDA    RMANDR        ;REMAINDER IS DIGIT
  472.     ADI    30H        ;CONVERT DIGIT TO ASCII
  473.     MOV    M,A        ;STORE CHARACTER
  474.     DCX    H        ;MOVE POINTER LEFT
  475.     LDA    QOTENT        ;GET RESULT OF DIVISION
  476.     MOV    E,A        ;RESULT IS LOW BYTE OF NEW N
  477.     ORA    D        ;IS NEW END = 0?
  478.     JNZ    BDECLP        ;LOOP BACK UP IF > 0
  479. ;
  480.     POP    PSW
  481.     POP    B
  482.     POP    D
  483.     POP    H        ;REGISTERS RESTORED
  484.     RET
  485.     ENDIF            ;(CITOH)
  486. ;----------------------------------------------------------------------
  487. ;
  488. ;    BMULT PERFORMS A 1-BYTE BY 2-BYTE MULTIPLY
  489. ;
  490. ;    THIS ROUTINE IS FROM ELECTRONICS MAGAZINE, FEB 24, 1982.
  491. ;    BY JERRY L. GOODRICH, PENN. STATE U.
  492. ;
  493. ;    INPUTS:
  494. ;        8-BIT NUMBER IN [A]
  495. ;        16-BIT NUMBER IN [BC]
  496. ;    OUTPUTS:
  497. ;        PRODUCT IN [A],[HL] (HIGH BYTE IN [A])
  498. ;    REGISTER STATUS:
  499. ;        SEE INPUTS AND OUTPUTS
  500. ;    ERROR CONDITIONS:
  501. ;        NONE
  502. ;
  503. BMULT    LXI    H,0        ;ZERO PARTIAL PRODUCT
  504.     LXI    D,7        ;D=0,E=BIT COUNTER
  505.     ADD    A        ;GET FIRST MULTIPLIER BIT
  506. LOOP1:    JNC    ZERO        ;ZERO SKIP
  507.     DAD    B        ;ONE-ADD MULTIPLICAND
  508.     ADC    D        ;ADD CARRY TO THIRD BYTE OF PRODUCT
  509. ZERO:    DAD    H        ;SHIFT PRODUCT LEFT
  510.     ADC    A
  511.     DCR    E        ;DECREMENT BIT COUNTER
  512.     JNZ    LOOP1        ;LOOP UNTIL DONE
  513.     RNC            ;DONE IF NO CARRY
  514.     DAD    B        ;OTHERWISE DO LAST ADD
  515.     ADC    D
  516.     RET            ;AND RETURN
  517. ;-----------------------------------------------------------------------
  518. ;    BYTE GETS NEXT BYTE IN BUFFER
  519. ;    NEXT RECORD IS READ IF NEED BE
  520. ;    INPUTS:
  521. ;        128 CHARACTER BUFFER @ DMA
  522. ;        CHARACTER POINTER @ POINTER WHICH IS SET @ LAST POSITION
  523. ;    OUTPUTS:
  524. ;        NEW BYTE IN ACCUMULATOR
  525. ;    REGISTER STATUS:
  526. ;        [BC],[DE],[HL] REGISTERS PRESERVED
  527. ;    ERROR CONDITIONS:
  528. ;        NONE- IF POINTER EXCEEDS 128, NEW RECORD IS READ
  529. ;
  530. BYTE    PUSH    B        ;SAVE REGISTERS
  531.     PUSH    D
  532.     PUSH    H
  533. ;
  534.     LDA    POINTER            ;GET POINTER VALUE
  535.     CPI    128D            ;IS POINTER=128?
  536.     CZ    READ            ;GET RECORD IF LAST ONE WAS #128
  537.     LDA    POINTER            ;GET NEW POINTER VALUE
  538.     INR    A            ;INCREMENT POINTER VALUE
  539.     STA    POINTER            ;STORE NEW POINTER VALUE
  540.     MOV    C,A            ;SAVE POINTER VALUE IN C
  541.     MVI    B,0            ;MAKE BC=C
  542.     LXI    H,DMA-1            ;LOAD HL WITH BYTE BEFORE DMA 
  543.     DAD    B            ;CALCULATE ADDR OF DESIRED BYTE
  544.     MOV    A,M            ;GET BYTE
  545. ;
  546.     POP    H        ;RESTORE REGISTERS
  547.     POP    D
  548.     POP    B
  549.     RET                ;DONE-- BYTE IS IN ACCUM.
  550. ;-----------------------------------------------------------------------
  551. ;
  552. ;    PRINTED CHARACTER OUTPUT
  553. ;
  554. ;    INPUTS:
  555. ;        CHARACTER IN REGISTER [A]
  556. ;
  557. ;    OUTPUTS:
  558. ;        GRAPHIC BUFFER IS FLUSHED
  559. ;        CHARACTER IS PUT OUT TO PRINTER
  560. ;        ADDRESS IN [HL] IS INCREMENTED BY (CWIDTH - 1)
  561. ;        DOT COUNTER INCREMENTED BY (CWIDTH - 1)
  562. ;        THE ABOVE ARE TO ACCOUNT FOR THE SIZE OF A CHARACTER
  563. ;        AS OPPOSED TO A SINGLE DOT
  564. ;    REGISTER STATUS:
  565. ;        [A,PSW],[BC] PRESERVED
  566. ;        [DE] DECREMENTED BY (CWIDTH -1)
  567. ;        [HL] INCREMENTED BY (CWIDTH -1)
  568. ;    ERROR CONDITIONS:
  569. ;        NONE
  570. ;
  571. CHAROUT: PUSH    PSW            ;SAVE REGISTERS
  572.     PUSH    B
  573.     PUSH    D
  574.     PUSH    H
  575. ;
  576.     XRI    10000000B        ;CLEAR HIGH BIT OF CHARACTER
  577.     CALL    GBUFOUT            ;FLUSH GRAPHIC BUFFER
  578.     MVI    C,05H            ;SELECT LIST OUTPUT
  579.     MOV    E,A            ;PASS CHARACTER
  580.     CALL    PDOS            ;SEND CHARACTER TO PRINTER
  581. ;
  582.     POP    H            ;RECALL REGISTERS
  583.     POP    D
  584.     MVI    A,CWIDTH-1
  585. CHARO1:    INX    H            ;INCREMENT ADDRESS
  586.     DCX    D            ;DECREMENT DOT COUNTER
  587.     SUI    1            ;DECREMENT LOOP COUNTER
  588.     JNZ    CHARO1
  589. ;
  590.     POP    B
  591.     POP    PSW
  592.     RET
  593. ;
  594. ;-----------------------------------------------------------------------
  595. ;
  596. ;    CLEAR MEMORY SUBROUTINE
  597. ;
  598. ;    INPUTS:
  599. ;        BITMAP OF SIZE MAPSIZE LOCATED AT ORIGIN
  600. ;        MAP COLOR STORED IN COLOR
  601. ;        (POS = PATTERNED, 0 = WHITE, - = COMPLEMENTARY)
  602. ;    OUTPUTS:
  603. ;        ENTIRE MAP AREA SET TO DESIRED COLOR OR PATTERN
  604. ;    REGISTERS:
  605. ;        ALL REGISTER VALUES DESTROYED
  606. ;    ERROR CONDITIONS:
  607. ;        NONE
  608. ;
  609. CLRMAP:    LDA    COLOR            ;GET COLOR
  610.     ORA    A            ;SET FLAGE ACCORDING TO COLOR
  611.     JNZ    CLRNZ            ;IS COLOR NON-WHITE?
  612.     LXI    D,MAPSIZE        ;PUT MAPSIZE IN [DE] AS COUNTER
  613.     LXI    H,ORIGIN        ;PUT START OF MAP IN [HL]
  614.     MVI    C,00H            ;C CONTAINS IMAGE OF WHITE BYTE
  615. CLRLP1:    MOV    M,C            ;TOP OF LOOP, STORE BYTE
  616.     INX    H            ;INCREMENT ADDRESS IN MAP
  617.     DCX    D            ;DECREMENT LOOP COUNTER
  618.     MOV    A,D            ;MOVE HIGH BYTE OF COUNT. TO [A]
  619.     ORA    E            ;CHECK FOR 0 COUNTER
  620.     JNZ    CLRLP1            ;LOOP UNTIL DONE
  621.     RET                ;FINISHED WITH WHITE ERASE
  622. ;
  623. CLRNZ:    PUSH    PSW        ;SAVE FLAG VALUES
  624. ;    NOW FORM 8 BYTE COLOR PATTERN
  625.     LXI    H,PATRN+7    ;POINT TO LAST IN PATTERN SEQUENCE
  626.     MVI    C,07H        ;INITIALIZE X COUNTER
  627. CLRLP2:    MVI    D,80H        ;SET UP Y BIT SELECT
  628.     MVI    E,07H        ;INITIALIZE Y COUNTER
  629.     MVI    B,00H        ;INITIALIZE PATTERN
  630. CLRLP3:    CALL    CLRMSK        ;FORM COLOR MASK BASED ON X,Y
  631.     LDA    CMASK        ;GET MASK
  632.     ANA    D        ;SELECT ONE BIT
  633.     ORA    B        ;ADD BIT TO PATTERN
  634.     MOV    B,A        ;SAVE NEW PATTERN
  635.     MOV    A,D        ;MODIFY BIT SELECT MASK
  636.     RRC            ;MOVE SELECT BIT DOWN ONE NOTCH
  637.     MOV    D,A        ;SAVE NEW BIT SELECT
  638.     DCR    E        ;DECREMENT Y COUNTER
  639.     JP    CLRLP3        ;JUMP BACK IF NOT NEGATIVE (NEED 0 PASS)
  640.     POP    PSW        ;RETRIEVE COLOR CODE FLAG SETTINGS
  641.     PUSH    PSW        ;RE-SAVE FLAGS SETTINGS
  642.     JP    CLRL31        ;POSITIVE FLAG MEANS PATTERN IS OK
  643.     MOV    A,B        ;GET PATTERN
  644.     CMA            ;COMPLEMENT PATTERN FOR NEGATIVE COLORS
  645.     MOV    B,A        ;STORE PATTERN BYTE
  646. CLRL31:    MOV    M,B        ;SAVE PATTERN FOR THIS X LOCATION
  647.     DCX    H        ;MOVE MEMORY POINTER OVER
  648.     DCR    C        ;DECREMENT X COORDINATE/COUNTER
  649.     JP    CLRLP2        ;ONLY DONE WHEN NEGATIVE (NEED 0 PASS)
  650. ;
  651. ;    SET UP FOR CLEARING MEMORY
  652. ;    ROTATE ARRAY OF PATTENRX DOWN TO MATCH
  653. ;
  654.     LXI    B,(MAXY+1) MOD 8+1;COUNTER FOR ROTATIONS DUE TO MISMATCH
  655. CLRLP4:    CALL    ROTPAT        ;ROTATE PATTERN ARRAY 1 POSITION
  656.     DCR    C        ;DECREMENT COUNTER
  657.     JNZ    CLRLP4        ;LOOP BACK IF NOT DONE
  658. ;
  659.     LXI    H,ORIGIN    ;SET MAP POINTER TO START OF MAP
  660.     LXI    B,(MAXY+1)/7    ;INITIALIZE LINE COUNTER
  661. CLRLP5:    LXI    D,(MAXX+1)/8    ;INITALIZE DOT COUNTER
  662. CLRL51:    LDA    PATRN        ;GET FIRST BYTE
  663.     ANI    7FH        ;CLEAR HI BIT
  664.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  665.     INX    H        ;MOVE MEMORY POINTER
  666.     LDA    PATRN+1        ;GET SECOND BYTE
  667.     ANI    7FH        ;CLEAR HI BIT
  668.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  669.     INX    H        ;MOVE MEMORY POINTER
  670.     LDA    PATRN+2
  671.     ANI    7FH        ;CLEAR HI BIT
  672.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  673.     INX    H        ;MOVE MEMORY POINTER
  674.     LDA    PATRN+3
  675.     ANI    7FH        ;CLEAR HI BIT
  676.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  677.     INX    H        ;MOVE MEMORY POINTER
  678.     LDA    PATRN+4
  679.     ANI    7FH        ;CLEAR HI BIT
  680.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  681.     INX    H        ;MOVE MEMORY POINTER
  682.     LDA    PATRN+5
  683.     ANI    7FH        ;CLEAR HI BIT
  684.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  685.     INX    H        ;MOVE MEMORY POINTER
  686.     LDA    PATRN+6
  687.     ANI    7FH        ;CLEAR HI BIT
  688.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  689.     INX    H        ;MOVE MEMORY POINTER
  690.     LDA    PATRN+7
  691.     ANI    7FH        ;CLEAR HI BIT
  692.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  693.     INX    H        ;MOVE MEMORY POINTER
  694.     DCX    D        ;DECREMENT X COUNTER
  695.     MOV    A,E
  696.     ORA    D        ;IS COUNTER ZERO?
  697.     JNZ    CLRL51        ;LOOP BACK UNTIL DONE
  698. ;
  699.     LXI    D,(MAXX+1)MOD 8    ;SET COUNTER FOR REST OF LINE
  700.     MOV    A,D        ;CHECK TO SEE IF LINESIZE ID MULT OF 8
  701.     ORA    E        ;WAS MOD 8 =0?
  702.     JZ    CLRLP6        ;JUMP TO BOTTOM OF LOOP IF FINISHED
  703.     LDA    PATRN        ;APPLY PATTERN TO REMANING 1-7 BYTES
  704.     ANI    7FH        ;CLEAR HI BIT
  705.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  706.     INX    H        ;MOVE MEMORY POINTER
  707.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  708.     MOV    A,E
  709.     ORA    D        ;IS COUNTER = 0?
  710.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  711.     LDA    PATRN+1        ;CONTINUE WITH NEXT PATTERN BYTE
  712.     ANI    7FH        ;CLEAR HI BIT
  713.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  714.     INX    H        ;MOVE MEMORY POINTER
  715.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  716.     MOV    A,E
  717.     ORA    D        ;IS COUNTER = 0?
  718.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  719.     LDA    PATRN+2        ;CONTINUE WITH NEXT PATTERN BYTE
  720.     ANI    7FH        ;CLEAR HI BIT
  721.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  722.     INX    H        ;MOVE MEMORY POINTER
  723.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  724.     MOV    A,E
  725.     ORA    D        ;IS COUNTER = 0?
  726.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  727.     LDA    PATRN+3        ;CONTINUE WITH NEXT PATTERN BYTE
  728.     ANI    7FH        ;CLEAR HI BIT
  729.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  730.     INX    H        ;MOVE MEMORY POINTER
  731.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  732.     MOV    A,E
  733.     ORA    D        ;IS COUNTER = 0?
  734.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  735.     LDA    PATRN+4        ;CONTINUE WITH NEXT PATTERN BYTE
  736.     ANI    7FH        ;CLEAR HI BIT
  737.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  738.     INX    H        ;MOVE MEMORY POINTER
  739.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  740.     MOV    A,E
  741.     ORA    D        ;IS COUNTER = 0?
  742.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  743.     LDA    PATRN+5        ;CONTINUE WITH NEXT PATTERN BYTE
  744.     ANI    7FH        ;CLEAR HI BIT
  745.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  746.     INX    H        ;MOVE MEMORY POINTER
  747.     DCX    D        ;DECREMENT LINE LENGTH COUNTER
  748.     MOV    A,E
  749.     ORA    D        ;IS COUNTER = 0?
  750.     JZ    CLRLP6        ;IF FINISHED, SKIP TO BOTTOM OF OUTER LP
  751.     LDA    PATRN+6        ;CONTINUE WITH NEXT PATTERN BYTE
  752.     ANI    7FH        ;CLEAR HI BIT
  753.     MOV    M,A        ;STORE PATTERN IN MEMORY MAP
  754.     INX    H        ;MOVE MEMORY POINTER
  755. ;
  756. CLRLP6:    CALL    ROTPAT        ;ROTATE PATTERN DOWN TO MATCH CELLS
  757.     DCX    B        ;BOTTOM OF OUTER LOOP. DEC LINE COUNTER
  758.     MOV    A,C
  759.     ORA    B        ;IS COUNTER = 0?
  760.     JNZ    CLRLP5        ;LOOP BACK UP FOR ANOTHER IF REQ'D
  761. ;
  762.     POP    PSW        ;CLEAN UP STACK
  763.     RET
  764. ;
  765. ;-----------------------------------------------------------------------
  766. ;
  767. ;    COLOR MASK
  768. ;
  769. ;    THIS SUBROUTINE FORMS THE COLOR MASK USED IN PLOTTING POINTS
  770. ;
  771. ;    METHOD:
  772. ;        THE PLOT IS DIVIDED UP INTO 8 X 8 RASTER CELLS.
  773. ;        FOR COLOR VALUES BETWEEN 1 AND 63, THE CELL IS COMPOSED
  774. ;        OF AN X PATTERN AND A Y PATTERN WHICH ARE XOR'ED WITH
  775. ;        EACH OTHER TO FORM A "PLAID" PATTERN
  776. ;        FOR COLOR VALUES 64 AND ABOVE, ORDERED DITHERING IS USED
  777. ;        ORDERED DITHERING IS A TECHNIQUE IN WHICH THE DOTS IN 
  778. ;        THE CELL ARE ADDED IN IN A PRE-ARRANGED POSITION BASED
  779. ;        UPON THE "INTENSITIY" OF THE CELL.  THE INTERSECTION OF
  780. ;        THE POINT AND THE PATTERN (STORED IN THE ARRAY "DITHARR"
  781. ;        DETERMINES WHETHER OR NOT THE POINT IS PLOTTED
  782. ;
  783. ;        FOR BOTH METHODS, A COLOR MASK IS CREATED, WHICH IS 
  784. ;        ALL 1'S IF THE POINT IN THE PATTERN PLANE IS ON, OR 
  785. ;        ALL 0'S IF THE POINT IN THE PATTERN PLANE IS OFF.
  786. ;    INPUTS:
  787. ;        X COORDINATE IN BC
  788. ;        Y COORDINATE IN DE
  789. ;    OUTPUTS:
  790. ;        COLOR MASK STORED IN CMASK
  791. ;    REGISTER STATUS:
  792. ;        ALL REGISTERS PRESERVED
  793. ;    ERROR CONDITIONS:
  794. ;        NONE
  795. ;
  796. CLRMSK    PUSH    PSW        ;SAVE REGISTERS
  797.     PUSH    B
  798.     PUSH    D
  799.     PUSH    H
  800. ;
  801.     MOV    A,C        ;FORM X CELL COORDINATE
  802.     ANI    00000111B
  803.     MOV    B,A
  804. ;
  805.     MOV    A,E        ;FORM Y CELL COORDINATE
  806.     ANI    00000111B
  807.     MOV    C,A
  808. ;
  809.     LDA    COLOR        ;GET COLOR CODE
  810.     ORA    A        ;SET FLAGS BASED ON BASIC CODE
  811.     JZ    WHTMSK        ;ZERO COLOR => WHITE MASK
  812.     JP    POSCLR        ;COLOR CODE IS POSITIVE
  813.     CMA            ;COMPLEMENT COLOR
  814.     ADI    01H        ;COLOR CODE IS NOW POSITIVE
  815. POSCLR    CPI    64D        ;IS COLOR CODE < 64
  816.     JNC    DITHER        ;CODE >=64 --> DITHERED
  817.     CPI    49D        ;IS COLOR CODE < 49
  818.     JNC    SPECIAL        ;CODE FROM 49 TO 63 --> CIFPAT'S ELSE PLAID
  819. ;
  820.     PUSH    PSW        ;SAVE COLOR CODE
  821.     ANI    07H        ;SELECT LOWER 3 BITS OF COLOR CODE
  822.     LXI    H,PLAIDS    ;GET BASE ADDRESS OF BASIC PATTERN
  823.     ADD    L        ;ADD X CODE TO BASE ADDR TO FIND PATTERN
  824.     MOV    L,A
  825.     MOV    A,H
  826.     ACI    00H        ;ADD CARRY TO HIGH BYTE OF ADDRESS
  827.     MOV    H,A
  828.     MOV    A,M        ;GET X PATTERN FOR CELL
  829.     INR    B        ;INCREMENT X COORDINATE TO BE COUNTER
  830. XCELLP    RAR            ;ROTATE PATTERN BIT INTO CARRY
  831.     DCR    B        ;DECREMENT COUNTER
  832.     JNZ    XCELLP        ;LOOP BACK IF NOT DONE
  833.     MVI    A,0FFH        ;CARRY --> PATTERN BIT SAYS PLOT POINT
  834.     JC    SAVXMSK        
  835.     MVI    A,00H
  836. SAVXMSK    MOV    B,A        ;REPLACE X CELL COORD WITH X COLOR MASK
  837. ;
  838.     POP    PSW        ;RETRIEVE COLOR CODE
  839.     ANI    38H        ;SELECT 2ND 3 BITS FOR Y CODE
  840.     RRC            ;ROTATE BITS TO LOW ORDER POSITION
  841.     RRC
  842.     RRC
  843.     LXI    H,PLAIDS    ;GET BASE ADDRESS OF BASIC PATTERN
  844.     ADD    L        ;ADD X CODE TO BASE ADDR TO FIND PATTERN
  845.     MOV    L,A
  846.     MOV    A,H
  847.     ACI    00H        ;ADD CARRY TO HIGH BYTE OF ADDRESS
  848.     MOV    H,A
  849.     MOV    A,M        ;GET Y PATTERN FOR CELL
  850.     INR    C        ;INCREMENT Y COORDINATE TO BE COUNTER
  851. YCELLP    RAR            ;ROTATE PATTERN BIT INTO CARRY
  852.     DCR    C        ;DECREMENT COUNTER
  853.     JNZ    YCELLP        ;LOOP BACK IF NOT DONE
  854.     MVI    A,0FFH        ;DOT WILL BE PLOTTED IF CARRY SET
  855.     JC    SAVYMSK        
  856.     MVI    A,00H
  857. SAVYMSK    XRA    B        ;FINAL COLOR MASK-- X PATRN XOR Y PATRN
  858.     STA    CMASK        ;SAVE COLOR MASK
  859. ;
  860.     POP    H        ;RESTORE REGISTERS
  861.     POP    D
  862.     POP    B
  863.     POP    PSW
  864.     RET            ;FINISHED   -END OF PLAID BRANCH
  865. ;
  866. DITHER    PUSH    PSW        ;SAVE COLOR CODE FOR FUTURE USE
  867.     MOV    A,C        ;MULTIPLY Y CELL COORDINATE BY 8
  868.     RLC
  869.     RLC
  870.     RLC
  871.     ADD    B        ;OFFSET INTO DITHER TABLE = Y*8 + X
  872.     LXI    H,DITHARR    ;GET BASE ADDRESS OF TABLE
  873.     ADD    L        ;ADD OFFSET TO BASE ADDRESS
  874.     MOV    L,A
  875.     MOV    A,H
  876.     ACI    00H        ;ADD CARRY TO HIGH BYTE
  877.     MOV    H,A
  878.     MOV    A,M        ;GET DITHER TABLE VALUE
  879.     POP    D        ;RETRIEVE COLOR CODE (FORMERLY IN [A])
  880.     CMP    D        ;IS DITHER VALUE > COLOR CODE?
  881.     MVI    A,0FFH        ;CARRY--> PLOT POINT
  882.     JC    SAVMSK
  883.     MVI    A,00H        ;CARRY NOT SET--> DON'T PLOT POINT
  884. SAVMSK    STA    CMASK        ;STORE MASK FOR FUTURE USE
  885. ;
  886.     POP    H
  887.     POP    D
  888.     POP    B
  889.     POP    PSW        ;REGISTERS RESTORED, STACK CLEANED UP
  890.     RET
  891. ;
  892. ;
  893. SPECIAL:SUI    49D        ;CODE IS NOW RELATIVE TO 49
  894.     RLC            ;CODE * 8
  895.     RLC
  896.     RLC
  897.     ADD    B        ;ADD X COORD TO FORM OFFSET INTO ARRAY
  898.     LXI    H,CIFPAT    ;GET FWA OF PATTERN ARRAY
  899.     ADD    L        ;ADD OFFSET TO FWA
  900.     MOV    L,A
  901.     MOV    A,H
  902.     ACI    00H        ;ADD CARRY TO HI BYTE
  903.     MOV    H,A        ;ADDITION COMPLETE
  904.     MOV    A,M        ;GET PATTERN BYTE FOR THIS X COORD.
  905.     INR    C        ;INCREMENT Y COORD TO FORM COUNTER 
  906. SPCLP:    RAR            ;ROTATE PATTERN BIT INTO CARRY
  907.     DCR    C        ;DECREMENT COUNTER
  908.     JNZ    SPCLP        ;LOOP BACK UNTIL DONE
  909.     MVI    A,0FFH        ;DOT WILL BE PLOTTED IF CARRY SET
  910.     JC    SAVMSK
  911.     MVI    A,00H        ;CARRY NOT SET- DON'T PLOT POINT
  912.     JMP    SAVMSK
  913. ;
  914. ;
  915. WHTMSK    MVI    A,0FFH        ;FOR WHITE, ALWAYS MODIFY DOT
  916.     JMP    SAVMSK        ;SAVE MASK AND RETURN
  917. ;
  918. ;-----------------------------------------------------------------------
  919. ;
  920. ;    DEFINE COLOR SUBROUTINE
  921. ;
  922. ;    INPUTS:
  923. ;        BUFFER @ DMA
  924. ;    OUTPUTS:
  925. ;        COLOR VALUE SAVED FOR FUTURE REFERENCE
  926. ;    REGISTER STATUS:
  927. ;        ALL REGISTER VALUES DESTROYED
  928. ;    ERROR CONDTIONS:
  929. ;        NONE
  930. ;
  931. COLOUR:    CALL    BYTE        ;GET COLOR VALUE
  932.     STA    COLOR        ;SAVE IT
  933.     RET
  934. ;
  935. ;-----------------------------------------------------------------------
  936. ;
  937. ;    THIS SUBROUTINE COMPUTES THE NEXT POINT IN A LINE SEGMENT
  938. ;    MUST BE USED WITH SEGINIT TO INITIALIZE ALL VARIABLES FIRST.
  939. ;
  940. ;    INPUTS:
  941. ;        NI    COUNTER USED BY CALLING SUB. TO KNOW WHEN DONE.
  942. ;        XPOS,YPOS    PRESENT POSITION
  943. ;        DX,DY    SIZE OF LINE SEGMENT ALONG X,Y AXIS
  944. ;        EPSLNX,EPSLNY,SX,SY,DELTA3    LOCAL VARIABLES
  945. ;    REGISTER STATUS:
  946. ;        ALL REGISTER VALUES DESTROYED.
  947. ;    ERROR CONDITIONS:
  948. ;        NONE PECULIAR TO THIS ROUTINE
  949. ;
  950. COMPSEG    LHLD    NI        ;GET COUNTER VALUE
  951.     INX    H        ;NI<DX- CONTINUE (FIRST INCR. NI)
  952.     SHLD    NI        ;STORE NEW NI VALUE
  953.     LHLD    XPOS        ;GET XPOS & PUT IN (BC)
  954.     MOV    B,H        ;HI BYTE TO (B)
  955.     MOV    C,L        ;LOW BYTE TO (C)
  956.     LHLD    YPOS        ;FETCH YPOS
  957.     XCHG            ;PUT YPOS IN (DE)
  958.     LHLD    EPSLNX        ;FETCH EPSILON X
  959.     DAD    B        ;ADD EPSILON X TO X POSITION
  960.     SHLD    XPOS        ;STORE NEW VALUE
  961.     LHLD    EPSLNY        ;FETCH EPSILON Y
  962.     DAD    D        ;ADD EPSILON Y TO Y POSITION
  963.     SHLD    YPOS        ;STORE NEW VALUE OF Y POSITION
  964.     LHLD    DELTAY        ;FETCH DELTA Y
  965.     XCHG            ;PUT DELTAY IN (DE)
  966.     LHLD    DELTA3        ;FETCH DELTA 3
  967.     DAD    D        ;ADD DELTA Y TO DELTA 3
  968.     SHLD    DELTA3        ;STORE NEW VALUE OF DELTA3
  969.     XCHG            ;PUT NEW VALUE OF DELTA 3 IN (DE)
  970.     LHLD    DELTAX        ;FETCH DELTA X
  971.     MOV    A,H        ;CONTINUE IF DELTA X < DELTA 3 
  972.     CMP    D        ;OTHERWISE PLOT POINT AND LOOP
  973.     JC    CONT2        ;HI BYTES FIRST- DELTA3 DEFINITELY >
  974.     JNZ    DOPT        ;DX > D3- PLOT POINT
  975.     MOV    A,L        ;HIGH BYTES =: LOOK @ LOW BYTES
  976.     CMP    E        ;NOW LOW BYTES
  977.     JNC    DOPT        ;D3<=DX: PLOT POINT
  978. CONT2    MOV    A,E        ;COMPUTE D3=D3-DX 
  979.     SUB    L        ;SUBTRACT LOW BYTE FIRST
  980.     MOV    L,A        ;PUT LOW BYTE IN POSITION FOR STORE
  981.     MOV    A,D        ;NOW HIGH BYTE OF D3
  982.     SBB    H        ;SUBTRACT HIGH BYTE
  983.     MOV    H,A        ;PUT HI BYTE IN POSITION FOR STORE
  984.     SHLD    DELTA3        ;STORE RESULT
  985.     LHLD    SX        ;COMPUTE XPOS=XPOS+SX
  986.     XCHG            ;PUT SX IN (DE)
  987.     LHLD    XPOS        ;FETCH X POSITION
  988.     DAD    D        ;ADD SX TO XPOS
  989.     SHLD    XPOS        ;STORE RESULT
  990.     LHLD    SY        ;COMPUTE YPOS=YPOS+SY
  991.     XCHG            ;PUT SY IN (DE)
  992.     LHLD    YPOS        ;FETCH Y POSITION
  993.     DAD    D        ;ADD SY
  994.     SHLD    YPOS        ;STORE NEW Y POSITION
  995. DOPT    RET            ;RETURN SO CALLING SUB CAN USE POSITION.
  996. ;
  997. ;-----------------------------------------------------------------------
  998. ;        CARRIAGE RETURN ROUTINE
  999. ;
  1000. ;    INPUTS:
  1001. ;        NONE
  1002. ;
  1003. ;    OUTPUTS:
  1004. ;        PRINTER CARRIAGE IS RETURNED AND PAPER ADVANCED
  1005. ;
  1006. ;    REGISTER STATUS:
  1007. ;        ALL VALUES PRESERVED
  1008. ;
  1009. ;    ERROR CONDITIONS:
  1010. ;        NONE
  1011. ;
  1012. CRLF    PUSH    PSW        ;SAVE ALL REGISTERS
  1013.     PUSH    B
  1014.     PUSH    D
  1015.     PUSH    H
  1016. ;
  1017.     MVI    C,05H        ;SELECT LIST OUTPUT
  1018.     MVI    E,0DH        ;PASS CARRIAGE RETURN CHARACTER
  1019.     CALL    PDOS
  1020.     MVI    C,05H        ;SELECT LIST OUTPUT
  1021.     MVI    E,0AH        ;PASS LINE FEED CHARACTER
  1022.     CALL    PDOS        ;SEND IT OUT
  1023.     POP    H        ;RESTORE REGISTERS
  1024.     POP    D
  1025.     POP    B
  1026.     POP    PSW
  1027.     RET
  1028. ;
  1029. ;-----------------------------------------------------------------------
  1030. ;    THIS SUBROUTINE FORMS THE MASK FOR THE PLOTTING OF A POINT
  1031. ;    DIGIT= YCOORD MOD 7
  1032. ;    INPUTS:
  1033. ;        XCOORD IN BC
  1034. ;        YCOORD IN DE
  1035. ;        XYADDR IN HL
  1036. ;    OUTPUTS:
  1037. ;        CONTENTS OF XYADDR IN B
  1038. ;        MASK (1 BIT ON) IN C
  1039. ;        YCOORD IN DE
  1040. ;        XYADDR IN HL
  1041. ;    REGISTER STATUS:
  1042. ;        SEE OUTPUTS
  1043. ;    ERROR CONDITIONS:
  1044. ;        OVERFLOW IN DIVIDE CALLS WOOPS
  1045. ;
  1046. DIGIT    PUSH    H            ;SAVE XYADDRESS
  1047.     PUSH    D            ;SAVE YCOORD
  1048.     CALL    CLRMSK        ;PREPARE COLOR MASK FOR FUTURE USE
  1049.     XCHG                ;PUT YCOORD IN HL
  1050.     SHLD    DIVDND            ;CALCULATE YCOORD MOD 7
  1051.     MVI    A,07H
  1052.     STA    DIVSOR
  1053.     CALL    DIVIDE            ;MOD IS DIVIDE W/O QUOTIENT
  1054.     LDA    RMANDR            ;GET RESULT
  1055.     ORA    A            ;SET FLAGS
  1056.     CM    WOOPS            ;RMANDR= -1 ON OVERFLOW
  1057.     MOV    B,A            ;MOVE # OF DIGIT TO B
  1058.     MVI    A,00H
  1059.     INR    B            ;INCREMENT B TO INIT FOR 1ST DEC
  1060.     IF    MSBTOP
  1061.     STC                ;CLEAR ACCUM, PUT 1 IN CARRY
  1062. ROTMASK    RAL                ;MOVE MASK BIT 1 LEFT
  1063.     ENDIF            ;(MSBTOP)
  1064. ;
  1065.     IF    NOT MSBTOP
  1066.     MVI    A,10000000B    ;SET HIGH BIT AND ROTATE IT RIGHT
  1067. ROTMASK RRC            ;MOVE MASK BIT 1 RIGHT
  1068.     ENDIF            ;(NOT MSBTOP)
  1069. ;
  1070.     DCR    B            ;DECREMENT # OF DIGIT
  1071.     JNZ    ROTMASK            ;LOOP BACK
  1072.     MOV    C,A        ;STORE MASK TEMPORARILY
  1073.     LDA    CMASK        ;GET COLOR MASK
  1074.     ANA    C        ;AND BIT MASK WITH COLOR MASK- BOTH RQD
  1075.     MOV    C,A            ;PUT MASK IN C
  1076.     POP    D            ;BRING BACK YCOORD
  1077.     POP    H            ;BRING BACK (XYADDR)
  1078.     MOV    B,M            ;GET BYTE @ (XYADDR)
  1079.     RET
  1080. ;
  1081. ;-----------------------------------------------------------------------
  1082. ;    DIVISION SUBROUTINE
  1083. ;    INPUTS:
  1084. ;        DIVDND  TWO BYTE POSITIVE NUMBER
  1085. ;        DIVSOR    ONE BYTE POSITIVE NUMBER
  1086. ;    OUTPUTS:
  1087. ;        QOTENT    ONE BYTE POSITIVE QUOTIENT
  1088. ;        RMANDR    ONE BYTE POSITIVE REMAINDER OR FLAG
  1089. ;    REGISTER STATUS:
  1090. ;        BC,DE,HL,PSW REGISTERS RETURNED TO ORIGINAL VALUES
  1091. ;    ERROR CONDITIONS:
  1092. ;        RMANDR=-1 IF OVERFLOW OCCURS
  1093. ;
  1094. DIVIDE    PUSH    PSW            ;SAVE REGISTERS
  1095.     PUSH    B
  1096.     PUSH    D
  1097.     PUSH    H
  1098.     LHLD    DIVDND        ;FETCH DIVIDEND
  1099.     XCHG                ;PUT DIVIDEND INTO THE DE PAIR
  1100.     LDA    DIVSOR            ;FETCH DIVSOR
  1101.     MOV    C,A            ;SAVE IN REGISTER C
  1102.     MVI    B,8            ;LOOP COUNTER IN REGISTER B
  1103. DIVLOOP    MOV    A,E            ;SHIFT LOW ORDER BYTE TO LEFT
  1104.     ANA    A            ;CLEAR CARRY
  1105.     RAL                ;SHIFT
  1106.     MOV    E,A            ;REPLACE VALUE
  1107.     MOV    A,D            ;FETCH HIGH ORDER BYTE
  1108.     RAL                ;ROTATE BRINGING IN HIGH BIT
  1109.     SUB    C            ;SUBTRACT DIVISOR
  1110.     JP    SETBIT            ;IF RESULT WAS POSITIVE, JUMP
  1111.     ADD    C            ;OTHERWISE ADD BACK DIVISOR
  1112.     MOV    D,A            ;REPLACE HIGH ORDER BYTE
  1113.     JMP    NEXT            ;GO TO INCREMENT PHASE
  1114. SETBIT    MOV    D,A            ;REPLACE HIGH ORDER BYTE
  1115.     MOV    A,E            ;FETCH LOW ORDER BYTE
  1116.     ORI    1            ;SET LOW ORDER BIT
  1117.     MOV    E,A            ;REPLACE LOW ORDER BYTE
  1118. NEXT    DCR    B            ;DECREMENT LOOP COUNTER
  1119.     JNZ    DIVLOOP            ;REPEAT UNTIL DONE
  1120.     MOV    A,E            ;QUOTIENT
  1121.     ANA    A            ;TEST SIGN OF RESULT
  1122.     JP    OK            ;IF POSITIVE RESULT IS ACCURATE
  1123.     MVI    A,0FFH            ;SET OVERFLOW VALUE
  1124.     STA    RMANDR
  1125.     JMP    DONE
  1126. OK    STA    QOTENT            ;SAVE QUOTIENT
  1127.     MOV    A,D            ;REMAINDER
  1128.     STA    RMANDR            ;SAVE REMAINDER
  1129. DONE    POP    H
  1130.     POP    D
  1131.     POP    B
  1132.     POP    PSW
  1133.     RET
  1134. ;
  1135. ;-----------------------------------------------------------------------
  1136. ;
  1137. ;    THIS SUBROUTINE PLOTS THE VERTICAL LINE USED TO FILL IN AREAS
  1138. ;
  1139. ;    INPUTS:
  1140. ;        XPOS,YPOS    CURRENT POSITION ON SEGMENT
  1141. ;        YFILL        HORIZONTAL LEVEL TO FILL TO
  1142. ;    OUTPUTS:
  1143. ;        VERTICAL LINE FROM (XPOS,YPOS) TO (XPOS,YFILL)
  1144. ;    REGISTER STATUS:
  1145. ;        ALL REGISTER VALUES DESTROYED
  1146. ;    ERROR CONDITIONS:
  1147. ;        NONE PECULIAR TO THIS ROUTINE.
  1148. ;        NOTE: ALL COORDINATE VALUES ASSUMED TO BE POSITIVE
  1149. ;
  1150. FILINE    CALL    STAT        ;UPDATE STATUS MESSAGE
  1151.     LHLD    XPOS        ;GET STARTING COORDINATES OF LINE
  1152.     SHLD    XDOT        ;XPOS WILL BE X COORD OF ALL DOTS
  1153.     LHLD    YPOS        ;GET Y COORDINATE
  1154.     PUSH    H        ;SAVE Y POSITION- PLOTDOT WILL RESET IT
  1155.     XCHG            ;PUT Y COORDINATE IN [DE]
  1156.     LHLD    YFILL        ;GET Y FILL VALUE
  1157. ;
  1158.     MOV    A,D        ;COMPARE Y COORDINATES FOR TOP AND BOT.
  1159.     CMP    H        ;COMPARE HIGH BYTES
  1160.     JC    YFXCH        ;CARRY INDICATES THAT YFILL IS > YPOS
  1161.     JNZ    CONTFIL        ;YFILL DEFINITELY LESS THAN YPOS
  1162.     MOV    A,E        ;HIGH BYTES EQUAL- COMPARE LOW BYTES
  1163.     CMP    L        ;IS YFILL ABOVE OR BELOW YPOS?
  1164.     JNC    CONTFIL        ;YFILL IS NOT ABOVE YPOS- CONTINUE
  1165. YFXCH    XCHG            ;SWITCH YPOS AND YFILL- LARGER VAL IN DE
  1166. CONTFIL    SHLD    YDOT        ;PASS Y COORDINATE TO PLOTDOT
  1167.     PUSH    D        ;SAVE REGISTERS
  1168.     PUSH    H
  1169.     CALL    PLOTDOT        ;PLOT POINT
  1170.     POP    H        ;RETRIEVE REGISTERS
  1171.     POP    D
  1172.     INX    H        ;INCREMENT Y POSITION
  1173. ;
  1174.     MOV    A,D        ;CHECK TO SEE IF LINE IS DONE
  1175.     CMP    H        ;COMPARE HIGH BYTES
  1176.     JC    DONEFIL        ;CARRY INDICATES THAT NEW Y IS ABOVE END
  1177.     JNZ    CONTFIL        ;NEW COORDINATE DEFINITELY BELOW END
  1178.     MOV    A,E        ;HIGH BYTES EQUAL- COMPARE LOW BYTES
  1179.     CMP    L        ;IS IT THERE YET?
  1180.     JC    DONEFIL        ;CARRY INDICATES THAT NEW Y IS ABOVE END
  1181.     JMP    CONTFIL        ;LOOP BACK AND DO NEXT POINT
  1182. DONEFIL    POP    H        ;RETRIEVE LINE Y POSITION
  1183.     SHLD    YPOS        ;RESTORE VALUE
  1184.     RET            ;ALL FINISHED!
  1185. ;
  1186. ;-----------------------------------------------------------------------
  1187. ;
  1188. ;    THIS SUBROUTINE WILL FILL AN AREA BETWEEN A LINE SEGMENT AND
  1189. ;    A HORIZONTAL LINE
  1190. ;
  1191. ;    INPUTS:
  1192. ;        BUFFER CONTAINING COORDINATE PAIRS AND Y COORDINATE OF 
  1193. ;        FILL LEVEL.  ALL FIVE ARE REAL VALUES
  1194. ;    OUTPUTS:
  1195. ;        XPOS,YPOS UPDATED TO END OF LINE SEGMENT
  1196. ;        AREA BETWEEN SEGMENT AND YFILL IS FILLED WITH CURRENT 
  1197. ;        COLOR VALUE
  1198. ;    REGISTER STATUS:
  1199. ;        ALL REGISTERS DESTROYED
  1200. ;    ERROR CONDITIONS:
  1201. ;        NONE PECULIAR TO THIS ROUTINE
  1202. ;
  1203. FILL    CALL    READXY        ;GET STARTING COORDINATES
  1204.     LHLD    X
  1205.     SHLD    XPOS        ;UPDATE X POSITION TO START OF SEGMENT
  1206.     LHLD    Y
  1207.     SHLD    YPOS        ;UPDATE Y POSITION TO START OF SEGMENT
  1208.     CALL    READXY        ;GET END COORDINATES
  1209.     CALL BYTE        ;GET FIRST BYTE OF FIXED PT. Y FILL
  1210.     PUSH    PSW        ;STORE FIRST BYTE
  1211.     CALL    BYTE        ;GET SECOND BYTE
  1212.     MOV    B,A        ;PUT HIGH BYTE IN [B]
  1213.     POP    PSW        ;GET LOW BYTE
  1214.     MOV    C,A        ;[BC] NOW CONTAINS FIXED POINT Y COORD.
  1215.     LXI    D,MAXY*2    ;PASS MAXIMUM RASTER ADDRESS
  1216.     CALL    MULT        ;MULTIPLY Y COORD BY NO. OF Y RASTERS
  1217.     XCHG            ;PUT HIGH BYTES IN [HL]
  1218.     SHLD    YFILL        ;SAVE INTEGER VALUE OF Y FILL LEVEL
  1219. ;
  1220.     CALL    SEGINIT        ;INITIALIZE VARIABLES FOR SEG. INTERP.
  1221.     CALL    FILINE        ;FILL AREA BETWEEN FIRST PT. & YFILL
  1222. STRTFIL    CALL    COMPSEG        ;COMPUTE NEXT POINT IN SEGMENT
  1223.     LHLD    DELTAX        ;TOP OF LOOP- END WHEN NI>DX
  1224.     XCHG            ;DELTAX IS NOW IN (DE)
  1225.     LHLD    NI        ;GET COUNTER
  1226.     MOV    A,D        ;COMPARE COUNTER W/DX HI BYTE FIRST
  1227.     CMP    H        ;COMPARE HI BYTES
  1228.     RC            ;CARRY INDICATES NI HI BYTE>DX HI BYTE
  1229.     JNZ    CHKFIL        ;CONTINUE IF NI DEFINITELY < DX
  1230.     MOV    A,E        ;HIGH BYTES EQUAL- LOOK @ LOW BYTE
  1231.     CMP    L        ;NOW LOW BYTE
  1232.     RC            ;NI LOW BYTE>DX LOW BYTE- DONE W/SEGMENT
  1233. CHKFIL    LHLD    XDOT        ;COMPARE XDOT AND XPOS
  1234.     XCHG
  1235.     LHLD    XPOS        ;XPOS=XDOT=> THIS WILL DUPLICATE FILL
  1236.     MOV    A,D
  1237.     CMP    H        ;ARE HIGH BYTES THE SAME?
  1238.     JNZ    LOOPFIL        ;GO ON IF HIGH BYTES ARE NOT EQUAL
  1239.     MOV    A,E        ;HIGH BYTES EQUAL- LOOK AT LOW BYTES
  1240.     CMP    L        ;ARE THE TWO EXACTLY THE SAME?
  1241.     JZ    STRTFIL        ;YES- SKIP THIS POSITION
  1242. LOOPFIL    CALL    FILINE        ;FILL AREA BETWEEN SEGMENT & YFILL
  1243.     JMP    STRTFIL        ;LOOP BACK TO TOP
  1244. ;
  1245. ;-----------------------------------------------------------------------
  1246. ;
  1247. ;    THIS SUBROUTINE WILL SEND A STRING OF CHARACTERS TO THE PRINTER
  1248. ;
  1249. ;    INPUTS:
  1250. ;        NUMBER-1 OF CHARACTERS TO SEND IN [DE]
  1251. ;        ADDRESS-1 OF FIRST CHARACTER IN [HL]
  1252. ;    OUTPUTS:
  1253. ;        0 THROUGH [DE] CHARACTERS SENT TO PRINTER
  1254. ;    REGISTER STATUS:
  1255. ;        ALL REGISTERS DESTROYED
  1256. ;    ERROR CONDITIONS:
  1257. ;        NONE DETECTED BY THIS ROUTINE
  1258. ;
  1259. GBOLOOP    NOP
  1260.     IF    OKI
  1261.     PUSH    D
  1262.     PUSH    H
  1263.     MVI    C,05H        ;SEND ETX TO START INTO GRAPHIC MODE
  1264.     MVI    E,03H
  1265.     CALL    PDOS
  1266.     POP    H
  1267.     POP    D
  1268.     ENDIF            ;(OKI)
  1269. ;
  1270. KIRKLOP    DCX    D        ;DECREMENT COUNTER
  1271.     INX    H        ;INCREMENT ADDRESS
  1272.     PUSH    D        ;SAVE COUNTER
  1273.     PUSH    H
  1274.     MOV    E,M        ;GET CHARACTER
  1275. ;
  1276.     IF    OKI        ;IF GRAPHIC BYTE IS <ETX>, A SECOND
  1277. ;<ETX> IS REQUIRED FOR THE OKI PRINTER
  1278.     MOV    A,E
  1279.     CPI    03H        ;IS BYTE <ETX>?
  1280.     JNZ    GBOLP1
  1281.     PUSH    D        ;SAVE BYTE
  1282.     MVI    C,05H        ;SELECT CP/M LIST FUNCTION
  1283.     CALL    PDOS
  1284.     MVI    E,03H        ;REPLACE <ETX> CHARACTER SENT
  1285.     POP    D        ;SAVE BYTE
  1286.     ENDIF            ;(OKI)
  1287. ;
  1288. GBOLP1    MVI    C,05        ;SELECT CP/M LIST OUTPUT FUNCTION
  1289.     CALL    PDOS        ;SEND CHARACTER OUT
  1290.     POP    H        ;RETRIEVE ADDRESS
  1291.     POP    D        ;RETRIEVE COUNTER
  1292.     MOV    A,E        ;IS COUNTER =0?
  1293.     ORA    D        ;TEST COUNTER
  1294.     JNZ    KIRKLOP        ;NOT DONE: LOOP BACK
  1295.     IF    OKI        ;SEND ETX-SO TO CANCEL GRAPHICS MODE
  1296.     PUSH    D        ;SAVE COUNTER
  1297.     PUSH    H        ;SAVE ADDRESS
  1298.     MVI    C,05H
  1299.     MVI    E,03H
  1300.     CALL    PDOS
  1301.     MVI    C,05H
  1302.     MVI    E,02H
  1303.     CALL    PDOS
  1304.     POP    H        ;RETRIEVE ADDRESS
  1305.     POP    D        ;RETRIEVE COUNTER
  1306.     ENDIF            ;(OKI)
  1307. ;
  1308.     RET
  1309. ;
  1310. ;-----------------------------------------------------------------------
  1311. ;    THIS ROUTINE SAVES A BYTE FROM BIT MAP IN GRAPHIC BUFFER
  1312. ;
  1313. ;    INPUTS:
  1314. ;        BYTE IN (B)
  1315. ;        2 BYTE COUNTER @ NGRAPH
  1316. ;
  1317. ;    OUTPUTS:
  1318. ;        NGRAPH INCREMENTED
  1319. ;        BYTE STORED IN BUFFER @ GBUFF
  1320. ;        BUFFER FLUSHED IF FULL
  1321. ;
  1322. ;    REGISTER STATUS:
  1323. ;        ALL REGISTERS PRESERVED
  1324. ;
  1325. ;    ERROR CONDITIONS:
  1326. ;        NONE
  1327. ;
  1328. GBUFIN    PUSH    PSW        ;SAVE REGISTERS
  1329.     PUSH    B
  1330.     PUSH    D
  1331.     PUSH    H
  1332. ;
  1333.     LHLD    NGRAPH        ;GET NO. OF BYTES IN BUFFER
  1334.     INX    H        ;INCREMENT NGRAPH
  1335.     SHLD    NGRAPH        ;STORE NEW VALUE
  1336.     XCHG            ;PUT NGRAPH IN [DE]
  1337. ;
  1338.     LXI    H,GBUFF-1    ;GET BUFFER BASE ADDRESS
  1339.     DAD    D        ;ADD COUNTER TO BASE ADDRESS
  1340.     MOV    M,B        ;STORE BYTE
  1341. ;
  1342. ;
  1343.     XCHG            ;PUT NGRAPH IN [HL]
  1344.     LXI    D,0-(MAXX+1)    ;PUT -MAX NO. OF BYTES IN [DE]
  1345.     DAD    D        ;[HL]=NGRAPH-(MAX NO. OF BYTES)
  1346.     MOV    A,H        ;IF [HL]=0 THEN BUFFER IS FULL
  1347.     ORA    L        ;SET FLAGS
  1348.     CZ    GBUFOUT
  1349.         ;BUFFER IS FULL- FLUSH IT TO PRINTER
  1350. ;
  1351.     POP    H        ;RESTORE REGISTERS
  1352.     POP    D
  1353.     POP    B
  1354.     POP    PSW
  1355.     RET
  1356. ;
  1357. ;-----------------------------------------------------------------------
  1358. ;        THIS SUBROUTINE FLUSHES THE GRAPHIC BUFFER
  1359. ;
  1360. ;    INPUTS:
  1361. ;        GRAPHIC BUFFER @ GBUFF
  1362. ;        NUMBER OF VALID BYTES IN BUFFER @ NGRAPH
  1363. ;        "ESC K" SEQUENCE STORED AHEAD OF NGRAPH
  1364. ;
  1365. ;    OUTPUTS:
  1366. ;        PRINTER IS PLACED IN DOT GRAPHIC MODE 
  1367. ;        GRAPHIC STRING TRANSMITTED BYTE BY BYTE TO PRINTER
  1368. ;
  1369. ;    REGISTER STATUS:
  1370. ;        ALL REGISTERS PRESERVED
  1371. ;
  1372. ;    ERROR CONDITIONS:
  1373. ;        NONE
  1374. ;
  1375. GBUFOUT    PUSH    PSW        ;SAVE REGISTERS
  1376.     PUSH    B
  1377.     PUSH    D
  1378.     PUSH    H
  1379. ;
  1380. GBOTOP    LHLD    NGRAPH        ;FETCH BUFFER COUNTER
  1381.     XCHG            ;PUT BUFFER COUNTER IN [DE]
  1382.     MOV    A,E        ;LOOK AT LOW BYTE
  1383.     ORA    D        ;IS COUNTER=0?
  1384.     JZ    GBUFRET        ;IF BUFFER IS EMPTY, DON'T O/P ANYTHING
  1385. ;
  1386. ;    SKIP TOTALLY BLANK LINES
  1387. ;
  1388.     LXI    B,MAXX+1    ;GET LENGTH OF BUFFER
  1389.     MOV    A,B        ;COMPARE HIGH BYTES FIRST
  1390.     CMP    D
  1391.     JNZ    GBO2        ;NO MATCH INDICATES SOMETHING ON THIS LINE
  1392.     MOV    A,C        ;COMPARE LOW BYTES NEXT
  1393.     CMP    E
  1394.     JNZ    GBO2        ;NO MATCH INDICATES SOMETHING ON THIS LINE
  1395. ;
  1396.     LXI    H,GBUFF        ;SET POINTER TO START OF BUFFER
  1397. GBO1    MOV    A,M        ;GET BYTE FROM BUFFER
  1398.     ORA    A        ;IS IT A BLANK STROKE?
  1399.     JNZ    GBO2        ;GO TO OUTPUT SECTION IF NOT BLANK
  1400.     INX    H        ;POINT TO NEW BYTE
  1401.     DCX    B        ;DECREMENT COUNTER
  1402.     MOV    A,B        ;CHECK FOR ZERO
  1403.     ORA    C
  1404.     JNZ    GBO1        ;REPEAT UNTIL LAST BYTE HAS BEEN CHECKED
  1405. ;
  1406.     JMP    GBUFRET        ;RETURN W/O PLOTTING SINCE ALL WERE BLANK
  1407. ;
  1408. GBO2    NOP            ;HEAD OF OUTPUT SECTION
  1409. ;
  1410.     IF    NO8BIT
  1411.     MOV    A,E        ;LOOK AT LOW BYTE OF COUNTER
  1412.     ORA    A        ;SET FLAGS- IS HIGH BIT SET?
  1413.     JP    GBO7        ;LOW BYTE HAS 7 BITS-O/P WHOLE THING.
  1414. ;
  1415. ;    THE PARALLEL INTERFACE WILL ONLY TRANSMIT 7 BITS.  THE LOW BYTE
  1416. ;    OF THE BUFFER COUNTER HAS ITS HIGH BIT SET, THEREFORE, THE 
  1417. ;    BUFFER MUST BE OUTPUT IN SMALLER CHUNKS
  1418. ;
  1419.     PUSH    D        ;SAVE NGRAPH ON STACK
  1420.     ENDIF            ;(NO8BIT)
  1421.     IF    EPSON AND NO8BIT
  1422.     LXI    D,126+4        ;COUNTER=>126 BYTES + 4 FOR ESCK,NGRAPH
  1423.     LXI    H,126D        ;SET NGRAPH TO 126
  1424.     SHLD    NGRAPH        ;PUT NEW NO. IN PRINTER SEQUENCE
  1425.     LXI    H,ESCK-1    ;START WITH ESCAPE SEQUENCE
  1426.     ENDIF            ;(EPSON AND NO8BIT)
  1427. ;
  1428.     IF    CITOH AND NO8BIT
  1429.     LXI    D,126+6        ;COUNTER=>126 BYTES + 6 FOR ESC S N3210
  1430.     LXI    H,ESCK+3    ;ADDRESS OF N1 BYTE
  1431.     LXI    B,126D        ;SET NO. OF BYTES
  1432.     MOV    M,B        ;STORE HIGH BYTE IN N1
  1433.     INX    H        ;ADDRESS OF N0
  1434.     MOV    M,C        ;STORE LOW BYTE IN N0
  1435.     LXI    H,ESCK-1    ;START WITH ESCAPE SEQUENCE
  1436.     ENDIF            ;(CITOH AND NO8BIT)
  1437. ;
  1438.     IF    NO8BIT
  1439.     CALL    GBOLOOP        ;SEND OUT FIRST 126 CHARACTERS
  1440. ;
  1441. ;    MOVE CHARACTERS IN BUFFER UP TO REPLACE THOSE SENT OUT
  1442. ;
  1443.     POP    H        ;RETRIEVE OLD VALUE OF NGRAPH
  1444.     LXI    D,0FF82H    ;[DE]=-126D
  1445.     DAD    D        ;[HL]NOW=NGRAPH-126
  1446.     SHLD    NGRAPH        ;STORE NEW VALUE
  1447.     XCHG            ;PUT NGRAPH IN [DE] TO ACT AS COUNTER
  1448.     LXI    H,GBUFF-1        ;GET BASE ADDRESS OF BUFFER
  1449.     PUSH    H        ;SAVE POINTER FOR SAVING DATA
  1450.     LXI    B,007EH        ;PUT 126D IN [BC]
  1451.     DAD    B        ;[HL] NOW POINTS TO NEW BYTES
  1452. ;
  1453. GBOMOV    INX    H        ;INCRMENT NEW DATA POINTER
  1454.     MOV    A,M        ;GET BYTE FROM BUFFER
  1455.     XTHL            ;EXCHANGE POINTERS
  1456.     INX    H        ;INCREMENT SAVE DATA POINTER
  1457.     MOV    M,A        ;MOVE BYTE UP IN BUFFER
  1458.     XTHL            ;EXCHANGE POINTERS BACK AGAIN
  1459.     DCX    D        ;DECREMENT COUNTER
  1460.     MOV    A,E        ;CHECK TO SEE IF LOOP IS DONE
  1461.     ORA    D        ;IS [DE]=0?
  1462.     JNZ    GBOMOV        ;LOOP BACK UP IF NOT DONE
  1463.     POP    H        ;RETRIEVE POINTER TO CLEAN UP STACK
  1464. ;
  1465. ;    NGRAPH HAS NOW BEEN UPDATED AND DATA IN BUFFER HAS BEEN MOVED
  1466. ;    TO REPLACE THAT WHICH HAS BEEN SENT OUT.  NOW READY TO TRY ALL
  1467. ;    OVER AGAIN WITH NEW SEGMENT OF DATA IN BUFFER.
  1468. ;
  1469.     JMP    GBOTOP
  1470.     ENDIF            ;(NO8BIT)
  1471. ;
  1472.     IF    EPSON
  1473. GBO7    INX    D
  1474.     INX    D
  1475.     INX    D
  1476.     INX    D
  1477.     LXI    H,ESCK-1    ;START WITH ESCAPE SEQUENCE
  1478.     ENDIF            ;(EPSON)
  1479. ;
  1480.     IF    CITOH
  1481. GBO7    LXI    H,ESCK+2    ;ADDRESS OF N3 BYTE FOR GRAPHICS SELECT
  1482.     MVI    A,30H        ;INITIALIZE NUMBER OF BYES TO "0000"
  1483.     MOV    M,A        ;"0"
  1484.     INX    H
  1485.     MOV    M,A        ;"00"
  1486.     INX    H
  1487.     MOV    M,A        ;"000"
  1488.     INX    H
  1489.     MOV    M,A        ;"0000"
  1490. ;
  1491.     CALL BINDEC        ;CONVERT N TO ASCII DECIMAL AND STORE
  1492. ;
  1493.     INX    D        ;INCREMENT COUNTER FOR ESC S N3-N0
  1494.     INX    D
  1495.     INX    D
  1496.     INX    D
  1497.     INX    D
  1498.     INX    D
  1499.     LXI    H,ESCK-1    ;START WITH ESCAPE SEQUENCE
  1500.     ENDIF            ;(CITOH)
  1501. ;
  1502.     IF    OKI
  1503. GBO7    LXI    H,GBUFF-1
  1504.     ENDIF            ;(OKI)
  1505. ;
  1506.     CALL    GBOLOOP        ;SEND OUT STRING OF GRAPHIC CHARACTERS
  1507. ;
  1508. GBUFRET    MVI    A,00H        ;CLEAR ACCUMULATOR
  1509.     STA    NGRAPH        ;SET NGRAPH=0
  1510.     STA    NGRAPH+1
  1511. POP    H        ;RESTORE REGISTERS
  1512.     POP    D
  1513.     POP    B
  1514.     POP    PSW
  1515.     RET
  1516. ;
  1517. ;-----------------------------------------------------------------------
  1518. ;    THIS SUBROUTINE PLOTS AN INCREMENTAL LINE SEGMENT FROM THE
  1519. ;    PRESENT POSITION
  1520. ;    INPUTS:
  1521. ;        FILE BUFFER @ DMA
  1522. ;        PRESENT POSITION @ XPOS,YPOS
  1523. ;    OUTPUTS:
  1524. ;        XPOS, YPOS UPDATED TO X,Y
  1525. ;        VISIBLE PORTION OF LINE SEGMENT DRAWN
  1526. ;    REGISTER STATUS:
  1527. ;        ALL REGISTER VALUES DESTROYED
  1528. ;    ERROR CONDITIONS:
  1529. ;        NONE PECULIAR TO THIS ROUTINE
  1530. ;
  1531. INCPLT    CALL    READXY            ;GET END POINT VALUES
  1532.     CALL    SEGINIT        ;INITIALIZE SEGMENT INTERPOLATION SUB.
  1533. ;
  1534. STRTPLT    LHLD    DELTAX        ;TOP OF LOOP- END WHEN NI>DX
  1535.     XCHG            ;DELTAX IS NOW IN (DE)
  1536.     LHLD    NI        ;GET COUNTER
  1537.     MOV    A,D        ;COMPARE COUNTER W/DX HI BYTE FIRST
  1538.     CMP    H        ;COMPARE HI BYTES
  1539.     RC            ;CARRY INDICATES NI HI BYTE>DX HI BYTE
  1540.     JNZ    CONTPLT        ;CONTINUE IF NI DEFINITELY < DX
  1541.     MOV    A,E        ;HIGH BYTES EQUAL- LOOK @ LOW BYTE
  1542.     CMP    L        ;NOW LOW BYTE
  1543.     RC            ;NI LOW BYTE>DX LOW BYTE- DONE W/SEGMENT
  1544. CONTPLT    CALL    COMPSEG        ;COMPUTE XPOS AND YPOS AT NEXT POINT
  1545.     LHLD    XPOS        ;FETCH X POSITION
  1546.     SHLD    XDOT        ;PASS IN XDOT
  1547.     LHLD    YPOS        ;FETCH Y POSITION
  1548.     SHLD    YDOT        ;PASS IN YDOT
  1549.     CALL    PLOTDOT        ;PLOT IT (FINALLY)
  1550.     JMP    STRTPLT        ;BOUNCE UP TO THE TOP OF THE LOOP
  1551. ;
  1552. ;-----------------------------------------------------------------------
  1553. ;            LINE SPACING SUBROUTINE
  1554. ;
  1555. ;    INPUTS:
  1556. ;        NONE
  1557. ;    OUTPUTS:
  1558. ;        FORM FEED SENT
  1559. ;        ESC A 7  SENT TO SET THE PRINTER TO 7/72" LINE SPACING
  1560. ;    REGISTER STATUS:
  1561. ;        ALL VALUES CHANGED
  1562. ;    ERROR CONDITIONS:
  1563. ;        NONE
  1564. ;
  1565.     IF    EPSON
  1566. LN772    MVI    C,05H        ;SELECT LIST OUTPUT
  1567. ;    MVI    E,0CH        ;PASS FORMFEED
  1568. ;    CALL    PDOS        ;SEND IT OUT
  1569. ;
  1570. ;    MVI    C,05H        ;SELECT LIST OUTPUT
  1571.     MVI    E,1BH        ;PASS ESC CHARACTER
  1572.     CALL    PDOS        ;SEND IT OUT
  1573. ;
  1574.     MVI    C,05H        ;SELECT LIST OUTPUT
  1575.     MVI    E,'A'        ;PASS "A"
  1576.     CALL    PDOS        ;SEND IT OUT
  1577. ;
  1578.     MVI    C,05H        ;SELECT LIST OUTPUT
  1579.     MVI    E,07H        ;PASS 7 FOR 7/72"
  1580.     CALL    PDOS
  1581. ;
  1582.     RET
  1583.     ENDIF            ;(EPSON)
  1584. ;
  1585.     IF    CITOH
  1586. LN772    MVI    C,05H        ;SELECT LIST OUTPUT
  1587. ;    MVI    E,0CH        ;PASS FORMFEED
  1588. ;    CALL    PDOS        ;SEND IT OUT
  1589. ;
  1590. ;    MVI    C,05H        ;SELECT LIST OUTPUT
  1591.     MVI    E,1BH        ;PASS ESC CHARACTER
  1592.     CALL    PDOS        ;SEND IT OUT
  1593. ;
  1594.     MVI    C,05H        ;SELECT LIST OUTPUT
  1595.     MVI    E,'>'        ;ESC >  SETS UNIDIRECTIONAL PRINTING
  1596.     CALL    PDOS        ;SEND IT OUT
  1597. ;
  1598.     MVI    C,05H        ;SELECT LIST OUTPUT
  1599.     MVI    E,1BH        ;PASS ESC CHARACTER
  1600.     CALL    PDOS        ;SEND IT OUT
  1601. ;
  1602.     MVI    C,05H        ;SELECT LIST OUTPUT
  1603.     MVI    E,'T'        ;PASS "T"
  1604.     CALL    PDOS        ;SEND IT OUT
  1605. ;
  1606.     MVI    C,05H
  1607.     MVI    E,'1'
  1608.     CALL    PDOS        ;SEND OUT 1 AS HIGH BYTE
  1609. ;
  1610.     MVI    C,05H        ;SELECT LIST OUTPUT
  1611.     MVI    E,'4'        ;PASS 14 FOR 14/144"
  1612.     CALL    PDOS
  1613. ;
  1614.     RET
  1615.     ENDIF            ;(CITOH)
  1616. ;
  1617.     IF    OKI
  1618. LN772    MVI    C,05H
  1619.     MVI    E,18H        ;CLEAR PRINTER
  1620.     CALL    PDOS
  1621.     MVI    C,05H
  1622.     MVI    E,1CH        ;SET 12 CPI
  1623.     CALL    PDOS
  1624.     MVI    C,05H
  1625.     MVI    E,1BH        ;ESC % "9" 14 TO SET LINE SPACING
  1626.     CALL    PDOS
  1627.     MVI    C,05H
  1628.     MVI    E,25H
  1629.     CALL    PDOS
  1630.     MVI    C,05H
  1631.     MVI    E,39H
  1632.     CALL    PDOS
  1633.     MVI    C,05H
  1634.     MVI    E,14D        ;14/144 "/LINE
  1635.     CALL    PDOS
  1636.     RET
  1637.     ENDIF            ;(OKI)
  1638. ;
  1639. ;-----------------------------------------------------------------------
  1640. ;    THIS SUBROUTINE CALCULATES THE ADDRESS FOR AN XY COORDINATE PAIR
  1641. ;    XYADDR= ORIGIN + XCOORD + (MAXY-YCOORD)/7 * (MAXX+1)
  1642. ;    INPUTS:
  1643. ;        XCOORDINATE IN REGISTERS BC
  1644. ;        YCOORDINATE IN REGISTERS DE
  1645. ;        MAXIMUM Y RASTER COUNT IN HL
  1646. ;    OUTPUTS:
  1647. ;        XCOORDINATE IN REGISTERS BC
  1648. ;        YCOORDINATE IN REGISTERS DE
  1649. ;        ADDRESS OF X,Y COORDINATES IN HL
  1650. ;        ADDRESS STORED @ XYADDR
  1651. ;    REGISTER STATUS:
  1652. ;        PSW VALUES CHANGED
  1653. ;    ERROR CONDITIONS:
  1654. ;        OVERFLOW OF ARITHMETIC CALLS WOOPS
  1655. ;
  1656. LOCDOT    PUSH    D        ;STORE Y COORD ON STACK
  1657.     PUSH    B        ;STORE X COORD ON STACK
  1658.     MOV    A,L
  1659.     SUB    E        ;SUBTRACT YCOORD FROM MAXY
  1660.     MOV    L,A
  1661.     MOV    A,H
  1662.     SBB    D
  1663.     MOV    H,A        ;[HL] NOW CONTAINS (MAXY - Y)
  1664.     SHLD    DIVDND        ;PASS (MAXY - Y) TO DIVISION ROUTINE
  1665.     MVI    A,07H        ;PASS 7 TO DIVISION ROUTINE
  1666.     STA    DIVSOR
  1667.     CALL    DIVIDE        ;(MAXY - Y)/7
  1668.     LDA    RMANDR        ;RMANDR IS NEGATIVE IF OVERFLOW
  1669.     ORA    A        ;SET FLAGS
  1670.     CM    WOOPS        ;OVERFLOW IN DIVISION
  1671.     LDA    QOTENT        ;GET RESULT OF DIVISION
  1672.     LXI    B,MAXX+1    ;[BC] NOW CONTAINS THE MAX. NO. OF X'S
  1673.     CALL     BMULT        ;[HL] HAS LOW ORDER BYTES, [A] THE HIGH
  1674. ;            [HL] NOW CONTAINS (MAX-YCOORD)/7*(MAX+1)
  1675.     POP    B            ;PUT XCOORD IN [BC]
  1676.     DAD    B            ;ADD TO X PREVIOUS TERM
  1677.     LXI    D,ORIGIN        ;LAST TERM
  1678.     DAD    D            ;FINAL SUM IS IN [HL]
  1679.     SHLD    XYADDR            ;STORE RESULT
  1680.     POP    D        ;RETRIEVE Y COORDINATE
  1681.     RET
  1682. ;
  1683. ;-----------------------------------------------------------------------
  1684. ;    OUTPUT ROUTINE
  1685. ;
  1686. ;    INPUTS:
  1687. ;        MEMORY MAP STARTING @ ORIGIN
  1688. ;
  1689. ;    OUTPUTS:
  1690. ;        MAP IS DUMPED TO PRINTER 1 BYTE AT A TIME
  1691. ;        MIXED GRAPHICS AND TEXT ARE OUTPUT
  1692. ;
  1693. ;    REGISTER STATUS:
  1694. ;        ALL VALUES DESTROYED
  1695. ;
  1696. ;    ERROR CONDITIONS:
  1697. ;        NONE. PRINTER WILL HANG IF IT DOESN'T GET PROPER INPUT
  1698. ;
  1699. MAPOUT    MVI    A,00H        ;RESET STATUS COUNTER
  1700.     STA    STATNO
  1701.     MVI    C,09H        ;PRINT PRINTING STATUS MESSAGE
  1702.     LXI    D,STAT3        
  1703.     CALL    FDOS
  1704. ;
  1705.     CALL    LN772        ;SET PRINTER TO 7/72" LINE SPACING
  1706.     LXI    H,ORIGIN    ;INITIAIZE START ADDRESS
  1707.     MVI    A,00H        ;CLEAR ACCUMULATOR
  1708.     STA    NGRAPH        ;INITIALIZE GRAPHICS COUNTER
  1709.     STA    NGRAPH+1
  1710.     MVI    C,(MAXY+1)/7    ;INITIALIZE LINE COUNTER
  1711. LINLOOP    LXI    D,MAXX+1    ;INITIALIZE DOT COUNTER
  1712. ;
  1713. BYTLOOP    MOV    B,M        ;GET BYTE
  1714.     MOV    A,B        ;PUT BYTE IN (A)
  1715.     ORA    A        ;SET FLAGS - IS IT A GRAPHIC BYTE?
  1716.     CM    CHAROUT        ;NO- HI BIT SET THEREFORE CHARACTER
  1717.     CP    GBUFIN        ;YES- SAVE IT IN GRAPHIC BUFFER
  1718. ;
  1719.     INX    H        ;INCREMENT ADDRESS TO NEXT X LOCATION
  1720.     DCX    D        ;DECREMENT DOT COUNTER
  1721.     MOV    A,D
  1722.     ORA    E        ;IS DOT COUNTER = 0?
  1723.     JNZ    BYTLOOP        ;NO- SO LOOP TO TOP AGAIN
  1724. ;
  1725.     CALL    GBUFOUT        ;AT END OF LINE- FLUSH BUFFER
  1726.     CALL    CRLF        ;SEND A LINE FEED TO PRINTER
  1727.     DCR    C        ;DECREMENT LINE COUNTER
  1728.     MOV    A,C        ;GET READY TO TEST LINE COUNTER
  1729.     ORA    A        ;SET FLAGS ON LINE COUNTER
  1730.     JNZ    LINLOOP        ;NOT DONE- REPEAT OUTER LOOP
  1731. ;
  1732.     CALL    PRESET        ;RESET PRINTER TO NORMAL MODE
  1733. ;
  1734.     RET            ;LAST LINE FINISHED
  1735. ;
  1736. ;-----------------------------------------------------------------------
  1737. ;    THIS SUBROUTINE MOVES THE PRESENT POSITION TO NEW COORDINATES
  1738. ;    WITHOUT DOING ANYTHING ELSE
  1739. ;
  1740. ;    INPUTS:
  1741. ;        COORDINATE PAIR IN BUFFER
  1742. ;    OUTPUTS:
  1743. ;        XPOS AND YPOS UPDATED TO NEW COORDINATES
  1744. ;    REGISTER STATUS:
  1745. ;        ALL VALUES DESTROYED
  1746. ;    ERROR CONDITIONS:
  1747. ;        NONE PECULIAR TO THIS ROUTINE
  1748. ;
  1749. MOVE    CALL    READXY        ;GET COORDINATE PAIR
  1750.     LHLD    X        ;GET X COORDINATE
  1751.     SHLD    XPOS        ;UPDATE X AXIS POSITION
  1752.     LHLD    Y        ;GET Y COORDINATE
  1753.     SHLD    YPOS        ;UPDATE    Y AXIS POSITION
  1754.     RET            ;POSITION NOW UPDATED.
  1755. ;
  1756. ;-----------------------------------------------------------------------
  1757. ;
  1758. ;    THIS SUBROUTINE MULTIPLIES TWO 16 BIT INTEGERS
  1759. ;
  1760. ;    THIS ROUTINE FROM ELECTRONICS MAGAZINE, FEB. 24, 1982.
  1761. ;    WRITTEN BY JERRY L. GOODRICH, PENN. STATE U.
  1762. ;
  1763. ;
  1764. ;    INPUTS:
  1765. ;        MULTIPLICAND IN [BC]
  1766. ;        MULTIPLIER IN [DE]
  1767. ;    OUTPUTS:
  1768. ;        32 BIT PRODUCT IN [DE],[HL] (MOST SIG. BITS IN [DE])
  1769. ;    REGISTER STATUS:
  1770. ;        SEE INPUTS AND OUTPUTS
  1771. ;    ERROR CONDITIONS:
  1772. ;        NONE
  1773. ;
  1774. MULT    MOV    A,E        ;LOAD LOWEST ORDER BYTE OF MULTIPLIER
  1775.     PUSH    D        ;SAVE HIGHEST ORDER BYTE OF MULTIPLIER
  1776.     CALL    BMULT        ;DO 1-BYTE MULTIPLY
  1777.     XTHL        ;SAVE LOWEST ORDER BYTES PRODUCT, GET MULTIPLIER
  1778.     PUSH    PSW        ;STORE HIGHEST ORDER BYTE OF FIRST PROD.
  1779.     MOV    A,H        ;LOAD HIGHEST ORDER BYTE OF MULTIPLIER
  1780.     CALL    BMULT        ;DO SECOND 1-BYTE MULTIPLY
  1781.     MOV    D,A        ;POSITION HIGHEST-ORDER BYTE OF PRODUCT
  1782.     POP    PSW        ;GET HIGHEST ORDER BYTE OF FIRST PRODUCT
  1783.     ADD    H        ;UPDATE THIRD BYTE OF PRODUCT
  1784.     MOV    E,A        ;AND PUT IT IN E
  1785.     JNC    NC1        ;DONT'T INCREMENT D IF NO CARRY
  1786.     INR    D        ;INCREMENT D IF CARRY
  1787. NC1:    MOV    H,L        ;RELOCATE LOWEST ORDER BYTES OF 2ND PROD
  1788.     MVI    L,0
  1789.     POP    B        ;GET LOWEST ORDER 2 BYTES OF FIRST PROD.
  1790.     DAD    B        ;GET FINAL PRODUCT LOWEST ORDER 2 BYTES
  1791.     RNC            ;DONE IF NO CARRY
  1792.     INX    D        ;OTHERWISE UPDATE HIGHEST ORDER 2 BYTES
  1793.     RET
  1794. ;
  1795. ;-----------------------------------------------------------------------
  1796. ;    PRINT OR DISK O/P SUBROUTINE
  1797. ;
  1798. ;    INPUTS:
  1799. ;        05H IN (C)
  1800. ;        CHARACTER IN (E)
  1801. ;        BUFFER POINTER SET TO LAST CHARACTER (POINTR2)
  1802. ;        O/P FLAG IN OPDISK
  1803. ;    OUTPUTS:
  1804. ;        CHARACTER PRINTED IF O/P FLAG SET
  1805. ;        CHARACTER WRITTEN TO DISK IF FLAG IS SET
  1806. ;    REGISTER STATUS:
  1807. ;        ALL REGISTER VALUES DESTROYED
  1808. ;    ERROR CONDITIONS:
  1809. ;        NONE IN THIS ROUTINE.
  1810. ;
  1811. PDOS    LDA    OPDISK            ;GET DISK O/P FLAG
  1812.     CPI    00H            ;IS FLAG SET?
  1813.     PUSH    PSW            ;SAVE FLAG
  1814.     CZ    FDOS            ;PRINT CHARACTER IF IT IS
  1815.     POP    PSW            ;RETRIEVE FLAGS
  1816.     RZ                ;RETURN IF CHARACTER WAS PRINTED
  1817. ;
  1818.     LDA    POINTR2            ;GET BUFFER POINTER
  1819.     INR    A            ;INCREMENT POINTER FOR NEW CHAR.
  1820.     STA    POINTR2            ;SAVE NEW VALUE
  1821.     MOV    C,A            ;SAVE POINTER VALUE IN (C)
  1822.     MVI    B,0            ;CLEAR HIGH BYTE OF (BC)
  1823.     LXI    H,DMA2-1        ;GET LAST ADDR. BEFORE DMA2
  1824.     DAD    B            ;CALCULATE ADDRESS OF BYTE
  1825.     MOV    M,E            ;PUT CHARACTER IN BUFFER
  1826.     CPI    128D            ;IS BUFFER FULL?
  1827.     CZ    WRITE            ;WRITE IT OUT IF IT IS.
  1828.     RET                ;DONE
  1829. ;
  1830. ;-----------------------------------------------------------------------
  1831. ;    THIS SUBROUTINE PLOTS A POINT @ XDOT,YDOT
  1832. ;    METHOD:
  1833. ;        FIND BYTE CONTAINING XDOT,YDOT
  1834. ;        FORM MASK EG: IF XDOT,YDOT IS IN #4 BIT,
  1835. ;        MASK = 00010000
  1836. ;        DIGIT= 76543210
  1837. ;        MODIFY BYTE ACCORDING TO COLOR & STORE IT BACK
  1838. ;    INPUTS:
  1839. ;        2 BYTE X LOCATION STORED @ XDOT
  1840. ;        2 BYTE Y LOCATION STORED @ YDOT
  1841. ;    OUTPUTS:
  1842. ;        XPOS, YPOS RESET TO VALUES GIVEN IN XDOT, YDOT
  1843. ;        APPROPRIATE DOT TURNED ON OR OFF IN MEMORY MAP
  1844. ;    REGISTER STATUS:
  1845. ;        ALL REGISTER VALUES DESTROYED
  1846. ;    ERROR CONDITIONS:
  1847. ;        IF XDOT OR YDOT ARE OUTSIDE OF WINDOW, NO POINT PLOTTED
  1848. ;        XPOS AND YPOS WILL STILL POINT OUTSIDE WINDOW
  1849. ;
  1850. PLOTDOT    LHLD    XDOT            ;GET X POSITION
  1851.     SHLD    XPOS            ;UPDATE CURRENT POSITION
  1852.     MOV    B,H            ;MOVING XDOT TO BC
  1853.     MOV    C,L            ;XDOT NOW IN BC
  1854.     LHLD    YDOT            ;GET Y POSITION
  1855.     SHLD    YPOS            ;UPDATE CURRENT POSITION
  1856.     MOV    D,H            ;MOVING YDOT TO DE
  1857.     MOV    E,L            ;YDOT NOW IN DE
  1858. ;XPOS AND YPOS NOW CONTAIN LAST POS. ATTEMPTED- MAY NOT BE IN WINDOW
  1859.     LXI    H,MAXX        ;PUT LIMITS OF X IN HL
  1860. XCHECK    MOV     A,B                ;CHECK FOR NEG X-SIGN IN HI BYTE
  1861.     ORA    A            ;IS XDOT NEGATIVE?
  1862.     RM                ;XDOT NEG- RETURN W/O PLOTTING
  1863.     MOV    A,H            ;WORK WITH HIGH BYTE FIRST
  1864.     CMP    B            ;COMPARE MAX & X HIGH BYTES
  1865.     RC                ;X>MAX- THEREFORE RETURN
  1866.     JNZ    YCHECK            ;X IS OK- CHECK Y
  1867.     MOV    A,L            ;HIGH BYTES ARE= LOOK @ LOW BYTE
  1868.     CMP    C            ;COMPARE X & MAX LOW BYTES
  1869.     RC                ;X>MAX- RETURN W/O PLOTTING
  1870. YCHECK    LXI    H,MAXY        ;PUT LIMIT OF Y IN HL
  1871.     MOV    A,D            ;YDOT HI BYTE CONTAINS SIGN
  1872.     ORA    A            ;IS YDOT NEGATIVE?
  1873.     RM                ;YDOT NEG- RETURN W/O PLOTTING
  1874.     MOV    A,H            ;HIGH BYTES FIRST
  1875.     CMP    D            ;COMPARE MAX & Y HIGH BYTES
  1876.     RC                ;Y>MAX- RETURN W/O PLOTTING
  1877.     JNZ    XYOK            ;Y IS OK- PLOT DOT
  1878.     MOV    A,L            ;HIGH BYTES= LOOK @ LOW BYTES
  1879.     CMP    E            ;COMPARE LOW BYTES
  1880.     RC                ;Y IS > MAX- RETURN W/O PLOTTING
  1881. XYOK    CALL    LOCDOT            ;GET ADDRESS OF BYTE FOR X,YDOT
  1882.     CALL    DIGIT            ;FORM MASK FOR PLOTTING
  1883.     MOV    A,B        ;DETERMINE IF BYTE IS GRAPHIC
  1884.     ORA    A        ;GRAPHIC?
  1885.     RM            ;MINUS= CHARACTER: RETURN W/O PLOTTING
  1886.     LDA    COLOR            ;GET COLOR VALUE
  1887.     ORA    A            ;SET FLAGS
  1888.     JZ    WHITE            ;0 = WHITE
  1889.     JM    COMPL            ;-1 = COMPLEMENTARY COLOR
  1890.     MOV    A,B            ;COLOR IS BLACK
  1891.     ORA    C            ;MODIFY BYTE BY TURNING BIT ON
  1892.     MOV    M,A            ;STORE BACK IN MEMORY
  1893.     RET                ;DONE- ( AT LAST)
  1894. ;
  1895. WHITE    MOV    A,B            ;WORK W/ BYTE CONTAINING X,Y
  1896.     CMA                ;COMPLEMENT BYTE
  1897.     ORA    C            ;MODIFY BYTE BY TURNING ON BIT
  1898.     CMA                ;COMPLEMENT BYTE BACK- BIT 0FF
  1899.     MOV    M,A            ;STORE BYTE BACK IN MEMORY
  1900.     RET                ;DONE- (FINALY)
  1901. ;
  1902. COMPL    MOV    A,B            ;WORK W/ BYTE CONTAINING X,Y
  1903.     XRA    C            ;COMPLEMENT BIT
  1904.     MOV    M,A            ;STORE IT
  1905.     RET                ;DONE-
  1906. ;
  1907. ;-----------------------------------------------------------------------
  1908. ;        PLOT POINT ROUTINE
  1909. ;
  1910. ;    INPUTS:
  1911. ;        BUFFER @ DMA
  1912. ;    OUTPUTS:
  1913. ;        POINT PLOTTED IN MEMORY
  1914. ;    REGISTER STATUS:
  1915. ;        ALL VALUES CHANGED
  1916. ;    ERROR CONDITIONS:
  1917. ;        NONE
  1918. ;
  1919. POINT    CALL    READXY        ;READ COORDINATES FOR POINT
  1920.     LHLD    X        ;FETCH X LOCATION
  1921.     SHLD    XDOT        ;PASS X TO DOT ROUTINE
  1922.     LHLD    Y        ;FETCH Y LOCATION
  1923.     SHLD    YDOT        ;PSSS Y TO DOT ROUTINE
  1924.     CALL    PLOTDOT
  1925.     RET
  1926. ;
  1927. ;-----------------------------------------------------------------------
  1928. ;            QUIT
  1929. ;    CLOSES OUTPUT FILE, TERMINATES PROGRAM
  1930. ;    INPUTS:
  1931. ;        FCB FOR OUTPUT FILE @ FCB2
  1932. ;        DISK OUTPUT FLAG @ OPDISK
  1933. ;    OUTPUTS:
  1934. ;        REMAINDER OF RECORD SET TO 0, DISK CLOSED.
  1935. ;    REGISTER STATUS:
  1936. ;        ALL VALUES DESTROYED
  1937. ;    ERROR CONDITIONS:
  1938. ;        NONE
  1939. ;
  1940. QUIT:    LDA    OPDISK            ;GET DISK OUTPUT FLAG
  1941.     CPI    00H            ;IS IT SET?
  1942.     JZ    BOOT            ;NO, SO ALL DONE
  1943. ;
  1944.     LDA    POINTR2            ;LOOK @ O/P POINTER
  1945.     CPI    0            ;IS O/P BUFFER EMPTY?
  1946.     JZ    BOOT            ;YES- DONE
  1947. ;
  1948. ;    FILL REMAINDER OF O/P BUFFER WITH NULLS
  1949. ;
  1950.     MOV    E,A            ;SAVE POINTER VALUE IN (E)
  1951.     MVI    D,00H            ;CLEAR HIGH BYTE OF (DE)
  1952.     MVI    A,128            ;SET MAX VALUE OF POINTER
  1953.     SUB    E            ;(A)= 128- POINTR2
  1954.     MOV    C,A            ;(C) NOW IS COUNT OF EXTRA BUFF.
  1955. ;
  1956. CLRBUF    PUSH    B            ;SAVE COUNTER
  1957.     MVI    E,00H            ;PASS A <NULL>
  1958.     CALL    PDOS            ;PUT IT IN BUFFER
  1959.     POP    B            ;RETRIEVE COUNTER
  1960.     DCR    C            ;COUNTER=COUNTER-1
  1961.     JNZ    CLRBUF            ;LOOP BACK UNTIL BUFFER IS FULL
  1962. ;
  1963.     MVI    C,10H            ;SELECT CLOSE FILE FUNCTION
  1964.     LXI    D,FCB2            ;PASS O/P FCB
  1965.     CALL    FDOS            ;CLOSE FILE
  1966. ;
  1967.     JMP    BOOT            ;DO WARM BOOT ON EXIT
  1968. ;
  1969. ;-----------------------------------------------------------------------
  1970. ;            LINE SEGMENT ROUTINE
  1971. ;    INPUTS:    FILE BUFFER @ DMA
  1972. ;
  1973. ;    OUTPUTS:
  1974. ;        XPOS, YPOS UPDATED TO X2,Y2
  1975. ;        VISIBLE PORTION OF LINE SEGMENT PLOTTED
  1976. ;
  1977. ;    REGISTERS:
  1978. ;        ALL REGISTERS VALUES DESTROYED
  1979. ;    ERROR CONDITIONS:
  1980. ;        NO CHECKS MADE IN THIS ROUTINE
  1981. ;
  1982. PLOTSEG    CALL    READXY        ;GET STARTING COORDINATES
  1983.     LHLD    X        ;FETCH STARTING X
  1984.     SHLD    XDOT        ;PASS TO DOT ROUTINE
  1985.     LHLD    Y        ;FETCH STARTING Y
  1986.     SHLD    YDOT        ;PASS TO DOT ROUTINE
  1987.     CALL    PLOTDOT        ;PLOT STARTING POINT
  1988.     CALL    INCPLT        ;PLOT REST OF SEGMENT
  1989.     RET            ;RETURN TO MAIN PROGRAM
  1990. ;
  1991. ;-----------------------------------------------------------------------
  1992. ;
  1993. ;    THIS SUBROUTINE RESETS THE PRINTER TO ITS NORMAL MODE 
  1994. ;
  1995. ;    INPUTS:
  1996. ;        NONE
  1997. ;    OUTPUTS:
  1998. ;        NONE RETURNED
  1999. ;    REGISTER STATUS:
  2000. ;        ALL REGISTERS CHANGED
  2001. ;    ERROR CONDITIONS:
  2002. ;        NONE
  2003. ;
  2004.     IF    EPSON
  2005. PRESET:    MVI    C,05H
  2006.     MVI    E,1BH        ;PASS ESC CHARACTER
  2007.     CALL    PDOS        ;SEND ESC
  2008.     MVI    C,05H
  2009.     MVI    E,'2'
  2010.     CALL    PDOS        ;ESC 2 SETS LINE SPACING TO 6 LINES/IN.
  2011.     MVI    C,05H
  2012.     MVI    E,CR        ;SEND CARRIAGE RETURN TO RESET HEAD
  2013.     CALL    PDOS
  2014.     RET
  2015.     ENDIF            ;(EPSON)
  2016. ;
  2017.     IF    CITOH
  2018. PRESET:    MVI    C,05H
  2019.     MVI    E,1BH        ;SEND ESC
  2020.     CALL    PDOS
  2021.     MVI    C,05H
  2022.     MVI    E,'A'        ;ESC A SETS LINE SPACING TO 6 LINES/IN.
  2023.     CALL    PDOS
  2024.     MVI    E,CR
  2025.     MVI    C,05H
  2026.     CALL    PDOS        ;SEND CARRIAGE RETURN TO RESET HEAD
  2027.     RET
  2028.     ENDIF            ;(CITOH)
  2029. ;
  2030.     IF    OKI
  2031. PRESET:    MVI    C,05H
  2032.     MVI    E,1BH        ;ESC % "9" 24 TO SET LINE SPACING
  2033.     CALL    PDOS
  2034.     MVI    C,05H
  2035.     MVI    E,25H        ; "%"
  2036.     CALL    PDOS
  2037.     MVI    C,05H
  2038.     MVI    E,39H        ; "9"
  2039.     CALL    PDOS
  2040.     MVI    C,05H
  2041.     MVI    E,24D        ;RESET TO NORMAL LINE SPACING
  2042.     CALL    PDOS
  2043.     RET
  2044. ;
  2045.     ENDIF            ;(OKI)
  2046. ;
  2047. ;-----------------------------------------------------------------------
  2048. ;    READ RECORD SUBROUTINE
  2049. ;    INPUTS:
  2050. ;        OPENED FILE
  2051. ;        FILE CONTROL BLOCK @ FCB
  2052. ;        128 CHAR FILE BUFFER @ DMA
  2053. ;        1 BYTE CHARACTER POINTER @ POINTER
  2054. ;    OUTPUTS:
  2055. ;        CHARACTER POINTER RESET TO 0
  2056. ;        NEW RECORD IN FILE BUFFER
  2057. ;    REGISTER STATUS:
  2058. ;        ALL REGISTER VALUES DESTROYED
  2059. ;    ERROR CONDITIONS:
  2060. ;        EOF: JUMP TO EOFEXIT INSTEAD OF NORMAL RETURN
  2061. ;
  2062. READ    MVI    C,26D            ;SELECT SET DMA FUNCTION
  2063.     LXI    D,DMA            ;PASS BUFFER ADDRESS
  2064.     CALL    FDOS            ;SET DMA ADDRESS TO I/P BUFFER
  2065. ;
  2066.     MVI    C,14H            ;SELECT SEQUENTIAL READ FUNCTION
  2067.     LXI    D,FCB            ;PASS FCB
  2068.     CALL    FDOS            ;READ RECORD INTO BUFFER @ DMA
  2069.     CPI    00H            ;READ OK?
  2070.     JZ    SETPNTR            ;RESET POINTER IF NOT EOF
  2071.     POP    B            ;POP RETURN ADDR OFF STACK
  2072.     JMP    EOFEXIT            ;GOTO EXIT INSTEAD OF NORMAL RTN
  2073. SETPNTR    MVI    A,0            ;CLEAR ACCUM.
  2074.     STA    POINTER            ;RESET POINTER TO 0
  2075.     RET                ;RETURN-NEW RECORD & POINTER POS
  2076. ;
  2077. EOFEXIT    MVI    C,09H        ;SELECT PRINT STRING FUNCTION
  2078.     LXI    D,EOFMSG        ;PASS MESSAGE
  2079.     CALL    FDOS        ;PRINT EOF MESSAGE
  2080.     JMP    BOOT        ;RETURN TO CP/M COMMAND LEVEL
  2081. ;-----------------------------------------------------------------------
  2082. ;
  2083. ;    THIS SUBROUTINE GETS AN XY PAIR
  2084. ;AND CONVERTS IT TO RASTER VALUES.  THE GENERAL ALGORITHM IS:
  2085. ;
  2086. ;    INTEGER = (FIXED POINT) * (NUMBER OF RASTERS) * 2/ 2^16
  2087. ; THE FIXED POINT NUMBER IS A 15 BIT VALUE IN THE RANGE 0 TO 1.  
  2088. ; WHEN VIEWED AS AN INTEGER, THE FIXED POINT COORDINATES RANGE FROM
  2089. ; 0 TO 32767.  WHEN MULTIPLIED BY THE RANGE OF THE RASTER COORDINATES,
  2090. ; THEY MUST BE DIVIDED BY 32767 TO REPRESENT THE TRUE VALUE.  THIS IS 
  2091. ; APPROXIMATED BY MULTIPLYING BY 2 / 65536   (2/64K).  DIVIDING BY 64K
  2092. ; IS ACCOMPLISHED BY SIMPLY DISREGARDING THE LOWER 2 BYTES OF THE RESULT
  2093. ;
  2094. ;    INPUTS:
  2095. ;        128 CHARACTER BUFFER @ DMA
  2096. ;        CHARACTER POINTER @ POINTER
  2097. ;    OUTPUTS:
  2098. ;        TWO BYTE VALUE STORED @ X
  2099. ;        TWO BYTE VALUE STORED @ Y
  2100. ;    REGISTER STATUS:
  2101. ;        ALL REGISTER VALUES DESTROYED
  2102. ;    ERROR CONDITIONS:
  2103. ;        NONE- BYTE WILL TERMINATE PROGRAM ON EOF IF NECESSARY
  2104. ;
  2105. READXY    CALL    BYTE            ;GET FIRST BYTE OF X
  2106.     PUSH    PSW        ;STORE FIRST BYTE
  2107.     CALL    BYTE        ;GET SECOND BYTE
  2108.     MOV    B,A        ;PUT HIGH BYTE IN [B]
  2109.     POP    PSW        ;GET LOW BYTE
  2110.     MOV    C,A        ;[BC] NOW CONTAINS FIXED POINT X COORD.
  2111.     LXI    D,MAXX*2    ;PASS MAXIMUM RASTER ADDRESS
  2112.     CALL    MULT        ;MULTIPLY X COORD BY NO. OF X RASTERS
  2113.     XCHG            ;PUT HIGH BYTES IN [HL]
  2114.     SHLD    X        ;STORE CORRESPONDING RASTER X COORDINATE
  2115. ;
  2116.     CALL BYTE        ;GET FIRST BYTE OF Y
  2117.     PUSH    PSW        ;STORE FIRST BYTE
  2118.     CALL    BYTE        ;GET SECOND BYTE
  2119.     MOV    B,A        ;PUT HIGH BYTE IN [B]
  2120.     POP    PSW        ;GET LOW BYTE
  2121.     MOV    C,A        ;[BC] NOW CONTAINS FIXED POINT Y COORD.
  2122.     LXI    D,MAXY*2    ;PASS MAXIMUM RASTER ADDRESS
  2123.     CALL    MULT        ;MULTIPLY Y COORD BY NO. OF Y RASTERS
  2124.     XCHG            ;PUT HIGH BYTES IN [HL]
  2125.     SHLD    Y        ;STORE CORRESPONDING RASTER Y COORDINATE
  2126.     RET
  2127. ;
  2128. ;---------------------------------------
  2129. ;
  2130. ;    THIS SUBROUTINE ROTATES THE PATTERNS USED FOR ERASING TO A COLOR
  2131. ;
  2132. ;    INPUTS:
  2133. ;        ARRAY OF 8 PATTERN BYTES STORED AT PATRN
  2134. ;    OUTPUTS:
  2135. ;        ARRAY IS ROTATED ONE BIT DOWN
  2136. ;    REGISTER STATUS:
  2137. ;        [BC],[HL] PRESERVED, ALL OTHERS DESTROYED
  2138. ;    ERROR CONDITIONS:
  2139. ;        NONE
  2140. ;
  2141. ROTPAT:    PUSH    B        ;SAVE COUNTER IN [BC]
  2142.     PUSH    H        ;SAVE POINTER IN [HL]
  2143.     MVI    B,8D        ;INITIALIZE COUNTER
  2144.     LXI    H,PATRN        ;INITIALIZE ADDRESS OF HEAD OF ARRAY
  2145. ROTPT1:    MOV    A,M        ;GET BYTE
  2146.     IF    MSBTOP
  2147.     RRC            ;ROTATE BYTE
  2148.     ENDIF            ;( MSBTOP )
  2149.     IF    NOT MSBTOP
  2150.     RLC
  2151.     ENDIF            ;( NOT MSBTOP )
  2152.     MOV    M,A        ;STORE ROTATED BYTE
  2153. ;
  2154.     INX    H        ;MOVE POINTER TO NEXT BYTE
  2155.     DCR    B        ;DECREMENT COUNTER
  2156.     JNZ    ROTPT1        ;LOOP BACK UNTIL DONE
  2157.     POP    H        ;RETRIEVE SAVED REGISTERS
  2158.     POP    B
  2159.     RET
  2160. ;
  2161. ;-----------------------------------------------------------------------
  2162. ;
  2163. ;    THIS SUBROUTINE INITIALIZES THE VARIABLES USED IN COMPUTING A 
  2164. ;    LINE SEGMENT
  2165. ;
  2166. ;    INPUTS:
  2167. ;        XPOS,YPOS    PRESENT POSITION
  2168. ;        X,Y        END POINTS OF SEGMENT
  2169. ;    OUTPUTS:
  2170. ;        DX,DY    X,Y SIZES OF LINE SEGMENT
  2171. ;        EPSLNX,EPSLNY,SX,SY,DELTA3    INTERNAL VARIABLES 
  2172. ;                        INITIALIZED
  2173. ;        NI    COUNTER USED TO DETERMINE WHEN DONE
  2174. ;    REGISTER SATUS:
  2175. ;        ALL REGISTER VALUES DESTROYED.
  2176. ;    ERROR CONDITIONS:
  2177. ;        NONE
  2178. ;
  2179. SEGINIT    LHLD    X            ;GET X
  2180.     XCHG                ;PUT X IN DE
  2181.     LHLD    XPOS            ;PUT PRESENT POS IN HL
  2182.     MOV    A,E            ;CALCULATE DELTA X
  2183.     SUB    L
  2184.     MOV    C,A
  2185.     MOV    A,D
  2186.     SBB    H
  2187.     MOV    B,A            ;BC NOW CONTAINS DELTA X (DX)
  2188.     LHLD    Y            ;GET Y END POINT VALUE
  2189.     XCHG                ;PUT Y IN DE
  2190.     LHLD    YPOS            ;GET PRESENT Y POSITION
  2191.     MOV    A,E            ;CALCULATE DELTA Y (DY)
  2192.     SUB    L
  2193.     MOV    E,A
  2194.     MOV    A,D
  2195.     SBB    H
  2196.     MOV    D,A            ;DE NOW CONTAINS DY
  2197.     XCHG                ;PUT DY IN HL, YPOS IN DE
  2198.     SHLD    DELTAY            ;STORE DY
  2199.     MOV    H,B
  2200.     MOV    L,C
  2201. ;
  2202.     SHLD    DELTAX            ;STORE DELTA X
  2203.     LXI    H,0000H            ;INITIALIZE VARIABLES
  2204.     SHLD    SX
  2205.     SHLD    EPSLNY
  2206.     LXI    H,0001H
  2207.     SHLD    SY
  2208.     SHLD    EPSLNX
  2209.     LDA    DELTAX+1        ;GET DX HIGH BYTE
  2210.     ORA    A        ;SET FLAGS ACCORDING TO DX HI BYTE
  2211.     JP    CHKDY
  2212.     LXI    H,0FFFFH        ;CHANGE INITIALIZATION FOR -DX
  2213.     SHLD    EPSLNX
  2214.     LHLD    DELTAX            ;CHANGE SIGN ON DX
  2215.     MOV    A,H
  2216.     CMA                ;COMPLEMENT HIGH BYTE
  2217.     MOV    H,A
  2218.     MOV    A,L
  2219.     CMA                ;COMPLEMENT LOW BYTE
  2220.     ADI    01H            ;ADD 1 TO MAKE IT TWO'S COMP.
  2221.     MOV    L,A
  2222.     MOV    A,H
  2223.     ACI    00H            ;ADD CARRY TO HIGH BYTE
  2224.     MOV    H,A
  2225.     SHLD    DELTAX            ;STORE NOW POSITIVE DX
  2226. CHKDY    LDA    DELTAY+1        ;GET DY HIGH BYTE- CONTAINS SIGN
  2227.     ORA    A        ;SET FLAGS ON DY HI BYTE
  2228.     JP    CHDXDY            ;DY IS POS- GOTO TRANSPOSE AXES
  2229.     LHLD    DELTAY            ;DY IS NEGATIVE- CHANGE SIGN
  2230.     MOV    A,H
  2231.     CMA                ;COMPLEMENT HI BYTE
  2232.     MOV    H,A
  2233.     MOV    A,L
  2234.     CMA
  2235.     ADI    01H            ;COMPLEMENT AND ADD 1
  2236.     MOV    L,A
  2237.     MOV    A,H
  2238.     ACI    00H            ;ADD CARRY FROM LOW BYTE
  2239.     MOV    H,A
  2240.     SHLD    DELTAY            ;STORE THE NOW POS. DY
  2241.     LXI    H,0FFFFH        ;LOAD -1 IN (HL)
  2242.     SHLD    SY            ;SY= -1
  2243. CHDXDY    LHLD    DELTAX            ;TRANSPOSE AXES IF DX<DY
  2244.     XCHG                ;PUT DX IN DE
  2245.     LHLD    DELTAY        ;GET DELTA Y
  2246.     MOV    A,D            ;PUT HIGH BYTE OF DX IN A
  2247.     CMP    H            ;DX < DY ? (HIGH BYTES FIRST)
  2248.     JC    TNSPOS            ;DX DEFINITELY < DY
  2249.     JNZ    LSTINIT            ; DX DEFINITELY > DY
  2250.     MOV    A,E            ;HIGH BYTES =, CHECK LOW BYTES
  2251.     CMP    L
  2252.     JNC    LSTINIT            ;IF NO CARRY, DX>= DY- START PLOTTING
  2253. TNSPOS    SHLD    DELTAX            ;DY WAS IN HL- STORE AS DX
  2254.     XCHG                ;DX NOW IN HL, DY NOW IN DE
  2255.     SHLD    DELTAY            ;STORE OLD DX AS NEW DY
  2256.     LHLD    EPSLNX
  2257.     SHLD    SX            ;REINITIALIZE: SX= EPSILON X
  2258.  
  2259.     LHLD    SY
  2260.     SHLD    EPSLNY        ;EPSILON Y = SY
  2261.     LXI    H,0000H
  2262.     SHLD    EPSLNX        ;EPSILON X = 0
  2263.     SHLD    SY        ;SY = 0
  2264. ;
  2265. LSTINIT    STC            ;CLEAR CARRY -SET=1, THEN COMPLEMENT
  2266.     CMC
  2267.     MOV    A,D        ;CALCULATE DELTAX/2 BY SHIFTING 1 RIGHT
  2268.     RAR            ;SHIFT
  2269.     MOV    D,A        ;STORE HIGH BYTE DELTAX/2 IN D
  2270.     MOV    A,E        ;NOW THE LOW BYTE
  2271.     RAR            ;SHIFT  (DIVIDE BY 2)
  2272.     MOV    E,A        ;PUT LOW BYTE BACK.
  2273.     XCHG            ;PUT DX/2 IN (HL)
  2274.     SHLD    DELTA3        ;STORE IN DELTA3
  2275. ;
  2276.     LXI    H,0001H        ;SET NI=1
  2277.     SHLD    NI        ;SAVE COUNTER VALUE
  2278.     RET            ;DONE WITH INITIALIZATION
  2279. ;
  2280. ;------------------------------------------------------------------------
  2281. ;            STATUS MESSAGE ROUTINE
  2282. ;
  2283. ;    THIS ROUTINE DISPLAYS A MESSAGE TO INDICATE THAT THE PROGRAM
  2284. ;    IS WORKING.
  2285. ;
  2286. ;    INPUTS:
  2287. ;        CURRENT COUNT STORED IN STATNO
  2288. ;    OUTPUTS:
  2289. ;        MESSAGE DISPLAYED
  2290. ;    REGISTER STATUS:
  2291. ;        ALL REGISTER VALUES PRESERVED
  2292. ;    ERROR CONDITIONS:
  2293. ;        NONE
  2294. ;
  2295. STAT    PUSH    PSW        ;SAVE REGISTERS
  2296.     PUSH    B
  2297.     PUSH    D
  2298.     PUSH    H
  2299. ;
  2300.     LDA    STATNO        ;GET COUNTER
  2301.     INR    A        ;UPDATE COUNTER
  2302.     STA    STATNO
  2303.     MVI    C,09H        ;SELECT WRITE FUNCTION
  2304.     CPI    01H        ;SELECT MESSAGE
  2305.     JNZ    STATM2
  2306.     LXI    D,STAT1
  2307.     CALL    FDOS        ;PRINT MESSAGE
  2308.     JMP    STATX        ;EXIT SUBROUTINE
  2309. ;
  2310. STATM2    CPI    128        ;CHECK FOR OTHER MESSAGE
  2311.     JNZ    STATX        ;NOT TIME FOR EITHER MESSAGE
  2312.     LXI    D,STAT2
  2313.     CALL    FDOS        ;PRINT OTHER MESSAGE
  2314. ;
  2315. STATX    POP    H        ;RESTORE REGISTERS
  2316.     POP    D
  2317.     POP    B
  2318.     POP    PSW
  2319.     RET
  2320. ;
  2321. ;------------------------------------------------------------------------
  2322. ;            STRING PLOTTING SUBROUTINE
  2323. ;    METHOD:
  2324. ;        ASCII CODE IS STORED REPEATEDLY IN THE AREA OCCUPIED BY
  2325. ;        THE CHARACTER (CWIDTH RASTERS).  HI BIT IS SET TO  
  2326. ;        INDICATE THAT THE BYTE IS ASCII AND NOT DOT IMAGE.
  2327. ;
  2328. ;    INPUT:
  2329. ;        X,Y IN FILE BUFFER
  2330. ;        BYTES READ SEQUENTIALLY FROM BUFFER UNTIL CARRIAGE RTN
  2331. ;        IS ENCOUNTERED.
  2332. ;
  2333. ;    OUTPUTS:
  2334. ;        EACH CHARACTER IS STORED IN THE BYTE CONTAINING THE BIT
  2335. ;        MAP COORDINATE INDICATED FOR THE CHARACTER
  2336. ;
  2337. ;    REGISTER STATUS:
  2338. ;        ALL REGISTER VALUES DESTROYED
  2339. ;
  2340. ;    ERROR CONDITIONS:
  2341. ;        X,Y LOCATIONS < 0 ARE RESET TO 0
  2342. ;        X,Y LOCATIONS > MAX ARE RESET TO 0
  2343. ;
  2344. CR    EQU    0DH        ;CR = CARRIAGE RETURN
  2345. STRING    CALL    READXY        ;GET STARTING COORDINATES
  2346. STRNG0    CALL    BYTE        ;GET FIRST CHARACTER
  2347.     CPI    CR        ;IS CHARACTER A CARRIAGE RETURN?
  2348.     RZ            ;YES- SO RETURN (ALL DONE)
  2349.     ORI    10000000B    ;SET HIGH BIT
  2350.     MOV    B,A        ;SAVE BYTE IN (B)
  2351.     LHLD    X        ;GET X LOCATION
  2352.     MOV    A,H        ;LOOK AT HIGH BYTE
  2353.     ORA    A        ;SET FLAGS
  2354.     JM    RESETX        ;X IS NEGATIVE- RESET TO 0
  2355.     LXI    D,MAXX-CWIDTH    ;GET MAXIMUM X VALUE 
  2356.     CMP    D        ;COMPARE MAX AND X HIGH BYTES
  2357.     JC    STRNG1        ;MAX DEFINITELY > X (X IS OK)
  2358.     JNZ    RESETX        ;X DEFINITELY > MAX -RESET X
  2359.     MOV    A,L        ;HI BYTES ARE =: LOOK AT LOW BYTES
  2360.     CMP    E        ;IS MAX LOW BYTE > X LOW BYTE?
  2361.     JC    STRNG1        ;YES IS IS - X IS OK
  2362.     JZ    STRNG1        ;LOW BYTES ARE =: X IS BARELY OK
  2363. RESETX    LXI    H,0000H        ;CLEAR HL
  2364.     SHLD    X        ;STORE 0 IN X
  2365. STRNG1    LHLD    Y        ;FETCH Y STARTING LOCATION
  2366.     MOV    A,H        ;LOOK AT Y HIGH BYTE
  2367.     ORA    A        ;SET FLAGS
  2368.     JM    RESETY        ;NEGATIVE - RESET TO 0
  2369.     LXI    D,MAXY    ;USE ENTIRE COORDINATE RANGE FOR Y
  2370.     CMP    D        ;COMPARE MAX AND Y HIGH BYTES
  2371.     JC    STRNG2        ;Y DEFINITELY OK
  2372.     JNZ    RESETY        ;Y DEFINITELY > MAX - RESET Y
  2373.     MOV    A,L        ;HI BYTES ARE =: LOOK @ LOW BYTES
  2374.     CMP    E        ;COMPARE MAX AND Y LOW BYTES
  2375.     JC    STRNG2        ;MAX > Y - Y IS OK
  2376.     JZ    STRNG2        ;Y = MAX
  2377. RESETY    LXI    H,0000H        ;CLEAR OLD VALUE OF Y
  2378.     SHLD    Y        ;Y = 0
  2379. STRNG2    XCHG            ;PUT Y IN (DE)
  2380.     LHLD    X        ;FETCH X
  2381.     PUSH    B        ;SAVE BYTE TEMPORARILY
  2382.     PUSH    D        ;SAVE Y COORD TEMPORARILY
  2383. ;    MAKE X COORD. A MULTIPLE OF CWIDTH FOR PROPER PRINTER OUTPUT
  2384.     SHLD    DIVDND        ;COMPUTE X=(X/CWIDTH)*CWIDTH
  2385.     MVI    A,CWIDTH    ;GET CWIDTH FOR DIVISOR
  2386.     STA    DIVSOR
  2387.     CALL    DIVIDE        ;DIVIDE X BY CWIDTH
  2388.     LDA    QOTENT        ;GET RESULTS (NO OVERFLOW AS 0<=X<1530)
  2389.     LXI    B,CWIDTH    ;PASS CHARACTER WIDTH
  2390.     CALL    BMULT        ;[HL] NOW CONTAINS (X/CWIDTH)*CWIDTH
  2391. ;
  2392.     MOV    B,H        ;PUT X IN (BC)
  2393.     MOV    C,L
  2394.     POP    D        ;RETRIEVE Y COORDINATE
  2395.     LXI    H,MAXY    ;PUT MAX Y IN (HL)
  2396.     CALL    LOCDOT    ;GET LOCATION OF BYTE
  2397.     POP    B        ;RETRIEVE BYTE
  2398.     MOV    M,B        ;PUT BYTE IN ADDRESS CONTAINING X,Y
  2399. ;    STORE BYTE REPEATEDLY TO BLANK OUT ENTIRE AREA OCCUPIED BY IT
  2400.     MVI    A,CWIDTH-1    ;INITIALIZE LOOP COUNTER
  2401. STRNG3:    INX    H        ;INCREMENT ADDRESS
  2402.     MOV    M,B        ;STORE BYTE
  2403.     SUI    1        ;DECREMENT LOOP COUNTER
  2404.     JNZ    STRNG3        ;LOOP BACK UP UNTIL FINISHED
  2405.     MVI    C,CWIDTH        ;PUT CWIDTH IN (C)
  2406.     LHLD    X        ;FETCH X LOCATION
  2407.     MVI    B,00H        ;CLEAR (B)
  2408.     DAD    B        ;INCREMENT X LOCATION FOR  NEXT CHARACTER
  2409.     SHLD    X        ;STORE NEW X LOCATION
  2410.     JMP    STRNG0        ;LOOP UP TO TOP
  2411. ;
  2412. ;-----------------------------------------------------------------------
  2413. ;    TEXT
  2414. ;
  2415. ;    THIS SUBROUTINE OUTPUTS TEXT IMMEDIATELY TO THE PRINTER
  2416. ;    NOTE: TEXT IS NOT PUT INTO MEMORY MAP
  2417. ;
  2418. ;    INPUTS:
  2419. ;        TEXT STRING IN FILE (ENDS WITH 0 BYTE)
  2420. ;    OUTPUTS:
  2421. ;        TEXT STRING PRINTED
  2422. ;    REGISTER STATUS:
  2423. ;        ALL REGISTER VALUES DESTROYED
  2424. ;    ERROR CONDITIONS:
  2425. ;        NONE PECULIAR TO THIS ROUTINE
  2426. ;
  2427. TEXT    CALL    BYTE        ;GET NEXT CHARACTER
  2428.     CPI    0        ;CHECK FOR END OF STRING
  2429.     RZ            ;RETURN IF FINISHED
  2430. ;
  2431.     MOV    E,A        ;PASS CHARACTER
  2432.     MVI    C,05        ;SELECT CP/M LST: OUTPUT
  2433.     CALL    PDOS        ;PRINT IT
  2434. ;
  2435.     JMP    TEXT        ;LOOP BACK UNTIL DONE
  2436. ;
  2437. ;-----------------------------------------------------------------------
  2438. ;
  2439. ;    THIS SUBROUTINE UPLOADS THE ARRAY DEFINING COLOR PALLET
  2440. ;
  2441. ;    INPUTS:
  2442. ;        16 BIT INTEGER SPECIFYING # OF DATA BYTES TO COME
  2443. ;        DATA BYTES IN INPUT FILE
  2444. ;    OUTPUTS:
  2445. ;        NEW COLOR VALUES STORED IN APPROPRIATE ARRAYS
  2446. ;    REGISTER STATUS:
  2447. ;        ALL REGISTER VALUES DESTROYED
  2448. ;    ERROR CONDITIONS:
  2449. ;        NONE
  2450. ;
  2451. UPLOAD:    CALL    BYTE        ;GET LOW BYTE OF INTEGER
  2452.     MOV    C,A        ;SAVE INTEGER IN [BC]
  2453.     CALL    BYTE        ;GET HIGH BYTE
  2454. ;
  2455.     ORA    A        ;CHECK VALUE OF HIGH BYTE
  2456.     JNZ    UPBAD        ;FOR THIS PROGRAM, HI BYTE MUST BE 0
  2457.     MOV    A,C        ;LOOK AT LOW BYTE
  2458.     CPI    7D        ;7 INDICATES UPLOAD PLAID PATTERNS
  2459.     JZ    UPLAID        ;PROCEED TO UPLOAD PLAID VALUES
  2460.     CPI    64D        ;64 INDICATES UPLOAD DITHER MATRIX
  2461.     JZ    UPDITH        ;PROCEED TO UPLOAD DITHER MATRIX
  2462.     CPI    120D        ;124 INDICATES UPLOAD SPECIAL PATTERNS
  2463.     JZ    UPCIF        ;PROCEED TO UPLOAD SPECIAL PATTERNS
  2464. ;
  2465. UPBAD:    CALL    BYTE        ;# HAS UNEXPECTED VALUE- SKIP BYTES
  2466.     DCX    B        ;DECREMENT LOOP COUNTER
  2467.     MOV    A,C
  2468.     ORA    B        ;IS COUNTER = 0 ?
  2469.     JNZ    UPBAD        ;LOOP BACK UNTIL FINISHED
  2470.     RET
  2471. ;
  2472. UPLAID:    LXI    H,PLAIDS+1    ;POINT TO PLAID ARRAY (LEAVE "0" ALONE)
  2473.     JMP    UPLP1        ;PROCEED TO READ-STORE LOOP
  2474. UPCIF:    LXI    H,CIFPAT    ;SET POINTER AT START OF SPECIAL PATTERNS
  2475.     JMP    UPLP1
  2476. UPDITH:    LXI    H,DITHARR    ;POINT TO DITHER ARRAY
  2477. UPLP1:    CALL    BYTE        ;GET COLOR PATTERN
  2478.     MOV    M,A        ;STORE PATTERN
  2479.     INX    H        ;POINT TO NEXT PATTERN SLOT
  2480.     DCR    C        ;DECREMENT COUNTER
  2481.     JNZ    UPLP1        ;LOOP BACK UNTIL FINISHED
  2482.     RET
  2483. ;
  2484. ;-----------------------------------------------------------------------
  2485. ;    THIS SUBROUTINE IS EXECUTED WHEN OVERFLOW OCCURS IN MULT. OR DIV
  2486. ;    INPUTS:
  2487. ;        NONE
  2488. ;    OUTPUTS:
  2489. ;        MESSAGE "OVERFLOW"
  2490. ;        ALL REGISTERS PUSHED ON STACK
  2491. ;        IN ORDER: PSW, H, D, B
  2492. ;        FINAL POSITION OF STACK POINTER SAVED IN OLDSTK
  2493. ;    REGISTER STATUS:
  2494. ;        ALL INPUT REGISTERS STORED ON STACK, C, DE, HL REG CHANGED
  2495. ;    ERROR CONDITIONS:
  2496. ;        NONE
  2497. ;
  2498. WOOPS    PUSH    PSW            ;SAVE ALL REGISTERS
  2499.     PUSH    H
  2500.     PUSH    D
  2501.     PUSH    B
  2502.     LXI    H,0000H        ;CLEAR (HL)
  2503.     DAD    SP        ;GET STACK POINTER
  2504.     SHLD    OLDSTK        ;SAVE STACK POINTER FOR DEBUG
  2505.     MVI    C,09H            ;SELECT PRINT FUNCTION
  2506.     LXI    D,OVFLMSG
  2507.     CALL    FDOS            ; PRINT 'OVERFLOW'
  2508.     JMP    BOOT            ;RETURN TO CP/M COMMAND LEVEL
  2509. OVFLMSG    DB    'OVERFLOW$'
  2510. ;
  2511. ;-----------------------------------------------------------------------
  2512. ;    WRITE RECORD SUBROUTINE
  2513. ;
  2514. ;    INPUTS:
  2515. ;        OPENED FILE
  2516. ;        FILE CONTROL BLOCK @ FCB2
  2517. ;        BUFFER @ DMA2
  2518. ;        BUFFER POINTER @ POINTR2
  2519. ;    OUTPUTS:
  2520. ;        BUFFER WRITTEN TO FILE
  2521. ;        BUFFER POINTER RESET TO 0
  2522. ;    REGISTER STATUS:
  2523. ;        ALL REGISTER VALUES CHANGED
  2524. ;    ERROR CONDITIONS:
  2525. ;        IF NO SPACE LEFT ON DISK, ERROR MESSAGE WRITTEN
  2526. ;        AND PROGRAM TERMINATES.
  2527. ;
  2528. WRITE    MVI    C,26D            ;SELECT SET DMA FUNCTION
  2529.     LXI    D,DMA2            ;PASS O/P BUFFER
  2530.     CALL    FDOS            ;SET DMA ADDRESS
  2531. ;
  2532.     MVI    C,21D            ;SELECT WRITE SEQUENTIAL
  2533.     LXI    D,FCB2            ;PASS O/P FCB
  2534.     CALL    FDOS            ;WRITE RECORD
  2535. ;
  2536.     CPI    00H            ;WAS WRITE OK?
  2537.     JNZ    FULLXIT            ;JUMP TO ERROR SECTION IF NOT
  2538.     MVI    A,00H            ;CLEAR (A)
  2539.     STA    POINTR2            ;POINTR2=0
  2540.     RET                ;DONE WITH SUCCESSFUL WRITE
  2541. FULLXIT    MVI    C,09D            ;SELECT PRINT FUNCTION
  2542.     LXI    D,NOROOM        ;PASS ERROR MESSAGE
  2543.     CALL    FDOS            ;PRINT IT
  2544. ;
  2545.     JMP    BOOT            ;TERMINATE WITH WARM START
  2546. ;
  2547. ;-----------------------------------------------------------------------
  2548. ;
  2549. ;    THIS SUBROUTINE IS USED FOR NON-STANDARD EXTENSIONS TO PLOT
  2550. ;
  2551. ;    INPUTS:
  2552. ;        NONE
  2553. ;    OUTPUTS:
  2554. ;        NONE
  2555. ;    REGSISTER STATUS:
  2556. ;        ALL VALUES PRESERVED
  2557. ;    ERROR CONDITIONS:
  2558. ;        NONE
  2559. ;
  2560. XTEND:    PUSH    PSW
  2561.     PUSH    B
  2562.     PUSH    D
  2563.     PUSH    H
  2564. ;
  2565.     CALL    BYTE        ;GET LOW BYTE OF NUMBER OF DATA BYTES
  2566.     MOV    A,C
  2567.     CALL    BYTE        ;GET HIGH BYTE OF NUMBER OF BYTES
  2568.     MOV    A,B        ;[BC] IS NOW 16 BIT INTEGER
  2569.     ORA    C        ;IS NUMBER = 0?
  2570.     JZ    XTND2        ;FINISHED IF N = 0
  2571. XTND1:    CALL    BYTE        ;GET DATA BYTE
  2572.     DCX    B        ;DECREMENT COUNTER
  2573.     MOV    A,C
  2574.     ORA    B        ;IS COUNTER = 0 ?
  2575.     JNZ    XTND1        ;LOOP BACK IF MORE TO COME
  2576. XTND2:    POP    H        ;RESTORE REGISTERS
  2577.     POP    D
  2578.     POP    B
  2579.     POP    PSW
  2580.     RET            ;FINISHED
  2581. ;
  2582. ;-----------------------------------------------------------------------
  2583. ;
  2584. ORIGIN                    ;START OF PICTURE MAP
  2585. ;
  2586. ;-----------------------------------------------------------------------
  2587.