-
Notifications
You must be signed in to change notification settings - Fork 0
/
9 - player and playfield.dasm
381 lines (336 loc) · 7.32 KB
/
9 - player and playfield.dasm
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
; Player and Playfield
;
; This merges our two examples together: player with multiple frames and control, and colored playfied
; But we've got problems. The rendering is messed up. The playfied seems to warp around the player.
; Also, according to the Stella debugger we're outputting extra scanlines here and there. And it seems
; like the extra scan lines and the warping are connected. But, I don't actually know that. I've been chasing it
; for an hour or more and I'm really not sure. It kinda seems like the warping happens no matter how many
; expensive ops I try to remove. Our code has also become generally unweildy. It's hard to know what's going on
; I need to find a way to reorganize. I'm looking at some stuff online (https://www.randomterrain.com/atari-2600-lets-make-a-game-spiceware-00.html)
; so hopefully I can get some inspiration
processor 6502
include vcs.h
include macro.h
org $F000
;Number of scanlines on the screen
ScanlineCount = $80
;Index of current scan line
ScanlineCounter = $81
;How long we VBLank for
VBlankTimer = $82
;How long we overscan for
OverscanTimer = #32
;Y Index in the playfied data tables
PlayFieldYIndex = $84
;How many lines we should debounce playfield rendering
PlayFieldLineSkip = $85
;Where we store input magic numbers
InputUp = $86
InputDown = $87
InputLeft = $88
InputRight = $89
;Magic number holder for motion codes
HorizMotionLeft = $8A
HorizMotionRight = $8D
;Y Position of player
PlayerSpriteY = $8B
;Used for rendering slices of sprites
SpriteSliceToDraw = $8C
;Buffer for player sprite
PlayerSpriteBuffer = $8E
;Playfield buffers
PlayFieldLineBuffer0 = $8F
PlayFieldLineBuffer1 = $90
PlayFieldLineBuffer2 = $91
PlayFieldColorBuffer = $92
;16 bit pointer for player sprite
PlayerSpritePointer = $93
.word;
PlayerSpritePointerReserved = $94
Start
;From macro.h gets memory and other stuff initialized
CLEAN_START
;Set background color
lda #$04
sta COLUBK
;Mirror the PF
lda #%1111
sta CTRLPF
;190 scanlines
lda #190
sta ScanlineCount
sta ScanlineCounter
;2752 CPU cycles for VBlank
lda #43
sta VBlankTimer
;2240 CPU cycles for Overscan
lda #35
sta OverscanTimer
lda #0
sta PlayFieldYIndex
lda #0
sta PlayFieldLineSkip
lda #75
sta PlayerSpriteY
lda #0
sta SpriteSliceToDraw
lda #%00010000
sta InputUp
lda #%00100000
sta InputDown
lda #%01000000
sta InputLeft
lda #%10000000
sta InputRight
lda #$10
sta HorizMotionLeft
lda #$F0
sta HorizMotionRight
SET_POINTER PlayerSpritePointer, SpriteFaceRight
;Tell the TV we're starting a new frame
VSync
;Moved to using DASM's macro
VERTICAL_SYNC
;We have 37 scanlines of VBlank time before we start drawing scan lines
;This is a great place to do logic. The tightest code would cycle count here
;but we use a timer instead. Not as tight, but still good.
VBlankStart
lda #%0010
sta VBLANK
lda VBlankTimer
sta TIM64T
VBlankLogic
lda ScanlineCount
sta ScanlineCounter
ldx #0
stx PlayFieldYIndex
stx SpriteSliceToDraw
CheckMoveUp
lda InputUp
bit SWCHA
bne CheckMoveDown
inc PlayerSpriteY
SET_POINTER PlayerSpritePointer, SpriteFaceUp
CheckMoveDown
lda InputDown
bit SWCHA
bne CheckMoveLeft
dec PlayerSpriteY
SET_POINTER PlayerSpritePointer, SpriteFaceDown
CheckMoveLeft
;We'll use register X for our horizontal movement speed
;Default horizontal speed is 0
ldx #0
lda InputLeft
bit SWCHA
bne CheckMoveRight
ldx HorizMotionLeft
lda #$0B
sta REFP0
SET_POINTER PlayerSpritePointer, SpriteFaceRight
CheckMoveRight
lda InputRight
bit SWCHA
bne SetHorizontalMovement
ldx HorizMotionRight
lda #0
sta REFP0
SET_POINTER PlayerSpritePointer, SpriteFaceRight
SetHorizontalMovement
stx HMP0
VBlankEnd
lda INTIM
bne VBlankEnd
lda #0
sta VBLANK
sta WSYNC
sta HMOVE
;There's a little bit of time before each scanline where you can do some logic
;Only around 10-15 CPU cycles or so, but still something
HBlank
;Do pre-line stuff here
sta WSYNC
DrawAndClearPlayerBuffer
;Draw the player buffer to the screen and then clear it out
;This is our only draw call, so this is the only thing that would
;add any cycle overhead to the currently rendering line
lda PlayerSpriteBuffer
sta GRP0
lda #0
sta PlayerSpriteBuffer
CheckPlayerOnScanline
;See if this is the line we should draw at
ldx ScanlineCounter
cpx PlayerSpriteY
;If it isn't the line we should start drawing the player sprite at move on
bne BufferPlayerSprite
;If it is the line we should start drawing at set the lines of sprite to draw to 8
lda #8
sta SpriteSliceToDraw
BufferPlayerSprite
;Load the sprite line count
ldy SpriteSliceToDraw
cpy #0
;If the line count is 0 there's nothing to draw so skip drawing
beq SkipPlayerSprite
;Load the sprite line and buffer it
lda (PlayerSpritePointer),y
sta PlayerSpriteBuffer
;Decrement and store the sprite draw line
dey
sty SpriteSliceToDraw
SkipPlayerSprite
;So, it seems that this performs better than buffered drawing. I can't really explain that.
BufferPlayfieldLine
ldx PlayFieldLineSkip
bne EndPlayfieldLine
ldx #10
stx PlayFieldLineSkip
ldx PlayFieldYIndex
lda PFC,X
sta COLUPF
lda PF0A,X
sta PF0
lda PF1A,X
sta PF1
lda PF2A,X
sta PF2
inx
stx PlayFieldYIndex
EndPlayfieldLine
dec PlayFieldLineSkip
;Now we have a whole glorious scanline worth of CPU to do whatever we want for the next line!
FinishScanline
;Reduce our scanline counter
dec ScanlineCounter
;If we're not on scanline 0 loop back to HBlank
bne HBlank
OverscanStart
sta WSYNC
lda #%0010
sta VBLANK
lda OverscanTimer
sta TIM64T
OverscanLogic
;Do overscan stuff here
OverscanEnd
sta WSYNC
lda INTIM
bne OverscanEnd
lda #0
sta VBLANK
sta WSYNC
jmp VSync
PF0A
.byte %11110000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %00010000
.byte %11010000
.byte %11010000
.byte %11010000
.byte %00010000
.byte %00010000
.byte %11110000
PF1A
.byte %11111111
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00110000
.byte %00110000
.byte %00110000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %11111111
PF2A
.byte %11111111
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %11000000
.byte %11000000
.byte %11000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %11111111
PFC
.byte $AA
.byte $A8
.byte $A4
.byte $A2
.byte $A0
.byte $AA
.byte $A8
.byte $A4
.byte $A2
.byte $A0
.byte $AA
.byte $A8
.byte $A4
.byte $A2
.byte $A0
.byte $AA
.byte $A8
.byte $A4
.byte $A0
SpriteFaceRight
.byte %00000000 ;
.byte %01111110 ;
.byte %11111111 ;
.byte %11111000 ;
.byte %11110111 ;
.byte %11111111 ;
.byte %11111001 ;
.byte %11111001 ;
.byte %01111110 ;
SpriteFaceDown
.byte %00000000 ;
.byte %01111110 ;
.byte %11000011 ;
.byte %10111101 ;
.byte %11111111 ;
.byte %10011001 ;
.byte %10011001 ;
.byte %11111111 ;
.byte %01111110 ;
SpriteFaceUp
.byte %00000000 ;
.byte %01111110 ;
.byte %11111111 ;
.byte %11111111 ;
.byte %11111111 ;
.byte %11111111 ;
.byte %11111111 ;
.byte %11111111 ;
.byte %01111110 ;
org $FFFC
.word Start
.word Start