Author Topic: Why won't you worrrrrrk??? [Floodfill routine]  (Read 4723 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
Why won't you worrrrrrk??? [Floodfill routine]
« on: May 11, 2011, 08:14:39 am »
So, I've been working on this floodfill routine that uses zero stack, and I've finally finished it........or so I thought. It seems to not be working. It just freezes the calc. When I go to debug in wabbitemu it seems to be frozen at $0CAF, on the line jp $0B65

Here's my hopefully-not-too-hard-to-read code:
Code: [Select]
#include ti83plus.inc
#define ProgStart $9D95
#define BUFF1 plotSScreen ; Location of drawing buffer 1
#define BUFF2 0 ; Location of drawing buffer 2 (for grayscale implementation)
.org ProgStart-2
.db $BB, $6D

InitTestData:
;; INIT DATA FOR TESTING
ld hl, 1
push hl
ld hl, 20
push hl

PROGRAM_START:
;; L contains the fill color
;; stack:
;; [0]: y-coordinate
;; [1]: x-coordinate


; Get the fill color and save it to (color)
ld a, l
ld (color), a

; Calculate the byte address for the pixel
;   and save it to (addr)
pop hl
ld a, 64
cp l
ret c
ld d, 0
ld e, l
add hl, hl
add hl, de
add hl, hl
add hl, hl
pop de
ld a, 96
cp e
ret c
ld d, 0
srl e
srl e
srl e
ld a, e
ld (xbyte), a ;save the byte column to (xbyte)
add hl, de
ld (addr), hl

; Calculate the bitmask for the pixel
;   and save it to (mask)
and 7
ld b, a
ld a, $80
jr z, ___skiploop
___loop:
rrca
djnz ___loop
___skiploop:
ld (mask), a

; make sure the starting color is not the fill color
ld de, BUFF1
add hl, de
and (hl)
cp 0
jr z, ___zero
ld a, 1
___zero:
ld (icolor), a
ld b, a
ld a, (color)
cp b
ret z ; return if the starting point is the fill color
call TurnByRule
Loop:
call GetBoundsPainted
ld a, b
cp 1
jp nz, _1bound
cp 2
jp nz, _2bounds
cp 3
jp nz, _3bounds
cp 4
jp nz, _4bounds
_0bounds:
call Paint
jp EndLoop
_4bounds:
call Paint
ret
_3bounds:
call GetAddr_Mask
or (hl)
ld (hl), a
;remove the mark, and reset rule and findpassage to defaults
xor a
ld (m_mask),a
ld (bool), a
ld a, $0F
jp EndLoop
_2bounds:
; jesus, this one will be tough...
ld a, (m_mask)
cp 0
jr nz, ___skip_place_mark
ld a, (bool)
and 1
cp 0
jr nz, ___skip_place_mark
ld (findpassage), a
ld a, (mask)
ld (m_mask), a
ld hl, (addr)
ld (m_addr), hl
ld a, (dir)
ld (m_dir), a
___skip_place_mark:
call MoveByRule
ld a, (m_mask)
cp 0
jr nz, ___null_mark
ld b, a
ld a, (mask)
cp b
jp nz, Loop
ld hl, (m_addr)
ld a, h
ld b, l
ld hl, (addr)
cp h
jp nz, Loop
ld a, b
cp l
jp nz, Loop
ld a, (dir)
ld b, a
ld a, (m_dir)
cp b
jr z, ___null_mark
ld (dir), a
ld a, (bool)
xor 1
ld (bool), a
xor a
ld (findpassage), a
___null_mark:
xor a
ld (m_mask), a
ld a, (bool)
and 1
cp 0
call nz, Paint
jp Loop
_1bound:
ld a, (bool)
and 1
jr z, __1bound_else
ld a, 1
ld (findpassage), a
jr EndLoop
__1bound_else:
; get opposite corners...
; if both are open
ld a, (dir)
dec a
push af
___find_bound:
pop af
inc a
push af
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
jr z, ___find_bound
pop af
inc a
inc a
call GetDirOffset
push af
push de
ex de, hl
dec a
call GetDirOffset
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop hl
pop af
jr nz, EndLoop
inc a
call GetDirOffset
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
call GetPixel
ld b, a
ld a, (icolor)
cp b
call z, Paint
EndLoop:
call MoveByRule
jp Loop


