Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / DirectX

CPS1.NET: A C# Based CPS1 (MAME) Emulator

5.00/5 (58 votes)
3 Apr 2021CPOL19 min read 112.3K   5.2K  
CPS1 emulator, ROM hacking

Image 1

CPS1.NET user interface

Introduction

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

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. CPS1.NET is a C# based CPS1 emulator, and it maintains the same architecture of MAME. By using C# and the powerful integrated development environment -- Microsoft Visual Studio, there is no macro and you can debug the CPS1 game anywhere. The origin screen size is 384x224 pixels. I maximize the default visible area to 512x512 pixels, so you can see more details (for example: the hanging sword). I set the transparent color to magenta to show more background detail.

Image 2

The hanging sword

CPS1.NET runs at following steps: load the ROMs, initialize the machine, soft reset the machine, and loop "cpuexec_timeslice" operation. The "cpuexec_timeslice" operation means execute M68000 CPU for a time slice, execute Z80 CPU for a time slice, and execute timer callbacks. Timer callbacks contains: video update, soft reset, M68000 interrupt, Z80 interrupt, set sound latched value, sound update, YM2151 interrupt. By these steps, CPS1.NET emulates the CPS1 board successfully. CPS1.NET has more functions: save and load state, record and replay input, cheat, cheat search, IPS (patch M68000 ROM), CPS1 debugger, M68000 debugger, Z80 debugger.

Load the ROMs

There are 2 CPUs working in CPS1 board: a Motorola M68000 CPU and a Zilog Z80 CPU. For CPS1 game, there are two different boards. I named them CPS-1 board and CPS-1(QSound) board.

As an emulator, CPS1.NET loads ROMs first. There are total 6 types of ROM: "maincpu.rom", "gfx.rom", "audiocpu.rom", "audiocpop.rom", "oki.rom" and "qsound.rom".

For CPS-1 board, the M68000 CPU runs at 10MHz (12MHz for some games). For CPS-1(QSound) board, the M68000 CPU runs at 12MHz. The program loads the file "maincpu.rom" as M68000 ROM. Size of "maincpu.rom" should be no greater than 0x400000 bytes.

You can dump the certain memory of running MAME and make the byte swap to make "maincpu.rom". The file "gfx.rom" contains tile data to display on screen. You can dump the certain memory of running MAME directly to make "gfx.rom". For CPS-1 board, the Z80 CPU runs at 3579545 Hz, and there are two sound chips: Yamaha YM2151, Oki MSM6295. The program loads the file "audiocpu.rom" as Z80 ROM.

Since there is CPS1 sound bank switch, the upper limit size of "audiocpu.rom" is 0x18000 bytes. The program loads the file "oki.rom" as the Oki MSM6295 ROM. For CPS-1(QSound) board, the Z80 CPU runs at 8MHz with Kabuki encrypted code, and there is a Q-Sound chip. The program loads the file "audiocpu.rom" as the Z80 ROM for ReadMemory only, the file "audiocpuop.rom" as the Z80 ROM for ReadOp only. Since there is Q-Sound bank switch, the upper limit size of "audiocpu.rom" is 0x50000 bytes. The program loads the file "qsound.rom" as the Q-Sound chip ROM. My former project M1.NET tells you how to dump these sound related ROMs from running MAME.

Since M68000 is a big-endian CPU, CPS1.NET handles memory in big-endian byte order too. The ROM format of CPS1.NET is the simplest. You can open and disassemble "maincpu.rom" and "audiocpu.rom" (only CPS-1 board) with IDA Pro directly. There is no combination of multiple ROMs, no CPS1 graphic effects decoding, no Kabuki decoding, and no byte swap. So the IPS file (.cht extension, the same as cheat file) is easy to understand. ROM hackers can focus on the real address-value pair and neglect ROM encoding and decoding. You can also disassemble CPU ROMs with the M68000 debugger and Z80 debugger functions in CPS1.NET.

Common Usage

Build environment: I only test on Windows 7 Ultimate X64, Microsoft Visual Studio 2008.

Operating environment: Microsoft .NET Framework 3.5 or higher.

Hotkey: F3 -- soft reset, F7 -- load state, Shift+F7 -- save state, F8 -- replay input, Shift+F8 -- record input (start and stop), 0-9 and A-Z after state related hotkey -- handle certain files, F10 -- toggle global throttle, P -- pause and continue, Shift+P -- skip a frame.

