示例#1
0
def __get_struct(is_wiiu: bool) -> Struct:
    if is_wiiu:
        content_hash = 'sha1' / Padded(0x20, ChecksumRaw(hashlib.sha1))
        app_type = ['app_type' / Hex(Bytes(4)), '_unk2' / Bytes(0x3a)]
    else:
        content_hash = 'sha256' / ChecksumRaw(hashlib.sha256)
        app_type = ['_unk2' / Bytes(0x3e)]

    return InliningStruct(
        'signature' / common.signature,
        '__raw_header_signed__' @ AttributeRawCopy(
            InlineStruct(
                'issuer' / PaddedString(0x40, 'ascii'),
                'format_version' / Byte, 'ca_crl_version' / Byte,
                'signer_crl_version' / Byte, '_unk1' / Bytes(1),
                'system_version' / Hex(Bytes(8)), 'title_id' / common.TitleID,
                'title_type' / Hex(Bytes(4)), 'group_id' / Hex(Bytes(2)), *
                app_type, 'access_rights' / Hex(Bytes(4)),
                'title_version' / Int16ub, 'content_count' / Int16ub,
                'boot_index' / Int16ub, Padding(2), 'content_info_sha256' /
                ChecksumValue(hashlib.sha256, this._.content_info))),
        'content_info' / ChecksumSourceData(
            Array(
                64,
                Struct(
                    'content_index' / Int16ub, 'content_count' / Int16ub,
                    'contents_sha256' / IfThenElse(
                        this.content_count > 0,
                        ChecksumValue(
                            hashlib.sha256, lambda this: this._.
                            contents[this.content_index:this.content_index +
                                     this.content_count], True),
                        ChecksumRaw(hashlib.sha256))))),
        'contents' / Array(
            this.content_count,
            ChecksumSourceData(
                Struct(
                    'id' / Hex(Int32ub),
                    'index' / Int16ub,
                    # 0x2000: always set (?)
                    # 0x4000: appears in DLC TMDs ("optional"?)
                    # 0x8000: "shared"?
                    'type' / FlagsEnum(Int16ub,
                                       encrypted=0x0001,
                                       hashed=0x0002,
                                       cfm=0x0004,
                                       unk1=0x2000,
                                       unk2=0x4000,
                                       unk3=0x8000),
                    'size' / Int64ub,
                    content_hash))),
        'certificates' / common.certificates,
        VerifyOrWriteChecksums,
        Terminated)
示例#2
0
def getrequest(reqtype):
    payload = None

    if reqtype == "SetOnOff":
        payload = OnOff
    elif reqtype == "SetBrightness":
        payload = Brightness

    return "msg" / Padded(
        18,
        Struct(Const(0x43, Int8ub), "type" / RequestType,
               "payload" / Embedded(payload)))
示例#3
0
def _gen_fmh3_struct(int_type, pointer_type, codepoint_type, addr_mode='rel'):
    return Struct(
        "pointer_offset" / (Computed(0) if addr_mode == 'abs' else Tell),
        "signature" / Const(b'FMH3'),
        Padding(4),
        "fonts_count" / Padded(pointer_type.sizeof(), int_type),
        "fonts_pointers_offset" / pointer_type,
        "fonts" / Pointer(
            lambda this: this.fonts_pointers_offset + this.pointer_offset,
            RepeatUntil(
                lambda obj, lst, ctx: ctx._index >= ctx.fonts_count - 1,
                Struct(
                    "pointer" / pointer_type,
                    "data" / Pointer(
                        lambda this: this.pointer + this._.pointer_offset,
                        Struct(
                            "id" / int_type,
                            "advance_width" / Byte,
                            "line_height" / Byte,
                            "box_width" / Byte,
                            "box_height" / Byte,
                            "layout_param_1" / Byte,
                            "layout_param_2_numerator" / Byte,
                            "layout_param_2_denominator" / Byte,
                            Padding(1),
                            "other_params?" / int_type,
                            "tex_size_chars" / int_type,
                            "chars_count" / int_type,
                            "chars_pointer" / pointer_type,
                            "chars" / Pointer(
                                lambda this: this.chars_pointer + this._._.
                                pointer_offset,
                                RepeatUntil(
                                    lambda obj, lst, ctx: ctx._index >= ctx.
                                    chars_count - 1,
                                    Struct(
                                        "codepoint" / codepoint_type,
                                        "halfwidth" / Flag,
                                        Padding(1),
                                        "tex_col" / Byte,
                                        "tex_row" / Byte,
                                        "glyph_x" / Byte,
                                        "glyph_width" / Byte,
                                    ))),
                        )),
                ))),
    )
