示例#1
0
class MetaTile(mrc.Block):
    top_left = mrc.BlockField(TileQuad, 0x00)
    top_right = mrc.BlockField(TileQuad, 0x02)
    bottom_left = mrc.BlockField(TileQuad, 0x04)
    bottom_right = mrc.BlockField(TileQuad, 0x06)

    @property
    def repr(self):
        return 'top_left: {}, top_right: {}, bottom_left: {}, bottom_right: {}'.format(
            self.top_left, self.top_right, self.bottom_left, self.bottom_right)
示例#2
0
class ResourceFork(mrc.Block):
    """
    """
    resourceDataOffset = mrc.UInt32_BE(0x00)
    resourceMapOffset = mrc.UInt32_BE(0x04)
    resourceDataSize = mrc.UInt32_BE(0x08)
    resourceMapSize = mrc.UInt32_BE(0x0c)
    resourceData = mrc.BlockField(ResourceData,
                                  offset=mrc.Ref("resourceDataOffset"),
                                  length=mrc.Ref("resourceDataSize"))
    resourceMap = mrc.BlockField(MapData,
                                 offset=mrc.Ref("resourceMapOffset"),
                                 length=mrc.Ref("resourceMapSize"))
示例#3
0
class PRSFile(mrc.Block):
    magic = mrc.Const(mrc.Bytes(0x00, length=0x18),
                      b'PRS Format Resource File')
    unk1 = mrc.UInt8(0x18)
    unk2 = mrc.UInt8(0x19)
    unk3 = mrc.UInt8(0x1f)
    chunks = mrc.BlockField(PRSChunk, 0x30, stream=True)
示例#4
0
class B800Screen(mrc.Block):
    B800_SCREEN_WIDTH = 80

    chars = mrc.BlockField(B800Char, 0x00, count=2000)

    @property
    def text(self):
        return '\n'.join([
            ''.join([
                c.char for c in self.chars[i * self.B800_SCREEN_WIDTH:]
                [:self.B800_SCREEN_WIDTH]
            ]) for i in range((len(self.chars) + 1) // self.B800_SCREEN_WIDTH)
        ])

    def ansi_format(self):
        result = []
        for i in range((len(self.chars) + 1) // self.B800_SCREEN_WIDTH):
            for c in self.chars[i *
                                self.B800_SCREEN_WIDTH:][:self.
                                                         B800_SCREEN_WIDTH]:
                result.append(c.ansi_format())
            result.append('\n')
        return ''.join(result)

    def print(self):
        print(self.ansi_format())

    def __str__(self):
        return self.ansi_format()

    def __repr__(self):
        return '<{}: {} chars, {}x{}>'.format(
            self.__class__.__name__, len(self.chars), self.B800_SCREEN_WIDTH,
            1 + (len(self.chars) - 1) // self.B800_SCREEN_WIDTH)
示例#5
0
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)
示例#6
0
class ChannelV4(mrc.Block):
    CHANNEL_MAP = {
        None:
        EmptyChannelV4,
        #        ChannelType.SPRITE: SpriteChannelV4,
        ChannelType.FRAME_SCRIPT:
        ScriptChannelV4,
        #        ChannelType.PALETTE: mrc.Unknown,
    }

    channel_size = mrc.UInt16_BE(0x00)
    channel_offset = mrc.UInt16_BE(0x02)

    @property
    def channel_row(self):
        return self.channel_offset // 0x14

    @property
    def channel_type(self):
        return self.channel_offset % 0x14

    @property
    def channel_type_wrap(self):
        return (ChannelType.PALETTE if self.channel_offset == 0x14 else
                self.channel_type) if self.channel_size else None

    data = mrc.BlockField(CHANNEL_MAP,
                          0x04,
                          block_type=mrc.Ref('channel_type_wrap'),
                          default_klass=mrc.Unknown,
                          length=mrc.Ref('channel_size'))

    @property
    def repr(self):
        return f'channel_size=0x{self.channel_size:02x}, channel_offset=0x{self.channel_offset:04x}, channel_row={self.channel_row}, channel_type={self.channel_type}'
示例#7
0
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'))
示例#8
0
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'))
示例#9
0
        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)
示例#10
0
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')
示例#11
0
class RIFX(mrc.Block):
    _endian = 'big'
    CHUNK_MAP_CLASS = RIFXMap

    magic = mrc.Const(mrc.UInt32_P(0x00), Tag(b'RIFX'))
    size = mrc.UInt32_P(0x04)
    map = mrc.BlockField(mrc.Ref('CHUNK_MAP_CLASS'),
                         0x08,
                         length=mrc.Ref('size'))
示例#12
0
class ShapeCastV4(mrc.Block):
    type = mrc.UInt16_BE(0x00, enum=ShapeType)
    rect = mrc.BlockField(Rect, 0x02)
    pattern = mrc.UInt16_BE(0x0a)
    fg_colour = mrc.UInt8(0x0c)
    bg_colour = mrc.UInt8(0x0d)
    fill_type = mrc.UInt8(0x0e)
    line_thickness = mrc.UInt8(0x0f)
    line_direction = mrc.UInt8(0x10)
示例#13
0
class FrameV4(mrc.Block):
    size = mrc.UInt16_BE(0x00)
    channels = mrc.BlockField(ChannelV4,
                              0x02,
                              stream=True,
                              length=mrc.Ref('size_channels'))

    @property
    def size_channels(self):
        return self.size - 0x02
示例#14
0
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)
示例#15
0
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)
示例#16
0
class GroundDAT(mrc.Block):
    """Represents a single graphical style."""

    _vgagr = None  # should be replaced by the correct VgagrDAT object

    #: Information for every type of interactive piece.
    interactive_info = mrc.BlockField(InteractiveInfo,
                                      0x0000,
                                      count=16,
                                      fill=b'\x00' * 28)
    #: Information for every type of terrain piece.
    terrain_info = mrc.BlockField(TerrainInfo,
                                  0x01c0,
                                  count=64,
                                  fill=b'\x00' * 8)

    #: Extended EGA palette used for rendering the level preview.
    palette_ega_preview = img.Palette(ibm_pc.EGAColour, 0x03c0, count=8)
    #: Copy of EGA palette used for rendering lemmings/action bar.
    #: Colours 0-6 are not used by the game, instead there is a palette embedded
    #: in the executable.
    #: Colour 7 is used for drawing the minimap and dirt particles.
    palette_ega_standard = img.Palette(ibm_pc.EGAColour, 0x03c8, count=8)
    #: EGA palette used for rendering interactive/terrain pieces.
    palette_ega_custom = img.Palette(ibm_pc.EGAColour, 0x03d0, count=8)
    #: VGA palette used for rendering interactive/terrain pieces.
    palette_vga_custom = img.Palette(ibm_pc.VGAColour, 0x03d8, count=8)
    #: Copy of VGA palette used for rendering lemmings/action bar.
    #: Colours 0-6 are not used by the game, instead there is a palette embedded
    #: in the executable.
    #: Colour 7 is used for drawing the minimap and dirt particles.
    palette_vga_standard = img.Palette(ibm_pc.VGAColour, 0x03f0, count=8)
    #: VGA palette used for rendering the level preview.
    palette_vga_preview = img.Palette(ibm_pc.VGAColour, 0x0408, count=8)

    @property
    def palette(self):
        if not hasattr(self, '_palette'):
            self._palette = [
                img.Transparent()
            ] + self.palette_vga_standard[1:] + self.palette_vga_custom
        return self._palette
