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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7da78146e2a5464fe4ed96f349275ee65216f41bdf8e027c8e4ee7d3047aa52f
4
- data.tar.gz: 785fd7b0986a2723258883d25d3fb4e04a5d62590ec9d9aac6a545dc172b8755
3
+ metadata.gz: f826901f510e6aa84902f901dc38eb470b42797f7bc4c422201df82b4acb432a
4
+ data.tar.gz: cfaaa43d70bbbd3ce7f402bdbcad30e5eae21677fb686e3b5e522fc50d90519c
5
5
  SHA512:
6
- metadata.gz: 4b42b64edb05084a18e3ee10a31fae908e7d5d22e11c4fef7d6f87d941e8e9b5aff9f2d611a424b041b741fa8965e4266485b38392f4d4a89ce37307e34136f9
7
- data.tar.gz: dbef5867bbc2404732f76eec75d665f771d06996c3e1e90d406f3c8d09ebd2b968a68a0da5c7402d6a4efbcbcb52e675d65a8e75dcf4007dcc2262ab00eee050
6
+ metadata.gz: 8daacbc64f5e5ed5e4a983c5a9e4a77fa9dc9478bc74f09207023d238e504b7427e093cc13d08f8eafe5fd04ba5e5743b8707f7911fc02c5125e1cc1b5cc9845
7
+ data.tar.gz: 606df2d9801958470c46247d6b170f253a6780f2b2caa9fadc8884c58dab93b58866d10079a9d4e2f01cfbba1b2a501c2d4284e4d397fe6b80bb8ee68040f2db
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
- ## [Unreleased]
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
- - Initial release
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
+ [![Gem Version](https://badge.fury.io/rb/ips-patcher.svg)](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 with `.patched` inserted before the extension
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
@@ -4,6 +4,6 @@ module Ips
4
4
  # IPS (International Patching System) patcher module for applying binary patches to ROM files.
5
5
  module Patcher
6
6
  # Current version of the ips-patcher gem
7
- VERSION = "0.1.0"
7
+ VERSION = "0.1.1"
8
8
  end
9
9
  end
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. The output
27
- # file is named with ".patched" inserted before the file extension.
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
- rom_dir = File.dirname(rom_path)
76
- filename = File.basename(rom_path, File.extname(rom_path))
77
- extension = File.extname(rom_path)
78
- output_path = File.join(rom_dir, "#{filename}.patched#{extension}")
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.0
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-22 00:00:00.000000000 Z
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
data/sig/ips/patcher.rbs DELETED
@@ -1,6 +0,0 @@
1
- module Ips
2
- module Patcher
3
- VERSION: String
4
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
- end
6
- end