示例#4
0
def __get_struct(is_wiiu: bool) -> Struct:
    if is_wiiu:
        swap = lambda x: x  # noop  # noqa: E731
        encoding = 'utf-16-be'
        # tga file
        icon_struct = Struct('128' / Bytes(0x2c + 128 * 128 * 4))
        icon_struct = 'icons_tga' / Padded(icon_struct.sizeof() + 4,
                                           icon_struct)
        region_all = 0xffffffff
    else:
        swap = ByteSwapped
        encoding = 'utf-16-le'
        # raw RGB565
        icon_struct = 'icons_raw' / Struct('24' / Bytes(24 * 24 * 2),
                                           '48' / Bytes(48 * 48 * 2))
        region_all = 0x7fffffff

    return InliningStruct(
        'checksum' / ChecksumValue(hashlib.sha256, this),
        ChecksumSourceData(
            InlineStruct(
                'title_id' / swap(common.TitleID), 'version' / swap(Int32ub),
                '_unk1' / Bytes(4), 'regions' / swap(
                    FlagsEnum(Int32ub,
                              JP=1 << 0,
                              US=1 << 1,
                              EU=1 << 2,
                              AU=1 << 3,
                              CN=1 << 4,
                              KO=1 << 5,
                              TW=1 << 6,
                              ALL=region_all)), '_unk2' / Bytes(0x1c),
                'title_info' / DictZipAdapter(
                    languages,
                    Array(
                        16,
                        Struct('short_name' / PaddedString(0x80, encoding),
                               'long_name' / PaddedString(0x100, encoding),
                               'publisher' / PaddedString(0x80, encoding)))),
                icon_struct)), VerifyOrWriteChecksums, Terminated)
示例#5
0
    stype_ip=0x32,
    stype_status=0x36,
    stype_change=0x29,
    stype_status_mixer=0x00  # djm 900 nxs sends this stype on type_status
)

DeviceType = Enum(Int8ub, djm=1, cdj=2, rekordbox=3)

PlayerNumberAssignment = Enum(Int8ub, auto=1, manual=2)

# received on udp port 50000
KeepAlivePacket = Struct(
    "magic" / Const(b'Qspt1WmJOL', String(10)),
    "type" / KeepAlivePacketType,  # pairs with subtype
    Padding(1),
    "model" / Padded(20, CString(encoding="ascii")),
    "u1" / Const(1, Int8ub),
    "device_type" / Default(DeviceType, "cdj"),
    Padding(1),
    "subtype" / KeepAlivePacketSubtype,
    Embedded(
        Switch(
            this.type,
            {
                # type=0x0a, request for other players to propose a player number?
                "type_hello":
                Struct("u2" /
                       Default(Int8ub, 1)),  # cdjs send 1, djm900nxs sends 3
                # type=0x04, publishing a proposed player number, check if anyone else has it? iteration goes 1..2..3
                "type_number":
                Struct("proposed_player_number" / Int8ub,
示例#6
0
vridge_control.send(
    '{"RequestedEndpointName":"HeadTracking","ProtocolVersion":1,"Code":1}')
newconnection = json.loads(vridge_control.recv())
#vridge_control.close() # Close socket

# Connect to new socket (timeout is normally 15 seconds)
endpoint_address = newconnection['EndpointAddress']
endpoint = context.socket(zmq.REQ)
endpoint.connect(endpoint_address)
# Connect to the endpoint channel (setting up debug class)
vridge_endpoint = debug(endpoint)

# Specify the structure for the fancy position matrix
structure = Struct(
    Const(Int32ul, 2),
    Const(Int32ul, 3),
    Const(Int32ul, 24),
    "data" / Padded(64, Array(6, Float32l)),
)

while True:
    for i in range(100):
        position = [0.0, 0.0, pi, 0.0, 1.0 + (i * 0.04), 0.0]
        byte_packet = structure.build(dict(data=position))
        endpoint.send(byte_packet)
        print("Send: " + str(structure.parse(byte_packet)))
        #print("Recieved: " + str(structure.parse(endpoint.recv())))
        endpoint.recv()

        time.sleep(0.1)
示例#7
0
    'jetsam_coalition_snapshot',
    kcdata_types_enum.STACKSHOT_KCTYPE_DONATING_PIDS: 'donating_pids',
    kcdata_types_enum.STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL:
    'dispatch_queue_label',
    kcdata_types_enum.KCDATA_BUFFER_BEGIN_STACKSHOT: 'kcdata_stackshot',
    kcdata_types_enum.STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS:
    'stackshot_fault_stats',
    kcdata_types_enum.STACKSHOT_KCTYPE_STACKSHOT_DURATION:
    'stackshot_duration',
}

predefined_name_substruct = 'name' / Computed(
    lambda ctx: predefined_names[ctx._.type])

uint32_desc = Struct(
    'name' / Padded(32, CString('utf8')),
    'obj' / Int32ul,
)

uint64_desc = Struct(
    'name' / Padded(32, CString('utf8')),
    'obj' / Int64ul,
)

jetsam_level = Struct(predefined_name_substruct, 'obj' / Int32ul)
thread_policy_version = Struct(predefined_name_substruct, 'obj' / Int32ul)
kernel_page_size = Struct(predefined_name_substruct, 'obj' / Int32ul)
osversion = Struct(predefined_name_substruct, 'obj' / CString('utf8'))
boot_args = Struct(predefined_name_substruct, 'obj' / CString('utf8'))
mach_timebase_info = Struct(
    predefined_name_substruct, 'obj' / Struct(
示例#8
0
#      Flag,
#      Padding(31),
#  )))

# Register: 0x10
IHOLD_IRUN = BitStruct(
    Padding(12),
    "IHOLDDELAY" / BitsInteger(4),
    Padding(3),
    "IRUN" / BitsInteger(5),
    Padding(3),
    "IHOLD" / BitsInteger(5),
)

# Register: 0x11
TPOWERDOWN = ByteSwapped(Padded(4, Int8ul))

# Register: 0x13
# TODO should be 20-bit-integer
TPWMTHRS = Int32ub

# Register: 0x20
# TODO
RAMPMODE = ByteSwapped(
    Padded(4, Enum(Int8ul, position=0, positive=1, negative=2, hold=3)))

# Register: 0x21
XACTUAL = Int32sb

# Register: 0x22
VACTUAL = ByteSwapped(Padded(4, Int24sl))
示例#9
0
from construct import Aligned, Struct, Int8ul, Int16ul, Int32ul, Padded

from . import bagl_font
from . import bagl_glyph
from .automation import TextEvent

bagl_component_t = Aligned(4, Struct(
    "type" / Int8ul,
    "userid" / Int8ul,
    "x" / Int16ul,
    "y" / Int16ul,
    "width" / Int16ul,
    "height" / Int16ul,
    "stroke" / Int8ul,
    "radius" / Int8ul,
    "fill" / Padded(4, Int8ul),
    "fgcolor" / Int32ul,
    "bgcolor" / Int32ul,
    "font_id" / Int16ul,
    "icon_id" / Int8ul,
))

BAGL_FILL = 1

BAGL_FILL_CIRCLE_1_OCTANT = 1
BAGL_FILL_CIRCLE_2_OCTANT = 2
BAGL_FILL_CIRCLE_3_OCTANT = 4
BAGL_FILL_CIRCLE_4_OCTANT = 8
BAGL_FILL_CIRCLE_5_OCTANT = 16
BAGL_FILL_CIRCLE_6_OCTANT = 32
BAGL_FILL_CIRCLE_7_OCTANT = 64
示例#10
0
def show_frame(*args):
	global Color_Min, Color_Max
	Color_Min = (Hue_Min, Saturation_Min, Value_Min)
	Color_Max = (Hue_Max, Saturation_Max, Value_Max)
	ret, frame1 = cap1.read()
	ret, frame2 = cap2.read()
	hsv1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2HSV)
	hsv2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2HSV)
	cxy, cyy, cntsy = colorDetector.object_pos(Color_Min, Color_Max, hsv1)
	cxy2, cyy2, cntsy2 = colorDetector.object_pos(Color_Min, Color_Max, hsv2)
	if cxy != None and cxy2 != None and X_SCREEN_DEPTH != None and Y_SCREEN_DEPTH != None:
		#Start Converting Pixel Coordinates To Angles
		CAMERA_ANGLE_AY = Coordinate_Calculations.pixels_to_camera_angle(X_SCREEN_DEPTH, cxy)
		CAMERA_ANGLE_YY1 = Coordinate_Calculations.pixels_to_camera_angle(Y_SCREEN_DEPTH, cyy)
		CAMERA_ANGLE_BY = Coordinate_Calculations.pixels_to_camera_angle(X_SCREEN_DEPTH, cxy2)
		CAMERA_ANGLE_YY2 = Coordinate_Calculations.pixels_to_camera_angle(Y_SCREEN_DEPTH, cyy2)
		#End Converting Pixel Coordinates To Angles
		#Start Calculating Variables Needed For Coordinate Calculations
		THETA_AY, THETA_BY = Coordinate_Calculations.topview_camera_angles_to_internal_angles(CAMERA_ANGLE_AY, CAMERA_ANGLE_BY)
		if THETA_AY or THETA_BY != 0:
			LAY, LBY = Coordinate_Calculations.topview_range_from_cams(Dis_Between_Cams, THETA_BY, THETA_AY)
			#End Calculating Variables Needed For Coordinate Calculations
			#Start Calculating Coordinates
			XY = Coordinate_Calculations.x_coord(THETA_AY, THETA_BY, LAY, LBY, Dis_Between_Cams)
			YY = Coordinate_Calculations.y_coord(THETA_AY, THETA_BY, LAY, LBY)
			ZY = Coordinate_Calculations.z_coord(CAMERA_ANGLE_YY1, YY, CAMERA_ANGLE_YY2, YY)
			#End Calculating Coordinates
			
			
			# Start sending information to Vridge
			print(XY, YY, ZY)
			# Specify the structure for the fancy position matrix
			structure = Struct(
				Const(Int32ul, 2),
				Const(Int32ul, 5),
				Const(Int32ul, 24),
				"data" / Padded(64, Array(3, Float32l)),
			)
			
			offset = [0.0, 0.0, 0.0] # offset in case you want to define where the origin is (in centimeters)
			xyz = [(XY + offset[0]) / 100, (YY + offset[1]) / 100, (ZY + offset[2]) / 100] # Steam VR requires this information in meters
			byte_packet = structure.build(dict(data=xyz))
			endpoint.send(byte_packet)
			print("Send: " + str(structure.parse(byte_packet)))
            endpoint.recv()   
            # Stop sending information to vridge 
			
			
			#Start Drawing Contours
			for (i, c) in enumerate(cntsy):
				# draw the contour
				(x, y), radius = cv2.minEnclosingCircle(c)
				cv2.drawContours(frame1, [c], -1, (0, 255, 255), 2)
				overlay1 = frame1.copy()
				cv2.rectangle(overlay1, (int(cxy+radius), cyy - 30), (int(cxy + radius + 200), cyy+60), (0, 0, 0), -1)
				cv2.addWeighted(overlay1, alpha, frame1, 1 - alpha, 0, frame1)
				if units:
					cv2.putText(frame1, "X Axis " + str(Coordinate_Calculations.ceiling(XY)) +"cm", (int(cxy + radius + 20), cyy), cv2.FONT_HERSHEY_DUPLEX, 0.6, (255, 150, 0), 1)
					cv2.putText(frame1, "Y Axis " + str(Coordinate_Calculations.ceiling(YY)) +"cm", (int(cxy + radius + 20), cyy + 20), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 255, 0), 1)
					cv2.putText(frame1, "Z Axis " + str(Coordinate_Calculations.ceiling(ZY)) +"cm", (int(cxy + radius + 20), cyy + 40), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 0, 255), 1)
				else:
					cv2.putText(frame1, "X Axis " + str(Coordinate_Calculations.ceiling(XY)), (int(cxy + radius + 20), cyy), cv2.FONT_HERSHEY_DUPLEX, 0.6, (255, 150, 0), 1)
					cv2.putText(frame1, "Y Axis " + str(Coordinate_Calculations.ceiling(YY)), (int(cxy + radius + 20), cyy + 20), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 255, 0), 1)
					cv2.putText(frame1, "Z Axis " + str(Coordinate_Calculations.ceiling(ZY)), (int(cxy + radius + 20), cyy + 40), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 0, 255), 1)

			for (i, c) in enumerate(cntsy2):
				# draw the contour
				(x, y), radius = cv2.minEnclosingCircle(c)
				cv2.drawContours(frame2, [c], -1, (0, 255, 255), 2)
				overlay2 = frame2.copy()
				cv2.rectangle(overlay2, (int(cxy2+radius), cyy2 - 30), (int(cxy2 + radius + 200), cyy2 + 60), (0, 0, 0), -1)
				cv2.addWeighted(overlay2, alpha, frame2, 1 - alpha, 0, frame2)
				if units:
					cv2.putText(frame2, "X Axis " + str(Coordinate_Calculations.ceiling(XY)) +"cm", (int(cxy2 + radius + 20), cyy2), cv2.FONT_HERSHEY_DUPLEX, 0.6, (255, 150, 0), 1)
					cv2.putText(frame2, "Y Axis " + str(Coordinate_Calculations.ceiling(YY)) +"cm", (int(cxy2 + radius + 20), cyy2 + 20), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 255, 0), 1)
					cv2.putText(frame2, "Z Axis " + str(Coordinate_Calculations.ceiling(ZY)) +"cm", (int(cxy2 + radius + 20), cyy2 + 40), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 0, 255), 1)
				else:
					cv2.putText(frame2, "X Axis " + str(Coordinate_Calculations.ceiling(XY)), (int(cxy2 + radius + 20), cyy2), cv2.FONT_HERSHEY_DUPLEX, 0.6, (255, 150, 0), 1)
					cv2.putText(frame2, "Y Axis " + str(Coordinate_Calculations.ceiling(YY)), (int(cxy2 + radius + 20), cyy2 + 20), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 255, 0), 1)
					cv2.putText(frame2, "Z Axis " + str(Coordinate_Calculations.ceiling(ZY)), (int(cxy2 + radius + 20), cyy2 + 40), cv2.FONT_HERSHEY_DUPLEX, 0.6, (0, 0, 255), 1)