示例#17
0
class SplashVGA(mrc.Block):
    palette = mrc.BlockField(ibm_pc.VGAColour, 0x0000, count=256)
    image_data = mrc.Bytes(0x0300)

    def __init__(self, *args, **kwargs):
        mrc.Block.__init__(self, *args, **kwargs)
        self.image = img.IndexedImage(self,
                                      width=320,
                                      height=200,
                                      palette=mrc.Ref('palette'),
                                      source=mrc.Ref('image_data'))
示例#18
0
class ResourceInfo(mrc.Block):
    int_id = mrc.Bits16(0x00, 0b1000000000000000, endian='little')
    type_id = mrc.Bits16(0x00, 0b0111111111111111, endian='little')
    count = mrc.UInt16_LE(0x02)
    reserved = mrc.Bytes(0x04, length=0x04)
    resources = mrc.BlockField(Resource, 0x08, count=mrc.Ref('count'))

    @property
    def repr(self):
        return 'type_id={}, int_id={}, count={}'.format(
            self.type_id, self.int_id, self.count)
示例#19
0
class ResourceTable(mrc.Block):
    align_shift = mrc.UInt16_LE(0x00)
    resourceinfo = mrc.BlockField(ResourceInfo,
                                  0x02,
                                  stream=True,
                                  stream_end=b'\x00\x00')

    #name_data =     mrc.Bytes( mrc.EndOffset( 'resourceinfo' ), length=0x107 )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
示例#20
0
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)
示例#21
0
class SoundCastV4(mrc.Block):
    unk1 = mrc.Bytes(0x00, length=0x20)
    extra_size = mrc.UInt8(0x20)
    extra = mrc.BlockField(SoundCastV4Extra,
                           0x21,
                           stream=True,
                           length=mrc.Ref('extra_size'))

    @property
    def repr(self):
        extra_str = f', name={self.extra[0].name}' if self.extra else ''
        return f'unk1={self.unk1}{extra_str}'
