home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / BEEHIVE / UTILITYS / PLOTBEE.ARC / PLOT33S.Z80 < prev    next >
Text File  |  1991-02-10  |  93KB  |  3,420 lines

  1.     .z80
  2.     aseg
  3. ;-----------------------------------------------------------------------
  4. ;            program plot
  5. ;-----------------------------------------------------------------------
  6. ;
  7. ;this program reads a sequential plot command file, makes a memory image
  8. ;of the plot, and prints the plot on the printer
  9. ;
  10. ;    copyright (c) 1984 by thomas e. speer. all rights reserved
  11. ;                          887 briddlewood ln.
  12. ;                          dayton, ohio  45430
  13. ;    this program is released to the public domain for 
  14. ;    non-commercial use only.
  15. ;
  16. ;
  17. ;revision history
  18. ;
  19. ;    version 3.3bs    14th Sep 90     P. de Lacey
  20. ;    extra code added for screen output for Microbee (Premium or later)
  21. ;
  22. ;    version 3.3    31 jul 84    t. speer
  23. ;    fixed bug in oki version of preset routine.  extraneous exit
  24. ;    graphics command was being sent.  
  25. ;
  26. ;    version 3.3     7 jul 84    t. speer
  27. ;    added text comand.  added quit to properly close output file.
  28. ;    modified gbufout to skip totally blank lines.
  29. ;
  30. ;    version 3.2b    27 jun 84    t. speer
  31. ;    cross hatched color patterns fine tuned.  added blinking 
  32. ;    status message.  special patterns corrected.  all subroutines
  33. ;    placed in alphabetical order.
  34. ;
  35. ;    version 3.2a    18 jun 84    t. speer
  36. ;    color patterns changed.  15 special patterns added from
  37. ;    49 to 63.  these make it easier to match patterns from
  38. ;    other systems.  the default patterns supplied are the same
  39. ;    as used for nmos and cmos vlsi cif plots.
  40. ;
  41. ;    version 3.2    28 mar 84    t. speer
  42. ;    citoh modifications debugged. ids mods removed (same as oki)
  43. ;    base2 mods removed (untested- not suitable for release)
  44. ;
  45. ;    version 3.2    3 feb 84    t. speer
  46. ;    this version adds the patterned erase, the upload (color 
  47. ;    codes), and extend commands.
  48. ;
  49. ;    version 3.1    10 dec 83    t. speer
  50. ;    added pattern fills and lines using a cross-hatched method and
  51. ;    an ordered dither matrix method.
  52. ;
  53. ;    version 3.0    5 nov 83    t. speer
  54. ;    this version reads all x and y coordinates as 
  55. ;    2 byte fixed point numbers (16 bit signed values between 0 and 1)
  56. ;
  57. ;    coordinates must be between 0.0 and 1.0 to lie on plot.  this 
  58. ;    makes the plot device independent.  the fixed point values are easily
  59. ;    created by the high level program by multiplying the coordinates by
  60. ;    32767 and truncating to an integer.
  61. ;
  62. ;    version 2.0            t. speer
  63. ;    this version used 32 bit floating point integers with a fortran
  64. ;    routine patched in to do the conversion to integer raster coord.
  65. ;
  66. ;    version 1.0            t. speer
  67. ;    this version used 16 bit integer coordinates that were tied to
  68. ;    the epson mx-80 resolution.  no conversion was required.
  69. ;
  70. ;-----------------------------------------------------------------------
  71. ;
  72.     org    100h        ;beginning of tpa
  73.     ld    c,09h        ;select print function
  74.     ld    de,banner    ;print banner message
  75.     call    fdos
  76. ;
  77.     jp    entry        ;jump around variable storage area
  78. banner:    defb    '         plot version 3.3  31/7/84',0dh,0ah
  79.     defb    '            (c) by t. e. speer',0dh,0ah,0ah,'$'
  80.     defb    '           all rights reserved',0dh,0ah,0dh,0ah,'$'
  81. ;
  82. ;
  83. ;
  84. ;========================= printer flags ==================================
  85. ;set the one that matches your printer to true, and set the others to false.
  86. ;
  87.     true    equ    0ffffh
  88.     false    equ    not true
  89. epson    equ    false        ;flag for epson mx-80 with graphtrax
  90. citoh    equ    false        ;flag for citoh, prowriter, etc 
  91. oki    equ    false        ;flag for okidata
  92. screen    equ    true
  93. ;ids        set oki   flag to true- ids printers act same as oki
  94. ;gemini    10    set epson flag to true- gemini 10 acts same as epson
  95. ;nec        set citoh flag to true- nec       acts same as citoh
  96. ;apple dot matrix - acts same as citoh, but some <esc> sequences differ.
  97. ;        set citoh flag to true and check <esc> sequences at esck,
  98. ;        and in ln772 and preset subroutines.
  99. ;
  100. ;====================== printer parameters ===============================
  101. ; this section sets the specific constants for your printer.
  102. ;
  103. ;***** note ***** the maximum value for maxx that can be used is 1530.
  104. ; the maximum value for maxy that can be used is 1785. these limits 
  105. ; are required to avoid arithmetic overflows.
  106. ; the size of the map ( (maxx+1)*(maxy+1)/7 ) must fit between the end of
  107. ; the program and the end of the tpa.
  108. ;
  109. ;    printers seem to have two basic methods of going into graphics
  110. ; mode.  the epson and citoh printers use an <esc> sequence 
  111. ; followed by a specified number of graphics bytes.  the okidata and ids
  112. ; printers use an <etx> to toggle into graphics mode, and then remain
  113. ; in graphics until an <etx><so> is received.  
  114. ;      the basic philosophy adopted here is to append the <esc> 
  115. ; sequence and the number of bytes (if required) to the head of the 
  116. ; graphics output buffer for those printers in the first group. printers 
  117. ; in the second group are handled by putting the <etx> commands in the 
  118. ; gbufout routine.  all printers are kept in normal text mode, except
  119. ; when actually printing graphics.
  120. ;
  121.     if    epson
  122. maxx    equ    559        ;set maximum width to dp100 low res mode
  123. maxy    equ    503        ;set maximum height to make square plot
  124. mapsize    equ    40320d        ;total size of map
  125. cwidth    equ    6        ;raster width of a printed character
  126. no8bit    equ    false        ;set to false if your interface can
  127. msbtop    equ    true        ;most sig. bit is top of stroke
  128. ;    set up graphic output buffer area
  129. esck:    defb    1bh,'k'        ;define esc "k" character sequence
  130. ngraph:    defw    0000h        ;initialize graphic counter
  131. gbuff:    defs    maxx+1        ;set aside area for graphic o/p buffer
  132.     endif            ;(epson)
  133. ;
  134.     if    citoh
  135. maxx    equ    636        ;set maximum width for 80 dots/inch mode
  136. maxy    equ    573        ;set maximum height to make square plot
  137. mapsize    equ    52234d        ;total size of map
  138. cwidth    equ    8        ;raster width of a printed character
  139. no8bit    equ    false        ;set to false even if 7 bit interface
  140. msbtop    equ    false        ;least sig. bit is top dot of stroke
  141. ;    set up graphic output buffer area
  142. esck:    defb    1bh,'s',0,0,0,0    ;graphic mode select code
  143. gbuff:    defs    maxx+1        ;set aside area for graphic o/p buffer
  144. ngraph:    defw    0000h        ;initialize graphic counter
  145.     endif            ;(citoh)
  146. ;
  147.     if    oki
  148. maxx    equ    575        ;set maximum width for 72 dots/inch
  149. maxy    equ    573        ;set maximum height to make square plot
  150. mapsize    equ    47232d        ;total size of map
  151. cwidth    equ    6        ;raster width of character
  152. no8bit    equ    false        ;should be false even if 7 bit interface
  153. msbtop    equ    false        ;least sig. bit is top dot of stroke
  154. ;    set up graphic output buffer area
  155. gbuff:    defs    maxx+1
  156. ngraph:    defw    0000h
  157.     endif            ;(oki)
  158. ;
  159.     if    screen
  160. maxx    equ    433        ;set maximum width
  161. maxy    equ    251        ;set maximum height to make square plot
  162. mapsize    equ    15624        ;total size of map
  163. cwidth    equ    8        ;raster width of a printed character
  164. no8bit    equ    false        ;set to false if your interface can
  165. msbtop    equ    true        ;most sig. bit is top of stroke
  166. ;    set up graphic output buffer area
  167. margin    equ    42D
  168. xcoord:    defw    margin
  169. ycoord:    defw    0000h
  170. ngraph:    defw    0000h        ;initialize graphic counter
  171. gbuff:    defs    maxx+1        ;set aside area for graphic o/p buffer
  172.     endif            ;(screen)
  173. ;
  174. ;========================= data storage section ============================
  175. ;
  176. color:    defb    0
  177. xpos:    defw    0
  178. ypos:    defw    0
  179. x:    defw    0
  180. y:    defw    0
  181. yfill:    defw    0
  182. nchar:    defw    0
  183. achar:    defb    40h
  184. pointer:    defb    128d    ;pointer in file buffer
  185. pointr2:    defb    00h    ;pointer in output file buffer
  186. oldstk:    defw    0000h
  187. stack:    defs    80h        ;set aside 128 level stack
  188. xdot:    defw    0000h        ;position of dot to be plotted
  189. ydot:    defw    0000h        ;position of dot to be plotted
  190. xyaddr:    defw    origin        ;address of x,y location
  191. xybit:    defb    00h        ;bit in byte @ xyaddr for x,y
  192. divdnd:    defw    0000h        ;2 byte dividend in divide
  193. divsor:    defb    00h        ;1 byte divisor in divide
  194. qotent:    defb    00h        ;1 byte quotient from divide
  195. rmandr:    defb    00h        ;1 byte remainder from divide
  196. blank    equ    ' '
  197. nospec:    defb    'no file specified',0dh,0ah,'$';error messages
  198. nofile:    defb    'file not found',0dh,0ah,'$'
  199. eofmsg:    defb    'end of file',0dh,0ah,'$'
  200. nodir:    defb    'no directory space available',0dh,0ah,'$'
  201. noroom:    defb    'disk is full',0dh,0ah,'$' 
  202. unknch:    defb    'undefined command character encountered',0dh,0ah,'$'
  203. stat1:    defb    '           working ...              ',0dh,'$'
  204. stat2:    defb    '                   ... working      ',0dh,'$'
  205. stat3:    defb    '           printing picture         ',07h,0dh,'$'
  206. statno:    defb    00h
  207. deltax:    defw    0000h        ;local variables for incplt
  208. deltay:    defw    0000h        ;local variables for incplt
  209. epslnx:    defw    0000h        ;local variables for incplt
  210. epslny:    defw    0000h        ;local variables for incplt
  211. sx:    defw    0000h        ;local variables for incplt
  212. sy:    defw    0000h        ;local variables for incplt
  213. delta3:    defw    0000h        ;local variables for incplt
  214. ni:    defw    0000h        ;local variables for incplt
  215. ;
  216. cmask:    defb    0ffh        ;color mask
  217. patrn:    defs    8        ;cell storage for clrmap (erase)
  218. plaids:    defb    00h,01h,71h,13h,05h,0fh,35h,11h; cross hatched patterns
  219. ;
  220. cifpat:    defb    00h, 03h, 48h, 03h, 00h, 30h, 84h, 30h;nd
  221.     defb    00h,0cch, 00h,0cch, 00h, 00h, 00h, 00h;ni  s
  222.     defb    08h, 04h, 02h, 01h, 80h, 40h, 20h, 10h;nt   p
  223.     defb    11h, 30h, 71h, 30h, 11h, 03h, 17h, 03h;nc    e
  224.     defb    22h, 00h, 88h, 00h, 22h, 00h, 88h, 00h;nm     c
  225.     defb    0c0h, 81h, 03h, 06h, 03h, 81h,0c0h, 60h;nb  p   i
  226.     defb    1ch, 3eh, 36h, 3eh, 1ch, 00h, 00h, 00h;ng   a   a
  227.     defb    8fh, 88h, 88h, 88h,0f8h, 88h, 88h, 88h;cw    t   l
  228.     defb    04h, 11h, 04h, 00h, 40h, 11h, 40h, 00h;cd     t
  229.     defb    02h, 04h, 08h, 10h, 20h, 40h, 80h, 01h;cp      e
  230.     defb    00h, 00h, 10h, 38h, 10h, 00h, 00h, 00h;cs       r
  231.     defb    66h, 99h, 99h, 66h, 66h, 99h, 99h, 66h;cc        n
  232.     defb    00h, 00h, 80h, 10h, 00h, 00h, 10h, 80h;cm         s
  233.     defb    81h,0c3h, 66h, 66h,0c3h, 81h, 00h, 00h;cg
  234.     defb    0fh, 0eh, 0ch, 08h, 00h, 00h, 00h, 00h;ce
  235. ;
  236. ditharr:    defb    63,  95,  71, 103,  65,  97,  73, 105;     ordered
  237.     defb    111,  79, 119,  87, 113,  81, 121,  89; 
  238.     defb    75, 107,  67,  99,  77, 109,  69, 101;     dither
  239.     defb    123,  91, 115,  83, 125,  93, 117,  85; 
  240.     defb    66,  98,  74, 106,  64,  96,  72, 104;     matrix
  241.     defb    114,  82, 122,  90, 112,  80, 120,  88; 
  242.     defb    78, 110,  70, 102,  76, 108,  68, 100; 
  243.     defb    126,  94, 118,  86, 124,  92, 116,  84; 
  244. ;
  245. ;
  246. ;
  247. ;
  248. boot    equ    0000h        ;cp/m system entry point
  249. fcb    equ    boot+005ch    ;location of file control block
  250. dma    equ    boot+0080h    ;file buffer address
  251. fdos    equ    boot+0005h    ;entry point for cpm functions
  252. fcb2:    defs    33d        ;output file control block
  253. dma2:    defs    128d        ;output file buffer
  254. opdisk:    defb    00h        ;output to disk flag
  255. ;
  256. ;-----------------------------------------------------------------------
  257. ;
  258. entry:    ld    sp,stack+80h    ;set new 128 level stack
  259.     ld    a,(fcb+9)    ;get first character of file type
  260.     cp    blank        ;is type blank?
  261.     jp    nz,name        ;no- type has been specified
  262.     ld    a,'V'        ;make default type "vec"
  263.     ld    (fcb+9),a    ;store default in file type area
  264.     ld    a,'E'
  265.     ld    (fcb+10),a    ;store default in file type area
  266.     ld    a,'C'
  267.     ld    (fcb+11),a    ;done- default is set
  268. name:    ld    a,(fcb+1)    ;get first char from fcb
  269.     cp    blank        ;is name blank?
  270.     jp    nz,openop    ;jump if a file name exists
  271.     ld    c,09h        ;select print string function
  272.     ld    de,nospec    ;pass error message
  273.     call    fdos        ;print it
  274.     jp    boot        ;return to cpm system level
  275. openop:    ld    a,(fcb+17d)    ;get 1st char of o/p file
  276.     cp    blank        ;is name blank?
  277.     jp    z,openfil    ;blank= normal print output
  278.     ld    a,01h        ;set o/p file flag=1 (disk o/p)
  279.     ld    (opdisk),a    ;store flag
  280. ;
  281. ;    move o/p file name to new fcb
  282. ;
  283.     ld    c,16d        ;half of fcb#1 is o/p info
  284.     ld    de,006ch    ;start of o/p file name
  285.     ld    hl,fcb2        ;set destination address
  286. movfcb:    ld    a,(de)        ;get name character
  287.     ld    (hl),a        ;store name character
  288.     inc    de        ;increment old name address
  289.     inc    hl        ;increment new name address
  290.     dec    c        ;decrement counter
  291.     jp    nz,movfcb    ;loop back if not done
  292. ;
  293.     ld    a,0        ;clear accumulator
  294.     ld    (fcb2+32d),a    ;zero cr field in o/p fcb
  295. ;
  296.     ld    a,(fcb2+9)    ;get 1st char in o/p file type
  297.     cp    blank        ;is file type blank?
  298.     jp    nz,delete    ;not blank- go to delelte old
  299.     ld    a,'P'        ;make default 'plt'
  300.     ld    (fcb2+9),a    ;store default 'p'
  301.     ld    a,'L'
  302.     ld    (fcb2+10),a    ;store default 'l'
  303.     ld    a,'T'
  304.     ld    (fcb2+11),a    ;store default 't'
  305. ;
  306. delete:    ld    de,fcb2        ;pass o/p file fcb
  307.     ld    c,19d        ;select delete function
  308.     call    fdos        ;delete old file
  309. ;
  310. ;    make new o/p file
  311. ;
  312.     ld    c,26d        ;select set dma function
  313.     ld    de,dma2        ;pass o/p file buffer address
  314.     call    fdos        ;set dma address
  315. ;
  316.     ld    c,22d        ;select make file function
  317.     ld    de,fcb2        ;pass fcb for o/p
  318.     call    fdos        ;make new file
  319.     cp    0ffh        ;is directory full?
  320.     jp    nz,openfil    ;no- go on with program
  321. ;
  322.     ld    c,09h        ;select print function
  323.     ld    de,nodir    ;pass no directory space msg
  324.     call    fdos        ;print error message
  325.     jp    boot        ;fatal error- quit
  326. ;
  327. ;open disk file of plot commands
  328. ;
  329. openfil:    ld    c,26d    ;select set dma function
  330.     ld    de,dma        ;pass i/p buffer location
  331.     call    fdos        ;set dma to i/p buffer
  332. ;
  333.     ld    c,0fh        ;select open file funcion
  334.     ld    a,00h        ;clear accumulator
  335.     ld    (fcb+12),a    ;clear extent counter
  336.     ld    (fcb+14),a    ;clear s2 parameter in fcb
  337.     ld    de,fcb        ;pass fcb
  338.     call    fdos        ;open file
  339.     cp    0ffh        ;was file found?
  340.     jp    nz,rewind    ;if file exits, rewind it
  341.     ld    c,09h        ;select print function
  342.     ld    de,nofile    ;pass message
  343.     call    fdos        ;print it
  344.     jp    boot        ;return to cpm command level
  345. ;
  346. rewind:    ld    a,00h        ;clear accumulator
  347.     ld    (fcb+32d),a    ;rewind by setting record#=0
  348. ;
  349. parse:    call    byte        ;get command character
  350.     cp    60h        ;is it lower case?
  351.     jp    c,parse0    ;no, so skip shifting it
  352.     xor    00100000b    ;shift character to upper case
  353. ;
  354. parse0:    cp    'P'        ;is it a "p"?
  355.     push    af        ;save command character
  356.     call    z,point        ;p commands plot point
  357.     pop    af
  358.     jp    z,parse        ;loop back for new char
  359. ;
  360.     call    stat        ;display status message
  361. ;
  362. ;
  363.     cp    'C'
  364.     push    af
  365.     call    z,colour    ;c commands set color
  366.     pop    af
  367.     jp    z,parse        ;loop back for new char
  368. ;
  369.     cp    'D'        ;is it a "d"?
  370.     push    af        ;save command character
  371.     call    z,plotseg    ;d commands plot segment
  372.     pop    af
  373.     jp    z,parse        ;loop back for new char
  374. ;
  375.     cp    'E'
  376.     push    af
  377.     call    z,clrmap    ;e commands clear memory map to color
  378.     pop    af
  379.     jp    z,parse        ;loop back for new char
  380. ;
  381.     cp    'F'
  382.     push    af
  383.     call    z,fill        ;f commands fill area to color
  384.     pop    af
  385.     jp    z,parse        ;loop back for new character
  386. ;
  387.     cp    'I'
  388.     push    af
  389.     call    z,incplt    ;i commands plot incremental segment
  390.     pop    af
  391.     jp    z,parse        ;loop back for new char
  392. ;
  393.     cp    'M'        ;m commands move to coord w/o plotting
  394.     push    af
  395.     call    z,move
  396.     pop    af
  397.     jp    z,parse
  398. ;
  399.     cp    'N'
  400.     jp    z,parse        ;n commands a no operation loop
  401. ;
  402.     cp    'O'
  403.     push    af
  404.     call    z,mapout    ;o commands printing of plot
  405.     pop    af
  406.     jp    z,parse        ;loop back for new char
  407. ;
  408.     cp    'Q'
  409.     push    af
  410.     call    z,quit        ;q commands termination of program
  411.     pop    af
  412.     jp    z,parse        ;loop back for new char
  413. ;
  414.     cp    'S'
  415.     push    af
  416.     call    z,string    ;s commands character string plotting
  417.     pop    af
  418.     jp    z,parse        ;loop back for new char
  419. ;
  420.     cp    'T'
  421.     push    af
  422.     call    z,text        ;t commands raw text output
  423.     pop    af
  424.     jp    z,parse        ;loop back for new char
  425. ;
  426.     cp    'U'
  427.     push    af
  428.     call    z,upload    ;u commands upload of color paterns
  429.     pop    af
  430.     jp    z,parse        ;loop back for new char
  431. ;
  432.     cp    'X'
  433.     push    af
  434.     call    z,xtend        ;provision for non-standard commands
  435.     pop    af
  436.     jp    z,parse        ;loop back for new char
  437. ;
  438.     cp    0dh        ;ignore carriage returns
  439.     jp    z,parse
  440. ;
  441.     cp    0ah
  442.     jp    z,parse        ;ignore line feeds
  443. ;
  444. ;    command character does not match any defined command
  445. ;
  446.     ld    c,09h        ;select print string function
  447.     ld    de,unknch    ;pass undefined character message
  448.     call    fdos        ;print it
  449.     jp    parse        ;loop up to top to get new character
  450. ;
  451. ;-----------------------------------------------------------------------
  452. ;                 define subroutines
  453. ;-----------------------------------------------------------------------
  454. ;
  455. ;    convert binary integer to decimal ascii number
  456. ;
  457. ;    inputs:
  458. ;        n (binary number) in [de]
  459. ;        address to store low digit in [hl]
  460. ;    outputs:
  461. ;        ascii number stored in memory, high byte first.
  462. ;             note: the address is decremented for each char.
  463. ;    register status:
  464. ;        all register values preserved
  465. ;    error conditions:
  466. ;        none
  467. ;
  468.     if    citoh
  469. bindec:    push    hl        ;save registers
  470.     push    de
  471.     push    bc
  472.     push    af
  473. ;
  474.     ld    a,10d        ;get a ten
  475.     ld    (divsor),a    ;divisions will be by base 10
  476. ;
  477. bdeclp:    push    hl        ;save address for future use
  478.     ld    a,d
  479.     ld    (divdnd),a    ;first divide high byte
  480.     ld    a,00h
  481.     ld    (divdnd+1),a    ;16 bit dividend now = 8 bit n high byte
  482.     call    divide        ;divide by 10
  483.     ld    a,(qotent)
  484.     ld    d,a        ;result is high byte of new n
  485.     ld    hl,rmandr
  486.     ld    h,(hl)        ;divide remainder with low byte of n
  487.     ld    l,e        ;add low byte of n to remainder
  488.     ld    (divdnd),hl
  489.     call    divide        ;divide low bytes by 10
  490.     pop    hl        ;retrieve address to receive character
  491.     ld    a,(rmandr)    ;remainder is digit
  492.     add    a,30h        ;convert digit to ascii
  493.     ld    (hl),a        ;store character
  494.     dec    hl        ;move pointer left
  495.     ld    a,(qotent)    ;get result of division
  496.     ld    e,a        ;result is low byte of new n
  497.     or    d        ;is new end = 0?
  498.     jp    nz,bdeclp    ;loop back up if > 0
  499. ;
  500.     pop    af
  501.     pop    bc
  502.     pop    de
  503.     pop    hl        ;registers restored
  504.     ret    
  505.     endif            ;(citoh)
  506. ;----------------------------------------------------------------------
  507. ;
  508. ;    bmult performs a 1-byte by 2-byte multiply
  509. ;
  510. ;    this routine is from electronics magazine, feb 24, 1982.
  511. ;    by jerry l. goodrich, penn. state u.
  512. ;
  513. ;    inputs:
  514. ;        8-bit number in [a]
  515. ;        16-bit number in [bc]
  516. ;    outputs:
  517. ;        product in [a],[hl] (high byte in [a])
  518. ;    register status:
  519. ;        see inputs and outputs
  520. ;    error conditions:
  521. ;        none
  522. ;
  523. bmult:    ld    hl,0        ;zero partial product
  524.     ld    de,7        ;d=0,e=bit counter
  525.     add    a,a        ;get first multiplier bit
  526. loop1:    jp    nc,zero        ;zero skip
  527.     add    hl,bc        ;one-add multiplicand
  528.     adc    a,d        ;add carry to third byte of product
  529. zero:    add    hl,hl        ;shift product left
  530.     adc    a,a
  531.     dec    e        ;decrement bit counter
  532.     jp    nz,loop1    ;loop until done
  533.     ret    nc        ;done if no carry
  534.     add    hl,bc        ;otherwise do last add
  535.     adc    a,d
  536.     ret            ;and return
  537. ;-----------------------------------------------------------------------
  538. ;    byte gets next byte in buffer
  539. ;    next record is read if need be
  540. ;    inputs:
  541. ;        128 character buffer @ dma
  542. ;        character pointer @ pointer which is set @ last position
  543. ;    outputs:
  544. ;        new byte in accumulator
  545. ;    register status:
  546. ;        [bc],[de],[hl] registers preserved
  547. ;    error conditions:
  548. ;        none- if pointer exceeds 128, new record is read
  549. ;
  550. byte:    push    bc        ;save registers
  551.     push    de
  552.     push    hl
  553. ;
  554.     ld    a,(pointer)    ;get pointer value
  555.     cp    128d        ;is pointer=128?
  556.     call    z,read        ;get record if last one was #128
  557.     ld    a,(pointer)    ;get new pointer value
  558.     inc    a        ;increment pointer value
  559.     ld    (pointer),a    ;store new pointer value
  560.     ld    c,a        ;save pointer value in c
  561.     ld    b,0        ;make bc=c
  562.     ld    hl,dma-1    ;load hl with byte before dma 
  563.     add    hl,bc        ;calculate addr of desired byte
  564.     ld    a,(hl)        ;get byte
  565. ;
  566.     pop    hl        ;restore registers
  567.     pop    de
  568.     pop    bc
  569.     ret            ;done-- byte is in accum.
  570. ;-----------------------------------------------------------------------
  571. ;
  572. ;    printed character output
  573. ;
  574. ;    inputs:
  575. ;        character in register [a]
  576. ;
  577. ;    outputs:
  578. ;        graphic buffer is flushed
  579. ;        character is put out to printer
  580. ;        address in [hl] is incremented by (cwidth - 1)
  581. ;        dot counter incremented by (cwidth - 1)
  582. ;        the above are to account for the size of a character
  583. ;        as opposed to a single dot
  584. ;    register status:
  585. ;        [a,psw],[bc] preserved
  586. ;        [de] decremented by (cwidth -1)
  587. ;        [hl] incremented by (cwidth -1)
  588. ;    error conditions:
  589. ;        none
  590. ;
  591. charout:    push    af    ;save registers
  592.     push    bc
  593.     push    de
  594.     push    hl
  595. ;
  596.     xor    10000000b    ;clear high bit of character
  597.     call    gbufout        ;flush graphic buffer
  598.     ld    c,05h        ;select list output
  599.     ld    e,a        ;pass character
  600.     call    pdos        ;send character to printer
  601. ;
  602.     pop    hl        ;recall registers
  603.     pop    de
  604.     ld    a,cwidth-1
  605. charo1:    inc    hl        ;increment address
  606.     dec    de        ;decrement dot counter
  607.     sub    1        ;decrement loop counter
  608.     jp    nz,charo1
  609. ;
  610.     pop    bc
  611.     pop    af
  612.     ret    
  613. ;
  614. ;-----------------------------------------------------------------------
  615. ;
  616. ;    clear memory subroutine
  617. ;
  618. ;    inputs:
  619. ;        bitmap of size mapsize located at origin
  620. ;        map color stored in color
  621. ;        (pos = patterned, 0 = white, - = complementary)
  622. ;    outputs:
  623. ;        entire map area set to desired color or pattern
  624. ;    registers:
  625. ;        all register values destroyed
  626. ;    error conditions:
  627. ;        none
  628. ;
  629. clrmap:    ld    a,(color)    ;get color
  630.     or    a        ;set flage according to color
  631.     jp    nz,clrnz    ;is color non-white?
  632.     ld    de,mapsize    ;put mapsize in [de] as counter
  633.     ld    hl,origin    ;put start of map in [hl]
  634.     ld    c,00h        ;c contains image of white byte
  635. clrlp1:    ld    (hl),c        ;top of loop, store byte
  636.     inc    hl        ;increment address in map
  637.     dec    de        ;decrement loop counter
  638.     ld    a,d        ;move high byte of count. to [a]
  639.     or    e        ;check for 0 counter
  640.     jp    nz,clrlp1    ;loop until done
  641.     ret            ;finished with white erase
  642. ;
  643. clrnz:    push    af        ;save flag values
  644. ;    now form 8 byte color pattern
  645.     ld    hl,patrn+7    ;point to last in pattern sequence
  646.     ld    c,07h        ;initialize x counter
  647. clrlp2:    ld    d,80h        ;set up y bit select
  648.     ld    e,07h        ;initialize y counter
  649.     ld    b,00h        ;initialize pattern
  650. clrlp3:    call    clrmsk        ;form color mask based on x,y
  651.     ld    a,(cmask)    ;get mask
  652.     and    d        ;select one bit
  653.     or    b        ;add bit to pattern
  654.     ld    b,a        ;save new pattern
  655.     ld    a,d        ;modify bit select mask
  656.     rrca            ;move select bit down one notch
  657.     ld    d,a        ;save new bit select
  658.     dec    e        ;decrement y counter
  659.     jp    p,clrlp3    ;jump back if not negative (need 0 pass)
  660.     pop    af        ;retrieve color code flag settings
  661.     push    af        ;re-save flags settings
  662.     jp    p,clrl31    ;positive flag means pattern is ok
  663.     ld    a,b        ;get pattern
  664.     cpl            ;complement pattern for negative colors
  665.     ld    b,a        ;store pattern byte
  666. clrl31:    ld    (hl),b        ;save pattern for this x location
  667.     dec    hl        ;move memory pointer over
  668.     dec    c        ;decrement x coordinate/counter
  669.     jp    p,clrlp2    ;only done when negative (need 0 pass)
  670. ;
  671. ;    set up for clearing memory
  672. ;    rotate array of pattenrx down to match
  673. ;
  674.     ld    bc,(maxy+1) mod 8+1;counter for rotations due to mismatch
  675. clrlp4:    call    rotpat        ;rotate pattern array 1 position
  676.     dec    c        ;decrement counter
  677.     jp    nz,clrlp4    ;loop back if not done
  678. ;
  679.     ld    hl,origin    ;set map pointer to start of map
  680.     ld    bc,(maxy+1)/7    ;initialize line counter
  681. clrlp5:    ld    de,(maxx+1)/8    ;initalize dot counter
  682. clrl51:    ld    a,(patrn)    ;get first byte
  683.     and    7fh        ;clear hi bit
  684.     ld    (hl),a        ;store pattern in memory map
  685.     inc    hl        ;move memory pointer
  686.     ld    a,(patrn+1)    ;get second byte
  687.     and    7fh        ;clear hi bit
  688.     ld    (hl),a        ;store pattern in memory map
  689.     inc    hl        ;move memory pointer
  690.     ld    a,(patrn+2)
  691.     and    7fh        ;clear hi bit
  692.     ld    (hl),a        ;store pattern in memory map
  693.     inc    hl        ;move memory pointer
  694.     ld    a,(patrn+3)
  695.     and    7fh        ;clear hi bit
  696.     ld    (hl),a        ;store pattern in memory map
  697.     inc    hl        ;move memory pointer
  698.     ld    a,(patrn+4)
  699.     and    7fh        ;clear hi bit
  700.     ld    (hl),a        ;store pattern in memory map
  701.     inc    hl        ;move memory pointer
  702.     ld    a,(patrn+5)
  703.     and    7fh        ;clear hi bit
  704.     ld    (hl),a        ;store pattern in memory map
  705.     inc    hl        ;move memory pointer
  706.     ld    a,(patrn+6)
  707.     and    7fh        ;clear hi bit
  708.     ld    (hl),a        ;store pattern in memory map
  709.     inc    hl        ;move memory pointer
  710.     ld    a,(patrn+7)
  711.     and    7fh        ;clear hi bit
  712.     ld    (hl),a        ;store pattern in memory map
  713.     inc    hl        ;move memory pointer
  714.     dec    de        ;decrement x counter
  715.     ld    a,e
  716.     or    d        ;is counter zero?
  717.     jp    nz,clrl51    ;loop back until done
  718. ;
  719.     ld    de,(maxx+1)mod 8;set counter for rest of line
  720.     ld    a,d        ;check to see if linesize id mult of 8
  721.     or    e        ;was mod 8 =0?
  722.     jp    z,clrlp6    ;jump to bottom of loop if finished
  723.     ld    a,(patrn)    ;apply pattern to remaning 1-7 bytes
  724.     and    7fh        ;clear hi bit
  725.     ld    (hl),a        ;store pattern in memory map
  726.     inc    hl        ;move memory pointer
  727.     dec    de        ;decrement line length counter
  728.     ld    a,e
  729.     or    d        ;is counter = 0?
  730.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  731.     ld    a,(patrn+1)    ;continue with next pattern byte
  732.     and    7fh        ;clear hi bit
  733.     ld    (hl),a        ;store pattern in memory map
  734.     inc    hl        ;move memory pointer
  735.     dec    de        ;decrement line length counter
  736.     ld    a,e
  737.     or    d        ;is counter = 0?
  738.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  739.     ld    a,(patrn+2)    ;continue with next pattern byte
  740.     and    7fh        ;clear hi bit
  741.     ld    (hl),a        ;store pattern in memory map
  742.     inc    hl        ;move memory pointer
  743.     dec    de        ;decrement line length counter
  744.     ld    a,e
  745.     or    d        ;is counter = 0?
  746.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  747.     ld    a,(patrn+3)    ;continue with next pattern byte
  748.     and    7fh        ;clear hi bit
  749.     ld    (hl),a        ;store pattern in memory map
  750.     inc    hl        ;move memory pointer
  751.     dec    de        ;decrement line length counter
  752.     ld    a,e
  753.     or    d        ;is counter = 0?
  754.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  755.     ld    a,(patrn+4)    ;continue with next pattern byte
  756.     and    7fh        ;clear hi bit
  757.     ld    (hl),a        ;store pattern in memory map
  758.     inc    hl        ;move memory pointer
  759.     dec    de        ;decrement line length counter
  760.     ld    a,e
  761.     or    d        ;is counter = 0?
  762.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  763.     ld    a,(patrn+5)    ;continue with next pattern byte
  764.     and    7fh        ;clear hi bit
  765.     ld    (hl),a        ;store pattern in memory map
  766.     inc    hl        ;move memory pointer
  767.     dec    de        ;decrement line length counter
  768.     ld    a,e
  769.     or    d        ;is counter = 0?
  770.     jp    z,clrlp6    ;if finished, skip to bottom of outer lp
  771.     ld    a,(patrn+6)    ;continue with next pattern byte
  772.     and    7fh        ;clear hi bit
  773.     ld    (hl),a        ;store pattern in memory map
  774.     inc    hl        ;move memory pointer
  775. ;
  776. clrlp6:    call    rotpat        ;rotate pattern down to match cells
  777.     dec    bc        ;bottom of outer loop. dec line counter
  778.     ld    a,c
  779.     or    b        ;is counter = 0?
  780.     jp    nz,clrlp5    ;loop back up for another if req'd
  781. ;
  782.     pop    af        ;clean up stack
  783.     ret    
  784. ;
  785. ;-----------------------------------------------------------------------
  786. ;
  787. ;    color mask
  788. ;
  789. ;    this subroutine forms the color mask used in plotting points
  790. ;
  791. ;    method:
  792. ;        the plot is divided up into 8 x 8 raster cells.
  793. ;        for color values between 1 and 63, the cell is composed
  794. ;        of an x pattern and a y pattern which are xor'ed with
  795. ;        each other to form a "plaid" pattern
  796. ;        for color values 64 and above, ordered dithering is used
  797. ;        ordered dithering is a technique in which the dots in 
  798. ;        the cell are added in in a pre-arranged position based
  799. ;        upon the "intensitiy" of the cell.  the intersection of
  800. ;        the point and the pattern (stored in the array "ditharr"
  801. ;        determines whether or not the point is plotted
  802. ;
  803. ;        for both methods, a color mask is created, which is 
  804. ;        all 1's if the point in the pattern plane is on, or 
  805. ;        all 0's if the point in the pattern plane is off.
  806. ;    inputs:
  807. ;        x coordinate in bc
  808. ;        y coordinate in de
  809. ;    outputs:
  810. ;        color mask stored in cmask
  811. ;    register status:
  812. ;        all registers preserved
  813. ;    error conditions:
  814. ;        none
  815. ;
  816. clrmsk:    push    af        ;save registers
  817.     push    bc
  818.     push    de
  819.     push    hl
  820. ;
  821.     ld    a,c        ;form x cell coordinate
  822.     and    00000111b
  823.     ld    b,a
  824. ;
  825.     ld    a,e        ;form y cell coordinate
  826.     and    00000111b
  827.     ld    c,a
  828. ;
  829.     ld    a,(color)    ;get color code
  830.     or    a        ;set flags based on basic code
  831.     jp    z,whtmsk    ;zero color => white mask
  832.     jp    p,posclr    ;color code is positive
  833.     cpl            ;complement color
  834.     add    a,01h        ;color code is now positive
  835. posclr:    cp    64d        ;is color code < 64
  836.     jp    nc,dither    ;code >=64 --> dithered
  837.     cp    49d        ;is color code < 49
  838.     jp    nc,special    ;code from 49 to 63 --> cifpat's else plaid
  839. ;
  840.     push    af        ;save color code
  841.     and    07h        ;select lower 3 bits of color code
  842.     ld    hl,plaids    ;get base address of basic pattern
  843.     add    a,l        ;add x code to base addr to find pattern
  844.     ld    l,a
  845.     ld    a,h
  846.     adc    a,00h        ;add carry to high byte of address
  847.     ld    h,a
  848.     ld    a,(hl)        ;get x pattern for cell
  849.     inc    b        ;increment x coordinate to be counter
  850. xcellp:    rra            ;rotate pattern bit into carry
  851.     dec    b        ;decrement counter
  852.     jp    nz,xcellp    ;loop back if not done
  853.     ld    a,0ffh        ;carry --> pattern bit says plot point
  854.     jp    c,savxmsk        
  855.     ld    a,00h
  856. savxmsk:    ld    b,a    ;replace x cell coord with x color mask
  857. ;
  858.     pop    af        ;retrieve color code
  859.     and    38h        ;select 2nd 3 bits for y code
  860.     rrca            ;rotate bits to low order position
  861.     rrca    
  862.     rrca    
  863.     ld    hl,plaids    ;get base address of basic pattern
  864.     add    a,l        ;add x code to base addr to find pattern
  865.     ld    l,a
  866.     ld    a,h
  867.     adc    a,00h        ;add carry to high byte of address
  868.     ld    h,a
  869.     ld    a,(hl)        ;get y pattern for cell
  870.     inc    c        ;increment y coordinate to be counter
  871. ycellp:    rra            ;rotate pattern bit into carry
  872.     dec    c        ;decrement counter
  873.     jp    nz,ycellp    ;loop back if not done
  874.     ld    a,0ffh        ;dot will be plotted if carry set
  875.     jp    c,savymsk        
  876.     ld    a,00h
  877. savymsk:    xor    b    ;final color mask-- x patrn xor y patrn
  878.     ld    (cmask),a    ;save color mask
  879. ;
  880.     pop    hl        ;restore registers
  881.     pop    de
  882.     pop    bc
  883.     pop    af
  884.     ret            ;finished   -end of plaid branch
  885. ;
  886. dither:    push    af        ;save color code for future use
  887.     ld    a,c        ;multiply y cell coordinate by 8
  888.     rlca    
  889.     rlca    
  890.     rlca    
  891.     add    a,b        ;offset into dither table = y*8 + x
  892.     ld    hl,ditharr    ;get base address of table
  893.     add    a,l        ;add offset to base address
  894.     ld    l,a
  895.     ld    a,h
  896.     adc    a,00h        ;add carry to high byte
  897.     ld    h,a
  898.     ld    a,(hl)        ;get dither table value
  899.     pop    de        ;retrieve color code (formerly in [a])
  900.     cp    d        ;is dither value > color code?
  901.     ld    a,0ffh        ;carry--> plot point
  902.     jp    c,savmsk
  903.     ld    a,00h        ;carry not set--> don't plot point
  904. savmsk:    ld    (cmask),a    ;store mask for future use
  905. ;
  906.     pop    hl
  907.     pop    de
  908.     pop    bc
  909.     pop    af        ;registers restored, stack cleaned up
  910.     ret    
  911. ;
  912. ;
  913. special:    sub    49d    ;code is now relative to 49
  914.     rlca            ;code * 8
  915.     rlca    
  916.     rlca    
  917.     add    a,b        ;add x coord to form offset into array
  918.     ld    hl,cifpat    ;get fwa of pattern array
  919.     add    a,l        ;add offset to fwa
  920.     ld    l,a
  921.     ld    a,h
  922.     adc    a,00h        ;add carry to hi byte
  923.     ld    h,a        ;addition complete
  924.     ld    a,(hl)        ;get pattern byte for this x coord.
  925.     inc    c        ;increment y coord to form counter 
  926. spclp:    rra            ;rotate pattern bit into carry
  927.     dec    c        ;decrement counter
  928.     jp    nz,spclp    ;loop back until done
  929.     ld    a,0ffh        ;dot will be plotted if carry set
  930.     jp    c,savmsk
  931.     ld    a,00h        ;carry not set- don't plot point
  932.     jp    savmsk
  933. ;
  934. ;
  935. whtmsk:    ld    a,0ffh        ;for white, always modify dot
  936.     jp    savmsk        ;save mask and return
  937. ;
  938. ;-----------------------------------------------------------------------
  939. ;
  940. ;    define color subroutine
  941. ;
  942. ;    inputs:
  943. ;        buffer @ dma
  944. ;    outputs:
  945. ;        color value saved for future reference
  946. ;    register status:
  947. ;        all register values destroyed
  948. ;    error condtions:
  949. ;        none
  950. ;
  951. colour:    call    byte        ;get color value
  952.     ld    (color),a    ;save it
  953.     ret    
  954. ;
  955. ;-----------------------------------------------------------------------
  956. ;
  957. ;    this subroutine computes the next point in a line segment
  958. ;    must be used with seginit to initialize all variables first.
  959. ;
  960. ;    inputs:
  961. ;        ni    counter used by calling sub. to know when done.
  962. ;        xpos,ypos    present position
  963. ;        dx,dy    size of line segment along x,y axis
  964. ;        epslnx,epslny,sx,sy,delta3    local variables
  965. ;    register status:
  966. ;        all register values destroyed.
  967. ;    error conditions:
  968. ;        none peculiar to this routine
  969. ;
  970. compseg:    ld    hl,(ni)    ;get counter value
  971.     inc    hl        ;ni<dx- continue (first incr. ni)
  972.     ld    (ni),hl        ;store new ni value
  973.     ld    hl,(xpos)    ;get xpos & put in (bc)
  974.     ld    b,h        ;hi byte to (b)
  975.     ld    c,l        ;low byte to (c)
  976.     ld    hl,(ypos)    ;fetch ypos
  977.     ex    de,hl        ;put ypos in (de)
  978.     ld    hl,(epslnx)    ;fetch epsilon x
  979.     add    hl,bc        ;add epsilon x to x position
  980.     ld    (xpos),hl    ;store new value
  981.     ld    hl,(epslny)    ;fetch epsilon y
  982.     add    hl,de        ;add epsilon y to y position
  983.     ld    (ypos),hl    ;store new value of y position
  984.     ld    hl,(deltay)    ;fetch delta y
  985.     ex    de,hl        ;put deltay in (de)
  986.     ld    hl,(delta3)    ;fetch delta 3
  987.     add    hl,de        ;add delta y to delta 3
  988.     ld    (delta3),hl    ;store new value of delta3
  989.     ex    de,hl        ;put new value of delta 3 in (de)
  990.     ld    hl,(deltax)    ;fetch delta x
  991.     ld    a,h        ;continue if delta x < delta 3 
  992.     cp    d        ;otherwise plot point and loop
  993.     jp    c,cont2        ;hi bytes first- delta3 definitely >
  994.     jp    nz,dopt        ;dx > d3- plot point
  995.     ld    a,l        ;high bytes =: look @ low bytes
  996.     cp    e        ;now low bytes
  997.     jp    nc,dopt        ;d3<=dx: plot point
  998. cont2:    ld    a,e        ;compute d3=d3-dx 
  999.     sub    l        ;subtract low byte first
  1000.     ld    l,a        ;put low byte in position for store
  1001.     ld    a,d        ;now high byte of d3
  1002.     sbc    a,h        ;subtract high byte
  1003.     ld    h,a        ;put hi byte in position for store
  1004.     ld    (delta3),hl    ;store result
  1005.     ld    hl,(sx)        ;compute xpos=xpos+sx
  1006.     ex    de,hl        ;put sx in (de)
  1007.     ld    hl,(xpos)    ;fetch x position
  1008.     add    hl,de        ;add sx to xpos
  1009.     ld    (xpos),hl    ;store result
  1010.     ld    hl,(sy)        ;compute ypos=ypos+sy
  1011.     ex    de,hl        ;put sy in (de)
  1012.     ld    hl,(ypos)    ;fetch y position
  1013.     add    hl,de        ;add sy
  1014.     ld    (ypos),hl    ;store new y position
  1015. dopt:    ret            ;return so calling sub can use position.
  1016. ;
  1017. ;-----------------------------------------------------------------------
  1018. ;        carriage return routine
  1019. ;
  1020. ;    inputs:
  1021. ;        none
  1022. ;
  1023. ;    outputs:
  1024. ;        printer carriage is returned and paper advanced
  1025. ;
  1026. ;    register status:
  1027. ;        all values preserved
  1028. ;
  1029. ;    error conditions:
  1030. ;        none
  1031. ;
  1032. crlf:    push    af        ;save all registers
  1033.     push    bc
  1034.     push    de
  1035.     push    hl
  1036. ;
  1037.     ld    c,05h        ;select list output
  1038.     ld    e,0dh        ;pass carriage return character
  1039.     call    pdos
  1040.     ld    c,05h        ;select list output
  1041.     ld    e,0ah        ;pass line feed character
  1042.     call    pdos        ;send it out
  1043.     pop    hl        ;restore registers
  1044.     pop    de
  1045.     pop    bc
  1046.     pop    af
  1047.     ret    
  1048. ;
  1049. ;-----------------------------------------------------------------------
  1050. ;    this subroutine forms the mask for the plotting of a point
  1051. ;    digit= ycoord mod 7
  1052. ;    inputs:
  1053. ;        xcoord in bc
  1054. ;        ycoord in de
  1055. ;        xyaddr in hl
  1056. ;    outputs:
  1057. ;        contents of xyaddr in b
  1058. ;        mask (1 bit on) in c
  1059. ;        ycoord in de
  1060. ;        xyaddr in hl
  1061. ;    register status:
  1062. ;        see outputs
  1063. ;    error conditions:
  1064. ;        overflow in divide calls woops
  1065. ;
  1066. digit:    push    hl        ;save xyaddress
  1067.     push    de        ;save ycoord
  1068.     call    clrmsk        ;prepare color mask for future use
  1069.     ex    de,hl        ;put ycoord in hl
  1070.     ld    (divdnd),hl    ;calculate ycoord mod 7
  1071.     ld    a,07h
  1072.     ld    (divsor),a
  1073.     call    divide        ;mod is divide w/o quotient
  1074.     ld    a,(rmandr)    ;get result
  1075.     or    a        ;set flags
  1076.     call    m,woops        ;rmandr= -1 on overflow
  1077.     ld    b,a        ;move # of digit to b
  1078.     ld    a,00h
  1079.     inc    b        ;increment b to init for 1st dec
  1080.     if    msbtop
  1081.     scf            ;clear accum, put 1 in carry
  1082. rotmask:    rla        ;move mask bit 1 left
  1083.     endif            ;(msbtop)
  1084. ;
  1085.     if    not msbtop
  1086.     ld    a,10000000b    ;set high bit and rotate it right
  1087. rotmask:    rrca        ;move mask bit 1 right
  1088.     endif            ;(not msbtop)
  1089. ;
  1090.     dec    b        ;decrement # of digit
  1091.     jp    nz,rotmask    ;loop back
  1092.     ld    c,a        ;store mask temporarily
  1093.     ld    a,(cmask)    ;get color mask
  1094.     and    c        ;and bit mask with color mask- both rqd
  1095.     ld    c,a        ;put mask in c
  1096.     pop    de        ;bring back ycoord
  1097.     pop    hl        ;bring back (xyaddr)
  1098.     ld    b,(hl)        ;get byte @ (xyaddr)
  1099.     ret    
  1100. ;
  1101. ;-----------------------------------------------------------------------
  1102. ;    division subroutine
  1103. ;    inputs:
  1104. ;        divdnd  two byte positive number
  1105. ;        divsor    one byte positive number
  1106. ;    outputs:
  1107. ;        qotent    one byte positive quotient
  1108. ;        rmandr    one byte positive remainder or flag
  1109. ;    register status:
  1110. ;        bc,de,hl,psw registers returned to original values
  1111. ;    error conditions:
  1112. ;        rmandr=-1 if overflow occurs
  1113. ;
  1114. divide:    push    af        ;save registers
  1115.     push    bc
  1116.     push    de
  1117.     push    hl
  1118.     ld    hl,(divdnd)    ;fetch dividend
  1119.     ex    de,hl        ;put dividend into the de pair
  1120.     ld    a,(divsor)    ;fetch divsor
  1121.     ld    c,a        ;save in register c
  1122.     ld    b,8        ;loop counter in register b
  1123. divloop:    ld    a,e    ;shift low order byte to left
  1124.     and    a        ;clear carry
  1125.     rla            ;shift
  1126.     ld    e,a        ;replace value
  1127.     ld    a,d        ;fetch high order byte
  1128.     rla            ;rotate bringing in high bit
  1129.     sub    c        ;subtract divisor
  1130.     jp    p,setbit    ;if result was positive, jump
  1131.     add    a,c        ;otherwise add back divisor
  1132.     ld    d,a        ;replace high order byte
  1133.     jp    next        ;go to increment phase
  1134. setbit:    ld    d,a        ;replace high order byte
  1135.     ld    a,e        ;fetch low order byte
  1136.     or    1        ;set low order bit
  1137.     ld    e,a        ;replace low order byte
  1138. next:    dec    b        ;decrement loop counter
  1139.     jp    nz,divloop    ;repeat until done
  1140.     ld    a,e        ;quotient
  1141.     and    a        ;test sign of result
  1142.     jp    p,ok        ;if positive result is accurate
  1143.     ld    a,0ffh        ;set overflow value
  1144.     ld    (rmandr),a
  1145.     jp    done
  1146. ok:    ld    (qotent),a    ;save quotient
  1147.     ld    a,d        ;remainder
  1148.     ld    (rmandr),a    ;save remainder
  1149. done:    pop    hl
  1150.     pop    de
  1151.     pop    bc
  1152.     pop    af
  1153.     ret    
  1154. ;
  1155. ;-----------------------------------------------------------------------
  1156. ;
  1157. ;    this subroutine plots the vertical line used to fill in areas
  1158. ;
  1159. ;    inputs:
  1160. ;        xpos,ypos    current position on segment
  1161. ;        yfill        horizontal level to fill to
  1162. ;    outputs:
  1163. ;        vertical line drom (xpos,ypos) to (xpos,yfill)
  1164. ;    register status:
  1165. ;        all register values destroyed
  1166. ;    error conditions:
  1167. ;        none peculiar to this routine.
  1168. ;        note: all coordinate values assumed to be positive
  1169. ;
  1170. filine:    call    stat        ;update status message
  1171.     ld    hl,(xpos)    ;get starting coordinates of line
  1172.     ld    (xdot),hl    ;xpos will be x coord of all dots
  1173.     ld    hl,(ypos)    ;get y coordinate
  1174.     push    hl        ;save y position- plotdot will reset it
  1175.     ex    de,hl        ;put y coordinate in [de]
  1176.     ld    hl,(yfill)    ;get y fill value
  1177. ;
  1178.     ld    a,d        ;compare y coordinates for top and bot.
  1179.     cp    h        ;compare high bytes
  1180.     jp    c,yfxch        ;carry indicates that yfill is > ypos
  1181.     jp    nz,contfil    ;yfill definitely less than ypos
  1182.     ld    a,e        ;high bytes equal- compare low bytes
  1183.     cp    l        ;is yfill above or below ypos?
  1184.     jp    nc,contfil    ;yfill is not above ypos- continue
  1185. yfxch:    ex    de,hl        ;switch ypos and yfill- larger val in de
  1186. contfil:    ld    (ydot),hl;pass y coordinate to plotdot
  1187.     push    de        ;save registers
  1188.     push    hl
  1189.     call    plotdot        ;plot point
  1190.     pop    hl        ;retrieve registers
  1191.     pop    de
  1192.     inc    hl        ;increment y position
  1193. ;
  1194.     ld    a,d        ;check to see if line is done
  1195.     cp    h        ;compare high bytes
  1196.     jp    c,donefil    ;carry indicates that new y is above end
  1197.     jp    nz,contfil    ;new coordinate definitely below end
  1198.     ld    a,e        ;high bytes equal- compare low bytes
  1199.     cp    l        ;is it there yet?
  1200.     jp    c,donefil    ;carry indicates that new y is above end
  1201.     jp    contfil        ;loop back and do next point
  1202. donefil:    pop    hl    ;retrieve line y position
  1203.     ld    (ypos),hl    ;restore value
  1204.     ret            ;all finished!
  1205. ;
  1206. ;-----------------------------------------------------------------------
  1207. ;
  1208. ;    this subroutine will fill an area between a line segment and
  1209. ;    a horizontal line
  1210. ;
  1211. ;    inputs:
  1212. ;        buffer containing coordinate pairs and y coordinate of 
  1213. ;        fill level.  all five are real values
  1214. ;    outputs:
  1215. ;        xpos,ypos updated to end of line segment
  1216. ;        area between segment and yfill is filled with current 
  1217. ;        color value
  1218. ;    register status:
  1219. ;        all registers destroyed
  1220. ;    error conditions:
  1221. ;        none peculiar to this routine
  1222. ;
  1223. fill:    call    readxy        ;get starting coordinates
  1224.     ld    hl,(x)
  1225.     ld    (xpos),hl    ;update x position to start of segment
  1226.     ld    hl,(y)
  1227.     ld    (ypos),hl    ;update y position to start of segment
  1228.     call    readxy        ;get end coordinates
  1229.     call    byte        ;get first byte of fixed pt. y fill
  1230.     push    af        ;store first byte
  1231.     call    byte        ;get second byte
  1232.     ld    b,a        ;put high byte in [b]
  1233.     pop    af        ;get low byte
  1234.     ld    c,a        ;[bc] now contains fixed point y coord.
  1235.     ld    de,maxy*2    ;pass maximum raster address
  1236.     call    mult        ;multiply y coord by no. of y rasters
  1237.     ex    de,hl        ;put high bytes in [hl]
  1238.     ld    (yfill),hl    ;save integer value of y fill level
  1239. ;
  1240.     call    seginit        ;initialize variables for seg. interp.
  1241.     call    filine        ;fill area between first pt. & yfill
  1242. strtfil:    call    compseg    ;compute next point in segment
  1243.     ld    hl,(deltax)    ;top of loop- end when ni>dx
  1244.     ex    de,hl        ;deltax is now in (de)
  1245.     ld    hl,(ni)        ;get counter
  1246.     ld    a,d        ;compare counter w/dx hi byte first
  1247.     cp    h        ;compare hi bytes
  1248.     ret    c        ;carry indicates ni hi byte>dx hi byte
  1249.     jp    nz,chkfil    ;continue if ni definitely < dx
  1250.     ld    a,e        ;high bytes equal- look @ low byte
  1251.     cp    l        ;now low byte
  1252.     ret    c        ;ni low byte>dx low byte- done w/segment
  1253. chkfil:    ld    hl,(xdot)    ;compare xdot and xpos
  1254.     ex    de,hl
  1255.     ld    hl,(xpos)    ;xpos=xdot=> this will duplicate fill
  1256.     ld    a,d
  1257.     cp    h        ;are high bytes the same?
  1258.     jp    nz,loopfil    ;go on if high bytes are not equal
  1259.     ld    a,e        ;high bytes equal- look at low bytes
  1260.     cp    l        ;are the two exactly the same?
  1261.     jp    z,strtfil    ;yes- skip this position
  1262. loopfil:    call    filine    ;fill area between segment & yfill
  1263.     jp    strtfil        ;loop back to top
  1264. ;
  1265. ;-----------------------------------------------------------------------
  1266. ;
  1267. ;    this subroutine will send a string of characters to the printer
  1268. ;
  1269. ;    inputs:
  1270. ;        number-1 of characters to send in [de]
  1271. ;        address-1 of first character in [hl]
  1272. ;    outputs:
  1273. ;        0 through [de] characters sent to printer
  1274. ;    register status:
  1275. ;        all registers destroyed
  1276. ;    error conditions:
  1277. ;        none detected by this routine
  1278. ;
  1279. gboloop:    nop    
  1280.     if    oki
  1281.     push    de
  1282.     push    hl
  1283.     ld    c,05h        ;send etx to start into graphic mode
  1284.     ld    e,03h
  1285.     call    pdos
  1286.     pop    hl
  1287.     pop    de
  1288.     endif            ;(oki)
  1289. ;
  1290. kirklop:    dec    de    ;decrement counter
  1291.     inc    hl        ;increment address
  1292.     push    de        ;save counter
  1293.     push    hl
  1294.     ld    e,(hl)        ;get character
  1295. ;
  1296.     if    oki        ;if graphic byte is <etx>, a second
  1297. ;<etx> is required for the oki printer
  1298.     ld    a,e
  1299.     cp    03h        ;is byte <etx>?
  1300.     jp    nz,gbolp1
  1301.     push    de        ;save byte
  1302.     ld    c,05h        ;select cp/m list function
  1303.     call    pdos
  1304.     ld    e,03h        ;replace <etx> character sent
  1305.     pop    de        ;save byte
  1306.     endif            ;(oki)
  1307. ;
  1308. gbolp1:    ld    c,05        ;select cp/m list output function
  1309.     call    pdos        ;send character out
  1310.     pop    hl        ;retrieve address
  1311.     pop    de        ;retrieve counter
  1312.     ld    a,e        ;is counter =0?
  1313.     or    d        ;test counter
  1314.     jp    nz,kirklop    ;not done: loop back
  1315.     if    oki        ;send etx-so to cancel graphics mode
  1316.     push    de        ;save counter
  1317.     push    hl        ;save address
  1318.     ld    c,05h
  1319.     ld    e,03h
  1320.     call    pdos
  1321.     ld    c,05h
  1322.     ld    e,02h
  1323.     call    pdos
  1324.     pop    hl        ;retrieve address
  1325.     pop    de        ;retrieve counter
  1326.     endif            ;(oki)
  1327. ;
  1328.     ret    
  1329. ;
  1330. ;-----------------------------------------------------------------------
  1331. ;    this routine saves a byte from bit map in graphic buffer
  1332. ;
  1333. ;    inputs:
  1334. ;        byte in (b)
  1335. ;        2 byte counter @ ngraph
  1336. ;
  1337. ;    outputs:
  1338. ;        ngraph incremented
  1339. ;        byte stored in buffer @ gbuff
  1340. ;        buffer flushed if full
  1341. ;
  1342. ;    register status:
  1343. ;        all registers preserved
  1344. ;
  1345. ;    error conditions:
  1346. ;        none
  1347. ;
  1348. gbufin:    push    af        ;save registers
  1349.     push    bc
  1350.     push    de
  1351.     push    hl
  1352. ;
  1353.     ld    hl,(ngraph)    ;get no. of bytes in buffer
  1354.     inc    hl        ;increment ngraph
  1355.     ld    (ngraph),hl    ;store new value
  1356.     ex    de,hl        ;put ngraph in [de]
  1357. ;
  1358.     ld    hl,gbuff-1    ;get buffer base address
  1359.     add    hl,de        ;add counter to base address
  1360.     ld    (hl),b        ;store byte
  1361. ;
  1362. ;
  1363.     ex    de,hl        ;put ngraph in [hl]
  1364.     ld    de,0-(maxx+1)    ;put -max no. of bytes in [de]
  1365.     add    hl,de        ;[hl]=ngraph-(max no. of bytes)
  1366.     ld    a,h        ;if [hl]=0 then buffer is full
  1367.     or    l        ;set flags
  1368.     call    z,gbufout
  1369.     ;buffer is full- flush it to printer
  1370. ;
  1371.     pop    hl        ;restore registers
  1372.     pop    de
  1373.     pop    bc
  1374.     pop    af
  1375.     ret    
  1376. ;
  1377. ;-----------------------------------------------------------------------
  1378. ;        this subroutine flushes the graphic buffer
  1379. ;
  1380. ;    inputs:
  1381. ;        graphic buffer @ gbuff
  1382. ;        number of valid bytes in buffer @ ngraph
  1383. ;        "esc k" sequence stored ahead of ngraph
  1384. ;
  1385. ;    outputs:
  1386. ;        printer is placed in dot graphic mode 
  1387. ;        graphic string transmitted byte by byte to printer
  1388. ;
  1389. ;    register status:
  1390. ;        all registers preserved
  1391. ;
  1392. ;    error conditions:
  1393. ;        none
  1394. ;
  1395. gbufout:    push    af    ;save registers
  1396.     push    bc
  1397.     push    de
  1398.     push    hl
  1399. ;
  1400. gbotop:    ld    hl,(ngraph)    ;fetch buffer counter
  1401.     ex    de,hl        ;put buffer counter in [de]
  1402.     ld    a,e        ;look at low byte
  1403.     or    d        ;is counter=0?
  1404.     jp    z,gbufret    ;if buffer is empty, don't o/p anything
  1405. ;
  1406. ;    skip totally blank lines
  1407. ;
  1408.     ld    bc,maxx+1    ;get length of buffer
  1409.     ld    a,b        ;compare high bytes first
  1410.     cp    d
  1411.     jp    nz,gbo2        ;no match indicates something on this line
  1412.     ld    a,c        ;compare low bytes next
  1413.     cp    e
  1414.     jp    nz,gbo2        ;no match indicates something on this line
  1415. ;
  1416.     ld    hl,gbuff    ;set pointer to start of buffer
  1417. gbo1:    ld    a,(hl)        ;get byte from buffer
  1418.     or    a        ;is it a blank stroke?
  1419.     jp    nz,gbo2        ;go to output section if not blank
  1420.     inc    hl        ;point to new byte
  1421.     dec    bc        ;decrement counter
  1422.     ld    a,b        ;check for zero
  1423.     or    c
  1424.     jp    nz,gbo1        ;repeat until last byte has been checked
  1425. ;
  1426.     jp    gbufret        ;return w/o plotting since all were blank
  1427. ;
  1428. gbo2:    nop            ;head of output section
  1429. ;
  1430.     if    no8bit
  1431.     ld    a,e        ;look at low byte of counter
  1432.     or    a        ;set flags- is high bit set?
  1433.     jp    p,gbo7        ;low byte has 7 bits-o/p whole thing.
  1434. ;
  1435. ;    the parallel interface will only transmit 7 bits.  the low byte
  1436. ;    of the buffer counter has its high bit set, therefore, the 
  1437. ;    buffer must be output in smaller chunks
  1438. ;
  1439.     push    de        ;save ngraph on stack
  1440.     endif            ;(no8bit)
  1441.     if    epson and no8bit
  1442.     ld    de,126+4    ;counter=>126 bytes + 4 for esck,ngraph
  1443.     ld    hl,126d        ;set ngraph to 126
  1444.     ld    (ngraph),hl    ;put new no. in printer sequence
  1445.     ld    hl,esck-1    ;start with escape sequence
  1446.     endif            ;(epson and no8bit)
  1447. ;
  1448.     if    citoh and no8bit
  1449.     ld    de,126+6    ;counter=>126 bytes + 6 for esc s n3210
  1450.     ld    hl,esck+3    ;address of n1 byte
  1451.     ld    bc,126d        ;set no. of bytes
  1452.     ld    (hl),b        ;store high byte in n1
  1453.     inc    hl        ;address of n0
  1454.     ld    (hl),c        ;store low byte in n0
  1455.     ld    hl,esck-1    ;start with escape sequence
  1456.     endif            ;(citoh and no8bit)
  1457. ;
  1458.     if    no8bit
  1459.     call    gboloop        ;send out first 126 characters
  1460. ;
  1461. ;    move characters in buffer up to replace those sent out
  1462. ;
  1463.     pop    hl        ;retrieve old value of ngraph
  1464.     ld    de,0ff82h    ;[de]=-126d
  1465.     add    hl,de        ;[hl]now=ngraph-126
  1466.     ld    (ngraph),hl    ;store new value
  1467.     ex    de,hl        ;put ngraph in [de] to act as counter
  1468.     ld    hl,gbuff-1    ;get base address of buffer
  1469.     push    hl        ;save pointer for saving data
  1470.     ld    bc,007eh    ;put 126d in [bc]
  1471.     add    hl,bc        ;[hl] now points to new bytes
  1472. ;
  1473. gbomov:    inc    hl        ;incrment new data pointer
  1474.     ld    a,(hl)        ;get byte from buffer
  1475.     ex    (sp),hl        ;exchange pointers
  1476.     inc    hl        ;increment save data pointer
  1477.     ld    (hl),a        ;move byte up in buffer
  1478.     ex    (sp),hl        ;exchange pointers back again
  1479.     dec    de        ;decrement counter
  1480.     ld    a,e        ;check to see if loop is done
  1481.     or    d        ;is [de]=0?
  1482.     jp    nz,gbomov    ;loop back up if not done
  1483.     pop    hl        ;retrieve pointer to clean up stack
  1484. ;
  1485. ;    ngraph has now been updated and data in buffer has been moved
  1486. ;    to replace that which has been sent out.  now ready to try all
  1487. ;    over again with new segment of data in buffer.
  1488. ;
  1489.     jp    gbotop
  1490.     endif            ;(no8bit)
  1491. ;
  1492.     if    epson
  1493. gbo7:    inc    de
  1494.     inc    de
  1495.     inc    de
  1496.     inc    de
  1497.     ld    hl,esck-1    ;start with escape sequence
  1498.     endif            ;(epson)
  1499. ;
  1500.     if    citoh
  1501. gbo7:    ld    hl,esck+2    ;address of n3 byte for graphics select
  1502.     ld    a,30h        ;initialize number of byes to "0000"
  1503.     ld    (hl),a        ;"0"
  1504.     inc    hl
  1505.     ld    (hl),a        ;"00"
  1506.     inc    hl
  1507.     ld    (hl),a        ;"000"
  1508.     inc    hl
  1509.     ld    (hl),a        ;"0000"
  1510. ;
  1511.     call    bindec        ;convert n to ascii decimal and store
  1512. ;
  1513.     inc    de        ;increment counter for esc s n3-n0
  1514.     inc    de
  1515.     inc    de
  1516.     inc    de
  1517.     inc    de
  1518.     inc    de
  1519.     ld    hl,esck-1    ;start with escape sequence
  1520.     endif            ;(citoh)
  1521. ;
  1522.     if    oki
  1523. gbo7:    ld    hl,gbuff-1
  1524.     endif            ;(oki)
  1525. ;
  1526.     call    gboloop        ;send out string of graphic characters
  1527. ;
  1528. gbufret:    ld    a,00h    ;clear accumulator
  1529.     ld    (ngraph),a    ;set ngraph=0
  1530.     ld    (ngraph+1),a
  1531.     pop    hl            ;restore registers
  1532.     pop    de
  1533.     pop    bc
  1534.     pop    af
  1535.     ret    
  1536. ;
  1537. ;-----------------------------------------------------------------------
  1538. ;    this subroutine plots an incremental line segment from the
  1539. ;    present position
  1540. ;    inputs:
  1541. ;        file buffer @ dma
  1542. ;        present position @ xpos,ypos
  1543. ;    outputs:
  1544. ;        xpos, ypos updated to x,y
  1545. ;        visible portion of line segment drawn
  1546. ;    register status:
  1547. ;        all register values destroyed
  1548. ;    error conditions:
  1549. ;        none peculiar to this routine
  1550. ;
  1551. incplt:    call    readxy        ;get end point values
  1552.     call    seginit        ;initialize segment interpolation sub.
  1553. ;
  1554. strtplt:    ld    hl,(deltax);top of loop- end when ni>dx
  1555.     ex    de,hl        ;deltax is now in (de)
  1556.     ld    hl,(ni)        ;get counter
  1557.     ld    a,d        ;compare counter w/dx hi byte first
  1558.     cp    h        ;compare hi bytes
  1559.     ret    c        ;carry indicates ni hi byte>dx hi byte
  1560.     jp    nz,contplt    ;continue if ni definitely < dx
  1561.     ld    a,e        ;high bytes equal- look @ low byte
  1562.     cp    l        ;now low byte
  1563.     ret    c        ;ni low byte>dx low byte- done w/segment
  1564. contplt:    call    compseg    ;compute xpos and ypos at next point
  1565.     ld    hl,(xpos)    ;fetch x position
  1566.     ld    (xdot),hl    ;pass in xdot
  1567.     ld    hl,(ypos)    ;fetch y position
  1568.     ld    (ydot),hl    ;pass in ydot
  1569.     call    plotdot        ;plot it (finally)
  1570.     jp    strtplt        ;bounce up to the top of the loop
  1571. ;
  1572. ;-----------------------------------------------------------------------
  1573. ;            line spacing subroutine
  1574. ;
  1575. ;    inputs:
  1576. ;        none
  1577. ;    outputs:
  1578. ;        form feed sent
  1579. ;        esc a 7  sent to set the printer to 7/72" line spacing
  1580. ;    register status:
  1581. ;        all values changed
  1582. ;    error conditions:
  1583. ;        none
  1584. ;
  1585.     if    epson
  1586. ln772:    ld    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.     ld    e,1bh        ;pass esc character
  1592.     call    pdos        ;send it out
  1593. ;
  1594.     ld    c,05h        ;select list output
  1595.     ld    e,'a'        ;pass "a"
  1596.     call    pdos        ;send it out
  1597. ;
  1598.     ld    c,05h        ;select list output
  1599.     ld    e,07h        ;pass 7 for 7/72"
  1600.     call    pdos
  1601. ;
  1602.     ret    
  1603.     endif            ;(epson)
  1604. ;
  1605.     if    citoh
  1606. ln772:    ld    c,05h        ;select list output
  1607. ;    mvi    e,0ch        ;pass formfeed
  1608. ;    call    pdos        ;send it out
  1609. ;
  1610. ;    mvi    c,05h        ;select list output
  1611.     ld    e,1bh        ;pass esc character
  1612.     call    pdos        ;send it out
  1613. ;
  1614.     ld    c,05h        ;select list output
  1615.     ld    e,'>'        ;esc >  sets unidirectional printing
  1616.     call    pdos        ;send it out
  1617. ;
  1618.     ld    c,05h        ;select list output
  1619.     ld    e,1bh        ;pass esc character
  1620.     call    pdos        ;send it out
  1621. ;
  1622.     ld    c,05h        ;select list output
  1623.     ld    e,'t'        ;pass "t"
  1624.     call    pdos        ;send it out
  1625. ;
  1626.     ld    c,05h
  1627.     ld    e,'1'
  1628.     call    pdos        ;send out 1 as high byte
  1629. ;
  1630.     ld    c,05h        ;select list output
  1631.     ld    e,'4'        ;pass 14 for 14/144"
  1632.     call    pdos
  1633. ;
  1634.     ret    
  1635.     endif            ;(citoh)
  1636. ;
  1637.     if    oki
  1638. ln772:    ld    c,05h
  1639.     ld    e,18h        ;clear printer
  1640.     call    pdos
  1641.     ld    c,05h
  1642.     ld    e,1ch        ;set 12 cpi
  1643.     call    pdos
  1644.     ld    c,05h
  1645.     ld    e,1bh        ;esc % "9" 14 to set line spacing
  1646.     call    pdos
  1647.     ld    c,05h
  1648.     ld    e,25h
  1649.     call    pdos
  1650.     ld    c,05h
  1651.     ld    e,39h
  1652.     call    pdos
  1653.     ld    c,05h
  1654.     ld    e,14d        ;14/144 "/line
  1655.     call    pdos
  1656.     ret    
  1657.     endif            ;(oki)
  1658. ;
  1659. ;-----------------------------------------------------------------------
  1660. ;    this subroutine calculates the address for an xy coordinate pair
  1661. ;    xyaddr= origin + xcoord + (maxy-ycoord)/7 * (maxx+1)
  1662. ;    inputs:
  1663. ;        xcoordinate in registers bc
  1664. ;        ycoordinate in registers de
  1665. ;        maximum y raster count in hl
  1666. ;    outputs:
  1667. ;        xcoordinate in registers bc
  1668. ;        ycoordinate in registers de
  1669. ;        address of x,y coordinates in hl
  1670. ;        address stored @ xyaddr
  1671. ;    register status:
  1672. ;        psw values changed
  1673. ;    error conditions:
  1674. ;        overflow of arithmetic calls woops
  1675. ;
  1676. locdot:    push    de        ;store y coord on stack
  1677.     push    bc        ;store x coord on stack
  1678.     ld    a,l
  1679.     sub    e        ;subtract ycoord from maxy
  1680.     ld    l,a
  1681.     ld    a,h
  1682.     sbc    a,d
  1683.     ld    h,a        ;[hl] now contains (maxy - y)
  1684.     ld    (divdnd),hl    ;pass (maxy - y) to division routine
  1685.     ld    a,07h        ;pass 7 to division routine
  1686.     ld    (divsor),a
  1687.     call    divide        ;(maxy - y)/7
  1688.     ld    a,(rmandr)    ;rmandr is negative if overflow
  1689.     or    a        ;set flags
  1690.     call    m,woops        ;overflow in division
  1691.     ld    a,(qotent)    ;get result of division
  1692.     ld    bc,maxx+1    ;[bc] now contains the max. no. of x's
  1693.     call    bmult        ;[hl] has low order bytes, [a] the high
  1694. ;            [hl] now contains (max-ycoord)/7*(max+1)
  1695.     pop    bc        ;put xcoord in [bc]
  1696.     add    hl,bc        ;add to x previous term
  1697.     ld    de,origin    ;last term
  1698.     add    hl,de        ;final sum is in [hl]
  1699.     ld    (xyaddr),hl    ;store result
  1700.     pop    de        ;retrieve y coordinate
  1701.     ret    
  1702. ;
  1703. ;-----------------------------------------------------------------------
  1704. ;    output routine
  1705. ;
  1706. ;    inputs:
  1707. ;        memory map starting @ origin
  1708. ;
  1709. ;    outputs:
  1710. ;        map is dumped to printer 1 byte at a time
  1711. ;        mixed graphics and text are output
  1712. ;
  1713. ;    register status:
  1714. ;        all values destroyed
  1715. ;
  1716. ;    error conditions:
  1717. ;        none. printer will hang if it doesn't get proper input
  1718. ;
  1719. mapout:    
  1720.     ld    a,00h        ;reset status counter    
  1721.     ld    (statno),a
  1722.     ld    c,09h        ;print printing status message
  1723.     ld    de,stat3        
  1724.     call    fdos
  1725. ;
  1726. if    screen
  1727.     call    _setup
  1728.     ld    hl,margin
  1729.     ld    (xcoord),hl
  1730.     ld    hl,0
  1731.     ld    (ycoord),hl
  1732. else
  1733.     call    ln772        ;set printer to 7/72" line spacing
  1734. endif
  1735.     ld    hl,origin    ;initialize start address
  1736.     ld    a,00h        ;clear accumulator
  1737.     ld    (ngraph),a    ;initialize graphics counter
  1738.     ld    (ngraph+1),a
  1739.     ld    c,(maxy+1)/7    ;initialize line counter
  1740.  
  1741. linloop:    
  1742.     ld    de,maxx+1    ;initialize dot counter
  1743. ;
  1744. bytloop:    
  1745.     ld    b,(hl)        ;get byte
  1746.     ld    a,b        ;put byte in (a)
  1747.     or    a        ;set flags - is it a graphic byte?
  1748. if screen
  1749.     call    m,scharout    ;no- hi bit set therefore character
  1750.     call    p,screenplot    ;yes- plot it on screen
  1751. else
  1752.     call    m,charout    ;no- hi bit set therefore character
  1753.     call    p,gbufin    ;yes- save it in graphic buffer
  1754. endif
  1755. ;
  1756.     inc    hl        ;increment address to next x location
  1757.     dec    de        ;decrement dot counter
  1758.     ld    a,d
  1759.     or    e        ;is dot counter = 0?
  1760.     jp    nz,bytloop    ;no- so loop to top again
  1761. ;
  1762. if screen
  1763.     call    eoline        ;set x,y for next line
  1764. else
  1765.     call    gbufout        ;at end of line- flush buffer
  1766.     call    crlf        ;send a line feed to printer
  1767. endif
  1768.     dec    c        ;decrement line counter
  1769.     ld    a,c        ;get ready to test line counter
  1770.     or    a        ;set flags on line counter
  1771.     jp    nz,linloop    ;not done- repeat outer loop
  1772. ;
  1773. if screen
  1774.     call    sreset        ;reset screen to normal mode
  1775. else
  1776.     call    preset        ;reset printer to normal mode
  1777. endif
  1778. ;
  1779.     ret            ;last line finished
  1780.  
  1781. if screen
  1782. scharout:        ;char output to screen
  1783.     push    af
  1784.     push    bc
  1785.     push    de
  1786.     push    hl
  1787.     ld    hl,(xcoord)
  1788.     push    hl
  1789.     ld    bc,cwidth
  1790.     add    hl,bc
  1791.     ld    (xcoord),hl
  1792.     pop    hl
  1793.     ld    de,(ycoord)
  1794.     call    SetChar
  1795.     pop    hl
  1796.     pop    de
  1797.     ld    a,cwidth-1
  1798. scharo1:    
  1799.     inc    hl        ;increment address
  1800.     dec    de        ;decrement dot counter
  1801.     sub    1        ;decrement loop counter
  1802.     jp    nz,scharo1
  1803.     pop    bc
  1804.     pop    af
  1805.     ret
  1806.     
  1807. screenplot:
  1808.     push    af
  1809.     push    bc
  1810.     push    hl
  1811.     push    de
  1812.     ld    hl,(xcoord)
  1813.     inc    hl
  1814.     ld    (xcoord),hl
  1815.     dec    hl
  1816.     ld    de,(ycoord)
  1817.     bit    6,a
  1818.     call    nz,Set
  1819.     inc    de
  1820.     bit    5,a
  1821.     call    nz,Set
  1822.     inc    de
  1823.     bit    4,a
  1824.     call    nz,Set
  1825.     inc    de
  1826.     bit    3,a
  1827.     call    nz,Set
  1828.     inc    de
  1829.     bit    2,a
  1830.     call    nz,Set
  1831.     inc    de
  1832.     bit    1,a
  1833.     call    nz,Set
  1834.     inc    de
  1835.     bit    0,a
  1836.     call    nz,Set
  1837.     pop    de
  1838.     pop    hl
  1839.     pop    bc
  1840.     pop    af
  1841.     ret
  1842.     
  1843. eoline:
  1844.     push    hl
  1845.     push    bc
  1846.     ld    hl,margin
  1847.     ld    (xcoord),hl
  1848.     ld    hl,(ycoord)
  1849.     ld    bc,7
  1850.     add    hl,bc
  1851.     ld    (ycoord),hl
  1852.     pop    bc
  1853.     pop    hl
  1854.     ret
  1855.     
  1856. sreset:
  1857.     call    _gstring
  1858.     call    _reset
  1859.     ret
  1860. ;
  1861. grf_illegal_pos    equ    1    ; Printing ftext off byte boundary.
  1862. grf_out_range_x    equ    2    ; X out of range.
  1863. grf_out_range_y    equ    3    ; Y out of range.
  1864.  
  1865. vml    equ    1ch
  1866.  
  1867. fix_y    macro        ;; This macro calculate Y = 255 - Y to put
  1868.     ld    a,e        ;; the origin at the top left instead of the
  1869.     cpl            ;; the bottom left.
  1870.     ld    e,a
  1871.     endm
  1872. ;;
  1873. ;; This macro does 16-bit negation on a register pair. The algorithim is
  1874. ;; -rr = ~rr + 1. Rr is a register pair.
  1875. ;; r1 = high reg, r2 = low reg, r3 = 16 bit reg.
  1876. ;;
  1877. neg16    macro    r1,r2,r3
  1878.  
  1879.     ld    a,r1        ;; Complement high byte.
  1880.     cpl
  1881.     ld    r1,a
  1882.  
  1883.     ld    a,r2        ;; Complement low byte.
  1884.     cpl
  1885.     ld    r2,a
  1886.     inc    r3        ;; And add one.
  1887.  
  1888.     endm
  1889.  
  1890. ;+
  1891. ;    SET: Sets the point (HL,DE) on the screen. SET adjusts the y value
  1892. ; to make the origin at the top left corner.
  1893. ;-
  1894. Set:    push    af
  1895.     push    bc
  1896.     push    de
  1897.     push    hl
  1898.     call    HSeth
  1899.     pop    hl
  1900.     pop    de
  1901.     pop    bc
  1902.     pop    af
  1903.     ret
  1904.         
  1905. _h_set_point:    
  1906. _h_setpnt:
  1907.     call    ld_xy        ; get x and y from stack
  1908. HSet:    fix_y            ; Adjust origin and...
  1909.  
  1910. HSeth:        
  1911.     call    HGoToxyh    ; Move current point.
  1912.     jp    c,error        ; Return if off screen.
  1913.     call    bytmsk        ; Get byte and mask
  1914.     or    (hl)        ; Set point.
  1915.     ld    (hl),a        ; and put it back.
  1916.     jp    return        ;
  1917.     
  1918. return:    ;ld    hl,0        ; 0 = OK
  1919.     ret
  1920.  
  1921. error:    ;ld    hl,77        ; not 0 = error
  1922.     ret
  1923.  
  1924. attrib    equ    144        ; Value to switch in Attribute RAM.
  1925. bank0    equ    128        ; Value to switch in Bank 0 of the PCG.
  1926. screenloc    equ    0f000h        ; Start of screen.
  1927. pcg    equ    0f800h        ; Start of PCG.
  1928. ;+
  1929. ;    BYTMSK: Finds the PCG bank, char, byte and bit required to manipulate the
  1930. ; bit (HL,DE) on the hires screen. The origin is assumed to be at the top left.
  1931. ; Returns with the needed bank switched in, HL containing the address of the
  1932. ; byte the bit is in, and A containing a mask to access the bit. The mask is
  1933. ; defined so that the OR (HL) instruction sets the bit.
  1934. ;-
  1935. bytmsk:    push    bc        ; Save temp register.
  1936.     ld    a,7        ; Do a divide by 8 by masking required bits.
  1937.     and    l        ; Mask out the remainder.
  1938.     ld    c,a        ; c = x mod 8.
  1939.     add    hl,hl        ; Shift X so next bit in right place.
  1940.     ld    a,01110000B    ; Keep only the needed bits.
  1941.     and    l        ; Get them.
  1942.     ld    b,a        ; b = ((x mod 64) div 8) * 16
  1943.     add    hl,hl        ; Put X div 64 in H.
  1944.     ld    a,7        ; Specs say use mod 512, so only need bottom 3
  1945.     and    h        ;    bits.
  1946.     add    a,128        ; Add bit 7 for VML.
  1947.     out    (vml),a        ; Get bank L.
  1948.     ld    a,e        ; D = 0 since 0 <= y <= 255.
  1949.     and    0fh        ; Get modulos.
  1950.     ld    d,a        ; Store y mod 16.
  1951.     ld    a,e        ;
  1952.     and    0f0h        ; A = (y div 16) * 16.
  1953.     rrca            ;
  1954.     rrca            ;
  1955.     rrca            ;
  1956.     rrca            ;
  1957.     ld    e,c        ; Move X mod 8 as BC is needed.
  1958.     add    a,b        ; a = pcg char = ((x mod 64) div 8) + y div 16.
  1959.     ld    l,a        ;
  1960.     ld    h,0        ;
  1961.     add    hl,hl        ; * 2.
  1962.     add    hl,hl        ; * 4.
  1963.     add    hl,hl        ; * 8.
  1964.     add    hl,hl        ; * 16. HL = Offset into pcg data.
  1965.     ld    bc,pcg        ;
  1966.     add    hl,bc        ; HL = Start address of char data.
  1967.     ld    c,d        ; Get offset into char's data.
  1968.     ld    b,0        ;
  1969.     add    hl,bc        ; HL = address of byte to be changed.
  1970.     push    hl        ;
  1971.     ld    hl,bits        ; Start of mask table.
  1972.     ld    c,e        ; Get offset into mask. Is 16 bits since b = 0
  1973.     add    hl,bc        ; still.
  1974.     ld    a,(hl)        ; Get the mask.
  1975.     pop    hl        ; Restore the address.
  1976.     pop    bc        ; Restore temp register.
  1977.     ret            ; and that's all!
  1978.  
  1979. bits:    defb    80h,40h,20h,10h,08h,04h,02h,01h
  1980.  
  1981. ;-
  1982. curr_x:    defs    2        ; X position of the graphics cursor.
  1983. curr_y:    defs    2        ; Y position of the graphics cursor.
  1984. ;+
  1985. ; GOXY, GOXYH: The moves the graphics cursor to (HL,DE). 
  1986. ; An error occurs if this point is off the screen.
  1987. ;-
  1988. _h_go_to_xy:    
  1989. _h_gotoxy:
  1990.     call    ld_xy        ; get x and y from stack
  1991.     call    HGoToxy        ;
  1992.     ret            ;
  1993.  
  1994. HGoToxy:fix_y            ; Adjust the Y value.
  1995.  
  1996. HGoToxyh:call    rcheck        ; Make sure that the points are valid.
  1997.     jp    c,error        ; Return if not.
  1998.     ld    (curr_x),hl    ; Store X.
  1999.     ld    (curr_y),de    ; Store Y.
  2000.     ret            ;
  2001. ;-
  2002. rcheck:    or    a        ; Clear Carry.
  2003.     push    af        ; Save A.
  2004.     ld    a,h        ;
  2005.     and    0feh        ; See if any of bits 9 - 15 are set.
  2006.     jr    z,x_ok        ; Branch if not.
  2007.     pop    af        ;
  2008.     scf            ;
  2009.     ld    a,grf_out_range_x ; Describe error.
  2010. ;    jr    exit        ; Jump to exit.
  2011.     ret    ;exit would pop af again
  2012. x_ok:    ld    a,d        ; See if bits 8-15 are set
  2013.     or    a        ;
  2014.     jr    z,exit        ; Branch if in range.
  2015.     pop    af        ;
  2016.     scf            ;
  2017.     ld    a,grf_out_range_y ; Describe error.
  2018.     ret    ;dont fall through
  2019. exit:    pop    af        ;
  2020.     ret            ; Return.
  2021. ;+
  2022. ; CMP16: Compares two 16-bit signed or unsigned wrds and returns the C, Z,
  2023. ;    and S flags accordingly. Inputs: HL = Minuend, DE = subtrahend. Is
  2024. ;    effectivly HL - DE.
  2025. ;-
  2026. cmp16:    or    a        ; Clear Carry.
  2027.     sbc    hl,de        ; Subtract subtrahend from minuend.
  2028.     ret    po        ; Return if no overflow.
  2029.     ld    a,h        ; Overflow - Invert sign flag.
  2030.     rra            ; Save carry in bit 7.
  2031.     xor    01000000B; Complement bit 6 (Sign bit).
  2032.     scf            ; Restore carry, complement sign.
  2033.     adc    a,a        ; Z = 0 for sure.
  2034.     ret            ;
  2035. ;+
  2036. ; ld_xy get x and y from the stack on entry to subroutine.
  2037. ; note that arguments are popped in the same order as
  2038. ; in the call. HI-TECH C pushes them in reverse order.
  2039. ;-
  2040. ld_xy:    pop    af        ; return address
  2041.     pop    bc        ; return address
  2042.     pop    hl        ; x
  2043.     pop    de        ; y
  2044.     push    de        ;
  2045.     push    hl        ;
  2046.     push    bc        ; restore stack
  2047.     push    af        ;
  2048.     ret            ;
  2049.  
  2050. ;
  2051. grf_illegal_pos    equ    1    ; Printing ftext off byte boundary.
  2052. grf_out_range_x    equ    2    ; X out of range.
  2053. grf_out_range_y    equ    3    ; Y out of range.
  2054.  
  2055. vml    equ    1ch
  2056.  
  2057.  
  2058. fix_y    macro        ;; This macro calculate Y = 255 - Y to put
  2059.     ld    a,e        ;; the origin at the top left instead of the
  2060.     cpl            ;; the bottom left.
  2061.     ld    e,a
  2062. endm
  2063. ;;
  2064. ;; This macro does 16-bit negation on a register pair. The algorithim is
  2065. ;; -rr = ~rr + 1. Rr is a register pair.
  2066. ;; r1 = high reg, r2 = low reg, r3 = 16 bit reg.
  2067. ;;
  2068.  
  2069. neg16     macro    r1,r2,r3
  2070.  
  2071.     ld    a,r1        ;; Complement high byte.
  2072.     cpl
  2073.     ld    r1,a
  2074.  
  2075.     ld    a,r2        ;; Complement low byte.
  2076.     cpl
  2077.     ld    r2,a
  2078.     inc    r3        ;; And add one.
  2079.  
  2080. endm
  2081.  
  2082. ;screen    equ    0f000h        ; Character rom overlays screen area.
  2083. romff    equ    0bh        ; Port of ROM read latch.
  2084. char_height    equ    16    ; Height of character definition.
  2085.  
  2086. HSetChar:
  2087.     push    af        ; Save character.
  2088.     fix_y            ; Adjust Origin.
  2089.     pop    af        ; Get character back.
  2090. SetChar:
  2091.     call     fchar1        ; get addresses
  2092.     
  2093. fits1s:    ld    a,(de)        ; get byte
  2094.     or    (hl)        ; include other bits
  2095.     ld    (hl),a        ; replace
  2096.     inc    de        ;
  2097.     inc    hl        ;
  2098.     dec    c        ; count
  2099.     jr    nz,fits1s    ;
  2100.     xor    a        ;
  2101.     out    (romff),a    ; Restore screen (also clears Carry).
  2102.     ret            ; THE END.
  2103.  
  2104. ;+
  2105. ; common subroutine.
  2106. ;-
  2107. fchar1:    call    HGoToxyh    ; See if point is on screen.
  2108.     ret    c        ; Return if not.
  2109.     and    07fh        ; Remove high bit.
  2110.     push    af        ; Save characper.
  2111.     ld    a,l        ; Get most of X value.
  2112.     and    0f8h        ; Make sure it is a multiple of  8.
  2113.         ld    l,a        ;
  2114.  
  2115.     ld    bc,char_height    ; Assume
  2116.     ld    a,e        ; Get Y value.
  2117.     cp    256-char_height    ; See if all of character will fit on screen.
  2118.     jr    c,fits        ; Branch if character will fit.
  2119.     neg            ; Get total number of rows that can be placed.
  2120.     ld    c,a        ; Put it in count.
  2121.  
  2122. fits:    call    bytmsk        ; Switch in bank and get start location.
  2123.     ld    a,1        ;
  2124.     out    (romff),a    ; Switch in character ROM.
  2125.     pop    af        ; Get character.
  2126.     push    hl        ; Save destination.
  2127.     ld    l,a        ; Make 16-bit value.
  2128.     ld    h,0        ;
  2129.     add    hl,hl        ; * 2.
  2130.     add    hl,hl        ; * 4.
  2131.     add    hl,hl        ; * 8.
  2132.     add    hl,hl        ; * 16. HL = Offset into character ROM.
  2133.     ld    de,screenloc    ; Start of ROM.
  2134.     add    hl,de        ; HL = Source of char data.
  2135.     pop    de        ; DE = Destination
  2136.     ex    de,hl        ; DE = Source, HL = destination
  2137.     ret            ;
  2138.  
  2139. start_x:defw    0        ; x at start of text 
  2140. start_y:defw    0        ; y at start of text    
  2141. count:    defw    0        ; maximum no of chars
  2142. chpointer:defw    0        ; char pointer
  2143. CR    equ    0dh        ;
  2144. DEL    equ    07fh        ;
  2145. BDOS    equ    5        ;
  2146. BELL    equ    7        ; beep
  2147. BS    equ    8        ; back space
  2148.  
  2149. _get_string:
  2150. _gstring:
  2151.     ex    af,af'        ;    
  2152.     pop    af        ; return address
  2153.     ex    af,af'        ; save it
  2154.     pop    af        ; x
  2155.     pop    de        ; y
  2156.     pop    bc        ; string length
  2157.     pop    hl        ; string pointer
  2158.  
  2159.     push    hl        ;
  2160.     push    bc        ;
  2161.     push    de        ;
  2162.     push    af        ;
  2163.     ex    af,af'        ; reurn address
  2164.     push    af        ; restore stack
  2165.     ex    af,af'        ; x
  2166.     ld    (chpointer),hl    ;
  2167.     push    af        ;
  2168.     pop    hl        ; hl = x, de =  y, bc = length
  2169.  
  2170.     ld    a,l        ;
  2171.     and    0f0h        ;
  2172.     ld    l,a        ; fix x
  2173.     ld    a,e        ;
  2174.     and    0f8h        ;
  2175.     ld    e,a        ; fix y
  2176.  
  2177.     ld    (start_x),hl    ;
  2178.     ld    (start_y),de    ;
  2179.         dec    bc        ;
  2180.     ld    (count),bc    ;
  2181.     call    curson        ; turn cursor  on
  2182.     call    setcur        ; set cursor
  2183.  
  2184. cloop:    push    hl        ; save
  2185.     push    de        ;
  2186.     push    bc        ;
  2187.     call    setcur        ; set cursor
  2188. rloop:    ld    e,0ffh        ; input
  2189.     ld    c,06h        ; direct i/o
  2190.     call    BDOS        ; any char typed ?
  2191.     or    a        ; set flags
  2192.     jr    z,rloop        ; no
  2193.     pop    bc        ;
  2194.     pop    de        ;
  2195.     pop    hl        ; restore
  2196.  
  2197.     cp    DEL        ; Delete key ?
  2198.     jr    z,dodel        ; yes
  2199.     cp    BS        ; back space ?
  2200.     jr    z,dodel        ; yes
  2201.     cp    CR        ; Return
  2202.     jr    z,docr        ; yes
  2203.     cp    ' '        ; control char ?
  2204.     jr    c,cloop        ; yes ignore it
  2205. ;+
  2206. ; Put all other characters on the screen and into the return string.
  2207. ; First check if the string is full.
  2208. ;- 
  2209.     dec    c        ; ckunt
  2210.     jr    nz,ok0        ; ok
  2211.  
  2212.         inc    c        ; count  = 1
  2213.     push    de        ;
  2214.     push    hl        ;
  2215.     push    bc        ;
  2216.     push    af        ;
  2217.     ld    e,BELL        ;
  2218.     ld    c,6        ; direct i/o
  2219.     call    BDOS        ;
  2220.     pop    af        ;
  2221.     pop    bc        ;
  2222.     pop    hl        ;
  2223.     pop    de        ; restore y
  2224.     jp    cloop        ; continue
  2225.  
  2226.  
  2227. ok0:    push    hl        ; save x
  2228.     ld    hl,(chpointer)    ;
  2229.     ld    (hl),a        ; put in string
  2230.     inc    hl        ;
  2231.     ld    (chpointer),hl    ;
  2232.     pop    hl        ; restore x
  2233.  
  2234.     call    putit        ; put char on screen.
  2235.  
  2236.     jp    cloop        ; continue
  2237.  
  2238. ;+
  2239. ; Delete the last char typed.
  2240. ;-
  2241. dodel:    push    hl        ;
  2242.     push    de        ;
  2243.     ld    de,(start_x)    ;
  2244.     or    a        ; clear carry
  2245.     sbc    hl,de        ; back too far ?
  2246.     jp    z,nobak        ; yes
  2247.  
  2248.     ld    hl,(chpointer)    ;
  2249.     dec    hl        ; move back to last char
  2250.     ld    a,(hl)        ; get character
  2251.     ld    (chpointer),hl    ;
  2252.  
  2253.     pop    de        ; y
  2254.     pop    hl        ; x
  2255.     push    de        ; y
  2256.     ld    de,-8        ; mova x back
  2257.     add    hl,de        ;
  2258.  
  2259.     pop    de        ; y
  2260.  
  2261.     call    putit        ; remove from screen
  2262.     push    de        ; y
  2263.     ld    de,-8        ; move x back
  2264.     add    hl,de        ;
  2265.     pop    de        ; 
  2266.         inc    c        ; fix count
  2267.     jp    cloop        ; next char
  2268.  
  2269. nobak:    pop    de        ; y
  2270.     pop    hl        ; x
  2271.     jp    cloop
  2272. ;+
  2273. ; CR = end of input.
  2274. ;-
  2275. docr:    ld    a,0        ;
  2276.     ld    hl,(chpointer)    ; 
  2277.     ld    (hl),a        ;
  2278.     call    cursof        ; turn cursor off
  2279.     ret            ;
  2280.                                                                                                 
  2281. putit:    push    de        ;
  2282.     push    hl        ;
  2283.     push    bc        ;
  2284.     push    af        ;
  2285. ;    call    HInvertChar    ; put character on screen
  2286.     pop    af        ;
  2287.     pop    bc        ;
  2288.     pop    hl        ;
  2289.     ld    de,8        ; 8 points per char
  2290.     add    hl,de        ; move x to right
  2291.     pop    de        ; restore y
  2292.     ret            ;
  2293. ;+
  2294. ; Turn Cursor on.
  2295. ;-
  2296. curson:    push    af        ;
  2297.     ld    a,10        ; cursor sart/blink
  2298.     out    (12),a        ; select register
  2299.     ld    a,00h        ; no flash line 0
  2300.     out    (13),a        ; set cursor start
  2301.     ld    a,11        ; cursor end
  2302.     out    (12),a        ; select register
  2303.     ld    a,0fh        ; line 15
  2304.     out    (13),a        ;
  2305.     pop    af        ;
  2306.     ret
  2307. ;+
  2308. ; Turn Cursor off.
  2309. ;-
  2310. cursof:    push    af        ;
  2311.     ld    a,10        ; cursor sart/blink
  2312.     out    (12),a        ; select registev
  2313.     ld    a,02fh        ; no cursor
  2314.     out    (13),a        ; set cursor start
  2315.     ld    a,11        ; cursor end
  2316.     out    (12),a        ; select register
  2317.     ld    a,0fh        ; line 15
  2318.     out    (13),a        ;
  2319.     pop    af        ;
  2320.     ret
  2321. ;+
  2322. ; Set cursor position.
  2323. ; HL = x, DE = y.
  2324. ;- 
  2325. setcur:    push    af        ;
  2326.     push    bc        ;    
  2327.     ld    (xt),hl        ;
  2328.     ld    (yt),de        ;
  2329.  
  2330.     ld    l,e        ;
  2331.     ld    h,d        ; hl = y
  2332.  
  2333.     ld    a,l        ;
  2334.     cpl            ; correct y
  2335.     inc    a        ;
  2336.     ld    l,a        ;
  2337.  
  2338.     add    hl,hl        ; * 2
  2339.     add    hl,hl        ; * 4
  2340.     ld    de,(xt)        ; x
  2341.     sra    d        ;
  2342.     rr    e        ; / 2
  2343.     sra    d        ;
  2344.     rr    e        ; / 4
  2345.     sra    d        ;
  2346.     rr    e        ; / 8
  2347.     add    hl,de        ; 64 * y + x
  2348.  
  2349.     ld    a,14        ; curs pos HI
  2350.     out    (12),a        ; select register
  2351.     ld    c,13        ; data port
  2352.     out    (c),h        ;
  2353.     inc    a        ; curs pos LO
  2354.     out    (12),a        ; select register
  2355.     out    (c),l        ;
  2356.     ld    hl,(xt)        ; restore x
  2357.     ld    de,(yt)        ; restore y
  2358.     pop    bc        ;
  2359.     pop    af        ;
  2360.     ret            ;
  2361.  
  2362. xt:    defw    0        ; x
  2363. yt:    defw    0        ; y
  2364.  
  2365.  
  2366. vml    equ    01ch        ; Video memory latch port.
  2367. bdos    equ    5        ; BDOS entry point.
  2368. attrib    equ    144        ; Value to switch in Attribute RAM.
  2369. bank0    equ    128        ; Value to switch in Bank 0 of the PCG.
  2370. ;screen    equ    0f000h        ; Start of screen.
  2371. pcg    equ    0f800h        ; Start of PCG.
  2372.  
  2373. _setup:    push    af
  2374.     push    bc
  2375.     push    de
  2376.     ld    hl,d6545    ; Load data for 64*16 mode.
  2377.     ld    b,16        ; Amount of data.
  2378.  
  2379. lp6545:    ld    a,b        ;
  2380.     dec    a        ;
  2381.     out    (0ch),a        ; Tell which register.
  2382.     ld    a,(hl)        ;
  2383.     out    (0dh),a        ; Put data in it.
  2384.     dec    hl        ;
  2385.     djnz    lp6545        ; Next.
  2386. ;+
  2387. ; Clear the rest of the 80*24 screen.
  2388. ;-
  2389.     ld    hl,screenloc+1024    ; Start of second bank.
  2390.     ld    de,screenloc+1025    ;
  2391.     ld    bc,1023        ;
  2392.     ld    (hl),' '    ; Clear first char.
  2393.     ldir            ;   then the rest.
  2394. ;+
  2395. ; Now clear all the bank of pcg.
  2396. ;-
  2397.     ld    a,bank0        ; Start bank.
  2398.     ld    b,8        ; No. of banks.
  2399.  
  2400. clr:    push    bc
  2401.     out    (vml),a        ; Get bank.
  2402.     ld    hl,pcg        ; Start of bank.
  2403.     ld    de,pcg+1    ; 
  2404.     ld    bc,2047        ; Size of bank - 1.
  2405.     ld    (hl),0        ; Clear first byte.
  2406.     ldir            ; Clear the rest.
  2407.  
  2408.     pop    bc        ;
  2409.     inc    a        ; Next bank.
  2410.     djnz    clr        ;
  2411. ;+
  2412. ; Now set up attribute RAM in the save manner as in Basic.
  2413. ; Registers are used as counters since the DEC r; JR  NZ combination
  2414. ; is faster than a PUSH BC; ...; POP BC; DJNZ  version.
  2415. ;-
  2416.     ld    a,attrib    ; Switch in Attribute RAM.
  2417.     out    (vml),a        ;
  2418.     ld    d,16        ; No. of lines.
  2419.     ld    hl,screenloc    ; 
  2420.  
  2421. fill1:    xor    a        ; Initial Bank = 0.
  2422.     ld    c,8        ; No. of banks along a screen line.
  2423.  
  2424. fill2:    ld    b,8        ; No. of chars per bank per line.
  2425.  
  2426. fill3:    ld    (hl),a        ; Put bank in the Attribute RAM.
  2427.     inc    hl        ;
  2428.     djnz    fill3        ;
  2429.  
  2430.     inc    a        ; Next bank.
  2431.     dec    c        ;
  2432.     jr    nz,fill2    ;
  2433.  
  2434.     dec    d        ; Next line.
  2435.     jr    nz,fill1    ;
  2436.     ld    a,bank0        ;
  2437.     out    (vml),a        ; Put back the screen memory.
  2438. ;+
  2439. ; Now put PCG characters down to reflect the attribute RAM
  2440. ;-
  2441. pcgs:    ld    hl,screenloc    ; Screen again.
  2442.     ld    d,16        ; No of lines.
  2443.     ld    e,128        ; Start pcg character.
  2444.  
  2445. pcg1:    ld    c,8        ; No of banks per line.
  2446.  
  2447. pcg2:    ld    a,e        ; Get start pcg char.
  2448.     ld    b,8        ; No of chars per bank.
  2449.  
  2450. pcg3:    ld    (hl),a        ;
  2451.     inc    hl        ;
  2452.     add    a,16        ; Next char.
  2453.     djnz    pcg3        ;
  2454.  
  2455.     dec    c        ; Next Bank.
  2456.     jr    nz,pcg2
  2457.  
  2458.     inc    e        ; Start char for next line.
  2459.     dec    d        ;
  2460.     jr    nz,pcg1        ; Next line.
  2461.     pop    de
  2462.     pop    bc
  2463.     pop    af
  2464.     ret            ; That's it.
  2465. ;+
  2466. ; Data for Video controller for 16*64 mode.
  2467. ;-
  2468.     defb    107    ; Total horiz chars -1 (R0)
  2469.     defb    64    ; Displayed Chars.     (R1)
  2470.     defb    81    ; Hor sync pos.        (R2)
  2471.     defb    37H    ; Vert & Hor Sync wid  (R3)
  2472.     defb    18    ; Total Vert rows - 1  (R4)
  2473.     defb    9    ; Total vert adjust    (R5)
  2474.     defb    16    ; Vert displayed       (R6)
  2475.     defb    17    ; Vert Sync Position   (R7)
  2476.     defb    48H     ; Mode Control         (R8)
  2477.     defb    15    ; Scan lines per char  (R9)
  2478.     defb    2FH    ; Cursor start & blink (R10)
  2479.     defb    15    ; Cursor End           (R11)
  2480.     defb    00H    ; Display Start HI     (R12)
  2481.     defb    00H    ; Display Start LO     (R13)
  2482.     defb    00H    ; Cursor pos HI        (R14)
  2483. d6545:    defb    00H    ; Cursor pos LO        (R15)
  2484. ;+
  2485. ; 6545 setup table for 80 * 24
  2486. ;-
  2487.     defb    107    ; Total horiz chars -1 (R0)
  2488.     defb    80    ; Displayed Chars.     (R1)
  2489.     defb    87    ; Hor sync pos.        (R2)
  2490.     defb    37H    ; Vert & Hor Sync wid  (R3)
  2491.     defb    27    ; Total Vert rows - 1  (R4)
  2492.     defb    5    ; Total vert adjust    (R5)
  2493.     defb    24    ; Vert displayed       (R6)
  2494.     defb    25    ; Vert Sync Positimn   (R7)
  2495.     defb    48H     ; Mode Control         (R8)
  2496.     defb    10    ; Scan lines per char  (R9)
  2497.     defb    2AH    ; Cursor start & blink (R10)
  2498.     defb    10    ; Cursor End           (R11)
  2499.     defb    20H    ; Display Start HI     (R12)
  2500.     defb    00H    ; Display Start LO     (R13)
  2501.     defb    00H    ; Cursor pos HI        (R14)
  2502. d8024:    defb    00H    ; Cursor pos LO        (R15)
  2503. ;+
  2504. ; Restore normal 80 * 24 operation for C/80.
  2505. ;
  2506. ; First set 6545 to 80 * 25.
  2507. ;-
  2508. _reset:    ld    hl,d8024    ; Load data for 80*24 mode.
  2509.     ld    b,16        ; Amount of data.
  2510. l6545:    ld    a,b        ;
  2511.     dec    a        ;
  2512.     out    (0ch),a        ; Tell which register.
  2513.     ld    a,(hl)        ;
  2514.     out    (0dh),a        ; Put data in it.
  2515.     dec    hl        ;
  2516.     djnz    l6545        ; Next.
  2517. ;+
  2518. ; Set attribute RAM to all zeros.
  2519. ;-
  2520.     ld    a,attrib    ; Switch in Attribute RAM.
  2521.     out    (vml),a        ;
  2522.     ld    bc,2047        ; 2K RAM.
  2523.     ld    hl,screenloc    ; 
  2524.     ld    de,screenloc+1    ;
  2525.     xor    a        ; zero
  2526.     ld    (hl),a        ; first byte
  2527.     ldir            ; rest
  2528. ;+
  2529. ; Restore inverse character data in PCG bank 0
  2530. ;+
  2531.     ld    a,bank0        ; Set PCG bank 0
  2532.     out    (vml),a        ;
  2533.     ld    a,1        ;
  2534.     out    (0BH),a        ; Set romread latch
  2535.  
  2536.     ld    hl,screenloc    ; Screen and character rom
  2537.     ld    de,pcg        ; PCG
  2538.  
  2539.     ld    b,128        ; 128 PCG characters
  2540.  
  2541. rest1:    push    bc        ;
  2542.     ld    b,16        ; 16 bytes per pcg
  2543.  
  2544. rest2:    ld    a,(HL)        ;
  2545.     cpl            ;
  2546.     ld    (de),a        ;
  2547.     inc    hl        ;
  2548.     inc    de        ;
  2549.     djnz    rest2        ;
  2550.     pop    bc        ;
  2551.     djnz    rest1        ;
  2552.  
  2553.     ld    a,0        ;
  2554.     out    (0BH),a        ; Reset romread latch
  2555.  
  2556.     ld    bc,2047        ; complete screen
  2557.     ld    hl,screenloc    ; 
  2558.     ld    de,screenloc+1    ;
  2559.     ld    a,' '        ; space
  2560.     ld    (hl),a        ; first byte
  2561.     ldir            ; rest
  2562.     ret            ; done
  2563.  
  2564. endif
  2565. ;
  2566. ;-----------------------------------------------------------------------
  2567. ;    this subroutine moves the present position to new coordinates
  2568. ;    without doing anything else
  2569. ;
  2570. ;    inputs:
  2571. ;        coordinate pair in buffer
  2572. ;    outputs:
  2573. ;        xpos and ypos updated to new coordinates
  2574. ;    register status:
  2575. ;        all values destroyed
  2576. ;    error conditions:
  2577. ;        none peculiar to this routine
  2578. ;
  2579. move:    call    readxy        ;get coordinate pair
  2580.     ld    hl,(x)        ;get x coordinate
  2581.     ld    (xpos),hl    ;update x axis position
  2582.     ld    hl,(y)        ;get y coordinate
  2583.     ld    (ypos),hl    ;update    y axis position
  2584.     ret            ;position now updated.
  2585. ;
  2586. ;-----------------------------------------------------------------------
  2587. ;
  2588. ;    this subroutine multiplies two 16 bit integers
  2589. ;
  2590. ;    this routine from electronics magazine, feb. 24, 1982.
  2591. ;    written by jerry l. goodrich, penn. state u.
  2592. ;
  2593. ;
  2594. ;    inputs:
  2595. ;        multiplicand in [bc]
  2596. ;        multiplier in [de]
  2597. ;    outputs:
  2598. ;        32 bit product in [de],[hl] (most sig. bits in [de])
  2599. ;    register status:
  2600. ;        see inputs and outputs
  2601. ;    error conditions:
  2602. ;        none
  2603. ;
  2604. mult:    ld    a,e        ;load lowest order byte of multiplier
  2605.     push    de        ;save highest order byte of multiplier
  2606.     call    bmult        ;do 1-byte multiply
  2607.     ex    (sp),hl        ;save lowest order bytes product, get multiplier
  2608.     push    af        ;store highest order byte of first prod.
  2609.     ld    a,h        ;load highest order byte of multiplier
  2610.     call    bmult        ;do second 1-byte multiply
  2611.     ld    d,a        ;position highest-order byte of product
  2612.     pop    af        ;get highest order byte of first product
  2613.     add    a,h        ;update third byte of product
  2614.     ld    e,a        ;and put it in e
  2615.     jp    nc,nc1        ;dont't increment d if no carry
  2616.     inc    d        ;increment d if carry
  2617. nc1:    ld    h,l        ;relocate lowest order bytes of 2nd prod
  2618.     ld    l,0
  2619.     pop    bc        ;get lowest order 2 bytes of first prod.
  2620.     add    hl,bc        ;get final product lowest order 2 bytes
  2621.     ret    nc        ;done if no carry
  2622.     inc    de        ;otherwise update highest order 2 bytes
  2623.     ret    
  2624. ;
  2625. ;-----------------------------------------------------------------------
  2626. ;    print or disk o/p subroutine
  2627. ;
  2628. ;    inputs:
  2629. ;        05h in (c)
  2630. ;        character in (e)
  2631. ;        buffer pointer set to last character (pointr2)
  2632. ;        o/p flag in opdisk
  2633. ;    outputs:
  2634. ;        character printed if o/p flag set
  2635. ;        character written to disk if flag is set
  2636. ;    register status:
  2637. ;        all register values destroyed
  2638. ;    error conditions:
  2639. ;        none in this routine.
  2640. ;
  2641. pdos:    ld    a,(opdisk)    ;get disk o/p flag
  2642.     cp    00h        ;is flag set?
  2643.     push    af        ;save flag
  2644.     call    z,fdos        ;print character if it is
  2645.     pop    af        ;retrieve flags
  2646.     ret    z        ;return if character was printed
  2647. ;
  2648.     ld    a,(pointr2)    ;get buffer pointer
  2649.     inc    a        ;increment pointer for new char.
  2650.     ld    (pointr2),a    ;save new value
  2651.     ld    c,a        ;save pointer value in (c)
  2652.     ld    b,0        ;clear high byte of (bc)
  2653.     ld    hl,dma2-1    ;get last addr. before dma2
  2654.     add    hl,bc        ;calculate address of byte
  2655.     ld    (hl),e        ;put character in buffer
  2656.     cp    128d        ;is buffer full?
  2657.     call    z,write        ;write it out if it is.
  2658.     ret            ;done
  2659. ;
  2660. ;-----------------------------------------------------------------------
  2661. ;    this subroutine plots a point @ xdot,ydot
  2662. ;    method:
  2663. ;        find byte containing xdot,ydot
  2664. ;        form mask eg: if xdot,ydot is in #4 bit,
  2665. ;        mask = 00010000
  2666. ;        digit= 76543210
  2667. ;        modify byte according to color & store it back
  2668. ;    inputs:
  2669. ;        2 byte x location stored @ xdot
  2670. ;        2 byte y location stored @ ydot
  2671. ;    outputs:
  2672. ;        xpos, ypos reset to values given in xdot, ydot
  2673. ;        appropriate dot turned on or off in memory map
  2674. ;    register status:
  2675. ;        all register values destroyed
  2676. ;    error conditions:
  2677. ;        if xdot or ydot are outside of window, no point plotted
  2678. ;        xpos and ypos will still point outside window
  2679. ;
  2680. plotdot:    ld    hl,(xdot);get x position
  2681.     ld    (xpos),hl    ;update current position
  2682.     ld    b,h        ;moving xdot to bc
  2683.     ld    c,l        ;xdot now in bc
  2684.     ld    hl,(ydot)    ;get y position
  2685.     ld    (ypos),hl    ;update current position
  2686.     ld    d,h        ;moving ydot to de
  2687.     ld    e,l        ;ydot now in de
  2688. ;xpos and ypos now contain last pos. attempted- may not be in window
  2689.     ld    hl,maxx        ;put limits of x in hl
  2690. xcheck:    ld    a,b        ;check for neg x-sign in hi byte
  2691.     or    a        ;is xdot negative?
  2692.     ret    m        ;xdot neg- return w/o plotting
  2693.     ld    a,h        ;work with high byte first
  2694.     cp    b        ;compare max & x high bytes
  2695.     ret    c        ;x>max- therefore return
  2696.     jp    nz,ycheck    ;x is ok- check y
  2697.     ld    a,l        ;high bytes are= look @ low byte
  2698.     cp    c        ;compare x & max low bytes
  2699.     ret    c        ;x>max- return w/o plotting
  2700. ycheck:    ld    hl,maxy        ;put limit of y in hl
  2701.     ld    a,d        ;ydot hi byte contains sign
  2702.     or    a        ;is ydot negative?
  2703.     ret    m        ;ydot neg- return w/o plotting
  2704.     ld    a,h        ;high bytes first
  2705.     cp    d        ;compare max & y high bytes
  2706.     ret    c        ;y>max- return w/o plotting
  2707.     jp    nz,xyok        ;y is ok- plot dot
  2708.     ld    a,l        ;high bytes= look @ low bytes
  2709.     cp    e        ;compare low bytes
  2710.     ret    c        ;y is > max- return w/o plotting
  2711. xyok:    call    locdot        ;get address of byte for x,ydot
  2712.     call    digit        ;form mask for plotting
  2713.     ld    a,b        ;determine if byte is graphic
  2714.     or    a        ;graphic?
  2715.     ret    m        ;minus= character: return w/o plotting
  2716.     ld    a,(color)    ;get color value
  2717.     or    a        ;set flags
  2718.     jp    z,white        ;0 = white
  2719.     jp    m,compl        ;-1 = complementary color
  2720.     ld    a,b        ;color is black
  2721.     or    c        ;modify byte by turning bit on
  2722.     ld    (hl),a        ;store back in memory
  2723.     ret            ;done- ( at last)
  2724. ;
  2725. white:    ld    a,b        ;work w/ byte containing x,y
  2726.     cpl            ;complement byte
  2727.     or    c        ;modify byte by turning on bit
  2728.     cpl            ;complement byte back- bit 0ff
  2729.     ld    (hl),a        ;store byte back in memory
  2730.     ret            ;done- (finaly)
  2731. ;
  2732. compl:    ld    a,b        ;work w/ byte containing x,y
  2733.     xor    c        ;complement bit
  2734.     ld    (hl),a        ;store it
  2735.     ret            ;done-
  2736. ;
  2737. ;-----------------------------------------------------------------------
  2738. ;        plot point routine
  2739. ;
  2740. ;    inputs:
  2741. ;        buffer @ dma
  2742. ;    outputs:
  2743. ;        point plotted in memory
  2744. ;    register status:
  2745. ;        all values changed
  2746. ;    error conditions:
  2747. ;        none
  2748. ;
  2749. point:    call    readxy        ;read coordinates for point
  2750.     ld    hl,(x)        ;fetch x location
  2751.     ld    (xdot),hl    ;pass x to dot routine
  2752.     ld    hl,(y)        ;fetch y location
  2753.     ld    (ydot),hl    ;psss y to dot routine
  2754.     call    plotdot
  2755.     ret    
  2756. ;
  2757. ;-----------------------------------------------------------------------
  2758. ;            quit
  2759. ;    closes output file, terminates program
  2760. ;    inputs:
  2761. ;        fcb for output file @ fcb2
  2762. ;        disk output flag @ opdisk
  2763. ;    outputs:
  2764. ;        remainder of record set to 0, disk closed.
  2765. ;    register status:
  2766. ;        all values destroyed
  2767. ;    error conditions:
  2768. ;        none
  2769. ;
  2770. quit:    ld    a,(opdisk)    ;get disk output flag
  2771.     cp    00h        ;is it set?
  2772.     jp    z,boot        ;no, so all done
  2773. ;
  2774.     ld    a,(pointr2)    ;look @ o/p pointer
  2775.     cp    0        ;is o/p buffer empty?
  2776.     jp    z,boot        ;yes- done
  2777. ;
  2778. ;    fill remainder of o/p buffer with nulls
  2779. ;
  2780.     ld    e,a        ;save pointer value in (e)
  2781.     ld    d,00h        ;clear high byte of (de)
  2782.     ld    a,128        ;set max value of pointer
  2783.     sub    e        ;(a)= 128- pointr2
  2784.     ld    c,a        ;(c) now is count of extra buff.
  2785. ;
  2786. clrbuf:    push    bc        ;save counter
  2787.     ld    e,00h        ;pass a <null>
  2788.     call    pdos        ;put it in buffer
  2789.     pop    bc        ;retrieve counter
  2790.     dec    c        ;counter=counter-1
  2791.     jp    nz,clrbuf    ;loop back until buffer is full
  2792. ;
  2793.     ld    c,10h        ;select close file function
  2794.     ld    de,fcb2        ;pass o/p fcb
  2795.     call    fdos        ;close file
  2796. ;
  2797.     jp    boot        ;do warm boot on exit
  2798. ;
  2799. ;-----------------------------------------------------------------------
  2800. ;            line segment routine
  2801. ;    inputs:    file buffer @ dma
  2802. ;
  2803. ;    outputs:
  2804. ;        xpos, ypos updated to x2,y2
  2805. ;        visible portion of line segment plotted
  2806. ;
  2807. ;    registers:
  2808. ;        all registers values destroyed
  2809. ;    error conditions:
  2810. ;        no checks made in this routine
  2811. ;
  2812. plotseg:    call    readxy    ;get starting coordinates
  2813.     ld    hl,(x)        ;fetch starting x
  2814.     ld    (xdot),hl    ;pass to dot routine
  2815.     ld    hl,(y)        ;fetch starting y
  2816.     ld    (ydot),hl    ;pass to dot routine
  2817.     call    plotdot        ;plot starting point
  2818.     call    incplt        ;plot rest of segment
  2819.     ret            ;return to main program
  2820. ;
  2821. ;-----------------------------------------------------------------------
  2822. ;
  2823. ;    this subroutine resets the printer to its normal mode 
  2824. ;
  2825. ;    inputs:
  2826. ;        none
  2827. ;    outputs:
  2828. ;        none returned
  2829. ;    register status:
  2830. ;        all registers changed
  2831. ;    error conditions:
  2832. ;        none
  2833. ;
  2834.     if    epson
  2835. preset:    ld    c,05h
  2836.     ld    e,1bh        ;pass esc character
  2837.     call    pdos        ;send esc
  2838.     ld    c,05h
  2839.     ld    e,'2'
  2840.     call    pdos        ;esc 2 sets line spacing to 6 lines/in.
  2841.     ld    c,05h
  2842.     ld    e,cr        ;send carriage return to reset head
  2843.     call    pdos
  2844.     ret    
  2845.     endif            ;(epson)
  2846. ;
  2847.     if    citoh
  2848. preset:    ld    c,05h
  2849.     ld    e,1bh        ;send esc
  2850.     call    pdos
  2851.     ld    c,05h
  2852.     ld    e,'a'        ;esc a sets line spacing to 6 lines/in.
  2853.     call    pdos
  2854.     ld    e,cr
  2855.     ld    c,05h
  2856.     call    pdos        ;send carriage return to reset head
  2857.     ret    
  2858.     endif            ;(citoh)
  2859. ;
  2860.     if    oki
  2861. preset:    ld    c,05h
  2862.     ld    e,1bh        ;esc % "9" 24 to set line spacing
  2863.     call    pdos
  2864.     ld    c,05h
  2865.     ld    e,25h        ; "%"
  2866.     call    pdos
  2867.     ld    c,05h
  2868.     ld    e,39h        ; "9"
  2869.     call    pdos
  2870.     ld    c,05h
  2871.     ld    e,24d        ;reset to normal line spacing
  2872.     call    pdos
  2873.     ret    
  2874. ;
  2875.     endif            ;(oki)
  2876. ;
  2877. ;-----------------------------------------------------------------------
  2878. ;    read record subroutine
  2879. ;    inputs:
  2880. ;        opened file
  2881. ;        file control block @ fcb
  2882. ;        128 char file buffer @ dma
  2883. ;        1 byte character pointer @ pointer
  2884. ;    outputs:
  2885. ;        character pointer reset to 0
  2886. ;        new record in file buffer
  2887. ;    register status:
  2888. ;        all register values destroyed
  2889. ;    error conditions:
  2890. ;        eof: jump to eofexit instead of normal return
  2891. ;
  2892. read:    ld    c,26d        ;select set dma function
  2893.     ld    de,dma        ;pass buffer address
  2894.     call    fdos        ;set dma address to i/p buffer
  2895. ;
  2896.     ld    c,14h        ;select sequential read function
  2897.     ld    de,fcb        ;pass fcb
  2898.     call    fdos        ;read record into buffer @ dma
  2899.     cp    00h        ;read ok?
  2900.     jp    z,setpntr    ;reset pointer if not eof
  2901.     pop    bc        ;pop return addr off stack
  2902.     jp    eofexit        ;goto exit instead of normal rtn
  2903. setpntr:    ld    a,0    ;clear accum.
  2904.     ld    (pointer),a    ;reset pointer to 0
  2905.     ret            ;return-new record & pointer pos
  2906. ;
  2907. eofexit:    ld    c,09h    ;select print string function
  2908.     ld    de,eofmsg    ;pass message
  2909.     call    fdos        ;print eof message
  2910.     jp    boot        ;return to cp/m command level
  2911. ;-----------------------------------------------------------------------
  2912. ;
  2913. ;    this subroutine gets an xy pair
  2914. ;and converts it to raster values.  the general algorithm is:
  2915. ;
  2916. ;    integer = (fixed point) * (number of rasters) * 2/ 2^16
  2917. ; the fixed point number is a 15 bit value in the range 0 to 1.  
  2918. ; when viewed as an integer, the fixed point coordinates range from
  2919. ; 0 to 32767.  when multiplied by the range of the raster coordinates,
  2920. ; they must be divided by 32767 to represent the true value.  this is 
  2921. ; approximated by multiplying by 2 / 65536   (2/64k).  dividing by 64k
  2922. ; is accomplished by simply disregarding the lower 2 bytes of the result
  2923. ;
  2924. ;    inputs:
  2925. ;        128 character buffer @ dma
  2926. ;        character pointer @ pointer
  2927. ;    outputs:
  2928. ;        two byte value stored @ x
  2929. ;        two byte value stored @ y
  2930. ;    register status:
  2931. ;        all register values destroyed
  2932. ;    error conditions:
  2933. ;        none- byte will terminate program on eof if necessary
  2934. ;
  2935. readxy:    call    byte        ;get first byte of x
  2936.     push    af        ;store first byte
  2937.     call    byte        ;get second byte
  2938.     ld    b,a        ;put high byte in [b]
  2939.     pop    af        ;get low byte
  2940.     ld    c,a        ;[bc] now contains fixed point x coord.
  2941.     ld    de,maxx*2    ;pass maximum raster address
  2942.     call    mult        ;multiply x coord by no. of x rasters
  2943.     ex    de,hl        ;put high bytes in [hl]
  2944.     ld    (x),hl        ;store corresponding raster x coordinate
  2945. ;
  2946.     call    byte        ;get first byte of y
  2947.     push    af        ;store first byte
  2948.     call    byte        ;get second byte
  2949.     ld    b,a        ;put high byte in [b]
  2950.     pop    af        ;get low byte
  2951.     ld    c,a        ;[bc] now contains fixed point y coord.
  2952.     ld    de,maxy*2    ;pass maximum raster address
  2953.     call    mult        ;multiply y coord by no. of y rasters
  2954.     ex    de,hl        ;put high bytes in [hl]
  2955.     ld    (y),hl        ;store corresponding raster y coordinate
  2956.     ret    
  2957. ;
  2958. ;---------------------------------------
  2959. ;
  2960. ;    this subroutine rotates the patterns used for erasing to a color
  2961. ;
  2962. ;    inputs:
  2963. ;        array of 8 pattern bytes stored at patrn
  2964. ;    outputs:
  2965. ;        array is rotated one bit down
  2966. ;    register status:
  2967. ;        [bc],[hl] preserved, all others destroyed
  2968. ;    error conditions:
  2969. ;        none
  2970. ;
  2971. rotpat:    push    bc        ;save counter in [bc]
  2972.     push    hl        ;save pointer in [hl]
  2973.     ld    b,8d        ;initialize counter
  2974.     ld    hl,patrn    ;initialize address of head of array
  2975. rotpt1:    ld    a,(hl)        ;get byte
  2976.     if    msbtop
  2977.     rrca            ;rotate byte
  2978.     endif            ;( msbtop )
  2979.     if    not msbtop
  2980.     rlca    
  2981.     endif            ;( not msbtop )
  2982.     ld    (hl),a        ;store rotated byte
  2983. ;
  2984.     inc    hl        ;move pointer to next byte
  2985.     dec    b        ;decrement counter
  2986.     jp    nz,rotpt1    ;loop back until done
  2987.     pop    hl        ;retrieve saved registers
  2988.     pop    bc
  2989.     ret    
  2990. ;
  2991. ;-----------------------------------------------------------------------
  2992. ;
  2993. ;    this subroutine initializes the variables used in computing a 
  2994. ;    line segment
  2995. ;
  2996. ;    inputs:
  2997. ;        xpos,ypos    present position
  2998. ;        x,y        end points of segment
  2999. ;    outputs:
  3000. ;        dx,dy    x,y sizes of line segment
  3001. ;        epslnx,epslny,sx,sy,delta3    internal variables 
  3002. ;                        initialized
  3003. ;        ni    counter used to determine when done
  3004. ;    register satus:
  3005. ;        all register values destroyed.
  3006. ;    error conditions:
  3007. ;        none
  3008. ;
  3009. seginit:    ld    hl,(x)    ;get x
  3010.     ex    de,hl        ;put x in de
  3011.     ld    hl,(xpos)    ;put present pos in hl
  3012.     ld    a,e        ;calculate delta x
  3013.     sub    l
  3014.     ld    c,a
  3015.     ld    a,d
  3016.     sbc    a,h
  3017.     ld    b,a        ;bc now contains delta x (dx)
  3018.     ld    hl,(y)        ;get y end point value
  3019.     ex    de,hl        ;put y in de
  3020.     ld    hl,(ypos)    ;get present y position
  3021.     ld    a,e        ;calculate delta y (dy)
  3022.     sub    l
  3023.     ld    e,a
  3024.     ld    a,d
  3025.     sbc    a,h
  3026.     ld    d,a        ;de now contains dy
  3027.     ex    de,hl        ;put dy in hl, ypos in de
  3028.     ld    (deltay),hl    ;store dy
  3029.     ld    h,b
  3030.     ld    l,c
  3031. ;
  3032.     ld    (deltax),hl    ;store delta x
  3033.     ld    hl,0000h    ;initialize variables
  3034.     ld    (sx),hl
  3035.     ld    (epslny),hl
  3036.     ld    hl,0001h
  3037.     ld    (sy),hl
  3038.     ld    (epslnx),hl
  3039.     ld    a,(deltax+1)    ;get dx high byte
  3040.     or    a        ;set flags according to dx hi byte
  3041.     jp    p,chkdy
  3042.     ld    hl,0ffffh    ;change initialization for -dx
  3043.     ld    (epslnx),hl
  3044.     ld    hl,(deltax)    ;change sign on dx
  3045.     ld    a,h
  3046.     cpl            ;complement high byte
  3047.     ld    h,a
  3048.     ld    a,l
  3049.     cpl            ;complement low byte
  3050.     add    a,01h        ;add 1 to make it two's comp.
  3051.     ld    l,a
  3052.     ld    a,h
  3053.     adc    a,00h        ;add carry to high byte
  3054.     ld    h,a
  3055.     ld    (deltax),hl    ;store now positive dx
  3056. chkdy:    ld    a,(deltay+1)    ;get dy high byte- contains sign
  3057.     or    a        ;set flags on dy hi byte
  3058.     jp    p,chdxdy    ;dy is pos- goto transpose axes
  3059.     ld    hl,(deltay)    ;dy is negative- change sign
  3060.     ld    a,h
  3061.     cpl            ;complement hi byte
  3062.     ld    h,a
  3063.     ld    a,l
  3064.     cpl    
  3065.     add    a,01h        ;complement and add 1
  3066.     ld    l,a
  3067.     ld    a,h
  3068.     adc    a,00h        ;add carry from low byte
  3069.     ld    h,a
  3070.     ld    (deltay),hl    ;store the now pos. dy
  3071.     ld    hl,0ffffh    ;load -1 in (hl)
  3072.     ld    (sy),hl        ;sy= -1
  3073. chdxdy:    ld    hl,(deltax)    ;transpose axes if dx<dy
  3074.     ex    de,hl        ;put dx in de
  3075.     ld    hl,(deltay)    ;get delta y
  3076.     ld    a,d        ;put high byte of dx in a
  3077.     cp    h        ;dx < dy ? (high bytes first)
  3078.     jp    c,tnspos    ;dx definitely < dy
  3079.     jp    nz,lstinit    ; dx definitely > dy
  3080.     ld    a,e        ;high bytes =, check low bytes
  3081.     cp    l
  3082.     jp    nc,lstinit    ;if no carry, dx>= dy- start plotting
  3083. tnspos:    ld    (deltax),hl    ;dy was in hl- store as dx
  3084.     ex    de,hl        ;dx now in hl, dy now in de
  3085.     ld    (deltay),hl    ;store old dx as new dy
  3086.     ld    hl,(epslnx)
  3087.     ld    (sx),hl        ;reinitialize: sx= epsilon x
  3088.  
  3089.     ld    hl,(sy)
  3090.     ld    (epslny),hl    ;epsilon y = sy
  3091.     ld    hl,0000h
  3092.     ld    (epslnx),hl    ;epsilon x = 0
  3093.     ld    (sy),hl        ;sy = 0
  3094. ;
  3095. lstinit:    scf        ;clear carry -set=1, then complement
  3096.     ccf    
  3097.     ld    a,d        ;calculate deltax/2 by shifting 1 right
  3098.     rra            ;shift
  3099.     ld    d,a        ;store high byte deltax/2 in d
  3100.     ld    a,e        ;now the low byte
  3101.     rra            ;shift  (divide by 2)
  3102.     ld    e,a        ;put low byte back.
  3103.     ex    de,hl        ;put dx/2 in (hl)
  3104.     ld    (delta3),hl    ;store in delta3
  3105. ;
  3106.     ld    hl,0001h    ;set ni=1
  3107.     ld    (ni),hl        ;save counter value
  3108.     ret            ;done with initialization
  3109. ;
  3110. ;------------------------------------------------------------------------
  3111. ;            status message routine
  3112. ;
  3113. ;    this routine displays a message to indicate that the program
  3114. ;    is working.
  3115. ;
  3116. ;    inputs:
  3117. ;        current count stored in statno
  3118. ;    outputs:
  3119. ;        message displayed
  3120. ;    register status:
  3121. ;        all register values preserved
  3122. ;    error conditions:
  3123. ;        none
  3124. ;
  3125. stat:    push    af        ;save registers
  3126.     push    bc
  3127.     push    de
  3128.     push    hl
  3129. ;
  3130.     ld    a,(statno)    ;get counter
  3131.     inc    a        ;update counter
  3132.     ld    (statno),a
  3133.     ld    c,09h        ;select write function
  3134.     cp    01h        ;select message
  3135.     jp    nz,statm2
  3136.     ld    de,stat1
  3137.     call    fdos        ;print message
  3138.     jp    statx        ;exit subroutine
  3139. ;
  3140. statm2:    cp    128        ;check for other message
  3141.     jp    nz,statx    ;not time for either message
  3142.     ld    de,stat2
  3143.     call    fdos        ;print other message
  3144. ;
  3145. statx:    pop    hl        ;restore registers
  3146.     pop    de
  3147.     pop    bc
  3148.     pop    af
  3149.     ret    
  3150. ;
  3151. ;------------------------------------------------------------------------
  3152. ;            string plotting subroutine
  3153. ;    method:
  3154. ;        ascii code is stored repeatedly in the area occupied by
  3155. ;        the character (cwidth rasters).  hi bit is set to  
  3156. ;        indicate that the byte is ascii and not dot image.
  3157. ;
  3158. ;    input:
  3159. ;        x,y in file buffer
  3160. ;        bytes read sequentially from buffer until carriage rtn
  3161. ;        is encountered.
  3162. ;
  3163. ;    outputs:
  3164. ;        each character is stored in the byte containing the bit
  3165. ;        map coordinate indicated for the character
  3166. ;
  3167. ;    register status:
  3168. ;        all register values destroyed
  3169. ;
  3170. ;    error conditions:
  3171. ;        x,y locations < 0 are reset to 0
  3172. ;        x,y locations > max are reset to 0
  3173. ;
  3174. cr    equ    0dh        ;cr = carriage return
  3175. string:    call    readxy        ;get starting coordinates
  3176. strng0:    call    byte        ;get first character
  3177.     cp    cr        ;is character a carriage return?
  3178.     ret    z        ;yes- so return (all done)
  3179.     or    10000000b    ;set high bit
  3180.     ld    b,a        ;save byte in (b)
  3181.     ld    hl,(x)        ;get x location
  3182.     ld    a,h        ;look at high byte
  3183.     or    a        ;set flags
  3184.     jp    m,resetx    ;x is negative- reset to 0
  3185.     ld    de,maxx-cwidth    ;get maximum x value 
  3186.     cp    d        ;compare max and x high bytes
  3187.     jp    c,strng1    ;max definitely > x (x is ok)
  3188.     jp    nz,resetx    ;x definitely > max -reset x
  3189.     ld    a,l        ;hi bytes are =: look at low bytes
  3190.     cp    e        ;is max low byte > x low byte?
  3191.     jp    c,strng1    ;yes is is - x is ok
  3192.     jp    z,strng1    ;low bytes are =: x is barely ok
  3193. resetx:    ld    hl,0000h    ;clear hl
  3194.     ld    (x),hl        ;store 0 in x
  3195. strng1:    ld    hl,(y)        ;fetch y starting location
  3196.     ld    a,h        ;look at y high byte
  3197.     or    a        ;set flags
  3198.     jp    m,resety    ;negative - reset to 0
  3199.     ld    de,maxy        ;use entire coordinate range for y
  3200.     cp    d        ;compare max and y high bytes
  3201.     jp    c,strng2    ;y definitely ok
  3202.     jp    nz,resety    ;y definitely > max - reset y
  3203.     ld    a,l        ;hi bytes are =: look @ low bytes
  3204.     cp    e        ;compare max and y low bytes
  3205.     jp    c,strng2    ;max > y - y is ok
  3206.     jp    z,strng2    ;y = max
  3207. resety:    ld    hl,0000h    ;clear old value of y
  3208.     ld    (y),hl        ;y = 0
  3209. strng2:    ex    de,hl        ;put y in (de)
  3210.     ld    hl,(x)        ;fetch x
  3211.     push    bc        ;save byte temporarily
  3212.     push    de        ;save y coord temporarily
  3213. ;    make x coord. a multiple of cwidth for proper printer output
  3214.     ld    (divdnd),hl    ;compute x=(x/cwidth)*cwidth
  3215.     ld    a,cwidth    ;get cwidth for divisor
  3216.     ld    (divsor),a
  3217.     call    divide        ;divide x by cwidth
  3218.     ld    a,(qotent)    ;get results (no overflow as 0<=x<1530)
  3219.     ld    bc,cwidth    ;pass character width
  3220.     call    bmult        ;[hl] now contains (x/cwidth)*cwidth
  3221. ;
  3222.     ld    b,h        ;put x in (bc)
  3223.     ld    c,l
  3224.     pop    de        ;retrieve y coordinate
  3225.     ld    hl,maxy        ;put max y in (hl)
  3226.     call    locdot        ;get location of byte
  3227.     pop    bc        ;retrieve byte
  3228.     ld    (hl),b        ;put byte in address containing x,y
  3229. ;    store byte repeatedly to blank out entire area occupied by it
  3230.     ld    a,cwidth-1    ;initialize loop counter
  3231. strng3:    inc    hl        ;increment address
  3232.     ld    (hl),b        ;store byte
  3233.     sub    1        ;decrement loop counter
  3234.     jp    nz,strng3    ;loop back up until finished
  3235.     ld    c,cwidth    ;put cwidth in (c)
  3236.     ld    hl,(x)        ;fetch x location
  3237.     ld    b,00h        ;clear (b)
  3238.     add    hl,bc        ;increment x location for  next character
  3239.     ld    (x),hl        ;store new x location
  3240.     jp    strng0        ;loop up to top
  3241. ;
  3242. ;-----------------------------------------------------------------------
  3243. ;    text
  3244. ;
  3245. ;    this subroutine outputs text immediately to the printer
  3246. ;    note: text is not put into memory map
  3247. ;
  3248. ;    inputs:
  3249. ;        text string in file (ends with 0 byte)
  3250. ;    outputs:
  3251. ;        text string printed
  3252. ;    register status:
  3253. ;        all register values destroyed
  3254. ;    error conditions:
  3255. ;        none peculiar to this routine
  3256. ;
  3257. text:    call    byte        ;get next character
  3258.     cp    0        ;check for end of string
  3259.     ret    z        ;return if finished
  3260. ;
  3261. if not screen
  3262.     ld    e,a        ;pass character
  3263.     ld    c,05        ;select cp/m lst: output
  3264.     call    pdos        ;print it
  3265. endif
  3266. ;
  3267.     jp    text        ;loop back until done
  3268. ;
  3269. ;-----------------------------------------------------------------------
  3270. ;
  3271. ;    this subroutine uploads the array defining color pallet
  3272. ;
  3273. ;    inputs:
  3274. ;        16 bit integer specifying # of data bytes to come
  3275. ;        data bytes in input file
  3276. ;    outputs:
  3277. ;        new color values stored in appropriate arrays
  3278. ;    register status:
  3279. ;        all register values destroyed
  3280. ;    error conditions:
  3281. ;        none
  3282. ;
  3283. upload:    call    byte        ;get low byte of integer
  3284.     ld    c,a        ;save integer in [bc]
  3285.     call    byte        ;get high byte
  3286. ;
  3287.     or    a        ;check value of high byte
  3288.     jp    nz,upbad    ;for this program, hi byte must be 0
  3289.     ld    a,c        ;look at low byte
  3290.     cp    7d        ;7 indicates upload plaid patterns
  3291.     jp    z,uplaid    ;proceed to upload plaid values
  3292.     cp    64d        ;64 indicates upload dither matrix
  3293.     jp    z,updith    ;proceed to upload dither matrix
  3294.     cp    120d        ;124 indicates upload special patterns
  3295.     jp    z,upcif        ;proceed to upload special patterns
  3296. ;
  3297. upbad:    call    byte        ;# has unexpected value- skip bytes
  3298.     dec    bc        ;decrement loop counter
  3299.     ld    a,c
  3300.     or    b        ;is counter = 0 ?
  3301.     jp    nz,upbad    ;loop back until finished
  3302.     ret    
  3303. ;
  3304. uplaid:    ld    hl,plaids+1    ;point to plaid array (leave "0" alone)
  3305.     jp    uplp1        ;proceed to read-store loop
  3306. upcif:    ld    hl,cifpat    ;set pointer at start of special patterns
  3307.     jp    uplp1
  3308. updith:    ld    hl,ditharr    ;point to dither array
  3309. uplp1:    call    byte        ;get color pattern
  3310.     ld    (hl),a        ;store pattern
  3311.     inc    hl        ;point to next pattern slot
  3312.     dec    c        ;decrement counter
  3313.     jp    nz,uplp1    ;loop back until finished
  3314.     ret    
  3315. ;
  3316. ;-----------------------------------------------------------------------
  3317. ;    this subroutine is executed when overflow occurs in mult. or div
  3318. ;    inputs:
  3319. ;        none
  3320. ;    outputs:
  3321. ;        message "overflow"
  3322. ;        all registers pushed on stack
  3323. ;        in order: psw, h, d, b
  3324. ;        final position of stack pointer saved in oldstk
  3325. ;    register status:
  3326. ;        all input registers stored on stack, c, de, hl reg changed
  3327. ;    error conditions:
  3328. ;        none
  3329. ;
  3330. woops:    push    af        ;save all registers
  3331.     push    hl
  3332.     push    de
  3333.     push    bc
  3334.     ld    hl,0000h    ;clear (hl)
  3335.     add    hl,sp        ;get stack pointer
  3336.     ld    (oldstk),hl    ;save stack pointer for debug
  3337.     ld    c,09h        ;select print function
  3338.     ld    de,ovflmsg
  3339.     call    fdos        ; print 'overflow'
  3340.     jp    boot        ;return to cp/m command level
  3341. ovflmsg:    defb    'overflow$'
  3342. ;
  3343. ;-----------------------------------------------------------------------
  3344. ;    write record subroutine
  3345. ;
  3346. ;    inputs:
  3347. ;        opened file
  3348. ;        file control block @ fcb2
  3349. ;        buffer @ dma2
  3350. ;        buffer pointer @ pointr2
  3351. ;    outputs:
  3352. ;        buffer written to file
  3353. ;        buffer pointer reset to 0
  3354. ;    register status:
  3355. ;        all register values changed
  3356. ;    error conditions:
  3357. ;        if no space left on disk, error message written
  3358. ;        and program terminates.
  3359. ;
  3360. write:    ld    c,26d        ;select set dma function
  3361.     ld    de,dma2        ;pass o/p buffer
  3362.     call    fdos        ;set dma address
  3363. ;
  3364.     ld    c,21d        ;select write sequential
  3365.     ld    de,fcb2        ;pass o/p fcb
  3366.     call    fdos        ;write record
  3367. ;
  3368.     cp    00h        ;was write ok?
  3369.     jp    nz,fullxit    ;jump to error section if not
  3370.     ld    a,00h        ;clear (a)
  3371.     ld    (pointr2),a    ;pointr2=0
  3372.     ret            ;done with successful write
  3373. fullxit:    ld    c,09d    ;select print function
  3374.     ld    de,noroom    ;pass error message
  3375.     call    fdos        ;print it
  3376. ;
  3377.     jp    boot        ;terminate with warm start
  3378. ;
  3379. ;-----------------------------------------------------------------------
  3380. ;
  3381. ;    this subroutine is used for non-standard extensions to plot
  3382. ;
  3383. ;    inputs:
  3384. ;        none
  3385. ;    outputs:
  3386. ;        none
  3387. ;    regsister status:
  3388. ;        all values preserved
  3389. ;    error conditions:
  3390. ;        none
  3391. ;
  3392. xtend:    push    af
  3393.     push    bc
  3394.     push    de
  3395.     push    hl
  3396. ;
  3397.     call    byte        ;get low byte of number of data bytes
  3398.     ld    a,c
  3399.     call    byte        ;get high byte of number of bytes
  3400.     ld    a,b        ;[bc] is now 16 bit integer
  3401.     or    c        ;is number = 0?
  3402.     jp    z,xtnd2        ;finished if n = 0
  3403. xtnd1:    call    byte        ;get data byte
  3404.     dec    bc        ;decrement counter
  3405.     ld    a,c
  3406.     or    b        ;is counter = 0 ?
  3407.     jp    nz,xtnd1    ;loop back if more to come
  3408. xtnd2:    pop    hl        ;restore registers
  3409.     pop    de
  3410.     pop    bc
  3411.     pop    af
  3412.     ret            ;finished
  3413. ;
  3414. ;-----------------------------------------------------------------------
  3415. ;
  3416. origin:    ;start of picture map
  3417. ;
  3418. ;-----------------------------------------------------------------------
  3419.