Paint:
;; Paints the current pixel the fill color
ld a, (color)
cp 0
jr z, __paint_off
call GetAddr_Mask
or (hl)
ld (hl), a
bcall(_GRBufCpy) ; just for testing purposes.
ret
__paint_off:
call GetAddr_Mask
xor $FF
and (hl)
ld (hl), a
bcall(_GRBufCpy) ; again just for testing purposes.
ret


MoveByRule:
;; Move to next location based on rule
;; OUT:
;; B is 0 if no tile was found to move to. Otherwise, non-zero.
call GetCurPixel
ld b, a
ld a, (icolor)
cp b
jr nz, ___move_dir ; if the current pixel is filled, just move foward
ld a, (dir)
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
jr nz, ___no_move ; if the pixel at dir is filled, don't move
; check the corner between the pixel at dir and the pixel to the side specified by rule
; if the pixel is on, just move forward
; otherwise move to that pixel
ld a, (bool)
and 1
ld c, a
ld a, (dir)
call GetDirOffset
push de
inc a
sub c
sub c
call GetDirOffset
pop hl
push af
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
push de
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop de
pop af
jr nz, ___move_dir
push af
call GetPixelAddr
ld (mask), a
ld a, d
ld (xbyte), a
ld (addr), hl
pop af
ld (dir), a
call TurnByRule
ld b, 1
ret
___move_dir:
ld a, (dir)
call GetDirOffset
call GetPixelAddr
ld (mask), a
ld a, d
ld (xbyte), a
ld (addr), hl
ld a, (bool)
and 1
ld b, a
ld a, (dir)
inc a
sub b
sub b
call remap_dir
ld (dir), a
call TurnByRule
ld b, 1
ret
___no_move:
ld b, 0
ret


TurnByRule:
;; OUT:
;; B is 0 if no tile was found to turn to. Otherwise non-zero.
ld b, 4
___turn_loop:
push bc
ld a, (dir)
call GetPixelInDir
;if pixel is on, dec
ld b, a
ld a, (icolor)
cp b
jr z, __chk_side_turn
ld a, (bool)
and 1
ld b, a
ld a, (dir)
dec a
add a, b
add a, b
call remap_dir
ld (dir), a
pop bc
djnz ___turn_loop
ret
__chk_side_turn:
ld a, (bool)
and 1
ld b, a
ld a, (dir)
inc a
sub b
sub b
call remap_dir
push af
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
pop af
pop bc
ret nz
ld (dir), a
djnz ___turn_loop
ret


remap_dir:
;; Maps the value in A to the range of 0 <= A < 4
cp 4
ret nc
cp 128
jr c, ___add
sub 4
jr remap_dir
___add:
add a, 4
jr remap_dir


GetDirOffset:
;; IN:
;; A contains the direction
call remap_dir
ld b, a
xor a
cp b
jr z, __dir_right
inc a
cp b
jr z, __dir_down
inc a
cp b
jr z, __dir_left
__dir_up:
ld a, b
ld de, $0100
ret
__dir_right:
ld a, b
ld de, $0001
ret
__dir_down:
ld a, b
ld de, $FF00
ret
__dir_left:
ld a, b
ld de, $00FF
ret


GetPixelInDir:
;; IN:
;; A contains the direction
call GetDirOffset
jp GetPixel


GetAddr_Mask:
;; OUT:
;; HL contains the addr of the pixel
;; A contains the mask of the pixel
ld hl, (addr)
ld de, BUFF1
add hl, de
ld a, (mask)
ret


