Pachy98 – A Patching Tool for the PC-98


GitHub

Download

Pachy98 for Windows v0.20.1 – zip – 5320 download(s) – 6 MB Pachy98 for Mac v0.20.1 – zip – 1102 download(s) – 7 MB

Changelog

0.20.0

– Pachy98 can now generate config json files. Syntax: ./pachy98 -generate Disk1.fdi Disk2.fdi Disk1Patched.fdi Disk2Patched.fdi
– First release also for Mac OS X.
– Add support for FDD and SLF disk images.
– schema.json is now bundled into the application, rather than a loose file.
– Fix a false complaint about invalid translation versions.

[collapse]

0.19.1

– HDD images can now be auto-detected even when the floppy version contians a unique file not found on the HDD.
– Fixes a crash that involved a missing DLL on some systems.
– Significant code refactoring and improvements by @meunierd, leading toward future Mac/Linux support.
– Pachy98 .json configs are checked against an included json schema.

[collapse]

0.17.3

– Pachy98 will now properly find and patch game files located in separate disk directories.
– Pachy98 can now detect disk volumes.
– Added support for XDF and DUP images, allowing users to patch Sharp X68000 disk images.
– A “mixed” type disk is no longer required in the image with id 0.
– The “options” array is no longer required.
– Pachy98 now skips malformed .json config files, instead of crashing when it accesses them.

[collapse]

Overview

Pachy98 is a tool to help automate patching floppy/hard disk images for end-users in a more efficient manner than simply utilizing xDelta or IPS alone.

Using a standard xDelta or IPS patch to target a specific disk image is a pretty error-prone way to modify PC games. These games usually store save files on a disk, which means saving the game will change the disk’s checksum, preventing a patch from recognizing it. Users either have to hope they find the specific disk images that is being targeted by the patch, or the creator of the patch will have to make patches for every version of the specific disk image floating around the internet. Not fun for either party.

With Pachy98, a patch creator may target specific files to be patched from a given disk. The files on the disk are less likely to be different and more easy to patch, making it so that an end-user could have one of many dumps, or even make their own dump of a disk, and Pachy98 could still target and patch the necessary files correctly while ignoring any differences on the rest of the disk (save files, for example).

How’s it Work?

First, the patch creator figures out what files they need to modify to achieve their goal with the game or software. In our case, that’s translating the game into English. Once done with the modifications to these files, the patch creator will then create xDelta patch files for each of the files that they modified and create a config file to tell Pachy98 what files need to be patched on which disks and distribute this config file and the patch files to the end-user. The end-user will take these and put them in their Pachy98 directory with their own personal images of the game/software, then run Pachy98.

Pachy98 will check its root directory for any disk images or bare files as instructed by the config file and ascertain which of the images contain the files that need to be patched. It will ask the user if the images are correct, and if so, it will start the patching process.

At this point, Pachy98 operates like a batch file and runs a bunch of command line instructions using two separate programs. The first is NDC, a Japanese command line utility which we use to look inside of images and extract/delete/import files from and into the specified images. The second is xDelta itself, which applies the patches for each of the files as specified in the config file from the patch creator. Once it has applied the proper patch to each of the files the patch creator specified in their respective disk images, the end-user will now have a freshly patched disk image.

It is worth it to note that backups are made in the Pachy98/backup directory in case the patching process fails or you want to use the pre-patched images again.

Pachy98 for Patch Creators

If you want to use Pachy98 to distribute a translation or modification to end-users, then this section is for you! If you just want to apply patches to your games, you don’t really need to read any further.

Does Pachy98 support the disk formats you’ll be targeting? All common PC-98 disk formats are supported, along with many used in other retro Japanese PC games.

fdi, hdi, hdm, dip, flp, vmdk, dsk, vfd, vhd, hdd, img, d88, fdd, tfd, thd, nfd, nhd, h0, h1, h2, h3, h4, slh, dcp, xdf, dup, slp

If so, first you’ll need to generate an individual xdelta3 patch for each of the files you’ll want to patch. Syntax for creating a patch with xdelta3.exe is as follows:

xdelta3.exe -e -s "ORIGINAL.IMG" "EDITED.IMG" "patch\ORIGINAL.IMG.xdelta"

Gather all the patches and put them in Pachy98’s “patch” directory.

Next you’ll want to write a Pachy98 config file.

We’ve prepared a commented sample config file here: Pachy98-sample.json. Alternatively you can look at the concrete examples of the config files we’ve used before:

If you take a look at the sample config file, you’ll see that first you’ll need to include information about the patch itself in the info object. The required variables here are “game”, “language”, “version”, and “author”. These will be displayed to the user when they start up Pachy98 using the config file and help the user to know exactly what it is your patch is going to be doing. Pretty self explanatory.

The other optional variables in the info object are “authorsite”, “versionurl”, and “downloadurl”. “versionurl” is used internally by Pachy98 to check to see if the user is using the latest version of your patch. Pachy98 will check the first line of the file at that URL for a string of numbers, and then compare that to the patch version that you specified above. If the file’s version is lower than the version at that URL, the user will be notified that there’s a newer version available at “downloadurl.” This user can continue applying the older patch they have if they wish.

Here’s an example of an info object that you’d normally see at the top of the JSON config:

"info":
 {
    "game": "E.V.O.: The Theory of Evolution",
    "language": "English",
    "version": "v1.1.1",
    "author": "46 OkuMen",
    "authorsite": "http://46okumen.com",
    "versionurl": "http://46okumen.com/translations/EVO/version.txt",
    "downloadurl": "http://46okumen.com/projects/e-v-o-the-theory-of-evolution"
 }

The next thing you’ll want to do is tell Pachy98 which files to patch, and where those files should be. We’ll use E.V.O. again for this example, since we needed to maintain support for users that had 4 floppy disk images, as well as users that had one hard disk image.

First, you’ll need to create an images array. Our array for E.V.O. will contain 4 objects. Since we want our patch to target either one HDD image or four floppy disk images, we’ll use the “mixed” media type for the first element. This tells Pachy98 that if it can find a hard disk image containing all of the files listed for it in this particular element, then ignore the floppy disks in the config. Otherwise, try the floppy disks.

Here’s an abbreviated example of a “mixed” type object inside of an images array, and 3 extra blank floppy disks.

"images":[
    {
       "id":0,
       "name":"HDI/User Disk",
       "type":"mixed",
       "floppy": {
          "files":[
             {
                // abbreviated for later
             }
          ]
       },
       "hdd": {
          "files":[
             {
                // abbreviated for later
             }
          ]
       }
    },
    {
       "id":1,
       "name":"Disk B2",
       "type":"floppy",
       "floppy": {
          "files":[
             {
                // abbreviated for later
             }
          ]
       }
    },
    {
       "id":2,
       "name":"Disk B3",
       "type":"floppy",
       "floppy": {
          "files":[
             {
                // abbreviated for later
             }
          ]
       }
    },
    {
       "id":3,
       "name":"Disk B4",
       "type":"floppy",
       "floppy": {
          "files":[
             {
                // abbreviated for later
             }
          ]
       }
    }
 }

As you can see, there are four elements in the array, one for each of the disks with the mixed media type including both a disk and a hard drive type. This tells Pachy98 all it needs to know about the disk types to expect from end-users. The last step here is filling out that “files” array and telling Pachy98 what files to expect. This can generally be a simple array of files with the names of the xdelta patches you created above, or you can use a number of options to allow for a much more customizable patch.

To continue with our E.V.O. example, one of the things we ran into was that the game had to be hacked to run from a hard disk image. This created two different 46.EXE files with different checksums, and we wanted to make sure that if a user was patching a hard disk image of the game, they need to have their 46.EXE patched to the HDD-compatible version if necessary. To accomplish this, we added a failsafelist patch type that will try to patch 46.EXE first to the hacked hard disk version necessary to play on a hard disk, and then patch that resulting file with our English text. This is good because if that first patch fails it doesn’t really matter, as the user could have a proper hard disk image with that particular hack already applied. The final patch has to succeed though, otherwise we know the user isn’t using any version of the game we’re expecting, and patching fails.

