CutterCross
Active member
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.
3. Add these variables to Zero Page RAM (Project -> Project Settings -> Zero Page RAM):
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:
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):
7. Add those same lines of code at the end of the StopSound macro (StopSound.asm):
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:
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.
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:
;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:
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:
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:
LDA #$00
STA $4010
STA $4011
7. Add those same lines of code at the end of the StopSound macro (StopSound.asm):
Code:
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:
;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.