draw.asm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. ; DRAW using bresenhams algorithm and screen positioning
  2. ; Copyleft (k) 2010 by J. Rodriguez (a.k.a. Boriel) http://www.boriel.com
  3. ; vim:ts=4:et:sw=4:
  4. ; Y parameter in A
  5. ; X parameter in high byte on top of the stack
  6. ;
  7. #include once <error.asm>
  8. #include once <in_screen.asm>
  9. #include once <cls.asm>
  10. #include once <SP/PixelDown.asm>
  11. #include once <SP/PixelUp.asm>
  12. #include once <SP/PixelLeft.asm>
  13. #include once <SP/PixelRight.asm>
  14. ;
  15. ;; DRAW PROCEDURE
  16. ;- PROC
  17. ;- LOCAL __DRAW1
  18. ;- LOCAL __DRAW2
  19. ;- LOCAL __DRAW3
  20. ;- LOCAL __DRAW4, __DRAW4_LOOP
  21. ;- LOCAL __DRAW5
  22. ;- LOCAL __DRAW6, __DRAW6_LOOP
  23. ;- LOCAL __DRAW_ERROR
  24. ;- LOCAL DX1, DX2, DY1, DY2
  25. ;- LOCAL __INCX, __INCY, __DECX, __DECY
  26. ;- LOCAL P_FLAG
  27. ;- P_FLAG EQU 23697
  28. __DRAW_ERROR:
  29. ;- jp __OUT_OF_SCREEN_ERR
  30. DRAW:
  31. ;; ENTRY POINT
  32. ;- LOCAL PIXEL_ADDR
  33. ;- LOCAL COORDS
  34. ;- LOCAL __DRAW_SETUP1, __DRAW_START, __PLOTOVER, __PLOTINVERSE
  35. lda z80_e ;- ex de,hl ; DE = Y OFFSET
  36. ldx z80_l
  37. stx z80_e
  38. sta z80_l
  39. lda z80_d
  40. ldx z80_h
  41. stx z80_d
  42. sta z80_h
  43. ;- pop hl ; return addr
  44. ;- ex (sp), hl ; CALLEE => HL = X OFFSET
  45. ;- ld bc, (COORDS)
  46. ;- ld a, c
  47. ;- add a, l
  48. ;- ld l, a
  49. ;- ld a, h
  50. ;- adc a, 0 ; HL = HL + C
  51. ;- ld h, a
  52. ;- jr nz, __DRAW_ERROR ; if a <> 0 => Out of Screen
  53. ;- ld a, b
  54. ;- add a, e
  55. ;- ld e, a
  56. ;- ld a, d
  57. ;- adc a, 0 ; DE = DE + B
  58. ;- ld d, a
  59. ;- jr nz, __DRAW_ERROR ; if a <> 0 => Out of Screen
  60. ;- ld a, 191
  61. ;- sub e
  62. ;- jr c, __DRAW_ERROR ; Out of screen
  63. ;- ld h, e ; now H,L = y2, x2
  64. __DRAW:
  65. ; __FASTCALL__ Entry. Plots from (COORDS) to coord H, L
  66. ;- push hl
  67. ;- ex de, hl ; D,E = y2, x2;
  68. ;- ld a, (P_FLAG)
  69. ;- ld c, a
  70. ;- bit 2, a ; Test for INVERSE1
  71. ;- jr z, __DRAW_SETUP1
  72. ;- ld a, 2Fh ; CPL
  73. ;- ld (__PLOTINVERSE), a
  74. ;- ld a, 0A6h ; and (hl)
  75. ;- jp __DRAW_START
  76. __DRAW_SETUP1:
  77. ;- xor a ; nop
  78. ;- ld (__PLOTINVERSE), a
  79. ;- ld a, 0B6h ; or (hl)
  80. ;- bit 0, c ; Test for OVER
  81. ;- jr z, __DRAW_START
  82. ;- ld a, 0AEh ; xor (hl)
  83. __DRAW_START:
  84. ;- ld (__PLOTOVER), a ; "Pokes" last operation
  85. lda z80_c ;- exx
  86. ldx z80_cp
  87. stx z80_c
  88. sta z80_cp
  89. lda z80_b
  90. ldx z80_bp
  91. stx z80_b
  92. sta z80_bp
  93. lda z80_e
  94. ldx z80_ep
  95. stx z80_e
  96. sta z80_ep
  97. lda z80_d
  98. ldx z80_dp
  99. stx z80_d
  100. sta z80_dp
  101. lda z80_l
  102. ldx z80_lp
  103. stx z80_l
  104. sta z80_lp
  105. lda z80_h
  106. ldx z80_hp
  107. stx z80_h
  108. sta z80_hp
  109. ;- ld bc, (COORDS) ; B'C' = y1, x1
  110. ;- ld d, b ; Saves B' in D'
  111. ;- ld a, 191
  112. ;- LOCAL __PIXEL_ADDR
  113. __PIXEL_ADDR EQU 22ACh
  114. ;- call __PIXEL_ADDR
  115. ;; Now gets pixel mask in A register
  116. ;- ld b, a
  117. ;- inc b
  118. ;- xor a
  119. ;- scf
  120. ;- LOCAL __PIXEL_MASK
  121. __PIXEL_MASK:
  122. ;- rra
  123. ;- djnz __PIXEL_MASK
  124. ;- ld b, d ; Restores B' from D'
  125. ;- pop de ; D'E' = y2, x2
  126. lda z80_c ;- exx
  127. ldx z80_cp
  128. stx z80_c
  129. sta z80_cp
  130. lda z80_b
  131. ldx z80_bp
  132. stx z80_b
  133. sta z80_bp
  134. lda z80_e
  135. ldx z80_ep
  136. stx z80_e
  137. sta z80_ep
  138. lda z80_d
  139. ldx z80_dp
  140. stx z80_d
  141. sta z80_dp
  142. lda z80_l
  143. ldx z80_lp
  144. stx z80_l
  145. sta z80_lp
  146. lda z80_h
  147. ldx z80_hp
  148. stx z80_h
  149. sta z80_hp
  150. ; At this point: D'E' = y2,x2 coords
  151. ; B'C' = y1, y1 coords
  152. ;- ex af, af' ; Saves A reg for later
  153. ; A' = Pixel mask
  154. ; H'L' = Screen Address of pixel
  155. ;- ld bc, (COORDS) ; B,C = y1, x1
  156. ;- ld a, e
  157. ;- sub c ; dx = X2 - X1
  158. ;- ld c, a ; Saves dx in c
  159. ;- ld a, 0Ch ; INC C opcode
  160. ;- ld hl, __INCX ; xi = 1
  161. ;- jr nc, __DRAW1
  162. ;- ld a, c
  163. ;- neg ; dx = X1 - X2
  164. ;- ld c, a
  165. ;- ld a, 0Dh ; DEC C opcode
  166. ;- ld hl, __DECX ; xi = -1
  167. __DRAW1:
  168. ;- ld (DX1), a
  169. ;- ld (DX1 + 2), hl ; Updates DX1 call address
  170. ;- ld (DX2), a
  171. ;- ld (DX2 + 2), hl ; Updates DX2 call address
  172. ;- ld a, d
  173. ;- sub b ; dy = Y2 - Y1
  174. ;- ld b, a ; Saves dy in b
  175. ;- ld a, 4 ; INC B opcode
  176. ;- ld hl, __INCY ; y1 = 1
  177. ;- jr nc, __DRAW2
  178. ;- ld a, b
  179. ;- neg
  180. ;- ld b, a ; dy = Y2 - Y1
  181. ;- ld a, 5 ; DEC B opcode
  182. ;- ld hl, __DECY ; y1 = -1
  183. __DRAW2:
  184. ;- ld (DY1), a
  185. ;- ld (DY1 + 2), hl ; Updates DX1 call address
  186. ;- ld (DY2), a
  187. ;- ld (DY2 + 2), hl ; Updates DX2 call address
  188. ;- ld a, b
  189. ;- sub c ; dy - dx
  190. ;- jr c, __DRAW_DX_GT_DY ; DX > DY
  191. ; At this point DY >= DX
  192. ; --------------------------
  193. ; HL = error = dY / 2
  194. ;- ld h, 0
  195. ;- ld l, b
  196. ;- srl l
  197. ; DE = -dX
  198. ;- xor a
  199. ;- sub c
  200. ;- ld e, a
  201. ;- sbc a, a
  202. ;- ld d, a
  203. ; BC = DY
  204. ;- ld c, b
  205. ;- ld b, h
  206. lda z80_c ;- exx
  207. ldx z80_cp
  208. stx z80_c
  209. sta z80_cp
  210. lda z80_b
  211. ldx z80_bp
  212. stx z80_b
  213. sta z80_bp
  214. lda z80_e
  215. ldx z80_ep
  216. stx z80_e
  217. sta z80_ep
  218. lda z80_d
  219. ldx z80_dp
  220. stx z80_d
  221. sta z80_dp
  222. lda z80_l
  223. ldx z80_lp
  224. stx z80_l
  225. sta z80_lp
  226. lda z80_h
  227. ldx z80_hp
  228. stx z80_h
  229. sta z80_hp
  230. ;- scf ; Sets Carry to signal update ATTR
  231. ;- ex af, af' ; Brings back pixel mask
  232. ;- ld e, a ; Saves it in free E register
  233. ;- jp __DRAW4_LOOP
  234. __DRAW3: ; While c != e => while y != y2
  235. lda z80_c ;- exx
  236. ldx z80_cp
  237. stx z80_c
  238. sta z80_cp
  239. lda z80_b
  240. ldx z80_bp
  241. stx z80_b
  242. sta z80_bp
  243. lda z80_e
  244. ldx z80_ep
  245. stx z80_e
  246. sta z80_ep
  247. lda z80_d
  248. ldx z80_dp
  249. stx z80_d
  250. sta z80_dp
  251. lda z80_l
  252. ldx z80_lp
  253. stx z80_l
  254. sta z80_lp
  255. lda z80_h
  256. ldx z80_hp
  257. stx z80_h
  258. sta z80_hp
  259. ;- add hl, de ; error -= dX
  260. ;- bit 7, h ;
  261. lda z80_c ;- exx ; recover coordinates
  262. ldx z80_cp
  263. stx z80_c
  264. sta z80_cp
  265. lda z80_b
  266. ldx z80_bp
  267. stx z80_b
  268. sta z80_bp
  269. lda z80_e
  270. ldx z80_ep
  271. stx z80_e
  272. sta z80_ep
  273. lda z80_d
  274. ldx z80_dp
  275. stx z80_d
  276. sta z80_dp
  277. lda z80_l
  278. ldx z80_lp
  279. stx z80_l
  280. sta z80_lp
  281. lda z80_h
  282. ldx z80_hp
  283. stx z80_h
  284. sta z80_hp
  285. ;- jr z, __DRAW4 ; if error < 0
  286. lda z80_c ;- exx
  287. ldx z80_cp
  288. stx z80_c
  289. sta z80_cp
  290. lda z80_b
  291. ldx z80_bp
  292. stx z80_b
  293. sta z80_bp
  294. lda z80_e
  295. ldx z80_ep
  296. stx z80_e
  297. sta z80_ep
  298. lda z80_d
  299. ldx z80_dp
  300. stx z80_d
  301. sta z80_dp
  302. lda z80_l
  303. ldx z80_lp
  304. stx z80_l
  305. sta z80_lp
  306. lda z80_h
  307. ldx z80_hp
  308. stx z80_h
  309. sta z80_hp
  310. ;- add hl, bc ; error += dY
  311. lda z80_c ;- exx
  312. ldx z80_cp
  313. stx z80_c
  314. sta z80_cp
  315. lda z80_b
  316. ldx z80_bp
  317. stx z80_b
  318. sta z80_bp
  319. lda z80_e
  320. ldx z80_ep
  321. stx z80_e
  322. sta z80_ep
  323. lda z80_d
  324. ldx z80_dp
  325. stx z80_d
  326. sta z80_dp
  327. lda z80_l
  328. ldx z80_lp
  329. stx z80_l
  330. sta z80_lp
  331. lda z80_h
  332. ldx z80_hp
  333. stx z80_h
  334. sta z80_hp
  335. ;- ld a, e
  336. DX1: ; x += xi
  337. inc z80_c ;- inc c
  338. jsr __INCX ;- call __INCX ; This address will be dynamically updated
  339. ;- ld e, a
  340. __DRAW4:
  341. DY1:
  342. ; y += yi
  343. inc z80_b ;- inc b
  344. jsr __INCY ;- call __INCY ; This address will be dyncamically updated
  345. ;- ld a, e ; Restores A reg.
  346. jsr __FASTPLOT ;- call __FASTPLOT
  347. __DRAW4_LOOP:
  348. ;- ld a, b
  349. ;- cp d
  350. ;- jp nz, __DRAW3
  351. ;- ld (COORDS), bc
  352. rts ;- ret
  353. __DRAW_DX_GT_DY: ; DX > DY
  354. ; --------------------------
  355. ; HL = error = dX / 2
  356. ;- ld h, 0
  357. ;- ld l, c
  358. ;- srl l ; HL = error = DX / 2
  359. ; DE = -dY
  360. ;- xor a
  361. ;- sub b
  362. ;- ld e, a
  363. ;- sbc a, a
  364. ;- ld d, a
  365. ; BC = dX
  366. ;- ld b, h
  367. lda z80_c ;- exx
  368. ldx z80_cp
  369. stx z80_c
  370. sta z80_cp
  371. lda z80_b
  372. ldx z80_bp
  373. stx z80_b
  374. sta z80_bp
  375. lda z80_e
  376. ldx z80_ep
  377. stx z80_e
  378. sta z80_ep
  379. lda z80_d
  380. ldx z80_dp
  381. stx z80_d
  382. sta z80_dp
  383. lda z80_l
  384. ldx z80_lp
  385. stx z80_l
  386. sta z80_lp
  387. lda z80_h
  388. ldx z80_hp
  389. stx z80_h
  390. sta z80_hp
  391. ;- ld d, e
  392. ;- scf ; Sets Carry to signal update ATTR
  393. ;- ex af, af' ; Brings back pixel mask
  394. ;- ld e, a ; Saves it in free E register
  395. ;- jp __DRAW6_LOOP
  396. __DRAW5: ; While loop
  397. lda z80_c ;- exx
  398. ldx z80_cp
  399. stx z80_c
  400. sta z80_cp
  401. lda z80_b
  402. ldx z80_bp
  403. stx z80_b
  404. sta z80_bp
  405. lda z80_e
  406. ldx z80_ep
  407. stx z80_e
  408. sta z80_ep
  409. lda z80_d
  410. ldx z80_dp
  411. stx z80_d
  412. sta z80_dp
  413. lda z80_l
  414. ldx z80_lp
  415. stx z80_l
  416. sta z80_lp
  417. lda z80_h
  418. ldx z80_hp
  419. stx z80_h
  420. sta z80_hp
  421. ;- add hl, de ; error -= dY
  422. ;- bit 7, h ; if (error < 0)
  423. lda z80_c ;- exx ; Restore coords
  424. ldx z80_cp
  425. stx z80_c
  426. sta z80_cp
  427. lda z80_b
  428. ldx z80_bp
  429. stx z80_b
  430. sta z80_bp
  431. lda z80_e
  432. ldx z80_ep
  433. stx z80_e
  434. sta z80_ep
  435. lda z80_d
  436. ldx z80_dp
  437. stx z80_d
  438. sta z80_dp
  439. lda z80_l
  440. ldx z80_lp
  441. stx z80_l
  442. sta z80_lp
  443. lda z80_h
  444. ldx z80_hp
  445. stx z80_h
  446. sta z80_hp
  447. ;- jr z, __DRAW6 ;
  448. lda z80_c ;- exx
  449. ldx z80_cp
  450. stx z80_c
  451. sta z80_cp
  452. lda z80_b
  453. ldx z80_bp
  454. stx z80_b
  455. sta z80_bp
  456. lda z80_e
  457. ldx z80_ep
  458. stx z80_e
  459. sta z80_ep
  460. lda z80_d
  461. ldx z80_dp
  462. stx z80_d
  463. sta z80_dp
  464. lda z80_l
  465. ldx z80_lp
  466. stx z80_l
  467. sta z80_lp
  468. lda z80_h
  469. ldx z80_hp
  470. stx z80_h
  471. sta z80_hp
  472. ;- add hl, bc ; error += dX
  473. lda z80_c ;- exx
  474. ldx z80_cp
  475. stx z80_c
  476. sta z80_cp
  477. lda z80_b
  478. ldx z80_bp
  479. stx z80_b
  480. sta z80_bp
  481. lda z80_e
  482. ldx z80_ep
  483. stx z80_e
  484. sta z80_ep
  485. lda z80_d
  486. ldx z80_dp
  487. stx z80_d
  488. sta z80_dp
  489. lda z80_l
  490. ldx z80_lp
  491. stx z80_l
  492. sta z80_lp
  493. lda z80_h
  494. ldx z80_hp
  495. stx z80_h
  496. sta z80_hp
  497. DY2: ; y += yi
  498. ;- inc b
  499. jsr __INCY ;- call __INCY ; This address will be dynamically updated
  500. __DRAW6:
  501. lda z80_e ;- ld a,e
  502. sta z80_a
  503. DX2: ; x += xi
  504. ;- inc c
  505. jsr __INCX ;- call __INCX ; This address will be dynamically updated
  506. lda z80_a ;- ld e,a
  507. sta z80_e
  508. jsr __FASTPLOT ;- call __FASTPLOT
  509. __DRAW6_LOOP:
  510. lda z80_c ;- ld a,c ; Current X coord
  511. sta z80_a
  512. ;- cp d
  513. ;- jp nz, __DRAW5
  514. ;- ld (COORDS), bc
  515. rts ;- ret
  516. PIXEL_ADDR EQU 22ACh
  517. COORDS EQU 5C7Dh
  518. __DRAW_END:
  519. lda z80_c ;- exx
  520. ldx z80_cp
  521. stx z80_c
  522. sta z80_cp
  523. lda z80_b
  524. ldx z80_bp
  525. stx z80_b
  526. sta z80_bp
  527. lda z80_e
  528. ldx z80_ep
  529. stx z80_e
  530. sta z80_ep
  531. lda z80_d
  532. ldx z80_dp
  533. stx z80_d
  534. sta z80_dp
  535. lda z80_l
  536. ldx z80_lp
  537. stx z80_l
  538. sta z80_lp
  539. lda z80_h
  540. ldx z80_hp
  541. stx z80_h
  542. sta z80_hp
  543. rts ;- ret
  544. ;
  545. ;; Given a A mask and an HL screen position
  546. ;; return the next left position
  547. ;; Also updates BC coords
  548. __DECX EQU SP.PixelLeft
  549. ;; Like the above, but to the RIGHT
  550. ;; Also updates BC coords
  551. __INCX EQU SP.PixelRight
  552. ;; Given an HL screen position, calculates
  553. ;; the above position
  554. ;; Also updates BC coords
  555. __INCY EQU SP.PixelUp
  556. ;; Given an HL screen position, calculates
  557. ;; the above position
  558. ;; Also updates BC coords
  559. __DECY EQU SP.PixelDown
  560. ;; Puts the A register MASK in (HL)
  561. __FASTPLOT:
  562. __PLOTINVERSE:
  563. ;- nop ; Replace with CPL if INVERSE 1
  564. __PLOTOVER:
  565. ldy #$00 ;- or (hl)
  566. ora (z80_hl),y
  567. ; Replace with XOR (hl) if OVER 1 AND INVERSE 0
  568. ; Replace with AND (hl) if INVERSE 1
  569. lda z80_a ;- ld (hl),a
  570. ldy #$00
  571. sta (z80_hl),y
  572. ldx z80_ap ;- ex af, af' ; Recovers flag. If Carry set => update ATTR
  573. sta z80_ap
  574. txa
  575. lda z80_e ;- ld a,e ; Recovers A reg
  576. sta z80_a
  577. bcc *+3 ;- ret nc
  578. rts
  579. lda z80_l ;- push hl
  580. pha
  581. lda z80_h
  582. pha
  583. lda z80_e ;- push de
  584. pha
  585. lda z80_d
  586. pha
  587. ;; gets ATTR position with offset given in SCREEN_ADDR
  588. lda z80_h ;- ld a,h
  589. sta z80_a
  590. ;- rrca
  591. ;- rrca
  592. ;- rrca
  593. and #$03 ;- and $03
  594. ora #$18 ;- or $18
  595. lda z80_a ;- ld h,a
  596. sta z80_h
  597. lda SCREEN_ADDR ;- ld de,(SCREEN_ADDR)
  598. sta z80_e
  599. lda SCREEN_ADDR+1
  600. sta z80_d
  601. ;- add hl,de ;; Final screen addr
  602. LOCAL PO_ATTR_2
  603. PO_ATTR_2 EQU 0BE4h ; Another entry to PO_ATTR
  604. jsr PO_ATTR_2 ;- call PO_ATTR_2 ; This will update attr accordingly. Beware, uses IY
  605. pla ;- pop de
  606. sta z80_d
  607. pla
  608. sta z80_e
  609. pla ;- pop hl
  610. sta z80_h
  611. pla
  612. sta z80_l
  613. ;- LOCAL __FASTPLOTEND
  614. __FASTPLOTEND:
  615. ora z80_a ;- or a ; Resets carry flag
  616. ldx z80_ap ;- ex af, af' ; Recovers A reg
  617. sta z80_ap
  618. txa
  619. lda z80_e ;- ld a,e
  620. sta z80_a
  621. rts ;- ret
  622. ;- ENDP