10 REM > M7Plot/src - MODE 7 plotting
   20 REM 12-Apr-1994 J.G.Harston
   30 REM Implements DRAW/MOVE &00-&0F, PLOT &40-&47
   40 REM Also PLOT &80+n to CLG to colour n
   50 REM Syntax: *M7PLOT (ON|OFF)
   60 :
   70 OSWRCH=&FFEE:OSNEWL=&FFE7:OSBYTE=&FFF4
   80 OSARGS=&FFDA:lptr=&A8
   90 vduv=&0226
  100 scrMap=&0356
  110 originXY=&030C:REM external coords
  120 latestXY=&0310:REM external coords
  130 beforeXY=&0314:REM external coords
  140 plotCM=&031F
  150 vduQXY=&0320:vduQX=vduQXY+0:vduQY=vduQXY+2
  160 plotXY=&0324:plotX=plotXY+0:plotY=plotXY+2:REM internal coords
  170 lastXY=&0328:lastX=lastXY+0:lastY=lastXY+2:REM internal coords
  180 prevXY=&032C:prevX=prevXY+0:prevY=prevXY+2:REM internal coords
  190 pixelY=&00D1
  200 cordXY=&00D2:x1=cordXY+0:y1=cordXY+1:x2=cordXY+2:y2=cordXY+3
  210 charXY=&00D6:charX=charXY+0:charY=charXY+1
  220 oldXY =&00DA:oldX =oldXY +0:oldY =oldXY +1
  230 dx=&DC:dy=&DD:xi=&DE:yi=&DF:ai=dx:bi=dy:d=&330:d=charX
  240 :
  250 REM &D0   = VDUSTAT
  260 REM &D1   = pixelY pixel line
  270 REM &D2   = x1
  280 REM &D3   = y1
  290 REM &D4   = x2
  300 REM &D5   = y2
  310 REM &D6/7 = charX, charY
  320 REM &D8/9 = character address base
  330 REM &DA/B = oldX, oldY
  340 REM &DC/D = dx, dy, ai, bi
  350 REM &DE/F = xi, yi
  360 :
  370 DIM mcode% 600:load%=&FFFF08CA
  380 FOR P=0 TO 1
  390   O%=mcode%:P%=load%
  400   [OPT P*3+4
  410   .init%
  420   LDA #1:LDX #lptr:LDY #0:JSR OSARGS    :\ ptr=>command line
  430   LDA (lptr),Y:CMP #13:BEQ switchOn     :\ M7PLOT<cr> -> turn on
  440   LDX #&FF
  450   .switchLp
  460   INX:LDA &FF00,X:CMP #&60:BNE switchLp :\ Look for RTS
  470   INY:LDA (lptr),Y:AND #&DF             :\ M7PLOT ON  -> turn on
  480   LDY #&FF:CMP #ASC"N":BNE switchOff    :\ M7PLOT OFF -> turn off
  490   .switchOn
  500   LDX #newplot AND 255:LDY #newplot DIV 256
  510   .switchOff
  520   STX vduv+0:STY vduv+1
  530   :
  540   .plotquit
  550   RTS
  560   .newplot
  570   BCS plotquit :\ VDU 23,nn
  580   \ &031F = PLOT number, also in A
  590   \ &0320 = PLOT X
  600   \ &0322 = PLOT Y        after cycling:
  610   \ &0324 = last X (int)  plotX
  620   \ &0326 = last Y (int)  plotY
  630   \ &0328 = prev X (int)  lastX
  640   \ &0328 = prev Y (int)  lastY
  650   \ &032C = temp X (int)  prevX
  660   \ &032E = temp Y (int)  prevY
  670   \
  680   \ Start by converting coordinates
  690   LDY scrMap:CPY #4:BNE plotquit:PHA :\ Not map 4, teletext mode
  700   AND #4:EOR #4:TAY:JSR plotadd      :\ Add origin or previous point
  710   :
  720   \ Cycle the coordinates
  730   LDX #3
  740   .loop
  750   \LDA latestXY,X:\STA beforeXY,X :\ Only needed for fills
  760   \LDA lastXY,X:\STA prevXY,X     :\ These are the
  770   LDA plotXY,X:STA lastXY,X       :\ three plotting
  780   LDA vduQXY,X:STA plotXY,X       :\ coordinates
  790   STA latestXY,X
  800   DEX:BPL loop
  810   :
  820   \ Scale the coordinates
  830   .plotscale
  840   LDX #plotX-&300           :\          1280
  850   LDY #4:JSR plotdiv:PHP    :\ DIV 16 =>  80, save sign
  860   LDA plotX
  870   CMP #60:BCC P%+4:SBC #1
  880   CMP #20:BCC P%+4:SBC #1   :\ Adjust =>  78
  890   PLP:BPL P%+4:ADC #2       :\ Adjust if negative
  900   STA plotX:PHA
  910   :
  920   LDX #plotY-&300           :\          1024
  930   LDY #3:JSR plotdiv:PHP    :\ DIV 8  => 125, save sign
  940   LDA plotY:STA pixelY
  950   LSR A:ADC #13:ADC pixelY
  960   ROR A:LSR A:LSR A
  970   ADC pixelY:ROR A:ADC pixelY
  980   ROR A:LSR A:LSR A         :\ DIV 5  =>  25
  990   CLC:ADC plotY             :\ 25+125 => 150
 1000   ROR A                     :\ DIV 2  =>  75
 1010   PLP:BPL P%+4:ADC #&66     :\ Adjust if negative
 1020   STA plotY
 1030   :
 1040   STA y1:STA y2
 1050   PLA:STA x1:STA x2         :\ Point to start plotting
 1060   PLA:TAY                   :\ Get PLOT action
 1070   AND #&F8:CMP #&80:BEQ clg :\ PLOT &8x -> set up screen
 1080   TYA:CMP #&48:BCS plotexit :\ Not DRAW or PLOT
 1090   AND #3:BEQ plotexit       :\ %xxxxxxxx00 - MOVE
 1100   LDA #134:JSR OSBYTE
 1110   STX oldX:STY oldY         :\ Save current text X,Y
 1120   LDA &D0:PHA:ORA #2:STA &D0:\ Don't scroll screen
 1130   LDA plotCM:JSR plotaction
 1140   PLA:STA &D0:BCS plotexit  :\ Skip past if no output
 1150   LDA #31:JSR OSWRCH        :\ Restore text X,Y
 1160   LDA oldX:JSR OSWRCH
 1170   LDA oldY:JMP OSWRCH
 1180   .plotexit
 1190   RTS
 1200   :
 1210   .clg
 1220   LDA #22:JSR OSWRCH
 1230   LDA #&87:JSR OSWRCH       :\ MODE &87
 1240   LDX #25:BNE initgo        :\ Initialise 25 lines
 1250   .initlp
 1260   JSR OSNEWL
 1270   .initgo
 1280   TYA:EOR #&10:JSR OSWRCH   :\ Set colour code
 1290   DEX:BNE initlp
 1300   LDA #30:JMP OSWRCH
 1310   :
 1320   .plotaction
 1330   CMP #&40:BCC plotdraw       :\ %00xxxxxx - DRAW
 1340   :                           :\ %0100xxxx - PLOT
 1350   :                           :\ %xxxxxx01 - set pixel
 1360   :                           :\ %xxxxxx10 - invert pixel
 1370   :                           :\ %xxxxxx11 - unset pixel
 1380   \ Core plot code, x1=hardware 0-77
 1390   \                 y1=hardware 0-74
 1400   .plotpoint
 1410   LDA y1:CMP #75:BCS plotnull :\ Off screen
 1420   LSR A:ADC #21:LSR A:LDY #3  :\ DIV 3
 1430   .plotdiv3
 1440   ADC y1:ROR A:LSR A
 1450   DEY:BNE plotdiv3:STA charY  :\ DIV 3  =>  25
 1460   ASL A:ADC charY             :\ 3*(Y DIV 3)
 1470   SBC y1:STA pixelY           :\ 3*(Y DIV 3) - Y
 1480   LDA x1:CMP #78:BCS plotnull :\ Off screen
 1490   PHA
 1500   :
 1510   LDA #31:JSR OSWRCH          :\ Position cursor
 1520   PLA:LSR A:PHP:CLC:ADC #1:JSR OSWRCH
 1530   LDA #24:SEC:SBC charY:JSR OSWRCH
 1540   LDA #135:JSR OSBYTE         :\ Get character
 1550   PLP:LDA pixelY:ROL A:TAY
 1560   LDA plotCM:LSR A:BCS plotpix:\ %xxxxxxx1 - set/unset pixel
 1570   TXA:BCC plotinv             :\ %xxxxxx10 - invert pixel
 1580   .plotpix
 1590   LSR A:TXA                   :\ %xxxxxx01 - set pixel
 1600   .plotset                    :\ %xxxxxx11 - unset pixel
 1610   ORA plotchars-&FA,Y:BCC plotwrite
 1620   .plotinv
 1630   EOR plotchars-&FA,Y
 1640   .plotwrite
 1650   ORA #&80:JSR OSWRCH:CLC     :\ Output character
 1660   .plotnull
 1670   RTS
 1680   :
 1690   \ Draw from lastX,lastY to plotX,plotY hardware coords
 1700   .plotdraw
 1710   PHA                         :\ Save plot command
 1720   LDA lastX:STA x1            :\ lastXY is start
 1730   LDA lastY:STA y1
 1740   :
 1750   \ Draw a line using Bresenham algorithm
 1760   \ Draw from    x1,y1    to    x2,y2
 1770   \
 1780   \ Decide direction to draw and step
 1790   LDX #1
 1800   .drawSignLp
 1810   LDA x1,X:CMP #&A8:LDA x2,X:BCC drawPlus
 1820   CMP #&A8:BCS drawSame:BCC drawDiff
 1830   .drawPlus
 1840   CMP #&A8:BCC drawSame
 1850   .drawDiff
 1860   LDA x2,X:CMP x1,X:JMP drawSign
 1870   .drawSame
 1880   LDA x1,X:CMP x2,X
 1890   .drawSign
 1900   BCS drawSub                      :\ x1<x2     y1<y2
 1910   SEC:LDA x2,X:SBC x1,X:STA dx,X   :\  dx=x2-x1  dy=y2-y1
 1920   LDA #1:STA xi,X:BNE drawSignNxt  :\  xi=+1     yi=+1
 1930   .drawSub                         :\ x1>x2     y1<y2
 1940   LDA x1,X:SBC x2,X:STA dx,X       :\  dx=x1-x2  dy=y1-y2
 1950   lda #255:STA xi,X                :\  xi=-1     yi=-1
 1960   .drawSignNxt
 1970   DEX:BPL drawSignLp
 1980   :
 1990   \ Test for primary axis (longer distance)
 2000   LDX #0:LDY #1                    :\ X is longer, X=Xaxis, Y=Yaxis
 2010   LDA dx:CMP dy:BCS P%+4:INX:DEY   :\ Y is longer, X=Yaxis, X=Xaxis
 2020   :
 2030   \ Draw the line
 2040   .drawXY
 2050   LDA dx,Y:PHA:SEC:SBC dx,X:STA ai :\ ai=dy-dx       or ai=dx-dy
 2060   ADC #12:STA d                    :\ d=dy-dx+offset or  d=dx-dy+offset
 2070   PLA:STA bi:JMP drawXYgo          :\ bi=dy          or bi=dx
 2080   .drawXYlp                        :\ while x1 <> x2
 2090   TXA:PHA:JSR plotpoint            :\ plot(x1,y1)
 2100   PLA:TAX:EOR #1:TAY
 2110   LDA d:CLC:BMI drawXYb            :\ diff<0, inc b
 2120   .drawXYa                         :\ diff>0, inc a
 2130   LDA xi,Y:ADC x1,Y:sta x1,Y       :\ y1 += yi
 2140   LDA ai:CLC:BCC drawXYplot
 2150   .drawXYb
 2160   LDA bi                           :\ diff += bi
 2170   .drawXYplot
 2180   ADC d:sta d                      :\ update diff
 2190   LDA xi,X:CLC:ADC x1,X:sta x1,X   :\ x1 += xi
 2200   .drawXYgo
 2210   LDA x1,X:EOR x2,X:BNE drawXYlp   :\ Loop until last point
 2220   PLA:AND #8:BNE drawdone          :\ Omit final point
 2230   JMP plotpoint
 2240   :
 2250   .plotdiv
 2260   LDA &301,X:ASL A
 2270   ROR &301,X:ROR &300,X
 2280   DEY:BNE plotdiv
 2290   LDA &301,X:\ Return with flags=sign
 2300   .drawdone
 2310   CLC:RTS
 2320   :
 2330   .plotadd
 2340   LDX #vduQXY-&300:JSR plotadd2
 2350   INX:INX:INY:INY
 2360   .plotadd2
 2370   CLC
 2380   LDA &300,X:ADC originXY+0,Y:STA &300,X
 2390   LDA &301,X:ADC originXY+1,Y:STA &301,X
 2400   RTS
 2410   :
 2420   .plotchars
 2430   EQUB &01:EQUB &02:EQUB &04
 2440   EQUB &08:EQUB &10:EQUB &40
 2450   :
 2460   ]:IF P%>&FFFF0B00:PRINT"Code overflow":END
 2470 NEXT
 2480 PRINT"*SAVE M7PLOT ";~mcode%;" ";~O%;" ";~init%OR&FFFF0000;" ";~load%
 2490 END
 2500 DEFPROCtest1
 2510 PLOT &87,0,0
 2520 FOR Y%=0 TO 999 STEP 8
 2530   PLOT 69,16+0000,Y%
 2540   PLOT 69,16+1229,Y%
 2550   PLOT 69,16+Y%*1230DIV1000,000+Y%+0
 2560   PLOT 69,16+Y%*1230DIV1000,999-Y%+1
 2570   PLOT 69,16+Y%*1230DIV1000,000
 2580   PLOT 69,16+Y%*1230DIV1000,999
 2590 NEXT:IFGET
 2600 PRINT'''
 2610 ENDPROC
 2620 DEFPROCtest2
 2630 PLOT &87,0,0
 2640 X%=0:Y%=890:V%=0:W%=0
 2650 REPEAT
 2660   MOVE V%,W%:DRAW X%,Y%
 2670   PRINTTAB(5,23);CHR$135;X%;",";Y%;
 2680   PRINT"  ";?dx;" ";?dy;" ";?xi;" ";?yi;
 2690   PRINT"  ";?ai;" ";?bi;" ";?d;"  ";
 2700   PRINTTAB(5,24);CHR$135;?&8F;" ";
 2710   A%=GET:VDU13
 2720   MOVE V%,W%:PLOT 7,X%,Y%
 2730   IF A%=ASC"."ORA%=ASC">":X%=X%+1-9*INKEY-1
 2740   IF A%=ASC","ORA%=ASC"<":X%=X%-1+9*INKEY-1
 2750   IF A%=ASC"A"ORA%=ASC"a":Y%=Y%+1-9*INKEY-1
 2760   IF A%=ASC"Z"ORA%=ASC"z":Y%=Y%-1+9*INKEY-1
 2770   IF A%=ASC"H"ORA%=ASC"h":V%=V%+1-4*INKEY-1
 2780   IF A%=ASC"G"ORA%=ASC"g":V%=V%-1+4*INKEY-1
 2790   IF A%=ASC"Y"ORA%=ASC"y":W%=W%+1-4*INKEY-1
 2800   IF A%=ASC"B"ORA%=ASC"b":W%=W%-1+4*INKEY-1
 2810 UNTIL FALSE
 2820 ENDPROC
 2830 DEFPROCtest3
 2840 PLOT &87,0,0
 2850 MOVE 0,0:DRAW 1279,0:DRAW 1279,999:DRAW 0,999
 2860 DRAW 0,0:DRAW 640,500:DRAW 1279,999
 2870 MOVE 0,999:DRAW 640,500:DRAW 1279,0
 2880 MOVE 440,400:PLOT 1,420,0:PLOT 1,0,199
 2890 PLOT 1,-420,0:PLOT 1,0,-199
 2900 MOVE 440,100:PLOT 10,420,0:PLOT 10,0,199
 2910 PLOT 10,-420,0:PLOT 10,0,-199
 2920 IFGET
 2930 PRINT'''
 2940 ENDPROC
 2950 DEFPROCtest4
 2960 PLOT &87,0,0
 2970 MOVE 0,0:DRAW 1279,0:DRAW 1279,999:DRAW 0,999
 2980 DRAW 0,0:DRAW 1279,999
 2990 MOVE 0,999:DRAW 1279,0
 3000 IFGET
 3010 PRINT'''
 3020 ENDPROC
 3030 DEFPROCtest5
 3040 PLOT &87,0,0
 3050 MOVE 16+0,0:DRAW 16+1229,0:DRAW 16+1229,999:DRAW 16+0,999
 3060 DRAW 16+0,0:DRAW 16+1229,999
 3070 MOVE 16+0,999:DRAW 16+1229,0
 3080 IFGET
 3090 PRINT'''
 3100 ENDPROC