What's new

Paranoid_Andy

Enthusiast
Joined
Mar 1, 2018
Messages
156
Reaction score
75
Location
Florida USA
Changing DIPs each time I change the game on the CPS1 or any multi is kind of a hassle. So it had me thinking. Can you change the way a ROM interprets DIP settings?

If so, that means that you could set all your multi DIPs to one permanent position, then modify your game ROM file to interpret those DIP settings the way you prefer and never have to change them again. If you did want to change the DIPs sometimes, maybe to increase the difficulty of a game, you could just have a ROM file for medium and a ROM for hard difficulty instead.

My programming experience is limited to Windows games but I feel like something like this may be possible however I'm not certain as I've never made/ported a game for another platform.

If so, I think this could make using any multi much more convenient.
 
Last edited:
Of course it's possible. It's quite an undertaking to rom hack all games though.
 
With enough reverse engineering, I believe this is definitely possible. A DIP switch is usually just an interrupt flag, just like a button. It's either on or off, so if you can find the routine in the ROM's data that pulls that interrupt value, you can change that value if necessary.

For example in my reverse engineering of Sonic the Fighters, there's a flag that indicates which DIPs are enabled. The most popular emulator for the Model2 games has hard-coded all DIPs to the "On" position without any way to turn them off, as some games had extra settings enabled in the service menu with specific dips. However, if the code to enable debug mode is entered, debug mode checks DIP-7 and if enabled removes the foreground layer, so menus cannot be navigated. Thankfully, in the ROM data, there is a flag that checks if the DIP position is enabled, and I can disable that to allow the m2emulator to run the game in debug mode with the foreground layer!

In my own humble opinion, flipping a switch to change difficulty on a game board is easier than swapping a ROM chip, or worse, multiple ROM chips, and owning multiple ROM sets of the same game seems like a costly investment compared to... the switches that exist on the board already. I feel like extending the DIP switch to an easier-to-reach location from the board might be the most simple and cost effective solution if you really do swap multi that frequently.
 
Very interesting. Thank you for the information. I was thinking that maybe firing the game up in emulator, then changing a dip and pausing the game on the same frame would maybe make dissecting the exact location of the dip easier. I'll have to think it over when I have more time.
 
Maybe this can get you started.

The dips are documented in MAME, no need to go to the trouble above to find them. Most are standard but the cps1.cpp driver notes the exceptions.

The standard:

void cps_state::main_map(address_map &map)
{
map(0x000000, 0x3fffff).rom();
map(0x800000, 0x800007).portr("IN1"); /* Player input ports */
/* forgottn, willow, cawing, nemo, varth read from 800010. Probably debug input leftover from development */
map(0x800018, 0x80001f).r(FUNC(cps_state::cps1_dsw_r)); /* System input ports / Dip Switches */

So boot with debugger (e.g. 'mame -debug strider') and open a memory window and look at 0x800018

1696820988562.png


That's the dips.

But the tedious part is editing every game's program files to adjust things around. I just pulled strider at random, you can toggle Difficulty and see the byte at 80001C move. So you can set a watchpoint to see what code is reading it:

wpset 80001C,2,r

Program code at 0x6A0 (at least) reads it. You will 100% need to search for more places that read in that dip value, that's just the first watchpoint that I ran across immediately. So if you wanted the game to look at another dip to use for the Difficulty toggle, you'd edit the binary there to watch another dip instead (and you should adjust the code that reads the other dip vice versa)

1696821171671.png


So idk, maybe 1039 0080 001F instead of 001C. Then you'd find all the references to the 1F dip and move those to 1C instead. Now you've swapped those dip functions, if you found all the code that reads them.

By the way the roms are interleaved so you're editing between two files (or merging them, making the edits, then splitting them)

ROM_START( strider )
ROM_REGION( CODE_SIZE, "maincpu", 0 ) /* 68000 code */
ROM_LOAD16_BYTE( "30.11f", 0x00000, 0x20000, CRC(da997474) SHA1(3e4ac98f9a6967d61899281b31c7de779723397b) )
ROM_LOAD16_BYTE( "35.11h", 0x00001, 0x20000, CRC(5463aaa3) SHA1(e2d07ec2d818e9a2e2d7a77ff0309ae4011c0083) )
 
@ekorz
Yes! That can get me started. This is very helpful information. I'm not sure if I will be able to accomplish what I want but it certainly helps me with at least 'attempting' to do it.
I wasn't expecting such a detailed answer. Thanks a ton!
 
Back
Top