Control Keys

  • 1 -- P1 start
  • 2 -- P2 start
  • 5 -- P1 coin
  • 6 -- P2 coin
  • R -- Service 1
  • T -- Service
  • W -- P1 up
  • S -- P1 down
  • A -- P1 left
  • D -- P1 right
  • J -- P1 button1
  • K -- P1 button 2
  • L -- P1 button 3
  • U -- P1 button 4
  • I -- P1 button 5
  • O -- P1 button 6
  • Up -- P2 up
  • Down -- P2 down
  • Left -- P2 left
  • Right -- P2 right
  • NumPad1 -- P2 button 1
  • NumPad2 -- P2 button 2
  • NumPad3 -- P2 button 3
  • NumPad4 -- P2 button 4
  • NumPad5 -- P2 button 5
  • NumPad6 -- P2 button 6

When the ROMs of a game are loaded, the emulator is auto paused. You can apply IPS and dip-switch now and press P to continue. You can get the proper dip-switch value from running MAME.

Image 3

Dip-switch (MAME)

Image 4

Dip-switch (CPS1.NET)

Occasionally, GDI+ error occurs and a red cross is shown. You can click “File-Reset picturebox” to handle the error.

You can make the CPS1.NET cheat file refer to cheat file of MAME or other emulators. You should make the ^1 operation to the cheat address for some emulators (for example: Winkawaks).

There are two files for record input. The .sta file records the initial state and the .inp file records the input key. You can combine multiple .inp files to one .inp file. For example, there are 8 record input in the directory "inp\punisher\" (1.sta to 8.sta, 1.inp to 8.inp). Remember do not input any control key between two record input. Copy the file "1.sta" to "q.sta" as the initial state. Sequentially concatenate the files "1.inp", "2.inp"… "8.inp" to a file "q.inp". So the "q" record input is the combination of "1", "2"… "8" record input. You can record your best input by the combination of multiple segments easily.

