This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Problem with NSF Play code on NESASM (nullsleep)

Problem with NSF Play code on NESASM (nullsleep)
by on (#38247)
I try make nsf play code on nesasm.. But doesnt work.
http://www.nullsleep.com/treasure/nsf_cart_guide/


http://www.speedyshare.com/672725504.html (files)


I cut NSF file header (no need minus $80 from load address)
(nsf header i put to music.hdr file separately)

Code:
   .inesprg 1   ; 1x 16KB PRG code
   .ineschr 0   ; 1x  8KB CHR data
   .inesmap 0   ; mapper 0 = NROM, no bank swapping
   .inesmir 0   ; background mirroring
 

   
   .bank 0

   .org $C000

RESET:

   cld         ; clear decimal flag
   sei         ; disable interrupts
   lda #%00000000      ; disable vblank interrupts by clearing
   sta $2000      ; the most significant bit of $2000


WaitV1:   
   lda $2002      ; give the PPU a little time to initialize
   bpl WaitV1      ; by waiting for a vblank
WaitV2:   
   lda $2002      ; wait for a second vblank to be safe
   bpl WaitV2      ; and now the PPU should be initialized



   lda #$00      ; clear all the sound registers by setting
   ldx #$00      ; everything to 0 in the Clear_Sound loop
Clear_Sound:
   sta $4000,x      ; store accumulator at $4000 offset by x
   inx         ; increment x
   cpx #$0F      ; compare x to $0F
   bne Clear_Sound      ; branch back to Clear_Sound if x != $0F

   lda #$10      ; load accumulator with $10
   sta $4010      ; store accumulator in $4010
   lda #$00      ; load accumulator with 0
   sta $4011      ; clear these 3 registers that are
   sta $4012      ; associated with the delta modulation
   sta $4013      ; channel of the NES

   lda #%00001111      ; enable all sound channels except
   sta $4015      ; the delta modulation channel

   lda #$C0      ; synchronize the sound playback routine
   sta $4017      ; to the internal timing of the NES

   lda #$01      ; replace dashes with song number
   ldx #$01      ; replace with $00 for NTSC or $01 for PAL
   jsr $F780      ; replace dashes with init address

   lda #%10000000      ; enable vblank interrupts by setting the
   sta $2000      ; most significant bit of $2000


NMI_Routine:
   lda $2002      ; read $2002 to reset the vblank flag
   lda #%00000000      ; clear the first PPU control register 
   sta $2000      ; writing 0 to it
   lda #%10000000      ; reenable vblank interrupts by setting
   sta $2000      ; the most significant bit of $2000
   jsr $F844      ; replace dashes with play address
   rti         ; return from interrupt routine


Forever:

   JMP Forever     ;jump back to Forever, infinite loop
 


   .bank 1

   .org $80F7
   .incbin "music.nsf"

   .org $FFFA
   .dw NMI_Routine
   .dw RESET
   .dw 0
 

 
[/code]

by on (#38263)
Move that Forever: JMP Forever above the NMI routine. The program flow, after reset, before it goes into the infinite loop is hitting that RTI and crashing (doing what I call BRK dancing).

by on (#38292)
doesnt work :/

by on (#38293)
sdm wrote:
doesnt work :/


I did some tests and here the issue:

Change .org $80F7 for $F780. You just inverted the load address. After that, it works fine.

here's a simplified version of your code. I removed some sound init code that may not be necessary but I'm no APU expert yet so don't trust that code 100% ;) I trim it to make it shorter to post on the forum.

edit:

The code didn't work with some emulator because the memory was not initialized properly. I removed the code and inserted it in the latest post.

by on (#38294)
i compile it and doesnt work :(

by on (#38296)
sdm wrote:
i compile it and doesnt work :(


It doesn't work with which emulator?

I used your nesasm3 included with your file, modified the code and tested with Nintendulator and it was working fine at the time of testing. I didn't had the chance to test with other emulator. I'm not very familiar with nesasm so I may have done some error.

If I have a chance, I will try it with other emulator and let you know since it was working.

For the time being, just try to fix the address in your original code and move the loop before the NMI. Maybe the code I removed cause some issues with other emulators.

Edit:

I did some quick tests and here the results.

Emulator that work with your code:
- Nintendulator
- FCEUDX 2.02
- FCEUSP 1.07
- Virtua nes

Emulator that doesn't work with your code:
- Nestopia
- Rocknes

I didn't have any other emulators to test so your code is almost working. Must be just a little something that I didn't saw yet.

Edit2:

I found your issue. Because you didn't initialize the memory/stack at the beginning, it failed in some emulator.

Here's the revised code (sorry guys, I know we're not supposed to post long code, I just want to help him):

Code:
   .inesprg 1      ; 1x 16KB PRG code
   .ineschr 0      ; 1x  8KB CHR data
   .inesmap 0      ; mapper 0 = NROM, no bank swapping
   .inesmir 0      ; background mirroring
   
   .bank 0

   .org $C000
RESET:
   cld             ; clear decimal flag
   sei             ; disable interrupts
   lda #%00000000  ; disable vblank interrupts by clearing
   sta $2000       ; the most significant bit of $2000
   
   ; Second issue was here: proper memory initialization
   sta $2001       ;

   ; Now clear the ram
   ldx #0
   
clrmem:
   sta $000,x ; Zero page
   sta $100,x ; stack
   sta $200,x ; Ram
   sta $300,x
   sta $400,x
   sta $500,x
   sta $600,x
   sta $700,x ; Remove this if you're storing reset-persistent data
   
   inx
   bne clrmem
   
    ldx #$FF       ; set stack
   txs   
   
WaitV1:   
   lda $2002       ; give the PPU a little time to initialize
   bpl WaitV1      ; by waiting for a vblank
WaitV2:   
   lda $2002       ; wait for a second vblank to be safe
   bpl WaitV2      ; and now the PPU should be initialized

   
   lda #%00001111  ; enable all sound channels except
   sta $4015       ; the delta modulation channel

   lda #$01        ; replace dashes with song number
   ldx #$01        ; replace with $00 for NTSC or $01 for PAL
   jsr $F780       ; replace dashes with init address

   lda #%10000000  ; enable vblank interrupts by setting the
   sta $2000       ; most significant bit of $2000

   Forever:
   JMP Forever     ; jump back to Forever, infinite loop

NMI_Routine:
   jsr $F844       ; replace dashes with play address
   rti             ; return from interrupt routine

   .bank 1

   ; The error was here
   .org $F780
   .incbin "music.nsf"

   .org $FFFA
   .dw NMI_Routine
   .dw RESET
   .dw 0


Hope it help. It should work now.

by on (#38297)
good bless you :)

by on (#38298)
sdm wrote:
good bless you :)


I guess this mean it works now then :) Now you should try to incorporate it with the small demo you did!

by on (#38300)
Yes, its work, i add code to my demo:
http://www.siudym.gower.pl/nes_demo_1.nes :)
(i compose original music for this demo)

by on (#38327)
sdm wrote:
Yes, its work, i add code to my demo:
http://www.siudym.gower.pl/nes_demo_1.nes :)
(i compose original music for this demo)


Great, it works. Once you have your original song, let's us hear it then :)

by on (#91244)
Ooold topic, new problem (long pause on NESASM coding)
I olways use NSF files from games, all play/init addres works. Now i try use my own NSF files from famitracker (simple songs and export to NSF) and doesn't work.

Maybe famitracker's NSF files had wrong play/init adress in header?

FT NSF test file:
http://www.siudym.webd.pl/nesasm/dupa.nsf

incbin - AA18
init - AB00
play - AB03

Image


Code:
   .inesprg 1      ; 1x 16KB PRG code
   .ineschr 0      ; 1x  8KB CHR data
   .inesmap 0      ; mapper 0 = NROM, no bank swapping
   .inesmir 0      ; background mirroring
   
   .bank 0

   .org $8000
RESET:
   cld             ; clear decimal flag
   sei             ; disable interrupts
   lda #%00000000  ; disable vblank interrupts by clearing
   sta $2000       ; the most significant bit of $2000
   
   ; Second issue was here: proper memory initialization
   sta $2001       ;

   ; Now clear the ram
   ldx #0
   
clrmem:
   sta $000,x ; Zero page
   sta $100,x ; stack
   sta $200,x ; Ram
   sta $300,x
   sta $400,x
   sta $500,x
   sta $600,x
   sta $700,x ; Remove this if you're storing reset-persistent data
   
   inx
   bne clrmem
   
    ldx #$FF       ; set stack
   txs   
   
WaitV1:   
   lda $2002       ; give the PPU a little time to initialize
   bpl WaitV1      ; by waiting for a vblank
WaitV2:   
   lda $2002       ; wait for a second vblank to be safe
   bpl WaitV2      ; and now the PPU should be initialized

   
   lda #%00001111  ; enable all sound channels except
   sta $4015       ; the delta modulation channel

   lda #$00        ; replace dashes with song number
   ldx #$01        ; replace with $00 for NTSC or $01 for PAL
   jsr $AB00       ; replace dashes with init address

   lda #%10000000  ; enable vblank interrupts by setting the
   sta $2000       ; most significant bit of $2000

   Forever:
   JMP Forever     ; jump back to Forever, infinite loop

NMI_Routine:
   jsr $AB03       ; replace dashes with play address
   rti             ; return from interrupt routine

   .bank 1

   .org $AA18
   .incbin "dupa.nsf" ;without header raw file!

   .org $FFFA
   .dw NMI_Routine
   .dw RESET
   .dw 0

by on (#91246)
You forgot to cut out the header. If works fine if you cut the first $80 bytes from the NSF.

Edit: Hmm... or maybe it only works almost fine. Seems to play way too fast, unless it's meant to be run at 50 FPS.

Edit 2:
Quote:
hitting that RTI and crashing (doing what I call BRK dancing)

Oh man! I am so glad this topic got bumped just for that. Made me laugh out loud.

by on (#91247)
I add link with FULL NSF file. But i ADD without header to code.

Code:
   .org $AA18
   .incbin "dupa.nsf" [b];without header raw file![/b]


by on (#91248)
I cut out the header of what you uploaded, and it worked for me. I changed nothing in your actual code. Shall I PM you the NSF I used and ROM I made?

And what emulator are you using? I've only tried it in two (VirtuaNES and Nintendulator), but it's worked on both.

Edit: While I'm asking questions, what version of NESASM are you using? If you're still using the same one from when you started this topic, that may be the problem. I assembled with v3.01 which can be found here.

by on (#91249)
fceuxdsp,nesasm3

All NSF from NES games work on fceuxdsp

edit:
OK WORKS.... :| :shock:

by on (#91250)
I'm glad you got it working. I figured out what was wrong in the zip code in case you started from scratch to get it working.

This was part of the code in the zip
Code:
lda #$01        ; replace dashes with song number

But this was in the code you posted as text.
Code:
lda #$00        ; replace dashes with song number

I went through the code line by line to see what was different about yours and mine, since the NSFs were identical.

by on (#91252)
Ok but... Work with that simple code only.
http://www.siudym.webd.pl/nesasm/dupa.nes

When i try put to my small demo its crashes:

http://www.siudym.webd.pl/nesasm/new.zip

When i use smal ~1kb nsf code works ok (new_1kb_nsf.nes), but my FT nsf has 5kb ;/

by on (#91281)
Without knowing anything else, you may be getting a bank overflow or your NMI routine is updating the graphics while the screen is still rendering.

Edit: Deleted a useless post. Now it's helpful! Sorry for those who saw the other.

Famitracker's music routine is using RAM you're trying to use. You're putting sprites into $0200-$02FF, but apparently the routine in the NSF is using this RAM for data. You can get the music to play by commenting out
Code:
;JSR LoadSprites

But the second you press any dpad button that touches that RAM, the music gets glitchy or the program crashes.

You should start looking into other audio solutions than this if you want to make an actual game. You can't use this method because it is a PAIN to find out what RAM the music routine is using with this one. If you use a music player that actually assembles with your code, you can relocate the RAM and know exactly how much it's using and where it is.

This bug was really obscure to find.

Famitone allows you to use famitracker's output and even supports sound effects. It's more difficult to set up at first, but it makes things much easier in the long run.

by on (#91284)
Ok thanks for info. I try use other msx code.