jotego / jtcores

FPGA cores compatible with multiple arcade game machines and KiCAD schematics of arcade games. Working on MiSTer FPGA/Analogue Pocket
https://patreon.com/jotego
GNU General Public License v3.0
227 stars 40 forks source link

SF2X/CPS2: launching a core too fast produces visual artifacts #561

Closed SuperKeeks closed 2 weeks ago

SuperKeeks commented 7 months ago

If launching a core very quickly after booting the system, the game shows with visual artifacts. An easy way to repro is to use the bootcore=lastcore option (which launches the game in 10 seconds)

This happens in Street Fighter 2X but it likely affects other CPS2 cores as well.

If waiting 15-20 seconds before launching the core, the issue doesn't happen.

image

image

image

paulb-nl commented 6 months ago

It is not just launching a core too fast. It also happens when loading a certain core before SSF2.

Loading Karnov's revenge in the NeoGeo core will result in massive glitches and flickering in the SSF2 games when loading them afterwards.

Here is a video where SSF2 is working normally and then I start the NeoGeo core: https://youtu.be/N-a2xj3a_v8

jotego commented 6 months ago

The game does not clean up the memories, neither does the hardware. But it should eventually overwrite old values. I wonder if this is related to the game data download being performed through the DDR memory. CPS2 is the only jtcore that uses the DDR download in order to speed up the ROM download. I think the NeoGeo core does it too. Maybe it is related to that. I think you can disable it without recompiling the core by taking away the address="0x30000000" text in the mra file. Could you try that and let me know how it goes, please?

SuperKeeks commented 6 months ago

I tried removing the address text. Game loads much slower, but issue still occurs :(

jotego commented 6 months ago

I tried removing the address text. Game loads much slower, but issue still occurs :(

Thank you

paulb-nl commented 6 months ago

The game does not clean up the memories, neither does the hardware

At least the games test Object and Work RAM so when those tests are finished the RAM should have the same contents every time.

jotego commented 6 months ago

At least the games test Object and Work RAM so when those tests are finished the RAM should have the same contents every time.

That's a good point. But if Ryu's silhouette can be seen in those scenes, there must be some wrong data in memory. It could be a MMR (device register), but I cannot think of something that could produce that silhouette effect

SuperKeeks commented 6 months ago

I've uploaded the issue in video form in case it's useful https://youtube.com/shorts/sNsjTJykaDI?si=7DmcBiZeseXO3Jkh

paulb-nl commented 6 months ago

After some testing I determined that there are no glitches if the first bank (8MB) of SDRAM is cleared before starting the game.

Only clearing 1MB at 0x500000 removes most of the glitches on the left half of the screen. What does the core use at that offset?

jotego commented 6 months ago

Thank you for looking into it. You must be clearing the object RAM, which agrees with the images as what we see is wrong objects (sprites) displayed.

paulb-nl commented 6 months ago

If I interpret your source correctly then Video RAM and Object RAM are at 0x200000 and 0x280000. https://github.com/jotego/jtcores/blob/29b50c1ba50dad2c975a85c2ed8c86a0b8a1d0c3/cores/cps1/hdl/jtcps1_sdram.v#L160-L161

Clearing only those offsets has no effect on the glitches.

I don't know what is at 0x500000. Is it the M68K ROM?

jotego commented 6 months ago

I think those offsets are referred to 16-bit words, whereas you're probably counting bytes. If you multiply by two, 0x28'0000*2=0x50'0000 How are you clearing it? By adding a part in the MRA?

paulb-nl commented 6 months ago

I cleared it with the Menu core. I modified it so I could select which part of SDRAM can be cleared.

Ok so clearing Object RAM helps a bit but does not remove all glitches.

I have found with Mame that this game only clears 0x0000 - 0x1C4F of both Object RAM banks. For 0x1C50 - 0x1FFF it reads the value then writes 0x00 and then writes the old value back.

jotego commented 6 months ago

I cleared it with the Menu core. I modified it so I could select which part of SDRAM can be cleared.

In principle, it is possible to have the MRA overwrite that region on start up. But I am not sure whether it will work with the current core as cores often do address transformations while downloading the MRA data

Ok so clearing Object RAM helps a bit but does not remove all glitches.

Maybe the regular VRAM also has the same problem?

I have found with Mame that this game only clears 0x0000 - 0x1C4F of both Object RAM banks. For 0x1C50 - 0x1FFF it reads the value then writes 0x00 and then writes the old value back.

I would need to check if that part of the object RAM is meant to be special. Maybe the object MMR go there. I do not remember off the top of my head. MMR sometimes cannot be read back and I do not implement the reading. Maybe in this case reading is supported and not implemented (?). I'd need to check it.

paulb-nl commented 6 months ago

Some more testing in Mame:

Filling Video RAM or 0xFF0000 RAM with random values shows no glitches. Filling Object RAM with random values shows massive glitches in Mame like we see in the core. Filling with 0x00 or 0xFF values shows no glitches.

Hyper SF2 also only clears Object RAM up to 0x1C4F but is not affected because it places the 0x8000 last sprite indicator in Object RAM which SSF2 does not.

X-men vs SF clears Object RAM completely.

So it appears that SSF2 expects uninitialized Object RAM to have certain values.

I think the Menu core that I modified is somehow not clearing Object RAM completely when writing 0x00 to 0x500000-0x5FFFFF.

In principle, it is possible to have the MRA overwrite that region on start up. But I am not sure whether it will work with the current core as cores often do address transformations while downloading the MRA data

Clearing Object RAM in the core itself seems like a better idea.

jotego commented 6 months ago

Another example of this issue

jotego commented 4 months ago

I cannot quite reproduce this issue but I have added logic to clear up the object RAM during reset in 581875c0, which follows @paulb-nl findings about this.

Let me know if you see it again. The files will be published next JTFRIDAY.

SuperKeeks commented 4 months ago

Cool, I'll try when I can after it's published and will update this thread with the results. Thanks!!

paulb-nl commented 4 months ago

I wanted to test the updated core but the cores update on friday were built from commit 4f7da4b which is from May 11th, before you committed the fix.

jotego commented 4 months ago

@paulb-nl you can use this one to test it:

jtcps2.rbf.zip

paulb-nl commented 4 months ago

Thank you for the test build. Unfortunately the issue remains.

Looking at your fix, it seems you are clearing a copy of the Object RAM which is in BRAM. BRAM is always cleared to 0 during loading of the FPGA bitstream so that is not needed.

What needs to be cleared is Object RAM in SDRAM: https://github.com/jotego/jtcores/blob/299bb31e7b50d78d023ac5409893dce1199640a4/cores/cps1/hdl/jtcps1_sdram.v#L269-L273

Reproducing this is easy. Load Karnov's revenge in the Neo Geo core and then load SSF2.

jotego commented 4 months ago

I see. Thank you. I will tackle this when executing #511 then as it will be easier to do when full SDRAM framework is used.

jotego commented 3 weeks ago

The RAM clear logic added in https://github.com/jotego/jtcores/commit/581875c01f8a2794e9d122afdf1ab0c17ba156d8 was faulty and it was not erasing all memory addresses. I will fix the logic and verify this issue again.

jotego commented 3 weeks ago

I think 11b7750509f68877a731d8ff33f490a79534e749 fixes this issue by correctly clearing the RAM

paulb-nl commented 2 weeks ago

Not fixed with jtcps2 v324111a.

Looking at your SDRAM clearing I see that SLOT0 is erased. SDRAMW = 23, SLOT0_AW = 17, slot0_offset = main_offset.

I assume that during reset main_offset defaults to VRAM_OFFSET which is 0x20_0000 https://github.com/jotego/jtcores/blob/11b7750509f68877a731d8ff33f490a79534e749/cores/cps1/hdl/jtcps1_sdram.v#L212-L213

erase_cnt is 17 bits = max 0x1_FFFF so this will only clear 0x20_0000 to 0x21_FFFF and it does not clear OBJECT ram. https://github.com/jotego/jtcores/blob/a6cbc3c93a976a6a5eb98ce3102322e4be340e96/modules/jtframe/hdl/sdram/jtframe_ram_rq.v#L88-L89

Object RAM (ORAM) offset is 0x28_0000 with AW=13 so 0x28_0000 to 0x28_1FFF. https://github.com/jotego/jtcores/blob/11b7750509f68877a731d8ff33f490a79534e749/cores/cps1/hdl/jtcps1_sdram.v#L162 https://github.com/jotego/jtcores/blob/11b7750509f68877a731d8ff33f490a79534e749/cores/cps1/hdl/jtcps1_sdram.v#L270-L274

jotego commented 2 weeks ago

Thank you @paulb-nl for the detail account. I have implemented it in e787541dd28c30798cb6e736a4b4d65e915f6dea

jotego commented 2 weeks ago

could you please test this new one? jtcps2.rbf.zip

paulb-nl commented 2 weeks ago

Thanks Jotego, that one works well.

The comments you have added in the commit are kind of unclear. It seems you forgot to say that the 3 extra bits are for erasing only. https://github.com/jotego/jtcores/blob/e787541dd28c30798cb6e736a4b4d65e915f6dea/cores/cps1/hdl/jtcps1_sdram.v#L220-L222

jotego commented 2 weeks ago

Thank you for all your help @paulb-nl and to everyone else for testing and proposing the change. This is a change that I would not have done without the push of the community.

I changed the code comment to

    // Top 3 bits of main_addr_x are always zero, but needed to set the
    // SLOT extension to cover the ORAM/VRAM_OFFSET during the on-reset erase

I will publish the new file on Friday.