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
|
.ROMBANKMAP
BANKSTOTAL 2
BANKSIZE $4000
BANKS 1
BANKSIZE $2000
BANKS 1
.ENDRO
.MEMORYMAP
DEFAULTSLOT 0
SLOTSIZE $4000
SLOT 0 $C000
SLOTSIZE $2000
SLOT 1 $0000
.ENDME
.ENUM $00
sleeping DB
.ENDE
; just use the actual locations in our copy of SPR-RAM rather than zero-page
; addresses, to avoid having to do multiple copies
.define sprite_x $0203
.define sprite_y $0200
.bank 0 slot 0
.org $0000
RESET:
SEI
CLD
LDX #$FF
TXS
INX
STX $2000.w
STX $2001.w
STX $4010.w
LDX #$40
STX $4017.w
vblankwait1:
BIT $2002
BPL vblankwait1
clrmem:
LDA #$00
STA $0000, x
STA $0100, x
STA $0300, x
STA $0400, x
STA $0500, x
STA $0600, x
STA $0700, x
LDA #$FE
STA $0200, x
INX
BNE clrmem
; start with the sprite near the middle of the screen
LDA #$80
STA sprite_x
STA sprite_y
vblankwait2:
BIT $2002
BPL vblankwait2
; PPU is initialized here, so we can start writing data into it. this is safe
; because we have not yet enabled drawing, and so we don't have to restrain
; ourselves to vblank.
; first, we load the palettes into $3F00 and $3F10
load_palettes:
LDA $2002 ; read here so that the next byte written to $2006 is the high
LDA #$3F ; byte of the address
STA $2006 ; write the high byte of the base address
LDA #$00
STA $2006 ; write the low byte of the base address
LDX #$00
load_palettes_loop:
LDA palette.w, x
STA $2007
INX
CPX #$20 ; 16 byte background palette plus 16 byte sprite palette
BNE load_palettes_loop
; then we draw the background (doing that here because it won't be changing)
LDA #$20
STA $2006 ; high byte of the starting address
LDA #$00
STA $2006 ; low byte of the starting address
LDA #$01 ; pattern index 1 is our background tile
LDX #$04 ; this loop will load $2000-$23FF, which includes the
LDY #$00 ; attribute table range, but we can just adjust the
load_background_loop: ; palette to take that into account
STA $2007
INY
BNE load_background_loop
DEX
BNE load_background_loop
; then we set the unchanging parts of our sprite (the pattern index and the
; attributes)
LDA #$00
STA $0201 ; pattern index 0 is our sprite
STA $0202 ; don't need any attributes
; enable the PPU
LDA #%10000000
STA $2000
LDA #%00011000
STA $2001
loop:
INC sleeping
wait_for_vblank_end:
LDA sleeping
BNE wait_for_vblank_end
LDA #$01
STA $4016
LDA #$00
STA $4016
; we don't care about a, b, select, start
LDA $4016
LDA $4016
LDA $4016
LDA $4016
up:
LDA $4016
AND #%00000001
BEQ down
LDX sprite_y.w
DEX
STX sprite_y.w
down:
LDA $4016
AND #%00000001
BEQ left
LDX sprite_y.w
INX
STX sprite_y.w
left:
LDA $4016
AND #%00000001
BEQ right
LDX sprite_x.w
DEX
STX sprite_x.w
right:
LDA $4016
AND #%00000001
BEQ loop_end
LDX sprite_x.w
INX
STX sprite_x.w
loop_end:
JMP loop
NMI:
PHA
TXA
PHA
TYA
PHA
; now the only thing we need to do here is issue a DMA call to transfer our
; sprite data into SPR-RAM
LDA #$00
STA $2003 ; reset the SPR-RAM write offset
LDA #$02
STA $4014 ; start the DMA transfer from $0200
LDA #$00
STA sleeping
PLA
TAY
PLA
TAX
PLA
RTI
palette:
.db $0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30
.db $0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30,$0F,$30
.orga $FFFA
.dw NMI
.dw RESET
.dw 0
.bank 1 slot 1
.org $0000
.incbin "sprites.chr"
|