Here’s an example of that inside of the files array, as well as a standard file patch.

"files":[
    {
       "name":"OPENING.EXE",
       "patch":"OPENING.EXE.xdelta"
    },
    {
       "name":"46.EXE",
       "patch":{
          "type":"failsafelist",
          "list":[
             "FtoH_46.EXE.xdelta",
             "HDI_46.EXE.xdelta"
          ]
       }
    }
 ]

You’ll need to create an entry in files for every file you want to patch and include the corresponding patch or option, like this. It can get rather long, so you may want to try to generate the list with a script, depending on how your toolset works. Not necessary, and you can make these by hand of course.

That’s the basic information you’ll need to create these JSON config files, but there are still a few more options that you’ll want to know about! We’ve included a method of asking end-users to choose certain customizable aspects of your patch.

Say you’ve done a cool thing but it only works on one set of emulators, but you still want to support other emulators and also include a version that doesn’t do that one thing. Luckily, we’ve got a good example in this, since we had to do just that for Rusty. You’d first need to add an element into the options array at the bottom of the config file. The “id” can be anything you want, but the “type” will have to be one of a couple of options here. The main one we’re concerned with for this is “boolean”. The element in the options array will look like this, and the “description” will be the question that the end-user is prompted with.

"options":[
    {
       "id":"speedhack",
       "type":"boolean",
       "description": "Faster text speed in cut scenes? (Requires Neko Project II)"
    }
 ]

In the above example, the user would see this question before patching and be given the option to choose yes or no. The next thing you’ll need to do is find the specific files that need to be one way or the other and modify their entries in the proper files arrays to look something more like this.

"files":[
    {
       "name":"VISUAL.COM",
       "patch":{
          "type":"boolean",
          "id":"speedhack",
          "false":"VISUAL.COM.xdelta",
          "true":"VISUAL_speedhack.COM.xdelta"
       }
    }
 ]

Notice that the “id” variable is the same as the “id” variable in the options array. This tells Pachy98 that the way the user answers the yes or no question affects which of the two patches are applied here. You can use as many options as you want and customize things as much as you want, but only with yes or no questions at present.

There’s also a more obscure hard-coded option that helps if you’re patching something that just barely fits on the disks. If you have an option with “id”: “delete_all_first” and “type”: “silent”, the patcher will delete and insert the files in batches, rather than deleting and inserting one after another. Strange, but necessary for patching Rusty floppy disks, as it turns out.

(These are just the options we’ve needed to implement for our projects. Let us know if there’s any other options or functionality that would be helpful to you!)

As is, that’s really all you need to know to make a config file. One useful tool that we recommend if you’re doing this by hand is the JSON Validator over at jsonlint.com. Your config file will have to work when pasted in there in order for it to work with Pachy98.

You can always grab any of our patches or config files and just modify them to work for your patches as well, just make sure you pay attention to the formatting and it’ll all be fine!

A Note on the Name

Pachy98 is named for E.V.O.‘s Pachycephalosaurus. Someone pointed out to us that Windows activates UAC whenever a program has “patch” in the name, so we wanted something that would almost have “patch” in it.

Useful Links

JSON Validator
NDC
xDelta

All Versions

  • Pachy98 for Mac
    Pachy98 for Mac
    Version
    Size
    Date
    DLs
    7 MB
    Apr 10, 2018 - 15:31
    1102
    7 MB
    Apr 08, 2018 - 00:31
    458
  • Pachy98 for Windows
    Pachy98 for Windows
    Version
    Size
    Date
    DLs
    6 MB
    Apr 10, 2018 - 15:30
    5320
    6 MB
    Apr 08, 2018 - 00:29
    499
    6 MB
    Dec 09, 2017 - 23:35
    661
    5 MB
    Jul 10, 2017 - 02:33
    475
    5 MB
    Jul 04, 2017 - 21:54
    498