-
Notifications
You must be signed in to change notification settings - Fork 0
/
intro_outro.asm
374 lines (321 loc) · 6.92 KB
/
intro_outro.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
.export IntroScreen
.export OutroScreen
.include "include.controller.asm"
.include "include.const.asm"
.include "include.branch-macros.asm"
.include "include.mov-macros.asm"
.include "include.sys.asm"
.include "gfx.h.asm"
.include "random.h.asm"
.include "general_mapper.h.asm"
.include "memory_layout.h.asm"
.include "read_controller.h.asm"
.include "gameplay.h.asm"
.include "marque.h.asm"
.include "sprite_space.h.asm"
.include "object_list.h.asm"
.include "render_action.h.asm"
.include "msg_catalog.h.asm"
.include "famitone.h.asm"
.include "sound.h.asm"
.include "endboss.h.asm"
.importzp ppu_ctrl_current, buttons_press, lives
.importzp values
.importzp which_level
.importzp main_yield
.importzp buttons
.import title_palette
.import title_graphics
.import game_over_palette
.import game_over_graphics
.import RESET
NUM_TIMES_TO_FLASH = 12
BOSS_LEVEL = MAX_LEVEL
outer = values + 4
inner = values + 5
wings_frame = values + 6
code_dist = values + 7
special_code = values + 8
.segment "CODE"
.proc IntroScreen
jsr WaitVblankFlag
; Load palette, which is defined in the prologue.
ldx #<title_palette
ldy #>title_palette
jsr LoadPalette
ldx #<title_graphics
ldy #>title_graphics
jsr MemoryLayoutLoadNametable
ldx #MSG_PRESS
jsr MsgRender
ldx #MSG_START
jsr MsgRender
ldx #MSG_COPYRIGHT
jsr MsgRender
ldx #TITLE_MEMORY_LAYOUT
jsr MemoryLayoutFillChrRam
jsr CreateFlyWings
mov code_dist, #0
mov special_code, _
mov which_level, #1
mov lives, #3
; Play a song.
lda #0
jsr FamiToneMusicPlay
jsr SpriteSpaceInit
jsr EnableNmiThenWaitNewFrameThenEnableDisplay
jsr Disable8x16
IntroLoop:
jsr WaitNewFrameWhileIncreasingRandomSeed
jsr FamiToneUpdate
jsr SpriteSpaceEraseAll
jsr SpriteSpaceNext
jsr ObjectListUpdate
jsr ReadController
; Start to exit normally.
lda buttons_press
and #BUTTON_START
bne TransitionOut
; Build a special code.
jsr AccumulateSpecialCode
; If special code.
lda special_code
beq IntroLoop
CodeIsActive:
lda buttons_press
and #BUTTON_LEFT
bne LevelDec
lda buttons_press
and #BUTTON_RIGHT
bne LevelInc
beq IntroLoop
LevelDec:
dec which_level
bne LevelSet
mov which_level, #MAX_LEVEL
bpl LevelSet
LevelInc:
inc which_level
lda which_level
cmp #(MAX_LEVEL + 1)
blt LevelSet
mov which_level, #1
LevelSet:
jsr RenderLevelSelection
jmp IntroLoop
TransitionOut:
jsr FamiToneMusicStop
lda #SFX_PRESS_START
jsr SoundPlay
mov outer, #NUM_TIMES_TO_FLASH
OuterLoop:
jsr ClearPressStart
jsr WaitFramesForFlash
ldx #MSG_PRESS
jsr MsgRender
ldx #MSG_START
jsr MsgRender
jsr WaitFramesForFlash
dec outer
bne OuterLoop
jsr WaitNewFrame
jsr FamiToneUpdate
ExitIntroScreen:
jsr DisableDisplayAndNmi
jmp MarqueScreen
ExitFast:
jsr DisableDisplayAndNmi
jmp GameplayMain
.endproc
.proc ClearPressStart
lda #11
jsr AllocateRenderAction
mov {render_action_addr_high,y}, #$22
mov {render_action_addr_low,y}, #$ab
ldx #0
Loop:
mov {render_action_data,y}, #0
iny
inx
cpx #11
bne Loop
rts
.endproc
.proc WaitFramesForFlash
mov inner, #4
Loop:
jsr WaitNewFrame
jsr FamiToneUpdate
dec inner
bne Loop
rts
.endproc
.proc OutroScreen
jsr RenderActionClear
jsr ClearBothNametables
; Load palette, which is defined in the prologue.
ldx #<game_over_palette
ldy #>game_over_palette
jsr LoadPalette
ldx #<game_over_graphics
ldy #>game_over_graphics
jsr MemoryLayoutLoadNametable
ldx #TITLE_MEMORY_LAYOUT
jsr MemoryLayoutFillChrRam
jsr CreateFlyWings
jsr SpriteSpaceInit
jsr EnableNmiThenWaitNewFrameThenEnableDisplay
OutroLoop:
jsr WaitNewFrame
jsr FamiToneUpdate
jsr SpriteSpaceEraseAll
jsr SpriteSpaceNext
jsr ObjectListUpdate
jsr ReadController
; Start to exit normally.
lda buttons_press
and #BUTTON_START
beq OutroLoop
TransitionToReset:
jsr FamiToneMusicStop
jmp RESET
.endproc
.proc Disable8x16
lda ppu_ctrl_current
and #($ff & ~PPU_CTRL_SPRITE_8x16)
sta ppu_ctrl_current
sta PPU_CTRL
rts
.endproc
.proc CreateFlyWings
jsr ObjectListInit
jsr ObjectAllocate
mov {object_kind,x}, #OBJECT_KIND_WING
mov {object_v,x}, #$9c
mov {object_h,x}, #$13
ldy #0
jsr ObjectConstructor
jsr ObjectAllocate
mov {object_kind,x}, #OBJECT_KIND_WING
mov {object_v,x}, #$9c
mov {object_h,x}, #$24
ldy #1
jsr ObjectConstructor
jsr ObjectAllocate
mov {object_kind,x}, #OBJECT_KIND_WING
mov {object_v,x}, #$9c
mov {object_h,x}, #$cc
ldy #2
jsr ObjectConstructor
jsr ObjectAllocate
mov {object_kind,x}, #OBJECT_KIND_WING
mov {object_v,x}, #$9c
mov {object_h,x}, #$dd
ldy #3
jsr ObjectConstructor
rts
.endproc
.proc AccumulateSpecialCode
bit special_code
bmi Return
; Check each bit one at a time.
mov outer, #8
lda buttons_press
beq Return
Loop:
lsr a
bcs GotButton
dec outer
beq Return
bne Loop
GotButton:
; If more than one button pressed, exit.
bne EraseCode
; Compare the pressed button to the expected sequence.
lda buttons_press
ldy code_dist
cmp code_sequence,y
bne EraseCode
; Correct value inputted, advance the code distance.
inc code_dist
lda code_dist
cmp #CODE_LENGTH
beq SpecialCodeComplete
rts
EraseCode:
mov code_dist, #0
; Special case.
lda buttons_press
cmp code_sequence+0
bne Return
; Start after step 1
inc code_dist
Return:
rts
SpecialCodeComplete:
lda #SFX_MAKE_STARS
jsr SoundPlay
mov special_code, #$ff
ldx #MSG_SELECT_LEVEL
jsr MsgRender
jsr RenderLevelSelection
rts
.endproc
KEY_RIGHT = 1
KEY_LEFT = 2
KEY_DOWN = 4
KEY_UP = 8
KEY_START = $10
KEY_SELECT = $20
KEY_B = $40
KEY_A = $80
code_sequence:
.byte KEY_DOWN, KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_B, KEY_A, KEY_DOWN
CODE_LENGTH = * - code_sequence
.proc RenderLevelSelection
lda which_level
cmp #BOSS_LEVEL
beq BossLevel
NormalLevel:
lda #6
jsr AllocateRenderAction
mov {render_action_addr_high,y}, #$22
mov {render_action_addr_low,y}, #$6d
mov {render_action_data+0,y}, #'L'
mov {render_action_data+1,y}, #'E'
mov {render_action_data+2,y}, #'V'
mov {render_action_data+3,y}, #'E'
mov {render_action_data+4,y}, #'L'
mov {render_action_data+5,y}, #' '
lda #1
jsr AllocateRenderAction
mov {render_action_addr_high,y}, #$22
mov {render_action_addr_low,y}, #$73
lda which_level
clc
adc #$30
sta render_action_data,y
rts
BossLevel:
lda #7
jsr AllocateRenderAction
mov {render_action_addr_high,y}, #$22
mov {render_action_addr_low,y}, #$6d
mov {render_action_data+0,y}, #' '
mov {render_action_data+1,y}, #'B'
mov {render_action_data+2,y}, #'O'
mov {render_action_data+3,y}, #'S'
mov {render_action_data+4,y}, #'S'
mov {render_action_data+5,y}, #' '
mov {render_action_data+6,y}, #' '
rts
.endproc
.proc WaitNewFrameWhileIncreasingRandomSeed
mov main_yield, #0
WaitLoop:
jsr RandomSeedInc
bit main_yield
bpl WaitLoop
mov main_yield, #0
rts
.endproc