Supported games:

  • Forgotten Worlds (World, newer) [forgottn]
  • Forgotten Worlds (World) [forgottna]
  • Forgotten Worlds (USA, B-Board 88621B-2, Rev. C) [forgottnu]
  • Forgotten Worlds (USA, B-Board 88618B-2, Rev. E) [forgottnue]
  • Forgotten Worlds (USA, B-Board 88618B-2, Rev. C) [forgottnuc]
  • Forgotten Worlds (USA, B-Board 88618B-2, Rev. A) [forgottnua]
  • Forgotten Worlds (USA, B-Board 88618B-2, Rev. AA) [forgottnuaa]
  • Lost Worlds (Japan) [lostwrld]
  • Lost Worlds (Japan Old Ver.) [lostwrldo]
  • Ghouls'n Ghosts (World) [ghouls]
  • Ghouls'n Ghosts (USA) [ghoulsu]
  • Daimakaimura (Japan) [daimakai]
  • Daimakaimura (Japan Resale Ver.) [daimakair]
  • Strider (USA, B-Board 89624B-2) [strider]
  • Strider (USA, B-Board 89624B-3) [striderua]
  • Strider (USA, B-Board 90629B-3, buggy Street Fighter II conversion) [strideruc]
  • Strider Hiryu (Japan) [striderj]
  • Strider Hiryu (Japan Resale Ver.) [striderjr]
  • Dynasty Wars (USA, B-Board 89624B-?) [dynwar]
  • Dynasty Wars (USA, B-Board 88622B-3) [dynwara]
  • Tenchi wo Kurau (Japan) [dynwarj]
  • Tenchi wo Kurau (Japan Resale Ver.) [dynwarjr]
  • Willow (World) [willow]
  • Willow (USA) [willowu]
  • Willow (USA Old Ver.) [willowuo]
  • Willow (Japan) [willowj]
  • U.N. Squadron (US) [unsquad]
  • Area 88 (Japan) [area88]
  • Area 88 (Japan Resale Ver.) [area88r]
  • Final Fight (World, set 1) [ffight]
  • Final Fight (World, set 2) [ffighta]
  • Final Fight (USA, set 1) [ffightu]
  • Final Fight (USA, set 2) [ffightu1]
  • Final Fight (USA 900112) [ffightua]
  • Final Fight (USA 900424) [ffightub]
  • Final Fight (USA 900613) [ffightuc]
  • Final Fight (Japan) [ffightj]
  • Final Fight (Japan 900112) [ffightj1]
  • Final Fight (Japan 900305) [ffightj2]
  • Final Fight (Japan 900613) [ffightj3]
  • Street Smart / Final Fight (Japan, hack) [ffightjh]
  • 1941: Counter Attack (World 900227) [1941]
  • 1941: Counter Attack (World) [1941r1]
  • 1941: Counter Attack (USA 900227) [1941u]
  • 1941: Counter Attack (Japan) [1941j]
  • Mercs (World 900302) [mercs]
  • Mercs (USA 900608) [mercsu]
  • Mercs (USA 900302) [mercsur1]
  • Senjou no Ookami II (Japan 900302) [mercsj]
  • Mega Twins (World 900619) [mtwins]
  • Chiki Chiki Boys (Japan 900619) [chikij]
  • Magic Sword: Heroic Fantasy (World 900725) [msword]
  • Magic Sword: Heroic Fantasy (World 900623) [mswordr1]
  • Magic Sword: Heroic Fantasy (USA 900725) [mswordu]
  • Magic Sword: Heroic Fantasy (Japan 900623) [mswordj]
  • Carrier Air Wing (World 901012) [cawing]
  • Carrier Air Wing (World 901009) [cawingr1]
  • Carrier Air Wing (USA 901012) [cawingu]
  • U.S. Navy (Japan 901012) [cawingj]
  • Nemo (World 901130) [nemo]
  • Nemo (World 901109) [nemor1]
  • Nemo (Japan 901120) [nemoj]
  • Street Fighter II: The World Warrior (World 910522) [sf2]
  • Street Fighter II: The World Warrior (World 910214) [sf2eb]
  • Street Fighter II: The World Warrior (World 910318) [sf2ed]
  • Street Fighter II: The World Warrior (World 910228) [sf2ee]
  • Street Fighter II: The World Warrior (USA 910206) [sf2ua]
  • Street Fighter II: The World Warrior (USA 910214) [sf2ub]
  • Street Fighter II: The World Warrior (USA 910306) [sf2uc]
  • Street Fighter II: The World Warrior (USA 910318) [sf2ud]
  • Street Fighter II: The World Warrior (USA 910228) [sf2ue]
  • Street Fighter II: The World Warrior (USA 910411) [sf2uf]
  • Street Fighter II: The World Warrior (USA 910522, Rev. G) [sf2ug]
  • Street Fighter II: The World Warrior (USA 910522, Rev. I) [sf2ui]
  • Street Fighter II: The World Warrior (USA 911101) [sf2uk]
  • Street Fighter II: The World Warrior (Japan 911210) [sf2j]
  • Street Fighter II: The World Warrior (Japan 910214) [sf2ja]
  • Street Fighter II: The World Warrior (Japan 910306) [sf2jc]
  • Street Fighter II: The World Warrior (Japan 910411) [sf2jf]
  • Street Fighter II: The World Warrior (Japan 910522) [sf2jh]
  • Street Fighter II: The World Warrior (Japan 920312) [sf2jl]
  • Street Fighter II: The World Warrior (TAB Austria, bootleg, set 1) [sf2ebbl]
  • Street Fighter II: The World Warrior (TAB Austria, bootleg, set 3) [sf2ebbl2]
  • Street Fighter II: The World Warrior (TAB Austria, bootleg, set 4) [sf2ebbl3]
  • Street Fighter II: The World Warrior (Quicken Pt-I, bootleg) [sf2qp1]
  • Street Fighter II: The World Warrior (Thunder Edition, bootleg) [sf2thndr]
  • Three Wonders (World 910520) [3wonders]
  • Three Wonders (World 910513) [3wondersr1]
  • Three Wonders (USA 910520) [3wondersu]
  • Wonder 3 (Japan 910520) [wonder3]
  • Three Wonders (bootleg) [3wondersb]
  • Three Wonders (hack) [3wondersh]
  • The King of Dragons (World 910805) [kod]
  • The King of Dragons (World 910711) [kodr1]
  • The King of Dragons (USA 910910) [kodu]
  • The King of Dragons (Japan 910805, B-Board 90629B-3) [kodj]
  • The King of Dragons (Japan 910805, B-Board 89625B-1) [kodja]
  • Captain Commando (World 911202) [captcomm]
  • Captain Commando (World 911014) [captcommr1]
  • Captain Commando (USA 910928) [captcommu]
  • Captain Commando (Japan 911202) [captcommj]
  • Captain Commando (Japan 910928) [captcommjr1]
  • Captain Commando (bootleg) [captcommb]
  • Knights of the Round (World 911127) [knights]
  • Knights of the Round (USA 911127) [knightsu]
  • Knights of the Round (Japan 911127, B-Board 91634B-2) [knightsj]
  • Knights of the Round (Japan 911127, B-Board 89625B-1) [knightsja]
  • Street Fighter II': Champion Edition (World 920513) [sf2ce]
  • Street Fighter II': Champion Edition (World 920313) [sf2ceea]
  • Street Fighter II': Champion Edition (USA 920313) [sf2ceua]
  • Street Fighter II': Champion Edition (USA 920513) [sf2ceub]
  • Street Fighter II': Champion Edition (USA 920803) [sf2ceuc]
  • Street Fighter II': Champion Edition (Japan 920322) [sf2ceja]
  • Street Fighter II': Champion Edition (Japan 920513) [sf2cejb]
  • Street Fighter II': Champion Edition (Japan 920803) [sf2cejc]
  • Street Fighter II': Champion Edition (Hung Hsi, bootleg) [sf2bhh]
  • Street Fighter II': Champion Edition (Rainbow, bootleg, set 1) [sf2rb]
  • Street Fighter II': Champion Edition (Rainbow, bootleg, set 2) [sf2rb2]
  • Street Fighter II': Champion Edition (Rainbow, bootleg, set 3) [sf2rb3]
  • Street Fighter II': Champion Edition (Red Wave, bootleg) [sf2red]
  • Street Fighter II': Champion Edition (V004, bootleg) [sf2v004]
  • Street Fighter II': Champion Edition (Accelerator!, bootleg, set 1) [sf2acc]
  • Street Fighter II': Champion Edition (Accelerator!, bootleg, set 2) [sf2acca]
  • Street Fighter II': Champion Edition (Accelerator Pt.II, bootleg) [sf2accp2]
  • Street Fighter II': Champion Edition (L735 Test Rom, bootleg) [sf2amf2]
  • Street Fighter II': Champion Edition (Double K.O. Turbo II, bootleg) [sf2dkot2]
  • Street Fighter II': Champion Edition (protected bootleg on non-dash board) [sf2ceblp]
  • Street Fighter II': Champion Edition ('Taiwan' bootleg with PAL) [sf2cebltw]
  • Street Fighter II': Champion Edition (M2, bootleg) [sf2m2]
  • Street Fighter II': Champion Edition (M3, bootleg) [sf2m3]
  • Street Fighter II': Champion Edition (M4, bootleg) [sf2m4]
  • Street Fighter II': Champion Edition (M5, bootleg) [sf2m5]
  • Street Fighter II': Champion Edition (M6, bootleg) [sf2m6]
  • Street Fighter II': Champion Edition (M7, bootleg) [sf2m7]
  • Street Fighter II': Champion Edition (M8, bootleg) [sf2m8]
  • Street Fighter II': Champion Edition (M10, bootleg) [sf2m10]
  • Street Fighter II': Champion Edition (YYC, bootleg) [sf2yyc]
  • Street Fighter II': Champion Edition (Xiang Long, Chinese bootleg) [sf2koryu]
  • Street Fighter II': Champion Edition (Dongfang Bubai protection, bootleg) [sf2dongb]
  • Adventure Quiz Capcom World 2 (Japan 920611) [cworld2j]
  • Adventure Quiz Capcom World 2 (Japan 920611, B-Board 90629B-3, no battery) [cworld2ja]
  • Adventure Quiz Capcom World 2 (Japan 920611, B-Board 91634B-2) [cworld2jb]
  • Varth: Operation Thunderstorm (World 920714) [varth]
  • Varth: Operation Thunderstorm (World 920612) [varthr1]
  • Varth: Operation Thunderstorm (USA 920612) [varthu]
  • Varth: Operation Thunderstorm (Japan 920714) [varthj]
  • Varth: Operation Thunderstorm (Japan Resale Ver. 920714) [varthjr]
  • Quiz & Dragons: Capcom Quiz Game (USA 920701) [qad]
  • Quiz & Dragons: Capcom Quiz Game (Japan Resale Ver. 940921) [qadjr]
  • Warriors of Fate (World 921031) [wof]
  • Warriors of Fate (World 921002) [wofr1]
  • Warriors of Fate (USA 921031) [wofu]
  • Sangokushi II (Asia 921005) [wofa]
  • Tenchi wo Kurau II: Sekiheki no Tatakai (Japan 921031) [wofj]
  • Huo Feng Huang (Chinese bootleg of Sangokushi II) [wofhfh]
  • Street Fighter II': Hyper Fighting (World 921209) [sf2hf]
  • Street Fighter II': Hyper Fighting (USA 921209) [sf2hfu]
  • Street Fighter II' Turbo: Hyper Fighting (Japan 921209) [sf2hfj]
  • Cadillacs and Dinosaurs (World 930201) [dino]
  • Cadillacs and Dinosaurs (USA 930201) [dinou]
  • Cadillacs: Kyouryuu Shin Seiki (Japan 930201) [dinoj]
  • Dinosaur Hunter (Chinese bootleg of Cadillacs and Dinosaurs) [dinohunt]
  • The Punisher (World 930422) [punisher]
  • The Punisher (USA 930422) [punisheru]
  • The Punisher (Hispanic 930422) [punisherh]
  • The Punisher (Japan 930422) [punisherj]
  • Biaofeng Zhanjing (Chinese bootleg of The Punisher) [punisherbz]
  • Saturday Night Slam Masters (World 930713) [slammast]
  • Saturday Night Slam Masters (USA 930713) [slammastu]
  • Muscle Bomber: The Body Explosion (Japan 930713) [mbomberj]
  • Muscle Bomber Duo: Ultimate Team Battle (World 931206) [mbombrd]
  • Muscle Bomber Duo: Heat Up Warriors (Japan 931206) [mbombrdj]
  • Pnickies (Japan 940608) [pnickj]
  • Quiz Tonosama no Yabou 2: Zenkoku-ban (Japan 950123) [qtono2j]
  • Mega Man: The Power Battle (CPS1, USA 951006) [megaman]
  • Mega Man: The Power Battle (CPS1, Asia 951006) [megamana]
  • Rockman: The Power Battle (CPS1, Japan 950922) [rockmanj]
  • Pokonyan! Balloon (Japan 940322) [pokonyan]
  • Pang! 3 (Euro 950601) [pang3]
  • Pang! 3 (Euro 950511) [pang3r1]
  • Pang! 3: Kaitou Tachi no Karei na Gogo (Japan 950511) [pang3j]
  • Pang! 3 (bootleg) [pang3b]
  • Tenchi wo Kurau II: Sekiheki no Tatakai (CPS Changer, Japan 921031) [wofch]
  • Street Fighter Zero (CPS Changer, Japan 951020) [sfzch]
  • Street Fighter Alpha: Warriors' Dreams (CPS Changer, Publicity USA 950727) [sfach]
  • Street Fighter Zero (CPS Changer, Brazil 950727) [sfzbch]
  • Sangokushi II: San Jian Sheng (Chinese bootleg set 1, 921005 Asia) [wof3js]
  • Warriors of Fate: 1v3 (Chinese bootleg) [wof1v3]
  • Tenchi wo Kurau II - Sekiheki no Tatakai (Japan 921031) (Chinese translation) [wofcn]
  • Tenchi wo Kurau II: Da Ren (Chinese bootleg) [wofdr]
  • Tenchi wo Kurau II: Da Ren 2020 (Chinese bootleg) [wofdr2020]
  • Tenchi wo Kurau II: Wu Shuang Jia Qiang (Chinese bootleg) [wofdwp]
  • Tenchi wo Kurau II: Dou Zhi (Chinese bootleg) [wofdz]
  • Tenchi wo Kurau II: San Mei (Chinese bootleg) [wofsm]
  • Tenchi wo Kurau II: Xia Hou En Fu Chou (Chinese bootleg) [wofx]
  • Tenchi wo Kurau II: Zhan Lang (Chinese bootleg) [wofzl]
  • Sangokushi II: Sheng Jian Sanguo (Chinese bootleg) [wofsj]
  • Sangokushi II: San Sheng Jian (Chinese bootleg) [wof3sj]
  • Sangokushi II: San Jian Sheng (Chinese bootleg set 2, 921005 Asia) [wof3jsa]
  • Warriors of Fate ('sgyxz' bootleg) [sgyxz]

