I helped with defeating the CPS-2 encryption scheme.
It all comes down to the function code pins on the CPU, which change depending on what kind of data you are fetching (regular data or program instructions) and whether you're in supervisor or user mode.
FC1, FC0: 01 = data, 10 = program
FC2: 0 = user, 1 = system
The encryption enable line is tied to FC2 and FC1, so it's only active when fetching program instructions in user mode. The reason for this is that the reset vector, which is accessed as supervisor program data, cannot be encrypted, otherwise the initial program counter and stack pointer would be wrong.
So, you could take over the interrupt table and run instructions in an ISR, but you still had a problem. If you tried to do MOVE (a0), d0 for example, it would try to read (a0) with the DATA function code, which would not activate decryption.
BUT...
The m68k manual states: Data items in the instruction stream can be accessed with the program counter relative addressing modes; these accesses classify as program references.
So, all you needed to do is use PC-relative addressing within an ISR, which can access the entire memory space if you program it right, and then just stream the whole program ROM out, decrypted, via whatever means you wanted.
This worked, but for some reason, the encryption chip would mysteriously shut down after a very short while.
This final puzzle piece could have remained a mystery forever, if Capcom hadn't inadvertently spilled the beans.
In a bid to enter the high end home market, Capcom released a "home" version of their CPS-1 system, along with very slightly modified versions of all their classic CPS-1 games. Their mistake came when they decided to port some CPS-2 games to CPS-1 (the systems were close enough to do it without too much difficulty). If you look at the program code in the CPS-2 converted titles, you'll notice a weird MOVE instruction that is sprinkled throughout the code, yet doesn't seem to do anything useful.
This is the final piece of the puzzle. That specific move instruction is read by the encryption chip, and used as a "keep alive". If enough time passes without that pattern being on the data bus, the encryption chip shuts down permanently, until you turn off power.
So all you needed to do is inject that MOVE instruction while you were reading out the program ROM using PC-relative MOVEs from your custom exception routine.
You know, I hate articles like this. They get you hooked, much like the pilot of a TV series - then say "wait until next week when we find out...etc".
But I don't follow individual sites much - rather aggregators like HN. Most likely, when the follow-up does appear, HN won't have it posted (unless someone submits it - which is a possibility).
I dunno - I understand why this is done from a business perspective (and maybe from a practical perspective - maybe the rest of the write-up hasn't been written up yet!) - but I would just rather wait until its all there, then plow thru the whole thing in one shot.
As it stands - with this and other articles in the past - I might revisit it, but its doubtful that I'll remember.
It's too bad - I like the topic, and it sounds very interesting.
RSS is a partial solution, in that it lets you follow the site posting the story. I will never understand why it's losing popularity so much. (Aside from the death of Google Reader, which shouldn't have caused that on its own.)
I worked at a game company that (among other things) made “retro” game collections of Capcom and Atari games for PS2 and Xbox 360. Even they didn’t have the source code for most of the smaller titles; we had to reverse nearly all of them.
I've heard that one approach to these kinds of projects (small number of games, no original source code) is to translate the code to (really ugly) C and compile that into a library-like blob; this can require manual intervention for runtime-dispatched jumps, overlays/mappers, and other dynamic oddities. At that point you can start using host/target debugging tools and it's "just" a matter of finding the entry points and data structures that you care about (player inputs, graphics patterns/palettes/coordinates, timers, etc.) instead of trying to RE the entire ball of mud.
Come to think of it, I think I remember reading about someone that did that with some DOS-era games to port them to ARM handheld game systems. I've got a similar target in mind. I've played with manually translating some of the assembly listings to C. Maybe I ought to continue going down that road, or seeing if some previous work has made some tools to help automate it.
It all comes down to the function code pins on the CPU, which change depending on what kind of data you are fetching (regular data or program instructions) and whether you're in supervisor or user mode.
FC1, FC0: 01 = data, 10 = program FC2: 0 = user, 1 = system
The encryption enable line is tied to FC2 and FC1, so it's only active when fetching program instructions in user mode. The reason for this is that the reset vector, which is accessed as supervisor program data, cannot be encrypted, otherwise the initial program counter and stack pointer would be wrong.
So, you could take over the interrupt table and run instructions in an ISR, but you still had a problem. If you tried to do MOVE (a0), d0 for example, it would try to read (a0) with the DATA function code, which would not activate decryption.
BUT...
The m68k manual states: Data items in the instruction stream can be accessed with the program counter relative addressing modes; these accesses classify as program references.
So, all you needed to do is use PC-relative addressing within an ISR, which can access the entire memory space if you program it right, and then just stream the whole program ROM out, decrypted, via whatever means you wanted.
This worked, but for some reason, the encryption chip would mysteriously shut down after a very short while.
This final puzzle piece could have remained a mystery forever, if Capcom hadn't inadvertently spilled the beans.
In a bid to enter the high end home market, Capcom released a "home" version of their CPS-1 system, along with very slightly modified versions of all their classic CPS-1 games. Their mistake came when they decided to port some CPS-2 games to CPS-1 (the systems were close enough to do it without too much difficulty). If you look at the program code in the CPS-2 converted titles, you'll notice a weird MOVE instruction that is sprinkled throughout the code, yet doesn't seem to do anything useful.
This is the final piece of the puzzle. That specific move instruction is read by the encryption chip, and used as a "keep alive". If enough time passes without that pattern being on the data bus, the encryption chip shuts down permanently, until you turn off power.
So all you needed to do is inject that MOVE instruction while you were reading out the program ROM using PC-relative MOVEs from your custom exception routine.