Skip to content

Commit 530b18d

Browse files
committed
initial commit
0 parents  commit 530b18d

File tree

12 files changed

+838
-0
lines changed

12 files changed

+838
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
build/
2+
.vscode
3+
*.gba
4+
*.gb
5+
*.zip
6+
*.ips
7+
*.ups
8+
*.bps
9+
*.sav
10+
*.state*

CMakeLists.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required(VERSION 3.0.2)
2+
3+
option(EXAMPLE_PATCHER "build patcher exe" OFF)
4+
5+
6+
project(patch LANGUAGES C)
7+
add_library(patch patch.c)
8+
9+
add_subdirectory(ips)
10+
add_subdirectory(ups)
11+
12+
target_link_libraries(patch PRIVATE ips ups)
13+
target_include_directories(patch PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
14+
15+
target_compile_options(patch PRIVATE
16+
$<$<OR:$<C_COMPILER_ID:Clang>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:GNU>>:
17+
-Wall
18+
-Wextra
19+
>
20+
$<$<C_COMPILER_ID:MSVC>:
21+
/W4
22+
>
23+
)
24+
25+
if (EXAMPLE_PATCHER)
26+
add_subdirectory(examples/patcher)
27+
endif()

examples/patcher/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
cmake_minimum_required(VERSION 3.0.2)
2+
3+
project(patcher LANGUAGES C)
4+
add_executable(patcher main.c)
5+
target_link_libraries(patcher PRIVATE patch)
6+
7+
target_compile_options(patcher PRIVATE
8+
$<$<OR:$<C_COMPILER_ID:Clang>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:GNU>>:
9+
-Wall
10+
-Wextra
11+
>
12+
$<$<C_COMPILER_ID:MSVC>:
13+
/W4
14+
>
15+
)
16+
17+
set_target_properties(patcher PROPERTIES
18+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
19+
)

examples/patcher/main.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// simple example of using the patchers
2+
// ./exe rom.bin patch.ips out.bin
3+
4+
#include "patch.h"
5+
6+
#include <stdint.h>
7+
#include <stdbool.h>
8+
#include <stddef.h>
9+
#include <stdio.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
13+
static uint8_t* ROM_DATA = {0};
14+
static uint8_t* PATCH_DATA = {0};
15+
static uint8_t* OUT_DATA = {0};
16+
17+
static size_t ROM_SIZE = {0};
18+
static size_t PATCH_SIZE = {0};
19+
static size_t OUT_SIZE = {0};
20+
21+
static int get_patch_type(const char* file_name)
22+
{
23+
static const char* extentions[] =
24+
{
25+
[PatchType_IPS] = ".ips",
26+
[PatchType_UPS] = ".ups",
27+
};
28+
29+
const char* ext = strrchr(file_name, '.');
30+
if (!ext)
31+
{
32+
return -1;
33+
}
34+
35+
if (!strcmp(ext, extentions[PatchType_IPS]))
36+
{
37+
return PatchType_IPS;
38+
}
39+
40+
if (!strcmp(ext, extentions[PatchType_UPS]))
41+
{
42+
return PatchType_UPS;
43+
}
44+
45+
return -1;
46+
}
47+
48+
static uint8_t* readfile(const char* filepath, size_t* size)
49+
{
50+
uint8_t* data = NULL;
51+
FILE* f = fopen(filepath, "rb");
52+
if (!f)
53+
{
54+
goto fail;
55+
}
56+
57+
fseek(f, 0, SEEK_END);
58+
*size = ftell(f);
59+
rewind(f);
60+
61+
if (!*size)
62+
{
63+
goto fail;
64+
}
65+
66+
data = malloc(*size);
67+
if (!data)
68+
{
69+
goto fail;
70+
}
71+
72+
if (*size != fread(data, 1, *size, f))
73+
{
74+
goto fail;
75+
}
76+
77+
fclose(f);
78+
79+
return data;
80+
81+
fail:
82+
if (f)
83+
{
84+
fclose(f);
85+
}
86+
if (data)
87+
{
88+
free(data);
89+
}
90+
return NULL;
91+
}
92+
93+
static bool writefile(const char* filepath, const void* data, size_t size)
94+
{
95+
FILE* f = fopen(filepath, "wb");
96+
if (!f)
97+
{
98+
return false;
99+
}
100+
101+
if (size != fwrite(data, 1, size, f))
102+
{
103+
goto fail;
104+
}
105+
106+
fclose(f);
107+
108+
return true;
109+
110+
fail:
111+
if (f)
112+
{
113+
fclose(f);
114+
}
115+
return false;
116+
}
117+
118+
static int cleanup(const char* error_message)
119+
{
120+
if (error_message)
121+
{
122+
printf("ERROR: %s\n", error_message);
123+
}
124+
125+
if (ROM_DATA)
126+
{
127+
free(ROM_DATA);
128+
ROM_DATA = NULL;
129+
}
130+
if (PATCH_DATA)
131+
{
132+
free(PATCH_DATA);
133+
PATCH_DATA = NULL;
134+
}
135+
if (OUT_DATA)
136+
{
137+
free(OUT_DATA);
138+
OUT_DATA = NULL;
139+
}
140+
141+
return 1;
142+
}
143+
144+
int main(int argc, char** argv)
145+
{
146+
if (argc < 4)
147+
{
148+
return cleanup("missing args: ./exe rom.bin patch.ips out.bin");
149+
}
150+
151+
const char* rom_filename = argv[1];
152+
const char* patch_filename = argv[2];
153+
const char* out_filename = argv[3];
154+
155+
ROM_DATA = readfile(rom_filename, &ROM_SIZE);
156+
PATCH_DATA = readfile(patch_filename, &PATCH_SIZE);
157+
158+
if (!ROM_DATA || !ROM_SIZE || !PATCH_DATA || !PATCH_SIZE)
159+
{
160+
return cleanup("failed to read files");
161+
}
162+
163+
const int patch_type = get_patch_type(patch_filename);
164+
if (patch_type == -1)
165+
{
166+
return cleanup("unkown patch type");
167+
}
168+
169+
if (PatchError_OK != patch(patch_type, &OUT_DATA, &OUT_SIZE, ROM_DATA, ROM_SIZE, PATCH_DATA, PATCH_SIZE))
170+
{
171+
return cleanup("failed to patch file");
172+
}
173+
174+
if (!writefile(out_filename, OUT_DATA, OUT_SIZE))
175+
{
176+
return cleanup("failed to write patched file");
177+
}
178+
179+
printf("patched: %s\n", out_filename);
180+
cleanup(NULL);
181+
182+
return 0;
183+
}

ips/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.0.2)
2+
3+
project(ips LANGUAGES C)
4+
add_library(ips ips.c)
5+
target_include_directories(ips PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
6+
7+
target_compile_options(ips PRIVATE
8+
$<$<OR:$<C_COMPILER_ID:Clang>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:GNU>>:
9+
-Wall
10+
-Wextra
11+
>
12+
$<$<C_COMPILER_ID:MSVC>:
13+
/W4
14+
>
15+
)

0 commit comments

Comments
 (0)