It is currently Tue Nov 20, 2018 5:35 pm

All times are UTC - 7 hours



Forum rules





Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sat Nov 10, 2018 7:40 pm 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
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.


Top
 Profile  
 
PostPosted: Sat Nov 10, 2018 9:54 pm 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3584
Location: Indianapolis
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.


Top
 Profile  
 
PostPosted: Sun Nov 11, 2018 9:59 am 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
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.


Top
 Profile  
 
PostPosted: Sun Nov 11, 2018 7:14 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20789
Location: NE Indiana, USA (NTSC)
For SPC700, I use a ca65 macro pack written by blargg.


Top
 Profile  
 
PostPosted: Sun Nov 11, 2018 7:20 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6961
Location: Canada
Thanks for that example, Memblers! Also for the link to that thread, tepples.


Top
 Profile  
 
PostPosted: Sun Nov 11, 2018 11:12 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2774
How are you going to get around having different PPU registers?


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 3:44 am 
Offline
Site Admin
User avatar

Joined: Mon Sep 20, 2004 6:04 am
Posts: 3584
Location: Indianapolis
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.


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).

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.

psycopathicteen wrote:
How are you going to get around having different PPU registers?

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.


Attachments:
TASM700.zip [2.13 KiB]
Downloaded 15 times
Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 4:29 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3694
Location: Mountain View, CA
Other SPC700 assembler possibilities include xkas-plus (see Releases tab for Win32 binaries), or bass. One would have to port the code from TASM to one of the aforementioned. That said: this thread made me happy to see classic TASM getting a shout-out.


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 4:36 am 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
psycopathicteen wrote:
How are you going to get around having different PPU registers?
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.


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 6:43 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20789
Location: NE Indiana, USA (NTSC)
Is this anything like upernes?


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 8:01 am 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
tepples wrote:
Is this anything like upernes?

I only took a quick look at upernes, upernes is a static recompiler while mine is a dynamic recompiler.

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.


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 10:24 am 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2774
How do you tell the difference between a STA $2007, and data that resembles a STA $2007 instruction?


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 12:01 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10977
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Nov 12, 2018 12:12 pm 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
psycopathicteen wrote:
How do you tell the difference between a STA $2007, and data that resembles a STA $2007 instruction?

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.

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.


Top
 Profile  
 
PostPosted: Mon Nov 19, 2018 12:04 am 
Offline

Joined: Sat Nov 10, 2018 2:49 pm
Posts: 7
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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: ndiddy and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group