Sprite corruption in Street Figther II

37 views
Skip to first unread message

Chris McClelland

unread,
Mar 28, 2012, 9:51:54 AM3/28/12
to UMDKv2 Developers
I read somewhere that Street Fighter II does a lot of VDP DMA, so I
tried it on the prototype with some strange results:

gendev.spritesmind.net/forum/viewtopic.php?t=1102

Chris

Rafael Gama

unread,
Mar 28, 2012, 10:06:53 AM3/28/12
to umdkv...@googlegroups.com

2012/3/28 Chris McClelland <proph...@gmail.com>
I read somewhere that Street Fighter II does a lot of VDP DMA, so I
tried it on the prototype with some strange results:

gendev.spritesmind.net/forum/viewtopic.php?t=1102


This is one kind of strange results I got with my old project. But on its last version, all graphics were working fine. I've tested with a bunch of games. That's why I guess that DMA reads are tighten and more frequent. But we really have to stop this guess working and start measuring things. That's my plans for the upcoming weekend.

The problem is that I haven't made a good documentation of my project. In fact, the only thing I have is some e-mails that I have sent, asking for help, to Charles MacDonald (he has some good docs on megadrive hw here: http://cgfm2.emuviews.com/). I will post a copy of that e-mails here. At least, it's a history log of the result I got.






Rafael Gama

unread,
Mar 28, 2012, 10:13:01 AM3/28/12
to umdkv...@googlegroups.com
*** CPLD old project results #1 (sent on May 02 of 2009) ***

Hi Charles,
 
At about one year has passed since I wrote you an e-mail about my "Genesis asynchronous dram interface" project. It really took me a long time to employ the ideas I had based on the information you gave, as I was really busy with studies/job.

So, here are my results:
 
1) Enabling the $A11000 register:
 
I've noticed a periodic pulse on /CE_0, every ~14us and it is a pretty good 'refresh request signal' for most DRAMs working with CAS-before-RAS refresh.
 
The next step was trying to decode those refresh request pulses from all other pulses (ROM access) on /CE_0. I started wondering about it and thought something like: "If genesis is addressing ROM area AND /CE_0 is asserted, it is a NORMAL access cycle. Thus, if genesis is NOT addressing ROM area and /CE_0 is asserted, its a REFRESH request pulse".
 
So, relying on some genesis addresing pins (A22 and A23) and /CE_0 I wrote something for the DRAM interface's state machine like the HDL pseudo-code that follows:
 
if (A23 == '1' && A22 == '1' && /CE_0 == '0') -> Execute a CBR refresh cycle
else
if (A23 == '0' && A22 == '0' && /CE_0 == '0') -> Execute a NORMAL access cycle
 
It gave good results. I've tested a bunch of games and all of them worked except some games that later I found to be reseting the $A11000 register (Lotus II, Top Gear 2 and others).
 
Anyway, a rigorous test showed that many games freezes after several running hours. It took me to turning on my old Tektronix Type 453 Oscilloscope and analyzing when the CBR refresh cycles were happening. I've dedicated a pin from the interface's CPLD for getting a high level while a CBR refresh was being executed. That analysis made me notice that those refresh events were really crazy. It was possible to trigger the periodic ones (every ~14us) and to watch a lot of difused ones. I felt like I had to change the refresh decoding logic, relying on other signals like /AS, /DTACK, etc but I couldn't get any better result.
 
2) Enabling the $A11000 and getting the 'refresh request' from /CAS_2:
 
As I could read in the forums, /CAS_2 has the same ~14us periodic pulse as /CE_0, even if $A11000 is disabled.
 
Using the same hardware as I described above but using /CAS_2 as a refresh trigger, I got the SAME results.
 
3) Disabling the $A11000 and getting the 'refresh request' from /CAS_2:
 
The system behavior was very similar as the described above but many graphics were messed up (Sprites, background tiles were at most ok). I think that is something related to the graphics loaded by DMA. Probably, if $A11000 is disabled, genesis won't make the DMAs wait for the refresh cycles.
 
So it generates broken graphics but no broken code. Maybe it is the reason why games keep running.
 
4) Enabling the $A11000 and generating an INTERNAL refresh request:
 
Here is the funny part. I've made a timer internal to my interface's dram controller. It generates a refresh request every ~15us and it makes the state machine attaches a hidden-refresh cycle at the end of a normal access cycle.
 
This approach gave me the best results. Everything seems to be really fine: Games did not freeze after several running hours, refresh cycles are where they have to be, graphics are ok.
 
The Problems ?
 
- Refreshes happens as a function of normal access and nothing grants me that genesis will keep accesing ROM to conform the refresh specs.
 
- By DISABLING $A11000, graphics turns into a total mess like in the above approach. It makes me think that DMAs are total evil to those refresh methods.
 
--
 
If you have any idea, please tell me. If you have any clue on how the Super Magic Drive do it, please tell me so.
 
I am wondering if the SMD run its DRAM controller from a clock signal coming from the genesis (VCLK or EDCLK). It would be a great difference from my approach, as i've been running my controller from an external 32 MHz clock for all this time.
 
--
 
Best Regards,
 
Rafael.

Rafael Gama

unread,
Mar 28, 2012, 10:16:27 AM3/28/12
to umdkv...@googlegroups.com
*** CPLD old project results #2 (last result) (sent on Jan 05 of 2011) ***

Hi Charles,
 
I must say sorry for the late reply too :)
 
In fact, the last results from my mega drive DRAM project are the ones reported in my last e-mail.
 
Unfortunatelly I got too busy in the last times.
 
As far as I remember, my best results relied on a self refresh timer approach and just don't make use of $A11000... The concept was trying to fit both normal access cyles and refresh cyles into the 68000's timing requirements.
 
Here is a pseudo hardware behavior description:
 
There is a timer, it will set a flag every refresh period (~15us).
 
If (timer flag) then do a refresh cycle; else
If (mega drive access) then do a read cycle; else
If (timer flag) and (mega drive access) then do a read cycle followed by a refesh cycle.
 
Only clear the timer flag if the refresh cycle was performed, ir order to perform a refresh cycle that was issued during a mega drive only access.
 
:end
 
Anyway the system fails in some DMA access cycles. I think that it happens because DMA cycles doesn't leave any space between the reads, thus my logic is not able to insert a refresh cycle during the entire DMA access. So, at first sight, system behavior is good. But if you leave a game running for 4 hours, it will surelly crash. An incremental data loss happens.
 
At this time I don't remember why I gave up with the $A11000. I just remember that I found some games that writes to that register turning it off. So, enabling it on my BIOS was useless. A friend that was helping me on that project, wrote a console tool (win32) that would search for that 'disabling code' in the game binary. He made me a list with a bunch of games that will disable that register.
 
 
My intention is to start a new project, generating my own /DTACK. So, it won't be able to run from the cartridge memory area. But I am still not sure If I will be able to interrupt a DMA cycle. I wrill try gathering informationg about the DMA controller.
 
So, it would be great if you could send me that signal list from the SMD. They probably do something really smarter than me :D. I am sure it will give me good ideas.
 
My dram project is poorly documented. But I can send you my verilog codes. Just let me know, if you want it.
 
Hope your new (not anymore) DRAM project is on full production ! :D
 
 
Regards,
 
Rafael.

Rafael Gama

unread,
Mar 28, 2012, 10:18:26 AM3/28/12
to umdkv...@googlegroups.com
In the above e-mails we talk about the SMD (Super Magic Drive).


and a link for its schematic: http://cgfm2.emuviews.com/img/smd-main-v1.png.


Rafael.
Reply all
Reply to author
Forward
0 new messages