class Transition(DataLoader): module = None name = None duration = None # in ms flags = None color = None moduleFile = None parameterData = None def __init__(self, reader: ByteIO): self.reader = reader self.flags = BitDict('Color') currentPosition = self.reader.tell() self.module = self.reader.read(4) self.name = self.reader.read(4) self.duration = self.reader.read_int32() self.flags.setFlags(self.reader.read_uint32()) self.color = [self.reader.read_uint8() for _ in range(4)] nameOffset = self.reader.read_int32() parameterOffset = self.reader.read_int32() parameterSize = self.reader.read_int32() self.reader.seek(currentPosition + nameOffset) self.moduleFile = self.reader.read_ascii_string() self.reader.seek(currentPosition + parameterOffset) self.parameterData = self.reader.read(parameterSize) def isStandard(self): return self.name == 'STDT'
class ExtendedHeader(DataLoader): def __init__(self, reader): self.reader = reader self.flags = BitDict( 'KeepScreenRatio', 'FrameTransition', # (HWA only) frame has a transition 'ResampleStretch', # (HWA only) resample while resizing 'GlobalRefresh' # (Mobile) force global refresh ) self.buildType = None self.buildFlags = None self.screenRatioTolerance = None self.screenAngle = None def read(self): self.flags.setFlags(self.reader.read_int32()) self.buildType = self.reader.read_uint32() self.buildFlags = self.reader.read_uint32() self.screenRatioTolerance = self.reader.read_int16() self.screenAngle = self.reader.read_int16() self.reader.read_int32() if self.buildType >= 0x10000000: self.update_settings(compat=True) def print(self): print(f'Flag: {self.flags}') print(f'Build type: {self.buildType}') print(f'Build flags: {self.buildFlags}') print(f'Screen ratio tolerance: {self.screenRatioTolerance}') print(f'Screen Angle: {self.screenAngle}')
class Transition(DataLoader): module = None name = None id = None transitionId = None duration = None # in ms flags = None color = None parameterData = None def initialize(self): self.flags = BitDict('Color') def read(self, reader): self.module = reader.read(reader.readInt()) self.name = reader.read(reader.readInt()) self.id = reader.read(4) self.transitionId = reader.read(4) self.duration = reader.readInt() self.flags.setFlags(reader.readInt()) self.color = reader.readColor() self.parameterData = reader.read(reader.readInt()) def write(self, reader): reader.writeInt(len(self.module)) reader.write(self.module) reader.writeInt(len(self.name)) reader.write(self.name) reader.write(self.id) reader.write(self.transitionId) reader.writeInt(self.duration) reader.writeInt(self.flags.getFlags()) reader.writeColor(self.color) reader.writeInt(len(self.parameterData)) reader.write(self.parameterData)
def initialize(self): self.palette = [] self.flags = BitDict('GrabDesktop', 'KeepDisplay', 'BackgroundCollisions', 'DisplayFrameTitle', 'ResizeToScreen', 'ForceLoadOnCall', 'NoDisplaySurface', 'ScreenSaverSetup', 'TimerBasedMovements', 'MochiAds', 'NoGlobalEvents')
def __init__(self, reader): self.reader = reader self.flags = BitDict( 'KeepScreenRatio', 'FrameTransition', # (HWA only) frame has a transition 'ResampleStretch', # (HWA only) resample while resizing 'GlobalRefresh' # (Mobile) force global refresh ) self.buildType = None self.buildFlags = None self.screenRatioTolerance = None self.screenAngle = None
class MusicFile(DataLoader): def __init__(self, reader: ByteIO): self.reader = reader self.handle = None self.name = None self.checksum = None self.references = None self.flags = BitDict( 'Wave', 'MIDI', None, None, 'LoadOnCall', 'PlayFromDisk', 'Loaded' ) self.data = None self.ext = '.mp3' def read(self): reader = self.reader debug = self.settings.get('debug', False) compressed = not debug and self.settings.get('compressed', True) self.handle = reader.read_int32() if compressed: reader = reader.auto_decompress(True) self.checksum = reader.read_uint32() self.references = reader.read_uint32() size = reader.read_uint32() self.flags.setFlags(reader.read_uint32()) reserved = reader.read_int32() name_length = reader.read_int32() self.name = reader.read_wide_string(name_length) self.data = reader.read_bytes(size - name_length) if self.flags['Wave']: self.ext = '.wav' elif self.flags['MIDI']: self.ext = '.midi' if self.settings.get('DUMPMUSIC', False) or self.settings.get('DUMPEVERYTHING', False): self.dump() def dump(self): if self.settings.get('VERBOSE', False): print(f'Saving "{self.name}{self.ext}"') with open(os.path.join(self.settings['dump_path'], 'MusicBank', f'{self.name}{self.ext}'), 'wb') as fp: fp.write(self.data) return self
class Layer(DataLoader): def __init__(self, reader: ByteIO): self.reader = reader self.name = '' self.flags = BitDict( 'XCoefficient', 'YCoefficient', 'DoNotSaveBackground', None, # Wrap (Obsolete) 'Visible', # visible 'WrapHorizontally', 'WrapVertically', None, None, None, None, None, None, None, None, None, 'Redraw', 'ToHide', 'ToShow' ) self.x_coefficient = 0 self.y_coefficient = 0 self.number_of_backgrounds = 0 self.background_index = 0 def read(self): reader = self.reader value = reader.read_uint32() self.flags.setFlags(value) self.x_coefficient = reader.read_float() self.y_coefficient = reader.read_float() self.number_of_backgrounds = reader.read_int32() self.background_index = reader.read_int32() self.name = reader.read_ascii_string() def write(self, reader: ByteIO): reader.write_uint32(self.flags.getFlags()) reader.write_float(self.x_coefficient) reader.write_float(self.y_coefficient) reader.write_int32(self.number_of_backgrounds) reader.write_int32(self.background_index) reader.write_ascii_string(self.name) def get_backgrounds(self, objectInstances): return objectInstances.items[ self.background_index:self.background_index + self.number_of_backgrounds] def get_instances(self, objectInstances): return self.parent.getObjectInstances(self, objectInstances)
def __init__(self, reader: ByteIO): self.reader = reader self.handle = None self.name = None self.checksum = None self.references = None self.flags = BitDict( 'Wave', 'MIDI', None, None, 'LoadOnCall', 'PlayFromDisk', 'Loaded' ) self.data = None self.ext = '.mp3'
def __init__(self, reader: ByteIO): self.reader = reader self.flags = BitDict('Color') currentPosition = self.reader.tell() self.module = self.reader.read(4) self.name = self.reader.read(4) self.duration = self.reader.read_int32() self.flags.setFlags(self.reader.read_uint32()) self.color = [self.reader.read_uint8() for _ in range(4)] nameOffset = self.reader.read_int32() parameterOffset = self.reader.read_int32() parameterSize = self.reader.read_int32() self.reader.seek(currentPosition + nameOffset) self.moduleFile = self.reader.read_ascii_string() self.reader.seek(currentPosition + parameterOffset) self.parameterData = self.reader.read(parameterSize)
def __init__(self, reader: ByteIO): self.reader = reader self.name = '' self.flags = BitDict( 'XCoefficient', 'YCoefficient', 'DoNotSaveBackground', None, # Wrap (Obsolete) 'Visible', # visible 'WrapHorizontally', 'WrapVertically', None, None, None, None, None, None, None, None, None, 'Redraw', 'ToHide', 'ToShow' ) self.x_coefficient = 0 self.y_coefficient = 0 self.number_of_backgrounds = 0 self.background_index = 0
def __init__(self, reader: ByteIO): self.reader = reader self.width = 0 self.height = 0 self.flags = BitDict( 'DisplayName', 'GrabDesktop', 'KeepDisplay', 'FadeIn', 'FadeOut', 'TotalCollisionMask', 'Password', 'ResizeAtStart', 'DoNotCenter', 'ForceLoadOnCall', 'NoSurface', 'Reserved_1', 'Reserved_2', 'RecordDemo', None, 'TimedMovements' ) self.background = None
class FrameHeader(DataLoader): def __init__(self, reader: ByteIO): self.reader = reader self.width = 0 self.height = 0 self.flags = BitDict( 'DisplayName', 'GrabDesktop', 'KeepDisplay', 'FadeIn', 'FadeOut', 'TotalCollisionMask', 'Password', 'ResizeAtStart', 'DoNotCenter', 'ForceLoadOnCall', 'NoSurface', 'Reserved_1', 'Reserved_2', 'RecordDemo', None, 'TimedMovements' ) self.background = None def read(self): reader = self.reader self.width = reader.read_int32() self.height = reader.read_int32() self.background = reader.read_fmt('BBBB') self.flags.setFlags(reader.read_uint32()) def write(self, reader: ByteIO): reader.write_int32(self.width) reader.write_int32(self.height) reader.write_fmt('BBBB', self.background) reader.write_uint32(self.flags.getFlags())
class RTFObject(DataLoader): RTF_FLAGS = BitDict( 'Transparent', 'VerticalSlider', 'HorizontalSlider' ) def __init__(self, reader: ByteIO): self.reader = reader self.options = self.RTF_FLAGS.copy() size = self.reader.read_int32() self.version = self.reader.read_int32() self.options.setFlags(self.reader.read_int32()) self.backColor = [self.reader.read_uint8() for _ in range(4)] self.width = self.reader.read_int32() self.height = self.reader.read_int32() self.reader.read_bytes(4) self.value = self.reader.read(self.reader.read_int32())
'None', 'Solid', 'Gradient', 'Motif' ] HORIZONTAL_GRADIENT = 0 VERTICAL_GRADIENT = 1 GRADIENT_TYPES = [ 'Horizontal', 'Vertical' ] SHAPE_FLAGS = BitDict( 'InverseX', 'InverseY' ) class AlterableValues(DataLoader): def __init__(self, reader: ByteIO): self.reader = reader self.items = [self.reader.read_int32() for _ in range(self.reader.read_uint16())] class AlterableStrings(DataLoader): def __init__(self, reader: ByteIO): self.reader = reader self.items = [self.reader.read_ascii_string() for _ in range(self.reader.read_uint16())]
import os from math import ceil from typing import Dict from PIL import Image from CTF_ByteIO import ByteIO from Loader import DataLoader from ProgressBar import ProgressBar from bitdict import BitDict POINT_MODE = 4 # 16 million colors FIFTEENPOINT_MODE = 6 # 32768 colors IMAGE_FLAGS = BitDict('RLE', 'RLEW', 'RLET', 'LZX', 'Alpha', 'ACE', 'Mac') class BasePoint: pass class IndexPoint(BasePoint): def __init__(self): self.size = 1 def read(self, data, position) -> int: return data[position] class Point(BasePoint): def __init__(self):
reader.writeInt(self.id) class Int(ParameterCommon): value = None def read(self, reader): self.value = reader.readInt() def write(self, reader): reader.writeInt(self.value) SAMPLE_FLAGS = BitDict( 'Uninterruptible', 'Bad', 'IPhoneAudioPlayer', 'IPhoneOpenAL' ) class Sample(ParameterCommon): handle = None flags = None def initialize(self): self.flags = SAMPLE_FLAGS.copy() def read(self, reader): self.handle = reader.readShort() self.flags.setFlags(reader.readShort(True)) self.name = self.readString(reader)
NONE_EFFECT: 'None', SEMITRANSPARENT_EFFECT: 'Semitransparent', INVERTED_EFFECT: 'Inverted', XOR_EFFECT: 'XOR', AND_EFFECT: 'AND', OR_EFFECT: 'OR', ADD_EFFECT: 'Add', MONOCHROME_EFFECT: 'Monochrome', SUBTRACT_EFFECT: 'Subtract', SHADER_EFFECT: 'Shader', HWA_EFFECT: 'HWA' } OBJECT_FLAGS = BitDict( 'LoadOnCall', 'Discardable', 'Global', 'Reserved_1' ) (PLAYER, KEYBOARD, CREATE, TIMER, GAME, SPEAKER, SYSTEM, QUICKBACKDROP, BACKDROP, ACTIVE, TEXT, QUESTION, SCORE, LIVES, COUNTER, RTF, SUBAPPLICATION) = range(-7, 10) def get_object_type(id): if id < EXTENSION_BASE: return objectTypes[id] else: return 'Extension' class ObjectName(StringChunk):
class Frame(DataLoader): handle = None name = None size = None background = None maxObjects = None password = None palette = None fadeIn = None fadeOut = None def initialize(self): self.palette = [] self.flags = BitDict('GrabDesktop', 'KeepDisplay', 'BackgroundCollisions', 'DisplayFrameTitle', 'ResizeToScreen', 'ForceLoadOnCall', 'NoDisplaySurface', 'ScreenSaverSetup', 'TimerBasedMovements', 'MochiAds', 'NoGlobalEvents') def read(self, reader): self.handle = reader.readInt() self.name = reader.read(reader.readInt()) self.size = (reader.readInt(), reader.readInt()) self.background = reader.readColor() self.flags.setFlags(reader.readInt(True)) self.maxObjects = reader.readInt() self.password = reader.read(reader.readInt()) checkDefault(reader, reader.readInt(), 0) self.lastViewedX = reader.readInt() self.lastViewedY = reader.readInt() self.palette = [reader.readColor() for _ in xrange(reader.readInt())] self.stampHandle = reader.readInt() self.activeLayer = reader.readInt() self.layers = [ self.new(Layer, reader) for _ in xrange(reader.readInt()) ] if reader.readByte() != 0: self.fadeIn = self.new(Transition, reader) if reader.readByte() != 0: self.fadeOut = self.new(Transition, reader) self.items = items = [ self.new(FrameItem, reader) for _ in xrange(reader.readInt()) ] self.folders = [ self.new(ItemFolder, reader) for _ in xrange(reader.readInt(True)) ] self.instances = [ self.new(FrameInstance, reader) for _ in xrange(reader.readInt()) ] self.events = self.new(Events, reader) self.chunks = self.new(ChunkList, reader) def write(self, reader): reader.writeInt(self.handle) reader.writeInt(len(self.name)) reader.write(self.name) reader.writeInt(self.size[0]) reader.writeInt(self.size[1]) reader.writeColor(self.background) reader.writeInt(self.flags.getFlags(), True) reader.writeInt(self.maxObjects) reader.writeInt(len(self.password)) reader.write(self.password) reader.writeInt(0) reader.writeInt(self.lastViewedX) reader.writeInt(self.lastViewedY) reader.writeInt(len(self.palette)) for item in self.palette: reader.writeColor(item) reader.writeInt(self.stampHandle) reader.writeInt(self.activeLayer) reader.writeInt(len(self.layers)) for item in self.layers: item.write(reader) for item in (self.fadeIn, self.fadeOut): if item is not None: reader.writeByte(1) item.write(reader) else: reader.writeByte(0) for item in (self.items, self.folders, self.instances): reader.writeInt(len(item), True) for subitem in item: subitem.write(reader) self.events.write(reader) self.chunks.write(reader)
self.parent) continue items.append(self.new(CHUNK_LOADERS[id], data)) size = reader.tell() - start reader.seek(start) self.saved = reader.read(size) def write(self, reader): if self.saved is not None: reader.write(self.saved) else: reader.writeByte(0) LAYER_FLAGS = BitDict('Visible', 'Locked', 'Obsolete', 'HideAtStart', 'NoBackground', 'WrapHorizontally', 'WrapVertically', 'PreviousEffect') class Layer(DataLoader): name = None xCoefficient = None yCoefficient = None flags = None def initialize(self): self.flags = LAYER_FLAGS.copy() def read(self, reader): self.name = reader.read(reader.readInt()) self.flags.setFlags(reader.readInt())
from CTF_ByteIO import ByteIO from Chunks.Common import ObjectInfoMixin, AceCommon from Chunks.Paramerers.Parameters import parameter_loaders, get_name from Loader import DataLoader from bitdict import BitDict HEADER = b'ER>>' EVENT_COUNT = b'ERes' EVENTGROUP_DATA = b'ERev' END = b'<<ER' ACE_FLAGS = BitDict('Repeat', 'Done', 'Default', 'DoneBeforeFadeIn', 'NotDoneInStart', 'Always', 'Bad', 'BadObject', None, 'Notable') ACE_OTHERFLAGS = BitDict('Not', 'Notable', 'Monitorable', 'ToDelete', 'NewSound') GROUP_FLAGS = BitDict('Once', 'NotAlways', 'Repeat', 'NoMore', 'Shuffle', 'EditorMark', 'UndoMark', 'ComplexGroup', 'Breakpoint', 'AlwaysClean', 'OrInGroup', 'StopInGroup', 'OrLogical', 'Grouped', 'Inactive', 'NoGood') class Qualifier(DataLoader, ObjectInfoMixin): def __init__(self, reader: ByteIO): self.reader = reader self.objectInfo = None self.type = None self.qualifier = None self.objects = None
def initialize(self): self.flags = BitDict('Color')
def get_type(self): reader = ByteIO(byte_object=self.data) header = reader.read_fourcc() header2 = reader.read_fourcc() if header == 'RIFF': return 'WAV' elif header2 == 'AIFF': return 'AIFF' elif header == 'OggS': return 'OGG' else: # assume MOD return 'MOD' SOUND_FLAGS = BitDict('Wave', 'MIDI', None, None, 'LoadOnCall', 'PlayFromDisk', 'Loaded') class SoundItem(BaseSound): def __init__(self, reader): super().__init__(reader) self.compressed = not self.settings.get('debug', False) self.checksum = None self.references = None self.flags = SOUND_FLAGS.copy() def read(self): reader = self.reader start = reader.tell() self.handle = reader.read_uint32() self.checksum = reader.read_int32()
'Joystick 1', 'Joystick 2', 'Joystick 3', 'Joystick 4', 'Keyboard' ] HEADER_FLAGS = BitDict( 'BorderMax', 'NoHeading', 'Panic', 'SpeedIndependent', 'Stretch', 'MusicOn', # obsolete? 'SoundOn', # obsolete? 'MenuHidden', 'MenuBar', 'Maximize', # maximized at bootup? 'MultiSamples', 'FullscreenAtStart', 'FullscreenSwitch', 'Protected', # wonder... 'Copyright', 'OneFile' # ? ) HEADER_NEW_FLAGS = BitDict( 'SamplesOverFrames', 'RelocFiles', 'RunFrame', 'SamplesWhenNotFocused', 'NoMinimizeBox',