GP2X Spc700 Asm Core


notaz

Certified Guru
Joined
Aug 23, 2005
Messages
4,913
Location
Lithuania
Website
notaz.gp2x.de
Hi,

Some of you may remember me after my Cyclone hacks. This time I did some more coding in ARM asm and rewrote the SPC700 emulation code (spc700.cpp) in asm. For those who didn't know SPC700 is CPU-like chip, which runs @~1MHz (which is not very far from main CPU speed) and controls the DSP in SNES. I wrote it while working on my SNES emu for Symbian UIQ phones, which is also derived from Yoyofr's OpenSnes9xGP.

Unfortunately it didn't improve performance as much as I expected, because Snes9x does too much sync between main CPU and SPC700 and the SPC700 context is constantly saved/loaded (so the idea of loading all frequently used stuff into registers and running for a while (like it is done in Cyclone/DrZ80) didn't work). Here is some comparison data (just don't laugh as it is from 156MHz phone which is doing GSM stuff in background and doesn't have fast screen access, etc.):

Avg FPS C code vs asm:
Super Mario World: ~10 vs ~15
Contra The Alien Wars: ~3.5 vs ~ 5.5
Final Fantasy VI: ~1 vs ~2.5 :unsure:

Adding some syncronization hacks gives another ~4fps, but breaks some games (added as an option in my emu).

Anyway, perhaps either Reesy or Squidge could take a look at the source code. Don't know if it would give any benefit, this was a (failed?) attempt to return something to GP32/GP2X community for their output to ARM based device world.
 
A speed gain is a speed gain, every little helps.

Thank you so much for working on this for free - i'm sure it will be put to good use!
 
notaz posted on Apr 1 2006 at 12:48 AM said:
Hi,



Avg FPS C code vs asm:
Super Mario World: ~10 vs ~15
Contra The Alien Wars: ~3.5 vs ~ 5.5
Final Fantasy VI: ~1 vs ~2.5 :unsure:

Adding some syncronization hacks gives another ~4fps, but breaks some games (added as an option in my emu).

Looks like a good improvement to me. 5 FPS here and there is always nice.

Thanks for the good work. I hope it will be put to use.
 
Last edited by a moderator:
DaveC posted on Mar 31 2006 at 08:50 PM said:
Looks like a good improvement to me. 5 FPS here and there is always nice.

Is it a 5 fps gain or is it a 50% gain? Does the gain scale?
 
Last edited by a moderator:
I have tried hus UIQ port and is pretty impressive with the specs of the machine (Arm9 156Mhz, 320x208 screen and some background processes for the phone itself)
I'm sure that these results will be better for the gp2x or even the gp32.
 
percentage wise thats bloody good stuff,

considering the laws of diminishing returns and all that, thats great work considering it was on a 156Mhz phone
 
Sounds very impressive to me, at least. Even if it doesn't scale very much. Although looking at the games' before and after framerates, it would seem to rather well... ratios look relatively consistent (although I imagine it would scale less well as framerates improved).

Nonetheless, any ARM ASM cores bring the reality of perfect snes closer, and more to the point, at least make it more certain whether it'll be achieved or not...
 
thanks notaz. I just threw away my wasted Motorola A920 (UIQ Phone) and I never heard about a SNES port, but it sounds hella impressive.

It'll be interesting to see what happens with UIQ 3.0 phones, as they have much simular hardware to the gp2x. I think there is a preference for a TI ARM9 reference board.

It'd be interesting to see if the SDL libs for UIQ 2.1 will be ported to 3.0.
 
Great work if those numbers are for real, if those are for the full emulator running and not only the sound engine, you must have done an awesome job =)
But still, I just took a quick look at the source and saw some things to optimise in the first functions. :p

Code:
// pushes reg, trashes r1
static void Push(char *reg)
{
	ot("  add   r1,spc_ram,spc_s\n");
	ot("  add   r1,r1,#0x100\n");
	ot("  strb  %s,[r1],#1\n", reg);
	ot("  sub   spc_s,spc_s,#1\n");
}
Can probably be optimised to:
Code:
	ot("  add   r1,spc_ram,spc_s\n");
	ot("  strb  %s,[r1,#0x100]\n", reg);
	ot("  sub   spc_s,spc_s,#1\n");
Or do you need r1 to be increased with 1 after the write?
If you haven't looked at the source to PocketSPC you can download it here, I haven't looked at that source so it might be possible to optimise further though.
 
An important thing to note is that 10 FPS->15 FPS isn't going to be a 5 FPS gain on the GP2X ... that is a 50% gain over the original performance level on the described phone hardware. It's very likely the performance gain would be greater than that. Not necessarily 50%, but likely more than 5 FPS. ;) The 65c816 isn't a very powerful processor and it's not that demanding to emulate with a fast ASM core, the main stressors are the video and audio processing. This could be just the boost needed to take SquidgeSNES from requiring 1-2 Frameskip to run at/near 60 FPS, to being just 1 or *0* Frameskip in many games.

Excellent work and thank you for the fine contribution. I'm sure much good'll come of it. :)
 
notaz posted on Apr 1 2006 at 01:48 AM said:
this was a (failed?) attempt to return something to GP32/GP2X community for their output to ARM based device world.
Failed?

Failed?

Are you mad?

This is awsome, thanks very much. An extra ASM core in an emulator is NEVER a bad thing :)
 
Last edited by a moderator:
FluBBa posted on Apr 2 2006 at 07:05 PM said:
Can probably be optimised to:
Code:
	ot("  add   r1,spc_ram,spc_s\n");
	ot("  strb  %s,[r1,#0x100]\n", reg);
	ot("  sub   spc_s,spc_s,#1\n");
Yes, you're right here, this was because I was rewriting C code and forgot about the power of ARM addressing modes.. Also the division algo is dumb and needs to be rewritten.

FluBBa posted on Apr 2 2006 at 07:05 PM said:
If you haven't looked at the source to PocketSPC...
Oh, so there was asm SPC core already.. I should better do more research next time. Had a quick look through the source, looks good, although it is using some stuff from the DS library.
 
Last edited by a moderator:
ok, looked through the addressing stuff and updated the source code. Also added proper division code from Cyclone.

Looked at PocketSPC core again and I think Garry did a better job with it. Don't know what to take from there though, it is written with different logic in mind..

Reesy, if you are implementing this you most likely noticed I changed a lot of stuff in my port. Most of the changes are unrelated to sound core, I was experimenting around, trying to squeeze some performance out. Here is what I what I would do when implementing:
  • Update SIAPU struct in apu.h
  • Update spc700.* files
  • Move the APU cycle count from struct SAPU -> SCPUState and update all related code to reflect this. This way it will be easy to access it from yoyofr's core.
  • In os9x_65c816, replace calls asm_APU_EXECUTE to spc700_execute. See how to calculate cycles in my code.
  • Update snapshot.cpp for savestates.
and that should be enough.

I am also interested how will it do on "good" hardware like GP2X. I noticed that memory access is very slow in my phone. The reduction of that gave ~30-50% increase there, but it can be much less in GP2X as I assume it has much faster memory.
 
Back
Top