示例#11
0
    GetStatistics=0x8c,  # for testing only
    Candela_A2=0xa2,
    Candela_A3=0xa3,
    Candela_A4=0xa4,
)

Request = Padded(
    18,
    Struct(
        Const(0x43, Byte),
        "type" / RequestType,
        "payload" / Switch(
            this.type,
            {
                "SetOnOff": Default(OnOff, Pass),
                "SetColor": Default(Color, Pass),
                "SetBrightness": Default(Brightness, Pass),
                "SetTemperature": Default(Temperature, Pass),
                "Pair": Pair,
                "GetAlarm": Default(Struct("id" / Byte), Pass),  # 1-6, 255
                "GetScene": Default(Struct("id" / Byte), Pass),  # 1-6, 255
                "GetSimpleFlow": Default(Struct("id" / Byte), Pass),
                "SetScene": Default(Scene, Pass),
            }),
    ))

ResponseType = Enum(
    Byte,
    StateResult=0x45,
    AlarmResult=0x49,
    FlowMode=0x4a,
示例#12
0
DIVIDEND_PAY_DATE = "Dividend Pay Date"

DELISTING_DATE = "Delisting Date"
SwappedField = FormatField("<", "f")

# Const(b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F")
from construct import CString

ascii_str = CString("ascii")
Master = Struct(
    "Header" / Bytes(8),
    "NumSymbols" / Int32ul,
    "Symbols" / GreedyRange(
        Struct(
            "Symbol" / Padded(492, CString("ascii")),
            "CONST" / Const(
                b"\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F"
            ),
            "Rest" / Bytes(1172 - 5 - 16 - 490 + 3),
        )),
)

# Symbol 7-151
# FullName Byte 152- 499
# 22C- 22F Schares Float
SymbolHeader = Struct(
    "Start" / Const(b"BROKDAt5"),  # 8
    "SymbolName" / Padded(144, CString("ascii")),  #144 + 8 = 152
    "FullName" / Padded(348, CString("ascii")),  # 152+349 =501
    #"Const"/Bytes(16),# 16 +501 =517
示例#13
0
        "de_queue": actions.de_queue,
        "postgame": actions.postgame,
        "de_attackmove": actions.de_attackmove,
        "de_autoscout": actions.de_autoscout
    }, default=Struct(
        "unk_action"/Computed(lambda ctx: ctx._.type),
        "bytes"/Bytes(lambda ctx: ctx._._.length - 1)
    ))),
    Padding(4)
)


