PS2 Namco arcade compatibility guide

first of all, thanks to krHACKen for explaining several things to me.

RPC Incompatibilities


COH-H models are plagued with this issue because their builtin software is based on a newer SDK (3.1.0) than the one used to make builtin software of retail PS2s


Unlike retail PS2s. the COH-H models dont have OSD versions of the stock drivers because there is no OSD (so drivers like rom0:XMCMAN dont exist)
please note the following:
the arcade modules rom0:MCSERV and rom0:PADMAN both use the OSD RPC. so their RPC service is equivalent to the rom0:XMCMAN and rom0:XPADMAN from retail PS2.

If you use those modules make sure to bind the MCSERV RPC like this:

mcInit(MC_TYPE_XMC);

and for the PADMAN module. link your application against libpadx not libpad

CDVDMAN RPC


Unlike retail PS2. the COH-H models do not load the CDVDMAN RPC service on boot (rom0:CDVDFSV). therefore. any function that requires access to CDVDMAN will hang if you dont execute that module first.
as soon as you reboot the IOP you should load that module like this:

SifLoadStartModule("rom0:CDVDFSV", 0, NULL, NULL);

File I/O Services


the COH-H models builtin FILEIO module is not compatible with our homebrew RPCs.
therefore, we must replace it. and for that, the IOP must be rebooted using an IOPRP image containing homebrew FILEIO.
for simplicity and to avoid surprises I decided to not only replace the FILEIO RPC service. I also replace the IOMAN module.
you can build your own, or use a prebuilt ioprp image

this is how a normal IOP Reboot looks like

    while (!SifIopReset("", 0));
    while (!SifIopSync()) {};

this is how you use an IOPRP image

    while (!SifIopRebootBuffer(ioprp, size_ioprp)) {}; //embed the ioprp image with bin2c
    while (!SifIopSync()) {};

newlib port issues


newlib will try to open rom0:ROMVER and use some of the mechacon cmds (wich require CDVDMAN), does that ring a bell? yes, we talked about these two things on the previous paragraph.

As an all in one solution, if your program only reboots the IOP once, I would do the following, delete the code for IOP reboot from your main function or whatever, and instead, add this to your code:

void _ps2sdk_memory_init() {
    while (!SifIopRebootBuffer(ioprp, size_ioprp)) {}; //replace FILEIO
    while (!SifIopSync()) {};
SifLoadStartModule("rom0:CDVDFSV", 0, NULL, NULL);
}

(I always add it after at the end of the source file holding main()):

this function is a weak definition found on the PS2SDK crt0, we can use it to gain code execution before newlib does things that will cause issues, giving us the change to replace FILEIO and load CDVDFSV so that newlib can do it’s thing without issues

extra tips that need more testing/information

Game display


if your homebrew will need video output, you must use ACJVLOAD.IRX module to init the display

Memory Card access


the COH-H models use two sets of magicgate keys. the port 1 is authenticated with the arcade magicgate keystore. therefore it only reads COH-H10020 security dongles. while port 2 uses retail keys, wich makes it read normal SCPH-10020 memory cards.

there is only one exception to this rule and it is the Soul Calibur 2 campaign cards. these are normal memory cards that seem to have some sort of encryption both on the console software and card hardware. this results on these campaign cards corrupting if accessed by any driver beyond the DONGLEMAN driver found on the game

accesing both mc0 and mc1 at the same time is imposible with the builtin ROM modules.
console has two memory card drivers:

the only solution to this is to use the DONGLEMAN driver from Bloody Roar 3 or use a homebrew clone of DONGLEMAN

Arcade Watchdog


The Arcade SYSCON chip has an additional mechanism on it’s software wich we know as “the watchdog”.
This system is basically a 5 min. countdown to shutdown the machine.
This countdown is reset when the mechacon successfully finishes the memory card authentication routine on a COH-H10020 security dongle (wich mechacon CMD fires this reset will be confirmed soon).
However, this check is not done all the time. A special IRX module must be executed for this (rom0:DAEMON).
But before running to make your app run this module keep in mind the following:

the DONGLEMAN module from Bloody Roar 3 not only auths both arcade and retail memory cards. it seems to have an additional semaphore wrapped around the functions involved on the auth reset (most likely to avoid corruption or somethin. yet this needs confirmation) (for the people interested on reversing: search the string sema hakama to find the creation of that semaphore).

Once I get my hands on my own COH-H model I’ll update the information about this with my findings. however, in the meantime:

rom0:DAEMON setups a thread that calls the internal mcman function McDetectCard2(0,0) once every 60secs. wich effectively makes the system go through the dongle auth process, satisfying the arcade watchdog.

Arcade Mechacon


The arcade mechacon is quite unique on certain features. being the most interesting one that it uses different magicgate keys to auth memory cards depending on the port. it uses arcade keys on mc0: and retail keys on mc1:. unlike retail mechacon wich only uses retail keys or developer mechacon wich uses both retail and developer keys on both ports

Another bit of information: although the arcade SECRMAN is based on the secrman_special from utility discs, wich has the memory card update routine included. it seems like the mechacon CMDs involved on binding updates to cards are stubbed. making update binding only possible via CECHMZ1 (PS3 memory card to usb adapter) or the modified devkits that sony sold to namco back then (wich we’ve never seen on the homebrew scene). there is also wLaunchELF MECHAEMU and DONGLEBINDER, two brand new homebrews that will allow you to rebind updates to dongle from retail ps2

C++ issues

If you chose C++ over C for your PS2 app, and you whant arcade compatibility. I have bad news for ya.

For some reason, C++ applications are crashing on arcade hardware, you remember that _ps2sdk_memory_init() that I mentioned above, that was useful to solve the incompatibilities while keeping newlib happy? well, the program crashes before crt0 executes that, so good luck finding the issue…

As of 2/01/2025 this problem has not been solved, I will continue to investigate it however.

Final notes


this article will be filled as time passes. most of this information was either learnt from other devs or discovered via trial and error. all of this without access to arcade hardware (wich will change soon). if any bit of information in here is wrong or incomplete let me know on discord/psx-place!