【原创】如何为自己编写的NES游戏添加音乐?
给大家介绍两个编辑NES音乐的工具:FamiTracker 和 FamiStudio。网上都能下载到,而且开源了的。如果下载不了,可以加到我的Q群,找群友帮助。
这两个软件都提供音乐引擎,但是经我测试FamiTracker的引擎连自己的Demo都不能够还原播放。而且FamiTracker的引擎是针对nsf的,改改是可以nes用。但一个不行的引擎那还是省省。
第二软件FamiStudio,是我这次推荐的。它的引擎配合一个nes框架可以生成nes。同时它提供3种汇编器对应的代码。同是6502汇编器,但是伪代码是有所不同的。这是说的3种汇编器是asm6,nesasm, ca65。
我个人喜欢asm6,原因是asm6语法“简单”。下面继续介绍FamiStudio的引擎和相关的东西。
FamiStudio的引擎是famistudio_asm6.asm
引擎的框架是demo_asm6.asm
值得注意的是:引擎的版本需要紧跟着你安装的FamiStudio的版本。例如现在最新的FamiStudio版本是4.0.6,那么引擎也要最新的4.0.5。因为旧引擎不支持新功能。
原框架对于更换音乐数据有点麻烦。我改了一下,这就方便了。文章的最后,会附我那改过的框架代码。因为我发现音乐数据的引用点都是开头位置,所以我利用这一点修改一下。只要更换包含(.include)文件名就行。
框架代码的842行、847行、850行分别更换音乐数据文件就行。支持3首曲目。这个框架用的是mapper0没有切页。只支持一个dpcm,就是说只能一支曲子有dmc文件。当然真正编游戏,可以用切页。
有一点遗憾,就是dmc必须放在$e000。我没能看懂引擎代码,不知道怎么更换它。
推荐FamiStudio的原因,其中一是引擎可用,第二是它的包容性,可以导入midi,可以导入nsf,可以打开FamiTracker的文档。
经我测试一个带dpmc的FamiTracker文档,但不能通过该引擎播放,但是用FamiTracker生成nsf后,再用FamiStudio导入nsf这就行了,成功通过该引擎播放。第三是可以混合效果音,我的游戏,除了背景声,还有效果音,例中刺刀、子弹和爆炸等,在这个引擎中也能实现。上述的数据是包含在SFX文件中,我们可以通过FamiStudio制作效果音输出生成sfx_asm6.asm。
看明白这个引擎框架就可以以这个框架为基础编写你的NES游戏了。
********************
说了半看,有可能没有能明白我的意思。“如何为自己编写的NES游戏添加音乐?”, 那就是用FamiStudio得到音乐数据,具体操作:例如我用的汇编器是asm6。那么用FamiStudio打开音乐后,按
得到窗口
点选:“FamiStudio Music Code”。我用的asm6,那么格式选asm6。这就行,提勾。输出的是音乐数据。
然后按本框架编写NES游戏,就可以插入音乐了。
如何编译呢?
将asm6.exe放在源文件同一文件夹中,我也改写批处理文件,执行它就能编译了。我改写的这个框架,需要将引擎也放在同一文件夹中。因为我改了它的包含路径。一言盖之,通通放在同一文件夹中,然后执行bat文件。
我写的bat文件
asm6 demo_asm6.asm demo_asm6.nes pause
我修改过的FamiStudio引擎的框架是demo_asm6.asm
1 FAMISTUDIO_VERSION_MAJOR = 4 2 FAMISTUDIO_VERSION_MINOR = 0 3 FAMISTUDIO_VERSION_HOTFIX = 0 4 5 ; HEADER 6 INES_MAPPER = 0 ; 0 = NROM 7 INES_MIRROR = 1 ; 0 = horizontal mirroring, 1 = vertical mirroring 8 INES_SRAM = 0 ; 1 = battery backed SRAM at $6000-7FFF 9 10 .db 'N', 'E', 'S', $1A ; ID 11 .db $02 ; 16k PRG bank count 12 .db $01 ; 8k CHR bank count 13 .db INES_MIRROR | (INES_SRAM << 1) | ((INES_MAPPER & $f) << 4) 14 .db (INES_MAPPER & %11110000) 15 .db $0, $0, $0, $0, $0, $0, $0, $0 ; padding 16 .fillvalue $ff 17 18 ; ZEROPAGE 19 .enum $0000 20 nmi_lock: .dsb 1 ; prevents NMI re-entry 21 nmi_count: .dsb 1 ; is incremented every NMI 22 nmi_ready: .dsb 1 ; set to 1 to push a PPU frame update, 2 to turn rendering off next NMI 23 scroll_x: .dsb 1 ; x scroll position 24 scroll_y: .dsb 1 ; y scroll position 25 scroll_nmt: .dsb 1 ; nametable select (0-3 = $2000,$2400,$2800,$2C00) 26 gamepad: .dsb 1 27 gamepad_previous: .dsb 1 28 gamepad_pressed: .dsb 1 29 song_index: .dsb 1 30 pause_flag: .dsb 1 31 nmt_update_mode: .dsb 1 ; update "mode", 0 = nothing to do, 1 = column mode, 2 = row mode + palettes 32 nmt_update_data: .dsb 128 ; nametable update entry buffer for PPU update 33 nmt_update_len: .dsb 1 ; number of bytes in nmt_update_data buffer 34 palette: .dsb 32 ; palette buffer for PPU update 35 36 ; General purpose temporary vars. 37 r0: .dsb 1 38 r1: .dsb 1 39 r2: .dsb 1 40 r3: .dsb 1 41 r4: .dsb 1 42 43 ; General purpose pointers. 44 p0: .dsb 2 45 .ende 46 47 ; RAM 48 .enum $0300 49 .ende 50 51 ; OAM 52 .enum $0200 53 oam: .dsb 256 ; sprite OAM data to be uploaded by DMA 54 .ende 55 56 ; CODE 57 .base $8000 58 59 ; FamiStudio config. 60 FAMISTUDIO_CFG_EXTERNAL = 1 61 FAMISTUDIO_CFG_DPCM_SUPPORT = 1 62 FAMISTUDIO_CFG_SFX_SUPPORT = 1 63 FAMISTUDIO_CFG_SFX_STREAMS = 2 64 FAMISTUDIO_CFG_EQUALIZER = 1 65 FAMISTUDIO_USE_VOLUME_TRACK = 1 66 FAMISTUDIO_USE_PITCH_TRACK = 1 67 FAMISTUDIO_USE_SLIDE_NOTES = 1 68 FAMISTUDIO_USE_VIBRATO = 1 69 FAMISTUDIO_USE_ARPEGGIO = 1 70 FAMISTUDIO_CFG_SMOOTH_VIBRATO = 1 71 FAMISTUDIO_USE_RELEASE_NOTES = 1 72 FAMISTUDIO_DPCM_OFF = $e000 73 74 ; ASM6-specific config. 75 FAMISTUDIO_ASM6_ZP_ENUM = $00b4 76 FAMISTUDIO_ASM6_BSS_ENUM = $0300 77 FAMISTUDIO_ASM6_CODE_BASE = $8000 78 79 ; FS音乐引擎 80 .include "famistudio_asm6.asm" 81 82 ; Our single screen. 83 screen_data_rle: 84 .incbin "demo.rle" 85 86 default_palette: 87 .incbin "demo.pal" 88 .incbin "demo.pal" 89 90 ; Silver Surfer - BGM 2 91 song_title_00: 92 .db $ff, $ff, $ff, $12, $22, $25, $2f, $1e, $2b, $ff, $12, $2e, $2b, $1f, $1e, $2b, $ff, $4f, $ff, $01, $06, $0c, $ff, $36, $ff, $ff, $ff, $ff 93 94 ; Journey To Silius - Menu 95 song_title_01: 96 .db $ff, $ff, $09, $28, $2e, $2b, $27, $1e, $32, $ff, $13, $28, $ff, $12, $22, $25, $22, $2e, $2c, $ff, $4f, $ff, $0c, $1e, $27, $2e, $ff, $ff 97 98 ; Shatterhand - Final Area 99 song_title_02: 100 .db $ff, $ff, $12, $21, $1a, $2d, $2d, $1e, $2b, $21, $1a, $27, $1d, $ff, $4f, $ff, $05, $22, $27, $1a, $25, $ff, $00, $2b, $1e, $1a, $ff, $ff 101 102 NUM_SONGS = 3 103 104 reset: 105 106 sei ; mask interrupts 107 lda #0 108 sta $2000 ; disable NMI 109 sta $2001 ; disable rendering 110 sta $4015 ; disable APU sound 111 sta $4010 ; disable DMC IRQ 112 lda #$40 113 sta $4017 ; disable APU IRQ 114 cld ; disable decimal mode 115 ldx #$FF 116 txs ; initialize stack 117 ; wait for first vblank 118 bit $2002 119 @wait_vblank_loop: 120 bit $2002 121 bpl @wait_vblank_loop 122 ; clear all RAM to 0 123 lda #0 124 ldx #0 125 @clear_ram_loop: 126 sta $0000, X 127 sta $0100, X 128 sta $0200, X 129 sta $0300, X 130 sta $0400, X 131 sta $0500, X 132 sta $0600, X 133 sta $0700, X 134 inx 135 bne @clear_ram_loop 136 ; place all sprites offscreen at Y=255 137 lda #255 138 ldx #0 139 @clear_oam_loop: 140 sta oam, X 141 inx 142 inx 143 inx 144 inx 145 bne @clear_oam_loop 146 ; wait for second vblank 147 @wait_vblank_loop2: 148 bit $2002 149 bpl @wait_vblank_loop2 150 ; NES is initialized, ready to begin! 151 ; enable the NMI for graphical updates, and jump to our main program 152 lda #%10001000 153 sta $2000 154 jmp main 155 156 nmi: 157 ; save registers 158 pha 159 txa 160 pha 161 tya 162 pha 163 ; prevent NMI re-entry 164 lda nmi_lock 165 beq @lock_nmi 166 jmp @nmi_end 167 @lock_nmi: 168 lda #1 169 sta nmi_lock 170 inc nmi_count 171 lda nmi_ready 172 bne @check_rendering_off ; nmi_ready == 0 not ready to update PPU 173 jmp @ppu_update_end 174 @check_rendering_off: 175 cmp #2 ; nmi_ready == 2 turns rendering off 176 bne @oam_dma 177 lda #%00000000 178 sta $2001 179 ldx #0 180 stx nmi_ready 181 jmp @ppu_update_end 182 @oam_dma: 183 ; sprite OAM DMA 184 ldx #0 185 stx $2003 186 lda #>oam 187 sta $4014 188 189 ; nametable update 190 @nmt_update: 191 lda nmt_update_mode 192 bne @do_update 193 jmp @update_done 194 @do_update: 195 ldx #0 196 cpx nmt_update_len 197 beq @palettes 198 asl 199 asl 200 ora #%10000000 201 sta $2000 202 ldx #0 203 @nmt_update_loop: 204 lda nmt_update_data, x 205 inx 206 sta $2006 207 lda nmt_update_data, x 208 inx 209 sta $2006 210 ldy nmt_update_data, x 211 inx 212 @col_loop: 213 lda nmt_update_data, x 214 inx 215 sta $2007 216 dey 217 bne @col_loop 218 cpx nmt_update_len 219 bcc @nmt_update_loop 220 221 ; palettes 222 @palettes: 223 lda nmt_update_mode 224 cmp #2 225 beq @palettes_need_update 226 jmp @update_done 227 @palettes_need_update: 228 lda $2002 229 lda #$3F 230 sta $2006 231 ldx #0 232 stx $2006 ; set PPU address to $3F00 233 lda palette+0 234 sta $2007 235 lda palette+1 236 sta $2007 237 lda palette+2 238 sta $2007 239 lda palette+3 240 sta $2007 241 lda palette+4 242 sta $2007 243 lda palette+5 244 sta $2007 245 lda palette+6 246 sta $2007 247 lda palette+7 248 sta $2007 249 lda palette+8 250 sta $2007 251 lda palette+9 252 sta $2007 253 lda palette+10 254 sta $2007 255 lda palette+11 256 sta $2007 257 lda palette+12 258 sta $2007 259 lda palette+13 260 sta $2007 261 lda palette+14 262 sta $2007 263 lda palette+15 264 sta $2007 265 lda palette+16 266 sta $2007 267 lda palette+17 268 sta $2007 269 lda palette+18 270 sta $2007 271 lda palette+19 272 sta $2007 273 lda palette+20 274 sta $2007 275 lda palette+21 276 sta $2007 277 lda palette+22 278 sta $2007 279 lda palette+23 280 sta $2007 281 lda palette+24 282 sta $2007 283 lda palette+25 284 sta $2007 285 lda palette+26 286 sta $2007 287 lda palette+27 288 sta $2007 289 lda palette+28 290 sta $2007 291 lda palette+29 292 sta $2007 293 lda palette+30 294 sta $2007 295 lda palette+31 296 sta $2007 297 298 @update_done: 299 ; Clear update mode. 300 lda #0 301 sta nmt_update_mode 302 sta nmt_update_len 303 304 @scroll: 305 lda scroll_nmt 306 and #%00000011 ; keep only lowest 2 bits to prevent error 307 ora #%10001000 308 sta $2000 309 lda scroll_x 310 sta $2005 311 lda scroll_y 312 sta $2005 313 ; enable rendering 314 lda #%00011110 315 sta $2001 316 ; flag PPU update complete 317 ldx #0 318 stx nmi_ready 319 @ppu_update_end: 320 ; if this engine had music/sound, this would be a good place to play it 321 ; unlock re-entry flag 322 lda #0 323 sta nmi_lock 324 @nmi_end: 325 ; restore registers and return 326 pla 327 tay 328 pla 329 tax 330 pla 331 rti 332 333 irq: 334 rti 335 336 ; ppu_update: waits until next NMI, turns rendering on (if not already), uploads OAM, palette, and nametable update to PPU 337 ppu_update: 338 lda #1 339 sta nmi_ready 340 @wait: 341 lda nmi_ready 342 bne @wait 343 rts 344 345 ; ppu_skip: waits until next NMI, does not update PPU 346 ppu_skip: 347 lda nmi_count 348 @wait: 349 cmp nmi_count 350 beq @wait 351 rts 352 353 ; ppu_off: waits until next NMI, turns rendering off (now safe to write PPU directly via $2007) 354 ppu_off: 355 lda #2 356 sta nmi_ready 357 @wait: 358 lda nmi_ready 359 bne @wait 360 rts 361 362 PAD_A = $01 363 PAD_B = $02 364 PAD_SELECT = $04 365 PAD_START = $08 366 PAD_U = $10 367 PAD_D = $20 368 PAD_L = $40 369 PAD_R = $80 370 371 gamepad_poll: 372 ; strobe the gamepad to latch current button state 373 lda #1 374 sta $4016 375 lda #0 376 sta $4016 377 ; read 8 bytes from the interface at $4016 378 ldx #8 379 @gamepad_loop: 380 pha 381 lda $4016 382 ; combine low two bits and store in carry bit 383 and #%00000011 384 cmp #%00000001 385 pla 386 ; rotate carry into gamepad variable 387 ror a 388 dex 389 bne @gamepad_loop 390 sta gamepad 391 rts 392 393 gamepad_poll_dpcm_safe: 394 395 lda gamepad 396 sta gamepad_previous 397 jsr gamepad_poll 398 @reread: 399 lda gamepad 400 pha 401 jsr gamepad_poll 402 pla 403 cmp gamepad 404 bne @reread 405 406 @toggle: 407 eor gamepad_previous 408 and gamepad 409 sta gamepad_pressed 410 411 rts 412 413 version_text: ; 414 .byte $34 + FAMISTUDIO_VERSION_MAJOR, $3e, $34 + FAMISTUDIO_VERSION_MINOR, $3e, $34 + FAMISTUDIO_VERSION_HOTFIX 415 416 play_song: 417 418 @text_ptr = p0 419 420 lda song_index 421 cmp #1 422 beq @song_01 423 cmp #2 424 beq @song_02 425 426 ; Here since both of our songs came from different FamiStudio projects, 427 ; they are actually 3 different song data, with a single song in each. 428 ; For a real game, if would be preferable to export all songs together 429 ; so that instruments shared across multiple songs are only exported once. 430 @song_00: 431 lda #<song_title_00 432 sta @text_ptr+0 433 lda #>song_title_00 434 sta @text_ptr+1 435 ldx #<song_data_00 436 ldy #>song_data_00 437 jmp @play_song 438 439 @song_01: 440 lda #<song_title_01 441 sta @text_ptr+0 442 lda #>song_title_01 443 sta @text_ptr+1 444 ldx #<song_data_01 445 ldy #>song_data_01 446 jmp @play_song 447 448 @song_02: 449 lda #<song_title_02 450 sta @text_ptr+0 451 lda #>song_title_02 452 sta @text_ptr+1 453 ldx #<song_data_02 454 ldy #>song_data_02 455 jmp @play_song 456 457 @play_song: 458 lda #1 ; NTSC 459 jsr famistudio_init 460 lda #0 461 jsr famistudio_music_play 462 463 ;update title. 464 ldx #2 465 ldy #15 466 jsr draw_text 467 jsr ppu_update 468 469 rts 470 471 equalizer_ppu_addr_lo_lookup: 472 .byte $47 ; Square 1 473 .byte $4b ; Square 2 474 .byte $4f ; Triangle 475 .byte $53 ; Noise 476 .byte $57 ; DPCM 477 478 equalizer_ppu_addr_hi_lookup: 479 .byte $22 ; Square 1 480 .byte $22 ; Square 2 481 .byte $22 ; Triangle 482 .byte $22 ; Noise 483 .byte $22 ; DPCM 484 485 ; Which 4 BG tiles to draw for each "volume" [0-7] 486 equalizer_volume_lookup: 487 .byte $e3, $e3, $e3, $e3 ; 0 488 .byte $e3, $e3, $e3, $e0 ; 1 489 .byte $e3, $e3, $e3, $f0 ; 2 490 .byte $e3, $e3, $e0, $f0 ; 3 491 .byte $e3, $e3, $f0, $f0 ; 4 492 .byte $e3, $e0, $f0, $f0 ; 5 493 .byte $e3, $f0, $f0, $f0 ; 6 494 .byte $e0, $f0, $f0, $f0 ; 7 495 .byte $f0, $f0, $f0, $f0 ; 8 496 497 ; To add some color variety. 498 equalizer_color_lookup: 499 .byte $00, $01, $02 500 .byte $00, $01 501 502 ; x = channel to update 503 update_equalizer: 504 505 channel_idx = r0 506 color_offset = r1 507 508 stx channel_idx 509 lda equalizer_color_lookup, x 510 sta color_offset 511 512 ; Write 2 addresses 513 ldy nmt_update_len 514 lda equalizer_ppu_addr_hi_lookup, x 515 sta nmt_update_data,y 516 lda equalizer_ppu_addr_lo_lookup, x 517 sta nmt_update_data+1,y 518 519 ; Always update 4 tiles 520 lda #4 521 sta nmt_update_data+2,y 522 523 ; Compute lookup index based on "volume". 524 lda famistudio_chn_note_counter, x 525 asl 526 asl 527 tax 528 529 clc 530 lda equalizer_volume_lookup, x 531 adc color_offset 532 sta nmt_update_data+3,y 533 lda equalizer_volume_lookup+1, x 534 adc color_offset 535 sta nmt_update_data+4,y 536 lda equalizer_volume_lookup+2, x 537 adc color_offset 538 sta nmt_update_data+5,y 539 lda equalizer_volume_lookup+3, x 540 adc color_offset 541 sta nmt_update_data+6,y 542 543 lda #7 544 adc nmt_update_len 545 sta nmt_update_len 546 ldx channel_idx 547 548 rts 549 550 main: 551 552 ldx #0 553 @palette_loop: 554 lda default_palette, x 555 sta palette, x 556 sta palette+16, x 557 inx 558 cpx #16 559 bcc @palette_loop 560 561 ; Force palette update. 562 lda #2 563 sta nmt_update_mode 564 565 jsr setup_background 566 jsr ppu_update 567 568 lda #0 ; song zero. 569 sta song_index 570 jsr play_song 571 572 ; Load SFX 573 ldx #<sounds 574 ldy #>sounds 575 jsr famistudio_sfx_init 576 577 @loop: 578 579 jsr gamepad_poll_dpcm_safe 580 581 @check_right: 582 lda gamepad_pressed 583 and #PAD_R 584 beq @check_left 585 586 ; dont go beyond last song. 587 lda song_index 588 cmp #(NUM_SONGS - 1) 589 beq @draw 590 591 ; next song. 592 clc 593 adc #1 594 sta song_index 595 jsr play_song 596 jmp @draw_done 597 598 @check_left: 599 lda gamepad_pressed 600 and #PAD_L 601 beq @check_select 602 603 ; dont go below zero 604 lda song_index 605 beq @draw 606 607 sec 608 sbc #1 609 sta song_index 610 jsr play_song 611 jmp @draw_done 612 613 @check_select: 614 lda gamepad_pressed 615 and #PAD_SELECT 616 beq @check_start 617 618 ; Undocumented: selects plays a SFX sample when journey to silius is loaded. 619 lda song_index 620 cmp #1 621 bne @draw 622 623 lda #21 624 jsr famistudio_sfx_sample_play 625 jmp @draw 626 627 @check_start: 628 lda gamepad_pressed 629 and #PAD_START 630 beq @check_a 631 632 lda #1 633 eor pause_flag 634 sta pause_flag 635 636 jsr famistudio_music_pause 637 jmp @draw 638 639 @check_a: 640 lda gamepad_pressed 641 and #PAD_A 642 beq @check_b 643 644 lda #0 645 ldx #FAMISTUDIO_SFX_CH0 646 jsr famistudio_sfx_play 647 beq @draw 648 649 @check_b: 650 lda gamepad_pressed 651 and #PAD_B 652 beq @draw 653 654 lda #1 655 ldx #FAMISTUDIO_SFX_CH1 656 jsr famistudio_sfx_play 657 beq @draw 658 659 @draw: 660 661 jsr famistudio_update ; TODO: Call in NMI. 662 663 lda nmt_update_mode 664 bne @draw_done ; Dont allow update if we already have an update pending. 665 666 ldx #0 667 jsr update_equalizer 668 ldx #1 669 jsr update_equalizer 670 ldx #2 671 jsr update_equalizer 672 ldx #3 673 jsr update_equalizer 674 ldx #4 675 jsr update_equalizer 676 677 lda #1 678 sta nmt_update_mode 679 680 @draw_done: 681 682 jsr ppu_update 683 jmp @loop 684 685 ; Shiru's code. 686 ; x = lo byte of RLE data addr 687 ; y = hi byte of RLE data addr 688 rle_decompress: 689 690 @rle_lo = r0 691 @rle_high = r1 692 @rle_tag = r2 693 @rle_byte = r3 694 695 stx <@rle_lo 696 sty <@rle_high 697 ldy #0 698 jsr rle_read_byte 699 sta <@rle_tag 700 @loop: 701 jsr rle_read_byte 702 cmp @rle_tag 703 beq @is_rle 704 sta $2007 705 sta <@rle_byte 706 bne @loop 707 @is_rle: 708 jsr rle_read_byte 709 cmp #0 710 beq @done 711 tax 712 lda <@rle_byte 713 @rle_loop: 714 sta $2007 715 dex 716 bne @rle_loop 717 beq @loop 718 @done: ;.4 719 rts 720 721 rle_read_byte: 722 723 @rle_lo = r0 724 @rle_high = r1 725 726 lda (@rle_lo),y 727 inc @rle_lo 728 bne @done 729 inc @rle_high 730 @done: 731 rts 732 733 ; Draws text with rendering on. 734 ; x/y = tile position 735 ; p0 = pointer to text data. 736 draw_text: 737 738 @temp_x = r2 739 @temp = r3 740 @text_ptr = p0 741 742 stx @temp_x 743 ldx nmt_update_len 744 tya 745 lsr 746 lsr 747 lsr 748 ora #$20 ; high bits of Y + $20 749 sta nmt_update_data,x 750 inx 751 tya 752 asl 753 asl 754 asl 755 asl 756 asl 757 sta @temp 758 lda @temp_x 759 ora @temp 760 sta nmt_update_data,x 761 inx 762 lda #28 ; all our strings have 28 characters. 763 sta nmt_update_data,x 764 inx 765 766 ldy #0 767 @text_loop: 768 lda (@text_ptr),y 769 sta nmt_update_data,x 770 inx 771 iny 772 cpy #28 773 bne @text_loop 774 775 stx nmt_update_len 776 lda #2 777 sta nmt_update_mode 778 rts 779 780 setup_background: 781 782 ; first nametable, start by clearing to empty 783 lda $2002 ; reset latch 784 lda #$20 785 sta $2006 786 lda #$00 787 sta $2006 788 789 ; BG image. 790 ldx #<screen_data_rle 791 ldy #>screen_data_rle 792 jsr rle_decompress 793 794 ; Add a few sprites to the FamiStudio logo. 795 lda #80 796 sta oam+3 797 lda #15 798 sta oam+0 799 lda #$51 800 sta oam+1 801 lda #1 802 sta oam+2 803 804 lda #72 805 sta oam+7 806 lda #23 807 sta oam+4 808 lda #$60 809 sta oam+5 810 lda #1 811 sta oam+6 812 813 lda #88 814 sta oam+11 815 lda #23 816 sta oam+8 817 lda #$62 818 sta oam+9 819 lda #1 820 sta oam+10 821 822 ; Draw version 823 lda $2002 824 lda #$23 825 sta $2006 826 lda #$79 827 sta $2006 828 829 ldy #0 830 @version_loop: 831 lda version_text,y 832 sta $2007 833 iny 834 cpy #5 835 bne @version_loop 836 837 rts 838 839 ; SONG 840 ;.org $a000 841 song_data_00: 842 .include "song_silver_surfer_asm6.asm" 843 sfx_data: 844 .include "sfx_asm6.asm" 845 ;.org $c000 846 song_data_01: 847 .include "song_superfusion_asm6.asm" 848 ;.org $d000 849 song_data_02: 850 .include "song_magic_jewelry_song_1_asm6.asm" 851 852 ; DPCM 853 .org $e000 854 .incbin "song_superfusion_asm6.dmc" 855 856 ; VECTORS 857 .org $fffa 858 .dw nmi 859 .dw reset 860 .dw irq 861 862 ; CHARS 863 .incbin "demo.chr" 864 .incbin "demo.chr"