Exploring CCPS and the CPS Arcade Platform: Emulation Challenges and Audio Analysis

I’ve been intending to discuss CCPS here on Retro RGB for some time, but I hesitated until I gained some hands-on experience.

CCPS is an SDK created by Fabien Sanglard for the renowned Capcom CPS arcade platform—the one featuring games like Final Fight, Ghouls’n Ghosts, Strider, and, of course, Street Fighter II, among others.

Fabien developed this impressive SDK as a direct outcome of his investigations while writing the Book of CP-System. I highly recommend reading it for anyone interested in the platform’s history, understanding the hardware, and delving into how the software uses the hardware to bring forth so many of our beloved games. it is a fascinating read and fortunately he has a physical version available as well, which I had to get immediately after it was published.

About a month ago, Jotego reached out regarding the audio mixing levels of CPS hardware, wondering if my work on MDFourier might have already documented this. The prospect of an immediately applied real-world scenario was too enticing to pass up, so I dedicated my time to implement a series of audio tests using Mr. Sanglard’s work since I had recently made a similar test for Neo Geo, given that both platforms use 68000 and Z80 CPUs.

I thought it would be an easy port combining the x68000 and Neo Geo versions of the test, since one had the YM2151 and the other a Z80. And in a very real way it was since Fabien Sanglard had already made his C friendly SDK. My issues were, surprisingly, related to coding it in C instead of assembly and some smaller details even when I am less terrible at C than asm.

I had it running it on M.A.M.E. in almost no time, but when I burned the EPROMs to test it on the Street Fighter 2 PCB, things didn’t work. This is something that I’ve found a lot of times when coding homebrew for old platforms and is in no way detrimental to emulation or the SDKs. It is just a reality due to complexity and the nature of the work.

Since emulation in general aims to run all available software for a platform by implementing equivalent procedures in the host platform, sometimes with new software you find instances that were never found in officially released software. Finding, documenting, and fixing these takes some time, especially for a novice like me. Thankfully the community, documentation, MAME debugger and tools are there to help. We are standing on the shoulders of giants.

One such case is how the CPSB registers, or the RAM are to be initialized. In emulation they usually start filled with zeroes or known good values. But on real hardware you must initialize them on purpose, or the system will crash or have unexpected results, so I modified the crt0 code to initialize the RAM and registers.

Another instance was when copying data into the Video RAM, in the emulator you can copy a vast amount of data in a single frame since you are using current gen hardware in the emulator itself. This works perfectly in MAME but would simply crash the real hardware when you are still writing to the same VRAM while it is being drawn.

Of course, this will never happen on the real hardware since you are supposed to be using different RAM locations for the current and next frames, switching between them. And official games are also written in a way that controls how much data can be written in a single vblank. But when you are learning the ropes, don’t know what you are doing and you get it working on the emulator, you might wrongly think “Since it works on the emulator, it should work on hardware”. And I have found that it isn’t that way things work in the past, as it has happened to me with the Neo Geo, Sega CD, SNES, and a long list of platforms due to my inexperience.

After learning and being able to have my code running on the PCB, I was able to record and compare about a dozen CPS1 PCBs. With this information we were able to identify two main audio signatures regarding the ADPCM filtering and mixing: the 88617A-XX and the 89626A-4. I know this is a limited set of data from a small sample of PCBs, and that there might be other A boards that differ out there. But I believe that the data is solid since the matches are basically perfect between them and very consistent between models.

Testing on hardware like so can be very time consuming, since you end up in a cycle of burning EPROMs, testing, and then exposing them to UV which can quickly run through your supply of ROMs and time even when you manage them. This slowed me down, even if I used the dip switches as inputs since my work cycles are sometimes more hunch than thought driven, and my assumptions end up being wrong due to being a hot-headed software guy. But thankfully I learn from all the great people that have documented and tested in the past and present.

Then comes PicoROM by Wickerwaka, since he saw what I was doing he suggested that this previous work of his might speed things up. It is a ROM emulator using the Raspberry Pico and its open design and software that connects to your PC via USB and you can change the ROM contents on every cycle, in no time. You just have it added to your pipeline of work, reboot your PCB if needed and testing is immediate. No more burn/erase cycles on your EPROMs and it even has a two-way communication mode that I need to explore.

Thanks to his work and kindness, I will now be able to speed up this process for future platforms. Yes, I do have the intention of doing this same work on other platforms that are within reach: Sega System 16, Toaplan HW, Cave 68000 and IGS’s PGM are some of them. This will of course take time and dedication, since I am slow, but it is fulfilling a long time dream of coding for them, learning and also help document the hardware and its behavior so that emulation in the future can implement audio that is closer to the hardware signature and so that future generations can listen to the systems with less bias and a more authentic sound, if the choose to do so. I have a strong belief that the analog filters were placed there on purpose, but I also believe that having them as the default is a great choice, with other filters or even no filter at all as options available for those that prefer that.

Since Jotego has a lot of experience and knowledge that I don’t have, he has been implementing matching filters derived from the schematics of several of these platforms that he already covers since he has already figured out why the audio filters previously used were not as effective as expected, and his engineering-based predictions have matched the hardware measurements closely.

Thanks for reading this and to all the people that kindly support this kind of work, I am really grateful.

Liked it? Take a second to support Artemio Urbina on Patreon!