Skip to content

Instantly share code, notes, and snippets.

@loveemu
Last active December 8, 2021 08:28
Show Gist options
  • Save loveemu/820fb2a419bbfe884672f21330c1113c to your computer and use it in GitHub Desktop.
Save loveemu/820fb2a419bbfe884672f21330c1113c to your computer and use it in GitHub Desktop.
HBS Sound File to SEQ/VAB Unpacker for Alice in Cyberland (Playstation)
"""HBS Sound File to SEQ/VAB Unpacker for Alice in Cyberland (Playstation)"""
import argparse
import struct
import sys
from pathlib import Path
from typing import BinaryIO
# HBS sound format (RIFF-like format):
# Header
# b'hHBS'
# File length
# 0
# 0xC
# Chunks
# FourCC
# Chunk length (including this header)
# Chunk data
#
# Available chunks:
# 'cVAB':
# Raw VAB Data
# 'cSEQ':
# Header (12 bytes)
# 00: byte - ?
# 01: byte - ?
# 02: word - ?
# 04: byte - song volume left
# 05: byte - song volume right
# 06: word - reverb type? (0x8000+n = reverb enabled)
# 08: byte - reverb depth left
# 09: byte - reverb depth right
# 0a: byte - reverb feedback
# 0b: byte - reverb delay time
# Raw SEQ Data
# 'cVHD':
# (Chunk for VH? Not supported)
# 'cVBD':
# (Chunk for VB? Not supported)
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('file', type=argparse.FileType('rb'), help='HBS file to be unpacked')
args = parser.parse_args()
hbs_file: BinaryIO = args.file
basename = Path(args.file.name).stem
signature, hbs_length, maybe_version, a0c = struct.unpack('<4sLLL', hbs_file.read(16))
if signature != b'hHBS':
sys.exit('Error: HBS file signature error')
if maybe_version != 0:
sys.exit('Error: Unsupported HBS file version')
offset = 0x10
while offset < hbs_length:
fourcc, full_chunk_length = struct.unpack('<4sL', hbs_file.read(8))
fourcc_str = fourcc.decode()
if full_chunk_length < 8:
sys.exit("Error: Chunk '%s' is too short (offset at 0x%X)" % (fourcc_str, offset))
data_length = full_chunk_length - 8
next_offset = offset + full_chunk_length
if fourcc == b'cVAB':
vab = hbs_file.read(data_length)
with open(basename + '.VAB', 'wb') as vab_file:
vab_file.write(vab)
elif fourcc == b'cSEQ':
if data_length < 12:
sys.exit("Error: Chunk '%s' is too short (offset at 0x%X)" % (fourcc_str, offset))
cseq_header = hbs_file.read(12)
#with open(basename + '.SEQHEADER', 'wb') as seq_h_file:
# seq_h_file.write(cseq_header)
seq = hbs_file.read(data_length - 12)
with open(basename + '.SEQ', 'wb') as seq_file:
seq_file.write(seq)
else:
hbs_file.seek(offset + full_chunk_length)
offset = next_offset
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment