0 Members and 2 Guests are viewing this topic.
#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, $6DInitTestData: ;; 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 TurnByRuleLoop: 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, PaintEndLoop: 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. retMoveByRule: ;; 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 GetPixelGetAddr_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) retGetBoundsPainted: ;; 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 retGetPixelAddr: ;; 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) retaddr: ; Initial address (no buffer address added) of the byte containing the current pixel (Y*12+X/8) .dw 0mask: ; Bitmask for the current pixel .db 0xbyte: ; The byte column containing the pixel (basically X/8) .db 0dir: .db 0m_addr: .dw 0m_mask: .db 0 ;0 means no markm_xbyte: .db 0m_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 0findpassage: .db 0color: ; The fill color (currently 0 or 1. If I implement grayscale it will be 0-3) .db 1icolor: .db 0 ; The color of the starting fill point .end
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.
#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, $6DInitTestData: ;; 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, PaintEndLoop: 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. retMoveByRule: ;; 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 GetPixelGetAddr_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) retGetBoundsPainted: ;; 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 retGetPixelAddr: ;; 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) retaddr: ; Initial address (no buffer address added) of the byte containing the current pixel (Y*12+X/8) .dw 0mask: ; Bitmask for the current pixel .db 0xbyte: ; The byte column containing the pixel (basically X/8) .db 0dir: .db 0m_addr: .dw 0m_mask: .db 0 ;0 means no markm_xbyte: .db 0m_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 0findpassage: .db 0color: ; The fill color (currently 0 or 1. If I implement grayscale it will be 0-3) .db 1icolor: .db 0 ; The color of the starting fill point .end
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.