aboutsummaryrefslogtreecommitdiff
path: root/drunkwalk.s
blob: ca8047599d14c8a0be0cc2f2f89c85aafc80544c (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
;;; 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

 ; do we need this now?
 lda lineaddrs_l,x    ; 5
 sta pixptr           ; 3
 lda lineaddrs_h,x    ; 5
 sta pixptr+1         ; 3

 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 drunkwalk

check_lru:
 ; 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 drunkwalk

check_lrd:
 ; 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 drunkwalk

stick:
 rts