Last active
February 14, 2019 21:58
-
-
Save Gemba/e9107eaf4c61d1643dc56432e1d3306e to your computer and use it in GitHub Desktop.
Create CBM D71/D81/D82 from Commodore 64 D64 multidisk game archives for ease of use in emulator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
# | |
# Creates D71/D81/D82 CBM disks from gamebase's C64 multidisk | |
# games archives (*.zip). | |
# | |
# Requires: http://style64.org/cbmdisk/ | |
# | |
# Note: Stuffing the multidisks on one larger disc may or may not work in the | |
# emulator, but it is worth a try before you need to fiddle with disc | |
# flipping during gameplay. | |
# | |
# Note: Since the module cbmdisk is only available on Windows platform this | |
# script works only on Windows. | |
# | |
# Author: Gemba | |
# License: MIT | |
# | |
from __future__ import print_function | |
import os | |
import re | |
import shutil | |
import site | |
import sys | |
import tempfile | |
import zipfile | |
try: | |
import cbmdisk | |
except ImportError: | |
print ("[!] Module cbmdisk is not present.") | |
print (" Please visit http://style64.org/cbmdisk/ and") | |
print (" download package, deploy contained cbmdisk.pyd into:") | |
sp = next(p for p in site.getsitepackages() if 'site-packages' in p) | |
print (" %s" % sp) | |
sys.exit(1) | |
# adjust the next two values to needs | |
# Where to find the flat directory structure with the gamebase zip archives? | |
ROM_HOME = "C:/temp/c64-multidisk/gamebase-multidisk-zips" | |
# Where to put the combined discs? | |
OUT_DIR = "C:/temp/c64-multidisk/d78x_out" | |
# used later to ignore VERSION.NFO within gamebase archives | |
PATTERN = re.compile(r"^VERSION.NFO$", re.IGNORECASE) | |
types = {} | |
for t in ['D71', 'D81', 'D82']: | |
types[t] = cbmdisk.Disk(type=t).free_blocks | |
# get list of CBM files from all *.D64 files | |
def get_cbm_files(rom_file): | |
base_name = os.path.basename(rom_file) | |
with zipfile.ZipFile(rom_file, 'r') as zh: | |
zip_contents = [nn for nn in zh.namelist() if not PATTERN.match(nn)] | |
disk0_fn = None | |
cbmdisk_title = None | |
total_blocks = 0 | |
cbm_files = [] | |
if len(zip_contents) > 1: | |
print("[+] Processing %s ..." % base_name) | |
tmp = os.path.join(tempfile.gettempdir(), base_name) | |
shutil.rmtree(tmp, ignore_errors=True) | |
os.mkdir(tmp) | |
for idx, m in enumerate(sorted(zip_contents)): | |
zh.extract(m, tmp) | |
#print (m) | |
d64 = cbmdisk.Disk(os.path.join(tmp, m)) | |
if idx == 0: | |
cbmdisk_title = d64.name | |
disk0_fn = m | |
for f in d64.files: | |
cbm_files.append(f) | |
total_blocks = total_blocks + f.size | |
#print ("%s: %d" % (f.name, f.size)) | |
shutil.rmtree(tmp, ignore_errors=True) | |
else: | |
print ("[-] Skipping %s. Not a multidisk game" % base_name) | |
return (disk0_fn, cbmdisk_title, total_blocks, cbm_files) | |
# determine target disk size | |
def get_cbm_disk_type(total_blocks): | |
type = 'D71' | |
if total_blocks > types['D71']: | |
type = 'D81' | |
if total_blocks > types['D81']: | |
if total_blocks <= types['D82']: | |
type = 'D82' | |
else: | |
type = None | |
return type | |
if __name__ == "__main__": | |
if not os.path.exists(ROM_HOME): | |
print ("[!] Path %s does not exist. Please fix." % ROM_HOME) | |
sys.exit(1) | |
if not os.path.exists(OUT_DIR): | |
os.mkdir(OUT_DIR) | |
for rom in [f for f in os.listdir(ROM_HOME) | |
if os.path.splitext(f)[1].lower() == ".zip"]: | |
rom_file = os.path.join(ROM_HOME, rom) | |
disk0_fn, cbm_dt, total_blocks, cbm_files = get_cbm_files(rom_file) | |
if not disk0_fn: | |
continue | |
type = get_cbm_disk_type(total_blocks) | |
if not type: | |
print ("[!] Fileset too large: %d blocks. Does exceed D82 " | |
"maximum capacity (%d blocks)." | |
% (total_blocks, types['D82'])) | |
print (" Skipping file %s" % os.path.basename(rom_file)) | |
shutil.rmtree(tmp, ignore_errors=True) | |
continue | |
# some exceptions | |
base_name = os.path.basename(rom_file) | |
if base_name == "OPERTHU0_05431_02.zip": | |
type = 'D82' | |
cbmdisk_tgt = cbmdisk.Disk(type=type) | |
cbmdisk_tgt.name = cbm_dt | |
# loop over all CBM files found in the *.D64 files | |
# and copy CBM files together | |
for f in cbm_files: | |
#print (f) | |
cbmdisk_tgt.files.copy(len(cbmdisk_tgt.files), f) | |
filename = os.path.splitext(disk0_fn)[0] + "." + type | |
outf = os.path.join(OUT_DIR, filename) | |
cbmdisk_tgt.save(outf) | |
print ("[+] ... wrote '%s' disktype to: %s for %s" % (type, outf, rom)) | |
print ("[+] Done.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment