-
Notifications
You must be signed in to change notification settings - Fork 0
/
Invaders.asm
382 lines (318 loc) · 7.53 KB
/
Invaders.asm
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
.include "header.inc"
.include "initsnes.asm"
.bank 0 slot 0
.org 0
.section "Vblank"
;--------------------------------------
VBlank:
rti ; F|NisH3D!
;--------------------------------------
.ends
.bank 0 slot 0
.org 0
.section "Main"
;--------------------------------------
Start:
InitSNES
; set up a clone of OAM for direct manipulation,
; then we'll just DMA it over every frame
rep #%00110000 ; 16 bit abxy
ldx #0 ; loop index
lda #$01 ; gonna set every sprite's X position to 1
_offscreen;
sta $1000, x ; mem addr for OAM copy starts at $1000
.rept 4 ; get to the next OAM entry
inx
.endr
cpx #$0200 ; size of low table of OAM
bne _offscreen;
lda #$5555 ; high table value - set all X values to negative
_xmsb:
sta $1000, X
inx
inx
cpx #$0220 ; end of high table of OAM
bne _xmsb
rep #%00010000 ;16 bit xy
sep #%00100000 ;8 bit ab
; load up palettes on DMA 0
ldx #Invaders_16_colorPalettes
lda #:Invaders_16_colorPalettes
ldy #(2 * 256) ; all the colors
stx $4302
sta $4304
sty $4305
lda #%00000000 ; transferring bytes mode
sta $4300
lda #$22; store to $2122 - CGRAM palette data
sta $4301
stz $2121 ; start writing palette data at first color in CGRAM
; load up tile character data on DMA 1
ldx #Invaders_16_colorTiles ; Address
lda #:Invaders_16_colorTiles ; of UntitledData
ldy #(16*16*4) ; length of data
stx $4312 ; write
sta $4314 ; address
sty $4315 ; and length
lda #%00000001 ; set this mode (transferring words)
sta $4310
lda #$18 ; $211[89]: VRAM data write
sta $4311 ; set destination
ldy #$0000 ; Write to VRAM from $0000
sty $2116
; start the DMA processes
lda #%00000011 ; start DMA, channels 0 + 1
sta $420B
lda #%10000000 ; VRAM writing mode
sta $2115
; initialize all the BG1 tiles to the blank tile
ldx #$4000 ; write to vram
stx $2116 ; from $4000
.rept 32
.rept 32
ldx #3
stx $2118
.endr
.endr
; initialize all the BG2 tiles to the blank tile
ldx #$6000 ; BG2 will start here
stx $2116
.rept 32
.rept 32
ldx #3
stx $2118
.endr
.endr
; initialize all the BG3 tiles to the blank tile
ldx #$7000 ; BG3 will start here
stx $2116
.rept 32
.rept 32
ldx #3
stx $2118
.endr
.endr
;set up the screen
lda #%00000001 ; 8x8 tiles, mode 1
sta $2105 ; screen mode register
lda #%01000000 ; data starts from $4000
sta $2107 ; for BG1
lda #%01100000 ; and $6000
sta $2108 ; for BG2
lda #%01110000 ; and $7000
sta $2109 ; for BG 3
stz $210B ; BG1 and BG2 use the $0000 tiles
;stz $210C ; so do BG 3 and 4
lda #%00010011 ; enable bg1&2 AND SPRITES ZOMG
sta $212C ; main screen
lda #0
sta $212D ; enable nothing for sub screen?
;The PPU doesn't process the top line, so we scroll down 1 line.
rep #$20 ; 16bit a
lda #$07FF ; this is -1 for BG1
sep #$20 ; 8bit a
sta $210E ; BG1 vert scroll
xba
sta $210E
rep #$20 ; 16bit a
lda #$FFFF ; this is -1 for BG2
sep #$20 ; 8bit a
sta $2110 ; BG2 vert scroll
xba
sta $2110
; done scrolling
; GAME INIT - initialize game RAM to sane values
rep #%00110000 ; 16 bit A
lda #$0000 ; clear A
sep #%00100000 ; 8 bit A
; put player sprite in middleish
lda #128
sta $0017
; put invaders x / y
lda #40
sta $0015 ; X coord
lda #50
sta $0016 ; Y coord
; put invaders on/off flag in mem
lda #$FF ; gonna put FF in every byte - struct is 2 bytes per row, 10 rows,
; each word high / low byte is a bit array of whether a given
; invader is dead. E.g.:
; #%00000011 11110000 - dead invaders in positions 0,1,2,3.
ldx #$0000 ; loop through the 20 bytes
-
sta $0000,x ; invaders status table stored at beginning of mem
inx
cpx #$14
bne -
; initialize BG 2 VRAM copy to blank
rep #%00110000 ; 16 bit axy
ldx #0
-
;lda #$2003 ; blank tile; priority bit set
lda #$0003 ; blank tile
sta $1300, x
cpx #$0800
inx
bne -
lda #$0000 ; clear a
sep #%00100000 ; 8 bit ab
phx
ldx $1337
plx
; initialize player sprite
lda #200 ; y position in sprite 1
sta $1001
lda #4 ; set tile # for player sprite
sta $1002
lda #%00100000 ; sprite priority
sta $1003
lda #%01010110 ; set 16x16 sprite, no X MSB
sta $1200
; set up sprite table data
lda #0 ; 8x8 and 16x16 sprites, sprite chr data at $0 in VRAM
sta $2102
; all done set up!
lda #%00001111 ; enable screen, set brightness to 15
sta $2100
lda #%10000001 ; enable NMI and joypads
sta $4200
forever:
wai
; start main loop
; implement game here lol
rep #%00110000 ; 16 bit a
lda #$0000 ; clear a
sep #%00100000 ;8 bit ab 16 bit xy
; position player sprite
lda $0017 ; x position in sprite 1
sta $1000
; loop player sprite animation?
lda $1002
lsr
sec
sbc #2
; a is now 0, 1, or 2
clc
adc #1
; loop back to 0 if over 2
cmp #3
bne +
lda #0
+
; a is now incremented and between 0 and 2. Convert it back to real value
clc
adc #2
asl
sta $1002
; set up invaders BG
rep #%00110000 ; 16 bit abxy
ldx #0;
LoopX:
ldy #0;
; calc offset in BG 2 VRAM
txa ; load up x into accumulator
.rept 6 ; multiply row by the 32 tiles on that row * 2 for a spacer row
asl
.endr
sta $0018 ; tmp
LoopY:
; calculate the bitmask for this index
lda #1;
phy ; store col index
LoopBitmask:
cpy #0 ; loop - shift left Y times
beq DoneCalcBitmask
asl
dey
bra LoopBitmask
DoneCalcBitmask
ply ; restore current col index
pha ; store a for use as bitmask cmp later
tya ; load up y into accumulator
adc #2 ; add 3 to y - starting column offset
asl ; multiple by 2
adc $0018 ; add back the x row offset we determined
asl ; multiple by 2 to get from word address to byte address
adc #$1300 ; offset from $1300 - working mem address
sta $0020 ; store off a for use as write address
;sta $2116 ; set VRAM writing address
pla ; a now has our bitmask
and $0000, x ; mask accumulator with the row we're doing in memory
cmp #0
beq InvaderDead ; check if invader alive; 1 alive 0 dead
; Invader alive
phx
ldx $0020; load write address
lda #16
sta $0000, x
lda #3 ; write the spacer bits
sta $0002, x
plx
bra DoneInvader
InvaderDead:
; Invader dead
phx
ldx $0020
lda #3 ; write the spacer bits
sta $0000, x
sta $0002, x
plx
DoneInvader:
iny
cpy #10 ; loop column index while not done
bne LoopY
inx
cpx #10 ; loop row index while not done
bne LoopX
; set the horizontal / vertical scroll for bg 2
rep #%00110000 ; 16 bit a
lda #$0000 ; clear a
sep #%00100000 ;8 bit ab 16 bit xy
; DMA over the OAM table on channel 0
; copy entire OAM - start OAM addr at 0
stz $2102
stz $2103
lda #$00
sta $4300 ; DMA write mode - 1 register, write once
lda #$04
sta $4301 ; DMA destination address 2104 - OAM data write
ldx #$1000 ; source address
stx $4302
lda #$7E ; bank address
sta $4304
ldx #$0220 ; size of OAM table
stx $4305
; copy BG 2 tileset data on channel 1
lda #$80 ; VRAM write mode - write words
sta $2115
ldx #$6000
stx $2116 ; set VRAM write address
lda #$01
sta $4310 ; DMA write mode - word increment
lda #$18
sta $4311 ; DMA destination address 2118 - VRAM write
ldx #$1300 ; source address
stx $4312
lda #$7E ; bank address
sta $4314
ldx #$0800 ; size of BG 2 tileset data
stx $4315
;ldx #$00FF
;stx $4315
; force v-blank?
;lda #%10000000
;sta $2100
lda #%00000001 ; do the DMA
sta $420B
; end forced v-blank?
;lda #%00001111
;sta $2100
; end main loop
jmp forever
;--------------------------------------
.ends
.bank 1 slot 0 ; We'll use bank 1
.org 0
.section "Tiledata"
.include "Invaders_16_color.inc"
.ends