[utopian-io] ips-util - Python package for manipulating IPS patches
Background
The International Patching System (IPS) patch format is a historically popular distribution format for ROM hacks. It's a very simple format, and a number of tools exist for creating IPS patches from binary data. I wanted to be able to create IPS patches programatically in Python scripts, however, and no existing library provided that support. So I made one.
I got enough testing and polish done on the library that I chose to upload it to PyPI as a formal Python package. As such, a released version can be acquired by any Python user with pip install ips-util
.
Links
Usage notes
(Pretty much straight from the README.)
To create a patch, using existing source and target binary files:
> ips_util create "Super Mario World.smc" "Super Mario World [1337357_h4x_3v4r].smc" -o 1337_p47ch.ips
To apply a patch to a binary file:
> ips_util apply 1337_p47ch.ips "Super Mario World.smc" -o w00t.smc
To dump the contents of a patch:
> ips_util trace 1337_p47ch.ips
The package can also be used within Python scripts to build IPS patches manually, as follows:
from ips_util import Patch
def this_is_my_patch():
patch = Patch()
patch.add_record(0x1234, 999.to_bytes(2, byteorder='little')) # Max out some stat
patch.add_rle_record(0x5678, b'\xea', 0x10) # NOP out a bunch of code
with open('gavroche.ips', 'w+b') as f:
f.write(patch.encode())
Testing
The package includes unit tests (contained in the ips_util/tests/test_patch.py
script) to verify design requirements and some common edge cases in IPS format:
Manually created patches
- Verify that a basic patch produces the desired result (
test_patch_core
) - Verify that a change made past the end of the original data will pad the result data as needed (
test_patch_padding
) - Verify that the truncation syntax used by some IPS tools functions as intended (
test_patch_truncation
) - Verify that the library generates an error when the starting address of a patch record is exactly 0x454f46 ('EOF') (
test_patch_eof_edge_case
)
Patches created from source and target binary data (the Patch.create()
API)
- Verify that the patch created from binary data reproduces the desired target data when applied (
test_create_equal_length
) - Verify that creating a patch correctly handles padding when the target data is longer than the source data (
test_create_padded_length
)- ... even when the padded data contains only zeros. (
test_create_padded_length_all_zero
)
- ... even when the padded data contains only zeros. (
- Verify that creating a patch correctly handles truncation when the target data is shorter than the source data (
test_create_truncated_length
) - Verify that when a difference occurs at the address 0x454f46, the generated patch shifts that address to avoid the EOF error noted above (
test_create_eof_edge_case
) - Verify that an error is generated when the binary data provided is longer than the maximum supported address (
test_create_address_overflow
) - Verify that when creating a patch, differences longer than the maximum supported size are handled gracefully (
test_create_size_overflow
)- ... even when the record is run-length encoded (
test_create_rle_size_overflow
)
- ... even when the record is run-length encoded (
Thank you for your contribution. I am a fan of the vintage game consoles e.g. 8-bit super mario. So does this utility work on 8-bit ROM files?
From the documentation, I can see it is a complete and useful tool and good job for putting it on
pip
.testdata
directories.Path.load
will probably throw exception?Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Thank you for your review, @justyy! Keep up the good work!
Hey, @nleseul!
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Congratulations @nleseul! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Click here to view your Board
If you no longer want to receive notifications, reply to this comment with the word
STOP
To support your work, I also upvoted your post!
Do not miss the last post from @steemitboard:
Hi @nleseul!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server