class SpeakAndSpellROM( mrc.Block ): count_a = mrc.UInt8( 0x00 ) count_b = mrc.UInt8( 0x01 ) count_c = mrc.UInt8( 0x02 ) count_d = mrc.UInt8( 0x03 ) offset_a = mrc.Pointer( mrc.UInt16_LE( 0x04 ), mrc.EndOffset( 'common' ) ) offset_b = mrc.Pointer( mrc.UInt16_LE( 0x06 ), mrc.EndOffset( 'list_a' ) ) offset_c = mrc.Pointer( mrc.UInt16_LE( 0x08 ), mrc.EndOffset( 'list_b' ) ) offset_d = mrc.Pointer( mrc.UInt16_LE( 0x0a ), mrc.EndOffset( 'list_c' ) ) @property def common_len( self ): return (self.offset_a - 0x0c) // 2 @common_len.setter def common_len( self, value ): self.offset_a = value * 2 + 0x0c common = mrc.UInt16_LE( 0x0c, count=mrc.Ref( 'common_len' ) ) list_a = mrc.UInt16_LE( mrc.Ref( 'offset_a' ), count=mrc.Ref( 'count_a' ) ) list_b = mrc.UInt16_LE( mrc.Ref( 'offset_b' ), count=mrc.Ref( 'count_b' ) ) list_c = mrc.UInt16_LE( mrc.Ref( 'offset_c' ), count=mrc.Ref( 'count_c' ) ) list_d = mrc.UInt16_LE( mrc.Ref( 'offset_d' ), count=mrc.Ref( 'count_d' ) ) raw_data = mrc.Bytes( mrc.EndOffset( 'list_d' ) )
class ResidentNameTable(mrc.Block): module_name_size = mrc.UInt8(0x00) module_name = mrc.Bytes(0x01, length=mrc.Ref('module_name_size')) padding = mrc.UInt16_LE(mrc.EndOffset('module_name')) resnames = mrc.BlockField(ResidentName, mrc.EndOffset('padding'), stream=True, stream_end=b'\x00')
class UPS(mrc.Block): STOP_CHECK = lambda buffer, pointer: pointer >= len(buffer) - 12 magic = mrc.Const(mrc.Bytes(0x00, length=4), b'UPS1') input_size = UIntVLV(0x04) output_size = UIntVLV(mrc.EndOffset('input_size')) blocks = mrc.BlockField(UPSBlock, mrc.EndOffset('output_size'), stream=True, stop_check=STOP_CHECK) input_crc32 = mrc.UInt32_LE(mrc.EndOffset('blocks')) output_crc32 = mrc.UInt32_LE(mrc.EndOffset('input_crc32')) patch_crc32 = mrc.UInt32_LE(mrc.EndOffset('output_crc32'))
class VGM150(mrc.Block): magic = mrc.Const(mrc.Bytes(0x00, length=0x04, default=b'Vgm '), b'Vgm ') eof_offset = mrc.UInt32_LE(0x04) version = mrc.UInt32_LE(0x08) sn76489_clock = mrc.UInt32_LE(0x0c) ym2413_clock = mrc.UInt32_LE(0x10) gd3_offset = mrc.UInt32_LE(0x14) total_sample_count = mrc.UInt32_LE(0x18) loop_offset = mrc.UInt32_LE(0x1c) loop_sample_count = mrc.UInt32_LE(0x20) rate = mrc.UInt32_LE(0x24) sn76489_feedback = mrc.UInt16_LE(0x28) sn76489_shiftwidth = mrc.UInt8(0x2a) sn76489_flags = mrc.UInt8(0x2b) ym2612_clock = mrc.UInt32_LE(0x2c) ym2151_clock = mrc.UInt32_LE(0x30) vgm_data_offset_raw = mrc.UInt32_LE(0x34) header_extra = mrc.Bytes(0x38, length=0x08, default=b'\x00' * 8) @property def vgm_data_offset(self): if self.version >= 0x150: return self.vgm_data_offset_raw + 0x34 return 0x40 vgm_data = mrc.ChunkField(COMMAND_MAP, mrc.Ref('vgm_data_offset'), id_field=mrc.UInt8, id_enum=Command, default_klass=mrc.Unknown, stream_end=b'\x66') extra = mrc.Bytes(mrc.EndOffset('vgm_data'), default=b'')
class KeyV4(mrc.Block): unk1 = mrc.UInt16_P(0x00) unk2 = mrc.UInt16_P(0x02) unk3 = mrc.UInt32_P(0x04) entry_count = mrc.UInt32_P(0x08) entries = mrc.BlockField(KeyEntry, 0x0c, count=mrc.Ref('entry_count')) garbage = mrc.Bytes(mrc.EndOffset('entries'))
class ScriptCastV4(mrc.Block): unk1 = mrc.Bytes(0x00, length=0x14) script_id = mrc.UInt16_BE(0x14) var_count = mrc.UInt16_BE(0x16) unk2 = mrc.UInt32_BE(0x18) vars = mrc.UInt32_BE(0x1c, count=mrc.Ref('var_count')) code = mrc.Bytes(mrc.EndOffset('vars'), length=mrc.Ref('code_len')) unk3 = mrc.Bytes(mrc.EndOffset('code')) @property def code_len(self): return self.vars[0] if self.vars else 0 @property def repr(self): return 'script_id={}'.format(self.script_id)
class Segment(mrc.Block): RELOCATION_TYPES = {1: RelocationTable, 0: NullRelocationTable} data = mrc.Bytes(0x00, length=mrc.Ref('_parent.size')) relocations = mrc.BlockField(RELOCATION_TYPES, mrc.EndOffset('data'), block_type=mrc.Ref('_parent.relocations'))
class ScriptV4(mrc.Block): unk1 = mrc.Bytes(0x00, length=0x10) code_store_offset = mrc.UInt16_BE(0x10) unk2 = mrc.Bytes(0x12, length=0x2e) functions_offset = mrc.UInt16_BE(0x40) unk3 = mrc.Bytes(0x42, length=6) functions_count = mrc.UInt16_BE(0x48) unk4 = mrc.UInt16_BE(0x4a) unk5 = mrc.UInt16_BE(0x4c) consts_count = mrc.UInt16_BE(0x4e) consts_offset = mrc.UInt16_BE(0x52) consts_unk = mrc.UInt16_BE(0x56) consts_base = mrc.UInt16_BE(0x5a) #unk6 = mrc.Bytes( 0x5c, length=0xc ) @property def code_store_size(self): return self.functions_offset - self.code_store_offset @code_store_size.setter def code_store_size(self, value): self.functions_offset = value + self.code_store_offset @property def code_store_base(self): return -self.code_store_offset code_store_raw = mrc.Bytes(mrc.Ref('code_store_offset'), length=mrc.Ref('code_store_size')) functions = mrc.BlockField(ScriptFunction, mrc.Ref('functions_offset'), count=mrc.Ref('functions_count')) consts = mrc.BlockField(ScriptConstant, mrc.Ref('consts_offset'), count=mrc.Ref('consts_count')) consts_raw = mrc.Bytes(mrc.EndOffset('consts')) @property def consts_store_offset(self): return self.consts_base - self.get_field_end_offset('consts') #test = mrc.Bytes( 0x00 ) def __init__(self, *args, **kwargs): self.consts_store = mrc.Store( self, mrc.Ref('consts_raw'), base_offset=mrc.Ref('consts_store_offset')) self.code_store = mrc.Store(self, mrc.Ref('code_store_raw'), base_offset=mrc.Ref('code_store_base')) super().__init__(*args, **kwargs)
class EXE(mrc.Block): dos_magic = mrc.Const(mrc.Bytes(0x00, length=2), b'MZ') dos_header = mrc.Bytes(0x02, length=0x3a) ne_offset = mrc.UInt16_LE(0x3c) dos_stub = mrc.Bytes(0x3e, length=mrc.Ref('dos_stub_length')) ne_header = mrc.BlockField(NEHeader, mrc.Ref('ne_offset')) segdata = mrc.Bytes( mrc.EndOffset('ne_header', align=mrc.Ref('sector_align'))) @property def sector_align(self): if self.ne_header: return 1 << self.ne_header.sector_shift return 32 @property def dos_stub_length(self): return self.ne_offset - 0x3e def __init__(self, *args, **kwargs): self.segdatastore = mrc.Store(self, mrc.Ref('segdata'), base_offset=mrc.EndOffset( 'ne_header', neg=True, align=mrc.Ref('sector_align')), align=mrc.Ref('sector_align')) super().__init__(*args, **kwargs)
class MacBinary(mrc.Block): version_old = mrc.Const(mrc.UInt8(0x00), 0) name_size = mrc.UInt8(0x01, range=range(1, 64)) name = mrc.Bytes(0x02, length=mrc.Ref('name_size')) type = mrc.Bytes(0x41, length=4) creator = mrc.Bytes(0x45, length=4) locked = mrc.Bits(0x49, 0b10000000) invisible = mrc.Bits(0x49, 0b01000000) bundle = mrc.Bits(0x49, 0b00100000) system = mrc.Bits(0x49, 0b00010000) bozo = mrc.Bits(0x49, 0b00001000) busy = mrc.Bits(0x49, 0b00000100) changed = mrc.Bits(0x49, 0b00000010) inited = mrc.Bits(0x49, 0b00000001) const1 = mrc.Const(mrc.UInt8(0x4a), 0) pos_y = mrc.UInt16_BE(0x4b) pos_x = mrc.UInt16_BE(0x4d) folder_id = mrc.UInt16_BE(0x4f) protected = mrc.Bits(0x51, 0b00000001) const2 = mrc.Const(mrc.UInt8(0x52), 0) data_size = mrc.UInt32_BE(0x53) resource_size = mrc.UInt32_BE(0x57) created = mrc.UInt32_BE(0x5a) modified = mrc.UInt32_BE(0x5e) data = mrc.Bytes(0x80, length=mrc.Ref('data_size')) resource = mrc.Bytes(mrc.EndOffset('data', align=0x80), length=mrc.Ref('resource_size'))
class UPSBlock(mrc.Block): rel_offset = UIntVLV(0x00) xor_data = XORData(mrc.EndOffset('rel_offset')) @property def repr(self): return f'rel_offset: 0x{self.rel_offset:x}, size: {len( self.xor_data )}'
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = mrc.LinearStore(parent=self, source=mrc.Ref('data_raw'), block_klass=mrc.Unknown, offsets=mrc.Ref('offsets'), base_offset=mrc.EndOffset('offsets', neg=True))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.songs = mrc.LinearStore(parent=self, source=mrc.Ref('songs_raw'), block_klass=Song, offsets=mrc.Ref('song_offsets'), base_offset=mrc.EndOffset('song_offsets', neg=True))
class Test(mrc.Block): data = mrc.ChunkField(CHUNK_MAP, 0x00, stream_end=b'\xff', id_field=mrc.UInt8, length_field=mrc.UInt8, fill=b'\x00') bonus = mrc.Bytes(mrc.EndOffset('data'))
class Test(mrc.Block): count = mrc.UInt8(0x00) elements = mrc.BlockField(ElementRef, count=mrc.Ref('count')) raw_data = mrc.Bytes(mrc.EndOffset('elements')) def __init__(self, *args, **kwargs): self.store = mrc.Store(self, mrc.Ref('raw_data')) super().__init__(*args, **kwargs)
class ResidentName(mrc.Block): size = mrc.UInt8(0x00) name = mrc.Bytes(0x01, length=mrc.Ref('size')) index = mrc.UInt16_LE(mrc.EndOffset('name')) @property def repr(self): return 'index=0x{:02x}, name={}'.format(self.index, self.name)
def __init__(self, *args, **kwargs): self.segdatastore = mrc.Store(self, mrc.Ref('segdata'), base_offset=mrc.EndOffset( 'ne_header', neg=True, align=mrc.Ref('sector_align')), align=mrc.Ref('sector_align')) super().__init__(*args, **kwargs)
class MUSFile(mrc.Block): count = mrc.UInt32_LE(0x00) entries = mrc.BlockField(MusicEntry, 0x04, count=mrc.Ref('count')) music_raw = mrc.Bytes(mrc.EndOffset('entries')) def __init__(self, *args, **kwargs): self.tracks = mrc.Store(parent=self, source=mrc.Ref('music_raw'), base_offset=mrc.EndOffset('entries', neg=True)) super().__init__(*args, **kwargs)
class IMGFile(mrc.Block): count = mrc.UInt32_LE(0x00) entries = mrc.BlockField(ImageEntry, 0x04, count=mrc.Ref('count')) images_raw = mrc.Bytes(mrc.EndOffset('entries')) def __init__(self, *args, **kwargs): self.images = mrc.Store(parent=self, source=mrc.Ref('images_raw'), base_offset=mrc.EndOffset('entries', neg=True)) super().__init__(*args, **kwargs)
class Test( mrc.Block ): count = mrc.UInt8( 0x00 ) offsets = mrc.UInt16_LE( 0x01, count=mrc.Ref( 'count' ) ) raw_data = mrc.Bytes( mrc.EndOffset( 'offsets' ) ) def __init__( self, *args, **kwargs ): self.elements = mrc.LinearStore( self, mrc.Ref( 'raw_data' ), Element, offsets=mrc.Ref( 'offsets' ) ) super().__init__( *args, **kwargs )
class Song(mrc.Block): mode = mrc.UInt8(0x0000) speed = mrc.UInt16_LE(0x0001) tempo = mrc.UInt8(0x0003) pattlen = mrc.UInt8(0x0004) chandelay = mrc.UInt8(0x0005, count=9) regbd = mrc.UInt8(0x000e) patch_count = mrc.UInt16_LE(0x000f) patches = mrc.BlockField(SongPatch, 0x0011, count=mrc.Ref('patch_count')) position_count = mrc.UInt16_LE(mrc.EndOffset('patches')) positions = mrc.BlockField(SongPosition, mrc.EndOffset('position_count'), count=mrc.Ref('position_count')) num_digital = mrc.UInt16_LE(mrc.EndOffset('positions')) patterns = mrc.BlockField(SongPattern, mrc.EndOffset('num_digital'), stream=True)
class MUSFile(mrc.Block): song_count = mrc.UInt16_LE(0x00) song_offsets = mrc.UInt32_LE(0x02, count=mrc.Ref('song_count')) songs_raw = mrc.Bytes(mrc.EndOffset('song_offsets')) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.songs = mrc.LinearStore(parent=self, source=mrc.Ref('songs_raw'), block_klass=Song, offsets=mrc.Ref('song_offsets'), base_offset=mrc.EndOffset('song_offsets', neg=True))
class MMapV4(mrc.Block): unk1 = mrc.Bytes(0x00, length=8) entries_max = mrc.UInt32_P(0x04) entries_used = mrc.UInt32_P(0x08) unk2 = mrc.Const(mrc.Bytes(0x0c, length=8), b'\xff' * 8) unk3 = mrc.UInt32_P(0x14) entries = mrc.BlockField(MMapEntry, 0x18, count=mrc.Ref('entries_max'), fill=b'\xaa' * 0x14) garbage = mrc.Bytes(mrc.EndOffset('entries')) @property def repr(self): return f'entries_max: {self.entries_max}, entries_used: {self.entries_used}'
class Resource(mrc.Block): files = mrc.BlockField(FileLookup, 0x00, stride=0x08, stream=True, stop_check=resource_stop_check, fill=b'\xff\xff\xff\xff\x00\x00\x00\x00') files_raw = mrc.Bytes(mrc.EndOffset('files')) def __init__(self, *args, **kwargs): self.files_store = mrc.Store(parent=self, source=mrc.Ref('files_raw'), base_offset=mrc.EndOffset('files', neg=True)) super().__init__(*args, **kwargs)
class Data(mrc.Block): count = mrc.UInt32_LE(0x00) offsets = mrc.UInt32_LE(0x04, bitmask=b'\xff\xff\xff\x3f', count=mrc.Ref('count')) data_raw = mrc.Bytes(mrc.EndOffset('offsets')) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = mrc.LinearStore(parent=self, source=mrc.Ref('data_raw'), block_klass=mrc.Unknown, offsets=mrc.Ref('offsets'), base_offset=mrc.EndOffset('offsets', neg=True))
class ModuleTable(mrc.Block): ne_header = mrc.BlockField(NEModule, 0x00) segdata = mrc.Bytes( mrc.EndOffset('ne_header', align=mrc.Ref('sector_align'))) @property def sector_align(self): if self.ne_header: return 1 << self.ne_header.sector_shift return 32 def __init__(self, *args, **kwargs): self.segdatastore = mrc.Store(self, mrc.Ref('segdata'), base_offset=mrc.EndOffset( 'ne_header', neg=True, align=mrc.Ref('sector_align')), align=mrc.Ref('sector_align')) super().__init__(*args, **kwargs)
class CastV4(mrc.Block): CAST_MAP = { CastType.BITMAP: BitmapCastV4, #CastType.SOUND: SoundCastV4, CastType.SCRIPT: ScriptCastV4, CastType.SHAPE: ShapeCastV4, } size1 = mrc.UInt16_BE(0x00) size2 = mrc.UInt32_BE(0x02) cast_type = mrc.UInt8(0x06, enum=CastType) unk1 = mrc.UInt8(0x07) detail = mrc.BlockField(CAST_MAP, 0x08, block_type=mrc.Ref('cast_type'), default_klass=mrc.Unknown) garbage = mrc.Bytes(mrc.EndOffset('detail')) @property def repr(self): return f'size1: {self.size1}, size2: {self.size2}, cast_type: {self.cast_type}'
class ScoreV4(mrc.Block): size = mrc.UInt32_BE(0x00) unk1 = mrc.UInt32_BE(0x04) unk2 = mrc.UInt32_BE(0x08) unk3 = mrc.UInt16_BE(0x0c) unk4 = mrc.UInt16_BE(0x0e) unk5 = mrc.UInt16_BE(0x10) unk6 = mrc.UInt16_BE(0x12) frames = mrc.BlockField(FrameV4, 0x14, stream=True, length=mrc.Ref('size_frames')) extra = mrc.Bytes(mrc.EndOffset('frames')) @property def size_frames(self): return self.size - 0x14 @property def repr(self): return 'num_frames={}'.format(len(self.frames))
class TextV4(mrc.Block): unk1 = mrc.UInt32_BE(0x00) length = mrc.UInt32_BE(0x04) unk2 = mrc.UInt32_BE(0x08) data = mrc.Bytes(0xc, length=mrc.Ref('length')) unk3 = mrc.Bytes(mrc.EndOffset('data'))
class ScriptV4(mrc.Block): unk1 = mrc.Bytes(0x00, length=0x10) code_store_offset = mrc.UInt16_BE(0x10) unk2 = mrc.Bytes(0x12, length=0x1c) cast_id = mrc.UInt16_BE(0x2e) factory_name_id = mrc.Int16_BE(0x30) unk9 = mrc.Bytes(0x32, length=0xe) globals_offset = mrc.UInt16_BE(0x40) globals_count = mrc.UInt16_BE(0x42) unk3 = mrc.Bytes(0x44, length=4) functions_count = mrc.UInt16_BE(0x48) unk4 = mrc.UInt16_BE(0x4a) functions_offset = mrc.UInt16_BE(0x4c) consts_count = mrc.UInt16_BE(0x4e) unk6 = mrc.UInt16_BE(0x50) consts_offset = mrc.UInt16_BE(0x52) unk7 = mrc.UInt16_BE(0x54) consts_unk = mrc.UInt16_BE(0x56) unk8 = mrc.UInt16_BE(0x58) consts_base = mrc.UInt16_BE(0x5a) @property def code_store_size(self): return self.functions_offset - self.code_store_offset @code_store_size.setter def code_store_size(self, value): self.functions_offset = value + self.code_store_offset @property def code_store_base(self): return -self.code_store_offset code_store_raw = mrc.Bytes(mrc.Ref('code_store_offset'), length=mrc.Ref('code_store_size')) globals = mrc.BlockField(ScriptGlobal, mrc.Ref('globals_offset'), count=mrc.Ref('globals_count')) functions = mrc.BlockField(ScriptFunction, mrc.Ref('functions_offset'), count=mrc.Ref('functions_count')) consts = mrc.BlockField(ScriptConstantV4, mrc.Ref('consts_offset'), count=mrc.Ref('consts_count')) consts_raw = mrc.Bytes(mrc.EndOffset('consts')) @property def consts_store_offset(self): return self.consts_base - self.get_field_end_offset('consts') #test = mrc.Bytes( 0x00 ) def __init__(self, *args, **kwargs): self.consts_store = mrc.Store( self, mrc.Ref('consts_raw'), base_offset=mrc.Ref('consts_store_offset')) self.code_store = mrc.Store(self, mrc.Ref('code_store_raw'), base_offset=mrc.Ref('code_store_base')) super().__init__(*args, **kwargs)