GetBoundsPainted:
;; OUT:
;; B contains the number of painted boundaries
;; bits 0-3 of C contain which bounds are painted (0:right,1:left,2:top,3:bottom)
ld bc, 0
push bc
ld de, $0001
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, $+9
pop bc
inc b
ld a, 1
or c
ld c, a
push bc
ld de, $00FF
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, $+9
pop bc
inc b
ld a, 2
or c
ld c, a
push bc
ld de, $0100
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, $+9
pop bc
inc b
ld a, 4
or c
ld c, a
push bc
ld de, $FF00
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop bc
ret nz
inc b
ld a, 8
or c
ld c, a
ret


GetCurPixel:
;; OUT:
;; A contains the color of the current pixel
ld hl, (addr)
ld de, BUFF1
add hl, de
ld a, (mask)
and (hl)
cp 0
ret z
ld a, 1
ret


GetPixelAddr:
;; IN:
;; D contains y offset
;; E contains x offset
;; OUT:
;; HL contains the addr of the pixel
;; A contains the mask for the pixel, or 0 if the pixel is off screen
;; D contains the xbyte for the pixel
ld hl, (addr)
__x_offset:
ld a, (mask)
ld b, e
ld e, a
ld a, b
cp 0
jr z, __y_offset
cp 1
ld a, (xbyte)
jr z, __shiftRight
rlc e
jr nc, __chk_side
dec a
jr __chk_side
__shiftRight:
rrc e
jr nc, __chk_side
inc a
__chk_side:
cp 12
jr c, __edgeaddr
__y_offset:
push af
ld a, d
cp 0
jr z, __return_addr
cp 1
jr z, __shiftUp
ld bc, -24
add hl, bc
jr __chk_top
__shiftUp:
ld bc, 12
add hl, bc
__chk_top:
push hl
ld bc, -768
add hl, bc
jr c, __edgeaddr
__return_addr:
pop hl
ld a, e
pop de
ret
__edgeaddr:
ld a, 0
ret


GetPixel:
;; IN:
;; D contains y offset
;; E contains x offset
;; OUT:
;; A contains the color of the pixel (1 or 0)
call GetPixelAddr
cp 0
jr z, __edgepxl
__getpxl:
ld de, BUFF1
add hl, de
and (hl)
ret
__edgepxl:
ld a, (color) ; pixel is off-screen, so return (color)
ret


addr: ; Initial address (no buffer address added) of the byte containing the current pixel (Y*12+X/8)
.dw 0
mask: ; Bitmask for the current pixel
.db 0
xbyte: ; The byte column containing the pixel (basically X/8)
.db 0
dir:
.db 0

m_addr:
.dw 0
m_mask:
.db 0 ;0 means no mark
m_xbyte:
.db 0
m_dir:
.db 0

bool: ; bit 0=rule ;;;;;I dunno why but I had this and findpassage as the same thing before. I still haven't taken all the "and 1" lines out from when I was testing rule...
.db 0
findpassage:
.db 0
color: ; The fill color (currently 0 or 1. If I implement grayscale it will be 0-3)
.db 1
icolor:
.db 0 ; The color of the starting fill point

.end

I wouldn't be surprised if it's something reeeeeally stupid. I'm new to ASM, so I'm sure I made multiple mistakes.
« Last Edit: May 11, 2011, 08:24:53 am by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline aeTIos

  • Nonbinary computing specialist
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3915
  • Rating: +184/-32
    • View Profile
    • wank.party
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #1 on: May 11, 2011, 08:40:03 am »
What label name does it freeze?
I'm not a nerd but I pretend:

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #2 on: May 11, 2011, 08:42:16 am »
I haven't been able to figure out what part is causing the issue yet...
There's something about Tuesday...


Pushpins 'n' stuff...


Offline aeTIos

  • Nonbinary computing specialist
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3915
  • Rating: +184/-32
    • View Profile
    • wank.party
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #3 on: May 11, 2011, 08:45:56 am »
You might also ask on Cemetech. They are a lot more focused on asm.
I'm not a nerd but I pretend:

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #4 on: May 11, 2011, 08:48:11 am »
Alright, thanks. I'll try that then, too.
There's something about Tuesday...


Pushpins 'n' stuff...


Offline aeTIos

  • Nonbinary computing specialist
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3915
  • Rating: +184/-32
    • View Profile
    • wank.party
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #5 on: May 11, 2011, 08:49:24 am »
I always ask asm questions on both sites.
I'm not a nerd but I pretend:

Offline calc84maniac

  • eZ80 Guru
  • Coder Of Tomorrow
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2912
  • Rating: +471/-17
    • View Profile
    • TI-Boy CE
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #6 on: May 11, 2011, 11:30:21 am »
Well... that's a really big routine and I can't really keep track of the whole thing. But one thing I did notice is that you didn't put the color value in L before PROGRAM_START.
"Most people ask, 'What does a thing do?' Hackers ask, 'What can I make it do?'" - Pablos Holman

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #7 on: May 11, 2011, 02:45:43 pm »
@aeTIos there are some good ASM coders here too, like calc84, Runer112 and tp77, they just happen to visit the board at different times and less often, so it might take a while to get an answer sometimes. It's good to ask at multiple places, though, just make sure to not drive everything ASM-related away from Omni, though. :P

Offline aeTIos

  • Nonbinary computing specialist
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3915
  • Rating: +184/-32
    • View Profile
    • wank.party
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #8 on: May 11, 2011, 02:46:50 pm »
I wasn't planning to. I just suggested something cuz imo, its a fact that the asm part of omni is not very active.
I'm not a nerd but I pretend:

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #9 on: May 11, 2011, 03:10:01 pm »
Yeah true but that's because most people are sent (or used to be invited) elsewhere to ask their questions :P. Otherwise I think this section is slightly more active than the BASIC one (although not as much as Axe).
« Last Edit: May 11, 2011, 03:10:17 pm by DJ_O »

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #10 on: May 11, 2011, 05:54:27 pm »
Well... that's a really big routine and I can't really keep track of the whole thing. But one thing I did notice is that you didn't put the color value in L before PROGRAM_START.
Yeah, I found that, too, and a few more issues as well. Here's my most recent version...
Code: [Select]
#include ti83plus.inc
#define ProgStart $9D95
#define BUFF1 plotSScreen ; Location of drawing buffer 1
#define BUFF2 0 ; Location of drawing buffer 2 (for grayscale implementation)
.org ProgStart-2
.db $BB, $6D

InitTestData:
;; INIT DATA FOR TESTING
ld hl, 20
push hl
push hl
ld hl, 1

PROGRAM_START:
;; L contains the fill color
;; stack:
;; [0]: y-coordinate
;; [1]: x-coordinate


; Get the fill color and save it to (color)
ld a, l
ld (color), a

; Calculate the byte address for the pixel
;   and save it to (addr)
pop hl
ld a, 64
cp l
pop de
ret c
push de
ld d, 0
ld e, l
add hl, hl
add hl, de
add hl, hl
add hl, hl
pop de
ld a, 96
cp e
ret c
ld d, 0
srl e
srl e
srl e
ld a, e
ld (xbyte), a ;save the byte column to (xbyte)
add hl, de
ld (addr), hl

; Calculate the bitmask for the pixel
;   and save it to (mask)
and 7
ld b, a
ld a, $80
jr z, ___skiploop
___loop:
rrca
djnz ___loop
___skiploop:
ld (mask), a

; make sure the starting color is not the fill color
ld de, BUFF1
add hl, de
and (hl)
cp 0
jr z, ___zero
ld a, 1
___zero:
ld (icolor), a
ld b, a
ld a, (color)
cp b
ret z ; return if the starting point is the fill color
call TurnByRule
call Loop
bcall(_getkey) ;just to pause it...
ret


Loop:
call GetBoundsPainted
ld a, b
cp 1
jp nz, _1bound
cp 2
jp nz, _2bounds
cp 3
jp nz, _3bounds
cp 4
jp nz, _4bounds
_0bounds:
call Paint
jp EndLoop
_4bounds:
call Paint
ret
_3bounds:
call GetAddr_Mask
or (hl)
ld (hl), a
;remove the mark, and reset rule and findpassage to defaults
xor a
ld (m_mask),a
ld (bool), a
ld a, $0F
jp EndLoop
_2bounds:
; jesus, this one will be tough...
ld a, (m_mask)
cp 0
jr nz, ___skip_place_mark
ld a, (bool)
and 1
cp 0
jr nz, ___skip_place_mark
ld (findpassage), a
ld a, (mask)
ld (m_mask), a
ld hl, (addr)
ld (m_addr), hl
ld a, (dir)
ld (m_dir), a
___skip_place_mark:
call MoveByRule
ld a, (m_mask)
cp 0
jr nz, ___null_mark
ld b, a
ld a, (mask)
cp b
jp nz, Loop
ld hl, (m_addr)
ld a, h
ld b, l
ld hl, (addr)
cp h
jp nz, Loop
ld a, b
cp l
jp nz, Loop
ld a, (dir)
ld b, a
ld a, (m_dir)
cp b
jr z, ___null_mark
ld (dir), a
ld a, (bool)
xor 1
ld (bool), a
xor a
ld (findpassage), a
___null_mark:
xor a
ld (m_mask), a
ld a, (bool)
and 1
cp 0
call nz, Paint
jp Loop
_1bound:
ld a, (bool)
and 1
jr z, __1bound_else
ld a, 1
ld (findpassage), a
jr EndLoop
__1bound_else:
; get opposite corners...
; if both are open
ld a, (dir)
ld b, 4
dec a
push af
___find_bound:
pop af
inc a
push af
push bc
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
pop bc
jr nz, ___found
djnz ___find_bound
pop af
xor a
ret
___found:
pop af
inc a
inc a
call GetDirOffset
push af
push de
ex de, hl
dec a
call GetDirOffset
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop hl
pop af
jr nz, EndLoop
inc a
call GetDirOffset
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
call GetPixel
ld b, a
ld a, (icolor)
cp b
call z, Paint
EndLoop:
call MoveByRule
jp Loop


Paint:
;; Paints the current pixel the fill color
ld a, (color)
cp 0
;jr z, __paint_off
call GetAddr_Mask
or (hl)
ld (hl), a
bcall(_GRBufCpy) ; just for testing purposes.
ret
__paint_off:
call GetAddr_Mask
xor $FF
and (hl)
ld (hl), a
bcall(_GRBufCpy) ; again just for testing purposes.
ret


MoveByRule:
;; Move to next location based on rule
;; OUT:
;; B is 0 if no tile was found to move to. Otherwise, non-zero.
call GetCurPixel
ld b, a
ld a, (icolor)
cp b
jr nz, ___move_dir ; if the current pixel is filled, just move foward
ld a, (dir)
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
jr nz, ___no_move ; if the pixel at dir is filled, don't move
; check the corner between the pixel at dir and the pixel to the side specified by rule
; if the pixel is on, just move forward
; otherwise move to that pixel
ld a, (bool)
and 1
ld c, a
ld a, (dir)
call GetDirOffset
push de
inc a
sub c
sub c
call GetDirOffset
pop hl
push af
ld a, h
or d
ld d, a
ld a, l
or e
ld e, a
push de
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop de
pop af
jr nz, ___move_dir
push af
call GetPixelAddr
ld (mask), a
ld a, d
ld (xbyte), a
ld (addr), hl
pop af
ld (dir), a
call TurnByRule
ld b, 1
ret
___move_dir:
ld a, (dir)
call GetDirOffset
call GetPixelAddr
ld (mask), a
ld a, d
ld (xbyte), a
ld (addr), hl
ld a, (bool)
and 1
ld b, a
ld a, (dir)
inc a
sub b
sub b
call remap_dir
ld (dir), a
call TurnByRule
ld b, 1
ret
___no_move:
ld b, 0
ret


