[4.5.6] Implementing DPCM Sample Playback

Post Reply
User avatar
CutterCross
Posts: 588
Joined: Sat Apr 28, 2018 9:42 pm
Contact:

[4.5.6] Implementing DPCM Sample Playback

Post by CutterCross » Mon Sep 21, 2020 11:59 pm

Alright, this has been a long time coming. And now that Byte-Off is over and I had the chance to implement this in 4.5.6, (and actually wrote some notes as I went this time,) here we go. I'm not doing a full tutorial on how to make and use DPCM samples within the context of FamiTracker or FamiStudio, as there are plenty of other tutorials for that. This will be strictly in the context of importing music files with DPCM samples into NESmaker projects.



IMPORTANT:

DPCM sample playback will not be for everyone. Each project is going to have their own needs with memory management in the static bank ($1F) and you will have to make compromises. You will also need to have some understanding on the quirks of DPCM and how to monitor your bank data with Shiru's NES Space Checker.



Quirks of Using DPCM Samples:

For UNROM 512 / Mapper#30, DPCM sample data must be stored in the static bank ($1F). This means it will share the same area in ROM with your initialization, main game loop, NMI, and whatever else needs to be loaded into the CPU memory window at all times. A default NESmaker project gives you around 2.7 KB to work with, but you'll have to plan if it's worth sacrificing potential space for custom routines in exchange for DPCM sample space. Other projects will vary on available sample space. You should also keep in mind the size of your samples when viewing them in FamiTracker's Instrument Editor. It will tell you the exact sizes of each sample.

Because of the issue with sample size and available ROM space in the static bank, anyone outsourcing a FamiTracker user for their game's music will have to communicate more and plan things out regarding your game's specific ROM limitations.

Playback of the DMC will lower the volume of the Triangle and Noise channels in a difficult to control manner. Keep this in mind when doing volume mixing / adjustments.

GGsound can occasionally play a sample at a pitch lower than intended on original NES hardware. This is not an issue with emulators to my knowledge, and is a pretty rare circumstance, but it's important to note.



How to Actually Implement DPCM Playback:

With all that out of the way, let's get to actually enabling sample playback. We'll assume you already have your FT txt file ready and you've accounted for everything above.



1. BACK UP YOUR ENTIRE NESMAKER FOLDER FOR DPCM PROJECTS. Just so nothing goes wrong with your non-DPCM projects, you'll want to make 2 separate folders for both DPCM and non-DPCM projects.

2. Uncomment FEATURE_DPCM at the top of ggsound.inc, and change the value it represents from 0 to 1.

Code: Select all

;Comment out these equates for features you do not wish to use.
FEATURE_DPCM = 1
FEATURE_ARPEGGIOS = 1
3. Add these variables to Zero Page RAM (Project -> Project Settings -> Zero Page RAM):

Code: Select all

	base_address_dpcm_sample_table 			;; 2 bytes
	base_address_dpcm_note_to_sample_index 		;; 2 bytes
	base_address_dpcm_note_to_sample_length 	;; 2 bytes
	base_address_dpcm_note_to_loop_pitch_index 	;; 2 bytes
	apu_dpcm_state 					;; 1 byte
4. Also in Zero Page RAM, sound_param_word_3 is misspelled. Fix Joe's mistake and rename it correctly.

5. Uncomment the following lines in Initialization.asm:

Code: Select all

	lda #<dpcm_list
   	sta sound_param_word_3
    	lda #>dpcm_list
    	sta sound_param_word_3+1
6. To make sure the DMC stops playing sample data along with the rest of the 2A03 channels, add this in Bank1B.asm under "jsr sound_stop" (line 8):

Code: Select all

	LDA #$00
	STA $4010
	STA $4011
7. Add those same lines of code at the end of the StopSound macro (StopSound.asm):

Code: Select all

	LDA #$00
	STA $4010
	STA $4011


Importing Your Music File and DPCM Sample Table:

Now that we've got all the initialization stuff out of the way, we can actually import our music and sample table.



1. Use GGsound's official ft_txt_to_asm converter to convert your FT txt file into an asm file. It will spit out both the converted asm file and the DPCM sample table asm file.

2. In Base.asm, include your DPCM sample table asm file right before the Reset vector:

Code: Select all

;3. Handle bank assignments
	.include SCR_ASSIGN_BANKS
	
;;;; Include DPCM sample table
		
	.include "Sound\track_dpcm.asm"		;; GGsound uses track_dpcm as the name for its default DPCM sample table,
						;; So that's the naming convention I stuck with for my projects.
						;; But you can name it whatever you want.
								
