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
|
;
; Автор: Авдюхин Алексей / clusterrr@clusterrr.com / http://clusterrr.com
; Специально для Mail.ru Group
;
; INES header
.inesprg 128 * 1024 ; 16 банков PRG
.ineschr 128 * 1024 ; 16 банков CHR
.inesmir 0 ; горизонтальный мирроринг
.inesmap 3914 ; маппер #3914 (кастомный)
.rsset $0020 ; адрес для переменных
COPY_SOURCE_ADDR .rs 2 ; исходный адрес для копирования данный
COPY_DEST_ADDR .rs 2 ; целевой адрес для копирования данный
FRAMES .rs 1 ; счётчик NMI
ACTIVE_BANK .rs 1 ; текущий PRG банк
CONSOLE_TYPE .rs 1 ; тип консоли
PAL_SOURCE_ADDR .rs 2 ; исходный адрес для загрузки палитры
PALETTE_CACHE .rs 16 ; кеш для временного хранения палитры
SPRITES_ENABLED .rs 1 ; включены ли спрайты
TEXT_SOURCE_ADDR .rs 2 ; исходный адрес текста
TEXT_LINE .rs 1 ; текущая строка текста на экране
TEXT_POS .rs 2 ; текущая позиция текста в строке
TEXT_NAMETABLE .rs 1 ; текущий nametable для текста
TEXT_SCROLL_STARTED .rs 1 ; флаг, что запущен автоскроллинг
SCROLL_POS .rs 1 ; текущая позиция скроллинга
SCROLL_NT .rs 1 ; текущий nametable скроллинга
SCROLL_TARGET_POS .rs 1 ; целевая позиция скроллинга
THE_END .rs 1 ; флаг, что пора зациклить
BUTTONS .rs 1 ; нажатые в данный момент кнопки
BUTTONS_TMP .rs 1 ; временные переменные для кнопок
LAST_KONAMI_BUTTON .rs 1 ; последняя кнопка для Konami Code
KONAMI_CODE_STATE .rs 1 ; состоения Konami Code
KONAMI_CODE_TRIGGERED .rs 1 ; флаг, что набран Konami Code
SYMBOL_COUNTER .rs 1 ; Счтётчик напечатанных символов
.rsset $0400
SPRITES .rs 256 ; тут хранятся спрайты
.bank 12 ; PRG банк #12, последние банки
.include music_asm ; Конастанты для музыки
.org NSF_LOAD_ADDR
music:
.incbin music_bin ; Код музыки
.bank 15 ; PRG банк #15, конец PRG
.org $FFFA ; Векторы прерываний
.dw NMI ; NMI вектор
.dw RESET ; Ресет вектор $FFFA
.dw IRQ ; IRQ
; Тут начинается наш код
.bank 15
.org $FD00
RESET:
; сразу же отключаем любые прерывания
sei
; обнуляем стек
ldx #$ff
txs
; обнуление переменных
clear_memory:
lda #$00
sta <COPY_SOURCE_ADDR
sta <COPY_SOURCE_ADDR+1
lda #0
ldy #$02
.memory_clean_loop:
sta [COPY_SOURCE_ADDR], y
iny
bne .memory_clean_loop
lda #BANK(main)/2
jsr select_prg_bank
jmp main
; основное прерывание по таймеру картриджа
IRQ:
php
pha
tya
pha
txa
pha
; вызываем код музыки из предпоследнего банка
; заодно это делает ack прерыванию
lda #BANK(music)/2
sta $6000
; играем музыку
jsr NSF_PLAY_ADDR
; читаем контроллер
lda #BANK(read_controller)/2
sta $6000
jsr read_controller
; возвращаем назад активный банк
lda <ACTIVE_BANK
sta $6000
pla
tax
pla
tay
pla
plp
rti
; прерывание по vblank
NMI:
php
pha
tya
pha
txa
pha
inc <FRAMES
; запускаем таймер в картридже
lda <ACTIVE_BANK
ora #%10000000
sta $6000
pla
tax
pla
tay
pla
plp
rti
; субрутина выбора PRG банка
select_prg_bank:
sta <ACTIVE_BANK
sta $6000
rts
; субрутина для выбора CHR банка с автопереключением
select_chr_auto_bank:
ora #%10000000
sta $6001
rts
; субрутина для выбора CHR банка без автопереключения
select_chr_solid_bank:
sta $6001
rts
; инициализация музыки
init_music:
lda ACTIVE_BANK
pha
lda #BANK(music)/2
jsr select_prg_bank
; номер трека
lda <CONSOLE_TYPE
; в регистре X задаётся регион: PAL или NTSC
ldx <CONSOLE_TYPE
; инициализируем музыкальный проигрыватель
jsr NSF_INIT_ADDR
pla
jsr select_prg_bank
rts
; загружаем nametable в $2000
; в A номер банка
; в COPY_SOURCE_ADDR - адрес данных
load_name_table:
tax
lda ACTIVE_BANK
pha
txa
jsr select_prg_bank
lda #$20
sta $2006
lda #$00
sta $2006
ldy #$00
ldx #$04
.loop:
lda [COPY_SOURCE_ADDR], y
sta $2007
iny
bne .loop
inc <COPY_SOURCE_ADDR+1
dex
bne .loop
pla
jsr select_prg_bank
rts
; далее пихаем код в нулевой банк
.bank 0
.org $8000
enable_ppu:
lda #%00001110
ldx <SPRITES_ENABLED
beq .sprites_disabled
ora #%00010000
.sprites_disabled:
sta PPUMASK
jsr wait_blank_simple
rts
disable_ppu:
lda #%10000000
sta PPUCTRL
lda #%00000000
sta PPUMASK
jsr wait_blank_simple
rts
; субрутина простого ожидания vblank
wait_blank_simple:
pha
lda <FRAMES
.loop:
cmp <FRAMES
beq .loop
pla
rts
; субрутина ожидания vblank
wait_blank:
pha
tya
pha
txa
pha
; скроллим, если нужно
lda <SCROLL_POS
cmp <SCROLL_TARGET_POS
beq .end_scroll
inc <SCROLL_POS
lda <SCROLL_POS
cmp #240
bne .end_scroll
lda #0
sta <SCROLL_POS
lda <SCROLL_NT
eor #1
sta <SCROLL_NT
.end_scroll:
bit PPUSTATUS
lda #0
sta PPUSCROLL
lda <SCROLL_POS
sta PPUSCROLL
lda <SCROLL_NT
bne .second_nt
lda #%10000000
jmp .write_ppuctrl
.second_nt:
lda #%10000010
.write_ppuctrl
sta PPUCTRL
jsr wait_blank_simple
pla
tax
pla
tay
pla
rts
wait_blank_x:
.loop:
jsr wait_blank
dex
bne .loop
rts
reset_scroll:
lda #0
sta <SCROLL_POS
sta <SCROLL_NT
sta <SCROLL_TARGET_POS
rts
; waiting for button release
wait_buttons_not_pressed:
jsr wait_blank ; waiting for v-blank
lda <BUTTONS
bne wait_buttons_not_pressed
rts
; waiting for any button pressed
wait_any_button:
jsr wait_blank ; waiting for v-blank
lda KONAMI_CODE_TRIGGERED
bne .end
lda <BUTTONS
beq wait_any_button
.end
rts
pause:
jsr wait_buttons_not_pressed
jsr wait_any_button
rts
.include "main.asm"
.include "clean.asm"
.include "dimming.asm"
.include "text.asm"
.include "buttons.asm"
.bank 1
.org $A000
title_palette:
.incbin title_palette_0_bin
.incbin title_palette_1_bin
.incbin title_palette_2_bin
.incbin title_palette_3_bin
frame_0_palette:
.incbin frame_0_palette_0_bin
.incbin frame_0_palette_1_bin
.incbin frame_0_palette_2_bin
.incbin frame_0_palette_3_bin
frame_1_palette:
.incbin frame_1_palette_0_bin
.incbin frame_1_palette_1_bin
.incbin frame_1_palette_2_bin
.incbin frame_1_palette_3_bin
frame_2_palette:
.incbin frame_2_palette_0_bin
.incbin frame_2_palette_1_bin
.incbin frame_2_palette_2_bin
.incbin frame_2_palette_3_bin
frame_3_palette:
.incbin frame_3_palette_0_bin
.incbin frame_3_palette_1_bin
.incbin frame_3_palette_2_bin
.incbin frame_3_palette_3_bin
credits_palette:
.incbin credits_palette_0_bin
.incbin credits_palette_1_bin
.incbin credits_palette_2_bin
.incbin credits_palette_3_bin
symbols_palette:
.incbin symbols_palette_bin
.incbin warface_logo_palette_bin
.db 0, 0, 0, 0
.db 0, 0, 0, 0
text_0:
.incbin text_0_bin
text_1:
.incbin text_1_bin
text_2:
.incbin text_2_bin
text_3:
.incbin text_3_bin
.include "sprites.asm"
.bank 2
.org $8000
.include "nametables.asm"
.include "patterns.asm"
|