From aba1e23a63897df18fa048315c880c4b316990f2 Mon Sep 17 00:00:00 2001 From: CGarz <20268068+cgarz@users.noreply.github.com> Date: Fri, 11 Jan 2019 23:14:57 +0000 Subject: [PATCH 1/6] added ability to return merged bin to split bin format. --- binmerge | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/binmerge b/binmerge index 2b05faf..419fb18 100644 --- a/binmerge +++ b/binmerge @@ -66,6 +66,13 @@ def read_cue_file(cue_path): if m: this_track.indexes.append({'id': int(m.group(1)), 'stamp': m.group(2), 'file_offset':cuestamp_to_sectors(m.group(2))}) + if len(files) == 1: + # only 1 file, assume splitting, calc sectors of each + next_item_offset = files[0].size // Track.globalBlocksize + for t in reversed(files[0].tracks): + t.sectors = next_item_offset - t.indexes[0]["file_offset"] + next_item_offset = t.indexes[0]["file_offset"] + for f in files: print("-- File --") print("Filename: %s" % f.filename) @@ -76,6 +83,7 @@ def read_cue_file(cue_path): print(" -- Track --") print(" Num: %d" % t.num) print(" Type: %s" % t.track_type) + if t.sectors: print(" Sectors: %s" % t.sectors) print(" Indexes: %s" % repr(t.indexes)) return files @@ -98,7 +106,7 @@ def cuestamp_to_sectors(stamp): return fields + (seconds * 75) + (minutes * 60 * 75) -def generate_cuesheet(bin_filename, files): +def gen_merged_cuesheet(bin_filename, files): cuesheet = 'FILE "%s" BINARY\n' % bin_filename # One sector is (BLOCKSIZE) bytes sector_pos = 0 @@ -110,6 +118,17 @@ def generate_cuesheet(bin_filename, files): sector_pos += f.size / Track.globalBlocksize return cuesheet +def gen_split_cuesheet(bin_filename, merged_file): + # similar to merged, could have it do both, but separate arguably cleaner + cuesheet = "" + for t in merged_file.tracks: + cuesheet += 'FILE "%s (Track %02d).bin" BINARY\n' % (bin_filename, t.num) + cuesheet += ' TRACK %02d %s\n' % (t.num, t.track_type) + for i in t.indexes: + sector_pos = i['file_offset'] - t.indexes[0]['file_offset'] + cuesheet += ' INDEX %02d %s\n' % (i['id'], sectors_to_cuestamp(sector_pos)) + return cuesheet + def merge_files(merged_filename, files): # cat is actually faster, but I prefer multi-platform and no special-casing chunksize = 1024 * 1024 @@ -123,16 +142,39 @@ def merge_files(merged_filename, files): outfile.write(chunk) return True +def split_files(cue_dir, new_basename, merged_file): + # use calculated sectors, read the same amount, start new file when equal + with open(os.path.join(cue_dir, merged_file.filename), 'rb') as infile: + for t in merged_file.tracks: + chunksize = 1024 * 1024 + out_name = '%s (Track %02d).bin' % (new_basename, t.num) + tracksize = t.sectors * Track.globalBlocksize + written = 0 + with open(out_name, 'wb') as outfile: + while True: + if chunksize + written > tracksize: + chunksize = tracksize - written + chunk = infile.read(chunksize) + outfile.write(chunk) + written += chunksize + if written == tracksize: + break + return True + def main(): parser = argparse.ArgumentParser(description="Using a cuesheet, merges numerous bin files into a single bin file and produces a new cuesheet with corrected offsets. Works great with Redump. Supports all block modes, but only binary track types. Should work on any python3 platform.") parser.add_argument('cuefile', help='path to source cuefile with multiple referenced bin tracks') parser.add_argument('new_name', help='name (without extension) for your new bin/cue files') + parser.add_argument('--split', help='Change mode from merging to splitting to allow reconstruction of the split format.', required=False, action="store_true") parser.add_argument('-o', dest='outdir', required=False, default=False, help='output directory. defaults to the same directory as source cue') args = parser.parse_args() cue_map = read_cue_file(args.cuefile) - cuesheet = generate_cuesheet(args.new_name+'.bin', cue_map) + if args.split: + cuesheet = gen_split_cuesheet(args.new_name, cue_map[0]) + else: + cuesheet = gen_merged_cuesheet(args.new_name+'.bin', cue_map) outdir = os.path.dirname(args.cuefile) if args.outdir: @@ -146,10 +188,17 @@ def main(): f.write(cuesheet) print("Wrote %s" % args.new_name+'.cue') - print("Merging files...") - if merge_files(os.path.join(outdir, args.new_name+'.bin'), cue_map): - print("Wrote %s" % args.new_name+'.bin') + if args.split: + print("Splitting files...") + if split_files(os.path.dirname(args.cuefile), os.path.join(outdir, args.new_name), cue_map[0]): + print("Wrote %d bin files" % len(cue_map[0].tracks)) + else: + print("Unable to split bin files") else: - print("Unable to merge bin files") + print("Merging files...") + if merge_files(os.path.join(outdir, args.new_name+'.bin'), cue_map): + print("Wrote %s" % args.new_name+'.bin') + else: + print("Unable to merge bin files") main() From e97516cc2064f6d4b53e701a0150f645357fffa2 Mon Sep 17 00:00:00 2001 From: CGarz <20268068+cgarz@users.noreply.github.com> Date: Fri, 11 Jan 2019 23:36:20 +0000 Subject: [PATCH 2/6] fixed gen_split_cue index indentation --- binmerge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 binmerge diff --git a/binmerge b/binmerge old mode 100644 new mode 100755 index 419fb18..17f8c97 --- a/binmerge +++ b/binmerge @@ -126,7 +126,7 @@ def gen_split_cuesheet(bin_filename, merged_file): cuesheet += ' TRACK %02d %s\n' % (t.num, t.track_type) for i in t.indexes: sector_pos = i['file_offset'] - t.indexes[0]['file_offset'] - cuesheet += ' INDEX %02d %s\n' % (i['id'], sectors_to_cuestamp(sector_pos)) + cuesheet += ' INDEX %02d %s\n' % (i['id'], sectors_to_cuestamp(sector_pos)) return cuesheet def merge_files(merged_filename, files): From ae9f9440942577d15a9092537bc746f8ee2b0b3d Mon Sep 17 00:00:00 2001 From: CGarz <20268068+cgarz@users.noreply.github.com> Date: Fri, 11 Jan 2019 23:41:54 +0000 Subject: [PATCH 3/6] forced cuesheet line endings to windows crlf to match redump --- binmerge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binmerge b/binmerge index 17f8c97..0c91fec 100755 --- a/binmerge +++ b/binmerge @@ -184,7 +184,7 @@ def main(): print("Output dir does not exist") return False - with open(os.path.join(outdir, args.new_name+'.cue'), 'w') as f: + with open(os.path.join(outdir, args.new_name+'.cue'), 'w', newline='\r\n') as f: f.write(cuesheet) print("Wrote %s" % args.new_name+'.cue') From 80f369d130b2e79e899f5ba1686da08ec3f3d88c Mon Sep 17 00:00:00 2001 From: CGarz <20268068+cgarz@users.noreply.github.com> Date: Sat, 12 Jan 2019 01:44:07 +0000 Subject: [PATCH 4/6] removed split_files redundant cue path prepending. fixes path errors when calling from another dir. --- binmerge | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/binmerge b/binmerge index 0c91fec..46f8d2d 100755 --- a/binmerge +++ b/binmerge @@ -142,9 +142,9 @@ def merge_files(merged_filename, files): outfile.write(chunk) return True -def split_files(cue_dir, new_basename, merged_file): +def split_files(new_basename, merged_file): # use calculated sectors, read the same amount, start new file when equal - with open(os.path.join(cue_dir, merged_file.filename), 'rb') as infile: + with open(merged_file.filename, 'rb') as infile: for t in merged_file.tracks: chunksize = 1024 * 1024 out_name = '%s (Track %02d).bin' % (new_basename, t.num) @@ -190,7 +190,7 @@ def main(): if args.split: print("Splitting files...") - if split_files(os.path.dirname(args.cuefile), os.path.join(outdir, args.new_name), cue_map[0]): + if split_files(os.path.join(outdir, args.new_name), cue_map[0]): print("Wrote %d bin files" % len(cue_map[0].tracks)) else: print("Unable to split bin files") From 9a3e0d467c7ec21d6d32e1fc3ff2c9ff7871b51f Mon Sep 17 00:00:00 2001 From: cgarz <20268068+cgarz@users.noreply.github.com> Date: Sat, 9 Mar 2019 15:52:55 +0000 Subject: [PATCH 5/6] documented --split with some example motivations --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index cf6c949..c336219 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,10 @@ FILE "Big Buddy.bin" BINARY INDEX 01 38:52:66 ``` +If you want to return to the split bin format you can instead pass a merged cue file with the --split paramater. + +This is useful for example to verify psx split bin files against the Redump project's psx dat file. + +Users of MAME's chdman tool may also find this option useful as chdman returns the merged cue format when decompressing. + Have fun! From 7ad4ddccc990fcb4a7a5b5638cae41158b479c60 Mon Sep 17 00:00:00 2001 From: cgarz <20268068+cgarz@users.noreply.github.com> Date: Sun, 10 Mar 2019 00:56:47 +0000 Subject: [PATCH 6/6] spelling fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c336219..3678b11 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ FILE "Big Buddy.bin" BINARY INDEX 01 38:52:66 ``` -If you want to return to the split bin format you can instead pass a merged cue file with the --split paramater. +If you want to return to the split bin format you can instead pass a merged cue file with the --split parameter. -This is useful for example to verify psx split bin files against the Redump project's psx dat file. +This is useful for example to verify PSX split bin files against the Redump project's PSX DAT file. Users of MAME's chdman tool may also find this option useful as chdman returns the merged cue format when decompressing.