DPCM ripping and play back? (Gauntlet 2 & others)
Moderator: Moderators
DPCM ripping and play back? (Gauntlet 2 & others)
My idea isn't fully fleshed out yet, but I want to rip DPCM sound from games and play them back on a microcontroller.
I did some fooling around with the 18.exe tool from pineight.com and got some sounds. I was able to pull out the the drum sample and some slashing sound from Ninja Gaiden but I had problems with Gauntlet 2. I can make out the potion noise and some really garbled voice samples but it sounds nothing like it does on real hardware or an emulator. I played with the bitrate and found that 21.3k seems to have the proper pitch. I used a low pass filter and played with the EQ but it's still unintelligible. I figured it might be 7-bit PCM but I shouldn't hear anything recognizable after ripping it as 1-bit DPCM if it were, right?
So does anyone know how Gauntlet 2 encodes it's samples?
Also, playback is as simple as incrementing/decrementing a 6-bit DAC at one of the 16 playback speeds, isn't it? Otherwise I've totally missed something.
Thanks!
EDIT: I've got the Ninja Gaiden slash sample playing back on my dac setup. The speed isn't right and the resistors are mismatched, but all things considered, it sounds pretty ok.
Now I just need "Red warrior shot the food!". Can anyone help?
I did some fooling around with the 18.exe tool from pineight.com and got some sounds. I was able to pull out the the drum sample and some slashing sound from Ninja Gaiden but I had problems with Gauntlet 2. I can make out the potion noise and some really garbled voice samples but it sounds nothing like it does on real hardware or an emulator. I played with the bitrate and found that 21.3k seems to have the proper pitch. I used a low pass filter and played with the EQ but it's still unintelligible. I figured it might be 7-bit PCM but I shouldn't hear anything recognizable after ripping it as 1-bit DPCM if it were, right?
So does anyone know how Gauntlet 2 encodes it's samples?
Also, playback is as simple as incrementing/decrementing a 6-bit DAC at one of the 16 playback speeds, isn't it? Otherwise I've totally missed something.
Thanks!
EDIT: I've got the Ninja Gaiden slash sample playing back on my dac setup. The speed isn't right and the resistors are mismatched, but all things considered, it sounds pretty ok.
Now I just need "Red warrior shot the food!". Can anyone help?
I know some of the sounds would pause the game, but I could be thinking of the first Gauntlet. It probably is done with the $4011 register. It was kinda low quality, I think you would get better results by recording sounds from the arcade version, resample to the best DPCM rate, then convert to 8-bit, then to 1-bit.
If you want to try that, get BridgeM1 (or something similar), it's a frontend for the M1 sound emulator.
But yeah, DPCM would be really easy to play on a microcontroller.
If you want to try that, get BridgeM1 (or something similar), it's a frontend for the M1 sound emulator.
But yeah, DPCM would be really easy to play on a microcontroller.
Well, it turns out it's PCM. I should have ruled that out before I posted.
When I use audacity and import it as 8bit unsigned, little endian it doesn't sound quite right. I know the NES uses 7-bit but isn't it stored as 7-bits packed in a byte?
Also, what's a good way to find the start, end and sample rate of specific samples? Could I disassemble and look for writes to a specific register?
I'm really fond of the NES gauntlet 2 sounds and would like to reproduce them specifically.
I didn't realize how simple some audio formats are. I banged out functional playback code in record time.
When I use audacity and import it as 8bit unsigned, little endian it doesn't sound quite right. I know the NES uses 7-bit but isn't it stored as 7-bits packed in a byte?
Also, what's a good way to find the start, end and sample rate of specific samples? Could I disassemble and look for writes to a specific register?
I'm really fond of the NES gauntlet 2 sounds and would like to reproduce them specifically.
I didn't realize how simple some audio formats are. I banged out functional playback code in record time.
Good call! It looks like that's exactly what it does.Memblers wrote:Maybe it's 4-bit PCM, or other bit resolution. I guess ADPCM could be possible, but I doubt it's that. In an emu you can put a breakpoint on writes to $4011, then see what it did before writing.
Code: Select all
LDA ($D1),Y @ $9253 = #$98
BEQ $F494
INY
STY $00D0 = #$01
AND #$F0
LSR
STA $4011 = #$FFCode: Select all
LDY #$00
LDA ($D1),Y @ $9252 = #$78
AND #$0F
ASL
ASL
ASL
STA $4011 = #$FFYou could try extracting .wav and looking at the result in Audacity to make sure your decoding algorithm is correct.
Stingray, or gate, dice? ...Skate, or, die.tepples wrote:![]()
![]()
You could try extracting .wav and looking at the result in Audacity to make sure your decoding algorithm is correct.
Sir tepples, I had found that thread and used the script. It works wonders, should be stickied!
I had been opening a hex dump in notepad++ and using a macro to insert a zero every other character, then importing it in a hex editor. I knew I should have used a script but I've only written one before that accesses files.
I think the playback is correct. Here's that section:
Code: Select all
ISR(TIMER2_OVF_vect) {
temp = table[i];
if (shift_count == 0){
PORTD = temp & 0b11110000;
}else{
PORTD = (temp << 4) & 0b11110000;
i++;
shift_count = 0;
}
shift_count++;
TCNT2=66;
if(i==2325){
i=0;
}
}I don't get why TCNT2 wants 66. My thinking is this: 16MHz(clock)/32(counter prescale)= 500,000/5265hz= 95; 256-95=161. That way the counter is loaded with 161 and counts 95 before it overflows. Ohwell.
I'm a moron. shift_count never gets read as 0 because it is inced after it gets set to 0. Thanks for making me check my work tepples.
I got compare mode to work though. It's not very well documented on arduinos. You have to read the atmega*8 datasheet and guess what the arduino will call the variables.
It's all fixed and working now.
I got compare mode to work though. It's not very well documented on arduinos. You have to read the atmega*8 datasheet and guess what the arduino will call the variables.
It's all fixed and working now.