示例#22
0
class ScriptContextV4(mrc.Block):
    #test = mrc.Bytes()
    unk1 = mrc.Bytes(0x00, length=0x8)
    list_count = mrc.UInt32_BE(0x08)
    list_count_2 = mrc.UInt32_BE(0x0c)
    list_offset = mrc.UInt16_BE(0x10)
    unk2 = mrc.UInt16_BE(0x12)
    unk3 = mrc.Bytes(0x14, length=22)

    entries = mrc.BlockField(ScriptContextEntry,
                             mrc.Ref('list_offset'),
                             count=mrc.Ref('list_count'))
示例#23
0
class SoundCastV4(mrc.Block):
    unk1 = mrc.Bytes(0x00, length=0x20)
    extra_size = mrc.UInt8(0x20)
    extra = mrc.BlockField(SoundCastV4Extra,
                           0x21,
                           stream=True,
                           length=mrc.Ref('extra_size'))

    @property
    def repr(self):
        return 'unk1={}{}'.format(
            self.unk1,
            ', name={}'.format(self.extra[0].name) if self.extra else '')
示例#24
0
class VgagrDAT(mrc.Block):
    stores = mrc.BlockField(VgagrStore,
                            0x0000,
                            stream=True,
                            transform=DATCompressor())

    @property
    def terrain_store(self):
        return self.stores[0]

    @property
    def interact_store(self):
        return self.stores[1]
示例#25
0
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'))
示例#26
0
class IPS(mrc.Block):
    magic = mrc.Const(mrc.Bytes(0x00, length=5), b'PATCH')
    records = mrc.BlockField(IPSRecord, 0x05, stream=True, stream_end=b'EOF')

    @property
    def repr(self):
        return f'records: {len( self.records )}'

    def create(self, source, target):
        pass

    def patch(self, source):
        return source
示例#27
0
class ScriptConstantV5(mrc.Block):
    SCRIPT_CONSTANT_TYPES = {
        0x0001: ScriptConstantString,
        0x0004: ScriptConstantUInt32,
        0x0009: ScriptConstantFloat
    }

    const_type = mrc.UInt32_BE(0x00, enum=ScriptConstantType)
    const = mrc.BlockField(SCRIPT_CONSTANT_TYPES,
                           0x04,
                           block_type=mrc.Ref('const_type'))

    @property
    def repr(self):
        return '{}: {}'.format(self.const_type, self.const.repr)
示例#28
0
class NEHeader(NEBase):
    linker_ver = mrc.UInt8(0x02)
    linker_rev = mrc.UInt8(0x03)

    entry_size = mrc.UInt16_LE(0x06)
    crc = mrc.UInt32_LE(0x08)

    ds_id = mrc.UInt16_LE(0x0e)

    resource_count = mrc.UInt16_LE(0x34)

    segtable = mrc.BlockField(SegmentHeader,
                              mrc.Ref('segtable_offset'),
                              count=mrc.Ref('segtable_count'))
    restable = mrc.BlockField(ResourceTable, mrc.Ref('restable_offset'))
    resnametable = mrc.BlockField(ResidentNameTable,
                                  mrc.Ref('resnames_offset'))
    modreftable = mrc.BlockField(ModuleReference,
                                 mrc.Ref('modref_offset'),
                                 count=mrc.Ref('modref_count'))
    impnamedata = mrc.Bytes(mrc.Ref('impnames_offset'),
                            length=mrc.Ref('impnames_size'))
    #entrydata =     mrc.BlockField( EntryBundle, mrc.Ref( 'entry_offset' ), stream=True, length=mrc.Ref( 'entry_size' ) )
    entrydata = mrc.Bytes(mrc.Ref('entry_offset'),
                          length=mrc.Ref('entry_size'))
    nonresnametable = mrc.BlockField(ResidentNameTable,
                                     mrc.Ref('nonresnames_offset'))

    @property
    def nonresnames_offset(self):
        return self.nonresnames_rel_offset - (self._parent.ne_offset
                                              if self._parent else 0)

    def __init__(self, *args, **kwargs):
        self.impnamestore = mrc.Store(self, mrc.Ref('impnamedata'))
        super().__init__(*args, **kwargs)
示例#29
0
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}'
示例#30
0
class ScriptConstantV4(mrc.Block):
    SCRIPT_CONSTANT_TYPES = {
        0x0001: ScriptConstantString,
        0x0004: ScriptConstantUInt32,
        0x0009: ScriptConstantFloat
    }

    const_type = mrc.UInt16_BE(0x00, enum=ScriptConstantType)
    const = mrc.BlockField(SCRIPT_CONSTANT_TYPES,
                           0x02,
                           block_type=mrc.Ref('const_type'))

    @property
    def repr(self):
        return f'{self.const_type}: {self.const.repr}'