; XMSNES EXAMPLE DEMO! .define nsongs 5 ; number of songs in package .include "memmap.inc" ; memory map stuff .include "cheader.inc" ; snes rom header .include "InitSNES.asm" ; snes initialization code .include "snes.inc" ; snes register definitions .BANK 1 .SECTION "GRAPHICS" ; include graphics (bank1) .include "graphics\gfx_window.inc" .include "graphics\gfx_font.inc" .include "graphics\gfx_bg.inc" .include "graphics\gfx_bg2.inc" ;.include "graphics\gfx_bub.inc" .ENDS .BANK 2 SLOT 3 ; include songs/samples (bank2) .SECTION "SPX_PACKAGE" TEST_PACKAGE: .incbin "test.xmp" .ENDS .ramsection "globals" BANK 0 SLOT 1 bg_ripple: db ; for bg effect bg_rippleL: db scr_fade: db ; for fading screen scr_flash: dsb 3 ; for flashing screen joypad: dw ; joypad state joypadc: dw ; joypad 'clicks' joypadl: dw ; last joypad state svar1: dw ; general purpose svar2: dw current_song: dw music_vol: dw ; 8.8 fixed custom_string: dsb 32 effect1: db ; sound effect indexes effect2: db effect3: db effect4: db inst_timer: dw .ends .BANK 0 .SECTION "MAIN" Main: InitSNES ; initialize everything REP #$10 ; 16bit index SEP #$20 ; 8bit accu lda #$80 ; turn off screen sta REG_INIDISP lda #%00001001 ; set display mode sta REG_BGMODE ; mode 1 jsl LoadBG ; load background bg jsl BuildWindow ; build the window thingy jsl LoadFont ; load the font jsl ClearAllText ; reset the text layer ;ldx #STR_SPCDATA ; draw "SPC Ports" ;ldy #14*32+12 jsl DrawText lda #%0110 ; blend the window with the background sta REG_TM ; enable bg1/2 main screen lda #%0000 ; enable bg0 subscreen sta REG_TD ; lda #%01100011 ; add bg0+backdrop+bg1 and half the result sta REG_CGADSUB lda #%00000010 sta REG_CGWSEL ;--------------------------------------------------------- ; SETUP XMSNES ;jsl BootSPC ; send code and initialize ;jsl SPX_Transfer_LFT ; transfer frequency table (linear mode) ;ldx #TEST_PACKAGE ; load package ;lda #:TEST_PACKAGE ; ;jsl SPXP_InstallPackage ; ;ldx #0 ; load song 0 ;jsl ChangeSong ; song is playing now... ;--------------------------------------------------------- lda #%10100001 ; enable vblank irq, enable joypad sta REG_NMITIMEN cli ; enable interrupts wai lda #0 ; reset darkness sta scr_fade ; sta REG_INIDISP ; ldx #22000 ; set playback volume stx music_vol ; ;jsl SPXM_SetVol ; _mainloop: ;----------------------------------- ; SCREEN FADE-IN lda scr_fade cmp #255 beq + clc adc #2 bcc ++ lda #255 ++ sta scr_fade lsr lsr lsr lsr sta REG_INIDISP + ;-------------------------------------- jsl UpdateBG ; Update the background effect ;jsl DrawSPCData ; Read SPC Ports and display them bit inst_timer+1 ; timer to hide instructions bmi ++ ; rep #$20 ; lda inst_timer ; dea ; bpl + ; ldy #(25*32) ; ldx #32 ; jsl ClearText ; + ; sta inst_timer ; sep #$20 ; ++ ; ;jsl SPX_Routine ; call this every frame, or every so often ;-------------------------------------- ; slide music volume to full rep #$20 lda music_vol cmp #$FFFF beq + adc #44 bcc ++ lda #$FFFF ++ sta music_vol sep #$20 xba ; jsl SPXM_SetVol + ;---------------------------------------- ;--------------------------------------- ; if user presses left, decrease song#, load new song sep #$20 lda joypadc+1 and #1 beq + ldx current_song inx cpx #nsongs bcc ++ ldx #nsongs-1 ++ jsl ChangeSong + ;------------------------------------------------- ; if user presses right, increase song#, load new song lda joypadc+1 and #%10 beq + ldx current_song dex bpl ++ ldx #0 ++ jsl ChangeSong + ;-------------------------------------------------- ;------------------------------------------------ ; if user presses A, play effect1, full volume, freq:4 lda joypadc and #%10000000 beq + ; A was pressed lda #$04 ; freq/priority xba lda effect1 ; sample# beq + tax lda #$77 ; volume jsl SPXS_Play + ;----------------------------------------------- ; if user presses B, play effect2, full volume, freq:4 lda joypadc+1 and #%10000000 beq + ; B was pressed lda #$04 ; freq/priority xba lda effect2 ; sample# beq + tax lda #$77 ; volume jsl SPXS_Play + ;----------------------------------------------- ; if user presses X, play effect3, full volume, freq:4 lda joypadc and #%1000000 beq + ; X was pressed lda #$04 ; freq/priority xba lda effect3 ; sample# beq + tax lda #$77 ; volume jsl SPXS_Play + ;----------------------------------------------- ; if user presses Y, play effect4, full volume, freq:3 lda joypadc+1 and #%1000000 beq + ; Y was pressed lda #$03 ; freq/priority xba lda effect4 ; sample# beq + tax lda #$77 ; volume jsl SPXS_Play + ;------------------------------------------------ ldx #0 stx joypadc wai ; wait for vblank jmp _mainloop ; loop ;--------------------------------------------------------- ; this function gets called when the snes receives a song message from the spc MessageReceived: ; a = message cmp #1 bne + jsl FlashScreen ; #1 = flash screen message + rtl ;--------------------------------------------------------- FlashScreen: lda #16 sta scr_flash rtl ;--------------------------------------------------------- cs_jumptable: .dw CS_WAR .dw CS_ACID .dw CS_JOURNEY .dw CS_SATELLITE .dw CS_RUSINA ChangeSong: ; x = song stx current_song ; save song# stz effect1 ; zero out sound effect indexes stz effect2 stz effect3 stz effect4 jsl SPXM_Reset ; queue reset playback jsl SPX_Flush ; flush rep #$20 ; get song*2 lda current_song asl tax sep #$20 jmp (cs_jumptable,x) ; and jump CS_WAR: ldx #STR_WAR_AUTHOR ; get author string phx ldx #STR_WAR_TITLE ; song title jmp CS_BEGINDRAWING CS_ACID: ; other songs ldx #STR_ACID_AUTHOR ; etc phx ldx #STR_ACID_TITLE jmp CS_BEGINDRAWING CS_JOURNEY: ldx #STR_JOURNEY_AUTHOR phx ldx #STR_JOURNEY_TITLE jmp CS_BEGINDRAWING CS_SATELLITE: ldx #STR_SATELLITE_AUTHOR phx ldx #STR_SATELLITE_TITLE jmp CS_BEGINDRAWING CS_RUSINA: ldx #STR_RUSINA_AUTHOR phx ldx #STR_RUSINA_TITLE jmp CS_BEGINDRAWING CS_BEGINDRAWING: phx ;preserve ldy #(8*32) ; clear text ldx #32 jsl ClearText ldy #(10*32) ldx #32 jsl ClearText plx ;restore ldy #16+(8*32) ; draw title jsl DrawCentered plx ldy #16+(10*32) ; draw author jsl DrawCentered ldx current_song ; get song# jsl SPXP_LoadSong ; transfer song ldx current_song ; check if song is 4 (has sound effects) cpx #4 ; bne + ; load some sfx ldx #0 ; hh.wav ldy #0 jsl SPXP_LoadSample sta effect1 ldx #1 ; ow.wav ldy #0 jsl SPXP_LoadSample sta effect2 ldx #2 ; sd.wav ldy #0 jsl SPXP_LoadSample sta effect3 ldx #3 ; OWWW.wav ldy #0 jsl SPXP_LoadSample sta effect4 ; be sure not to load too much stuff ldy #(25*32) ldx #32 jsl ClearText ldx #STR_INST1 ; tell the user to push buttons ldy #(25*32)+16 jsl DrawCentered bra ++ + ldy #(25*32) ldx #32 jsl ClearText ldx #STR_INST2 ; tell the user to push buttons ldy #(25*32)+16 jsl DrawCentered ++ ldx #300 stx inst_timer jsl SPXM_Play ; start playing song rtl ; return ;------------------------------------------------------------------------------- ; TEXT RENDERING STUFF DrawText: ; x = source ; y = offset stz REG_VMAIN ; setup vram increment stuff rep #$20 ; set destination address tya ; ora #($9000/2) ; sta REG_VMADDL ; tay ; sec ; sep #$20 ; _dt_loop: lda $0000, x ; beq _dt_exit ; exit when 0 inx ; increment counter sbc #32 ; viewable ascii characters start at 32 bpl + ; check for newline tya ; newline adc #32 ; edit vram address sta REG_VMADDL ; tay ; sec ; bra _dt_loop ; loop + sta REG_VMDATAL ; store value bra _dt_loop ; loop _dt_exit: rtl ; end ClearText: ; x = length ; y = offset stz REG_VMAIN ; setup vram pointer rep #$20 ; tya ; ora #($9000/2) ; sta REG_VMADDL ; sep #$20 lda #$00 ; start clearing memory _ct_loop: sta REG_VMDATAL ; store... dex ; count... bne _ct_loop ; loop... _ct_exit: sep #$20 ; restore 8-bit accu rtl ; end ClearAllText: lda #%10000000 ; setup vram pointer sta REG_VMAIN ; ldx #($9000/2) stx REG_VMADDL ldx #$100|(0<<10)|(1<<13) ; $100 = blank tile ldy #1024 ; 1024 = 32*32 tiles - stx REG_VMDATAL ; store value dey ; count.. bne - ; loop rtl ; end DrawCentered: ; x = string address ; y = line sty svar2 stx svar1 jsl strlen rep #$20 txa sec sbc svar1 lsr clc eor #$FFFF inc a adc svar2 tay ldx svar1 sep #$20 jmp DrawText DrawSPCData: lda #0 xba ldx #0 stx svar1 - lda REG_APUI00, x inx stx svar2 pha lsr lsr lsr lsr clc tay lda HEX2ASCII, y ldx svar1 sta custom_string,x inx pla and #$0F tay lda HEX2ASCII, y sta custom_string,x inx lda #32 sta custom_string,x inx stx svar1 ldx svar2 cpx #4 bne - ldy #11+(16*32) ldx #custom_string jsl DrawText rtl ;--------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; INITIALIZATION / EFFECTS LoadBub: lda #%10000000 sta REG_VMAIN ldx #$ BuildWindow: lda #%10000000 ; setup vram pointer sta REG_VMAIN ldx #$7C00/2 stx REG_VMADDL ldx #0 REP #$20 - lda.l gfx_window, x ; load graphics sta REG_VMDATAL inx inx cpx #$120 bne - SEP #$20 LDA #-1 ; setup bg attributes sta REG_BG0VOFS stz REG_BG0VOFS lda #($11<<2) sta REG_BG0SC ldy #($8800)/2 sty REG_VMADDL ldx #464 ldy #1024 - stx REG_VMDATAL dey bne - ldy #($8980)/2 sty REG_VMADDL ldx #1000|(2<<10) ldy #32 - stx REG_VMDATAL dey bne - ldx #1000|(2<<10) ldy #32*11 - stx REG_VMDATAL dey bne - ldx #1000|(2<<10) ldy #32 - stx REG_VMDATAL dey bne - lda #32 ; load palette sta REG_CGADD ldx #gfxp_window ldy #32 lda #(REG_CGDATA&255) xba lda #:gfxp_window jsl DMA_TRANSFER rtl LoadFont: lda #%10000000 ; setup vram pointer sta REG_VMAIN ldy #($7000/2) sty REG_VMADDL ldx #0 rep #$20 - lda.l gfx_font, x ; load byte sta REG_VMDATAL ; store inx ; count inx cpx #$600 ; transfer $600*2 bytes bne - sep #$20 ; setup palette lda #0 sta REG_CGADD sta REG_CGDATA sta REG_CGDATA lda #$FF ; white sta REG_CGDATA lda #$7F sta REG_CGDATA lda #%00000000 ; black sta REG_CGDATA sta REG_CGDATA lda #-1 ; setup bg sta REG_BG2VOFS stz REG_BG2VOFS lda #($12<<2) ; source = $9000 sta REG_BG2SC lda #$03 ; set character offset sta REG_BG23NBA rtl LoadBG: lda #%10000000 sta REG_VMAIN ldx #0 stx REG_VMADDL ldx #$1000 ; transfer data REP #$20 - lda.l gfx_bg-$1000, x sta REG_VMDATAL inx inx bpl - ldx #0 stx REG_VMADDL - lda.l gfx_bg2, x sta REG_VMDATAL inx inx cpx #96 bne - sep #$20 lda #-1 sta REG_BG1VOFS stz REG_BG1VOFS lda #($10<<2) sta REG_BG1SC ; setup bg ldy #$8000/2 sty REG_VMADDL ldy #(1<<10) - sty REG_VMDATAL iny cpy #896|(1<<10) bne - ldy #$8000/2 sty REG_VMADDL ldy #32*5 ldx #2|(3<<10) - stx REG_VMDATAL dey bne - ldy #32 ldx #1|(3<<10) - stx REG_VMDATAL dey bne - ldy #$84C0/2 sty REG_VMADDL ldy #32 ldx #0|(3<<10) - stx REG_VMDATAL dey bne - ldy #32*8 ldx #2|(3<<10) - stx REG_VMDATAL dey bne - lda #48 sta REG_CGADD ldx #gfxp_bg2 ldy #32 lda #(REG_CGDATA & 255) xba lda #:gfxp_bg2 jsl DMA_TRANSFER rtl BG_PALETTE: ;.dw 0,0,1024,1024,2048,2048,2081,3105,3105,4129,4129,4129,5153,5153,6177,6210,6210,6210,6177,5153,5153,4129,4129,4129,3105,3105,2081,2048,2048,1024,1024,0,0,0,1024,1024,2048,2048,2081,3105,3105,4129,4129,4129,5153,5153,6177,6210, ;.dw 6276,6276,7300,7300,8324,8324,8357,9381,9381,10405,10405,10405,11429,11429,12453,12486,12486,12486,12453,11429,11429,10405,10405,10405,9381,9381,8357,8324,8324,7300,7300,6276,6276,6276,7300,7300,8324,8324,8357,9381,9381,10405,10405,10405,11429,11429,12453,12486, .dw 4162,5186,5186,6243,6243,7267,8291,8291,9348,9348,10372,11396,11396,12453,12453,13477,14501,13477,12453,12453,11396,11396,10372,9348,9348,8291,8291,7267,6243,6243,5186,5186,4162,5186,5186,6243,6243,7267,8291,8291,9348,9348,10372,11396,11396,12453,12453,13477, ;.dw 2116,2117,2117,3174,3174,3175,3176,3176,4233,4233,4234,4235,4235,5292,5292,5293,5294,5293,5292,5292,4235,4235,4234,4233,4233,3176,3176,3175,3174,3174,2117,2117,2116,2117,2117,3174,3174,3175,3176,3176,4233,4233,4234,4235,4235,5292,5292,5293, ;red UpdateBG: clc lda bg_rippleL adc #99 sta bg_rippleL bcs + rtl + lda bg_ripple inc a rep #$20 and #31 sta bg_ripple asl tay sep #$20 lda #0 sta REG_CGADD ldx #16 lda scr_flash rep #$20 and #31 asl asl asl asl asl ora scr_flash asl asl asl asl asl ora scr_flash sta scr_flash+1 sep #$20 cmp #0 beq + dec scr_flash dec scr_flash dec scr_flash dec scr_flash + clc lda BG_PALETTE, y adc scr_flash+1 sta REG_CGDATA lda BG_PALETTE+1, y adc scr_flash+2 sta REG_CGDATA lda #16 sta REG_CGADD - lda BG_PALETTE, y adc scr_flash+1 sta REG_CGDATA lda BG_PALETTE+1, y adc scr_flash+2 sta REG_CGDATA iny iny dex bne - rtl ;----------------------------------------------------------------------------------------------------------------------------------------------------------------- ; DMA DMA_TRANSFER: ; x = src ; y = length ; a = bank# ; b = dest stz REG_DMAP0 ; set mode stx REG_A1T0L ; set source sta REG_A1B0 ; set bank# xba ; sta REG_BBAD0 ; set dest sty REG_DAS0L ; set #bytes lda #1 ; start transfer sta REG_MDMAEN rtl ; end ;---------------------------------------------------------------------------------------------------------------------------------------------------------- ; INTERRUPTS .index 16 .accu 8 VBlank: sei rep #$20 pha ; preserve a lda joypad ; update last joypad state sta joypadl ; sep #$20 lda #1 - bit $4212 ; check if joypad is ready bne - ; wait... rep #$20 lda REG_JOY1L ; load joystate sta joypad ; save to memory eor joypadl ; mask with old state and joypad ; mask some more.. sta joypadc ; store button 'clicks' sep #$20 lda REG_TIMEUP ; do something rep #$20 pla ; restore a rti ; exit ;-------------------------------------------------------------------------------------- ; misc strlen: ; x = str address ; returns x = str address + length - lda $0000, x beq + inx bra - + rtl ;------------------------------------------------------------------------------------- ; STRINGS STR_HELP: .DB "Press left/right to", 1 .db "change songs",0 STR_SPCDATA: .db "SPC Ports",0 HEX2ASCII: .db 48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70 STR_WAR_TITLE: .db "War in Middle Earth", 0 STR_WAR_AUTHOR: .db "by Skaven", 0 STR_ACID_TITLE: .db "Acidjazzed Evening", 0 STR_ACID_AUTHOR: .db "by Tempest", 0 STR_JOURNEY_TITLE: .db "Your Journey Awaits", 0 STR_JOURNEY_AUTHOR: .db "by AlexG", 0 STR_SATELLITE_TITLE: .db "Satellite One",0 STR_SATELLITE_AUTHOR: .db "by Purple Motion",0 STR_RUSINA_TITLE: .db "Rusinahumppa",0 STR_RUSINA_AUTHOR: .db "by Croaker",0 STR_INST1: .db "Press A/B/X/Y for SFX",0 STR_INST2 .db "Change songs with left/right",0 .ENDS