http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / hacks / images / m6502 / breakout.asm
1 ; Brick Out by Blake Ramsdell <blaker@gmail.com> http://www.blakeramsdell.com
2
3 ; A poor attempt at brick out with no player involved. Maybe someday I'll
4 ; let you play it, or you can view this as an exercise for the reader to put
5 ; in a paddle that is user-controlled.
6
7 ; I guess this is Copyright (C) 2007 Blake Ramsdell, and you have a license to
8 ; do whatever you want with it, just tell me what you did and give me a
9 ; mention. If you want to sell it, and you make a billion dollars, then good
10 ; for you. You might at least throw a party and invite me.
11
12 ; The gist of it is pretty simple -- you have a ball, and the ball has an X
13 ; and a Y velocity. When it hits something, it bounces off of it. If the thing
14 ; that it hits is not a wall, then it erases it. Pretty dead-simple behavior.
15
16 ; I don't like the vertical movement -- there's a shortcut in here somewhere
17 ; to make it less computationally expensive I think. Right now it just does a
18 ; two byte add and subtract of $20.
19
20 ; The ball motion is also a bit weird looking. I don't know if this is an
21 ; artifact of the simulation environment combined with a normal tearing
22 ; artifact related to refresh or what.
23
24 ; Blake Ramsdell, May 2007
25
26 init:
27  lda #$fe
28  sta $2         ; X velocity (0 = fast, ff = slow)
29                 ; (low bit is direction, 0 = down or right, 1 = up or left)
30  lda #$ee
31  sta $3         ; Y velocity
32
33 drawbox:
34  lda #0         ; Use $0-$1 as a screen address for drawing the field
35  sta $0
36  lda #2
37  sta $1
38
39  ldx #$20       ; Loop $20 times
40 boxloop:
41  lda #2         ; Line color (red)
42  sta $1ff,x     ; Top line
43  sta $5df,x     ; Bottom line
44  ldy #0
45  sta ($0),y     ; Left line
46  ldy #$1f
47  sta ($0),y     ; Right line
48
49  cpx #$1        ; If we're just before the bottom line...
50  beq noblocks   ; Don't draw any blocks there
51
52
53  lda #3         ; First block for this row, Cyan in color
54  ldy #$17       ; It's at X position $17
55  sta ($0),y     ; Draw it
56
57  lda #4         ; Second block for this row, Purple in color
58  iny            ; It's at the next X position
59  sta ($0),y     ; Draw it
60
61  lda #5         ; Third block for this row, Green in color
62  iny            ; It's at the next X position
63  sta ($0),y     ; Draw it
64
65  lda #6         ; Fourth block for this row, Blue in color
66  iny            ; It's at the next X position
67  sta ($0),y     ; Draw it
68
69
70 noblocks:
71  clc            ; Get ready to increment the row, clear the carry for add
72  lda $0         ; Get the low byte
73  adc #$20       ; Add $20 to it for the next row
74  sta $0         ; Put it back
75  lda $1         ; Get the high byte
76  adc #0         ; Factor in the carry
77  sta $1         ; Put it back
78
79  dex            ; Decrement the loop counter
80  bne boxloop    ; Do it again unless it's zero
81
82  ldx $2         ; Load the X velocity
83  ldy $3         ; Load the Y velocity
84
85  lda #$44       ; Pick a start point
86  sta $0         ; Ball position low
87  lda #$02
88  sta $1         ; Ball position high
89
90 drawball:
91  txa            ; Preserve X
92  pha
93  lda #1         ; Ball color (white)
94  ldx #0         ; Clear X for indirect addressing for writing to screen
95  sta ($0,x)     ; Draw the ball
96  pla            ; Restore X
97  tax
98
99 decloop:
100  dex            ; Decrement the X velocity
101  beq updatexpos ; If it's zero, time to adjust X
102  dey            ; Decrement the Y velocity
103  bne decloop    ; If it's not zero, loop, otherwise fall through to adjust Y
104
105 updateypos:
106  txa            ; Preserve X
107  pha
108  jsr clearball  ; Put background over the current ball position
109 updateyposnoclear:
110  lda $3         ; Get the Y velocity
111  and #1         ; See if it's down
112  bne moveup     ; If not, then it's up, otherwise fall through to down
113
114 movedown:
115  clc            ; Prepare for moving to the next Y line and doing the add
116  lda $0         ; Low byte of the current ball position
117  adc #$20       ; Next row
118  sta $0         ; Put it back
119  bcc ycollision ; If no carry, go on to check for collision
120  inc $1         ; Had a carry, fix the high byte of the address
121  bne ycollision ; Z flag is always clear ($1 will never be zero)
122
123 moveup:
124  sec            ; Prepare for moving to the previous Y line and subtracting
125  lda $0         ; Low byte of the current ball position
126  sbc #$20       ; Previous row
127  sta $0         ; Put it back
128  lda $1         ; High byte
129  sbc #$0        ; Factor out the carry
130  sta $1         ; Put it back
131
132 ycollision:
133  ldx #0         ; Prepare for indirect read
134  lda ($0,x)     ; Get the current pixel at the new ball position
135  bne ycollided  ; If it's not zero (the background color) then we hit
136  ldy $3         ; Otherwise, load up the current Y velocity
137  pla            ; Restore the X velocity
138  tax
139  jmp drawball   ; Back to the top
140
141 ycollided:
142  cmp #$2        ; Border color?
143  beq ycollided2 ; If so, then we just bounce, don't eat a brick
144
145                 ; Erase brick
146  lda #0         ; Background color (black)
147  sta ($0,x)     ; Erase it
148
149 ycollided2:
150  lda #1         ; Get ready to change direction
151  eor $3         ; Flip the low bit on the Y velocity (change direction)
152  sta $3         ; Put it back
153  jmp updateyposnoclear  ; Go back to make sure we didn't hit anything else
154
155 updatexpos:
156  jsr clearball  ; Put background over the current ball position
157 updatexposnoclear:
158  lda $2         ; Get the current X velocity
159  and #1         ; See if it's right by testing the low bit
160  bne moveleft   ; If not, move left
161
162 moveright:
163  inc $0         ; Move right
164  bne xcollision ; Z flag is always clear
165
166 moveleft:
167  dec $0         ; Move left
168
169 xcollision:
170  ldx #0         ; Prepare for indirect read
171  lda ($0,x)     ; Get the current pixel at the new ball position
172  bne xcollided  ; If it's not zero (the background color) then we hit
173  ldx $2         ; Otherwise, load up the current X velocity
174  jmp drawball   ; Back to the top
175
176 xcollided:
177  cmp #$2        ; Border color?
178  beq xcollided2 ; If so, then we just bounce, don't eat a brick
179
180                 ; Erase brick
181  lda #0         ; Background color (black)
182  sta ($0,x)     ; Erase it
183
184 xcollided2:
185  lda #1         ; Get ready to change direction
186  eor $2         ; Flip the low bit on the X velocity (change direction)
187  sta $2         ; Put it back
188  jmp updatexposnoclear  ; Go back to make sure we didn't hit anything else
189
190 clearball:
191  lda #0         ; Background color (black)
192  tax            ; Clear X for indirect
193  sta ($0,x)     ; Black out the ball
194  rts            ; Return to caller
195