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
|
.segment "CODE"
.scope Over
;; Has the "Game over" screen been displayed yet?
zp_displayed = $10
;; Timer set whenever the "Game over" screen has been displayed. Whenever it
;; times out, then the player is redirected to the title screen.
zp_timer = $11
;; Amount of time the player has to wait for the title screen to appear
;; again.
TIMER_VALUE = HZ * 3
;; Initialize all variables for the "Game over" screens.
.proc init
lda #0
sta Over::zp_displayed
sta Over::zp_timer
rts
.endproc
;; Handle a "Game over" screen. It has two phases:
;; 1. Render a "Game over" message.
;; 2. Wait for a timer to time out.
;; It will set 1 to the 'a' register if the timer has run out, signaling
;; that the game can start over. Otherwise it sets 0 to the 'a' register.
.proc handle
ldy #0
;; Has the "Game over" screen been displayed? If not do it now.
lda Over::zp_displayed
bne @do_handle
jsr Over::render
jmp @end
@do_handle:
lda Over::zp_timer
bne @dec_timer
iny
beq @end
@dec_timer:
dec Over::zp_timer
@end:
tya
rts
.endproc
;; Render the "Game over" message to the screen. This is done in two
;; phases. We first ensure to disable the PPU, and in the second phase we do
;; the actual writing.
.proc render
;; Is PPU disabled? If it is then jump into rendering the screen
;; directly.
lda PPU::zp_mask
beq @do_render
;; Nope! Force the PPU to be disabled and quit.
lda Globals::zp_flags
ora #%01000000
sta Globals::zp_flags
lda #$00
sta PPU::zp_mask
rts
@do_render:
jsr Over::clear_out_screen
;; TODO: coin game over.
jsr Over::render_regular_game_over
;; Enable back the PPU (only background).
lda #%00001110
sta PPU::zp_mask
;; Update PPU registers.
lda #%01000000
ora Globals::zp_flags
sta Globals::zp_flags
;; Set the "Game over" message as displayed and fire up the timer.
lda #1
sta Over::zp_displayed
lda #Over::TIMER_VALUE
sta Over::zp_timer
rts
.endproc
;; Remove all platforms and the ground.
.proc clear_out_screen
;; Remove left platform.
bit PPU::m_status
ldx #$29
stx PPU::m_address
ldx #$83
stx PPU::m_address
lda #$00
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
;; Remove center platform.
bit PPU::m_status
ldx #$29
stx PPU::m_address
ldx #$EF
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
;; Remove right platform.
bit PPU::m_status
ldx #$29
stx PPU::m_address
ldx #$38
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
;; Ground
bit PPU::m_status
ldx #$2B
stx PPU::m_address
ldx #$20
stx PPU::m_address
ldx #$20
@clear_ground_loop:
sta PPU::m_data
dex
bne @clear_ground_loop
;; The low part of the rocket.
bit PPU::m_status
ldx #$2B
stx PPU::m_address
ldx #$15
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
;; High part of the rocket.
bit PPU::m_status
ldy #$2A
sty PPU::m_address
ldx #$75
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
bit PPU::m_status
sty PPU::m_address
ldx #$95
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
bit PPU::m_status
sty PPU::m_address
ldx #$B5
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
;; Middle part of the rocket.
bit PPU::m_status
sty PPU::m_address
ldx #$D5
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
bit PPU::m_status
sty PPU::m_address
ldx #$F5
stx PPU::m_address
sta PPU::m_data
sta PPU::m_data
rts
.endproc
;; Render the regular "Game over" screen.
.proc render_regular_game_over
;; Set the position.
bit PPU::m_status
ldx #$29
stx PPU::m_address
ldx #$6C
stx PPU::m_address
;; And just iterate over the "message" until we reach the end of string
;; $FF character.
ldx #0
@message_loop:
lda message, x
cmp #$FF
beq @out
sta PPU::m_data
inx
bne @message_loop
@out:
;; Reset attributes for the end of the message.
bit PPU::m_status
ldx #$2B
stx PPU::m_address
ldx #$D5
stx PPU::m_address
lda #0
sta PPU::m_data
sta PPU::m_data
sta PPU::m_data
rts
message:
;; "GAME "
.byte $21, $1B, $27, $1F, $00
;; "OVER"
.byte $29, $30, $1F, $2C, $FF
.endproc
.endscope
|