drawrect.z80 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. bordermask = TempWord2
  2. fillmask = TempWord3
  3. leftmask = bordermask
  4. rightmask = fillmask
  5. rect:
  6. ;Inputs:
  7. ; A is the type of rectangle to draw
  8. ; 0 = White
  9. ; 1 = Black
  10. ; 2 = XOR
  11. ; 3 = Black border
  12. ; 4 = White border
  13. ; 5 = XOR border
  14. ; 6 = Black border, white fill
  15. ; 7 = Black border, invert fill
  16. ; 8 = White border, black fill
  17. ; 9 = White border, invert fill
  18. ; 10 = Shift Up
  19. ; 11 = Shift Down
  20. ; 12 = Shift Right *Not Implmented
  21. ; 13 = Shift Left *Not Implemented
  22. ; 14 = Pxl-Test Rect (count the on pixels)
  23. ; 15 = Pxl-Test border (count the on pixels)
  24. ; 16 = Invert border, Black fill
  25. ; 17 = Invert border, White fill
  26. ; B is the height
  27. ; C is the Y pixel coordinate
  28. ; D is the width in pixels
  29. ; E is is the X pixel coordinate
  30. ; (gbuf_temp) points to the buffer to draw to.
  31. ;Outputs:
  32. ; BC is the count for the pixel test methods.
  33. ;Destroys:
  34. ; AF,BC,DE,HL, TempWord1, TempWord2
  35. ; IX is destroyed in the pixel count and shifting routines.
  36. or a
  37. jp z,rect_wbwf
  38. dec a
  39. jp z,rect_bbbf
  40. dec a
  41. jp z,rect_xbxf
  42. dec a
  43. jp z,rect_bbcf
  44. dec a
  45. jp z,rect_wbcf
  46. dec a
  47. jp z,rect_xbcf
  48. dec a
  49. jr z,rect_bbwf
  50. dec a
  51. jr z,rect_bbxf
  52. dec a
  53. jr z,rect_wbbf
  54. dec a
  55. jr z,rect_wbxf
  56. dec a
  57. jp z,rect_shift_up
  58. dec a
  59. jp z,rect_shift_down
  60. dec a
  61. jp z,rect_shift_right
  62. dec a
  63. jp z,rect_shift_left
  64. dec a
  65. jp z,pixel_test_rect
  66. dec a
  67. jp z,pixel_test_border
  68. dec a
  69. jr z,rect_xbbf
  70. dec a
  71. ret nz
  72. rect_xbwf:
  73. push de
  74. push bc
  75. call rect_xbcf
  76. jr rect_white_fill
  77. rect_bbwf:
  78. push de
  79. push bc
  80. call rect_bbcf
  81. rect_white_fill:
  82. pop bc
  83. pop de
  84. inc c
  85. inc e
  86. ld a,b
  87. sub 2
  88. ret c
  89. ld b,a
  90. ld a,d
  91. sub 2
  92. ret c
  93. ld d,a
  94. jr rect_wbwf
  95. rect_bbxf:
  96. push de
  97. push bc
  98. call rect_bbcf
  99. jr rect_x_fill
  100. rect_wbxf:
  101. push de
  102. push bc
  103. call rect_wbcf
  104. rect_x_fill:
  105. pop bc
  106. pop de
  107. inc c
  108. inc e
  109. ld a,b
  110. sub 2
  111. ret c
  112. ld b,a
  113. ld a,d
  114. sub 2
  115. ret c
  116. ld d,a
  117. jr rect_xbxf
  118. rect_wbbf:
  119. push de
  120. push bc
  121. call rect_wbcf
  122. jr rect_black_fill
  123. rect_xbbf:
  124. push de
  125. push bc
  126. call rect_xbcf
  127. rect_black_fill:
  128. pop bc
  129. pop de
  130. inc c
  131. inc e
  132. ld a,b
  133. sub 2
  134. ret c
  135. ld b,a
  136. ld a,d
  137. sub 2
  138. ret c
  139. ld d,a
  140. jr rect_bbbf
  141. rect_wbwf:
  142. call rectsub
  143. ret nc
  144. _:
  145. call horiz_wb
  146. djnz -_
  147. ret
  148. rect_bbbf:
  149. call rectsub
  150. ret nc
  151. _:
  152. call horiz_bb
  153. djnz -_
  154. ret
  155. rect_xbxf:
  156. call rectsub
  157. ret nc
  158. _:
  159. call horiz_xb
  160. djnz -_
  161. ret
  162. rect_bbcf:
  163. call rectsub
  164. ret nc
  165. rra
  166. jr c,+_
  167. push af
  168. call horiz_bb
  169. pop af
  170. dec b
  171. ret z
  172. _:
  173. ld de,(bordermask)
  174. rra
  175. push af
  176. jr nc,rect_bbcf_loopend
  177. _:
  178. push bc
  179. push hl
  180. ld a,d
  181. or (hl)
  182. ld (hl),a
  183. ld b,0
  184. dec c
  185. add hl,bc
  186. ld a,e
  187. or (hl)
  188. ld (hl),a
  189. pop hl
  190. ld c,12
  191. add hl,bc
  192. pop bc
  193. rect_bbcf_loopend:
  194. djnz -_
  195. pop af
  196. ret c
  197. ld de,(fillmask)
  198. jp horiz_bb
  199. rect_wbcf:
  200. call rectsub
  201. ret nc
  202. rra
  203. jr c,+_
  204. push af
  205. call horiz_wb
  206. pop af
  207. dec b
  208. ret z
  209. _:
  210. ld de,(bordermask)
  211. rra
  212. push af
  213. ld de,(bordermask)
  214. ld a,d
  215. cpl
  216. ld d,a
  217. ld a,e
  218. cpl
  219. ld e,a
  220. jr nc,rect_wbcf_loopend
  221. _:
  222. push bc
  223. push hl
  224. ld a,d
  225. and (hl)
  226. ld (hl),a
  227. ld b,0
  228. dec c
  229. add hl,bc
  230. ld a,e
  231. and (hl)
  232. ld (hl),a
  233. pop hl
  234. ld c,12
  235. add hl,bc
  236. pop bc
  237. rect_wbcf_loopend:
  238. djnz -_
  239. pop af
  240. ret c
  241. ld de,(fillmask)
  242. jp horiz_wb
  243. rect_xbcf:
  244. call rectsub
  245. ret nc
  246. rra
  247. jr c,+_
  248. push af
  249. call horiz_xb
  250. pop af
  251. dec b
  252. ret z
  253. _:
  254. ld de,(bordermask)
  255. rra
  256. push af
  257. jr nc,rect_xbcf_loopend
  258. _:
  259. push bc
  260. push hl
  261. ld a,d
  262. xor (hl)
  263. ld (hl),a
  264. ld b,0
  265. dec c
  266. add hl,bc
  267. ld a,e
  268. xor (hl)
  269. ld (hl),a
  270. pop hl
  271. ld c,12
  272. add hl,bc
  273. pop bc
  274. rect_xbcf_loopend:
  275. djnz -_
  276. pop af
  277. ret c
  278. ld de,(fillmask)
  279. jp horiz_xb
  280. horizline_white:
  281. ;takes as input E=x, A=y, D=width as input
  282. ld b,1
  283. ld c,a
  284. call rectsub
  285. ret nc
  286. horiz_wb:
  287. ;Draws a horizontal white border
  288. ;Save the width and height
  289. push bc
  290. ;Get the width in B
  291. ld b,c
  292. ;Check if the width is 1
  293. ld a,d
  294. dec b
  295. jr nz,+_
  296. and e
  297. cpl
  298. and (hl)
  299. ld (hl),a
  300. jr rect_add12
  301. _:
  302. ;save the pointer so that we can add 12 later
  303. push hl
  304. cpl
  305. and (hl)
  306. ld (hl),a
  307. xor a
  308. .db $FE
  309. _:
  310. ld (hl),a
  311. inc hl
  312. djnz -_
  313. ld a,e
  314. cpl
  315. and (hl)
  316. ld (hl),a
  317. ;restore the pointer and add 12
  318. ;take advantage of B=0 before restoring
  319. jr rect_restadd12
  320. horizline_black:
  321. ;takes as input E=x, A=y, D=width as input
  322. ld b,1
  323. ld c,a
  324. call rectsub
  325. ret nc
  326. horiz_bb:
  327. ;Draws a horizontal black border
  328. ;Save the width and height
  329. push bc
  330. ;Get the width in B
  331. ld b,c
  332. ;Check if the width is 1
  333. ld a,d
  334. dec b
  335. jr nz,+_
  336. and e
  337. or (hl)
  338. ld (hl),a
  339. jr rect_add12
  340. _:
  341. ;save the pointer so that we can add 12 later
  342. push hl
  343. or (hl)
  344. ld (hl),a
  345. ld a,-1
  346. .db $FE
  347. _:
  348. ld (hl),a
  349. inc hl
  350. djnz -_
  351. ld a,e
  352. or (hl)
  353. ld (hl),a
  354. jr rect_restadd12
  355. horizline_invert:
  356. ;takes as input E=x, A=y, D=width as input
  357. ld b,1
  358. ld c,a
  359. call rectsub
  360. ret nc
  361. horiz_xb:
  362. ;Draws a horizontal inverted border
  363. ;Save the width and height
  364. push bc
  365. ;Get the width in B
  366. ld b,c
  367. ;Check if the width is 1
  368. ld a,d
  369. dec b
  370. jr nz,+_
  371. and e
  372. xor (hl)
  373. ld (hl),a
  374. jr rect_add12
  375. _:
  376. ;save the pointer so that we can add 12 later
  377. push hl
  378. xor (hl)
  379. ld (hl),a
  380. jr $+5
  381. _:
  382. ld a,(hl)
  383. cpl
  384. ld (hl),a
  385. inc hl
  386. djnz -_
  387. ld a,e
  388. xor (hl)
  389. ld (hl),a
  390. ;restore the pointer and add 12
  391. ;take advantage of B=0 before restoring
  392. rect_restadd12:
  393. pop hl
  394. rect_add12:
  395. ld c,12
  396. add hl,bc
  397. pop bc
  398. ret
  399. horiz_count:
  400. ;returns A as the number of set bits.
  401. ;screen is less than 256 pixels wide, so no need to worry about overflow
  402. push bc
  403. ld b,c
  404. ld c,-1
  405. dec b
  406. jr nz,+_
  407. ld a,d
  408. and e
  409. and (hl)
  410. inc c
  411. add a,a
  412. jr c,$-2
  413. jr nz,$-3
  414. add ix,bc
  415. jr rect_add12
  416. _:
  417. push hl
  418. ld a,(hl)
  419. and d
  420. inc c
  421. add a,a
  422. jr c,$-2
  423. jr nz,$-3
  424. jr horiz_count_loop_end
  425. horiz_count_loop:
  426. ld a,(hl)
  427. .db $FE
  428. inc c
  429. add a,a
  430. jr c,$-2
  431. jr nz,$-3
  432. horiz_count_loop_end:
  433. inc hl
  434. djnz horiz_count_loop
  435. ld a,(hl)
  436. and e
  437. .db $FE
  438. inc c
  439. add a,a
  440. jr c,$-2
  441. jr nz,$-3
  442. add ix,bc
  443. jr rect_restadd12
  444. rect_shift_up:
  445. call rectsub
  446. ret nc
  447. dec c
  448. jr z,rect_shift_up_1col
  449. jr rect_shift_up_end
  450. rect_shift_up_loop:
  451. push bc
  452. push hl
  453. push hl
  454. pop ix
  455. ld a,(ix+12)
  456. xor (hl)
  457. and d
  458. xor (hl)
  459. ld (hl),a
  460. ld b,c
  461. jr rect_shift_up_loop_final
  462. _:
  463. ld a,(ix+12)
  464. ld (hl),a
  465. rect_shift_up_loop_final:
  466. inc hl
  467. inc ix
  468. djnz -_
  469. ld a,(ix+12)
  470. xor (hl)
  471. and e
  472. xor (hl)
  473. ld (hl),a
  474. pop hl
  475. ld c,12
  476. add hl,bc
  477. pop bc
  478. rect_shift_up_end:
  479. djnz rect_shift_up_loop
  480. inc c
  481. jp horiz_wb
  482. rect_shift_up_1col:
  483. ld a,d
  484. and e
  485. ld d,a
  486. jr rect_shift_up_1col_end
  487. _:
  488. push hl
  489. pop ix
  490. ld a,(ix+12)
  491. xor (hl)
  492. and d
  493. xor (hl)
  494. ld (hl),a
  495. ld a,l
  496. add a,12
  497. ld l,a
  498. jr nc,rect_shift_up_1col_end
  499. inc h
  500. rect_shift_up_1col_end:
  501. djnz -_
  502. ld a,d
  503. cpl
  504. and (hl)
  505. ld (hl),a
  506. ret
  507. rect_shift_down:
  508. call rectsub
  509. ret nc
  510. ;need to start at the bottom and work backwards!
  511. ;HL + B*12-1
  512. push bc
  513. push hl
  514. ld a,c
  515. dec b
  516. ld h,0
  517. ld l,b
  518. ld b,h
  519. ld c,l
  520. add hl,hl
  521. add hl,bc
  522. add hl,hl
  523. add hl,hl
  524. dec l ;B is at most 63, B*12 != 0 mod 256, so this is safe
  525. ld c,a
  526. add hl,bc
  527. pop bc
  528. add hl,bc
  529. pop bc
  530. dec c
  531. jr z,rect_shift_down_1col
  532. jr rect_shift_down_end
  533. rect_shift_down_loop:
  534. push bc
  535. push hl
  536. push hl
  537. pop ix
  538. ld a,(ix-12)
  539. xor (hl)
  540. and e
  541. xor (hl)
  542. ld (hl),a
  543. ld b,c
  544. jr rect_shift_down_loop_final
  545. _:
  546. ld a,(ix-12)
  547. ld (hl),a
  548. rect_shift_down_loop_final:
  549. dec hl
  550. dec ix
  551. djnz -_
  552. ld a,(ix-12)
  553. xor (hl)
  554. and d
  555. xor (hl)
  556. ld (hl),a
  557. pop hl
  558. ld bc,-12
  559. add hl,bc
  560. pop bc
  561. rect_shift_down_end:
  562. djnz rect_shift_down_loop
  563. or a
  564. sbc hl,bc
  565. inc c
  566. jp horiz_wb
  567. rect_shift_down_1col:
  568. ld a,d
  569. and e
  570. ld d,a
  571. jr rect_shift_up_1col_end
  572. _:
  573. push hl
  574. pop ix
  575. ld a,(ix-12)
  576. xor (hl)
  577. and d
  578. xor (hl)
  579. ld (hl),a
  580. ld a,l
  581. sub 12
  582. ld l,a
  583. jr nc,rect_shift_down_1col_end
  584. dec h
  585. rect_shift_down_1col_end:
  586. djnz -_
  587. ld a,d
  588. cpl
  589. and (hl)
  590. ld (hl),a
  591. ret
  592. rect_shift_right:
  593. rect_shift_left:
  594. ret
  595. setBC_0:
  596. ld bc,0
  597. ret
  598. pixel_test_rect:
  599. call rectsub
  600. jr nc,setBC_0
  601. ld ix,0
  602. _:
  603. call horiz_count
  604. djnz -_
  605. ld b,ixh
  606. ld c,ixl
  607. ret
  608. pixel_test_border:
  609. call rectsub
  610. jr nc,setBC_0
  611. ld ix,0
  612. call horiz_count
  613. dec b
  614. ret z
  615. ld de,(bordermask)
  616. jr pixel_test_border_loop_end
  617. pixel_test_border_loop:
  618. push bc
  619. push hl
  620. ld a,d
  621. and (hl)
  622. jr z,+_
  623. inc ix
  624. _:
  625. ld b,0
  626. dec c
  627. add hl,bc
  628. ld a,e
  629. and (hl)
  630. jr z,+_
  631. inc ix
  632. _:
  633. pop hl
  634. ld c,12
  635. add hl,bc
  636. pop bc
  637. pixel_test_border_loop_end:
  638. djnz pixel_test_border_loop
  639. ld de,(fillmask)
  640. call horiz_count
  641. ld b,ixh
  642. ld c,ixl
  643. ret
  644. rectsub:
  645. ;Input:
  646. ; (B,C) is (height,y)
  647. ; (D,E) is (width,x)
  648. ld a,b
  649. ld b,e
  650. ld e,a
  651. ;(E,C) = (x,y) signed
  652. ;(D,B) = (w,h) unsigned
  653. ;Output:
  654. ; Start Mask D
  655. ; End Mask E
  656. ; Height B
  657. ; Byte width C
  658. ; buf ptr HL
  659. ; bit 0 of A set if top clipped
  660. ; bit 1 of A set if bottom clipped
  661. ;H will temporarily keep track of left and right OOB
  662. ;bit 0 means left OOB, bit 1 means right OOB
  663. ;bit 2 means top OOB, bit 3 means bottom OOB
  664. ld hl,0
  665. ld (bordermask),hl
  666. bit 7,b
  667. jr z,+_
  668. ;Here, b is negative, so we have to add width to x.
  669. ;If the result is still negative, the entire box is out of bounds, so return
  670. ;otherwise, set width=newvalue,b=0
  671. ld a,d
  672. add a,b
  673. ret nc
  674. ld d,a
  675. ld b,h
  676. inc h
  677. _:
  678. bit 7,c
  679. jr z,+_
  680. ld a,e
  681. add a,c
  682. ret nc
  683. ld e,a
  684. ld c,0
  685. set 2,h
  686. _:
  687. ;We have clipped all negative areas.
  688. ;Now we need to verify that (x,y) are on the screen.
  689. ;If they aren't, then the whole rectangle is off-screen so no need to draw.
  690. ld a,b
  691. cp 96
  692. ret nc
  693. ld a,c
  694. cp 64
  695. ret nc
  696. ;Let's also verfiy that height and width are non-zero:
  697. ld a,d
  698. or a
  699. ret z
  700. ld a,e
  701. or a
  702. ret z
  703. ;Now we need to clip the width and height to be in-bounds
  704. add a,c
  705. cp 65
  706. jr c,+_
  707. ;Here we need to set e=64-c
  708. ld a,64
  709. sub c
  710. ld e,a
  711. set 3,h
  712. _:
  713. ld a,d
  714. add a,b
  715. cp 97
  716. jr c,+_
  717. ;Here we need to set d=96-b
  718. ld a,96
  719. sub b
  720. ld d,a
  721. inc h
  722. inc h
  723. _:
  724. ;B is starting X
  725. ;C is starting Y
  726. ;D is width
  727. ;E is height
  728. ;H has info on if the masks need to be adjusted for border vs. fill
  729. push bc
  730. ;Generate the first mask
  731. ld l,b
  732. ld a,b
  733. and 7
  734. ld b,a
  735. ld a,-1
  736. jr z,+_
  737. rra \ djnz $-1
  738. _:
  739. inc a
  740. cpl
  741. ld (fillmask+1),a ;left mask
  742. rr h
  743. jr c,+_
  744. add a,1
  745. rra
  746. ld (bordermask+1),a
  747. _:
  748. dec d
  749. ld a,l
  750. add a,d
  751. and 7
  752. ld b,a
  753. ld a,$7F
  754. jr z,+_
  755. rrca \ djnz $-1
  756. _:
  757. inc a
  758. ld (fillmask),a ;left mask
  759. rr h
  760. jr c,+_
  761. dec a
  762. cpl
  763. ld (bordermask),a
  764. _:
  765. ex (sp),hl
  766. ld a,h
  767. ld h,b
  768. add hl,hl
  769. add hl,bc
  770. add hl,hl
  771. add hl,hl
  772. ld b,a
  773. rrca
  774. rrca
  775. rrca
  776. and 31
  777. add a,l
  778. ld l,a
  779. jr nc,+_
  780. inc h
  781. _:
  782. ;B is the starting x, D is width
  783. ;Only A,B,D,E are available
  784. ld a,b
  785. add a,d
  786. and $F8
  787. ld d,a
  788. ld a,b
  789. and $F8
  790. ld b,a
  791. ld a,d
  792. sub b
  793. rrca
  794. rrca
  795. rrca
  796. ld c,a
  797. ld b,e
  798. ld de,(gbuf_temp)
  799. add hl,de
  800. ld de,(fillmask)
  801. inc c
  802. pop af
  803. scf
  804. ret