TurnByRule:
;; OUT:
;; B is 0 if no tile was found to turn to. Otherwise non-zero.
ld b, 4
___turn_loop:
push bc
ld a, (dir)
call GetPixelInDir
;if pixel is on, dec
ld b, a
ld a, (icolor)
cp b
jr z, __chk_side_turn
ld a, (bool)
and 1
ld b, a
ld a, (dir)
dec a
add a, b
add a, b
call remap_dir
ld (dir), a
pop bc
djnz ___turn_loop
ret
__chk_side_turn:
;jump from push bc
ld a, (bool)
and 1
ld b, a
ld a, (dir)
inc a
sub b
sub b
call remap_dir
push af
call GetPixelInDir
ld b, a
ld a, (icolor)
cp b
pop af
pop bc
ret nz
ld (dir), a
djnz ___turn_loop
ret


remap_dir:
;; Maps the value in A to the range of 0 <= A < 4
cp 4
ret nc
cp 128
jr c, ___add
sub 4
jr remap_dir
___add:
add a, 4
jr remap_dir


GetDirOffset:
;; IN:
;; A contains the direction
call remap_dir
ld b, a
xor a
cp b
jr z, __dir_right
inc a
cp b
jr z, __dir_down
inc a
cp b
jr z, __dir_left
__dir_up:
ld a, b
ld de, $0100
ret
__dir_right:
ld a, b
ld de, $0001
ret
__dir_down:
ld a, b
ld de, $FF00
ret
__dir_left:
ld a, b
ld de, $00FF
ret


GetPixelInDir:
;; IN:
;; A contains the direction
call GetDirOffset
jp GetPixel


GetAddr_Mask:
;; OUT:
;; HL contains the addr of the pixel
;; A contains the mask of the pixel
ld hl, (addr)
ld de, BUFF1
add hl, de
ld a, (mask)
ret


GetBoundsPainted:
;; OUT:
;; B contains the number of painted boundaries
;; bits 0-3 of C contain which bounds are painted (0:right,1:left,2:top,3:bottom)
ld bc, 0
push bc
ld de, $0001
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, ___skip1
pop bc
inc b
ld a, 1
or c
ld c, a
push bc
___skip1:
ld de, $00FF
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, ___skip2
pop bc
inc b
ld a, 2
or c
ld c, a
push bc
___skip2:
ld de, $0100
call GetPixel
ld b, a
ld a, (icolor)
cp b
jr nz, ___skip3
pop bc
inc b
ld a, 4
or c
ld c, a
push bc
___skip3:
ld de, $FF00
call GetPixel
ld b, a
ld a, (icolor)
cp b
pop bc
ret nz
inc b
ld a, 8
or c
ld c, a
ret


GetCurPixel:
;; OUT:
;; A contains the color of the current pixel
ld hl, (addr)
ld de, BUFF1
add hl, de
ld a, (mask)
and (hl)
cp 0
ret z
ld a, 1
ret


GetPixelAddr:
;; IN:
;; D contains y offset
;; E contains x offset
;; OUT:
;; HL contains the addr of the pixel
;; A contains the mask for the pixel, or 0 if the pixel is off screen
;; D contains the xbyte for the pixel
ld hl, (addr)
__x_offset:
ld a, (mask)
ld b, e
ld e, a
ld a, b
cp 0
jr z, __y_offset
cp 1
ld a, (xbyte)
jr z, __shiftRight
rlc e
jr nc, __chk_side
dec a
jr __chk_side
__shiftRight:
rrc e
jr nc, __chk_side
inc a
__chk_side:
cp 12
jr c, __edgeaddr
__y_offset:
push af
ld a, d
cp 0
jr z, __return_addr
cp 1
jr z, __shiftUp
ld bc, -24
add hl, bc
jr __chk_top
__shiftUp:
ld bc, 12
add hl, bc
__chk_top:
push hl
ld bc, -768
add hl, bc
pop hl
pop af
jr c, __edgeaddr
__return_addr:
push af
ld a, e
pop de
ret
__edgeaddr:
ld a, 0
ret


