;;; Subroutine: drunkwalk ;;; Walk the point around randomly until it either is ;;; adjacent to a set pixel or goes out of bounds. ;;; Return with Z=0 if out of bounds, Z=1 if it hit a pixel. ;;; This is the innermost loop, so it should be as optimized as ;;; possible. ; Y and X are backwards: Y holds the X coordinate, and X holds the Y coordinate. ; Has to be, because there's no (zpind),x addressing mode. drunkwalk: oob: ldy RANDOM ; spawn a new particle lda (spawn_x),y sta cursor_x lda (spawn_y),y sta cursor_y tax ldy cursor_x lda lineaddrs_l,x ; 5 sta pixptr ; 3 lda lineaddrs_h,x ; 5 sta pixptr+1 ; 3 move_pixel: bit RANDOM ; 4 ; use top 2 bits (probably more random, definitely faster) bmi lr ; 2/3 bvc down ; 2/3 up: dex ; 2 ; N=1 V=1 up selfmod_ymin = * + 1 cpx #0 ; 2 beq oob ; 2 stx cursor_y jmp check_lru down: inx ; 2 ; N=1 V=0 down selfmod_ymax = * + 1 cpx #0 ; 2 beq oob ; 2 stx cursor_y jmp check_lrd lr: bvc right ; 2/3 left: dey ; 3 ; N=0 V=1 left selfmod_xmin = * + 1 cpy #0 ; 2 beq oob ; 2 sty cursor_x ; check left neighbor (we just vacated the right one) dey lda (pixptr),y bne stick iny jmp check_ud ; 3 ; still have to check Y (up/down) neighbors. right: iny ; 3 ; N=0 V=0 right selfmod_xmax = * + 1 cpy #0 ; 2 beq oob ; 2 sty cursor_x ; check right neighbor (we just vacated the left one) iny lda (pixptr),y bne stick dey ; fall through to check_ud check_ud: ; check up neighbor lda lineaddrs_l-1,x sta pixptr2 lda lineaddrs_h-1,x sta pixptr2+1 lda (pixptr2),y bne stick ; check down neighbor lda lineaddrs_l+1,x sta pixptr2 lda lineaddrs_h+1,x sta pixptr2+1 lda (pixptr2),y bne stick jmp move_pixel check_lru: lda lineaddrs_l,x ; 5 sta pixptr ; 3 lda lineaddrs_h,x ; 5 sta pixptr+1 ; 3 ; check left neighbor dey lda (pixptr),y bne stick iny ; check right neighbor iny lda (pixptr),y bne stick dey ; check up neighbor lda lineaddrs_l-1,x sta pixptr2 lda lineaddrs_h-1,x sta pixptr2+1 lda (pixptr2),y bne stick jmp move_pixel check_lrd: lda lineaddrs_l,x ; 5 sta pixptr ; 3 lda lineaddrs_h,x ; 5 sta pixptr+1 ; 3 ; check left neighbor dey lda (pixptr),y bne stick iny ; check right neighbor iny lda (pixptr),y bne stick dey ; check down neighbor lda lineaddrs_l+1,x sta pixptr2 lda lineaddrs_h+1,x sta pixptr2+1 lda (pixptr2),y bne stick jmp move_pixel stick: ; pixel stuck next to an existing pixel, draw it and return. ldx cursor_y lda lineaddrs_l,x sta pixptr lda lineaddrs_h,x sta pixptr+1 ldy cursor_x lda #1 sta (pixptr),y rts