Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

M1.NET (for CPS1)

, 15 Sep 2013
Rate this:
Please Sign up or sign in to vote.
Decrypt CPS1 audio

Introduction

CPS1 is an arcade system board developed by Capcom that ran game software stored on removable ROM cartridges. There are some classic games release on it, such as Final Fight, Street Fighter II': Champion Edition, Cadillacs and Dinosaurs. There are some emulators to emulate it: MAME, WinKawaks, Nebula, FBA...

The sound of CPS1 is amazing too. I have found the only software named M1 to reproduce the music of arcade games. M1 lets you enjoy music from over 1400 arcade games. But M1 is not a open source software.

MAME is strictly a non-profit project. Its main purpose is to be a reference to the inner workings of the emulated arcade machines. You can do anything about arcade games with MAME source code. To show the detail of decrypting CPS1 game audio, I programmed this software named M1.NET (for CPS1).

How It Works?

For CPS1 audio, there are two different boards. I named them CPS-1 and Capcom QSound (CPS version).

For CPS-1, the Z-80 CPU runs at 3579545 Hz, and there are two sound chips: Yamaha YM2151, Oki OKI6295. The program load the file "audiocpu.rom" as the Z-80 ROM, file "oki.rom" as the OKI6295 ROM. Then the Z-80 CPU runs. When you double click the track or click the play button, the function CPlay or CStop is triggered.

For Capcom QSound (CPS version), the Z-80 CPU runs at 8000000 Hz with Kabuki encrypted code, and there is a Q-Sound chip. The program loads the file "audiocpu.rom" as the Z-80 ROM for ReadMemory only, file "audiocpuop.rom" as the Z-80 ROM for ReadOp only, and file "qsound.rom" as the Q-Sound chip ROM. Then the Z-80 CPU runs. When you double click the track or click the play button, the function QPlay or QStop is triggered.

public static void CPlay(ushort ID)
{
    Sound.latched_value[0] = (byte)ID;
}
public static void CStop(ushort ID)
{
    Sound.latched_value[0] = (byte)ID;
}
public static void QPlay(ushort ID)
{
    qsound_sharedram1_w(0x00, 0x00);
    qsound_sharedram1_w(0x01, ID);
    qsound_sharedram1_w(0x0f, 0x00);
}
public static void QStop(ushort ID)
{
    qsound_sharedram1_w(0x00, (ushort)(ID >> 8));
    qsound_sharedram1_w(0x01, ID);
    qsound_sharedram1_w(0x0f, 0x00);
}

The program uses the same .lst file as BridgeM, and it uses the truncated format of the file "m1.xml" of BridgeM1. You should install Microsoft .NET Framework 3.5 or higher before running the program. The UI is simple and it has the similar function as BridgeM1. I've added the file "wofhfh.lst". Since "wofhfh" is a bootleg, I have some problem in stopping voice. You can edit "m1.xml", add .lst file and make ROMs for any CPS1 game to get its audio.

M1.NET (for CPS1) user interface

Make the ROMs

Now I explain how to make the roms for both boards.
For CPS-1 game "ffight", I will make the following files: "audiocpu.rom", "oki.rom". From the MAME CPS1 code:
http://www.mamedev.org/source/src/mame/drivers/cps1.c.html
Find the following code:

/* B-Board 89624B-3 */
ROM_START( ffight )
…
    ROM_REGION( 0x18000, "audiocpu", 0 ) /* 64k for the audio CPU (+banks) */
    ROM_LOAD( "ff_09.12b", 0x00000, 0x08000, 
    CRC(b8367eb5) SHA1(ec3db29fdd6200e9a8f4f8073a7e34aef731354f) )
    ROM_CONTINUE(          0x10000, 0x08000 )
 
    ROM_REGION( 0x40000, "oki", 0 ) /* Samples */
    ROM_LOAD( "ff_18.11c", 0x00000, 0x20000, 
    CRC(375c66e7) SHA1(36189e23209ce4ae5d9cbabd1574540d0591e7b3) )
    ROM_LOAD( "ff_19.12c", 0x20000, 0x20000, 
    CRC(1ef137f9) SHA1(974b5e72aa28b87ebfa7438efbdfeda769dedf5e) )
…
ROM_END

