Author Topic: Rectangle Drawing Routines  (Read 8386 times)

0 Members and 1 Guest are viewing this topic.

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Rectangle Drawing Routines
« on: July 02, 2011, 12:51:48 am »
I have a program that uses two buffers and it toggles which buffer it's writing to using a flag. Because it uses that flag I figured it would be a good idea to utilize that for drawing routines so they can draw to whichever buffer it's currently set to instead of having to have separate routines for each buffer.

While writing those routines, I came up with this set of rectangle drawing routines that I think are pretty good, though they probably could be optimized quite a bit.

Anyway, I thought I'd share them:

Code: [Select]
;;---------------------
;; Rect Off/On/Inv
;;---------------------
RectOff:
;;Clears a rectangle on the buffer
;;IN:
;; D contains x
;; E contains width
;; H contains y
;; L contains height
;;DESTROYS: All, OP1, 1st byte of OP2
call GetRectLine
ld a, 12
sub c
ld e, a
ld d, 0
_rOffLoop1:
push de
ld de, OP1
push bc
ld b, c
_rOffLoop2:
ld a, (de)
cpl
and (hl)
ld (hl), a
inc hl
inc de
djnz _rOffLoop2
pop bc
pop de
add hl, de
djnz _rOffLoop1
ret

RectOn:
;;Draws a rectangle on the buffer
;;IN:
;; D contains x
;; E contains width
;; H contains y
;; L contains height
;;DESTROYS: All, OP1, 1st byte of OP2
call GetRectLine
ld a, 12
sub c
ld e, a
ld d, 0
_rOnLoop1:
push de
ld de, OP1
push bc
ld b, c
_rOnLoop2:
ld a, (de)
or (hl)
ld (hl), a
inc hl
inc de
djnz _rOnLoop2
pop bc
pop de
add hl, de
djnz _rOnLoop1
ret


RectInv:
;;Inverts a rectangle on the buffer
;;IN:
;; D contains x
;; E contains width
;; H contains y
;; L contains height
;;DESTROYS: All, OP1, 1st byte of OP2
call GetRectLine
ld a, 12
sub c
ld e, a
ld d, 0
_rInvLoop1:
push de
ld de, OP1
push bc
ld b, c
_rInvLoop2:
ld a, (de)
xor (hl)
ld (hl), a
inc hl
inc de
djnz _rInvLoop2
pop bc
pop de
add hl, de
djnz _rInvLoop1
ret


GetRectLine:
;;IN:
;; D contains x
;; E contains width
;; H contains y
;; L contains height
;;OUT:
;; HL points to first byte of rectangle in buffer
;; B contains rows
;; C contains columns
;; OP1 [and possibly first byte of OP2] contains mask data for the line
xor a
or l
ret z ;return if height is zero
ld a, d
add a, e
cp d
ret z ;return if the width is zero
cp 96
jr c, _grl_widthOK ;if width is > 90
ld a, 96
_grl_widthOK:
dec a
ld e, a
call RectLineToOP1
;c contains width in bytes
;b contains first column
ld a, h
add a, l
add a, -64
jr nc, _grl_heightOK
neg
add a, l
ld l, a
_grl_heightOK:
ld a, l ;store height in a
ld l, h
ld h, 0
ld d, h
ld e, l
add hl, hl
add hl, de
add hl, hl
add hl, hl
ld e, b
add hl, de
; This next line gets the current buffer address into DE.
; Obviously zBufMode is the buffer flag in zModeFlags, and backBuffer holds the address of my backBuffer.
; Note that it uses $+# format because I use it normally in a #define. I've just written it out here for you to see.
bit zBufMode, (iy+zModeFlags) \ jr z, $+7 \ ld de, plotSScreen \ jr $+5 \ ld de, backBuffer
add hl, de ;hl points to first byte of rect in buffer
ld b, a ;b contains height, c contains width
ret


RectLineToOP1:
;;IN:
;; D contains starting x
;; E contains ending x
;;OUT:
;; C contains length of line
;; B contains starting x byte
;; OP1 [and possibly 1st byte of OP2] contains mask data for the line
;;DESTROYS: All except HL
ld a, e
cp d
ld b, 0
ret z
srl a
srl a
srl a
ld c, d
srl c
srl c
srl c
ld b, c
sub c ;a contains num bytes spanned minus 1
ld c, a
push bc
push hl
ld hl, OP1
;get mask
ld a, d
and 7
ld b, a
ld a, $FF
jr z, _skipmask
_maskloop:
sla a
djnz _maskloop
_skipmask:
ld b, c
ld c, a
xor a
or b
jr z, _lastbyte
ld a, c
_hloop:
ld (hl), a
inc hl
ld a, $FF
djnz _hloop
ld c, a
_lastbyte:
ld a, e
cpl
and 7
ld b, a
ld a, $FF
jr z, _skipmask2
_maskloop2:
add a, a
djnz _maskloop2
_skipmask2:
and c
ld (hl), a
pop hl
pop bc
inc c
ret

Honestly I'm not sure that these routines are even the best way to do it, but I feel they're pretty good. If anyone has better routines that I could swap these for, then I'd love to see them!


EDIT: Thanks to Calc84maniac, the bugs have been fixed and it now works properly!  ;D
« Last Edit: July 03, 2011, 01:18:15 am by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline Jerros

  • LV4 Regular (Next: 200)
  • ****
  • Posts: 137
  • Rating: +9/-0
    • View Profile
Re: Rectangle Drawing Routines
« Reply #1 on: July 02, 2011, 08:35:01 am »
Looks nifty, might make use of it! :3


79% of all statistics are made up randomly.

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Rectangle Drawing Routines
« Reply #2 on: July 02, 2011, 08:57:46 am »
Thanks! Again, I'm not going to say that this is the most efficient method by any means. It's just what I happened to come up with. There's probably some genius out there who could write one much better than this *cough*Runer/ThePenguin/Brandon/calc84*cough*
« Last Edit: July 02, 2011, 08:58:09 am by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline Quigibo

  • The Executioner
  • CoT Emeritus
  • LV11 Super Veteran (Next: 3000)
  • *
  • Posts: 2031
  • Rating: +1075/-24
  • I wish real life had a "Save" and "Load" button...
    • View Profile
Re: Rectangle Drawing Routines
« Reply #3 on: July 02, 2011, 10:27:49 pm »
Well, there's always the Axe rectangle routine (see p_Box in commands.inc from developers folder).  I'm not sure if it's more efficient than yours or not because it depends on what size/speed tradeoff you want and I haven't measured the size and speed of your routine.
« Last Edit: July 02, 2011, 10:28:17 pm by Quigibo »
___Axe_Parser___
Today the calculator, tomorrow the world!

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Rectangle Drawing Routines
« Reply #4 on: July 02, 2011, 11:18:02 pm »
Unfortunately it seems there are a few errors somewhere in my routine...I could have sworn it was working just fine before. If I can get them figured out I'll post that fixed version. THEN maybe it would be worthwhile to see the size/speed of this routine.


EDIT: Fixed, all thanks to Calc84. Now you can check for speed and size if you want...I don't know how to go about doing that, otherwise I would do it myself (I'm curious to know, too!)
« Last Edit: July 03, 2011, 01:19:06 am by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...