Technical Note

The CPS1 frame update frequency is 59.61 Hz in CPS1.NET. I only collect 11 classic CPS1 games. If you add some codes to "mame\cps\CPS.cs" and "ui\mame.xml", and make the corresponding ROMs, any other CPS1 game will be supported. If you dump mainrom, gfxram, or mainram from running MAME, you should make the byte swap before compare to the CPS1.NET value. You can easily extract background or sprite of CPS1 games by using the CPS1 debugger function.

Image 5

Chun-Li's background

By the following code, you can automatically play the game and get the best score (14 seconds left). I've recorded it as "inp\wof\r.inp".

Image 6

Modify source

Image 7

Eat fastest

Since there is little unsafe code, the efficiency of CPS1.NET is lower than other emulators. You should use rather high performance hardware to run CPS1.NET, or the game will run slower than normal.

ROM Hacking

You can hack the ROMs effectively with the M68000 debugger and Z80 debugger functions of CPS1.NET. For a beginner, M68000 ROM hacking contains the following steps: determine the key mainram address and value, debug M68000 CPU "backward" until you get the certain mainrom address and value, patch the object mainrom. Now I show three examples:

1. Final Fight, Change the First Enemy

Using the cheat search function, I find the base mainram address of the first enemy is 0x8FE8. The offset 0x13 and 0x14 bytes (mainram[0x8FFB] and mainram[0x8FFC]) determine the type of first enemy. I record "1" record input, modify "mame\cps\Memory.cs" and "ui\m68000Form.cs" as follows:

