summaryrefslogtreecommitdiffstats
path: root/hacks/images/m6502/breakout.asm
blob: a0fa694de5fe3f94cd81664bbafb3aef11949782 (plain) (blame)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
; Brick Out by Blake Ramsdell <blaker@gmail.com> http://www.blakeramsdell.com

; A poor attempt at brick out with no player involved. Maybe someday I'll
; let you play it, or you can view this as an exercise for the reader to put
; in a paddle that is user-controlled.

; I guess this is Copyright (C) 2007 Blake Ramsdell, and you have a license to
; do whatever you want with it, just tell me what you did and give me a
; mention. If you want to sell it, and you make a billion dollars, then good
; for you. You might at least throw a party and invite me.

; The gist of it is pretty simple -- you have a ball, and the ball has an X
; and a Y velocity. When it hits something, it bounces off of it. If the thing
; that it hits is not a wall, then it erases it. Pretty dead-simple behavior.

; I don't like the vertical movement -- there's a shortcut in here somewhere
; to make it less computationally expensive I think. Right now it just does a
; two byte add and subtract of $20.

; The ball motion is also a bit weird looking. I don't know if this is an
; artifact of the simulation environment combined with a normal tearing
; artifact related to refresh or what.

; Blake Ramsdell, May 2007

init:
 lda #$fe
 sta $2         ; X velocity (0 = fast, ff = slow)
                ; (low bit is direction, 0 = down or right, 1 = up or left)
 lda #$ee
 sta $3         ; Y velocity

drawbox:
 lda #0         ; Use $0-$1 as a screen address for drawing the field
 sta $0
 lda #2
 sta $1

 ldx #$20       ; Loop $20 times
boxloop:
 lda #2         ; Line color (red)
 sta $1ff,x     ; Top line
 sta $5df,x     ; Bottom line
 ldy #0
 sta ($0),y     ; Left line
 ldy #$1f
 sta ($0),y     ; Right line

 cpx #$1        ; If we're just before the bottom line...
 beq noblocks   ; Don't draw any blocks there


 lda #3         ; First block for this row, Cyan in color
 ldy #$17       ; It's at X position $17
 sta ($0),y     ; Draw it

 lda #4         ; Second block for this row, Purple in color
 iny            ; It's at the next X position
 sta ($0),y     ; Draw it

 lda #5         ; Third block for this row, Green in color
 iny            ; It's at the next X position
 sta ($0),y     ; Draw it

 lda #6         ; Fourth block for this row, Blue in color
 iny            ; It's at the next X position
 sta ($0),y     ; Draw it


noblocks:
 clc            ; Get ready to increment the row, clear the carry for add
 lda $0         ; Get the low byte
 adc #$20       ; Add $20 to it for the next row
 sta $0         ; Put it back
 lda $1         ; Get the high byte
 adc #0         ; Factor in the carry
 sta $1         ; Put it back

 dex            ; Decrement the loop counter
 bne boxloop    ; Do it again unless it's zero

 ldx $2         ; Load the X velocity
 ldy $3         ; Load the Y velocity

 lda #$44       ; Pick a start point
 sta $0         ; Ball position low
 lda #$02
 sta $1         ; Ball position high

drawball:
 txa            ; Preserve X
 pha
 lda #1         ; Ball color (white)
 ldx #0         ; Clear X for indirect addressing for writing to screen
 sta ($0,x)     ; Draw the ball
 pla            ; Restore X
 tax

decloop:
 dex            ; Decrement the X velocity
 beq updatexpos ; If it's zero, time to adjust X
 dey            ; Decrement the Y velocity
 bne decloop    ; If it's not zero, loop, otherwise fall through to adjust Y

updateypos:
 txa            ; Preserve X
 pha
 jsr clearball  ; Put background over the current ball position
updateyposnoclear:
 lda $3         ; Get the Y velocity
 and #1         ; See if it's down
 bne moveup     ; If not, then it's up, otherwise fall through to down

movedown:
 clc            ; Prepare for moving to the next Y line and doing the add
 lda $0         ; Low byte of the current ball position
 adc #$20       ; Next row
 sta $0         ; Put it back
 bcc ycollision ; If no carry, go on to check for collision
 inc $1         ; Had a carry, fix the high byte of the address
 bne ycollision ; Z flag is always clear ($1 will never be zero)

moveup:
 sec            ; Prepare for moving to the previous Y line and subtracting
 lda $0         ; Low byte of the current ball position
 sbc #$20       ; Previous row
 sta $0         ; Put it back
 lda $1         ; High byte
 sbc #$0        ; Factor out the carry
 sta $1         ; Put it back

ycollision:
 ldx #0         ; Prepare for indirect read
 lda ($0,x)     ; Get the current pixel at the new ball position
 bne ycollided  ; If it's not zero (the background color) then we hit
 ldy $3         ; Otherwise, load up the current Y velocity
 pla            ; Restore the X velocity
 tax
 jmp drawball   ; Back to the top

ycollided:
 cmp #$2        ; Border color?
 beq ycollided2 ; If so, then we just bounce, don't eat a brick

                ; Erase brick
 lda #0         ; Background color (black)
 sta ($0,x)     ; Erase it

ycollided2:
 lda #1         ; Get ready to change direction
 eor $3         ; Flip the low bit on the Y velocity (change direction)
 sta $3         ; Put it back
 jmp updateyposnoclear  ; Go back to make sure we didn't hit anything else

updatexpos:
 jsr clearball  ; Put background over the current ball position
updatexposnoclear:
 lda $2         ; Get the current X velocity
 and #1         ; See if it's right by testing the low bit
 bne moveleft   ; If not, move left

moveright:
 inc $0         ; Move right
 bne xcollision ; Z flag is always clear

moveleft:
 dec $0         ; Move left

xcollision:
 ldx #0         ; Prepare for indirect read
 lda ($0,x)     ; Get the current pixel at the new ball position
 bne xcollided  ; If it's not zero (the background color) then we hit
 ldx $2         ; Otherwise, load up the current X velocity
 jmp drawball   ; Back to the top

xcollided:
 cmp #$2        ; Border color?
 beq xcollided2 ; If so, then we just bounce, don't eat a brick

                ; Erase brick
 lda #0         ; Background color (black)
 sta ($0,x)     ; Erase it

xcollided2:
 lda #1         ; Get ready to change direction
 eor $2         ; Flip the low bit on the X velocity (change direction)
 sta $2         ; Put it back
 jmp updatexposnoclear  ; Go back to make sure we didn't hit anything else

clearball:
 lda #0         ; Background color (black)
 tax            ; Clear X for indirect
 sta ($0,x)     ; Black out the ball
 rts            ; Return to caller