ips-patcher 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -2
- data/README.md +11 -1
- data/lib/ips/patcher/version.rb +1 -1
- data/lib/ips/patcher.rb +20 -8
- metadata +2 -3
- data/sig/ips/patcher.rbs +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f826901f510e6aa84902f901dc38eb470b42797f7bc4c422201df82b4acb432a
|
|
4
|
+
data.tar.gz: cfaaa43d70bbbd3ce7f402bdbcad30e5eae21677fb686e3b5e522fc50d90519c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8daacbc64f5e5ed5e4a983c5a9e4a77fa9dc9478bc74f09207023d238e504b7427e093cc13d08f8eafe5fd04ba5e5743b8707f7911fc02c5125e1cc1b5cc9845
|
|
7
|
+
data.tar.gz: 606df2d9801958470c46247d6b170f253a6780f2b2caa9fadc8884c58dab93b58866d10079a9d4e2f01cfbba1b2a501c2d4284e4d397fe6b80bb8ee68040f2db
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.1] - 2026-01-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Optional `output` parameter to `Ips::Patcher.apply` method for specifying custom output file path
|
|
2
12
|
|
|
3
13
|
## [0.1.0] - 2026-01-20
|
|
4
14
|
|
|
5
|
-
|
|
15
|
+
### Added
|
|
16
|
+
- Initial release of ips-patcher gem
|
|
17
|
+
- `Ips::Patcher.apply` method for applying IPS patches to ROM files
|
|
18
|
+
- Support for standard IPS records (byte replacement at specific offsets)
|
|
19
|
+
- Support for RLE (Run-Length Encoding) records for efficient byte filling
|
|
20
|
+
- Automatic output filename generation (inserts `.patched` before file extension)
|
|
21
|
+
- Non-destructive patching (original ROM file remains unchanged)
|
|
22
|
+
- Comprehensive error handling with `Ips::Patcher::Error` exception class
|
|
23
|
+
- Binary reader and writer utilities for IPS format parsing
|
|
24
|
+
- Pure Ruby implementation with no external dependencies
|
|
25
|
+
- Full test coverage with RSpec
|
|
26
|
+
- YARD documentation support
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
- Validates IPS patch file format (checks for "PATCH" header)
|
|
30
|
+
- Processes patch records sequentially until "EOF" marker
|
|
31
|
+
- Handles both standard and RLE-compressed patch records
|
|
32
|
+
- Creates new patched ROM file without modifying the original
|
|
33
|
+
|
|
34
|
+
[0.1.1]: https://github.com/meruen/ips-patcher/releases/tag/v0.1.1
|
|
35
|
+
[0.1.0]: https://github.com/meruen/ips-patcher/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Ips::Patcher
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/rb/ips-patcher)
|
|
4
|
+
|
|
3
5
|
A Ruby library for applying IPS (International Patching System) patches to video game ROM files. IPS is a binary patch format commonly used to distribute patches for ROM images, such as translation patches, bug fixes, or game modifications.
|
|
4
6
|
|
|
5
7
|
## Features
|
|
@@ -45,6 +47,14 @@ Ips::Patcher.apply("game.rom", "patch.ips")
|
|
|
45
47
|
|
|
46
48
|
The patcher reads the ROM file and the IPS patch file, applies all patch records, and creates a new patched file. The output filename is automatically generated by inserting `.patched` before the file extension.
|
|
47
49
|
|
|
50
|
+
You can also specify a custom output path:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
# Apply a patch with a custom output filename
|
|
54
|
+
Ips::Patcher.apply("game.rom", "patch.ips", output: "custom_output.rom")
|
|
55
|
+
# Creates: custom_output.rom
|
|
56
|
+
```
|
|
57
|
+
|
|
48
58
|
### Example
|
|
49
59
|
|
|
50
60
|
```ruby
|
|
@@ -62,7 +72,7 @@ Ips::Patcher.apply("super_metroid.sfc", "translation_jp_to_en.ips")
|
|
|
62
72
|
3. Processes each patch record:
|
|
63
73
|
- **Standard records**: Replace bytes at a specific offset
|
|
64
74
|
- **RLE records**: Fill bytes with a repeated value (when size is 0)
|
|
65
|
-
4. Creates a new patched ROM file
|
|
75
|
+
4. Creates a new patched ROM file. If no output path is specified, `.patched` is inserted before the file extension
|
|
66
76
|
5. The original ROM file remains unchanged
|
|
67
77
|
|
|
68
78
|
## IPS Format
|
data/lib/ips/patcher/version.rb
CHANGED
data/lib/ips/patcher.rb
CHANGED
|
@@ -23,8 +23,9 @@ module Ips
|
|
|
23
23
|
# Applies an IPS patch file to a ROM file.
|
|
24
24
|
#
|
|
25
25
|
# This method reads both the ROM and patch files, validates the patch format,
|
|
26
|
-
# and applies all patch records to create a new patched ROM file.
|
|
27
|
-
# file is named with ".patched" inserted before
|
|
26
|
+
# and applies all patch records to create a new patched ROM file. If no output
|
|
27
|
+
# path is specified, the output file is named with ".patched" inserted before
|
|
28
|
+
# the file extension.
|
|
28
29
|
#
|
|
29
30
|
# The IPS format supports two types of records:
|
|
30
31
|
# - Standard records: Replace bytes at a specific offset
|
|
@@ -32,15 +33,22 @@ module Ips
|
|
|
32
33
|
#
|
|
33
34
|
# @param rom_path [String] path to the ROM file to be patched
|
|
34
35
|
# @param patch_path [String] path to the IPS patch file
|
|
36
|
+
# @param output [String, nil] optional path for the output file. If nil, the
|
|
37
|
+
# output file is automatically named with ".patched" inserted before the
|
|
38
|
+
# file extension
|
|
35
39
|
# @raise [Error] if the patch file does not have a valid "PATCH" header
|
|
36
40
|
# @return [void]
|
|
37
41
|
#
|
|
38
|
-
# @example Apply a patch
|
|
42
|
+
# @example Apply a patch with automatic output naming
|
|
39
43
|
# Ips::Patcher.apply("game.nes", "translation.ips")
|
|
40
44
|
# # Output: game.patched.nes
|
|
41
45
|
#
|
|
46
|
+
# @example Apply a patch with custom output path
|
|
47
|
+
# Ips::Patcher.apply("game.nes", "translation.ips", output: "patched_game.nes")
|
|
48
|
+
# # Output: patched_game.nes
|
|
49
|
+
#
|
|
42
50
|
# @note The original ROM file is not modified; a new patched file is created
|
|
43
|
-
def self.apply(rom_path, patch_path)
|
|
51
|
+
def self.apply(rom_path, patch_path, output: nil)
|
|
44
52
|
rom = File.binread(rom_path)
|
|
45
53
|
patch = File.binread(patch_path)
|
|
46
54
|
|
|
@@ -72,10 +80,14 @@ module Ips
|
|
|
72
80
|
writer.set_bytes(offset, bytes)
|
|
73
81
|
end
|
|
74
82
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
output_path = output
|
|
84
|
+
|
|
85
|
+
unless output_path
|
|
86
|
+
rom_dir = File.dirname(rom_path)
|
|
87
|
+
filename = File.basename(rom_path, File.extname(rom_path))
|
|
88
|
+
extension = File.extname(rom_path)
|
|
89
|
+
output_path = File.join(rom_dir, "#{filename}.patched#{extension}")
|
|
90
|
+
end
|
|
79
91
|
|
|
80
92
|
writer.save_to_file(output_path)
|
|
81
93
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ips-patcher
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- eml
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: yard
|
|
@@ -47,7 +47,6 @@ files:
|
|
|
47
47
|
- lib/ips/binary_writer.rb
|
|
48
48
|
- lib/ips/patcher.rb
|
|
49
49
|
- lib/ips/patcher/version.rb
|
|
50
|
-
- sig/ips/patcher.rbs
|
|
51
50
|
homepage: https://github.com/meruen/ips-patcher
|
|
52
51
|
licenses:
|
|
53
52
|
- MIT
|