-
Notifications
You must be signed in to change notification settings - Fork 1
/
eboot_patch.py
495 lines (462 loc) · 41.2 KB
/
eboot_patch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
################################################################################
### Copyright © 2012-2013 BlackDragonHunt
### Copyright © 2012-2013 /a/nonymous scanlations
###
### This file is part of the Super Duper Script Editor.
###
### The Super Duper Script Editor is free software: you can redistribute it
### and/or modify it under the terms of the GNU General Public License as
### published by the Free Software Foundation, either version 3 of the License,
### or (at your option) any later version.
###
### The Super Duper Script Editor is distributed in the hope that it will be
### useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
### GNU General Public License for more details.
###
### You should have received a copy of the GNU General Public License
### along with the Super Duper Script Editor.
### If not, see <http://www.gnu.org/licenses/>.
################################################################################
#from bitstring import array.array, BitStream
from enum import Enum
import array, os
import Common
import clt
NAME = "name"
ENABLED = "enabled"
EXT_ONLY = "extended_only"
CFG_ID = "cfg_id"
DATA = "data"
POS = "pos"
ORIG = "orig"
PATCH = "patch"
# LANGUAGES = [u"Japanese", u"English", u"French", u"Spanish", u"German", u"Italian", u"Dutch", u"Portuguese", u"Russian", u"Korean", u"Traditional Chinese", u"Simplified Chinese"]
LANGUAGES = [u"日本語", u"English", u"Français", u"Español", u"Deutsch", u"Italiano", u"Nederlands", u"Português", u"Русский", u"한국어", u"繁體中文", u"简体中文"]
LANG_CFG_ID = "sys_menu_lang"
CLT_CFG_ID = "custom_clt"
EBOOT_PATCHES = [
{NAME: "Extend EBOOT", ENABLED: True, EXT_ONLY: True, CFG_ID: "00_extend_eboot", DATA:
[
{POS: 0x0000002C, ORIG: array.array('B', [0x03, 0x00]), PATCH: array.array('B', [0x04, 0x00])},
{POS: 0x00000054, ORIG: array.array('B', [0x01,0x00,0x00,0x00,0x40,0xCB,0x20,0x00,0x80,0xCA,0x20,0x00,0x00,0x00,0x00,0x00,0x28,0xE4,0x00,0x00,0x84,0x2A,0x2E,0x00,0x06,0x00,0x00,0x00,0x40,0x00,0x00,0x00]), PATCH: array.array('B', [0x01,0x00,0x00,0x00,0x40,0xCB,0x20,0x00,0x20,0xF5,0x4E,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x00,0x20,0x01,0x00,0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00])},
{POS: 0x00000074, ORIG: array.array('B', [0xA0,0x00,0x00,0x70,0x70,0xAF,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x56,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0x01,0x00,0x00,0x00,0x40,0xEB,0x21,0x00,0x80,0xCA,0x20,0x00,0x00,0x00,0x00,0x00,0x28,0xE4,0x00,0x00,0x84,0x2A,0x2E,0x00,0x06,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xA0,0x00,0x00,0x70,0x70,0xCF,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x56,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00])},
]
},
{NAME: "Game Button Order", ENABLED: True, EXT_ONLY: True, CFG_ID: "01_game_btn", DATA:
[
# Patch works only on extended EBOOT
{POS: 0x0007A4C8, ORIG: array.array('B', [0x04,0x00,0xB1,0x8F]), PATCH: array.array('B', [0x48,0xCD,0x33,0x0A])},
{POS: 0x0020CB40, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0x04,0x00,0xB1,0x8F,0x21,0x20,0x20,0x02,0x00,0x20,0x25,0x32,0x02,0x00,0xA0,0x14,0x00,0x40,0x31,0x36,0x00,0x40,0x31,0x3A,0x00,0x40,0x84,0x30,0x02,0x00,0x80,0x14,0x00,0x20,0x31,0x36,0x00,0x20,0x31,0x3A,0x03,0xF9,0x21,0x0A,0x00,0x00,0x00,0x00])},
]
},
{NAME: "Home/Save Button Order", ENABLED: True, EXT_ONLY: False, CFG_ID: "03_home_btn", DATA:
[
{POS: 0x0008CCF8, ORIG: array.array('B', [0x21,0x10,0x80,0x00]), PATCH: array.array('B', [0x01,0x00,0x02,0x24])},
]
},
{NAME: "Fix Error Code 80020148", ENABLED: True, EXT_ONLY: False, CFG_ID: "04_fix_80020148", DATA:
[
{POS: 0x00000004, ORIG: array.array('B', [0x00]), PATCH: array.array('B', [0x01])},
{POS: 0x00000007, ORIG: array.array('B', [0x01]), PATCH: array.array('B', [0x00])},
]
},
{NAME: "Increase Dialog Line Limit to 96 Characters", ENABLED: True, EXT_ONLY: True, CFG_ID: "05_dialog_line_96", DATA:
[
# Move current line buffer: raw addresses (0x08CAF3C6 -> 0x08CF3550)
{POS: 0x000CB528, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000CB534, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000D1BD0, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000D1BD4, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000D25D8, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000D25DC, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000D962C, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000D9638, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000D963C, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000DB820, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DB824, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DB828, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000DB82C, ORIG: array.array('B', [0x26,0xEA]), PATCH: array.array('B', [0xD0,0x2D])},
{POS: 0x000DB95C, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000DB960, ORIG: array.array('B', [0x26,0xEA]), PATCH: array.array('B', [0xD0,0x2D])},
{POS: 0x000DB96C, ORIG: array.array('B', [0x38,0x00]), PATCH: array.array('B', [0xC0,0x00])},
{POS: 0x000DCFE0, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DCFEC, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000DE5E8, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DE5F4, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000DE92C, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DE938, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000DE93C, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000FF1DC, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000FF230, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000FF1E4, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000FF2D0, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000FF2D8, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000FFD34, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000FFD38, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x000FFE44, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x000FFE48, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x001000B0, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x00100430, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x00100598, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x0010059C, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
{POS: 0x00100724, ORIG: array.array('B', [0x2A,0x00]), PATCH: array.array('B', [0x2E,0x00])},
{POS: 0x0010072C, ORIG: array.array('B', [0x46,0xE9]), PATCH: array.array('B', [0xD0,0x2A])},
# Move current line buffer: relative addresses
{POS: 0x0020CFF0, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x04,0x3C,0xEA,0x32,0x84,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x44,0x00])},
{POS: 0x000CE600, ORIG: array.array('B', [0x40,0x10,0x05,0x00,0x21,0x10,0x48,0x00]), PATCH: array.array('B', [0x74,0xCE,0x33,0x0E,0x40,0x10,0x05,0x00])},
{POS: 0x0020D000, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x07,0x3C,0xEA,0x32,0xE7,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x47,0x00])},
{POS: 0x000CE754, ORIG: array.array('B', [0x40,0x10,0x06,0x00,0x21,0x10,0x48,0x00]), PATCH: array.array('B', [0x78,0xCE,0x33,0x0E,0x40,0x10,0x06,0x00])},
{POS: 0x0020D010, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x04,0x3C,0xEA,0x32,0x84,0x24,0x08,0x00,0xE0,0x03,0x21,0x18,0x64,0x00])},
{POS: 0x000CE7EC, ORIG: array.array('B', [0x40,0x18,0x0A,0x00,0x21,0x18,0x7E,0x00]), PATCH: array.array('B', [0x7C,0xCE,0x33,0x0E,0x40,0x18,0x0A,0x00])},
{POS: 0x0020D020, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x03,0x3C,0xEA,0x32,0x63,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x43,0x00])},
{POS: 0x000CE9C4, ORIG: array.array('B', [0x40,0x10,0x04,0x00,0x21,0x10,0x50,0x00]), PATCH: array.array('B', [0x80,0xCE,0x33,0x0E,0x40,0x10,0x04,0x00])},
{POS: 0x0020D030, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x07,0x3C,0xEA,0x32,0xE7,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x47,0x00])},
{POS: 0x000CEA84, ORIG: array.array('B', [0x40,0x10,0x06,0x00,0x21,0x10,0x50,0x00]), PATCH: array.array('B', [0x84,0xCE,0x33,0x0E,0x40,0x10,0x06,0x00])},
{POS: 0x0020D040, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x04,0x3C,0xEA,0x32,0x84,0x24,0x08,0x00,0xE0,0x03,0x21,0x18,0x64,0x00])},
{POS: 0x000CEB10, ORIG: array.array('B', [0x40,0x18,0x0A,0x00,0x21,0x18,0x71,0x00]), PATCH: array.array('B', [0x88,0xCE,0x33,0x0E,0x40,0x18,0x0A,0x00])},
{POS: 0x000CE974, ORIG: array.array('B', [0x66,0x02,0xA2,0x94,0x00,0x01,0x42,0x2C]), PATCH: array.array('B', [0x8C,0xCE,0x33,0x0E,0x00,0x00,0x00,0x00])},
{POS: 0x0020D050, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x02,0x3C,0x50,0x35,0x42,0x94,0x08,0x00,0xE0,0x03,0x00,0x01,0x42,0x2C])},
# Move current line CLT buffer: relative addreses
{POS: 0x0020D060, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x07,0x3C,0x0A,0x35,0xE7,0x24,0x08,0x00,0xE0,0x03,0x21,0x50,0x47,0x01])},
{POS: 0x000CE7F4, ORIG: array.array('B', [0x23,0x10,0x47,0x00,0x21,0x50,0x5E,0x01]), PATCH: array.array('B', [0x90,0xCE,0x33,0x0E,0x23,0x10,0x47,0x00])},
{POS: 0x0020D070, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x07,0x3C,0x0A,0x35,0xE7,0x24,0x08,0x00,0xE0,0x03,0x21,0x50,0x47,0x01])},
{POS: 0x000CEB18, ORIG: array.array('B', [0x23,0x10,0x47,0x00,0x21,0x50,0x51,0x01]), PATCH: array.array('B', [0x94,0xCE,0x33,0x0E,0x23,0x10,0x47,0x00])},
# Move current line CLT buffer: load
{POS: 0x0020D080, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x08,0x3C,0x50,0x38,0x08,0x25,0x21,0x40,0x06,0x01,0x08,0x00,0xE0,0x03,0x00,0x00,0x08,0x91])},
{POS: 0x000CEB88, ORIG: array.array('B', [0x19,0x00,0x97,0x00,0x21,0x10,0x70,0x00,0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86,0x46,0x03,0x48,0x90]), PATCH: array.array('B', [0x98,0xCE,0x33,0x0E,0x19,0x00,0x97,0x00,0x21,0x10,0x70,0x00,0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86])},
{POS: 0x000CEBC0, ORIG: array.array('B', [0x19,0x00,0x92,0x00,0x21,0x10,0x70,0x00,0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86,0x46,0x03,0x48,0x90]), PATCH: array.array('B', [0x98,0xCE,0x33,0x0E,0x19,0x00,0x92,0x00,0x21,0x10,0x70,0x00,0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86])},
{POS: 0x000CEC04, ORIG: array.array('B', [0x21,0x10,0xC8,0x00,0xBA,0x03,0x05,0x85,0xBC,0x03,0x06,0x85,0x46,0x03,0x48,0x90]), PATCH: array.array('B', [0x98,0xCE,0x33,0x0E,0x21,0x10,0xC8,0x00,0xBA,0x03,0x05,0x85,0xBC,0x03,0x06,0x85])},
{POS: 0x000CEC30, ORIG: array.array('B', [0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86,0x46,0x03,0x48,0x90]), PATCH: array.array('B', [0x98,0xCE,0x33,0x0E,0xBA,0x03,0x05,0x86,0xBC,0x03,0x06,0x86])},
# Move current line buffer and current line CLT buffer: 0xDB91C
{POS: 0x000DB9DC, ORIG: array.array('B', [0x40,0x10,0x0B,0x00,0x21,0x10,0x45,0x00]), PATCH: array.array('B', [0xA0,0xCE,0x33,0x0E,0x40,0x10,0x0B,0x00])},
{POS: 0x000DB9E4, ORIG: array.array('B', [0x21,0x18,0x65,0x01]), PATCH: array.array('B', [0x00,0x00,0x00,0x00])},
{POS: 0x0020D0A0, ORIG: array.array('B', [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]), PATCH: array.array('B', [0xCF,0x08,0x0A,0x3C,0xEA,0x32,0x4A,0x25,0x21,0x10,0x4A,0x00,0xCF,0x08,0x0A,0x3C,0x0A,0x35,0x4A,0x25,0x08,0x00,0xE0,0x03,0x21,0x18,0x6A,0x01])},
# Reducing backlog length from 512 lines to 144 lines
{POS: 0x000CECA4, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000CECB0, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000CECB8, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000CEEB0, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000CEEF8, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000DBAA8, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000DBAD0, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000DBAD4, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x000DBAF8, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x0016814C, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
{POS: 0x0016819C, ORIG: array.array('B', [0x00, 0x02]), PATCH: array.array('B', [0x09, 0x00])},
# Change line length: 28 -> 96
{POS: 0x000CED00, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000CEDFC, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000D7CA0, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000D8B7C, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000D90C4, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000DB830, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000DB9B0, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000DBA5C, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
{POS: 0x000DBAC0, ORIG: array.array('B', [0x1C, 0x00]), PATCH: array.array('B', [0x60, 0x00])},
# Change line length: 84 -> 288
{POS: 0x000CE8D8, ORIG: array.array('B', [0x54,0x00]), PATCH: array.array('B', [0x20,0x01])},
# Change line length: 112 -> 384
{POS: 0x000CE5E0, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE618, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE6BC, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE8CC, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE8F0, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE9DC, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CE9F8, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000CEB68, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
{POS: 0x000D2410, ORIG: array.array('B', [0x70, 0x00]), PATCH: array.array('B', [0x80, 0x01])},
# Change line length: 224 -> 768
{POS: 0x000CB53C, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000CFEB8, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000D1BDC, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000D25E8, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000D7C94, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000D8B70, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000D9644, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000DCFF4, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000DE5FC, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000DE944, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000FF1F0, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000FF2DC, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000FFD44, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x000FFE50, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x0010043C, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x001005AC, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
{POS: 0x00100734, ORIG: array.array('B', [0xE0, 0x00]), PATCH: array.array('B', [0x00, 0x03])},
# Change line length: sll ... 2 -> sll ... 5
{POS: 0x000CE720, ORIG: array.array('B', [0x80,0x10,0x09,0x00]), PATCH: array.array('B', [0x40,0x11,0x09,0x00])},
{POS: 0x000CE934, ORIG: array.array('B', [0x80,0x20,0x03,0x00]), PATCH: array.array('B', [0x40,0x21,0x03,0x00])},
{POS: 0x000CEA1C, ORIG: array.array('B', [0x80,0x10,0x05,0x00]), PATCH: array.array('B', [0x40,0x11,0x05,0x00])},
{POS: 0x000CEA54, ORIG: array.array('B', [0x80,0x10,0x09,0x00]), PATCH: array.array('B', [0x40,0x11,0x09,0x00])},
{POS: 0x000CED08, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000CED40, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000CEDB4, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000CEE04, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000CEE40, ORIG: array.array('B', [0x80,0x18,0x09,0x00]), PATCH: array.array('B', [0x40,0x19,0x09,0x00])},
{POS: 0x000DB9B8, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000DBA08, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000DBA3C, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
{POS: 0x000DBD48, ORIG: array.array('B', [0x80,0x18,0x03,0x00]), PATCH: array.array('B', [0x40,0x19,0x03,0x00])},
# Change line length: sll ... 5 -> sll ... 7
{POS: 0x000CE724, ORIG: array.array('B', [0x40,0x19,0x09,0x00]), PATCH: array.array('B', [0xC0,0x19,0x09,0x00])},
{POS: 0x000CE938, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
{POS: 0x000CEA20, ORIG: array.array('B', [0x40,0x19,0x05,0x00]), PATCH: array.array('B', [0xC0,0x19,0x05,0x00])},
{POS: 0x000CEA58, ORIG: array.array('B', [0x40,0x19,0x09,0x00]), PATCH: array.array('B', [0xC0,0x19,0x09,0x00])},
{POS: 0x000CED04, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
{POS: 0x000CED3C, ORIG: array.array('B', [0x40,0x21,0x03,0x00]), PATCH: array.array('B', [0xC0,0x21,0x03,0x00])},
{POS: 0x000CEDB0, ORIG: array.array('B', [0x40,0x21,0x03,0x00]), PATCH: array.array('B', [0xC0,0x21,0x03,0x00])},
{POS: 0x000CEE00, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
{POS: 0x000CEE44, ORIG: array.array('B', [0x40,0x11,0x09,0x00]), PATCH: array.array('B', [0xC0,0x11,0x09,0x00])},
{POS: 0x000DB9B4, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
{POS: 0x000DBA04, ORIG: array.array('B', [0x40,0x21,0x03,0x00]), PATCH: array.array('B', [0xC0,0x21,0x03,0x00])},
{POS: 0x000DBA38, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
{POS: 0x000DBD44, ORIG: array.array('B', [0x40,0x11,0x03,0x00]), PATCH: array.array('B', [0xC0,0x11,0x03,0x00])},
# Change line length: divisor 0x24924925 -> 0x0AAAAAAB
{POS: 0x001FA5CC, ORIG: array.array('B', [0x25,0x49,0x92,0x24]), PATCH: array.array('B', [0xAB,0xAA,0xAA,0x0A])},
{POS: 0x000CE998, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x000D8378, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x000E69E4, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x000FBAB8, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x001673F0, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x00167748, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x001677D0, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x00167910, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x00174610, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x0017F720, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x0017FDA8, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x001800EC, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x00180460, ORIG: array.array('B', [0x92,0x24]), PATCH: array.array('B', [0xAA,0x0A])},
{POS: 0x000CE99C, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x000D837C, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x000E69E8, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x000FBABC, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x001673F4, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x0016774C, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x001677D8, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x00167918, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x00174618, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x0017F728, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x0017FDB0, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x001800F8, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
{POS: 0x0018046C, ORIG: array.array('B', [0x25,0x49]), PATCH: array.array('B', [0xAB,0xAA])},
]
},
{NAME: "Fix Line Height", ENABLED: True, EXT_ONLY: False, CFG_ID: "06_line_height_fix", DATA:
[
# It fixes the offset. Offset is calculated in the cycle between 0887A740 and 0887A768 in memory.
# Offset by Y is in f3, which is calculated as f3 = f0 - f24.
# f24 value is gathered at 0887A160, which 0x001F9BB0 in EBOOT. its value is 0x43080000
# It corresponds to 136 in FPU. If changed to 0x43100000, which is 144, it does the trick
# Patch also works without eboot expansion
{POS: 0x001F9BB0, ORIG: array.array('B', [0x00,0x00,0x08,0x43]), PATCH: array.array('B', [0x00,0x00,0x10,0x43])},
# And this fixes the height of system messages. There's quite a long op, which results into lwc1 f0,0x8(sp) at 088F5068
# and cvt.s.w f2,f0 in the next op
# This part of memory is written as a hi of 088F4664 mult v0,s6.
# s6 is defined in two parts at 088F459C
# lui a0,0x51EB
# ori s6,a0,0x851F
# hi of the multiplication relies almost solely on a0. So, when changing it to 0x7EEB, it becomes ok
# (but some strange inter-letter space occures, need to check whether it's font or code)
{POS: 0x000F065C, ORIG: array.array('B', [0xEB,0x51,0x04,0x3C]), PATCH: array.array('B', [0xEB,0x7E,0x04,0x3C])},
]
},
{NAME: "English Font for Labels", ENABLED: True, EXT_ONLY: False, CFG_ID: "07_eng_labels_fix", DATA:
[
# The font is given in the format X,Y,W with static H = 13 px. Bitmap is the 6th file in jp/cg/tex_system.pak
# The mapping itself was done by the function Z - 0x30A1, where Z is the symbol number.
# This is done inside the function on 088F8EC0, which is called on 088F91FC
# So now the mapping will be done like Z - 0x0020 ("space" symbol), containing the symbols from space to Z (0x0020 to 0x005A)
# The font mapping starts at 0x00208B77 in EBOOT
# The font used is Joystix, width for each char is 11 (0x0B)
#
# First, the alphabet
{POS: 0x00208B77, ORIG: array.array('B', [0x9C,0x68,0x0B]), PATCH: array.array('B',[0x00,0x00,0x0B])}, # fullwidth ? to !
{POS: 0x00208B7A, ORIG: array.array('B', [0xD7,0x0D,0x0B]), PATCH: array.array('B',[0x0B,0x00,0x0B])}, # fullwidth - to "
{POS: 0x00208B7D, ORIG: array.array('B', [0xC1,0x0D,0x0B]), PATCH: array.array('B',[0x16,0x00,0x0B])}, # fullwidth A to #
{POS: 0x00208B80, ORIG: array.array('B', [0xCC,0x0D,0x0B]), PATCH: array.array('B',[0x21,0x00,0x0B])}, # fullwidth B to $
{POS: 0x00208B83, ORIG: array.array('B', [0xA9,0x0D,0x0B]), PATCH: array.array('B',[0x2C,0x00,0x0B])}, # fullwidth M to %
{POS: 0x00208B86, ORIG: array.array('B', [0xB6,0x0D,0x0B]), PATCH: array.array('B',[0x37,0x00,0x0B])}, # fullwidth P to &
{POS: 0x00208B89, ORIG: array.array('B', [0x8B,0x00,0x0B]), PATCH: array.array('B',[0x42,0x00,0x0B])}, # fullwidth 0 to '
{POS: 0x00208B8C, ORIG: array.array('B', [0x96,0x00,0x07]), PATCH: array.array('B',[0x4D,0x00,0x0B])}, # fullwidth 1 to (
{POS: 0x00208B8F, ORIG: array.array('B', [0x9D,0x00,0x0B]), PATCH: array.array('B',[0x58,0x00,0x0B])}, # fullwidth 2 to )
{POS: 0x00208B92, ORIG: array.array('B', [0xA8,0x00,0x0B]), PATCH: array.array('B',[0x63,0x00,0x0B])}, # fullwidth 3 to *
{POS: 0x00208B95, ORIG: array.array('B', [0xB3,0x00,0x0B]), PATCH: array.array('B',[0x6E,0x00,0x0B])}, # fullwidth 4 to +
{POS: 0x00208B98, ORIG: array.array('B', [0xBE,0x00,0x0B]), PATCH: array.array('B',[0x79,0x00,0x0B])}, # fullwidth 5 to ,
{POS: 0x00208B9B, ORIG: array.array('B', [0xC9,0x00,0x0B]), PATCH: array.array('B',[0x84,0x00,0x0B])}, # fullwidth 6 to -
{POS: 0x00208B9E, ORIG: array.array('B', [0xD4,0x00,0x0B]), PATCH: array.array('B',[0x8F,0x00,0x0B])}, # fullwidth 7 to .
{POS: 0x00208BA1, ORIG: array.array('B', [0xDF,0x00,0x0B]), PATCH: array.array('B',[0x9A,0x00,0x0B])}, # fullwidth 8 to /
{POS: 0x00208BA4, ORIG: array.array('B', [0xEA,0x00,0x0B]), PATCH: array.array('B',[0xA5,0x00,0x0B])}, # fullwidth 9 to 0
{POS: 0x00208BA7, ORIG: array.array('B', [0x4D,0x00,0x0D]), PATCH: array.array('B',[0xB0,0x00,0x0B])}, # jap a to 1
{POS: 0x00208BAA, ORIG: array.array('B', [0x00,0x00,0x0F]), PATCH: array.array('B',[0xBB,0x00,0x0B])}, # jap A to 2
{POS: 0x00208BAD, ORIG: array.array('B', [0x5A,0x00,0x0D]), PATCH: array.array('B',[0xC6,0x00,0x0B])}, # jap i to 3
{POS: 0x00208BB0, ORIG: array.array('B', [0x0F,0x00,0x0F]), PATCH: array.array('B',[0xD1,0x00,0x0B])}, # jap I to 4
{POS: 0x00208BB3, ORIG: array.array('B', [0x67,0x00,0x0C]), PATCH: array.array('B',[0xDC,0x00,0x0B])}, # jap u to 5
{POS: 0x00208BB6, ORIG: array.array('B', [0x1E,0x00,0x0F]), PATCH: array.array('B',[0xE7,0x00,0x0B])}, # jap U to 6
{POS: 0x00208BB9, ORIG: array.array('B', [0x73,0x00,0x0C]), PATCH: array.array('B',[0xF2,0x00,0x0B])}, # jap e to 7
{POS: 0x00208BBC, ORIG: array.array('B', [0x2D,0x00,0x10]), PATCH: array.array('B',[0x00,0x0D,0x0B])}, # jap E to 8
{POS: 0x00208BBF, ORIG: array.array('B', [0x7F,0x00,0x0C]), PATCH: array.array('B',[0x0B,0x0D,0x0B])}, # jap o to 9
{POS: 0x00208BC2, ORIG: array.array('B', [0x3D,0x00,0x10]), PATCH: array.array('B',[0x16,0x0D,0x0B])}, # jap O to :
{POS: 0x00208BC5, ORIG: array.array('B', [0x00,0x0D,0x10]), PATCH: array.array('B',[0x21,0x0D,0x0B])}, # jap KA to ;
{POS: 0x00208BC8, ORIG: array.array('B', [0x4C,0x0D,0x12]), PATCH: array.array('B',[0x2C,0x0D,0x0B])}, # jap GA to <
{POS: 0x00208BCB, ORIG: array.array('B', [0x10,0x0D,0x0F]), PATCH: array.array('B',[0x37,0x0D,0x0B])}, # jap KI to =
{POS: 0x00208BCE, ORIG: array.array('B', [0x5E,0x0D,0x12]), PATCH: array.array('B',[0x42,0x0D,0x0B])}, # jap GI to >
{POS: 0x00208BD1, ORIG: array.array('B', [0x1F,0x0D,0x0F]), PATCH: array.array('B',[0x4D,0x0D,0x0B])}, # jap KU to ?
{POS: 0x00208BD4, ORIG: array.array('B', [0x70,0x0D,0x12]), PATCH: array.array('B',[0x58,0x0D,0x0B])}, # jap GU to @
{POS: 0x00208BD7, ORIG: array.array('B', [0x2E,0x0D,0x10]), PATCH: array.array('B',[0x63,0x0D,0x0B])}, # jap KE to A
{POS: 0x00208BDA, ORIG: array.array('B', [0x83,0x0D,0x14]), PATCH: array.array('B',[0x6E,0x0D,0x0B])}, # jap GE to B
{POS: 0x00208BDD, ORIG: array.array('B', [0x3E,0x0D,0x0E]), PATCH: array.array('B',[0x79,0x0D,0x0B])}, # jap KO to C
{POS: 0x00208BE0, ORIG: array.array('B', [0x97,0x0D,0x12]), PATCH: array.array('B',[0x84,0x0D,0x0B])}, # jap GO to D
{POS: 0x00208BE3, ORIG: array.array('B', [0x00,0x1A,0x10]), PATCH: array.array('B',[0x8F,0x0D,0x0B])}, # jap SA to E
{POS: 0x00208BE6, ORIG: array.array('B', [0x4C,0x1A,0x14]), PATCH: array.array('B',[0x9A,0x0D,0x0B])}, # jap ZA to F
{POS: 0x00208BE9, ORIG: array.array('B', [0x10,0x1A,0x0F]), PATCH: array.array('B',[0xA5,0x0D,0x0B])}, # jap SI to G
{POS: 0x00208BEC, ORIG: array.array('B', [0x60,0x1A,0x10]), PATCH: array.array('B',[0xB0,0x0D,0x0B])}, # jap ZI to H
{POS: 0x00208BEF, ORIG: array.array('B', [0x1F,0x1A,0x0F]), PATCH: array.array('B',[0xBB,0x0D,0x0B])}, # jap SU to I
{POS: 0x00208BF2, ORIG: array.array('B', [0x70,0x1A,0x12]), PATCH: array.array('B',[0xC6,0x0D,0x0B])}, # jap ZU to J
{POS: 0x00208BF5, ORIG: array.array('B', [0x2E,0x1A,0x0F]), PATCH: array.array('B',[0xD1,0x0D,0x0B])}, # jap SE to K
{POS: 0x00208BF8, ORIG: array.array('B', [0x82,0x1A,0x13]), PATCH: array.array('B',[0xDC,0x0D,0x0B])}, # jap ZE to L
{POS: 0x00208BFB, ORIG: array.array('B', [0x3D,0x1A,0x0F]), PATCH: array.array('B',[0xE7,0x0D,0x0B])}, # jap SO to M
{POS: 0x00208BFE, ORIG: array.array('B', [0x95,0x1A,0x12]), PATCH: array.array('B',[0xF2,0x0D,0x0B])}, # jap ZO to N
{POS: 0x00208C01, ORIG: array.array('B', [0x00,0x27,0x0F]), PATCH: array.array('B',[0x00,0x1A,0x0B])}, # jap TA to O
{POS: 0x00208C04, ORIG: array.array('B', [0x4B,0x27,0x13]), PATCH: array.array('B',[0x0B,0x1A,0x0B])}, # jap DA to P
{POS: 0x00208C07, ORIG: array.array('B', [0x0F,0x27,0x0F]), PATCH: array.array('B',[0x16,0x1A,0x0B])}, # jap TI to Q
{POS: 0x00208C0A, ORIG: array.array('B', [0x5E,0x27,0x12]), PATCH: array.array('B',[0x21,0x1A,0x0B])}, # jap DI to R
{POS: 0x00208C0D, ORIG: array.array('B', [0xA1,0x27,0x0C]), PATCH: array.array('B',[0x2C,0x1A,0x0B])}, # jap TSU to S
{POS: 0x00208C10, ORIG: array.array('B', [0x1E,0x27,0x10]), PATCH: array.array('B',[0x37,0x1A,0x0B])}, # jap DZU to T
{POS: 0x00208C13, ORIG: array.array('B', [0x70,0x27,0x11]), PATCH: array.array('B',[0x42,0x1A,0x0B])}, # jap TE to U
{POS: 0x00208C16, ORIG: array.array('B', [0x2E,0x27,0x0F]), PATCH: array.array('B',[0x4D,0x1A,0x0B])}, # jap DE to V
{POS: 0x00208C19, ORIG: array.array('B', [0x81,0x27,0x12]), PATCH: array.array('B',[0x58,0x1A,0x0B])}, # jap TO to W
{POS: 0x00208C1C, ORIG: array.array('B', [0x3D,0x27,0x0E]), PATCH: array.array('B',[0x63,0x1A,0x0B])}, # jap DO to X
{POS: 0x00208C1F, ORIG: array.array('B', [0x93,0x27,0x0E]), PATCH: array.array('B',[0x6E,0x1A,0x0B])}, # jap tsu to Y
{POS: 0x00208C22, ORIG: array.array('B', [0x00,0x34,0x10]), PATCH: array.array('B',[0x79,0x1A,0x0B])}, # jap NA to Z
{POS: 0x00208C25, ORIG: array.array('B', [0x10,0x34,0x0E]), PATCH: array.array('B',[0x84,0x1A,0x0B])}, # jap NI to [
{POS: 0x00208C28, ORIG: array.array('B', [0x1E,0x34,0x0E]), PATCH: array.array('B',[0x8F,0x1A,0x0B])}, # jap NU to /
{POS: 0x00208C2B, ORIG: array.array('B', [0x2C,0x34,0x0F]), PATCH: array.array('B',[0x9A,0x1A,0x0B])}, # jap NE to ]
{POS: 0x00208C2E, ORIG: array.array('B', [0x3B,0x34,0x0E]), PATCH: array.array('B',[0xA5,0x1A,0x0B])}, # jap NO to ^
{POS: 0x00208C31, ORIG: array.array('B', [0x00,0x41,0x11]), PATCH: array.array('B',[0xB0,0x1A,0x0B])}, # jap HA to _
{POS: 0x00208C34, ORIG: array.array('B', [0x49,0x34,0x11]), PATCH: array.array('B',[0xBB,0x1A,0x0B])}, # jap BA to `
{POS: 0x00208C37, ORIG: array.array('B', [0x4E,0x41,0x11]), PATCH: array.array('B',[0xC6,0x1A,0x0B])}, # jap PA to =
#
# Now, the algorithm. The function is from 0x000F4F80 to 0x000f5046 (0x088F8EC0 in memory)
# The old one looks like this:
# put 2-byte word with char idx into the a0
# set v0 to 0xFF1F, compare with a0, jump to exit if ok
# same stuff for the 0xFF0D, 0xFF21, 0xFF22, 0xFF2D, 0xFF30
# subtract 0x30A1 (katakana A) from a0 and put result into 2-byte word, check if the result < 5F, jump to exit if ok
# if it was bigger - same, but now subtract 0x0030 from a0 (number)
# The result is kept within v1
# before exit - shift by 1 and add the same (multiply by 3)
# The new one will look like this:
# put 2-byte word with char idx into the a0
# set v1 to 3F - 20 = 1F, set v0 to 0xFF1F, compare with a0, jump to exit if ok (i want to keep ?, it's widely used)
# subtract 0x0020 (space) from a0, check if the result < 3A (0x5A-0x20, our range), if ok - jump to exit
# if bigger - set v1 to 1F (ok, let it be ???)
# before exit - add 1 (too lazy to think right now why), shift by 1 and add the same (multiply by 3)
# The patch was prepared using ppssppe disasm, so plz dont ask me wtf is written below.
# Just try to make the same thing by yourself
{POS: 0x000F4F80, ORIG: array.array('B', [0xFF,0xFF,0x84,0x30,0x1F,0xFF,0x02,0x34,0x22,0x00,0x82,0x10,0x03,0x00,0x03,0x24,0x0D,0xFF,0x02,0x34,0x1F,0x00,0x82,0x10,0x06,0x00,0x03,0x24,0x21,0xFF,0x02,0x34,0x1C,0x00,0x82,0x10,0x09,0x00,0x03,0x24,0x22,0xFF,0x02,0x34,0x19,0x00,0x82,0x10,0x0C,0x00,0x03,0x24,0x2D,0xFF,0x02,0x34,0x16,0x00,0x82,0x10,0x0F,0x00,0x03,0x24,0x30,0xFF,0x02,0x34,0x13,0x00,0x82,0x10,0x12,0x00,0x03,0x24,0x5F,0xCF,0x83,0x24,0xFF,0xFF,0x62,0x30,0x5F,0x00,0x42,0x2C,0x10,0x00,0x40,0x14,0x40,0x10,0x03,0x00,0xF0,0x00,0x82,0x24,0xFF,0xFF,0x42,0x30,0x0A,0x00,0x42,0x2C,0x0F,0x00,0x40,0x14,0xFF,0xFF,0x03,0x3C,0xD0,0xFF,0x84,0x24,0xFF,0xFF,0x82,0x30,0x0A,0x00,0x42,0x2C,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x15,0x00,0x43,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x60,0x00,0x21,0x10,0x43,0x00,0x33,0x00,0x43,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x60,0x00,0xF0,0x00,0x63,0x34,0x21,0x18,0x83,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x15,0x00,0x43,0x24,0x08,0x00,0xE0,0x03,0x21,0x10,0x60]),
PATCH: array.array('B', [0xFF,0xFF,0x84,0x30,0x1F,0xFF,0x02,0x34,0x1F,0x00,0x03,0x24,0x1C,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFE,0x02,0x24,0xFF,0xFF,0x42,0x30,0x00,0x00,0x03,0x24,0x16,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x24,0xE0,0xFF,0x83,0x24,0xFF,0xFF,0x62,0x30,0x40,0x00,0x42,0x2C,0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x03,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x00,0x00,0x00,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x08,0x00,0xE0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])},
# Patch also works without eboot expansion
]
},
{NAME: "Custom CLT", ENABLED: False, EXT_ONLY: False, CFG_ID: CLT_CFG_ID, DATA: []},
]
def apply_sys_lang(eboot):
#if LANG_CFG_ID in common.editor_config.hacks:
# sys_menu_lang = common.editor_config.hacks[LANG_CFG_ID]
#else:
# sys_menu_lang = 1
# common.editor_config.hacks[LANG_CFG_ID] = sys_menu_lang
sys_menu_lang = 1
patch_loc = 0x0008C2FC
patch = array.array('B', [sys_menu_lang]) + array.array('B', [0x00,0x02,0x24])
l = len(patch)
eboot[patch_loc:patch_loc+l] = patch
return eboot
def apply_clt_patch(eboot):
#if common.editor_config.hacks[CLT_CFG_ID]:
# styles = clt.CLT_STYLES
#else:
# styles = clt.CLT_ORIGINAL
styles = clt.CLT_ORIGINAL
patch_loc = 0x207288
for i in sorted(styles.keys()):
if i > clt.MAX_CLT:
break
patch = styles[i].to_bin()
l = len(patch)
loc = patch_loc + (i * 0x10)
eboot[loc:loc+l] = patch
return eboot
def extend_eboot(eboot):
NEW_SECTION_POS = 0x20CB40
NEW_SECTION_SIZE = 73728
ORIG_SIZE = 3081800
EXTENDED_SIZE = ORIG_SIZE + NEW_SECTION_SIZE
# Already extended, don't need to do it again.
if len(eboot) == EXTENDED_SIZE:
return eboot
elif len(eboot) != ORIG_SIZE:
raise ValueError("EBOOT neither matches original nor extended size. Try restoring the original, decrypted EBOOT.BIN to PSP_GAME/SYSDIR, then repack everything.")
eboot[NEW_SECTION_POS:NEW_SECTION_POS] = array.array('B', [0] * NEW_SECTION_SIZE)
# Since we're adding another program segment between program segments 0 and 1,
# we need to update references to program segment 1 on the relocation table
# so that they point to program segment 2.
#
# The pseudocode for this step is:
#
# For b = every 8 bytes from 0x22CF70 to the end of the file:
# If b[5] == 1, replace it with 2.
# If b[6] == 1, replace it with 2.
TABLE_START = 0x22CF70
pos = TABLE_START
while pos < len(eboot):
# Go to b[5]
pos += 5
if eboot[pos] == 0x01:
eboot[pos] = 0x02
# Next to b[6]
pos += 1
if eboot[pos] == 0x01:
eboot[pos] = 0x02
# And to the new line
pos += 2
return eboot
def generate_boot(eboot):
l = len(eboot)
boot = array.array('B', [0] * l)
return boot
def apply_eboot_patches(eboot, extend):
if extend:
eboot = extend_eboot(eboot)
for patch in EBOOT_PATCHES:
# Skip extended-only patches if eboot's not extended
if not extend and patch[EXT_ONLY]:
print "Skipping patch %s" % patch[CFG_ID]
continue
print "Applying patch %s" % patch[CFG_ID]
enabled = patch[ENABLED]
#if patch[CFG_ID] and patch[CFG_ID] in common.editor_config.hacks:
# enabled = common.editor_config.hacks[patch[CFG_ID]]
# So we can undo patches if they've already been applied.
key = PATCH if enabled else ORIG
for item in patch[DATA]:
l = len(item[key])
eboot[item[POS]:item[POS]+l] = item[key]
eboot = apply_sys_lang(eboot)
eboot = apply_clt_patch(eboot)
return eboot
if __name__ == "__main__":
src = "Test/EBOOT.BIN"
dst = "Test/EBOOT_PATCHED.BIN"
dst_boot = "Test/BOOT_PATCHED.BIN"
test = array.array('B')
test.fromfile(open(src,'rb'), os.path.getsize(src)/test.itemsize)
extend = True
test = apply_eboot_patches(test, extend)
boot = generate_boot(test)
with open(dst, "wb") as f:
test.tofile(f)
with open(dst_boot, "wb") as f:
boot.tofile(f)
### EOF ###