Image 8

Modify source

Replay "1" record input. The object PPC is 0x006210.

Image 9

Main form

Image 10

M68000 debugger

Recover files "mame\cps\Memory.cs" and "ui\m68000Form.cs". Get the following disassembly information:

ASM
A[3]=0x0006D02C    A[4]=0xFFFF8FE8
006210: 196B 0007 0013        move.b   ($7,A3), ($13,A4)
006216: 396B 0008 0014        move.w   ($8,A3), ($14,A4)

If you change the bytes mainrom[0x06D02C+0x07] and mainrom[0x06D02C+0x08], you will change the type of the first enemy. So I make the IPS file "ips\ffight.cht".

Image 11

Change Bred to G. Oriber
2. Captain Commando, Captain Discharges Ice

First, I'll find the key difference between fire sprite and ice sprite. I use the cheat search function to make an ice robot first (the cheat file "cht\cc robot.cht"). Then I find the base mainram address of fire or ice sprite is 0xB094. The offset 0x23 byte (mainram[0xB0B7]) determines the fire or ice sprite (0x06 for fire and 0x07 for ice). I record "1" record input, modify "ui\m68000Form.cs" as following:

Image 12

Modify source

Replay "1" record input, and get the TotalExecutedCycles 0x1011A877.

Image 13

