Earlier this year, I wrote a nifty corruptor for the cult DOS racing game Rally-Sport, which lets you corrupt and play the game in your favorite browser. You can run the corruptor here, and find its source code here.
In this blog post, I'll go over the corruptor's implementation details. It's a relatively simple program overall, using vanilla JavaScript and some existing functionality to keep the codebase nicely minimalistic.
In case you're wondering what a corruptor is, here's a take from corrupt.wiki:
The act of "corrupting games" is taking a video game and breaking it using whatever means necessary, usually with a program called a corruptor. This software can modify the game's files to produce unexpected or unusual graphics, gameplay or audio.
This particular corruptor is a web app consisting of two main parts: the part where you select and apply corruptions, and the part where you play the corrupted game.
The app's HTML is correspondingly simple (paraphrasing):
<body> <iframe id='rs-iframe'/> <main id='control-panel'/> <script src='rs.js'/> </body>
The <iframe> displays a DOSBox web frontend that I've written earlier. It loads the game in a browser-based DOSBox and applies selected corruptions to the game's files.
The control panel provides the user a selectable list of the available corruptions. Note that corruptions are called mutations here.
The <script> runs the app's JavaScript code, which populates the control panel and defines some glue logic to link the control panel to the DOSBox frontend iframe.
As noted above, the control panel is where the user finds the list of available corruptions. The panel is populated from a JSON-like JavaScript file containing the available pre-defined corruptions:
export default { 'RC cars': { payload: [ // Offset 28879 is the start of a routine to scale car meshes. We'll put // a RET instruction there to prevent the meshes from being scaled, which // leads to the cars being quite small. 'byte rallye.exe 28879 195', ], author: 'Tarpeeksi Hyvae Soft', id: '359df72246af', }, ... }
Each property in the exported object defines one corruption. The name of the corruption is given by the property key (e.g. "RC cars"), and the payload sub-property defines the actual corruption – one or more bytes modified in the game's asset files to produce the desired corruptive effect.
The app's JavaScript parses the object to populate the control panel with selectable corruptions:
When a corruption is toggled in the control panel, the app concatenates all selected corruptions' payload strings and inserts them into the <iframe>'s src attribute, which causes the DOSBox frontend to restart the game with those corruptions applied. In the next section, we'll go over how that happens.
As outlined above, the corruptor uses a custom DOSBox frontend to run the game in an <iframe>. Before reading further, you're encouraged to read a bit about how the frontend works.
If we assume that the frontend is hosted at "localhost/dosbox", the <iframe>'s src attribute will point to "localhost/dosbox/#/rally-sport/rs", as per this configuration of the frontend:
'^/?rally-sport/rs/?$': { title: 'Rally-Sport (RS)', zip: './content/rally-sport/rs/rallys.zip', persist: '/rs-mutat', run: '?run', }
The file ./content/rally-sport/rs/rallys.zip contains the demo version of Rally-Sport. Its contents are loaded through the frontend into DOSBox's emulated DOS sandbox.
The run attribute instructs the frontend to look in the URL's run parameter for the command(s) to be executed in the emulated DOS environment once the emulation has started. For example, if the URL is "localhost/dosbox/?run=[rally]#/rally-sport/rs", the command rally will be executed, which in the DOS environment invokes the RALLY.BAT batch file to start the game.
The default run parameter that's passed to the <iframe> is like so:
?run=[ 'copy rallye.org rallye.exe', 'rally' ]
This formulation of the parameter first resets any previous corruptions to the game's main executable by overwriting it with a clean version of the file, then starts the game.
When any corruptions are selected, their payloads are inserted into the run paremeter. For example, with the payload of the "RC cars" corruption:
?run=[ 'copy rallye.org rallye.exe', 'byte rallye.exe 28879 195', 'rally' ]
The byte command invokes in the emulated DOS environment a custom BYTE.EXE tool included in the rallys.zip archive that modifies the value of a byte at a given index in a given file. In this case, the tool is instructed to set the byte at index 28879 in RALLYE.EXE to a value of 195 (which corresponds in x86 assembly to a RET instruction), making the game's cars tiny.
The app is hosted on GitHub Pages, with the repository being automatically deployed. Users of the app can submit new corruptions by opening a pull request and having it merged.