GetPixel:
;; IN:
;; D contains y offset
;; E contains x offset
;; OUT:
;; A contains the color of the pixel (1 or 0)
call GetPixelAddr
cp 0
jr z, __edgepxl
__getpxl:
ld de, BUFF1
add hl, de
and (hl)
ret
__edgepxl:
ld a, (color) ; pixel is off-screen, so return (color)
ret


addr: ; Initial address (no buffer address added) of the byte containing the current pixel (Y*12+X/8)
.dw 0
mask: ; Bitmask for the current pixel
.db 0
xbyte: ; The byte column containing the pixel (basically X/8)
.db 0
dir:
.db 0

m_addr:
.dw 0
m_mask:
.db 0 ;0 means no mark
m_xbyte:
.db 0
m_dir:
.db 0

bool: ; bit 0=rule ;;;;;I dunno why but I had this and findpassage as the same thing before. I still haven't taken all the "and 1" lines out from when I was testing rule...
.db 0
findpassage:
.db 0
color: ; The fill color (currently 0 or 1. If I implement grayscale it will be 0-3)
.db 1
icolor:
.db 0 ; The color of the starting fill point

.end

At KermM's suggestion I indented pushes and pops. That helped me catch multiple issues. But it's still not working right. For some reason the Paint routine is never even called. I'm not sure why.


Edit: Here's my pseudocode for the routine. It may help to understand it better:
Code: [Select]
This algorithm:
http://en.wikipedia.org/wiki/Flood_fill#Fixed_memory_method_.28right-hand_fill_method.29

RULE = right
MARK = null
MARKDIR = null
FINDPASSAGE = false
-----

if 4 bounds painted
        paint cur
        stop
else if 3 bounds painted
        MARK = null
        FINDPASSAGE = false
        RULE = right
        paint cur
        move to open bound
         
//#######################     
else if 2 bounds painted
        if MARK == null && RULE == right
                MARK = cur
                MARKDIR = dir
                FINDPASSAGE = false
        move based on RULE               //after moving
                                        //set "dir" to the next direction
                                        //according to RULE (right hand rule or left hand rule)
        if cur == MARK
                if dir == MARKDIR
                        MARK = null
                else
                        RULE = left
                        dir = MARKDIR
                        MARK = null
                        FINDPASSAGE = false
                         
        if MARK == null && RULE == right
                paint cur
//######################
                 
else if 1 bound painted
        if RULE == left  //then we''re in a loop, and this triggers the second stage
                FINDPASSAGE = true
        else
                if both opposite corners are open && MARK == null
                        paint cur
        move base on RULE
else if 0 bounds painted
        if RULE == left
                FINDPASSAGE = true
        paint cur
        move anywhere :P
         
         
        //_0_            how do you follow the right hand rule? Which is next?
        //_#_
        //___
//first way
        //_#0        //If the current pixel is painted before moving, move here
        //_#_
        //___
//second way
        //___        //but if the pixel is NOT painted before moving, move around to the
        //_#0        //next edge because going to the corner would make it now have
        //___        //no borders.
« Last Edit: May 11, 2011, 06:07:10 pm by ZippyDee »
There's something about Tuesday...


Pushpins 'n' stuff...


Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Why won't you worrrrrrk??? [Floodfill routine]
« Reply #11 on: May 11, 2011, 06:09:12 pm »
I'm lost. How exactly are you trying to flood fill? Like, what is your general plan of action? Because at the moment, I have no idea what is going on.
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline ZippyDee

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 729
  • Rating: +83/-8
  • Why not zoidberg?
    • View Profile
There's something about Tuesday...


Pushpins 'n' stuff...