trying to get nullsleep's NSF playback code working...

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
mcfiredrill
Posts: 9
Joined: Sun May 13, 2007 8:36 pm
Contact:

trying to get nullsleep's NSF playback code working...

Post by mcfiredrill »

hello all,

I'm trying to get the NSF playback code from Nullsleep's guide working...the only problem is I am using NESASM because I couldn't get X186 to work.Here is the code I had at first:

Code: Select all

; *** X816 SETTINGS ***
	.mem 8			; 8-bit memory mode
	.index 8		; 8-bit index mode
	.opt on			; address optimize
	
	.org $8000		; replace dashes with load address MINUS $80
	.incbin "nomryi.nsf"	; include NSF tune 

	
Reset_Routine:
	cld			; clear decimal flag
	sei			; disable interrupts
	lda #%00000000		; disable vblank interrupts by clearing
	sta $2000		; the most significant bit of $2000
	
; *** WAIT 2 VBLANKS ***
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
	
; *** CLEAR SOUND REGISTERS ***
	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
	
; *** ENABLE SOUND CHANNELS ***
	lda #%00001111		; enable all sound channels except
	sta $4015		; the delta modulation channel
	
; *** RESET FRAME COUNTER AND CLOCK DIVIDER ***
	lda #$C0		; synchronize the sound playback routine 
	sta $4017		; to the internal timing of the NES
	
; *** SET SONG # & PAL/NTSC SETTING ***
	lda #$00		; replace dashes with song number
	ldx #$00		; replace with $00 for NTSC or $01 for PAL
	jsr $8000		; replace dashes with init address
	
; *** ENABLE VBLANK NMI ***
	lda #%10000000		; enable vblank interrupts by setting the 
	sta $2000		; most significant bit of $2000

Loop:
	jmp Loop		; loop loop loop loop ...
	
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 $8003		; replace dashes with play address
	rti			; return from interrupt routine
	
IRQ_Routine:
	rti			; return from interrupt routine

.pad $FFFA
	.dw	NMI_Routine	; setup the NMI vector at $FFFA
	.dw	Reset_Routine	; setup the Reset vector at $FFFC
	.dw	IRQ_Routine	; setup the IRQ vector at $FFFE

	
Then I tried to change the X186 settings to the ines settings required by NESASM...and I change the .pad to .org, because the assembler didnt recognize .org:

Code: Select all

		.inesprg	1
		.ineschr	1
		.inesmir	1
		.inesmap	0
	
	.org $8000		; replace dashes with load address MINUS $80
	.incbin "nomryi.nsf"	; include NSF tune 

	
Reset_Routine:
	cld			; clear decimal flag
	sei			; disable interrupts
	lda #%00000000		; disable vblank interrupts by clearing
	sta $2000		; the most significant bit of $2000
	
; *** WAIT 2 VBLANKS ***
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
	
; *** CLEAR SOUND REGISTERS ***
	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
	
; *** ENABLE SOUND CHANNELS ***
	lda #%00001111		; enable all sound channels except
	sta $4015		; the delta modulation channel
	
; *** RESET FRAME COUNTER AND CLOCK DIVIDER ***
	lda #$C0		; synchronize the sound playback routine 
	sta $4017		; to the internal timing of the NES
	
; *** SET SONG # & PAL/NTSC SETTING ***
	lda #$00		; replace dashes with song number
	ldx #$00		; replace with $00 for NTSC or $01 for PAL
	jsr $8000		; replace dashes with init address
	
; *** ENABLE VBLANK NMI ***
	lda #%10000000		; enable vblank interrupts by setting the 
	sta $2000		; most significant bit of $2000

Loop:
	jmp Loop		; loop loop loop loop ...
	
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 $8003		; replace dashes with play address
	rti			; return from interrupt routine
	
IRQ_Routine:
	rti			; return from interrupt routine

	.org $FFFA
	.dw	NMI_Routine	; setup the NMI vector at $FFFA
	.dw	Reset_Routine	; setup the Reset vector at $FFFC
	.dw	IRQ_Routine	; setup the IRQ vector at $FFFE
	

I can get this to compile but I don't get any sound at all. Any help would be appreciated, thanks alot!
User avatar
Memblers
Site Admin
Posts: 3902
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

First thing I noticed is that .inesprg 1 should be .inesprg 2 since you want a 32kB program instead of 16kB.

Secondly, NESASM is just weird. It's kinda notorious for assembling non-working code (and not giving an error or warning) if you don't follow it's special conventions. One of those is that you have to use the .bank command before .org. Try .bank 0 at the beginning, then before the .org $FFFA .bank 1 2 or 3. I don't know what it expects really.. if you're still stuck after trying that, check out the source to another program that uses NESASM and see how it does it. MCK is one program that uses it successfully.
User avatar
No Carrier
Posts: 290
Joined: Tue Dec 13, 2005 4:19 pm
Location: Gainesville, FL - USA
Contact:

Post by No Carrier »

Or, if you get really stuck, you could try NSFulator:

http://nesdev.com/bbs/viewtopic.php?t=1184

I re-uploaded it here, since the link in that thread is dead:

http://www.sendspace.com/file/riblqn

Good luck!

NC
mcfiredrill
Posts: 9
Joined: Sun May 13, 2007 8:36 pm
Contact:

Post by mcfiredrill »

Ack! Well after I added those changes my emulator won't even open the .nes file. It gives a corrupt file error. I'm thinking maybe there's a better assembler I should use...any ideas? I'll try X186 again.

NoCarrier: I plan on adding a simple graphic later so I don't think NSFulator would help me(?).

Here's my code in case someone notices something obviously wrong with it:

Code: Select all

		.inesprg	2
		.ineschr	1
		.inesmir	1
		.inesmap	0

	.bank 0
	.org $8000		; replace dashes with load address MINUS $80
	.incbin "nomryi.nsf"	; include NSF tune 

	
Reset_Routine:
	cld			; clear decimal flag
	sei			; disable interrupts
	lda #%00000000		; disable vblank interrupts by clearing
	sta $2000		; the most significant bit of $2000
	
; *** WAIT 2 VBLANKS ***
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
	
; *** CLEAR SOUND REGISTERS ***
	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
	
; *** ENABLE SOUND CHANNELS ***
	lda #%00001111		; enable all sound channels except
	sta $4015		; the delta modulation channel
	
; *** RESET FRAME COUNTER AND CLOCK DIVIDER ***
	lda #$C0		; synchronize the sound playback routine 
	sta $4017		; to the internal timing of the NES
	
; *** SET SONG # & PAL/NTSC SETTING ***
	lda #$00		; replace dashes with song number
	ldx #$00		; replace with $00 for NTSC or $01 for PAL
	jsr $8000		; replace dashes with init address
	
; *** ENABLE VBLANK NMI ***
	lda #%10000000		; enable vblank interrupts by setting the 
	sta $2000		; most significant bit of $2000

Loop:
	jmp Loop		; loop loop loop loop ...
	
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 $8003		; replace dashes with play address
	rti			; return from interrupt routine
	
IRQ_Routine:
	rti			; return from interrupt routine

	

	.bank 1
	.org $FFFA
	.dw	NMI_Routine	; setup the NMI vector at $FFFA
	.dw	Reset_Routine	; setup the Reset vector at $FFFC
	.dw	IRQ_Routine	; setup the IRQ vector at $FFFE
	
Post Reply