home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol144 / graph.zq0 / GRAPH.Z80
Encoding:
Text File  |  1985-02-10  |  15.3 KB  |  662 lines

  1. ;GRAPH is a package of subroutines to allow graphs
  2. ;  to be printed on an MX80 with GRAFTRAX
  3. ;Using programs written either in Microsoft Basic or Fortran
  4. ;
  5. ;    Written Dec 1981 by    Trevor Marshall,
  6. ;                SYSOP, Thousand Oaks Tech RCPM
  7. ;                3423 Hill Canyon Ave, TO CA 91360
  8. ;
  9. ; (C) Copyright 1981 by Trevor Marshall
  10. ; Permission is given for this package to be 
  11. ;   distributed and used, but not for profit.
  12. ;
  13. ; This version is for 400 dots x 200 dots (25 Lines)
  14. ; The complete buffer array is stored in memory so that
  15. ;  multiple plots and other graphics may be facilitated
  16. ;Although this takes up a lot of memory the multiple plot
  17. ; ability is extremely useful
  18. ;
  19. ; There are 6 Subroutines.
  20. ; INITAX initializes the 400x200 array and fills in axes at 0,0
  21. ; INITGR initializes the 400x200 array but does not fill in axes
  22. ;     calls to SCALEX or SCALEY are used for axes
  23. ; MARK marks a point with a square around it,given the coordinates
  24. ; PLOT plots a single point in the array, given its coordinates
  25. ; ANNOTY prints 5 condensed chars at the left of the Y axis
  26. ; PUTIT Prints the stored array, together with axis names
  27. ; (It is left to the calling program to print any descriptive
  28. ;      header information.)
  29. ; As the EPSON normally loses count of top of form position
  30. ;  (it only counts the number of lines/ page), when the line
  31. ;   is other than 12 dots high; PUTIT readjusts TOF
  32. ;
  33. ; The calling sequence from the MICROSOFT BASIC COMPILER is:
  34. ;    CALL INITAX    or CALL INITGR        (no params)
  35. ;    CALL MARK(X%,Y%), 0 <= X% <= 399; 0 <= Y <= 199
  36. ;    CALL PLOT(X%,Y%)
  37. ;    CALL ANNOTY(VALUE$,Y%)
  38. ;    ; VALUE$ is a string of 5 chars (may be blank)
  39. ;    ;  to identify the axis, Y% is the coordinate it is to be placed at
  40. ;    CALL PUTIT(XALPHA$,YALPHA$), where
  41. ;    ; XALPHA is a string to annotate the X axis ( <= 79 chars)
  42. ;    ; YALPHA is a string to annotate the Y axis ( <= 25 chars)
  43. ;    ;  either of them may be blank but not null
  44. ;
  45. ;If the Conditional FORTRAN is TRUE (for Microsoft Fortran),
  46. ; All the Alpha strings must be type LOGICAL, and are called thus
  47. ; LOGICAL VALUE(5), XALPHA(79), YALPHA(25)
  48. ; INTEGER X,Y
  49. ; CALL INITAX  or  CALL INITGR    (no params)
  50. ; CALL MARK(X,Y)
  51. ; CALL PLOT(X,Y)
  52. ; CALL ANNOTY(VALUE,Y)
  53. ; CALL PUTIT(XALPHA,YALPHA)
  54. ;
  55. BDOS    EQU    5
  56. ;
  57. FALSE    EQU    0
  58. TRUE    EQU    -1
  59. ;
  60. TESTING EQU    FALSE    ;Set true if stand alone
  61. FORTRAN EQU    FALSE    ;Set true if compiling for Microsoft Fortran
  62. ;
  63.     GLOBAL    INITAX,INITGR,MARK,PLOT,ANNOTY,PUTIT
  64. ;
  65. ;------------------------------------------------------------------------------
  66.     IF    TESTING        ;If Testing we use as a stand-alone package
  67. ;
  68.     ORG    100H        ;To reduce compilation/linking time
  69. ;
  70.     CALL     INITAX
  71. ;Now plot an example line
  72.     LD    HL,99    ;X from 100 -> 299
  73.     LD    DE,200    ;Y from 199 -> 0
  74. LP8:    INC    HL
  75.     DEC    DE
  76.     LD    A,E
  77.     OR    D
  78.     JR    Z,NXT78    ;DONE
  79.     PUSH    HL
  80.     PUSH    DE
  81. ;CALL PLOT(X%,Y%):
  82.     CALL    PUT.PARAM    ;Into MICROSOFT format
  83.     CALL    PLOT
  84.     POP    DE
  85.     POP    HL
  86.     JR    LP8
  87. ;
  88. NXT78:    
  89. ;CALL MARK(20,100)
  90.     LD    HL,20
  91.     LD    DE,100
  92.     CALL    PUT.PARAM
  93.     CALL    MARK
  94. ;
  95. ;CALL MARK(0,0)    ;To check if marking is only performed within correct limits
  96.     LD    HL,0
  97.     LD    DE,0
  98.     CALL    PUT.PARAM
  99.     CALL    MARK
  100. ;
  101. ;CALL MARK(399,199) ;as above
  102.     LD    HL,399
  103.     LD    DE,199
  104.     CALL    PUT.PARAM
  105.     CALL    MARK
  106. ;
  107. ;CALL ANNOTY(STRING$,Y%)
  108.     LD    HL,S3
  109.     LD    DE,190
  110.     LD    (P2),DE
  111.     LD    DE,P2
  112.     CALL    ANNOTY
  113.     LD    HL,S4
  114.     LD    DE,10
  115.     LD    (P2),DE
  116.     LD    DE,P2
  117.     CALL    ANNOTY
  118. ;
  119. ;CALL    PUTIT(XALPHA$,YALPHA$)
  120.     LD    HL,S1    ;XALPHA$
  121.     LD    DE,S2    ;YALPHA$
  122.     CALL    PUTIT
  123.     JP    0        ;Done
  124. ;
  125. PUT.PARAM:    ;Store passed variables
  126.     LD    (P1),HL
  127.     LD    HL,P1
  128.     LD    (P2),DE
  129.     LD    DE,P2
  130.     RET
  131. ;
  132. P1:    DW    0
  133. P2:    DW    0
  134. S1:    DB    79
  135.     DW    ST1
  136. S2:    DB    24
  137.     DW    ST2
  138. S3:    DB    5
  139.     DW    ST3
  140. S4:    DB    5
  141.     DW    ST4
  142. ST1:    DB    'This is the string which can be '
  143.     db    'used to annotate the X axis for coordinates,etc.'
  144. ST2:    DB    'THIS IS THE Y AXIS STRING'
  145. ST3:    DB    'ts1.1'
  146. ST4:    DB    'ts2.2'
  147. ;
  148. ;
  149.     ENDIF    ;TESTING
  150. ;------------------------------------------------------------------------------
  151. ;Firstly a S/R to get the passed parameters
  152. GET@HL: LD    A,(HL)
  153.     INC    HL
  154.     LD    H,(HL)
  155.     LD    L,A    ;Return with @HL in HL
  156.     RET
  157. ;
  158. ;LIST.STRING is a subroutine to send a string to the LIST device
  159. ; HL points to the string on entry, B contains its length
  160. LIST.STRING: LD    C,5    ;BDOS LIST function
  161. LP5:    LD    E,(HL)
  162.     PUSH    HL
  163.     PUSH    BC
  164.     CALL    BDOS
  165.     POP    BC
  166.     POP    HL
  167.     INC    HL
  168.     DJNZ    LP5
  169.     RET
  170. ;
  171. CRLF:    LD    E,0DH    ;Put out a CRLF
  172.     LD    C,5
  173.     CALL    BDOS
  174.     LD    E,0AH
  175.     LD    C,5
  176.     CALL    BDOS
  177.     RET
  178. ;
  179. ;
  180. ; INITGR merely initializes the array
  181. INITGR:    LD    HL,BUFFER ;HL points at start of buffer
  182.     LD    DE,BUFFER+1 ;Get ready for block Fill
  183.     LD    BC,BUFF.LENGTH-1
  184.     LD    (HL),0        ;Zero the first locn
  185.     LDIR            ;and now the rest
  186. ; Now initialize the ANNOT.BUFFER
  187.     LD    HL,ANNOT.BUFFER
  188.     LD    DE,ANNOT.BUFFER+1
  189.     LD    BC,25*5-1
  190.     LD    (HL),' '
  191.     LDIR
  192.     RET    
  193. ;
  194. ; INITAX initializes the array and fills in axes at 0,0
  195. INITAX:
  196.     CALL    INITGR
  197. ; Now Fill in Vertical axis
  198.     LD    DE,400        ;Row increment
  199.     LD    B,25        ;The number of rows
  200.     LD    HL,BUFFER    ;Get where the Y axis will be
  201. LP1:    LD    (HL),0FFH    ;Fill in solid left axis
  202.     ADD    HL,DE
  203.     DJNZ    LP1
  204. ;Fill in Horizontal axis
  205.     LD    HL,BUFFER+10000-400 ;Point at first char of axis row
  206.     LD    BC,400    ;The length of the axis
  207. LP6:    LD    A,(HL)    ;Set the bottom bit
  208.     OR    A,1    ;Set the bottom bit
  209.     LD    (HL),A
  210.     INC    HL
  211.     DEC    BC
  212.     LD    A,C
  213.     OR    B    ;Is BC=0?
  214.     JR    NZ,LP6        
  215. ;Now put in the 'pips' on the vertical axis***********************
  216.     RET
  217. ;
  218. ;Output the buffer & strings
  219. PUTIT:
  220.     IF    NOT FORTRAN    ;FORTRAN does not have a length byte
  221.     INC    HL        ;Point past the string length byte
  222.     ENDIF
  223.     CALL    GET@HL        
  224.     LD    (X.COORD),HL    ;Save address of HL string
  225.     EX    DE,HL
  226.     IF    NOT FORTRAN
  227.     INC    HL        ;as above
  228.     ENDIF
  229.     CALL    GET@HL
  230.     LD    (Y.COORD),HL    ;Y string
  231. ;
  232.     LD    HL,BUFFER    ;Initialize the output pointer
  233.     LD    (BUFF.PTR),HL
  234.     LD    A,25        ;Number of rows
  235.     LD    (ROW),A
  236.     LD    A,-1        ;Point at first Y axis char
  237.     LD    (STRING.PTR),A
  238. ;Set to 8 dot linefeed
  239.     LD    HL,SPACE.8
  240.     LD    B,3    ;Number of chars O/P
  241.     CALL    LIST.STRING
  242.     LD    B,8
  243.     LD    HL,NORMAL    ;cancel special print
  244.     CALL    LIST.STRING
  245.     CALL    CRLF    ;Clean up format
  246. ;
  247. ;First put out the ALPHA label ID
  248. LP3:    LD    A,(STRING.PTR)    ;Point at next char in Y string
  249.     INC    A
  250.     LD    (STRING.PTR),A
  251. ;
  252.     LD    B,4
  253.     LD    HL,EXP.ON    ;set expanded emphasized mode
  254.     CALL    LIST.STRING
  255. ;
  256.     LD    HL,(Y.COORD)
  257.     LD    B,0    ;Calculate the index of the current string char
  258.     LD    C,A
  259.     ADD    HL,BC
  260. ;
  261.     LD    E,(HL)
  262.     LD    C,5
  263.     CALL    BDOS    ;Send it to printer
  264. ;
  265.     LD    B,8
  266.     LD    HL,NORMAL ;Reset to standard chars
  267.     CALL    LIST.STRING
  268. ;
  269.     LD    B,2
  270.     LD    HL,COMPRESSED
  271.     CALL    LIST.STRING    ;Set compressed chars
  272. ;    LD    B,6    ;Now send 6 spaces
  273. ;    LD    HL,SPACE
  274. ;    CALL    LIST.STRING
  275. ; Print a space, plus the 5 ANNOTated chars (if non-blank)
  276.     LD    E,' '
  277.     LD    C,5
  278.     CALL    BDOS
  279.     LD    A,(ROW)    ;Calculate the string in the ANNOT buffer
  280.     DEC    A    ;make 0 to 24
  281.     SCF
  282.     CCF
  283.     LD    B,A    ;save *1
  284.     RL    A    ; *2
  285.     RL    A    ; *4
  286.     ADD    B    ; *4 + *1 = *5
  287.     LD    C,A
  288.     LD    B,0
  289.     LD    HL,ANNOT.BUFFER
  290.     ADD    HL,BC    ;Now we are pointing at
  291.     LD    B,5    ;Character count
  292. LP2:    LD    E,(HL)    ;Get the char
  293.     LD    C,5
  294.     PUSH    BC
  295.     PUSH    HL
  296.     CALL    BDOS    ;Output it
  297.     POP    HL
  298.     POP    BC
  299.     INC    HL
  300.     DJNZ    LP2    ;Loop until 5 chars done
  301. ;
  302.     LD    B,8    ;Set printer chars back to normal
  303.     LD    HL,NORMAL
  304.     CALL    LIST.STRING
  305. ; print the graphics preamble
  306.     LD    HL,START.GRAPHICS
  307.     LD    B,4    ;The number of chars
  308.     CALL    LIST.STRING
  309. ;Now print one row
  310.     LD    HL,400        ;Number of chars
  311.     LD    (CHAR),HL    ;Save it
  312. LP4:    LD    HL,(BUFF.PTR)
  313.     LD    C,5
  314.     LD    E,(HL)
  315.     INC    HL
  316.     LD    (BUFF.PTR),HL
  317.     CALL    BDOS
  318.     LD    HL,(CHAR)
  319.     DEC    HL
  320.     LD    (CHAR),HL
  321.     LD    A,L
  322.     OR    H    ;Is it zero yet?
  323.     JR    NZ,LP4
  324. ;
  325.     CALL    CRLF    ;Terminate row
  326. ;
  327.     LD    A,(ROW)
  328.     DEC    A
  329.     LD    (ROW),A
  330.     JP    NZ,LP3    ;and output the remaining rows
  331. ;Whilst we were outputting the array we had 26 narrow (8 dot) lines
  332. ;Normally 12 dot lines are used
  333. ;We have 2 more short ones next,so we must compensate for 
  334. ; the lost dots by feeding 
  335. ; a 12 + 26*4 + 11 + 1*4 = 119 dot line (We have to use 85+34+12)
  336. ;First print X axis description
  337.     LD    HL,SPACE.1    ;Don't cramp description
  338.     LD    B,3
  339.     CALL    LIST.STRING
  340.     CALL    CRLF
  341. ;Now output the X axis string
  342.     LD    HL,(X.COORD)
  343.     LD    B,79
  344.     CALL    LIST.STRING
  345.     CALL    CRLF
  346. ;Do a 119 dot line feed
  347.     LD    HL,SPACE.85
  348.     LD    B,3
  349.     CALL    LIST.STRING
  350.     CALL    CRLF
  351.     LD    HL,SPACE.46
  352.     LD    B,3
  353.     CALL     LIST.STRING
  354.     CALL    CRLF
  355. ;**************I HAF MADE A MISTAKE (I THINK)
  356. ; We appear to be 1.5 lines short (approx),
  357. ; so let's fudge the correct solution by doing
  358.     LD    HL,FUDGE
  359.     LD    B,3
  360.     CALL    LIST.STRING
  361.     CALL    CRLF
  362. ;Exit after resetting to 12 dot lines
  363.     LD    HL,SPACE.12
  364.     LD    B,2
  365.     CALL    LIST.STRING
  366. ;
  367.     RET
  368. ;
  369. ;
  370. ; ANNOTY Stores strings for annotating the rows of the Y axis
  371. ANNOTY:
  372.     IF    NOT FORTRAN
  373.     INC    HL        ;Point past string length byte
  374.     ENDIF
  375.     CALL    GET@HL
  376.     LD    (X.COORD),HL    ;Actually a string address is saved
  377.     EX    DE,HL
  378.     CALL    GET@HL
  379. ;Now check that the Y coordinate (in HL) is < 200 and compensate
  380. ; for the fact that the top graph row is printed first
  381.     LD    DE,199    ;The Y axis goes from 0 to 199
  382.     XOR    A    ;Clear carry
  383.     EX    DE,HL    ;Get Ycoord to DE, subtract it from 199
  384.     SBC    HL,DE    ;If Y coord was > 199 will get a carry
  385.     RET    C    ;So we will exit if out of range
  386. ;
  387. ;We now get the row count into HL
  388. ; by dividing HL by 8 
  389.     XOR    A
  390.     RR    H    ; divide HL by 2
  391.     RR    L
  392.     RR    H    ; /4
  393.     RR    L
  394.     RR    H    ;/8
  395.     RR    L
  396. ;    DEC    L    ;make row go 0 to 24, not 1 to 25
  397.     LD    A,L
  398.     SCF        ;And compute the offset into the ANNOT.BUFFER
  399.     CCF
  400.     RL    A    ; *2
  401.     RL    A    ; *4
  402.     ADD    L    ; *4 + *1 = *5
  403.     LD    C,A
  404.     LD    B,0
  405.     LD    HL,ANNOT.BUFFER 
  406.     ADD    HL,BC    ;Addr of where string goes is in HL
  407.     LD    DE,(X.COORD) ;Get pointer to string
  408.     LD    B,5    ;Bytes to copy
  409. LP9:    LD    A,(DE)    ;copy them
  410.     LD    (HL),A
  411.     INC    DE
  412.     INC    HL
  413.     DJNZ    LP9    ;Loop till done
  414.     RET
  415. ;
  416. ;
  417. ;
  418. ; MARK, A subroutine to mark a square around a dot in the array
  419. MARK:    CALL    GET@HL        ;Get the first passed parameter
  420.     LD    (X.COORD),HL
  421.     EX    DE,HL        ;Now get the second passed param
  422.     CALL    GET@HL        ;into HL
  423. ;Now check that the Y coordinate (in HL) is < 200 and compensate
  424. ; for the fact that the top graph row is printed first
  425.     LD    DE,199    ;The Y axis goes from 0 to 199
  426.     XOR    A    ;Clear carry
  427.     EX    DE,HL    ;Get Ycoord to DE, subtract it from 199
  428.     SBC    HL,DE    ;If Y coord was > 199 will get a carry
  429.     RET    C    ;So we will exit if out of range
  430.     LD    (Y.COORD),HL
  431. ; Processed parameters, now mark the array thus:
  432. ;    .....    Start 2 rows and 2 dots backwards, mark 5
  433. ;    .   .    inc Y by 1, decr X by 4, dot, inc X by 4, dot
  434. ;    . . .    etc
  435. ;    .   .    etc
  436. ;    .....    5 final dots
  437. ;
  438.     CALL    PLOT2    ;And plot the wanted point
  439.     LD    DE,-2    ;Now the top left of square
  440.     CALL    INCX
  441.     CALL    INCY
  442.     CALL    PLOT2
  443. ;
  444.     LD    B,4    ;4 more  dots 
  445. LP10:    LD    DE,1
  446.     CALL    INCX
  447.     PUSH    BC
  448.     CALL    PLOT2
  449.     POP    BC
  450.     DJNZ    LP10
  451. ;
  452.     LD    B,3    ;Three lines of fence
  453. LP11:    PUSH    BC
  454.     LD    DE,1
  455.     CALL    INCY
  456.     LD    DE,-4
  457.     CALL    INCX
  458.     CALL    PLOT2
  459.     LD    DE,4
  460.     CALL    INCX
  461.     CALL    PLOT2
  462.     POP    BC
  463.     DJNZ    LP11
  464. ;
  465.     LD    DE,1
  466.     CALL    INCY
  467.     LD    DE,-5
  468.     CALL    INCX
  469.     LD    B,5    ;5 dots 
  470. LP12:    LD    DE,1
  471.     CALL    INCX
  472.     PUSH    BC
  473.     CALL    PLOT2
  474.     POP    BC
  475.     DJNZ    LP12
  476. ;
  477.     RET    ;Done marking
  478. ;
  479. PLOT2:    ;Before jumping to PLOT routine check that coords
  480.     ;are within the correct range
  481.     LD    HL,(Y.COORD)
  482.     LD    DE,-199-1
  483.     ADD    HL,DE
  484.     RET    C    ;Exit if out of range
  485.     JR    PLOT3
  486. ;
  487. ; S/Rs to increment the coordinates by the amount in DE
  488. INCX:    LD    HL,(X.COORD)
  489.     ADD    HL,DE
  490.     LD    (X.COORD),HL
  491.     RET
  492. INCY:    LD    HL,(Y.COORD)
  493.     ADD    HL,DE
  494.     LD    (Y.COORD),HL
  495.     RET
  496. ;
  497. ;
  498. ; PLOT, A Subroutine to put a dot in the array,
  499. ;       given the X coordinate in HL
  500. ;        &    Y coordinate in DE
  501. PLOT:
  502.     CALL    GET@HL        ;Get the first passed parameter
  503.     LD    (X.COORD),HL
  504.     EX    DE,HL        ;Now get the second passed param
  505.     CALL    GET@HL        ;into HL
  506. ;Now check that the Y coordinate (in HL) is < 200 and compensate
  507. ; for the fact that the top graph row is printed first
  508.     LD    DE,199    ;The Y axis goes from 0 to 199
  509.     XOR    A    ;Clear carry
  510.     EX    DE,HL    ;Get Ycoord to DE, subtract it from 199
  511.     SBC    HL,DE    ;If Y coord was > 199 will get a carry
  512.     RET    C    ;So we will exit if out of range
  513.     LD    (Y.COORD),HL
  514. ;
  515. PLOT3:    LD    HL,(X.COORD)    ;Get X coord to DE
  516.     LD    DE,-399-1    ;Check it is less than 399
  517.     ADD    HL,DE
  518.     RET    C    ;Exit if out of range
  519. ;We now get the row count into HL and the dot count into E
  520. ; by dividing HL by 8 and putting the remainder into E
  521.     LD    HL,(Y.COORD)    ; get data again
  522.     XOR    A
  523.     LD    E,A    ;Clear carry and E
  524.     RR    H    ; divide HL by 2
  525.     RR    L
  526.     RR    E    ;E contains the carry bit mask
  527.     RR    H    ; /4
  528.     RR    L
  529.     RR    E
  530.     RR    H    ;/8
  531.     RR    L
  532.     RR    E    ;Top 3 bits contain the remainder
  533.     LD    (Y2.COORD),HL ;Save our row count
  534.     RR    E
  535.     RR    E
  536.     RR    E
  537.     RR    E
  538.     RR    E    ;Now E is fully adjusted with remainder in 3 LSBs
  539.     LD    A,7    ;We need to adjust remainder rel to 7
  540.     SUB    E    ;So that the interpolation is correct
  541.     LD    (BIT.MASK),A ;Save it
  542. ;The coordinate of the byte to be marked is (Y/8)*400 + X
  543.     LD    A,8        ;Set up the multiply S/R
  544.     LD    (POKE1),A    ; to be 8 x 8
  545.     LD    DE,400        ;chars/row
  546.     LD    BC,(Y2.COORD)    ;Get scaled Y coordinate to BC
  547.     CALL    MULTIPLY    ;The result will be in HL
  548.     LD    DE,(X.COORD)    ;Add the X coordinate
  549.     ADD    HL,DE
  550.     LD    DE,BUFFER    ;and the buffer base address
  551.     ADD    HL,DE        ;This is the address of the wanted byte
  552.     LD    A,(BIT.MASK)
  553.     LD    B,A    ;Ready for the DJNZ
  554.     INC    B    ;Make shifts 1-8, not 0-7
  555.     SCF    ;set  carry
  556.     LD    A,0    ;If remainder = 0 then LSB is set
  557. LP7:    RL    A    ;On first shift LSB is set
  558.     DJNZ    LP7    ;And so on
  559. ; A now contains a mask we OR with memory to set the required bit
  560.     OR    A,(HL)
  561.     LD    (HL),A
  562.     RET
  563. ;
  564. ;
  565. ;
  566. ; MATHLIB: a 16 Bit Arithmetic Package for Z80
  567. ; Sourced 26 Nov '80 by Trevor Marshall
  568. ;
  569. MULTIPLY: ; 16 x 16 Bit multiplication
  570. ;
  571. ;result (HL) = multiplicand (DE) x multiplier (BC)
  572. ;
  573. ; The multiplicand is in DE
  574. ; The multiplier is in BC
  575. ; The result will be in HL
  576. ; It overflows safely, but without indication
  577. ; Registers are destroyed
  578. ;
  579. ;    Example: 5 x 3
  580. ;        101
  581. ;         x  011
  582. ;    ----------------
  583. ;        101    (Shifted LSBit=1)
  584. ;           101    (Shifted LSBit=1)
  585. ;          000    (Shifted LSBit=0,no add)
  586. ;    ----------------
  587. ;          01111    (Result)
  588. ;
  589. ;  Multiplier is in BC
  590.     LD    A,16    ; Loop count in A
  591. ;count must be >= max number of bits used in BC
  592. POKE1    EQU    $-1    ;address of loop count byte
  593.             ;Allows SELF-MODIFYING code
  594.     LD    HL,0    ;Clear result
  595. ZZMULT:    
  596. ; is multiplier LSBit = 1 ?
  597.     SRL    B    ;Right shift multiplier MSB
  598.             ; 0 -> MSBit, LSBit -> Carry
  599.     RR    C    ;Rotate right multiplier LSB
  600.             ;Carry -> MSBit, LSBit -> Carry
  601.     JR    NC,ZZNOADD ;LSBit not 1, Dont add
  602. ; Could test for overflow by using this here:
  603. ;    CCF    ;Carry will be 1, C -> 0
  604. ;    ADC    HL,DE
  605. ;    JR    C,OVERFLOW.ROUTINE
  606. ; But will use the simpler
  607.     ADD    HL,DE    ;LSBit = 1, so add multiplicand
  608.             ;    to (shifted) result
  609. ZZNOADD:
  610. ;Now we shift left the multiplicand
  611.     SLA    E    ; 0 -> LSBit, MSBit -> Carry
  612.     RL    D    ; Carry -> LSBit, MSBit -> Carry
  613. ;
  614.     DEC    A    ;Loop cntr
  615.     JR    NZ,ZZMULT
  616. ;
  617.     RET    ; ***** DONE *****
  618. ;
  619. ;
  620. ;
  621. X.COORD: DW    0
  622. Y.COORD: DW    0
  623. Y2.COORD: DW    0 
  624. BIT.MASK: DB    0
  625. Y.ADDR:    DW    0
  626. X.ADDR:    DW    0
  627. ;
  628. START.GRAPHICS: DB    1BH,'K'
  629.     DW    400    ;The number of bytes
  630. SPACE.1: DB    1BH,'3',3
  631. SPACE.8: DB    1BH,'3',24
  632. SPACE.12: DB    1BH,'2'
  633. SPACE.85: DB    1BH,'3',255
  634. SPACE.46: DB    1BH,'3',138
  635. FUDGE:     DB    1BH,'3',90
  636. SPACE:    DB    '      '
  637. NORMAL:    DB    1BH,'F',1BH,'H',1BH,'Q',1BH,'T'    ;Cancel all special modes
  638. EXP.ON:    DB    1BH,'S',1BH,'E'
  639. COMPRESSED: DB    1BH,'P'
  640. ;
  641. CHAR:    DW    0
  642. BUFF.PTR: DW    0
  643. STRING.PTR: DB    0
  644. ROW:    DB    0
  645. ;
  646. ;
  647. ;
  648.     IF    NOT TESTING
  649.     DATA
  650.     ENDIF
  651. ;
  652. ; The main data array buffer:
  653. BUFFER:    DS    400*25    ;10k Locs of 8 bytes = 80k bits
  654. BUFF.LENGTH EQU $-BUFFER
  655. ; The buffer is organized as 25 rows each of 400 bytes,
  656. ;  each row being printed in turn (descending)
  657. ;
  658. ; The buffer for Y axis strings:
  659. ANNOT.BUFFER: DS 25*5    ;25 rows of 5 chars
  660. ;
  661.     END
  662.