Insert 0x8000 zero bytes at offset 0x8000 of file "ff_09.12b" (or other name in previous version, just check the CRC32 b8367eb5 to confirm the file), and save it as file "audiocpu.rom" with the length 0x18000. Simply sequentially concatenate the files "ff_18.11c", "ff_19.12c" to a file "oki.rom" with the length 0x40000. You can do it with WinHex easily.

Insert 0x8000 (32768) bytes of 0x00 at the offset 0x8000

Sequently concatenate the files "ff_18.11c", "ff_19.12c"

For Capcom QSound (CPS version) game "wof", so I will make the following files: "audiocpu.rom", "audiocpuop.rom", "qsound.rom". Find the following code from the MAME CPS1 code:

/* B-Board 91635B-2 */
ROM_START( wof )
…
    ROM_REGION( 0x28000, "audiocpu", 0 ) /* QSound Z80 code */
    ROM_LOAD( "tk2_qa.5k",   0x00000, 0x08000, 
    CRC(c9183a0d) SHA1(d8b1d41c572f08581f8ab9eb878de77d6ea8615d) )
    ROM_CONTINUE(          ; 0x10000, 0x18000 )
 
    ROM_REGION( 0x200000, "qsound", 0 ) /* QSound samples */
    ROM_LOAD( "tk2-q1.1k",   0x000000, 0x80000, 
    CRC(611268cf) SHA1(83ab059f2110fb25fdcff928d56b790fc1f5c975) )
    ROM_LOAD( "tk2-q2.2k",   0x080000, 0x80000, 
    CRC(20f55ca9) SHA1(90134e9a9c4749bb65c728b66ea4dac1fd4d88a4) )
    ROM_LOAD( "tk2-q3.3k",   0x100000, 0x80000, 
    CRC(bfcf6f52) SHA1(2a85ff3fc89b4cbabd20779ec12da2e116333c7c) )
    ROM_LOAD( "tk2-q4.4k",   0x180000, 0x80000, 
    CRC(36642e88) SHA1(8ab25b19e2b67215a5cb1f3aa81b9d26009cfeb8) )
…
ROM_END

Simply sequentially concatenate the files "tk2-q1.1k", "tk2-q2.2k", "tk2-q3.3k", "tk2-q4.4k" to a file "qsound.rom" with the length 0x200000. By debugging MAME, you can set a breakpoint at the end of function "kabuki_decode" in source file "src\mame\machine\kabuki.c" and find the start address, then dump the memory to file:

Dump memory by MAME debugging

start address length filename
0x048114c0(dest_op address) 0x8000 audiocpuop.rom
0x04798660(dest_data address) 0x28000 audiocpu.rom

Or you can do the same as type CPS-1 for file "audiocpu.rom". Then dump memory from running process (for example: MAME, WinKawaks, Nebula, FBA, BridgeM1…) when ROMs loaded by finding key bytes and replace the first 0x8000 bytes of file "audiocpu.rom". And dump memory for "audiocpuop.rom" with the length 0x8000.

Dump memory from running Nebula by finding key bytes

Conclusion

I've finished M1.NET (for CPS1). It figures out how the audio ROMs work. You can make any other CPS1 games supported. By the translation from C to C#, there is no unsafe code and the code is much more readable. I've preserved the main architecture of MAME. Programmers can refer more to this. For example: make it support other sound chips, program an emulator like WinKawaks...

References

  1. MAME-Multiple Arcade Machine Emulator - http://www.mamedev.org/source/
  2. MSDN - http://msdn.microsoft.com
  3. bizhawk Z80 code - http://code.google.com/p/bizhawk/source/browse/trunk/BizHawk.Emulation/CPUs/Z80/
  4. VCMAME detail by Bryan McPhail - http://www.codeproject.com/Articles/4923/VCMAME-Multiple-Arcade-Machine-Emulator-for-Visual
  5. MAME and MAMEUI Visual C Project Files - http://www.mikesarcade.com/arcade/vcmame.html
  6. BridgeM1 - http://www.e2j.net/downloads.html
  7. WinHex - http://www.x-ways.net/winhex/

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberAntonio Petricca1-Sep-13 23:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 16 Sep 2013
Article Copyright 2013 by shunninghuang
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid