diff --git a/README b/README index 5a80bc4..6d42f6a 100644 --- a/README +++ b/README @@ -150,6 +150,10 @@ Command line arguments are: This should normally not be needed as we automatically inject the magic word to the emulator running on the PS3. +--romhacks : Comma separated list of romhacks to apply. + Only supported types are .ppf and .xdelta files. + There must be one romhack for each disk image in the + conversion. --snd0 : Provide an audio file to be played when this game is focused on the XMB. See the SND0.AT3 section below. --auto-libcrypt : Try to automatically create and apply a patch for @@ -203,6 +207,23 @@ Similarly, files named as _pic0.png and _pic1.png are used for the scr images. +ROMHACKS +======== +Romhacks can be provided and automatically applied. +These must either be in PPF format and have a 'ppf' extension or in +Xdelta[3] format and have a 'xdelta' extension. +This is a comma-separated list of hacks to apply, one hack for each disk +in the conversion. +If you don't want to specify a hack for a disk in the set, then specify 'none'. + +Example: +To apply a romhack on a single disc: +$ ./pop-fe.py --psp-dir=auto --romhacks SMT.xdelta Shin\ Megami\ Tensei.cue + +To apply a romhack to only the second disc of a two disc game: +$ ./pop-fe.py --psp-dir=auto --romhacks none,X.ppf D1.cue D2.cue + + PS3 External config files ========================= External configs is a way to add commands to the ps1_netemu emulator that to diff --git a/pop-fe.py b/pop-fe.py index 1bc03f9..a1a85c9 100755 --- a/pop-fe.py +++ b/pop-fe.py @@ -1927,6 +1927,45 @@ def apply_ppf_fixes(real_disc_ids, cue_files, img_files, subdir): return cue_files, img_files + +def ApplyXDELTA(img, romhack): + print('Applying XDELTA', romhack) + _tmp = img + 'tmp' + subprocess.run(['xdelta3', 'decode', '-s', img, romhack, _tmp], timeout=30, check=True) + os.remove(img) + os.rename(_tmp, img) + +# +# Apply all romhacks +# +def apply_romhacks(real_disc_ids, cue_files, img_files, romhacks, subdir): + for i in range(len(real_disc_ids)): + if romhacks[i] == 'none': + continue + if subdir != cue_files[i][:len(subdir)]: + # Need to copy the bin/cue to the work directory. + # We know this is a single bin at this point as if it would have + # been merged into the work directory otherwise + _c = subdir + 'PATCH%02x.cue' % i + _b = subdir + 'PATCH%02x.bin' % i + print('Copy %s -> %s so we can apply ROMHACK' % (img_files[i], _b)) + copy_file(img_files[i], _b) + temp_files.append(_b) + with open(cue_files[i], 'r') as fi: + l = fi.readlines() + l[0] = 'FILE "%s" BINARY\n' % ('PATCH%02x.bin' % i) + with open(_c, 'w') as fo: + fo.writelines(l) + temp_files.append(_c) + cue_files[i] = _c + img_files[i] = _b + + if romhacks[i][-4:] == '.ppf': + ApplyPPF(img_files[i], romhacks[i]) + if romhacks[i][-7:] == '.xdelta': + ApplyXDELTA(img_files[i], romhacks[i]) + return cue_files, img_files + def generate_cu2_files(cue_files, img_files, subdir): cu2_files = [] @@ -2036,6 +2075,7 @@ def generate_aea_files(cue_files, img_files, subdir): help='List available themes') parser.add_argument('--theme', help='Theme to use') + parser.add_argument('--romhacks', help='Romhacks to apply') parser.add_argument('files', nargs='*') args = parser.parse_args() @@ -2233,6 +2273,17 @@ def generate_aea_files(cue_files, img_files, subdir): # cue_files, img_files = apply_ppf_fixes(real_disc_ids, cue_files, img_files, subdir) + # + # Apply all romhacks + # + if args.romhacks: + romhacks = args.romhacks.split(',') + if len(romhacks) != len(cue_files): + print('--romhacks must have one patch for each disk. Found %d disks but only %d romhacks.' % (len(cue_files), len(romhacks))) + shutil.rmtree('pop-fe-work', ignore_errors=True) + os._exit(1) + cue_files, img_files = apply_romhacks(real_disc_ids, cue_files, img_files, romhacks, subdir) + cu2_files = generate_cu2_files(cue_files, img_files, subdir) if args.psp_dir or args.ps3_pkg or args.retroarch_pbp_dir: