home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / uploads / zplot10a.lbr / ZPLOT.ZZ0 / ZPLOT.Z80
Encoding:
Text File  |  1993-06-07  |  46.9 KB  |  1,799 lines

  1. ;-----------------------------------------------------------------------
  2. ;                Zplot
  3. ;-----------------------------------------------------------------------
  4. ;
  5. ;This program reads a sequential plot command file, makes a memory image
  6. ;of the plot, and prints the plot on the printer.
  7. ;
  8. ;Adapted and Z-ified by Greg Trice
  9. ;            476 Thorndale Drive
  10. ;            Waterloo, Ontario N2T1W5
  11. ;            Canada
  12. ;    from the program Plot33 by Thomas E. Speer
  13. ;
  14. ;    This program is released to the Public Domain
  15. ;
  16. ;Revision history
  17. ;
  18. ;    Zplot version 1.0    December 1989    Greg Trice
  19. ;    Rewritten in Z80 code, Z-system support added, allowing
  20. ;    du: or dir: specs for files. Support for non-Epson
  21. ;    printers removed (as just about every printer today supports
  22. ;    Epson graphics)
  23. ;------------------------------------------------------------------------
  24. ;
  25. true    equ    0ffffh
  26. false    equ    not true
  27. blank    equ    ' '
  28. CR    equ    0dh
  29. LF    equ    0ah
  30. bel    equ    7
  31. ESC    equ    1bh
  32. ;
  33. boot    equ    0        ;warm boot entry point
  34. fcb    equ    5ch        ;file control block
  35. tbuff    equ    80h        ;buffer
  36. bdos    equ    5        ;o/s entry point
  37. ;
  38. ;====================== Printer parameters ===============================
  39. ;this section sets the specific constants for your printer.
  40. ;
  41. ;***** NOTE ***** The maximum value for maxx that can be used is 1530.
  42. ;The maximum value for maxy that can be used is 1785. these limits
  43. ;are required to avoid arithmetic overflows.
  44. ;The size of the map ( (maxx+1)*(maxy+1)/7 ) must fit between the end of
  45. ;the program and the end of the tpa.
  46. ;To go into graphics mode, Epson printers use an <esc> sequence
  47. ;followed by a specified number of graphics bytes.
  48. ;
  49. maxx    equ    479        ;set maximum width to epson low res mode
  50. maxy    equ    573        ;set maximum height to make square plot
  51. mapsize    equ    39360        ;total size of map
  52. cwidth    equ    6        ;raster width of a printed character
  53.  
  54.     org    100h        ;beginning of tpa
  55.     jp    entry
  56.     db    'Z3ENV'
  57.     db    0
  58. z3eadr:
  59.     dw    0 
  60. banner:
  61.     db    '            ZPLOT Version 1.0 Dec 12 1989',CR,LF,'$'
  62. ;
  63. ;    set up graphic output buffer area
  64. esck:
  65.     db    ESC,'K'        ;define esc "K" character sequence
  66. ngraph:
  67.     dw    0        ;initialize graphic counter
  68. gbuff:
  69.     ds    maxx+1        ;set aside area for graphic o/p buffer
  70. ;
  71. ;========================= data storage section ============================
  72. ;
  73. color:
  74.     db    0
  75. xpos:
  76.     dw    0
  77. ypos:
  78.     dw    0
  79. x:
  80.     dw    0
  81. y:
  82.     dw    0
  83. yfill:
  84.     dw    0
  85. pointer:
  86.     db    128        ;file buffer ptr
  87. pointr2:
  88.     db    0        ;output file buffer ptr
  89. sysstk:
  90.     dw    0
  91. oldstk:
  92.     dw    0
  93. stack:
  94.     ds    80h        ;128 level stack
  95. olduser:
  96.     db    0
  97. xdot:
  98.     dw    0        ;dot x-coord
  99. ydot:
  100.     dw    0        ;dot y-coord
  101. xyaddr:
  102.     dw    origin        ;address of x,y location
  103. divdnd:
  104.     dw    0        ;divide routine variables
  105. divsor:
  106.     db    0        ;    "
  107. qotent:
  108.     db    0        ;    "
  109. rmandr:
  110.     db    0        ;    "
  111. nomem:
  112.     db    'Not Enough Memory',CR,LF,'$'
  113. nofile:
  114.     db    'File Not Found',CR,LF,'$'
  115. eofmsg:
  116.     db    'End of File',CR,LF,'$'
  117. nodir:
  118.     db    'No Directory Space Available',CR,LF,'$'
  119. noroom:
  120.     db    'Disk is Full',CR,LF,'$'
  121. unknch:
  122.     db    'Undefined Command Character Encountered',CR,LF,'$'
  123. stat1:
  124.     db    '              Working ...              ',CR,'$'
  125. stat2:
  126.     db    '                      ... Working      ',CR,'$'
  127. stat3:
  128.     db    '              Printing Picture         ',bel,CR,'$'
  129. statno:
  130.     db    0
  131. deltax:
  132.     dw    0        ;local variables for incplt
  133. deltay:
  134.     dw    0        ;    "
  135. epslnx:
  136.     dw    0        ;    "
  137. epslny:
  138.     dw    0        ;    "
  139. sx:
  140.     dw    0        ;    "
  141. sy:
  142.     dw    0        ;    "
  143. delta3:
  144.     dw    0        ;    "
  145. ni:
  146.     dw    0        ;    "
  147. ;
  148. cmask:
  149.     db    0ffh        ;color mask
  150. patrn:
  151.     ds    8        ;cell storage for clrmap (erase)
  152. plaids:
  153.     db    00h,01h,71h,13h,05h,0fh,35h,11h    ;cross hatched patterns
  154. ;
  155. cifpat:
  156.     db    00h, 03h, 48h, 03h, 00h, 30h, 84h, 30h ;nd
  157.     db    00h,0cch, 00h,0cch, 00h, 00h, 00h, 00h ;ni  s
  158.     db    08h, 04h, 02h, 01h, 80h, 40h, 20h, 10h ;nt   p
  159.     db    11h, 30h, 71h, 30h, 11h, 03h, 17h, 03h ;nc    e
  160.     db    22h, 00h, 88h, 00h, 22h, 00h, 88h, 00h ;nm     c
  161.     db    0c0h,81h, 03h, 06h, 03h, 81h,0c0h, 60h ;nb  p   i
  162.     db    1ch, 3eh, 36h, 3eh, 1ch, 00h, 00h, 00h ;ng   a   a
  163.     db    00h, 00h, 00h, 00h, 00h, 00h, 00h, 01h ;cw    t   l
  164.     db    04h, 11h, 04h, 00h, 40h, 11h, 40h, 00h ;cd     t  
  165.     db    02h, 04h, 08h, 10h, 20h, 40h, 80h, 01h ;cp     e
  166.     db    00h, 00h, 10h, 38h, 10h, 00h, 00h, 00h ;cs      r
  167.     db    66h, 99h, 99h, 66h, 66h, 99h, 99h, 66h ;cc       n
  168.     db    00h, 00h, 80h, 10h, 00h, 00h, 10h, 80h ;cm        s
  169.     db    81h,0c3h, 66h, 66h,0c3h, 81h, 00h, 00h ;cg
  170.     db    0fh, 0eh, 0ch, 08h, 00h, 00h, 00h, 00h ;ce
  171. ;
  172. ditharr:
  173.     db     63,  95,  71, 103,  65,  97,  73, 105 ;ordered
  174.     db    111,  79, 119,    87, 113,  81, 121,  89 ;
  175.     db     75, 107,  67,  99,  77, 109,  69, 101 ;dither
  176.     db    123,  91, 115,    83, 125,  93, 117,  85 ;
  177.     db     66,  98,  74, 106,  64,  96,  72, 104 ;matrix
  178.     db    114,  82, 122,    90, 112,  80, 120,  88 ;
  179.     db     78, 110,  70, 102,  76, 108,  68, 100 ;
  180.     db    126,  94, 118,    86, 124,  92, 116,  84 ;
  181. fcb2:
  182.     ds    33        ;output fcb
  183. obuff:
  184.     ds    128        ;output file buffer
  185. opdisk:
  186.     db    0        ;output to disk flag
  187. ;
  188. ;-----------------------------------------------------------------------
  189. ;
  190. helpmsg:
  191.     db    'ZPLOT 1.0 ',CR,LF
  192.     db    'Usage - ZPLOT infile[.VEC] [outfile[.PLT]]',CR,LF
  193.     db    'If outfile is not supplied,'
  194.     db    ' output goes directly to printer.',CR,LF,'$'
  195. help:
  196.     ld    c,9
  197.     ld    de,helpmsg
  198.     jp    bdos
  199. ;
  200. ;----------------------------------------------------------------------
  201. ;
  202. entry:
  203.     ld    a,(tbuff)
  204.     or    a        ;no command tail
  205.     jr    z,help
  206.     ld    a,(fcb+1)
  207.     cp    '/'
  208.     jr    z,help        ;help requested
  209.     ld    c,9
  210.     ld    de,banner    ;print banner message
  211.     call    bdos
  212.     ld    hl,(bdos+1)    ;get end of tpa
  213.     ld    de,origin    ;start of bitmap
  214.     or    a
  215.     sbc    hl,de        ;total workspace available in HL
  216.     ld    de,mapsize    ;workspace needed
  217.     sbc    hl,de        ;must be >=0
  218.     jr    nc,wsok
  219.     ld    de,nomem    ;error message
  220.     ld    c,9
  221.     jp    bdos        ;display it and exit
  222.  
  223. wsok:
  224.     ld    hl,0
  225.     add    hl,sp
  226.     ld    (sysstk),hl    ;save system stack
  227.     ld    sp,stack+80h    ;set new stack
  228.     ld    c,32
  229.     ld    e,0ffh        ;get user
  230.     call    bdos
  231.     ld    (olduser),a    ;save it
  232.     ld    iy,fcb        ;pointer to fcb
  233.     ld    a,(iy+9)    ;get first character of file type
  234.     cp    blank        ;is type blank?
  235.     jr    nz,name        ;no type has been specified
  236.     ld    a,'V'        ;make default type "VEC"
  237.     ld    (iy+9),a
  238.     ld    a,'E'
  239.     ld    (iy+10),a
  240.     ld    a,'C'
  241.     ld    (iy+11),a
  242. name:
  243.     ld    a,(iy+17)    ;get 1st char of o/p file
  244.     cp    blank        ;is name blank?
  245.     jr    z,openfil    ;blank= normal print output
  246.     ld    a,1        ;set o/p file flag=1 (disk o/p)
  247.     ld    (opdisk),a    ;store flag
  248.     ld    bc,16
  249.     ld    hl,fcb+16    ;move o/p file name
  250.     ld    de,fcb2        ;to output fcb
  251.     ldir
  252.     xor    a
  253.     ld    ix,fcb2        ;pointer to output fcb
  254.     ld    (ix+32),a    ;zero cr field in o/p fcb
  255.     ld    a,(ix+9)    ;get 1st char in o/p file type
  256.     cp    blank        ;is file type blank?
  257.     jr    nz,delete    ;not blank- go to delete old
  258.     ld    a,'P'        ;make default 'plt'
  259.     ld    (ix+9),a
  260.     ld    a,'L'
  261.     ld    (ix+10),a
  262.     ld    a,'T'
  263.     ld    (ix+11),a
  264. delete:
  265.     ld    e,(iy+29)
  266.     ld    c,32
  267.     call    bdos        ;set o/p user #
  268.     ld    de,fcb2        ;o/p fcb
  269.     ld    c,19        ;delete 
  270.     call    bdos
  271.     ld    c,26        ;set dma 
  272.     ld    de,obuff    ;o/p file buffer
  273.     call    bdos
  274.     ld    c,22        ;make file 
  275.     ld    de,fcb2        ;o/p fcb
  276.     call    bdos
  277.     cp    0ffh        ;is directory full?
  278.     jr    nz,openfil    ;no- go on with program
  279.     ld    c,9
  280.     ld    de,nodir    ;no directory space msg
  281.     call    bdos
  282.     jp    exit        ;fatal error- quit
  283.  
  284. ;
  285. ;open disk file of plot commands
  286. ;
  287. openfil:
  288.     ld    e,(iy+13)
  289.     ld    c,32
  290.     call    bdos        ;set user #
  291.     ld    c,26        ;set dma 
  292.     ld    de,tbuff    ;i/p buffer
  293.     call    bdos
  294.     ld    c,15        ;open file
  295.     xor    a
  296.     ld    (iy+12),a    ;clear extent counter
  297.     ld    (iy+14),a    ;clear s2
  298.     ld    de,fcb
  299.     call    bdos
  300.     cp    0ffh        ;was file found?
  301.     jr    nz,rewind    ;if file exits, rewind it
  302.     ld    c,9
  303.     ld    de,nofile    ;error message
  304.     call    bdos
  305.     jp    exit        ;done
  306. ;
  307. rewind:
  308.     xor    a
  309.     ld    (iy+32),a    ;rewind by setting record#=0
  310. parse:
  311.     call    byte        ;get command character
  312.     cp    60h        ;is it lower case?
  313.     jr    c,parse0    ;no
  314.     xor    00100000b    ;change to upper case
  315. parse0:
  316.     ld    bc,16        ;number of valid command bytes
  317.     ld    hl,commands    ;list of command bytes
  318.     cpir            ;check against list
  319.     jr    z,parse1    ;a match is found
  320.     ld    c,9
  321.     ld    de,unknch    ;unknown command
  322.     call    bdos
  323.     jr    parse        ;get next byte
  324.  
  325. parse1:
  326.     ld    ix,comtabl    ;table of command routines
  327.     add    ix,bc
  328.     add    ix,bc        ;point to selected routine
  329.     ld    de,parse    ;return address
  330.     push    de
  331.     ld    l,(ix+0)    ;get the address in HL
  332.     ld    h,(ix+1)
  333.     jp    (hl)        ;dispatch to routine
  334.  
  335. parse2:
  336.     pop    hl        ;discard return address
  337.     jr    parse        ;get next byte
  338.  
  339. commands:
  340.     db    'PCDEFIMNOQSTUX',CR,LF
  341. comtabl:
  342.     dw    parse2        ;ignore line feeds
  343.     dw    parse2        ;ignore carriage returns
  344.     dw    xtend        ;provision for non-standard commands
  345.     dw    upload        ;upload of color patterns
  346.     dw    text        ;raw text output
  347.     dw    string        ;character string plotting
  348.     dw    quit        ;termination of program
  349.     dw    mapout        ;printing of plot
  350.         dw    parse2        ;no operation loop
  351.     dw    move        ;move to coord w/o plotting
  352.     dw    incplt        ;plot incremental segment
  353.     dw    fill        ;fill area to color
  354.     dw    clrmap        ;clear memory map to color
  355.     dw    plotseg     ;plot segment
  356.     dw    colour        ;set color
  357.     dw    point        ;plot point
  358. ;
  359. ;-----------------------------------------------------------------------
  360. ;    Exit restoring original user
  361. exit:
  362.     ld    a,(olduser)
  363.     ld    e,a
  364.     ld    c,32        ;set user #
  365.     call    bdos
  366.     ld    hl,(sysstk)    ;get system stack
  367.     ld    sp,hl        ;reset stack
  368.     jp    boot        ;back to system
  369. ;
  370. ;-----------------------------------------------------------------------
  371. ;    Multiply A by HL, result in AHL
  372. bmult:
  373.     ld    hl,0        ;zero partial product
  374.     ld    de,7        ;d=0,e=bit counter
  375.     add    a,a        ;get first multiplier bit
  376. loop1:
  377.     jr    nc,zero        ;zero skip
  378.     add    hl,bc        ;one-add multiplicand
  379.     adc    a,d        ;add carry to third byte of product
  380. zero:
  381.     add    hl,hl        ;shift product left
  382.     adc    a,a
  383.     dec    e        ;decr bit counter
  384.     jr    nz,loop1    ;loop until done
  385.     ret    nc        ;done if no carry
  386.     add    hl,bc        ;otherwise do last add
  387.     adc    a,d
  388.     ret
  389. ;-----------------------------------------------------------------------
  390. ;    Gets next byte in buffer, next record is read if need be
  391. byte:
  392.     push    bc        ;save registers
  393.     push    de
  394.     push    hl
  395.     ld    a,(pointer)    ;get pointer value
  396.     cp    128        ;is pointer=128?
  397.     call    z,read        ;get record if last one was #128
  398.     ld    hl,pointer    ;get new pointer
  399.     inc    (hl)        ;incr pointer
  400.     ld    c,(hl)        ;get pointer in BC
  401.     ld    b,0
  402.     ld    hl,tbuff-1    ;load hl with byte before tbuff
  403.     add    hl,bc        ;calculate addr of desired byte
  404.     ld    a,(hl)        ;get byte
  405.     pop    hl        ;restore registers
  406.     pop    de
  407.     pop    bc
  408.     ret            ;done-- byte is in A
  409. ;-----------------------------------------------------------------------
  410. ;    Print character in A
  411. ;    outputs:
  412. ;        graphic buffer is flushed
  413. ;        character is put out to printer
  414. ;        address in HL is incremented by (cwidth - 1)
  415. ;        dot counter incremented by (cwidth - 1)
  416. ;        the above are to account for the size of a character
  417. ;        as opposed to a single dot
  418. charout:
  419.     push    af        ;save registers
  420.     push    bc
  421.     push    de
  422.     push    hl
  423.     xor    10000000b    ;clear high bit of character
  424.     call    gbufout        ;flush graphic buffer
  425.     ld    c,5        ;list output
  426.     ld    e,a        ;character
  427.     call    pdos        ;send character to printer
  428.     pop    hl        ;recall registers
  429.     pop    de
  430.     ld    a,cwidth-1
  431. charo1:
  432.     inc    hl        ;incr address
  433.     dec    de        ;decr dot counter
  434.     sub    1        ;decr loop counter
  435.     jr    nz,charo1
  436.     pop    bc
  437.     pop    af
  438.     ret
  439. ;
  440. ;-----------------------------------------------------------------------
  441. ;    Clear memory
  442. ;    inputs:    bitmap of size mapsize located at origin
  443. ;        map color stored in color
  444. ;        (pos = patterned, 0 = white, - = complementary)
  445. ;        Entire map area set to desired color or pattern
  446. clrmap:
  447.     ld    a,(color)    ;get color
  448.     or    a        ;check color
  449.     jr    nz,clrnz    ;non-white?
  450.     ld    de,mapsize    ;put mapsize in DE as counter
  451.     ld    hl,origin    ;put start of map in HL
  452.     ld    c,0        ;c contains image of white byte
  453. clrlp1:
  454.     ld    (hl),c        ;store byte
  455.     inc    hl        ;incr address in map
  456.     dec    de        ;decr loop counter
  457.     ld    a,d
  458.     or    e
  459.     jr    nz,clrlp1    ;loop until done
  460.     ret
  461. ;
  462. clrnz:
  463.     push    af        ;save flag values
  464.     ld    hl,patrn+7    ;point to last in pattern sequence
  465.     ld    c,7        ;initialize x counter
  466. clrlp2:
  467.     ld    d,80h        ;set up y bit select
  468.     ld    e,7        ;initialize y counter
  469.     ld    b,0        ;initialize pattern
  470. clrlp3:
  471.     call    clrmsk        ;form color mask based on x,y
  472.     ld    a,(cmask)    ;get mask
  473.     and    d        ;one bit
  474.     or    b        ;add bit to pattern
  475.     ld    b,a        ;save new pattern
  476.     rrc    d        ;move select bit down one notch
  477.     dec    e        ;decr y counter
  478.     jp    p,clrlp3    ;jump back if not negative (need 0 pass)
  479.     pop    af        ;retrieve color code flag settings
  480.     push    af        ;re-save flags settings
  481.     jp    p,clrl31    ;positive flag means pattern is ok
  482.     ld    a,b        ;get pattern
  483.     cpl            ;complement pattern for negative colors
  484.     ld    b,a        ;store pattern byte
  485. clrl31:
  486.     ld    (hl),b        ;save pattern for this x location
  487.     dec    hl        ;move memory pointer over
  488.     dec    c        ;decr x coordinate/counter
  489.     jp    p,clrlp2    ;only done when negative (need 0 pass)
  490.     ld    c,[maxy+1] mod 8+1 ;counter for rotations due to mismatch
  491. clrlp4:
  492.     call    rotpat        ;rotate pattern array 1 position
  493.     dec    c        ;decr counter
  494.     jr    nz,clrlp4    ;loop back if not done
  495.     ld    hl,origin    ;set map pointer to start of map
  496.     ld    bc,[maxy+1]/7    ;initialize line counter
  497. clrlp5:
  498.     ld    de,[maxx+1]/8    ;initalize dot counter
  499. clrl51:
  500.     ld    ix,patrn    ;pointer to pattern
  501.     exx
  502.     ld    b,8        ;loop counter
  503. clrl52:
  504.     exx
  505.     ld    a,(ix+0)    ;get byte
  506.     and    7fh        ;clear hi bit
  507.     ld    (hl),a        ;store pattern in memory map
  508.     inc    hl        ;move memory pointer
  509.     inc    ix        ;move pattern pointer
  510.     exx    
  511.     djnz    clrl52        ;repeat for entire pattern
  512.     exx
  513.     dec    de        ;decr x counter
  514.     ld    a,e
  515.     or    d        ;is counter zero?
  516.     jr    nz,clrl51    ;loop back until done
  517.     ld    e,[maxx+1]mod 8 ;set counter for rest of line
  518.     ld    d,7        ;pattern loop counter
  519.     ld    ix,patrn    ;pointer to pattern
  520.     inc    e
  521. clrl53:
  522.     dec    e
  523.     jr    z,clrlp6    ;jump out of loop if done
  524.     ld    a,(ix+0)    ;apply pattern to remaining bytes
  525.     and    7fh        ;clear hi bit
  526.     ld    (hl),a        ;store pattern in memory map
  527.     inc    hl        ;move memory pointer
  528.     inc    ix
  529.     dec    d
  530.     jr    nz,clrl53    ;repeat for entire pattern
  531. clrlp6:
  532.     call    rotpat        ;rotate pattern down to match cells
  533.     dec    bc        ;decr line counter
  534.     ld    a,c
  535.     or    b        ;is counter = 0?
  536.     jr    nz,clrlp5    ;loop back up for another if req'd
  537.     pop    af        ;clean up stack
  538.     ret
  539. ;
  540. ;-----------------------------------------------------------------------
  541. ;    Forms the color mask used in plotting points
  542. ;
  543. ;    Method:    The plot is divided up into 8 x 8 raster cells.
  544. ;        For color values between 1 and 63, the cell is composed
  545. ;        of an x pattern and a y pattern which are xor'ed with
  546. ;        each other to form a "PLAID" pattern
  547. ;        For color values 64 and above, ordered dithering is used
  548. ;        Ordered dithering is a technique in which the dots in
  549. ;        the cell are added in in a pre-arranged position based
  550. ;        upon the "INTENSITY" of the cell.  The intersection of
  551. ;        the point and the pattern (stored in the array "DITHARR"
  552. ;        determines whether or not the point is plotted
  553. ;        For both methods, a color mask is created, which is
  554. ;        all 1's if the point in the pattern plane is on, or
  555. ;        all 0's if the point in the pattern plane is off.
  556. ;    inputs:
  557. ;        x coordinate in bc
  558. ;        y coordinate in de
  559. ;    outputs:
  560. ;        color mask stored in cmask
  561. ;
  562. clrmsk:
  563.     push    af        ;save registers
  564.     push    bc
  565.     push    de
  566.     push    hl
  567.     ld    a,c        ;form x cell coordinate
  568.     and    00000111b
  569.     ld    b,a
  570.     ld    a,e        ;form y cell coordinate
  571.     and    00000111b
  572.     ld    c,a
  573.     ld    a,(color)    ;get color code
  574.     or    a        ;set flags based on basic code
  575.     jp    z,whtmsk    ;zero color => white mask
  576.     jp    p,posclr    ;color code is positive
  577.     cpl            ;complement color
  578.     inc    a        ;color code is now positive
  579. posclr:
  580.     cp    64        ;is color code < 64
  581.     jr    nc,dither    ;code >=64 --> dithered
  582.     cp    49        ;is color code < 49
  583.     jr    nc,special    ;code from 49 to 63 --> cifpat's else plaid
  584.     push    af        ;save color code
  585.     and    00000111b    ;select lower 3 bits of color code
  586.     exx
  587.     ld    hl,plaids    ;get base address of basic pattern
  588.     ld    d,0
  589.     ld    e,a
  590.     add    hl,de        ;add x code to base addr to find pattern
  591.     ld    a,(hl)        ;get x pattern for cell
  592.     exx
  593.     inc    b        ;incr x coordinate to be counter
  594. xcellp:
  595.     rra            ;rotate pattern bit into carry
  596.     djnz    xcellp        ;loop back if not done
  597.     ld    a,0ffh        ;carry --> pattern bit says plot point
  598.     jr    c,savxmsk
  599.     xor    a
  600. savxmsk:
  601.     ld    b,a        ;replace x cell coord with x color mask
  602.     pop    af        ;retrieve color code
  603.     and    00111000b    ;select 2nd 3 bits for y code
  604.     rrca            ;rotate bits to low order position
  605.     rrca
  606.     rrca
  607.     exx
  608.     ld    hl,plaids    ;get base address of basic pattern
  609.     ld    e,a
  610.     ld    d,0
  611.     add    hl,de        ;add x code to base addr to find pattern
  612.     ld    a,(hl)        ;get y pattern for cell
  613.     exx
  614.     inc    c        ;incr y coordinate to be counter
  615. ycellp:
  616.     rra            ;rotate pattern bit into carry
  617.     dec    c        ;decr counter
  618.     jr    nz,ycellp    ;loop back if not done
  619.     ld    a,0ffh        ;dot will be plotted if carry set
  620.     jr    c,savymsk
  621.     xor    a
  622. savymsk:
  623.     xor    b        ;final color mask-- x patrn xor y patrn
  624.     ld    (cmask),a    ;save color mask
  625.     pop    hl        ;restore registers
  626.     pop    de
  627.     pop    bc
  628.     pop    af
  629.     ret
  630. ;
  631. dither:
  632.     push    af        ;save color code for future use
  633.     ld    a,c        ;multiply y cell coordinate by 8
  634.     rlca
  635.     rlca
  636.     rlca
  637.     add    a,b        ;offset into dither table = y*8 + x
  638.     ld    hl,ditharr    ;get base address of table
  639.     ld    e,a
  640.     ld    d,0
  641.     add    hl,de        ;add offset to base address
  642.     ld    a,(hl)        ;get dither table value
  643.     pop    de        ;retrieve color code (formerly in A)
  644.     cp    d        ;is dither value > color code?
  645.     ld    a,0ffh        ;carry--> plot point
  646.     jr    c,savmsk
  647.     xor    a        ;carry not set--> don't plot point
  648. savmsk:
  649.     ld    (cmask),a    ;store mask for future use
  650.     pop    hl
  651.     pop    de
  652.     pop    bc
  653.     pop    af        ;registers restored, stack cleaned up
  654.     ret
  655. ;
  656. special:
  657.     sub    49        ;code is now relative to 49
  658.     rlca            ;code * 8
  659.     rlca
  660.     rlca
  661.     add    a,b        ;add x coord to form offset into array
  662.     exx
  663.     ld    hl,cifpat    ;get fwa of pattern array
  664.     ld    e,a
  665.     ld    d,0
  666.     add    hl,de        ;add offset to fwa
  667.     ld    a,(hl)        ;get pattern byte for this x coord.
  668.     exx
  669.     inc    c        ;incr y coord to form counter
  670. spclp:
  671.     rra            ;rotate pattern bit into carry
  672.     dec    c        ;decr counter
  673.     jr    nz,spclp    ;loop back until done
  674.     ld    a,0ffh        ;dot will be plotted if carry set
  675.     jr    c,savmsk
  676.     xor    a        ;carry not set- don't plot point
  677.     jr    savmsk
  678. ;
  679. whtmsk:
  680.     ld    a,0ffh        ;for white, always modify dot
  681.     jr    savmsk        ;save mask and return
  682. ;
  683. ;-----------------------------------------------------------------------
  684. ;    Define color
  685. ;    inputs:
  686. ;        buffer @ tbuff
  687. ;    outputs:
  688. ;        color value saved for future reference
  689. colour:
  690.     call    byte        ;get color value
  691.     ld    (color),a    ;save it
  692.     ret
  693. ;
  694. ;-----------------------------------------------------------------------
  695. ;    Compute the next point in a line segment.
  696. ;    Must be used with seginit to initialize all variables first.
  697. ;
  698. ;    inputs:
  699. ;        ni        counter used by calling sub. to know when done.
  700. ;        xpos,ypos    present position
  701. ;        dx,dy        size of line segment along x,y axis
  702. ;        epslnx,epslny,sx,sy,delta3    local variables
  703. ;
  704. compseg:
  705.     ld    hl,(ni)
  706.     inc    hl        ;incr. ni
  707.     ld    (ni),hl
  708.     ld    bc,(xpos)
  709.     ld    de,(ypos)
  710.     ld    hl,(epslnx)
  711.     add    hl,bc        ;add epsilon x to x position
  712.     ld    (xpos),hl    ;store new value
  713.     ld    hl,(epslny)    ;fetch epsilon y
  714.     add    hl,de        ;add epsilon y to y position
  715.     ld    (ypos),hl    ;store new value of y position
  716.     ld    de,(deltay)
  717.     ld    hl,(delta3)
  718.     add    hl,de        ;add delta y to delta 3
  719.     ld    (delta3),hl    ;store new value of delta3
  720.     ld    de,(deltax)
  721.     or    a
  722.     sbc    hl,de
  723.     jr    c,dopt        ;dx > d3- plot point
  724.     ld    (delta3),hl    ;store  d3=d3-dx
  725.     ld    hl,(sx)        ;compute xpos=xpos+sx
  726.     ld    de,(xpos)
  727.     add    hl,de        ;add sx to xpos
  728.     ld    (xpos),hl    ;store result
  729.     ld    hl,(sy)        ;compute ypos=ypos+sy
  730.     ld    de,(ypos)
  731.     add    hl,de        ;add sy
  732.     ld    (ypos),hl    ;store new y position
  733. dopt:
  734.     ret
  735. ;
  736. ;-----------------------------------------------------------------------
  737. ;        Carriage return routine
  738. ;        Printer carriage is returned and paper advanced
  739. crlf:
  740.     push    af        ;save all registers
  741.     push    bc
  742.     push    de
  743.     push    hl
  744.     ld    c,5        ;list output
  745.     ld    e,CR
  746.     call    pdos
  747.     ld    c,5
  748.     ld    e,LF
  749.     call    pdos
  750.     pop    hl        ;restore registers
  751.     pop    de
  752.     pop    bc
  753.     pop    af
  754.     ret
  755. ;
  756. ;-----------------------------------------------------------------------
  757. ;    Form the mask for the plotting of a point
  758. ;    digit= ycoord mod 7
  759. ;    inputs:
  760. ;        xcoord in bc
  761. ;        ycoord in de
  762. ;        xyaddr in hl
  763. ;    outputs:
  764. ;        contents of xyaddr in b
  765. ;        mask (1 bit on) in c
  766. ;        ycoord in de
  767. ;        xyaddr in hl
  768. ;
  769. digit:
  770.     push    hl        ;save xyaddress
  771.     push    de        ;save ycoord
  772.     call    clrmsk        ;prepare color mask for future use
  773.     ex    de,hl        ;put ycoord in hl
  774.     ld    (divdnd),hl    ;calculate ycoord mod 7
  775.     ld    a,7
  776.     ld    (divsor),a
  777.     call    divide        ;mod is divide w/o quotient
  778.     ld    a,(rmandr)    ;get result
  779.     or    a        ;set flags
  780.     call    m,woops        ;rmandr= -1 on overflow
  781.     ld    b,a        ;move # of digit to b
  782.     xor    a
  783.     inc    b        ;incr b to init for 1st dec
  784.     scf            ;clear accum, put 1 in carry
  785. rotmask:
  786.     rla            ;move mask bit 1 left
  787.     djnz    rotmask        ;loop back
  788.     ld    c,a        ;store mask temporarily
  789.     ld    a,(cmask)    ;get color mask
  790.     and    c        ;and bit mask with color mask- both rqd
  791.     ld    c,a        ;put mask in c
  792.     pop    de        ;bring back ycoord
  793.     pop    hl        ;bring back (xyaddr)
  794.     ld    b,(hl)        ;get byte @ (xyaddr)
  795.     ret
  796. ;
  797. ;-----------------------------------------------------------------------
  798. ;    16 bit by 8 bit division routine
  799. ;    inputs:
  800. ;        divdnd    two byte positive number
  801. ;        divsor    one byte positive number
  802. ;    outputs:
  803. ;        qotent    one byte positive quotient
  804. ;        rmandr    one byte positive remainder or flag
  805. ;    error conditions:
  806. ;        rmandr=-1 if overflow occurs
  807. ;
  808. divide:
  809.     push    af        ;save registers
  810.     push    bc
  811.     push    de
  812.     push    hl
  813.     ld    de,(divdnd)    ;fetch dividend
  814.     ld    a,(divsor)    ;fetch divsor
  815.     ld    c,a        ;save in register c
  816.     ld    b,8        ;loop counter in register b
  817. divloop:
  818.     and    a        ;clear carry
  819.     rl    e        ;shift low order byte to left
  820.     ld    a,d        ;fetch high order byte
  821.     rla            ;rotate bringing in high bit
  822.     sub    a,c        ;subtract divisor
  823.     jp    p,setbit    ;if result was positive, jump
  824.     add    a,c        ;otherwise add back divisor
  825.     ld    d,a        ;replace high order byte
  826.     jr    next        ;go to incr phase
  827. setbit:
  828.     ld    d,a        ;replace high order byte
  829.     set    0,e        ;set low order bit
  830. next:
  831.     djnz    divloop        ;repeat until done
  832.     bit    7,e        ;test sign of result
  833.     jr    z,ok        ;if positive result is accurate
  834.     ld    a,0ffh        ;set overflow value
  835.     ld    (rmandr),a
  836.     jr    done
  837. ok:
  838.     ld    a,e
  839.     ld    (qotent),a    ;save quotient
  840.     ld    a,d
  841.     ld    (rmandr),a    ;save remainder
  842. done:
  843.     pop    hl
  844.     pop    de
  845.     pop    bc
  846.     pop    af
  847.     ret
  848. ;
  849. ;-----------------------------------------------------------------------
  850. ;    Plots the vertical line used to fill in areas
  851. ;    inputs:
  852. ;        xpos,ypos    current position on segment
  853. ;        yfill        horizontal level to fill to
  854. ;    outputs:
  855. ;        vertical line from (xpos,ypos) to (xpos,yfill)
  856. ;        note: all coordinate values assumed to be positive
  857. filine:
  858.     call    stat        ;update status message
  859.     ld    hl,(xpos)    ;get starting coordinates of line
  860.     ld    (xdot),hl    ;xpos will be x coord of all dots
  861.     ld    de,(ypos)    ;get y coordinate
  862.     push    de        ;save y position- plotdot will reset it
  863.     ld    hl,(yfill)    ;get y fill value
  864.     or    a
  865.     push    hl
  866.     sbc    hl,de        ;compare y coordinates for top and bot.
  867.     pop    hl
  868.     jr    c,contfil    ;yfill definitely less than ypos
  869.     ex    de,hl        ;switch ypos and yfill- larger val in de
  870. contfil:
  871.     ld    (ydot),hl    ;y coordinate to plotdot
  872.     push    de        ;save registers
  873.     push    hl
  874.     call    plotdot        ;plot point
  875.     pop    hl        ;retrieve registers
  876.     pop    de
  877.     inc    hl        ;incr y position
  878.     or    a
  879.     push    hl
  880.     sbc    hl,de
  881.     pop    hl
  882.     jr    c,contfil    ;new coordinate definitely below end
  883.     pop    hl        ;retrieve line y position
  884.     ld    (ypos),hl    ;restore value
  885.     ret
  886. ;
  887. ;-----------------------------------------------------------------------
  888. ;    Fill an area between a line segment and a horizontal line
  889. ;    inputs:
  890. ;        Buffer containing coordinate pairs and y coordinate of
  891. ;        fill level.
  892. ;    outputs:
  893. ;        xpos,ypos updated to end of line segment
  894. ;        area between segment and yfill is filled with current
  895. ;        color value
  896. fill:
  897.     call    readxy        ;get starting coordinates
  898.     ld    hl,(x)
  899.     ld    (xpos),hl    ;update x position to start of segment
  900.     ld    hl,(y)
  901.     ld    (ypos),hl    ;update y position to start of segment
  902.     call    readxy        ;get end coordinates
  903.     call    byte        ;get first byte of fixed pt. y fill
  904.     push    af        ;save first byte
  905.     call    byte        ;get second byte
  906.     ld    b,a        ;put high byte in B
  907.     pop    af        ;get low byte
  908.     ld    c,a        ;BC now contains y coord.
  909.     ld    de,maxy*2    ;maximum raster address
  910.     call    mult        ;multiply y coord by no. of y rasters
  911.     ex    de,hl        ;put high bytes in HL
  912.     ld    (yfill),hl    ;save integer value of y fill level
  913.     call    seginit        ;initialize variables for seg. interp.
  914.     call    filine        ;fill area between first pt. & yfill
  915. strtfil:
  916.     call    compseg        ;compute next point in segment
  917.     ld    hl,(deltax)    ;top of loop- end when ni>dx
  918.     ld    de,(ni)        ;get counter
  919.     or    a
  920.     sbc    hl,de        ;compare counter w/dx
  921.     ret    c        ;ni > dx
  922.     ld    de,(xdot)    ;compare xdot and xpos
  923.     ld    hl,(xpos)
  924.     or    a
  925.     sbc    hl,de        ;are the two exactly the same?
  926.     jr    z,strtfil    ;yes- skip this position
  927.     call    filine        ;fill area between segment & yfill
  928.     jr    strtfil        ;loop back to top
  929. ;
  930. ;-----------------------------------------------------------------------
  931. ;    Send a string of characters to the printer
  932. ;    inputs:
  933. ;        number-1 of characters to send in DE
  934. ;        address-1 of first character in HL
  935. ;    outputs:
  936. ;        0 through DE characters sent to printer
  937. gboloop:
  938.     dec    de        ;decr counter
  939.     inc    hl        ;incr address
  940.     push    de        ;save counter
  941.     push    hl
  942.     ld    e,(hl)        ;get character
  943.     ld    c,5        ;list output 
  944.     call    pdos        ;send character out
  945.     pop    hl        ;retrieve address
  946.     pop    de        ;retrieve counter
  947.     ld    a,e        ;is counter =0?
  948.     or    d
  949.     jr    nz,gboloop    ;not done: loop back
  950.     ret
  951. ;
  952. ;-----------------------------------------------------------------------
  953. ;    Save a byte from bit map in graphic buffer
  954. ;    inputs:
  955. ;        byte in B
  956. ;        2 byte counter @ ngraph
  957. ;    outputs:
  958. ;        ngraph incremented
  959. ;        byte stored in buffer @ gbuff
  960. ;        buffer flushed if full
  961. gbufin:
  962.     push    af        ;save registers
  963.     push    bc
  964.     push    de
  965.     push    hl
  966.     ld    de,(ngraph)    ;get no. of bytes in buffer
  967.     inc    de        ;incr ngraph
  968.     ld    (ngraph),de    ;store new value
  969.     ld    hl,gbuff-1    ;get buffer base address
  970.     add    hl,de        ;add counter to base address
  971.     ld    (hl),b        ;store byte
  972.     ld    hl,maxx+1    ;put max no. of bytes in HL
  973.     or    a
  974.     sbc    hl,de        ;compare ngraph with (max no. of bytes)
  975.     call    z,gbufout    ;buffer is full- flush it to printer
  976.     pop    hl        ;restore registers
  977.     pop    de
  978.     pop    bc
  979.     pop    af
  980.     ret
  981. ;
  982. ;-----------------------------------------------------------------------
  983. ;    Flush the graphic buffer
  984. ;    inputs:
  985. ;        graphic buffer @ gbuff
  986. ;        number of valid bytes in buffer @ ngraph
  987. ;        "ESC K" sequence stored ahead of ngraph
  988. ;    outputs:
  989. ;        printer is placed in dot graphic mode
  990. ;        graphic string transmitted byte by byte to printer
  991. ;
  992. gbufout:
  993.     push    af        ;save registers
  994.     push    bc
  995.     push    de
  996.     push    hl
  997.     ld    hl,(ngraph)    ;fetch buffer counter
  998.     ld    a,l        ;look at low byte
  999.     or    h        ;is counter=0?
  1000.     jr    z,gbufret    ;if buffer is empty, don't o/p anything
  1001.     ld    bc,maxx+1    ;get length of buffer
  1002.     or    a
  1003.     sbc    hl,bc
  1004.     jr    nz,gbo2        ;no match indicates something on this line
  1005.     ld    hl,gbuff    ;set pointer to start of buffer
  1006. gbo1:
  1007.     ld    a,(hl)        ;get byte from buffer
  1008.     or    a        ;is it a blank stroke?
  1009.     jr    nz,gbo2        ;go to output section if not blank
  1010.     inc    hl        ;point to new byte
  1011.     dec    bc        ;decr counter
  1012.     ld    a,b        ;check for zero
  1013.     or    c
  1014.     jr    nz,gbo1        ;repeat until last byte has been checked
  1015.     jr    gbufret        ;return w/o plotting since all were blank
  1016. ;
  1017. gbo2:
  1018.     ld    de,(ngraph)    ;number of chars to output
  1019.     inc    de        ;add 4 for escape sequencew
  1020.     inc    de
  1021.     inc    de
  1022.     inc    de
  1023.     ld    hl,esck-1    ;start with escape sequence
  1024.     call    gboloop        ;send out string of graphic characters
  1025. gbufret:
  1026.     ld    hl,0
  1027.     ld    (ngraph),hl    ;set ngraph=0
  1028.     pop    hl        ;restore registers
  1029.     pop    de
  1030.     pop    bc
  1031.     pop    af
  1032.     ret
  1033. ;
  1034. ;-----------------------------------------------------------------------
  1035. ;    Plot an incremental line segment from the present position
  1036. ;    inputs:
  1037. ;        file buffer @ tbuff
  1038. ;        present position @ xpos,ypos
  1039. ;    outputs:
  1040. ;        xpos, ypos updated to x,y
  1041. ;        visible portion of line segment drawn
  1042. incplt:
  1043.     call    readxy        ;get end point values
  1044.     call    seginit        ;initialize segment interpolation sub.
  1045. strtplt:
  1046.     ld    de,(deltax)    ;top of loop- end when ni>dx
  1047.     ld    hl,(ni)        ;get counter
  1048.     or    a
  1049.     sbc    hl,de
  1050.     ret    nc        ;ni >= dx e- done w/segment
  1051.     call    compseg        ;compute xpos and ypos at next point
  1052.     ld    hl,(xpos)
  1053.     ld    (xdot),hl
  1054.     ld    hl,(ypos)
  1055.     ld    (ydot),hl
  1056.     call    plotdot        ;plot it
  1057.     jr    strtplt        ;back to the top of the loop
  1058. ;
  1059. ;-----------------------------------------------------------------------
  1060. ;        Line spacing routine
  1061. ;    inputs:
  1062. ;        none
  1063. ;    outputs:
  1064. ;        ESC A 7  sent to set the printer to 7/72in line spacing
  1065. ln772:
  1066.     ld    c,5        ;list output
  1067.     ld    e,ESC
  1068.     call    pdos
  1069.     ld    c,5
  1070.     ld    e,'A'
  1071.     call    pdos
  1072.     ld    c,5
  1073.     ld    e,7
  1074.     call    pdos
  1075.     ret
  1076. ;
  1077. ;-----------------------------------------------------------------------
  1078. ;    Calculate the address for an xy coordinate pair
  1079. ;    xyaddr= origin + xcoord + (maxy-ycoord)/7 * (maxx+1)
  1080. ;    inputs:
  1081. ;        xcoordinate in registers bc
  1082. ;        ycoordinate in registers de
  1083. ;        maximum y raster count in hl
  1084. ;    outputs:
  1085. ;        xcoordinate in registers bc
  1086. ;        ycoordinate in registers de
  1087. ;        address of x,y coordinates in hl
  1088. ;        address stored @ xyaddr
  1089. locdot:
  1090.     push    de        ;store y coord on stack
  1091.     push    bc        ;store x coord on stack
  1092.     or    a
  1093.     sbc    hl,de        ;subtract ycoord from maxy
  1094.     ld    (divdnd),hl
  1095.     ld    a,7
  1096.     ld    (divsor),a
  1097.     call    divide        ;(maxy - y)/7
  1098.     ld    a,(rmandr)    ;rmandr is negative if overflow
  1099.     or    a        ;set flags
  1100.     call    m,woops        ;overflow in division
  1101.     ld    a,(qotent)    ;get result of division
  1102.     ld    bc,maxx+1    ;BC now contains the max. no. of x's
  1103.     call    bmult        ;HL has low order bytes, A the high
  1104. ;    HL now contains (max-ycoord)/7*(max+1)
  1105.     pop    bc        ;put xcoord in BC
  1106.     add    hl,bc        ;add to x previous term
  1107.     ld    de,origin    ;last term
  1108.     add    hl,de        ;final sum is in HL
  1109.     ld    (xyaddr),hl    ;store result
  1110.     pop    de        ;retrieve y coordinate
  1111.     ret
  1112. ;
  1113. ;-----------------------------------------------------------------------
  1114. ;    Output routine
  1115. ;    inputs:
  1116. ;        memory map starting @ origin
  1117. ;    outputs:
  1118. ;        map is dumped to printer 1 byte at a time
  1119. ;        mixed graphics and text are output
  1120. mapout:
  1121.     xor    a        ;reset status counter
  1122.     ld    (statno),a
  1123.     ld    c,9        ;printing status message
  1124.     ld    de,stat3
  1125.     call    bdos
  1126.     call    ln772        ;set printer to 7/72in line spacing
  1127.     ld    hl,0
  1128.     ld    (ngraph),hl    ;initialize graphics counter
  1129.     ld    hl,origin    ;initialize start address
  1130.     ld    c,[maxy+1]/7    ;initialize line counter
  1131. linloop:
  1132.     ld    de,maxx+1    ;initialize dot counter
  1133. bytloop:
  1134.     ld    b,(hl)        ;get byte
  1135.     ld    a,b        ;put byte in A
  1136.     or    a        ;set flags - is it a graphic byte?
  1137.     call    m,charout    ;no- hi bit set therefore character
  1138.     call    p,gbufin    ;yes- save it in graphic buffer
  1139.     inc    hl        ;incr address to next x location
  1140.     dec    de        ;decr dot counter
  1141.     ld    a,d
  1142.     or    e        ;is dot counter = 0?
  1143.     jr    nz,bytloop    ;no- so loop to top again
  1144.     call    gbufout        ;at end of line- flush buffer
  1145.     call    crlf        ;send a line feed to printer
  1146.     dec    c        ;decr line counter
  1147.     jr    nz,linloop    ;not done- repeat outer loop
  1148.     call    preset        ;reset printer to normal mode
  1149.     ret            ;last line finished
  1150. ;
  1151. ;-----------------------------------------------------------------------
  1152. ;    Move to new coordinates without doing anything else
  1153. ;    inputs:
  1154. ;        coordinate pair in buffer
  1155. ;    outputs:
  1156. ;        xpos and ypos updated to new coordinates
  1157. move:
  1158.     call    readxy        ;get coordinate pair
  1159.     ld    hl,(x)        ;get x coordinate
  1160.     ld    (xpos),hl    ;update x axis position
  1161.     ld    hl,(y)        ;get y coordinate
  1162.     ld    (ypos),hl    ;update y axis position
  1163.     ret            ;position now updated.
  1164. ;
  1165. ;-----------------------------------------------------------------------
  1166. ;    Multiply BC by DE, result in DEHL
  1167. mult:
  1168.     ld    a,e        ;load low byte of multiplier
  1169.     push    de        ;save high byte of multiplier
  1170.     call    bmult        ;do 1-byte multiply
  1171.     ex    (sp),hl        ;save low bytes product, get multiplier
  1172.     push    af        ;store high byte of first prod.
  1173.     ld    a,h        ;load high byte of multiplier
  1174.     call    bmult        ;do 1-byte multiply
  1175.     ld    d,a        ;position high byte of product
  1176.     pop    af        ;get high byte of first product
  1177.     add    a,h        ;update third byte of product
  1178.     ld    e,a        ;and put it in e
  1179.     jr    nc,nc1        ;don't incr D if no carry
  1180.     inc    d        ;incr D if carry
  1181. nc1:
  1182.     ld    h,l        ;relocate low bytes of 2nd prod
  1183.     ld    l,0
  1184.     pop    bc        ;get low 2 bytes of first prod.
  1185.     add    hl,bc        ;get final product low 2 bytes
  1186.     ret    nc        ;done if no carry
  1187.     inc    de        ;otherwise update high 2 bytes
  1188.     ret
  1189. ;
  1190. ;-----------------------------------------------------------------------
  1191. ;    Print or disk o/p routine
  1192. ;    inputs:
  1193. ;        5 in C
  1194. ;        character in (e)
  1195. ;        buffer pointer set to last character (pointr2)
  1196. ;        o/p flag in opdisk
  1197. ;    outputs:
  1198. ;        character printed if o/p flag set
  1199. ;        character written to disk if flag is set
  1200. pdos:
  1201.     ld    a,(opdisk)    ;get disk o/p flag
  1202.     or    a        ;is flag set?
  1203.     push    af        ;save flag
  1204.     call    z,bdos        ;print character if it is
  1205.     pop    af        ;retrieve flags
  1206.     ret    z        ;return if character was printed
  1207.     ld    hl,pointr2    ;get buffer pointer
  1208.     inc    (hl)        ;incr pointer for new char.
  1209.     ld    c,(hl)        ;save pointer value in BC
  1210.     ld    b,0
  1211.     ld    hl,obuff-1    ;get last addr. before obuff
  1212.     add    hl,bc        ;calculate address of byte
  1213.     ld    (hl),e        ;put character in buffer
  1214.     ld    a,128
  1215.     cp    c        ;is buffer full?
  1216.     call    z,write        ;write it out if it is.
  1217.     ret
  1218. ;
  1219. ;-----------------------------------------------------------------------
  1220. ;    Plot a point @ xdot,ydot
  1221. ;    method:
  1222. ;        find byte containing xdot,ydot
  1223. ;        form mask eg: if xdot,ydot is in #4 bit,
  1224. ;        mask = 00010000
  1225. ;        digit= 76543210
  1226. ;        modify byte according to color & store it back
  1227. ;    inputs:
  1228. ;        2 byte x location stored @ xdot
  1229. ;        2 byte y location stored @ ydot
  1230. ;    outputs:
  1231. ;        xpos, ypos reset to values given in xdot, ydot
  1232. ;        appropriate dot turned on or off in memory map
  1233. plotdot:
  1234.     ld    bc,(xdot)    ;get x position
  1235.     ld    (xpos),bc    ;update current position
  1236.     ld    de,(ydot)    ;get y position
  1237.     ld    (ypos),de    ;update current position
  1238. ;xpos and ypos now contain last pos. attempted- may not be in window
  1239.     ld    hl,maxx        ;put limits of x in hl
  1240.     bit    7,b        ;check for neg x-sign in hi byte
  1241.     ret    nz        ;xdot neg- return w/o plotting
  1242.     or    a
  1243.     sbc    hl,bc        ;compare max & x high bytes
  1244.     ret    c        ;x>max- therefore return
  1245.     ld    hl,maxy        ;put limit of y in hl
  1246.     bit    7,d        ;ydot hi byte contains sign
  1247.     ret    nz        ;ydot neg- return w/o plotting
  1248.     or    a
  1249.     sbc    hl,de        ;compare max & y high bytes
  1250.     ret    c        ;y>max- return w/o plotting
  1251.     ld    hl,maxy        ;y limit
  1252.     call    locdot        ;get address of byte for x,ydot
  1253.     call    digit        ;form mask for plotting
  1254.     bit     7,b        ;determine if byte is graphic
  1255.     ret    nz        ;minus= character: return w/o plotting
  1256.     ld    a,(color)    ;get color value
  1257.     or    a        ;set flags
  1258.     jr    z,white        ;0 = white
  1259.     jp    m,compl        ;-1 = complementary color
  1260.     ld    a,b        ;color is black
  1261.     or    c        ;modify byte by turning bit on
  1262.     ld    (hl),a        ;store back in memory
  1263.     ret
  1264. ;
  1265. white:
  1266.     ld    a,b        ;work w/ byte containing x,y
  1267.     cpl            ;complement byte
  1268.     or    c        ;modify byte by turning on bit
  1269.     cpl            ;complement byte back- bit off
  1270.     ld    (hl),a        ;store byte back in memory
  1271.     ret
  1272. ;
  1273. compl:
  1274.     ld    a,b        ;work w/ byte containing x,y
  1275.     xor    c        ;complement bit
  1276.     ld    (hl),a        ;store it
  1277.     ret
  1278. ;
  1279. ;-----------------------------------------------------------------------
  1280. ;    Plot point routine
  1281. ;    inputs:
  1282. ;        buffer @ tbuff
  1283. ;    outputs:
  1284. ;        point plotted in memory
  1285. point:
  1286.     call    readxy        ;read coordinates for point
  1287.     ld    hl,(x)
  1288.     ld    (xdot),hl
  1289.     ld    hl,(y)
  1290.     ld    (ydot),hl
  1291.     call    plotdot        ;plot point
  1292.     ret
  1293. ;
  1294. ;-----------------------------------------------------------------------
  1295. ;    Quit - closes output file, terminates program
  1296. ;    inputs:
  1297. ;        fcb for output file @ fcb2
  1298. ;        disk output flag @ opdisk
  1299. ;    outputs:
  1300. ;        remainder of record set to 0, disk closed.
  1301. quit:
  1302.     ld    a,(opdisk)    ;get disk output flag
  1303.     or    a        ;is it set?
  1304.     jp    z,exit        ;no, so all done
  1305.     ld    e,(iy+29)
  1306.     ld    c,32
  1307.     call    bdos        ;set o/p user #
  1308.     ld    a,(pointr2)    ;look @ o/p pointer
  1309.     or    a        ;is o/p buffer empty?
  1310.     jp    z,exit        ;yes- done
  1311.     ld    e,a        ;save pointer value in E
  1312.     ld    d,0
  1313.     ld    a,128        ;set max value of pointer
  1314.     sub    a,e        ;A= 128- pointr2
  1315.     ld    c,a        ;C now is count of extra buff.
  1316. clrbuf:
  1317.     push    bc        ;save counter
  1318.     ld    e,0        ;output a <null>
  1319.     call    pdos
  1320.     pop    bc        ;retrieve counter
  1321.     dec    c        ;decr it
  1322.     jr    nz,clrbuf    ;loop back until buffer is full
  1323.     ld    c,16        ;close file
  1324.     ld    de,fcb2        ;o/p fcb
  1325.     call    bdos
  1326.     jp    exit        
  1327. ;
  1328. ;-----------------------------------------------------------------------
  1329. ;    Line segment routine
  1330. ;    inputs:
  1331. ;        file buffer @ tbuff
  1332. ;    outputs:
  1333. ;        xpos, ypos updated to x2,y2
  1334. ;        visible portion of line segment plotted
  1335. plotseg:
  1336.     call    readxy        ;get starting coordinates
  1337.     ld    hl,(x)
  1338.     ld    (xdot),hl
  1339.     ld    hl,(y)
  1340.     ld    (ydot),hl
  1341.     call    plotdot        ;plot starting point
  1342.     call    incplt        ;plot rest of segment
  1343.     ret
  1344. ;
  1345. ;-----------------------------------------------------------------------
  1346. ;    Reset the printer to its normal mode
  1347. preset:
  1348.     ld    c,5
  1349.     ld    e,ESC
  1350.     call    pdos
  1351.     ld    c,5
  1352.     ld    e,'2'
  1353.     call    pdos        ;esc 2 sets line spacing to 6 lines/in.
  1354.     ld    c,5
  1355.     ld    e,cr        ;send carriage return to reset head
  1356.     call    pdos
  1357.     ret
  1358. ;
  1359. ;-----------------------------------------------------------------------
  1360. ;    Read record
  1361. ;    inputs:
  1362. ;        opened file
  1363. ;        file control block @ fcb
  1364. ;        128 char file buffer @ tbuff
  1365. ;        1 byte character pointer @ pointer
  1366. ;    outputs:
  1367. ;        character pointer reset to 0
  1368. ;        new record in file buffer
  1369. ;        eof: jump to eofexit instead of normal return
  1370. read:
  1371.     ld    e,(iy+13)
  1372.     ld    c,32
  1373.     call    bdos        ;set user #
  1374.     ld    c,26        ;set dma
  1375.     ld    de,tbuff    ;buffer
  1376.     call    bdos
  1377.     ld    c,20        ;sequential read
  1378.     ld    de,fcb
  1379.     call    bdos        ;read record into buffer @ tbuff
  1380.     or    a        ;read ok?
  1381.     jr    z,setpntr    ;reset pointer if not eof
  1382.     pop    bc        ;pop return addr off stack
  1383.     jr    eofexit        ;goto exit instead of normal rtn
  1384. setpntr:
  1385.     xor    a
  1386.     ld    (pointer),a    ;reset pointer to 0
  1387.     ret
  1388. ;
  1389. eofexit:
  1390.     ld    c,9        ;print string
  1391.     ld    de,eofmsg
  1392.     call    bdos        ;print eof message
  1393.     jp    exit        ;return
  1394. ;
  1395. ;-----------------------------------------------------------------------
  1396. ;    Get an xy pair and convert it to raster values.
  1397. ;The general algorithm is:
  1398. ;integer = (fixed point) * (number of rasters) * 2/ 2^16
  1399. ;the fixed point number is a 15 bit value in the range 0 to 1.
  1400. ;when viewed as an integer, the fixed point coordinates range from
  1401. ;0 to 32767.  when multiplied by the range of the raster coordinates,
  1402. ;they must be divided by 32767 to represent the true value.  this is
  1403. ;approximated by multiplying by 2 / 65536   (2/64k).  dividing by 64k
  1404. ;is accomplished by simply disregarding the lower 2 bytes of the result
  1405. ;
  1406. ;    inputs:
  1407. ;        128 character buffer @ tbuff
  1408. ;        character pointer @ pointer
  1409. ;    outputs:
  1410. ;        two byte value stored @ x
  1411. ;        two byte value stored @ y
  1412. readxy:
  1413.     call    byte        ;get first byte of x
  1414.     push    af        ;save first byte
  1415.     call    byte        ;get second byte
  1416.     ld    b,a        ;put high byte in B
  1417.     pop    af        ;get low byte
  1418.     ld    c,a        ;BC now contains x coord.
  1419.     ld    de,maxx*2    ;maximum raster address
  1420.     call    mult        ;multiply x coord by no. of x rasters
  1421.     ex    de,hl        ;put high bytes in HL
  1422.     ld    (x),hl        ;store corresponding raster x coordinate
  1423.     call    byte        ;get first byte of y
  1424.     push    af        ;save first byte
  1425.     call    byte        ;get second byte
  1426.     ld    b,a        ;put high byte in B
  1427.     pop    af        ;get low byte
  1428.     ld    c,a        ;BC now contains y coord.
  1429.     ld    de,maxy*2    ;maximum raster address
  1430.     call    mult        ;multiply y coord by no. of y rasters
  1431.     ex    de,hl        ;put high bytes in HL
  1432.     ld    (y),hl        ;store corresponding raster y coordinate
  1433.     ret
  1434. ;
  1435. ;---------------------------------------
  1436. ;    Rotates the patterns used for erasing to a color
  1437. ;    inputs:
  1438. ;        array of 8 pattern bytes stored at patrn
  1439. ;    outputs:
  1440. ;        array is rotated one bit down
  1441. rotpat:
  1442.     exx
  1443.     ld    b,8        ;initialize counter
  1444.     ld    hl,patrn    ;initialize address of head of array
  1445. rotpt1:
  1446.     rrc    (hl)        ;rotate byte
  1447.     inc    hl        ;move pointer to next byte
  1448.     djnz    rotpt1        ;loop back until done
  1449.     exx
  1450.     ret
  1451. ;
  1452. ;-----------------------------------------------------------------------
  1453. ;    Initialize the variables used in computing a line segment
  1454. ;    inputs:
  1455. ;        xpos,ypos    present position
  1456. ;        x,y        end points of segment
  1457. ;    outputs:
  1458. ;        dx,dy    x,y sizes of line segment
  1459. ;        epslnx,epslny,sx,sy,delta3    internal variables initialized
  1460. ;        ni    counter used to determine when done
  1461. seginit:
  1462.     ld    hl,(x)        ;get x
  1463.     ld    de,(xpos)    ;put present pos in hl
  1464.     or    a
  1465.     sbc    hl,de        ;calculate delta x
  1466.     ld    (deltax),hl
  1467.     bit    7,h        ;record sign of dx
  1468.     push    af        ;save flags
  1469.     ld    hl,(y)        ;get y end point value
  1470.     ld    de,(ypos)    ;get present y position
  1471.     or    a
  1472.     sbc    hl,de        ;calculate delta y (dy)
  1473.     ld    (deltay),hl    ;store dy
  1474.     ld    hl,0        ;initialize variables
  1475.     ld    (sx),hl
  1476.     ld    (epslny),hl
  1477.     inc    hl
  1478.     ld    (sy),hl
  1479.     ld    (epslnx),hl
  1480.     pop    af        ;recover flags
  1481.     jr    z,chkdy        ;if dx was positive
  1482.     ld    hl,-1        ;change initialization for -dx
  1483.     ld    (epslnx),hl
  1484.     ld    hl,(deltax)    ;change sign on dx
  1485.     ld    a,h
  1486.     cpl
  1487.     ld    h,a
  1488.     ld    a,l
  1489.     cpl
  1490.     ld    l,a
  1491.     inc    hl
  1492.     ld    (deltax),hl    ;store now positive dx
  1493. chkdy:
  1494.     ld    hl,(deltay)    ;get dy
  1495.     bit    7,h        ;check if positive
  1496.     jr    z,chdxdy    ;dy is pos- goto transpose axes
  1497.     ld    a,h        ;dy is negative- change sign
  1498.     cpl
  1499.     ld    h,a
  1500.     ld    a,l
  1501.     cpl
  1502.     ld    l,a
  1503.     inc    hl
  1504.     ld    (deltay),hl    ;store the now pos. dy
  1505.     ld    hl,-1
  1506.     ld    (sy),hl        ;sy= -1
  1507. chdxdy:
  1508.     ld    de,(deltax)    ;transpose axes if dx<dy
  1509.     ld    hl,(deltay)    ;get delta y
  1510.     push    hl
  1511.     or    a
  1512.     sbc    hl,de        ;dx < dy ? (high bytes first)
  1513.     pop    hl
  1514.     jr    c,lstinit    ;dx definitely > dy
  1515.     ld    (deltax),hl    ;dy was in hl- store as dx
  1516.     ld    (deltay),de    ;store old dx as new dy
  1517.     ld    hl,(epslnx)
  1518.     ld    (sx),hl        ;reinitialize: sx= epsilon x
  1519.     ld    hl,(sy)
  1520.     ld    (epslny),hl    ;epsilon y = sy
  1521.     ld    hl,0
  1522.     ld    (epslnx),hl    ;epsilon x = 0
  1523.     ld    (sy),hl        ;sy = 0
  1524. lstinit:
  1525.     or    a        ;clear flags
  1526.     rr    d        ;calculate deltax/2 by shifting 1 right
  1527.     rr    e
  1528.     ld    (delta3),de    ;store in delta3
  1529.     ld    hl,1        ;set ni=1
  1530.     ld    (ni),hl
  1531.     ret
  1532. ;
  1533. ;------------------------------------------------------------------------
  1534. ;    Status message routine
  1535. ;    this routine displays a message to indicate that the program
  1536. ;    is working.
  1537. ;    inputs:
  1538. ;        current count stored in statno
  1539. ;    outputs:
  1540. ;        message displayed
  1541. stat:
  1542.     push    af        ;save registers
  1543.     push    bc
  1544.     push    de
  1545.     push    hl
  1546. ;
  1547.     ld    a,(statno)    ;get counter
  1548.     inc    a        ;update counter
  1549.     ld    (statno),a
  1550.     ld    c,9
  1551.     cp    1
  1552.     jr    nz,statm2
  1553.     ld    de,stat1
  1554.     call    bdos        ;print message
  1555.     jr    statx
  1556. ;
  1557. statm2:
  1558.     cp    128        ;check for other message
  1559.     jr    nz,statx    ;not time for either message
  1560.     ld    de,stat2
  1561.     call    bdos        ;print other message
  1562. statx:
  1563.     pop    hl        ;restore registers
  1564.     pop    de
  1565.     pop    bc
  1566.     pop    af
  1567.     ret
  1568. ;
  1569. ;------------------------------------------------------------------------
  1570. ;    String plotting routine
  1571. ;    method:
  1572. ;        ASCII code is stored repeatedly in the area occupied by
  1573. ;        the character (cwidth rasters).  Hi bit is set to
  1574. ;        indicate that the byte is ascii and not dot image.
  1575. ;    input:
  1576. ;        x,y in file buffer
  1577. ;        bytes read sequentially from buffer until carriage rtn
  1578. ;        is encountered.
  1579. ;    outputs:
  1580. ;        each character is stored in the byte containing the bit
  1581. ;        map coordinate indicated for the character
  1582. ;        x,y locations < 0 are reset to 0
  1583. ;        x,y locations > max are reset to 0
  1584. string:
  1585.     call    readxy        ;get starting coordinates
  1586. strng0:
  1587.     call    byte        ;get first character
  1588.     cp    cr        ;is character a carriage return?
  1589.     ret    z        ;yes- so return (all done)
  1590.     or    10000000b    ;set high bit
  1591.     ld    b,a        ;save byte in B
  1592.     ld    hl,(x)        ;get x location
  1593.     bit    7,h        ;look at msb
  1594.     jr    nz,resetx    ;x is negative- reset to 0
  1595.     ld    de,maxx-cwidth    ;get maximum x value
  1596.     or    a
  1597.     sbc    hl,de
  1598.     jr    c,strng1    ;max definitely > x (x is ok)
  1599.     jr    z,strng1    ;equal : x is barely ok
  1600. resetx:
  1601.     ld    hl,0
  1602.     ld    (x),hl        ;x=0
  1603. strng1:
  1604.     ld    hl,(y)        ;fetch y starting location
  1605.     bit    7,h        ;look at y msb
  1606.     jr    nz,resety    ;negative - reset to 0
  1607.     ld    de,maxy        ;use entire coordinate range for y
  1608.     or    a
  1609.     sbc    hl,de        ;compare max and y high bytes
  1610.     jr    c,strng2    ;y definitely ok
  1611.     jr    z,strng2    ;y = max
  1612. resety:
  1613.     ld    hl,0        ;clear old value of y
  1614.     ld    (y),hl        ;y = 0
  1615. strng2:
  1616.     ld    de,(y)        ;put y in DE
  1617.     ld    hl,(x)        ;fetch x
  1618.     push    bc        ;save byte
  1619.     push    de        ;save y coord
  1620. ;    make x coord. a multiple of cwidth for proper printer output
  1621.     ld    (divdnd),hl    ;compute x=(x/cwidth)*cwidth
  1622.     ld    a,cwidth    ;get cwidth for divisor
  1623.     ld    (divsor),a
  1624.     call    divide        ;divide x by cwidth
  1625.     ld    a,(qotent)    ;get results (no overflow as 0<=x<1530)
  1626.     ld    bc,cwidth    ;pass character width
  1627.     call    bmult        ;HL now contains (x/cwidth)*cwidth
  1628.     ld    b,h        ;put x in BC
  1629.     ld    c,l
  1630.     pop    de        ;retrieve y coordinate
  1631.     ld    hl,maxy        ;put max y in HL
  1632.     call    locdot        ;get location of byte
  1633.     pop    bc        ;retrieve byte
  1634.     ld    (hl),b        ;put byte in address containing x,y
  1635. ;    store byte repeatedly to blank out entire area occupied by it
  1636.     ld    a,cwidth-1    ;initialize loop counter
  1637. strng3:
  1638.     inc    hl        ;increment address
  1639.     ld    (hl),b        ;store byte
  1640.     dec    a        ;decr loop counter
  1641.     jr    nz,strng3    ;loop back up until finished
  1642.     ld    c,cwidth
  1643.     ld    hl,(x)        ;fetch x location
  1644.     ld    b,0
  1645.     add    hl,bc        ;incr x location for  next character
  1646.     ld    (x),hl        ;store new x location
  1647.     jr    strng0        ;loop up to top
  1648. ;
  1649. ;-----------------------------------------------------------------------
  1650. ;    Text - outputs text immediately to the printer
  1651. ;    note: text is not put into memory map
  1652. ;    inputs:
  1653. ;        text string in file (ends with 0 byte)
  1654. ;    outputs:
  1655. ;        text string printed
  1656. text:
  1657.     call    byte        ;get next character
  1658.     or    a        ;check for end of string
  1659.     ret    z        ;return if finished
  1660.     ld    e,a
  1661.     ld    c,5        ;lst: output
  1662.     call    pdos        ;print it
  1663.     jr    text        ;loop back until done
  1664. ;
  1665. ;-----------------------------------------------------------------------
  1666. ;    Upload the array defining color palette
  1667. ;    inputs:
  1668. ;        16 bit integer specifying # of data bytes to come
  1669. ;        data bytes in input file
  1670. ;    outputs:
  1671. ;        new color values stored in appropriate arrays
  1672. upload:
  1673.     call    byte        ;get low byte of integer
  1674.     ld    c,a        ;save in C
  1675.     call    byte        ;get high byte
  1676.     or    a        ;check value of high byte
  1677.     jr    nz,upbad    ;for this program, hi byte must be 0
  1678.     ld    a,c        ;look at low byte
  1679.     cp    7        ;7 indicates upload plaid patterns
  1680.     jr    z,uplaid    ;proceed to upload plaid values
  1681.     cp    64        ;64 indicates upload dither matrix
  1682.     jr    z,updith    ;proceed to upload dither matrix
  1683.     cp    120        ;120 indicates upload special patterns
  1684.     jr    z,upcif        ;proceed to upload special patterns
  1685. upbad:
  1686.     call    byte        ;# has unexpected value- skip bytes
  1687.     dec    bc        ;decr loop counter
  1688.     ld    a,c
  1689.     or    b        ;is counter = 0 ?
  1690.     jr    nz,upbad    ;loop back until finished
  1691.     ret
  1692. ;
  1693. uplaid:
  1694.     ld    hl,plaids+1    ;point to plaid array (leave "0" alone)
  1695.     jr    uplp1        ;proceed to read-store loop
  1696. upcif:
  1697.     ld    hl,cifpat    ;set pointer at start of special patterns
  1698.     jr    uplp1
  1699. updith:
  1700.     ld    hl,ditharr    ;point to dither array
  1701. uplp1:
  1702.     call    byte        ;get color pattern
  1703.     ld    (hl),a        ;store pattern
  1704.     inc    hl        ;point to next pattern slot
  1705.     dec    c        ;decr counter
  1706.     jr    nz,uplp1    ;loop back until finished
  1707.     ret
  1708. ;
  1709. ;-----------------------------------------------------------------------
  1710. ;    Overflow occured in mult. or div
  1711. ;    inputs:
  1712. ;        none
  1713. ;    outputs:
  1714. ;        message "overflow"
  1715. ;        all registers pushed on stack
  1716. ;        in order: af,hl,de,bc
  1717. ;        final position of stack pointer saved in oldstk
  1718. woops:
  1719.     push    af        ;save all registers
  1720.     push    hl
  1721.     push    de
  1722.     push    bc
  1723.     ld    hl,0
  1724.     add    hl,sp        ;get stack pointer
  1725.     ld    (oldstk),hl    ;save stack pointer for debug
  1726.     ld    c,9        ;print 
  1727.     ld    de,ovflmsg
  1728.     call    bdos        ;print 'overflow'
  1729.     jp    exit        
  1730. ovflmsg:
  1731.     db    'OVERFLOW$'
  1732. ;
  1733. ;-----------------------------------------------------------------------
  1734. ;    Write record
  1735. ;    inputs:
  1736. ;        opened file
  1737. ;        file control block @ fcb2
  1738. ;        buffer @ obuff
  1739. ;        buffer pointer @ pointr2
  1740. ;    outputs:
  1741. ;        buffer written to file
  1742. ;        buffer pointer reset to 0
  1743. write:
  1744.     ld    e,(iy+29)
  1745.     ld    c,32
  1746.     call    bdos        ;set o/p user #
  1747.     ld    c,26        ;set dma 
  1748.     ld    de,obuff    ;o/p buffer
  1749.     call    bdos
  1750.     ld    c,21        ;write sequential
  1751.     ld    de,fcb2        ;o/p fcb
  1752.     call    bdos
  1753.     or    a        ;was write ok?
  1754.     jr    nz,fullxit    ;jump to error section if not
  1755.     xor    a
  1756.     ld    (pointr2),a    ;pointr2=0
  1757.     ret            ;done with successful write
  1758.  
  1759. fullxit:
  1760.     ld    c,9
  1761.     ld    de,noroom    ;error message
  1762.     call    bdos
  1763.     jp    exit        
  1764. ;
  1765. ;-----------------------------------------------------------------------
  1766. ;    Non-standard extensions to Zplot
  1767. ;    inputs:
  1768. ;        none
  1769. ;    outputs:
  1770. ;        none
  1771. xtend:
  1772.     push    af
  1773.     push    bc
  1774.     push    de
  1775.     push    hl
  1776.     call    byte        ;get low byte of number of data bytes
  1777.     ld    a,c
  1778.     call    byte        ;get high byte of number of bytes
  1779.     ld    a,b        ;BC is now 16 bit integer
  1780.     or    c        ;is number = 0?
  1781.     jr    z,xtnd2        ;finished if n = 0
  1782. xtnd1:
  1783.     call    byte        ;get data byte
  1784.     dec    bc        ;decr counter
  1785.     ld    a,c
  1786.     or    b        ;is counter = 0 ?
  1787.     jr    nz,xtnd1    ;loop back if more to come
  1788. xtnd2:
  1789.     pop    hl        ;restore registers
  1790.     pop    de
  1791.     pop    bc
  1792.     pop    af
  1793.     ret
  1794. ;
  1795. ;-----------------------------------------------------------------------
  1796. origin:
  1797.                 ;start of picture map
  1798. ;-----------------------------------------------------------------------
  1799.