# Action - length followed by data.
action = "action"/Struct(
    "length"/Int32ul,
    Padded(lambda ctx: ctx.length + 4, action_data)
)


# Synchronization.
sync = "sync"/Struct(
    "time_increment"/Int32ul,
    Peek("next"/Int32ul),
    "checksum"/If(lambda ctx: not ctx.next, Struct(
        Padding(8),
        "sync"/Int32ul,
        "unknown"/Bytes(4),
        "sequence"/Int32ul,
        If(lambda ctx: ctx.sequence > 0, Bytes(332)),
        Bytes(8)
    ))
示例#14
0
                               GetName=0x52,
                               Pair=0x67,
                               SetNightMode=0x6f,
                               GetNightMode=0x70,
                               GetSleepTimer=0x80,
                               GetWakeUp=0x88,
                               GetStatistics=0x8c,
                               )

Request = "msg" / Padded(18, Struct(
    Const(Int8ub, 0x43),
    "type" / RequestType,
    "payload" / Embedded(
        Switch(this.type, {
            "SetOnOff": OnOff,
            "SetColor": Color,
            "SetBrightness": Brightness,
            "SetTemperature": Temperature,
            "Pair": Pair,
        }, default=Pass),
    ),
))

ResponseType = "type" / Enum(Byte,
                             StateResult=0x45,
                             FlowMode=0x4a,
                             SetName=0x51,
                             GetNameResult=0x53,
                             Unknown_5c=0x5c,
                             Status=0x62,
                             PairingResult=0x63,
示例#15
0
文件: mst.py 项目: scieloorg/ioisis
    def create_control_record_struct(self):
        little_endian = self.endianness == "little"
        min_mod = self.min_modulus
        control_len = self.control_len

        # Data types for integer values
        Int16s, Int16u, Int32s, Int32u = {
            "big": (Int16sb, Int16ub, Int32sb, Int32ub),
            "little": (Int16sl, Int16ul, Int32sl, Int32ul),
        }[self.endianness]

        # The 16 bytes that used to have the legacy MFTYPE field
        # has both the actual MFTYPE and the MSTXL,
        # and their order is affected by the endianness
        mftype = "mftype" / Default(Byte, 0)
        mstxl = "mstxl" / Rebuild(
            Byte,
            lambda this: this.mstxl
            if "mstxl" in this and this.mstxl is not None else this.get(
                "shift",
                this.modulus.bit_length() - 1
                if "modulus" in this else self.default_shift,
            ),
        )

        # MFCXX2 and MFCXX3 are used for locking the file on updating
        if self.lockable:
            mfcxx2 = "_mfcxx2" / Union(
                0,
                "mfcxx2" / Default(Int32s, 0),
                "delock_count" / Int32u,  # Data entry lock
            )
            mfcxx3 = "_mfcxx3" / Union(
                0,
                "mfcxx3" / Default(Int32s, 0),
                "ewlock" / ExprAdapter(
                    Int32u,  # Exclusive write lock
                    lambda obj, ctx: bool(obj),
                    lambda obj, ctx: int(obj)),
            )
        else:
            mfcxx2 = "mfcxx2" / Default(Int32s, 0)
            mfcxx3 = "mfcxx3" / Default(Int32s, 0)

        # Legacy shift replacement
        if self.shift4is3:
            shift = "shift" / Computed(lambda this: 3
                                       if this.mstxl == 4 else this.mstxl)
        else:
            shift = "shift" / Computed(lambda this: this.mstxl)

        # The control record struct for all cases
        nested_unpadded_struct = Struct(
            # First 4 fields, including information about the whole file
            "mfn" / Default(Int32s, 0),  # CTLMFN
            Check(lambda this: this.mfn == 0),
            "next_mfn" / Default(Int32s, 1),  # NXTMFN
            "next_block" / Default(Int32s, 1),  # NXTMFB
            "next_offset" / Default(Int16u, self.control_len),  # NXTMFP
            *([mftype, mstxl] if little_endian else [mstxl, mftype]),

            # Get the MST (modulus) and XRF (shift) alignment/shift values
            # from the MSTXL field, fixing the "legacy" replacements
            shift,
            "modulus" / Computed(lambda this: max(min_mod, 1 << this.shift)),
            Check(lambda this: control_len % this.modulus == 0),

            # Fields used for "statistics during backup/restore",
            # where the last two fields are also used for multi-user locking
            "reccnt" / Default(Int32s, 0),
            "mfcxx1" / Default(Int32s, 0),
            mfcxx2,
            mfcxx3,
        )
        return Padded(
            length=control_len,
            subcon=Unnest(["_mfcxx2", "_mfcxx3"], nested_unpadded_struct)
            if self.lockable else nested_unpadded_struct,
            pattern=self.control_filler,
        )