aboutsummaryrefslogtreecommitdiff
path: root/drunkwalk.s
blob: 6156e4a591a355f343aaea5512eb8a6cf848e52a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
;;; 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.
oob:
 rts

drunkwalk:
 ldy part_x           ; 3
 ldx part_y           ; 3

 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 part_y
 jmp check_lru
down:
 inx            ; 2 ; N=1 V=0 down
selfmod_ymax = * + 1
 cpx #0         ; 2
 beq oob        ; 2
 stx part_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 part_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 part_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:
 rts