Number output files and folders instead of overwriting

Pack now writes <Name>.cache, or <Name>.cache.1, .2, ... if that file
already exists (replaces the fixed .cache.new name). Unpack writes each
target folder under ARCANE_DUMP the same way, e.g. COBJECTS.1. The
output folder is created only after the cache loads, so a missing cache
does not leave an empty numbered folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-16 13:43:40 -04:00
1 parent 7bcbed08a8
commit 9005de76d9
3 files changed
+60 -45

No files matched your search

@@ -6,6 +6,7 @@
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
import os
import struct
import zlib
@@ -81,7 +82,21 @@ def write_bytes(cache_file, value):
cache_file.write(value)
def next_available_path(path):
# Returns path if unused, otherwise the first free path.1, path.2, ...
if not os.path.exists(path):
return path
index = 1
while os.path.exists(f'{path}.{index}'):
index += 1
return f'{path}.{index}'
def save_cache_file(filename, resources, compress=True):
filename = next_available_path(filename)
print('Packing to ' + filename)
cache_file = open(filename, 'wb')
num_resources = len(resources)
+1 -1
View File
@@ -6,5 +6,5 @@
# Magicbane Emulator Project © 2013 - 2022
# www.magicbane.com
from .ArcFileCache import load_cache_file, save_cache_file
from .ArcFileCache import load_cache_file, save_cache_file, next_available_path
from .ResStream import ResStream
+44 -44
View File
@@ -89,6 +89,14 @@ EDITOR_TARGETS = [
]
def create_unpack_directory(base_directory):
# Never unpack over an existing folder; use the next free numbered name.
directory = next_available_path(base_directory)
os.makedirs(directory)
print('Unpacking to ' + directory)
return directory
def init_cobjects():
for obj_type in COBJECTS_MAP:
directory_path = os.path.join(COBJECTS_DIRECTORY, OBJECT_TYPE_TO_STRING[obj_type])
@@ -146,9 +154,11 @@ def init_render():
def unpack_cobjects():
init_cobjects()
resources = load_cache_file('CObjects.cache')
directory = create_unpack_directory(COBJECTS_DIRECTORY)
for obj_type in COBJECTS_MAP:
os.makedirs(os.path.join(directory, OBJECT_TYPE_TO_STRING[obj_type]))
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
@@ -158,7 +168,7 @@ def unpack_cobjects():
arc_in = COBJECTS_MAP[obj_type]()
filepath = os.path.join(
COBJECTS_DIRECTORY,
directory,
OBJECT_TYPE_TO_STRING[obj_type],
f'{res_id:d}.json'
)
@@ -193,7 +203,7 @@ def pack_cobjects():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('CObjects.cache.new', resources)
save_cache_file('CObjects.cache', resources)
def test_cobjects():
@@ -221,16 +231,15 @@ def test_cobjects():
def unpack_czones():
init_czones()
resources = load_cache_file('CZone.cache')
directory = create_unpack_directory(CZONE_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_zone = ArcZone()
in_stream = ResStream(data)
filepath = os.path.join(
CZONE_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_zone.load_binary(in_stream)
@@ -257,7 +266,7 @@ def pack_czones():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('CZone.cache.new', resources)
save_cache_file('CZone.cache', resources)
def test_czones():
@@ -280,16 +289,15 @@ def test_czones():
def unpack_sound():
init_sound()
resources = load_cache_file('Sound.cache')
directory = create_unpack_directory(SOUND_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_sound = ArcSound()
in_stream = ResStream(data)
filepath = os.path.join(
SOUND_DIRECTORY,
directory,
f'{res_id:d}.wav'
)
@@ -319,7 +327,7 @@ def pack_sound():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Sound.cache.new', resources, False)
save_cache_file('Sound.cache', resources, False)
def test_sound():
@@ -350,16 +358,15 @@ def test_sound():
def unpack_texture():
init_texture()
print('Decompressing Texture Cache...')
resources = load_cache_file('Textures.cache')
directory = create_unpack_directory(TEXTURE_DIRECTORY)
print('Writing images')
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
filepath = os.path.join(
TEXTURE_DIRECTORY,
directory,
f'{res_id:d}.tga'
)
@@ -386,7 +393,7 @@ def pack_texture():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Textures.cache.new', resources)
save_cache_file('Textures.cache', resources)
def test_texture():
@@ -418,14 +425,13 @@ def test_texture():
def unpack_terrain():
init_terrain()
resources = load_cache_file('TerrainAlpha.cache')
directory = create_unpack_directory(TERRAIN_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
filepath = os.path.join(
TERRAIN_DIRECTORY,
directory,
f'{res_id:d}.tga'
)
@@ -452,7 +458,7 @@ def pack_terrain():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('TerrainAlpha.cache.new', resources)
save_cache_file('TerrainAlpha.cache', resources)
def test_terrain():
@@ -486,16 +492,15 @@ def test_terrain():
def unpack_mesh():
init_mesh()
resources = load_cache_file('Mesh.cache')
directory = create_unpack_directory(MESH_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_mesh = ArcMesh()
in_stream = ResStream(data)
filepath = os.path.join(
MESH_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_mesh.load_binary(in_stream)
@@ -522,7 +527,7 @@ def pack_mesh():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Mesh.cache.new', resources)
save_cache_file('Mesh.cache', resources)
def test_mesh():
@@ -545,16 +550,15 @@ def test_mesh():
def unpack_visual():
init_visual()
resources = load_cache_file('Visual.cache')
directory = create_unpack_directory(VISUAL_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_visual = ArcVisual()
in_stream = ResStream(data)
filepath = os.path.join(
VISUAL_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_visual.load_binary(in_stream)
@@ -581,7 +585,7 @@ def pack_visual():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Visual.cache.new', resources)
save_cache_file('Visual.cache', resources)
def test_visual():
@@ -604,16 +608,15 @@ def test_visual():
def unpack_motion():
init_motion()
resources = load_cache_file('Motion.cache')
directory = create_unpack_directory(MOTION_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_motion = ArcMotion()
in_stream = ResStream(data)
filepath = os.path.join(
MOTION_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_motion.load_binary(in_stream)
@@ -640,7 +643,7 @@ def pack_motion():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Motion.cache.new', resources)
save_cache_file('Motion.cache', resources)
def test_motion():
@@ -663,16 +666,15 @@ def test_motion():
def unpack_tile():
init_tile()
resources = load_cache_file('Tile.cache')
directory = create_unpack_directory(TILE_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_tile = ArcTileManager()
in_stream = ResStream(data)
filepath = os.path.join(
TILE_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_tile.load_binary(in_stream)
@@ -699,7 +701,7 @@ def pack_tile():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Tile.cache.new', resources)
save_cache_file('Tile.cache', resources)
def test_tile():
@@ -722,16 +724,15 @@ def test_tile():
def unpack_skeleton():
init_skeleton()
resources = load_cache_file('Skeleton.cache')
directory = create_unpack_directory(SKELETON_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_skeleton = ArcSkeleton()
in_stream = ResStream(data)
filepath = os.path.join(
SKELETON_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_skeleton.load_binary(in_stream)
@@ -759,7 +760,7 @@ def pack_skeleton():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Skeleton.cache.new', resources)
save_cache_file('Skeleton.cache', resources)
def test_skeleton():
@@ -782,16 +783,15 @@ def test_skeleton():
def unpack_render():
init_render()
resources = load_cache_file('render.cache')
directory = create_unpack_directory(RENDER_DIRECTORY)
with tqdm(total=len(resources)) as pBar:
for res_id, data in resources:
arc_render = ArcRender()
in_stream = ResStream(data)
filepath = os.path.join(
RENDER_DIRECTORY,
directory,
f'{res_id:d}.json'
)
arc_render.load_binary(in_stream)
@@ -819,7 +819,7 @@ def pack_render():
resources.append([res_id, out_stream.get_bytes()])
save_cache_file('Render.cache.new', resources)
save_cache_file('Render.cache', resources)
def test_render():