draw3.asm 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. ; -----------------------------------------------------------
  2. ; vim: et:ts=4:sw=4:ruler:
  3. ; DRAW an arc using ZX ROM algorithm.
  4. ; DRAW x, y, r => r = Arc in radians
  5. ; r parameter in A ED BC register
  6. ; X, and Y parameter in high byte on top of the stack
  7. #include once <error.asm>
  8. #include once <plot.asm>
  9. #include once <stackf.asm>
  10. #include once <draw.asm>
  11. ; Ripped from the ZX Spectrum ROM
  12. DRAW3:
  13. PROC
  14. LOCAL STACK_TO_BC
  15. LOCAL STACK_TO_A
  16. LOCAL COORDS
  17. LOCAL L2477
  18. LOCAL L2420
  19. LOCAL L2439
  20. LOCAL L245F
  21. LOCAL L23C1
  22. LOCAL L2D28
  23. LOCAL SUM_C, SUM_B
  24. L2D28 EQU 02D28h
  25. COORDS EQU 5C7Dh
  26. STACK_TO_BC EQU 2307h
  27. STACK_TO_A EQU 2314h
  28. lda z80_c ;- exx
  29. ldx z80_cp
  30. stx z80_c
  31. sta z80_cp
  32. lda z80_b
  33. ldx z80_bp
  34. stx z80_b
  35. sta z80_bp
  36. lda z80_e
  37. ldx z80_ep
  38. stx z80_e
  39. sta z80_ep
  40. lda z80_d
  41. ldx z80_dp
  42. stx z80_d
  43. sta z80_dp
  44. lda z80_l
  45. ldx z80_lp
  46. stx z80_l
  47. sta z80_lp
  48. lda z80_h
  49. ldx z80_hp
  50. stx z80_h
  51. sta z80_hp
  52. ;- ex af, af' ;; Preserves ARC
  53. pla ;- pop hl
  54. sta z80_h
  55. pla
  56. sta z80_l
  57. pla ;- pop de
  58. sta z80_d
  59. pla
  60. sta z80_e
  61. ;- ex (sp), hl ;; CALLEE
  62. lda z80_e ;- push de
  63. pha
  64. lda z80_d
  65. pha
  66. jsr __FPSTACK_I16 ;- call __FPSTACK_I16 ;; X Offset
  67. pla ;- pop hl
  68. sta z80_h
  69. pla
  70. sta z80_l
  71. jsr __FPSTACK_I16 ;- call __FPSTACK_I16 ;; Y Offset
  72. lda z80_c ;- exx
  73. ldx z80_cp
  74. stx z80_c
  75. sta z80_cp
  76. lda z80_b
  77. ldx z80_bp
  78. stx z80_b
  79. sta z80_bp
  80. lda z80_e
  81. ldx z80_ep
  82. stx z80_e
  83. sta z80_ep
  84. lda z80_d
  85. ldx z80_dp
  86. stx z80_d
  87. sta z80_dp
  88. lda z80_l
  89. ldx z80_lp
  90. stx z80_l
  91. sta z80_lp
  92. lda z80_h
  93. ldx z80_hp
  94. stx z80_h
  95. sta z80_hp
  96. ;- ex af, af'
  97. jsr __FPSTACK_PUSH ;- call __FPSTACK_PUSH ;; R Arc
  98. ; Now enter the calculator and store the complete rotation angle in mem-5
  99. RST 28H ;; FP-CALC x, y, A.
  100. DEFB $C5 ;;st-mem-5 x, y, A.
  101. ; Test the angle for the special case of 360 degrees.
  102. DEFB $A2 ;;stk-half x, y, A, 1/2.
  103. DEFB $04 ;;multiply x, y, A/2.
  104. DEFB $1F ;;sin x, y, sin(A/2).
  105. DEFB $31 ;;duplicate x, y, sin(A/2),sin(A/2)
  106. DEFB $30 ;;not x, y, sin(A/2), (0/1).
  107. DEFB $30 ;;not x, y, sin(A/2), (1/0).
  108. DEFB $00 ;;jump-true x, y, sin(A/2).
  109. DEFB $06 ;;forward to L23A3, DR-SIN-NZ
  110. ;;if sin(r/2) is not zero.
  111. ; The third parameter is 2*PI (or a multiple of 2*PI) so a 360 degrees turn
  112. ; would just be a straight line. Eliminating this case here prevents
  113. ; division by zero at later stage.
  114. DEFB $02 ;;delete x, y.
  115. DEFB $38 ;;end-calc x, y.
  116. JP L2477
  117. ; ---
  118. ; An arc can be drawn.
  119. ;; DR-SIN-NZ
  120. DEFB $C0 ;;st-mem-0 x, y, sin(A/2). store mem-0
  121. DEFB $02 ;;delete x, y.
  122. ; The next step calculates (roughly) the diameter of the circle of which the
  123. ; arc will form part. This value does not have to be too accurate as it is
  124. ; only used to evaluate the number of straight lines and then discarded.
  125. ; After all for a circle, the radius is used. Consequently, a circle of
  126. ; radius 50 will have 24 straight lines but an arc of radius 50 will have 20
  127. ; straight lines - when drawn in any direction.
  128. ; So that simple arithmetic can be used, the length of the chord can be
  129. ; calculated as X+Y rather than by Pythagoras Theorem and the sine of the
  130. ; nearest angle within reach is used.
  131. DEFB $C1 ;;st-mem-1 x, y. store mem-1
  132. DEFB $02 ;;delete x.
  133. DEFB $31 ;;duplicate x, x.
  134. DEFB $2A ;;abs x, x (+ve).
  135. DEFB $E1 ;;get-mem-1 x, X, y.
  136. DEFB $01 ;;exchange x, y, X.
  137. DEFB $E1 ;;get-mem-1 x, y, X, y.
  138. DEFB $2A ;;abs x, y, X, Y (+ve).
  139. DEFB $0F ;;addition x, y, X+Y.
  140. DEFB $E0 ;;get-mem-0 x, y, X+Y, sin(A/2).
  141. DEFB $05 ;;division x, y, X+Y/sin(A/2).
  142. DEFB $2A ;;abs x, y, X+Y/sin(A/2) = D.
  143. ; Bring back sin(A/2) from mem-0 which will shortly get trashed.
  144. ; Then bring D to the top of the stack again.
  145. DEFB $E0 ;;get-mem-0 x, y, D, sin(A/2).
  146. DEFB $01 ;;exchange x, y, sin(A/2), D.
  147. ; Note. that since the value at the top of the stack has arisen as a result
  148. ; of division then it can no longer be in integer form and the next re-stack
  149. ; is unnecessary. Only the Sinclair ZX80 had integer division.
  150. ;;DEFB $3D ;;re-stack (unnecessary)
  151. DEFB $38 ;;end-calc x, y, sin(A/2), D.
  152. ; The next test avoids drawing 4 straight lines when the start and end pixels
  153. ; are adjacent (or the same) but is probably best dispensed with.
  154. LD A,(HL) ; fetch exponent byte of D.
  155. CP $81 ; compare to 1
  156. JR NC,L23C1 ; forward, if > 1, to DR-PRMS
  157. ; else delete the top two stack values and draw a simple straight line.
  158. RST 28H ;; FP-CALC
  159. DEFB $02 ;;delete
  160. DEFB $02 ;;delete
  161. DEFB $38 ;;end-calc x, y.
  162. JP L2477 ; to LINE-DRAW
  163. ; ---
  164. ; The ARC will consist of multiple straight lines so call the CIRCLE-DRAW
  165. ; PARAMETERS ROUTINE to pre-calculate sine values from the angle (in mem-5)
  166. ; and determine also the number of straight lines from that value and the
  167. ; 'diameter' which is at the top of the calculator stack.
  168. ;; DR-PRMS
  169. L23C1: CALL 247Dh ; routine CD-PRMS1
  170. ; mem-0 ; (A)/No. of lines (=a) (step angle)
  171. ; mem-1 ; sin(a/2)
  172. ; mem-2 ; -
  173. ; mem-3 ; cos(a) const
  174. ; mem-4 ; sin(a) const
  175. ; mem-5 ; Angle of rotation (A) in
  176. ; B ; Count of straight lines - max 252.
  177. PUSH BC ; Save the line count on the machine stack.
  178. ; Remove the now redundant diameter value D.
  179. RST 28H ;; FP-CALC x, y, sin(A/2), D.
  180. DEFB $02 ;;delete x, y, sin(A/2).
  181. ; Dividing the sine of the step angle by the sine of the total angle gives
  182. ; the length of the initial chord on a unary circle. This factor f is used
  183. ; to scale the coordinates of the first line which still points in the
  184. ; direction of the end point and may be larger.
  185. DEFB $E1 ;;get-mem-1 x, y, sin(A/2), sin(a/2)
  186. DEFB $01 ;;exchange x, y, sin(a/2), sin(A/2)
  187. DEFB $05 ;;division x, y, sin(a/2)/sin(A/2)
  188. DEFB $C1 ;;st-mem-1 x, y. f.
  189. DEFB $02 ;;delete x, y.
  190. ; With the factor stored, scale the x coordinate first.
  191. DEFB $01 ;;exchange y, x.
  192. DEFB $31 ;;duplicate y, x, x.
  193. DEFB $E1 ;;get-mem-1 y, x, x, f.
  194. DEFB $04 ;;multiply y, x, x*f (=xx)
  195. DEFB $C2 ;;st-mem-2 y, x, xx.
  196. DEFB $02 ;;delete y. x.
  197. ; Now scale the y coordinate.
  198. DEFB $01 ;;exchange x, y.
  199. DEFB $31 ;;duplicate x, y, y.
  200. DEFB $E1 ;;get-mem-1 x, y, y, f
  201. DEFB $04 ;;multiply x, y, y*f (=yy)
  202. ; Note. 'sin' and 'cos' trash locations mem-0 to mem-2 so fetch mem-2 to the
  203. ; calculator stack for safe keeping.
  204. DEFB $E2 ;;get-mem-2 x, y, yy, xx.
  205. ; Once we get the coordinates of the first straight line then the 'ROTATION
  206. ; FORMULA' used in the arc loop will take care of all other points, but we
  207. ; now use a variation of that formula to rotate the first arc through (A-a)/2
  208. ; radians.
  209. ;
  210. ; xRotated = y * sin(angle) + x * cos(angle)
  211. ; yRotated = y * cos(angle) - x * sin(angle)
  212. ;
  213. DEFB $E5 ;;get-mem-5 x, y, yy, xx, A.
  214. DEFB $E0 ;;get-mem-0 x, y, yy, xx, A, a.
  215. DEFB $03 ;;subtract x, y, yy, xx, A-a.
  216. DEFB $A2 ;;stk-half x, y, yy, xx, A-a, 1/2.
  217. DEFB $04 ;;multiply x, y, yy, xx, (A-a)/2. (=angle)
  218. DEFB $31 ;;duplicate x, y, yy, xx, angle, angle.
  219. DEFB $1F ;;sin x, y, yy, xx, angle, sin(angle)
  220. DEFB $C5 ;;st-mem-5 x, y, yy, xx, angle, sin(angle)
  221. DEFB $02 ;;delete x, y, yy, xx, angle
  222. DEFB $20 ;;cos x, y, yy, xx, cos(angle).
  223. ; Note. mem-0, mem-1 and mem-2 can be used again now...
  224. DEFB $C0 ;;st-mem-0 x, y, yy, xx, cos(angle).
  225. DEFB $02 ;;delete x, y, yy, xx.
  226. DEFB $C2 ;;st-mem-2 x, y, yy, xx.
  227. DEFB $02 ;;delete x, y, yy.
  228. DEFB $C1 ;;st-mem-1 x, y, yy.
  229. DEFB $E5 ;;get-mem-5 x, y, yy, sin(angle)
  230. DEFB $04 ;;multiply x, y, yy*sin(angle).
  231. DEFB $E0 ;;get-mem-0 x, y, yy*sin(angle), cos(angle)
  232. DEFB $E2 ;;get-mem-2 x, y, yy*sin(angle), cos(angle), xx.
  233. DEFB $04 ;;multiply x, y, yy*sin(angle), xx*cos(angle).
  234. DEFB $0F ;;addition x, y, xRotated.
  235. DEFB $E1 ;;get-mem-1 x, y, xRotated, yy.
  236. DEFB $01 ;;exchange x, y, yy, xRotated.
  237. DEFB $C1 ;;st-mem-1 x, y, yy, xRotated.
  238. DEFB $02 ;;delete x, y, yy.
  239. DEFB $E0 ;;get-mem-0 x, y, yy, cos(angle).
  240. DEFB $04 ;;multiply x, y, yy*cos(angle).
  241. DEFB $E2 ;;get-mem-2 x, y, yy*cos(angle), xx.
  242. DEFB $E5 ;;get-mem-5 x, y, yy*cos(angle), xx, sin(angle).
  243. DEFB $04 ;;multiply x, y, yy*cos(angle), xx*sin(angle).
  244. DEFB $03 ;;subtract x, y, yRotated.
  245. DEFB $C2 ;;st-mem-2 x, y, yRotated.
  246. ; Now the initial x and y coordinates are made positive and summed to see
  247. ; if they measure up to anything significant.
  248. DEFB $2A ;;abs x, y, yRotated'.
  249. DEFB $E1 ;;get-mem-1 x, y, yRotated', xRotated.
  250. DEFB $2A ;;abs x, y, yRotated', xRotated'.
  251. DEFB $0F ;;addition x, y, yRotated+xRotated.
  252. DEFB $02 ;;delete x, y.
  253. DEFB $38 ;;end-calc x, y.
  254. ; Although the test value has been deleted it is still above the calculator
  255. ; stack in memory and conveniently DE which points to the first free byte
  256. ; addresses the exponent of the test value.
  257. LD A,(DE) ; Fetch exponent of the length indicator.
  258. CP $81 ; Compare to that for 1
  259. POP BC ; Balance the machine stack
  260. JP C,L2477 ; forward, if the coordinates of first line
  261. ; don't add up to more than 1, to LINE-DRAW
  262. ; Continue when the arc will have a discernable shape.
  263. PUSH BC ; Restore line counter to the machine stack.
  264. ; The parameters of the DRAW command were relative and they are now converted
  265. ; to absolute coordinates by adding to the coordinates of the last point
  266. ; plotted. The first two values on the stack are the terminal tx and ty
  267. ; coordinates. The x-coordinate is converted first but first the last point
  268. ; plotted is saved as it will initialize the moving ax, value.
  269. RST 28H ;; FP-CALC x, y.
  270. DEFB $01 ;;exchange y, x.
  271. DEFB $38 ;;end-calc y, x.
  272. LD A,(COORDS) ;; Fetch System Variable COORDS-x
  273. CALL L2D28 ;; routine STACK-A
  274. RST 28H ;; FP-CALC y, x, last-x.
  275. ; Store the last point plotted to initialize the moving ax value.
  276. DEFB $C0 ;;st-mem-0 y, x, last-x.
  277. DEFB $0F ;;addition y, absolute x.
  278. DEFB $01 ;;exchange tx, y.
  279. DEFB $38 ;;end-calc tx, y.
  280. LD A,(COORDS + 1) ; Fetch System Variable COORDS-y
  281. CALL L2D28 ; routine STACK-A
  282. RST 28H ;; FP-CALC tx, y, last-y.
  283. ; Store the last point plotted to initialize the moving ay value.
  284. DEFB $C5 ;;st-mem-5 tx, y, last-y.
  285. DEFB $0F ;;addition tx, ty.
  286. ; Fetch the moving ax and ay to the calculator stack.
  287. DEFB $E0 ;;get-mem-0 tx, ty, ax.
  288. DEFB $E5 ;;get-mem-5 tx, ty, ax, ay.
  289. DEFB $38 ;;end-calc tx, ty, ax, ay.
  290. POP BC ; Restore the straight line count.
  291. ; -----------------------------------
  292. ; THE 'CIRCLE/DRAW CONVERGENCE POINT'
  293. ; -----------------------------------
  294. ; The CIRCLE and ARC-DRAW commands converge here.
  295. ;
  296. ; Note. for both the CIRCLE and ARC commands the minimum initial line count
  297. ; is 4 (as set up by the CD_PARAMS routine) and so the zero flag will never
  298. ; be set and the loop is always entered. The first test is superfluous and
  299. ; the jump will always be made to ARC-START.
  300. ;; DRW-STEPS
  301. L2420: DEC B ; decrement the arc count (4,8,12,16...).
  302. ;JR Z,L245F ; forward, if zero (not possible), to ARC-END
  303. JP L2439 ; forward to ARC-START
  304. ; --------------
  305. ; THE 'ARC LOOP'
  306. ; --------------
  307. ;
  308. ; The arc drawing loop will draw up to 31 straight lines for a circle and up
  309. ; 251 straight lines for an arc between two points. In both cases the final
  310. ; closing straight line is drawn at ARC_END, but it otherwise loops back to
  311. ; here to calculate the next coordinate using the ROTATION FORMULA where (a)
  312. ; is the previously calculated, constant CENTRAL ANGLE of the arcs.
  313. ;
  314. ; Xrotated = x * cos(a) - y * sin(a)
  315. ; Yrotated = x * sin(a) + y * cos(a)
  316. ;
  317. ; The values cos(a) and sin(a) are pre-calculated and held in mem-3 and mem-4
  318. ; for the duration of the routine.
  319. ; Memory location mem-1 holds the last relative x value (rx) and mem-2 holds
  320. ; the last relative y value (ry) used by DRAW.
  321. ;
  322. ; Note. that this is a very clever twist on what is after all a very clever,
  323. ; well-used formula. Normally the rotation formula is used with the x and y
  324. ; coordinates from the centre of the circle (or arc) and a supplied angle to
  325. ; produce two new x and y coordinates in an anticlockwise direction on the
  326. ; circumference of the circle.
  327. ; What is being used here, instead, is the relative X and Y parameters from
  328. ; the last point plotted that are required to get to the current point and
  329. ; the formula returns the next relative coordinates to use.
  330. ;; ARC-LOOP
  331. L2425: RST 28H ;; FP-CALC
  332. DEFB $E1 ;;get-mem-1 rx.
  333. DEFB $31 ;;duplicate rx, rx.
  334. DEFB $E3 ;;get-mem-3 cos(a)
  335. DEFB $04 ;;multiply rx, rx*cos(a).
  336. DEFB $E2 ;;get-mem-2 rx, rx*cos(a), ry.
  337. DEFB $E4 ;;get-mem-4 rx, rx*cos(a), ry, sin(a).
  338. DEFB $04 ;;multiply rx, rx*cos(a), ry*sin(a).
  339. DEFB $03 ;;subtract rx, rx*cos(a) - ry*sin(a)
  340. DEFB $C1 ;;st-mem-1 rx, new relative x rotated.
  341. DEFB $02 ;;delete rx.
  342. DEFB $E4 ;;get-mem-4 rx, sin(a).
  343. DEFB $04 ;;multiply rx*sin(a)
  344. DEFB $E2 ;;get-mem-2 rx*sin(a), ry.
  345. DEFB $E3 ;;get-mem-3 rx*sin(a), ry, cos(a).
  346. DEFB $04 ;;multiply rx*sin(a), ry*cos(a).
  347. DEFB $0F ;;addition rx*sin(a) + ry*cos(a).
  348. DEFB $C2 ;;st-mem-2 new relative y rotated.
  349. DEFB $02 ;;delete .
  350. DEFB $38 ;;end-calc .
  351. ; Note. the calculator stack actually holds tx, ty, ax, ay
  352. ; and the last absolute values of x and y
  353. ; are now brought into play.
  354. ;
  355. ; Magically, the two new rotated coordinates rx and ry are all that we would
  356. ; require to draw a circle or arc - on paper!
  357. ; The Spectrum DRAW routine draws to the rounded x and y coordinate and so
  358. ; repetitions of values like 3.49 would mean that the fractional parts
  359. ; would be lost until eventually the draw coordinates might differ from the
  360. ; floating point values used above by several pixels.
  361. ; For this reason the accurate offsets calculated above are added to the
  362. ; accurate, absolute coordinates maintained in ax and ay and these new
  363. ; coordinates have the integer coordinates of the last plot position
  364. ; ( from System Variable COORDS ) subtracted from them to give the relative
  365. ; coordinates required by the DRAW routine.
  366. ; The mid entry point.
  367. ;; ARC-START
  368. L2439: PUSH BC ; Preserve the arc counter on the machine stack.
  369. ; Store the absolute ay in temporary variable mem-0 for the moment.
  370. RST 28H ;; FP-CALC ax, ay.
  371. DEFB $C0 ;;st-mem-0 ax, ay.
  372. DEFB $02 ;;delete ax.
  373. ; Now add the fractional relative x coordinate to the fractional absolute
  374. ; x coordinate to obtain a new fractional x-coordinate.
  375. DEFB $E1 ;;get-mem-1 ax, xr.
  376. DEFB $0F ;;addition ax+xr (= new ax).
  377. DEFB $31 ;;duplicate ax, ax.
  378. DEFB $38 ;;end-calc ax, ax.
  379. LD A,(COORDS) ; COORDS-x last x (integer ix 0-255)
  380. CALL L2D28 ; routine STACK-A
  381. RST 28H ;; FP-CALC ax, ax, ix.
  382. DEFB $03 ;;subtract ax, ax-ix = relative DRAW Dx.
  383. ; Having calculated the x value for DRAW do the same for the y value.
  384. DEFB $E0 ;;get-mem-0 ax, Dx, ay.
  385. DEFB $E2 ;;get-mem-2 ax, Dx, ay, ry.
  386. DEFB $0F ;;addition ax, Dx, ay+ry (= new ay).
  387. DEFB $C0 ;;st-mem-0 ax, Dx, ay.
  388. DEFB $01 ;;exchange ax, ay, Dx,
  389. DEFB $E0 ;;get-mem-0 ax, ay, Dx, ay.
  390. DEFB $38 ;;end-calc ax, ay, Dx, ay.
  391. LD A,(COORDS + 1) ; COORDS-y last y (integer iy 0-175)
  392. CALL L2D28 ; routine STACK-A
  393. RST 28H ;; FP-CALC ax, ay, Dx, ay, iy.
  394. DEFB $03 ;;subtract ax, ay, Dx, ay-iy ( = Dy).
  395. DEFB $38 ;;end-calc ax, ay, Dx, Dy.
  396. CALL L2477 ; Routine DRAW-LINE draws (Dx,Dy) relative to
  397. ; the last pixel plotted leaving absolute x
  398. ; and y on the calculator stack.
  399. ; ax, ay.
  400. POP BC ; Restore the arc counter from the machine stack.
  401. DJNZ L2425 ; Decrement and loop while > 0 to ARC-LOOP
  402. ; -------------
  403. ; THE 'ARC END'
  404. ; -------------
  405. ; To recap the full calculator stack is tx, ty, ax, ay.
  406. ; Just as one would do if drawing the curve on paper, the final line would
  407. ; be drawn by joining the last point plotted to the initial start point
  408. ; in the case of a CIRCLE or to the calculated end point in the case of
  409. ; an ARC.
  410. ; The moving absolute values of x and y are no longer required and they
  411. ; can be deleted to expose the closing coordinates.
  412. ;; ARC-END
  413. L245F: RST 28H ;; FP-CALC tx, ty, ax, ay.
  414. DEFB $02 ;;delete tx, ty, ax.
  415. DEFB $02 ;;delete tx, ty.
  416. DEFB $01 ;;exchange ty, tx.
  417. DEFB $38 ;;end-calc ty, tx.
  418. ; First calculate the relative x coordinate to the end-point.
  419. LD A,($5C7D) ; COORDS-x
  420. CALL L2D28 ; routine STACK-A
  421. RST 28H ;; FP-CALC ty, tx, coords_x.
  422. DEFB $03 ;;subtract ty, rx.
  423. ; Next calculate the relative y coordinate to the end-point.
  424. DEFB $01 ;;exchange rx, ty.
  425. DEFB $38 ;;end-calc rx, ty.
  426. LD A,($5C7E) ; COORDS-y
  427. CALL L2D28 ; routine STACK-A
  428. RST 28H ;; FP-CALC rx, ty, coords_y
  429. DEFB $03 ;;subtract rx, ry.
  430. DEFB $38 ;;end-calc rx, ry.
  431. ; Finally draw the last straight line.
  432. L2477:
  433. call STACK_TO_BC ;;Pops x, and y, and stores it in B, C
  434. ld hl, (COORDS) ;;Calculates x2 and y2 in L, H
  435. rl e ;; Rotate left to carry
  436. ld a, c
  437. jr nc, SUM_C
  438. neg
  439. SUM_C:
  440. add a, l
  441. ld l, a ;; X2
  442. rl d ;; Low sign to carry
  443. ld a, b
  444. jr nc, SUM_B
  445. neg
  446. SUM_B:
  447. add a, h
  448. ld h, a
  449. jp __DRAW ;;forward to LINE-DRAW (Fastcalled)
  450. ENDP