Need sound help emulating NES on SNES
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Need sound help emulating NES on SNES
This summer, I started making a NES emulator running on base SNES as a challenge (no additional processor in game cart).
CPU and PPU emulation are near perfect. I am starting to look into sound and mappers (not all mappers will be supported).
I tried searching for tutorials for both SNES and NES sound but they all seem incomplete. I understand the communication ports and the instruction set for the APU but I'm completely lost when I read anything about playing a sound sample.
CPU and PPU emulation are near perfect. I am starting to look into sound and mappers (not all mappers will be supported).
I tried searching for tutorials for both SNES and NES sound but they all seem incomplete. I understand the communication ports and the instruction set for the APU but I'm completely lost when I read anything about playing a sound sample.
Re: Need sound help emulating NES on SNES
Sounds cool. I took a peek at my old SPC code, and it does something basically along these lines:
init:
1: set up a "sample directory"
2: disable ADSR, set gain, main volume, and key-on all channels
play:
1: when duty cycle changes, set new sample #, then key on
2: otherwise, I only write DSP regs for frequency and volume (regs $x0, $x1, $x2, $x3)
Code is in spc.asm if you want to take a peek. http://membler-industries.com/SNES/2a03-src.zip
One problem with my code is that the interpolation totally ruins the sharp edges of the waveforms. IIRC it was _mic who later released a sound emulator showing you can get a cleaner sound by using a set of larger samples played at the highest rates possible, as it will be affected less by the interpolation. My player just had one short sample per waveform that gets scaled over the entire NES frequency.
init:
1: set up a "sample directory"
2: disable ADSR, set gain, main volume, and key-on all channels
play:
1: when duty cycle changes, set new sample #, then key on
2: otherwise, I only write DSP regs for frequency and volume (regs $x0, $x1, $x2, $x3)
Code is in spc.asm if you want to take a peek. http://membler-industries.com/SNES/2a03-src.zip
One problem with my code is that the interpolation totally ruins the sharp edges of the waveforms. IIRC it was _mic who later released a sound emulator showing you can get a cleaner sound by using a set of larger samples played at the highest rates possible, as it will be affected less by the interpolation. My player just had one short sample per waveform that gets scaled over the entire NES frequency.
Re: Need sound help emulating NES on SNES
Wow, thanks. This looks like exactly what I need.
Are there instructions on how to download the assembler for the SPC-700?
I am using my own assembler for the 65816 and worst case scenario I can adjust it to support the SPC-700.
I don't plan on modifying the SPC code if it already works as intended.
Are there instructions on how to download the assembler for the SPC-700?
I am using my own assembler for the 65816 and worst case scenario I can adjust it to support the SPC-700.
I don't plan on modifying the SPC code if it already works as intended.
Re: Need sound help emulating NES on SNES
For SPC700, I use a ca65 macro pack written by blargg.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Need sound help emulating NES on SNES
Thanks for that example, Memblers! Also for the link to that thread, tepples.
-
- Posts: 3140
- Joined: Wed May 19, 2010 6:12 pm
Re: Need sound help emulating NES on SNES
How are you going to get around having different PPU registers?
Re: Need sound help emulating NES on SNES
I used "Table-Driven Assembler" (TASM), which was the only option at the time. It's a DOS program, so if you're using something like Win7 64-bit, you'll have to run it in DOSbox. I've attached the SPC700 definition file for it. Command to assemble is "tasm -t700 -b -a spc.asm" (outputs to spc.obj).Myself086 wrote:Wow, thanks. This looks like exactly what I need.
Are there instructions on how to download the assembler for the SPC-700?
I am using my own assembler for the 65816 and worst case scenario I can adjust it to support the SPC-700.
I don't plan on modifying the SPC code if it already works as intended.
If you want to use the code, you're certainly welcome to. The upernes emulator uses it. https://forums.nesdev.com/viewtopic.php?f=3&t=13229
I had thought about going back to it and improving the sound quality (using longer samples like I mentioned previously), but unfortunately I wasn't able to build a windows version of upernes (it was developed for linux), so I didn't take the idea any further.
It does work well for what it does, but there are several things it doesn't even attempt to do:
-no DPCM channel
-no periodic noise
-frame counter alternate timing is ignored (I'm not sure if games really used this, anyways it was usually omitted from NSF rips back at the time anyways)
-doesn't reset pulse phase when $4003 or $4007 is written
Also, the length counter emulation (60hz rate) is done on the 65816 side. SPC does linear counter (240 hz), and sweep register (120hz). It uses timers for those, not sure if I was worried about the SPC getting bogged down, or if I ran out of timers, or what. If you look through that upernes thread, I explained a little more about how it works.
I'm curious too. Presumably it's static recompilation (like replacing register reads/writes with a JSR), which has it's own challenges, but any other way seems pretty difficult.psycopathicteen wrote: How are you going to get around having different PPU registers?
- Attachments
-
- TASM700.zip
- (2.13 KiB) Downloaded 499 times
Re: Need sound help emulating NES on SNES
This is a dynamic recompiler emulator which means each function is translated into native code for the Snes at runtime. Some opcodes and IO ports yield different instructions than in the original code. IO ports become JSL to code that emulates them (except gamepad). Some ports are slower to emulate than others, mostly writing to Vram.psycopathicteen wrote:How are you going to get around having different PPU registers?
Re: Need sound help emulating NES on SNES
I only took a quick look at upernes, upernes is a static recompiler while mine is a dynamic recompiler.tepples wrote:Is this anything like upernes?
This means that recompiling is done by the Snes itself which has pros and cons.
I only tested SMB so far. First playable version ran the intro at about 15% but now it runs the intro at just over 200% (if uncapped). Sprite 0 is emulated but bit 8 of scrolling seems to have some conflicts for the top part (flickers). The SMB logo is missing in the intro.
I should start a proper thread for this emulator, I was only looking for sound help here.
-
- Posts: 3140
- Joined: Wed May 19, 2010 6:12 pm
Re: Need sound help emulating NES on SNES
How do you tell the difference between a STA $2007, and data that resembles a STA $2007 instruction?
Re: Need sound help emulating NES on SNES
I suppose you could recompile only the parts that the PC actually hits (possibly causing slowdown the first time they're executed), or you could keep a copy of the original ROM to use exclusively as data in read operations... The real challenge IMO is self-modifiable code, but thankfully I don't think that's very common in NES games.
Re: Need sound help emulating NES on SNES
It only reads whole instructions, it starts from the entry point of the function and reads until something ends the execution (rts, jmp, beq+bne not recognized yet). Branches and jumps within the same bank will be recompiled as part of the same function.psycopathicteen wrote:How do you tell the difference between a STA $2007, and data that resembles a STA $2007 instruction?
It may derail sometimes but the new code will never affect data, if you attempt to read the STA $2007 by using LDA it will return just that. But during execution, PC register never points to the original addresses. If your code is at $90CC then PC could be at $7F0219 executing a translated copy.
Re: Need sound help emulating NES on SNES
I decided to implement the SPC instruction set into my personal assembler. The syntax is very close to the original and 2 incomplete lines threw errors. I used the binary from upernes to compare builds.
I optimized part of the CPU code while porting to my assembler. I lost about 2500 cycles per frame and I'm not even doing 240 hz updates yet, it looks like 240 hz were on CPU side because calling emulate_length_counter 4 times in a row fixed most length issues. I don't know how much free time the SPC has but I'd like to move as much code as possible over there. Possibly even transfer data using HDMA.
It sounds kinda bad, I haven't tried upernes but I'm guessing part of my code isn't right.
I sent the Rom to 2 friends and they couldn't get sound to work on various Snes emulators nor console. Either the sound wasn't working or black screen. Which tells me my first uploader is wrong. Sound worked on snes9x v1.53.
EDIT: Here's a clip from a friend after some fixes https://youtu.be/Kvs9MQyCi_s
I optimized part of the CPU code while porting to my assembler. I lost about 2500 cycles per frame and I'm not even doing 240 hz updates yet, it looks like 240 hz were on CPU side because calling emulate_length_counter 4 times in a row fixed most length issues. I don't know how much free time the SPC has but I'd like to move as much code as possible over there. Possibly even transfer data using HDMA.
It sounds kinda bad, I haven't tried upernes but I'm guessing part of my code isn't right.
I sent the Rom to 2 friends and they couldn't get sound to work on various Snes emulators nor console. Either the sound wasn't working or black screen. Which tells me my first uploader is wrong. Sound worked on snes9x v1.53.
EDIT: Here's a clip from a friend after some fixes https://youtu.be/Kvs9MQyCi_s