Skip to content

Instantly share code, notes, and snippets.

@Gemba
Last active February 14, 2019 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gemba/e9107eaf4c61d1643dc56432e1d3306e to your computer and use it in GitHub Desktop.
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
#!/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