Main form

Image 14

M68000 debugger

To debug "backward", replay "1" record input, step till TotalExecutedCycles 0x1011A777 (back 0x100 cycles), then step till TotalExecutedCycles 0x1011A877 and log the disassembly information when TotalExecutedCycles are between 0x1011A777 and 0x1011A877:

ASM
001D80: 3B41 2816             move.w   D1, ($2816,A5)
001D84: 4E75                  rts     
01F39C: 49FA 00CC             lea      ($CC,PC), A4
01F3A0: 4EB8 2FEC             jsr      $2FEC.w
002FEC: 214C 001C             move.l   A4, ($1C,A0)
002FF0: 6000 0022             bra      $3014
003014: 2868 001C             movea.l  ($1C,A0), A4
003018: 315C 0020             move.w   (A4)+, ($20,A0)
00301C: 315C 0058             move.w   (A4)+, ($58,A0)
003020: 315C 0022             move.w   (A4)+, ($22,A0)
003024: 215C 0024             move.l   (A4)+, ($24,A0)

Note the lea operation changes the A4 value to 0x0001F46A and goes to fire sub function (PPC=0x01F39C, PC=PPC+2=0x01F39E, A4=0x01F39E+0x00CC=0x0001F46A).

Image 15

M68000 debugger

Debug similarly for ice sprite ("2" record input), and get the following disassembly information:

ASM
001D80: 3B41 2816             move.w   D1, ($2816,A5)
001D84: 4E75                  rts     
01F3DC: 49FA 04C0             lea      ($4C0,PC), A4
01F3E0: 4EB8 2FEC             jsr      $2FEC.w
002FEC: 214C 001C             move.l   A4, ($1C,A0)
002FF0: 6000 0022             bra      $3014
003014: 2868 001C             movea.l  ($1C,A0), A4
003018: 315C 0020             move.w   (A4)+, ($20,A0)
00301C: 315C 0058             move.w   (A4)+, ($58,A0)
003020: 315C 0022             move.w   (A4)+, ($22,A0)
003024: 215C 0024             move.l   (A4)+, ($24,A0)

Note the lea operation changes the A4 value to 0x0001F89E and goes to ice sub function (PPC=0x01F3DC, PC=PPC+2=0x01F3DE, A4=0x01F3DE+0x04C0=0x0001F89E).

If I change the PPC=0x01F39C operation "lea      ($CC,PC), A4" to "lea      ($0500,PC), A4" (0x01F39E+0x0500=0x01F3DE+0x04C0=0x01F89E), the Captain will discharges ice. So the IPS command is (see "ips\captcomm.cht"):

[captain discharge]
fire=01F39E,00;01F39F,CC
ice=01F39E,05;01F39F,00

3. The Punisher, Always Gun

There is the following code in the MAME cheat file "punisher.xml":

XML
<cheat desc="Always have Gun drawn">
        <script state="run">
                <action>main.pb@FF5D96=01</action>
        </script>
</cheat>

So I modify "mame\cps\Memory.cs" and insert breakpoint as follows and play the game:

Image 16

Modify source

I find the following PPC code frequently writes mainram[0x5D96] to zero (A5=0xFFFF8000):

ASM
0268E6: 422D DD96             clr.b    ($DD96,A5)

I read the M68000 operation code and find BSETr operation is similar to CLR operation. BSETr writes nonzero and CLR writes zero. If I patch the M68000 ROM to:

ASM
0268E6: 01ED DD96             bset     D0, ($DD96,A5)

The player will always have gun drawn.

Image 17

Always gun

In the shootout scene, the following PPC code frequently writes mainram[0x5D96] to nonzero (A5=0xFFFF8000):

ASM
05E93E: 522D DD96             addq.b   1, ($DD96,A5)

If I patch the M68000 ROM to:

ASM
0268E6: 522D DD96             addq.b   1, ($DD96,A5)

The player will always have gun drawn too.

If I patch the M68000 ROM to:

ASM
0268E6: 4E71                  nop
0268E8: 4E71                  nop

or:

ASM
0268E6: 422D 8000             clr.b    ($8000,A5)

I disable the frequently "write mainram[0x5D96] to zero" operation. Once the player draws the gun, he will never withdraw the gun. So I make the IPS file "ips\punisher.cht".

Warriors of Fate Support

How to add new support for a bootleg game?

  1. Download original ROMs.
  2. Modify MAME code and dump ROMs from running MAME.
  3. Add a common driver for the bootleg game and disassemble the M68000 code.
  4. Change CPS parameters and add customized driver until the bootleg game runs OK.

I've added some common and bootleg series of Warriors of Fate:

Image 18

Warriors of Fate (World 921002) [wof]

Image 19

Warriors of Fate (US 921031) [wofu]

Image 20

Sangokushi II (Asia 921005) [wofa]

Image 21

Tenchi wo Kurau II - Sekiheki no Tatakai (Japan 921031) [wofj]

Image 22

Sangokushi II: San Jian Sheng (Chinese bootleg set 1, 921005 Asia) [wof3js]

Image 23

Tenchi wo Kurau II - Sekiheki no Tatakai (Japan 921031) (Chinese translation) [wofcn]

Image 24

Huo Feng Huang (Chinese bootleg of Sangokushi II) [wofhfh]

Image 25

Sangokushi II: Sheng Jian Sanguo (Chinese bootleg) [wofsj]

Image 26

Sangokushi II: San Sheng Jian (Chinese bootleg) [wof3sj]

Image 27

Sangokushi II: San Jian Sheng (Chinese bootleg set 2, 921005 Asia) [wof3jsa]

Image 28

Warriors of Fate ('sgyxz' bootleg) [sgyxz]
Image 29
Warriors of Fate: 1v3 (Chinese bootleg) [wof1v3]
Image 30
Tenchi wo Kurau II: Da Ren (Chinese bootleg) [wofdr]
Image 31
Tenchi wo Kurau II: Da Ren 2020 (Chinese bootleg) [wofdr2020]
Image 32
Tenchi wo Kurau II: Wu Shuang Jia Qiang (Chinese bootleg) [wofdwp]
Image 33
Tenchi wo Kurau II: Dou Zhi (Chinese bootleg) [wofdz]
Image 34
Tenchi wo Kurau II: San Mei (Chinese bootleg) [wofsm]
Image 35
Tenchi wo Kurau II: Xia Hou En Fu Chou (Chinese bootleg) [wofx]
Image 36
Tenchi wo Kurau II: Zhan Lang (Chinese bootleg) [wofzl]

I've extracted the following information from "maincpu.rom" and "gfx.rom" of ROMs.

English 日本語 简体中文
Shang-Lo: a country ruled by murder and violence under the iron fist of the dark lord Akkila-Orkhan. Having driven his own country into ruin and despair, Akkila-Orkhan now casts his covetous eyes on his neighboring countries. As his conquering shadow spread, one man rose up against this black tide. His name was Kuan-Ti, and with the aid of the five greatest warriors and the one wisest mind in his realm, Kuan-Ti would fight to defend his people and lands. The battle begins... 2200年まえ、中国たいりくに漢とよばれろ帝国があった。劉邦がきずいた漢帝国も400年をすぎ、ついに乱れろときがやってきた。混乱にじようじて政權をにぎった董卓は、暴虐のかぎりをつくし、民をくろしめた。漢王朝の血をひく劉備は關羽、張飛、趙雲とともに連合军にくわわり、董卓の野望をうちくだいた。それから7年漢の1/3を手にいれた曹操はみずからを魏王となのり、劉備たちのすひ荊州に攻めcんできた。 距今2200年前,刘邦建立汉朝。400年后,汉朝分裂,天下大乱。混乱之中,政权落入了董卓之手。残暴的统治,令百姓民不聊生,哀嚎遍野。拥有汉室血统的刘备,联同关羽、张飞、赵云一起加入了联合军,粉碎了董卓的野心。七年后,汉朝1/3的领土落入了曹操手中。他自立为魏王,起兵攻打驻荆州的刘备。
With the defeat of Akkila-Orkhan, Kuan-Ti soon rebuilt his kingdom. With peace and prosperity restored to the land, he began a long and glorious reign which was remembered and celebrated for generations. 劉備は漢王朝を復興させた。人びとは平和なくらしをとりもどした。 刘备复兴了汉王朝。人们又重新过上了和平的生活。
Akkila-Orkhan soon returned and with help of his minions, he quickly conquered the country. Crushing any dissent in his iron fist. 国にかえった曹操は劉備をたおすcとに力をそそぎ国力を回復すろと荊州へ攻めcみ、cれを制压した。 回国后的曹操为打败刘备全力备战。国力恢复后就立刻向荆州进攻,占领了荆州。
  国にかえった曹操は劉備との戰いに勝てなくなり魏、吳、蜀の3国がけいせいされていく••• 回国后的曹操没能战胜刘备。魏、吴、蜀三国鼎立的局面逐渐形成…

Conclusion

I've finished CPS1.NET. It figures out how CPS1 games work. You can make any other CPS1 game supported by referring to MAME source codes. By the translation from C to C#, there is little unsafe code and the code is much more readable. I've preserved the main architecture of MAME. Programmers can refer to the CPS1.NET source code and emulate more M68000 and Z80 based game systems by C#.

History

  • 2015-09-01: Finish CPS1.NET (build 20150901)
  • 2016-01-25: Improve the code and the architecture (build 20160125)
  • 2016-04-29: Add support for series of Warriors of Fate (build 20160429)
  • 2016-08-01: Support 191 games (build 20160801)
  • 2018-01-09: Improve the code and the architecture, support 192 games (build 20180109)
  • 2018-12-27: Fix mercs error (build 20181227)
  • 2021-04-04: Add 8 bootleg games, support 200 games (build 20210404)

References

  1. MAME-Multiple Arcade Machine Emulator - https://github.com/mamedev
  2. MSDN - https://msdn.microsoft.com
  3. bizhawk M68000 and Z80 code - https://github.com/TASVideos/BizHawk/tree/master/src/BizHawk.Emulation.Cores/CPUs
  4. VCMAME detail by Bryan McPhail - https://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. M1.NET - https://www.codeproject.com/Tips/646359/M-NET

License

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