It is currently Sun Oct 22, 2017 5:09 am

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 14 posts ] 
Author Message
PostPosted: Wed Nov 30, 2016 5:12 pm 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
I figured this may be the right forum to post in:
The goal is to get "real" save states working on SNES Hardware (as a feature of my current project) and I cannot figure out a way to know the state of the APU (Memory content and registers) when it is running any uploaded software.
I use an FPGA in this project, so I potentially have a fair amount of options. But I would like to keep this as simple as possible/needed.
There seems to be no way to interrupt the processor if I don't know how any music engine processes data on the APU Ports (SNES $2140-2143). One solution would be to patch the music engine somehow. I thought of intercepting the /RESET Line of the SMP and getting it to boot it's IPL ROM in order to upload some custom code to get the RAM contents, but this has two problems:
1) I would need some space for the code, which would overwrite data (and writing it to the stack is apparently not an option, because some music engines move the stack pointer randomly to store and retrieve buffered data for whatever; Donkey Kong Country 2 does this).
2) The register contents (A, X, Y, Stack Pointer and Processor Status) would be lost
So this is likely not the solution.
Another solution would be to just get the APU synthesized on the FPGA and use that instead of the original one. But this would be overkill (I guess).
Where is the IPL ROM actually stored? Is it part of the SMP or the DSP? Maybe I could map in a custom IPL that would be executed when resetting the processor, so I could get the data unchanged.
Are there any other ideas to pull all the data from the APU?
And what should consider when attempting to get the state of the APU (could the Internal Timers be a potential problem? Or the DSP Echo Register?)


Top
 Profile  
 
PostPosted: Wed Nov 30, 2016 5:35 pm 
Offline
User avatar

Joined: Wed Feb 13, 2008 9:10 am
Posts: 578
Location: Estonia, Rapla city (50 and 60Hz compatible :P)
Apart from emulating the thing I'm not seeing how you can know or restore the state (but I am no expert), the thing is really self contained and very much invisible to the external world.
Boot ROM lives inside the SMP, you can capture DSP writes by sniffing the bus in the SPC module, but SMP internal regs you'll not be able to capture like that. With more invasive mod you could possibly feed the SMP your own data to make it execute your code and that way spit out its registers and later on load up all data in same manner but that requires whole bunch of soldering and couple additional mods for interception.

_________________
http://www.tmeeco.eu


Top
 Profile  
 
PostPosted: Wed Nov 30, 2016 5:45 pm 
Offline
User avatar

Joined: Sat Oct 04, 2014 3:48 pm
Posts: 34
Funny that you posted. I've created FPGA/CPLD hardware in the past that has performed load/save states on console (SNESTap, 21FX) and im working on a final variant 21FX-Toploader (MITM style cart): https://pbs.twimg.com/media/Cx2Lf0XXcAA4q3L.png , boards come in sometime this week.

I've learned to just give up on the APU and patch in solutions per game. I don't think its worth creating your own APU on FPGA and overriding the sound, but there is an open source implementation on FPGA of one. You could passively capture the APU load stream with the FPGA and on a load state reset the whole system and reload the all memories including the WRAM/PPU/APU... the only issue is that some SPC implementations keep a running sequence count with the program code. If your sequence counts don't match it could cause lockup. Every SPC implementation could be different.

So my strategy is to basically do what GameSaver currently does which is basically don't touch the APU at all and retain APU sequence count state on load state of a game. However these sequence counts are located in different memory addresses depending on the game implementation. This is why GameSaver has you input patch code on boot depending on the game you are playing.

Edit:

21FX load state example w/yoshis island: https://twitter.com/defparam/status/727012094206468096 (had to serialize SuperFX state)
21FX load state example w/SMW: https://twitter.com/defparam/status/727010513360699392


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 8:16 am 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
@TmEE
I came to the same conclusion, but I thought there was a kind of workaround to get to the SMP data easier. I guess recreating the APU on the FPGA might be the way to go in order to get savestates fully working.

@defparam
I remember seeing your project some time ago, nice work so far. I guess you have looked into solutions to get the APU data without touching internal hardware of the SNES? I would go as far as intercepting the SMP databus, but this does actually too bear some problems, so going for APU recreation on the FPGA may be the only way.
I dont think it would be worth to put all the effort towards patching every game in order to get the APU data, this would require a load of work that could be put towards implementing the FPGA APU.
Capturing the data stream is also not an option so far because I would need a load of memory to keep that stream somewhere.
I also think that serializing the data port streams of the APU (and any other external hardware processor) is not the best solution for savestates because these external processors execute their code more or less independent of the SNES, so the execution time of the code for those processors play a role too (unless I misunderstood what is actually done in order to restore for example the SuperFX state).

The FPGA APU would work from the cartridge port without any mods, you actually just need to reset the /MUTE Bit in the original APU control register and then put it in an endless loop (or let it execute STP Instruction) which will stall it until the next reset, then just snoop on SNES $2140-2143 with the the FPGA APU (at least I guess this would not cause any issues). That would be the way I would implement the FPGA APU.
I would actually even scrap the idea of getting savestates working for now, it would kind of suffice to just halt the SMP until an interrupt occures (like the SNES WAI Instruction halts the CPU until an Interrupt occurres). Would that somehow be possible? Could I just supply the APU with a custom clock signal from the FPGA and hope register contents of the SMP and DSP are kept for an indefinite time? Has anyone tested this?
The documentation on the SNES APU Hardware and Pins is kind of scarce which makes it hard to know what is actually possible and what not...


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 9:11 am 
Offline
User avatar

Joined: Sat Oct 04, 2014 3:48 pm
Posts: 34
Quote:
...The FPGA APU would work from the cartridge port without any mods, you actually just need to reset the /MUTE Bit in the original APU control register and then put it in an endless loop...


Fair enough, if that is the case then what I would do is look into creating either 1) an FPGA "Man in the middle" cart or 2) a flash cart like SD2SNES. The CART port already has AUDIO L/R pins to on board sound mixing. What your cart would do is when it loads a game ROM is have it redirect all APU read/writes from $2140-$2143 (SNES APU Range) to $2184-$2187 (unmapped expansion). Your FPGA APU will sit on $2184-$2187 doing exactly was an APU does and you can have your DAC feed audio to sound mixer through those CART audio pins while the real snes APU stays untouched the whole time (and presumably mute). Then on your FPGA you have visibility to your SMP processor and can serialize things to your hearts content. With my MITM cart I decided to leave the audio pins alone, however for true APU emulator-like load/save state I may look doing what I just mentioned in the future prehaps.

In the case of SD2SNES or making a cart similar to it. The SD2SNES feeds audio to those cart audio pins for MSU-1 support (I believe). That cart hardware may be already set up to test my theory from above. The only limitation would be the FPGA size. I doubt there is much room to add an emulated APU + memory to store save state + etc...

Edit: corrected addresses

Edit2: Or better yet, you don't need a fully emulated APU on your FPGA and a DAC to mix sound in via cart. Just keep a 6502 implementation as a "shadow" APU on the FPGA, use the actual APU on the console no need to redirect $2140-$2143 and all your "shadow" APU is doing is monitoring reads/writes to the real APU on the "B" bus and rendering an exact replica of processor flags/state and APU RAM so that you don't need to extract any state from the real APU. In your shadow APU you have everything you need to get back to a functioning state. At that point since you have all your data.. on load state just trigger the console /RST pin and now you are in IPLROM to serialize in your rendered shadow APU state along with all the other memory states. The only gotcha maybe would be how you align back the processor and register flags on the real APU... you may need some unallocated APU RAM to do so ... :/


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 10:40 am 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
@defparam
The Idea in Edit2 actually sounds really good. I could just implement the SPC700 processor part and ditch the DSP (i could use an existing 6502 core as the base, but there are additional conditions needed to be worked in, in order to replicate the SPC700). It would need to keep track of the registers and timers, but nothing more.
Question is, when the DSP's echo is enabled, it would essentially rewrite the memory, how would I prevent that? Just pull the DSP /RESET Line low and everyone is happy?
Just an info to my project, it will be like an MITM, but it will be internally built into the SNES. The idea is to be able to play original cartridges, but also be able to load games off an SD Card. Imagine it like the SuperUfo8 Pro (which kinda inspired this idea), it allows for playing either a cartridge inserted or play a ROM from an SD Card. There are also a load of other features I am going to implement, like savestates, hence the topic.
Currently I am intercepting the /RD, /WR and /IRQ signal of the CPU to the Cartridge to decide whether the FPGA or the Cartridge is being mapped on Bus A.

I see that I could potentially map in FPGA BRAM instead of the APU RAM at will, have it store my own program, and when the SMP is reset, I would make it just jump from the IPL to my FPGA RAM, from where it executes my own transfer scheme to map APU RAM anywhere.
for example I can see mapping 32k of APU RAM + IPL in the upper half; $8000-$FFFF, and the FPGA RAM is mapped in $0000-$7FFF, that way I only need to intercept the APU RAM CE Lines to enable either the lower or upper APU RAM memory-half. I can map some FPGA Register to the lower half on the SMP Bus, and use it to control whether to map in FPGA memory, which of the 32k halfs are supposed to be mapped, or restore normal behavior again.
Something that would need to be sorted out is getting the timers back to their initial value, but that should be fairly easy to do, maybe some cycle counted loop which sets the timers in a manner that they would after some time reach their initial value. Luckily they are 8 Bits only, so there is no perceivable waiting time in order to get them restored.
This solution is then only going to work on the older SNES models with the APU components seperated. For full compatibility, I guess there is no way around getting the full DSP onto the FPGA.

to the other part you wrote, I dont think it would be easy to just redirect the writes from $2140-2143 to somewhere else by just evaluating the rom. you have to assume that the program uses indirect addressing to access the APU ports (or very unlikely use DMA), so that would fall off as a solution. Or like before mentioned, you would need a patch for every game to redirect any APU access.
The SD2SNES actually does feed the Audio Pins on the Cartridge Bus, and it should also be possible to get a full APU running on it without any further hardware requirements. This would allow true savestates on the SD2SNES (if they are not implemented yet).


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 11:33 am 
Offline
User avatar

Joined: Sat Oct 04, 2014 3:48 pm
Posts: 34
OK! well good luck on your architecture. I'm curious of your findings as you progress. I think a number of these implementations are worth looking into at some level. For me I think I may not pursue a "one size fits all" APU load/save solution, most likely i'll figure out solutions per ROM as needed.

Quote:
to the other part you wrote, I dont think it would be easy to just redirect the writes from $2140-2143 to somewhere else by just evaluating the rom. you have to assume that the program uses indirect addressing to access the APU ports (or very unlikely use DMA), so that would fall off as a solution. Or like before mentioned, you would need a patch for every game to redirect any APU access.
The SD2SNES actually does feed the Audio Pins on the Cartridge Bus, and it should also be possible to get a full APU running on it without any further hardware requirements. This would allow true savestates on the SD2SNES (if they are not implemented yet).


Good point, to perform such a redirection would be ROM specific. If you are just modifying 1 console then you could achieve that by cutting and proxying the /PARD /PAWR lines through the FPGA. Also, I don't believe DMA is used to communicate to the APU. If you look at the IPLROM disassembly it is a bi-directional handshake to transfer a single byte from the CPU to the APU.


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 12:24 pm 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
defparam wrote:
Also, I don't believe DMA is used to communicate to the APU. If you look at the IPLROM disassembly it is a bi-directional handshake to transfer a single byte from the CPU to the APU.

Even though many games would use the IPLROM to transfer Blocks of data, there is still the possibility of implementing your own upload and download routines for the SMP. As long as it is not 100% proven that all official games use the "common-sense" way of transfering data (N-SPC APU driver by Nintendo), I assume the craziest ways too (so using DMA in some crazy way to transfer data just because why not) :D


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 1:07 pm 
Offline
User avatar

Joined: Sat Oct 04, 2014 3:48 pm
Posts: 34
Quote:
Even though many games would use the IPLROM to transfer Blocks of data, there is still the possibility of implementing your own upload and download routines for the SMP. As long as it is not 100% proven that all official games use the "common-sense" way of transfering data (N-SPC APU driver by Nintendo), I assume the craziest ways too (so using DMA in some crazy way to transfer data just because why not) :D


I agree that ROMs (post IPL load) can implement their own communication mechanisms between the CPU/APU. But the reason why DMA won't work and the reason why the IPLROM is a bi-directional hanshake is because the CPU and APU 1) are on different clock domains and 2) you aren't directly accessing memory, you are writing to an APU register and having the APU process it and store it into RAM at some point. With DMA you can't backpressure the DMA engine, so if the APU didn't get enough time to store/process the byte from one access the DMA engine will immediately clobber it on the subsequent accesses. As a result I don't think you'll find any ROM that will DMA into the APU, unless it is for a transfer length of 1 (which is pointless?)


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 1:09 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6294
Location: Seattle
There are proofs-of-concept that use HDMA to transfer data to the APU.


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 1:13 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19115
Location: NE Indiana, USA (NTSC)
In particular: 93143 explains how HDMA to the APU would work. The receiving loop runs once per scanline.


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 1:20 pm 
Offline
User avatar

Joined: Sat Oct 04, 2014 3:48 pm
Posts: 34
ah thanks for the example, I stand corrected! That must be some really tight timing and short strides :) in any case back to the original point. If you were to redirect a non-DMA APU access you could perform the same re-direction on a DMA APU access (via /PARD /PAWR proxy or ROM patching).


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 1:32 pm 
Offline
User avatar

Joined: Sat Dec 01, 2012 4:10 am
Posts: 65
nice example, so this actually does exist (even though its just a proof-of-concept).
But you are right defparam, when intercepting the /PARD and /PAWR signals on the hardware side, it wouldnt matter anyways how data is transferred.


Top
 Profile  
 
PostPosted: Thu Dec 01, 2016 6:19 pm 
Offline

Joined: Fri Jul 04, 2014 9:31 pm
Posts: 788
I wouldn't call my method a proof-of-concept, since it hasn't been run or even assembled, at least not by me (I did use the term for the time-delay code snippets, but they're simple enough to be judged by inspection).

But N-Warp Daisakusen is an actual complete game that uses HDMA to stream audio, and, like my method, its APU-side streaming engine can receive 4 bytes per scanline.

(Unlike my method, it dumps the data to the stack during the transfer, which means it has to be picked back up and put in the correct location afterwards; I presume this is to maximize the timing tolerance. My method takes a bit more time during the transfer loop to put the data where it belongs in the first place, theoretically resulting in better average bandwidth, but as a result I have to be much more careful with the exact length of the time-delay code, possibly resorting to measuring the CPU/APU clock ratio at boot...)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: kogami and 4 guests


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