;4 The Reset
	.include SCR_RESET
3. In NESmaker, right-click on Sound and left-click "Load Converted FamiTracker .asm" and import your converted asm music file.



And that should do it! Sample at your own risk.

*EDIT: In Bank1B.asm and StopSound.asm, you want to set #$00 to BOTH $4010 and $4011 to properly reset the DMC load counter back to 0, which will restore the proper volume balance of the Triangle and Noise channels.
Last edited by CutterCross on Tue Oct 13, 2020 5:54 am, edited 2 times in total.
User avatar
TakuikaNinja
Posts: 124
Joined: Thu Feb 28, 2019 10:11 pm
Location: Wellington, NZ
Contact:

Re: [4.5.6] Implementing DPCM Sample Playback

Post by TakuikaNinja » Tue Sep 22, 2020 2:55 am

Nice! Can't wait to play around with this in my own game!

I do remember there was a bug in the ft_txt_to_asm python script which prevented looping samples from working.
Here's the fix CutterCross shared with me -> Line 642: Change << 4 to << 6.
Maybe we should get FunctionalForm to compile the fixed version into an executable file for convenience.

By the way, how would you set up a double controller read to work around the DMC channel corrupting the controller input?
User avatar
CutterCross
Posts: 588
Joined: Sat Apr 28, 2018 9:42 pm
Contact:

Re: [4.5.6] Implementing DPCM Sample Playback

Post by CutterCross » Tue Sep 22, 2020 3:02 am

I knew I forgot something. In doHandleInputReads.asm you'll want to replace the main "DO GamePadCheck" with this. This was originally for 4.1.5 but it works fine in 4.5.6. Special credit to Kasumi for the main logic and Dale Coop for this 2 player variant:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DO GamePadCheck
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;; Kasumi's Double-Read Routine for DPCM ;;;;;;;;;;;;;;;;;;;;;;   
;;;;;;;;;;;;;;;;;;;;; Modified for 2 controllers by Dale Coop ;;;;;;;;;;;;;;;;;;;;;



GamePadCheck:
    LDA gamepad        ;backup values from last frame
    STA temp

    LDA gamepad2    ;backup values from last frame
    STA temp1
    
    LDA #$01
    STA $4016
    LSR
    STA $4016
    
    LDA #$01
    STA $4017
    LSR
    STA $4017

    LDA #$80
    STA gamepad
    STA gamepad2
    STA temp2
    STA temp3    

    
ReadControllerBytesLoop:
    LDA $4017
    AND #%00000011
    CMP #%00000001
    ROR gamepad2
    
    LDA $4016
    AND #%00000011
    CMP #%00000001
    ROR gamepad
    BCC ReadControllerBytesLoop
    
    LDA #$01
    STA $4016
    LSR
    STA $4016
    
    LDA #$01
    STA $4017
    LSR
    STA $4017
    
ReadControllerBytesLoop2:
    LDA $4017
    AND #%00000011
    CMP #%00000001
    ROR temp3
    
    LDA $4016
    AND #%00000011
    CMP #%00000001
    ROR temp2
    BCC ReadControllerBytesLoop2
    
    LDA temp2
    CMP gamepad
    BEQ ReadController1DpcmMatch
    LDA temp
    STA gamepad
    ReadController1DpcmMatch:

    LDA temp3
    CMP gamepad2
    BEQ ReadController2DpcmMatch
    LDA temp1
    STA gamepad2
    ReadController2DpcmMatch:

	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;END GamePadCheck
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
User avatar
Logana
Posts: 426
Joined: Mon Nov 18, 2019 10:14 pm

Re: [4.5.6] Implementing DPCM Sample Playback

Post by Logana » Fri Sep 25, 2020 10:38 am

Dose this also readable note effects and if so dose it take any extra data to store the note effects
I’m currently working on platycat viewtopic.php?f=52&t=5848
A fun platform game also Monster Slayer witch is the bigger prodject viewtopic.php?f=52&t=6010
User avatar
CutterCross
Posts: 588
Joined: Sat Apr 28, 2018 9:42 pm
Contact:

Re: [4.5.6] Implementing DPCM Sample Playback

Post by CutterCross » Fri Sep 25, 2020 2:55 pm

Logana wrote:
Fri Sep 25, 2020 10:38 am
Dose this also readable note effects and if so dose it take any extra data to store the note effects
The only effect GGsound supports is Bxx, and it must be used in all used channels, on the same line, on unique note patterns, and can only be implemented with GGsound's official ft_txt_to_asm converter. This does not add any extra support for effects, only the ability to play back DPCM samples.
Post Reply