示例#1
0
def get_production_actions(produce):
    """
    Get the action list that implements the given produce-block in nfo.

    @param produce: Produce-block to parse.
    @type produce: L{Produce}
    """
    action_list = []
    act6 = action6.Action6()
    action6.free_parameters.save()

    result_list = []
    varact2parser = action2var.Varaction2Parser(0x0A, 0x0A)
    if all(x.supported_by_actionD(False) for x in produce.param_list):
        version = 0
        offset = 4
        for i, param in enumerate(produce.param_list):
            result, offset = actionD.write_action_value(
                param, action_list, act6, offset, 2 if i < 5 else 1)
            result_list.append(result.value)
    else:
        version = 1
        for param in produce.param_list:
            result_list.append(resolve_prodcb_register(param, varact2parser))

    if len(act6.modifications) > 0:
        action_list.append(act6)
    prod_action = Action2Production(produce.name.value, produce.pos, version,
                                    result_list[0:3], result_list[3:5],
                                    result_list[5])

    return finish_production_actions(produce, prod_action, action_list,
                                     varact2parser)
示例#2
0
文件: action3.py 项目: stormcone/nml
def create_action3(feature, id, action_list, act6, is_livery_override):
    # Vehicles use an extended byte
    size = 2 if feature <= 3 else 1
    offset = 4 if feature <= 3 else 3

    id, offset = actionD.write_action_value(id, action_list, act6, offset, size)
    return Action3(feature, id.value, is_livery_override)
示例#3
0
def parse_minmax(value, unit_str, action_list, act6, offset):
    """
    Parse a min or max value in a switch block.

    @param value: Value to parse
    @type value: L{Expression}

    @param unit_str: Unit to use
    @type unit_str: C{str} or C{None}

    @param action_list: List to append any extra actions to
    @type action_list: C{list} of L{BaseAction}

    @param act6: Action6 to add any modifications to
    @type act6: L{Action6}

    @param offset: Current offset to use for action6
    @type offset: C{int}

    @return: A tuple of two values:
                - The value to use as min/max
                - Whether the resulting range may need a sanity check
    @rtype: C{tuple} of (L{ConstantNumeric} or L{SpriteGroupRef}), C{bool}
    """
    if unit_str is not None:
        raise generic.ScriptError(
            "Using a unit is in switch-ranges is not (temporarily) not supported",
            value.pos)
    result, offset = actionD.write_action_value(value, action_list, act6,
                                                offset, 4)
    check_range = isinstance(value, expression.ConstantNumeric)
    return (result, offset, check_range)
示例#4
0
文件: actionB.py 项目: spnda/nml
def parse_error_block(error):
    action6.free_parameters.save()
    action_list = []
    act6 = action6.Action6()

    severity = actionD.write_action_value(error.severity, action_list, act6, 1,
                                          1)[0]

    langs = [0x7F]
    if isinstance(error.msg, expression.String):
        custom_msg = True
        msg_string = error.msg
        grfstrings.validate_string(msg_string)
        langs.extend(grfstrings.get_translations(msg_string))
        for lang in langs:
            assert lang is not None
    else:
        custom_msg = False
        msg = error.msg.reduce_constant().value

    if error.data is not None:
        error.data = error.data.reduce()
        if isinstance(error.data, expression.String):
            grfstrings.validate_string(error.data)
            langs.extend(grfstrings.get_translations(error.data))
            for lang in langs:
                assert lang is not None
        elif not isinstance(error.data, expression.StringLiteral):
            raise generic.ScriptError(
                "Error parameter 3 'data' should be the identifier of a custom sting",
                error.data.pos)

    params = []
    for expr in error.params:
        if isinstance(expr, expression.Parameter) and isinstance(
                expr.num, expression.ConstantNumeric):
            params.append(expr.num)
        else:
            tmp_param, tmp_param_actions = actionD.get_tmp_parameter(expr)
            action_list.extend(tmp_param_actions)
            params.append(expression.ConstantNumeric(tmp_param))

    langs = list(set(langs))
    langs.sort()
    for lang in langs:
        if custom_msg:
            msg = grfstrings.get_translation(msg_string, lang)
        if error.data is None:
            data = None
        elif isinstance(error.data, expression.StringLiteral):
            data = error.data.value
        else:
            data = grfstrings.get_translation(error.data, lang)
        if len(act6.modifications) > 0:
            action_list.append(act6)
        action_list.append(ActionB(severity, lang, msg, data, params))

    action6.free_parameters.restore()
    return action_list
示例#5
0
文件: actionA.py 项目: stormcone/nml
def parse_actionA(replaces):
    """
    Parse replace-block to ActionA.

    @param replaces: Replace-block to parse.
    @type  replaces: L{ReplaceSprite}
    """
    action_list = []
    action6.free_parameters.save()
    act6 = action6.Action6()

    real_sprite_list = real_sprite.parse_sprite_data(replaces)
    block_list = []
    total_sprites = len(real_sprite_list)
    offset = 2  # Skip 0A and <num-sets>
    sprite_offset = 0  # Number of sprites already covered by previous [<num-sprites> <first-sprite>]-pairs

    while total_sprites > 0:
        this_block = min(total_sprites, 255)  # number of sprites in this block
        total_sprites -= this_block
        offset += 1  # Skip <num-sprites>

        first_sprite = replaces.start_id  # number of first sprite
        if sprite_offset != 0:
            first_sprite = expression.BinOp(
                nmlop.ADD, first_sprite,
                expression.ConstantNumeric(sprite_offset, first_sprite.pos),
                first_sprite.pos).reduce()
        first_sprite, offset = actionD.write_action_value(
            first_sprite, action_list, act6, offset, 2)
        block_list.append((this_block, first_sprite.value))

        sprite_offset += this_block  # increase first-sprite for next block

    if len(act6.modifications) > 0:
        action_list.append(act6)
    action6.free_parameters.restore()

    action_list.append(ActionA(block_list))
    action_list.extend(real_sprite_list)

    return action_list
示例#6
0
def create_action0(feature, id, act6, action_list):
    """
    Create an action0 with variable id

    @param feature: Feature of the action0
    @type feature: C{int}

    @param id: ID of the corresponding item
    @type id: L{Expression}

    @param act6: Action6 to add any modifications to
    @type act6: L{Action6}

    @param action_list: Action list to append any extra actions to
    @type action_list: C{list} of L{BaseAction}

    @return: A tuple of (resulting action0, offset to use for action6)
    @rtype: C{tuple} of (L{Action0}, C{int})
    """
    id, offset = actionD.write_action_value(id, action_list, act6, 5, 2)

    action0 = Action0(feature, id.value)
    return (action0, offset)
示例#7
0
def get_layout_action2s(spritelayout, feature, spr_pos):
    """
    @param spr_pos: Position information of the sprite view.
    @type  spr_pos: L{Position}
    """
    ground_sprite = None
    building_sprites = []
    actions = []

    if feature not in action2.features_sprite_layout:
        raise generic.ScriptError(
            "Sprite layouts are not supported for feature '{}'.".format(
                general.feature_name(feature)))

    # Allocate registers
    param_map = {}
    param_registers = []
    for param in spritelayout.param_list:
        reg = action2var.VarAction2CallParam(param.value)
        param_registers.append(reg)
        param_map[param.value] = reg
    param_map = (param_map, lambda name, value, pos: action2var.
                 VarAction2LoadCallParam(value, name))
    spritelayout.register_map[feature] = param_registers

    # Reduce all expressions, can't do that earlier as feature is not known
    all_sprite_sets = []
    layout_sprite_list = []  # Create a new structure
    for layout_sprite in spritelayout.layout_sprite_list:
        param_list = []
        layout_sprite_list.append(
            (layout_sprite.type, layout_sprite.pos, param_list))
        for param in layout_sprite.param_list:
            param_val = action2var.reduce_varaction2_expr(
                param.value, action2var.get_scope(feature), [param_map])
            param_list.append((param.name, param_val))
            if isinstance(param_val, expression.SpriteGroupRef):
                spriteset = action2.resolve_spritegroup(param_val.name)
                if not spriteset.is_spriteset():
                    raise generic.ScriptError(
                        "Expected a reference to a spriteset.", param_val.pos)
                all_sprite_sets.append(spriteset)
    actions.extend(
        action1.add_to_action1(all_sprite_sets, feature, spritelayout.pos))

    temp_registers = []
    for type, pos, param_list in layout_sprite_list:
        if type.value not in layout_sprite_types:
            raise generic.ScriptError(
                "Invalid sprite type '{}' encountered. Expected 'ground', 'building', or 'childsprite'."
                .format(type.value),
                type.pos,
            )
        sprite = Action2LayoutSprite(feature, layout_sprite_types[type.value],
                                     pos, [param_map])
        for name, value in param_list:
            sprite.set_param(name, value)
        temp_registers.extend(sprite.get_all_registers())
        if sprite.type == Action2LayoutSpriteType.GROUND:
            if ground_sprite is not None:
                raise generic.ScriptError(
                    "Sprite layout can have no more than one ground sprite",
                    spritelayout.pos)
            ground_sprite = sprite
        else:
            building_sprites.append(sprite)

    if ground_sprite is None:
        if len(building_sprites) == 0:
            # no sprites defined at all, that's not very much.
            raise generic.ScriptError(
                "Sprite layout requires at least one sprite", spr_pos)
        # set to 0 for no ground sprite
        ground_sprite = Action2LayoutSprite(feature,
                                            Action2LayoutSpriteType.GROUND)
        ground_sprite.set_param(expression.Identifier("sprite"),
                                expression.ConstantNumeric(0))

    action6.free_parameters.save()
    act6 = action6.Action6()

    advanced = any(x.is_advanced_sprite()
                   for x in building_sprites + [ground_sprite])

    offset = 4
    sprite_num = ground_sprite.get_sprite_number()
    sprite_num, offset = actionD.write_action_value(sprite_num, actions, act6,
                                                    offset, 4)
    if advanced:
        offset += ground_sprite.get_registers_size()

    for sprite in building_sprites:
        sprite_num = sprite.get_sprite_number()
        sprite_num, offset = actionD.write_action_value(
            sprite_num, actions, act6, offset, 4)
        if advanced:
            offset += sprite.get_registers_size()
        offset += 3 if sprite.type == Action2LayoutSpriteType.CHILD else 6

    if len(act6.modifications) > 0:
        actions.append(act6)

    layout_action = Action2Layout(
        feature,
        spritelayout.name.value + " - feature {:02X}".format(feature),
        spritelayout.pos,
        ground_sprite,
        building_sprites,
        param_registers,
    )
    actions.append(layout_action)

    if temp_registers:
        varact2parser = action2var.Varaction2Parser(
            feature, action2var.get_scope(feature))
        for register_info in temp_registers:
            reg, expr = register_info[1], register_info[2]
            if reg is None:
                continue
            varact2parser.parse_expr(expr)
            varact2parser.var_list.append(nmlop.STO_TMP)
            varact2parser.var_list.append(reg)
            varact2parser.var_list.append(nmlop.VAL2)
            varact2parser.var_list_size += reg.get_size() + 2

    # Only continue if we actually needed any new registers
    if temp_registers and varact2parser.var_list:  # lgtm[py/uninitialized-local-variable]
        # Remove the last VAL2 operator
        varact2parser.var_list.pop()
        varact2parser.var_list_size -= 1

        actions.extend(varact2parser.extra_actions)
        extra_act6 = action6.Action6()
        for mod in varact2parser.mods:
            extra_act6.modify_bytes(mod.param, mod.size, mod.offset + 4)
        if len(extra_act6.modifications) > 0:
            actions.append(extra_act6)

        varaction2 = action2var.Action2Var(
            feature,
            "{}@registers - feature {:02X}".format(spritelayout.name.value,
                                                   feature), spritelayout.pos,
            0x89)
        varaction2.var_list = varact2parser.var_list
        ref = expression.SpriteGroupRef(spritelayout.name, [], None,
                                        layout_action)
        varaction2.ranges.append(
            action2var.VarAction2Range(expression.ConstantNumeric(0),
                                       expression.ConstantNumeric(0), ref, ""))
        varaction2.default_result = ref
        varaction2.default_comment = ""

        # Add two references (default + range)
        # Make sure that registers allocated here are not used by the spritelayout
        action2.add_ref(ref, varaction2, True)
        action2.add_ref(ref, varaction2, True)
        spritelayout.set_action2(varaction2, feature)
        actions.append(varaction2)
    else:
        spritelayout.set_action2(layout_action, feature)

    action6.free_parameters.restore()
    return actions
示例#8
0
def get_production_actions(produce):
    """
    Get the action list that implements the given produce-block in nfo.

    @param produce: Produce-block to parse.
    @type produce: L{Produce}
    """
    action_list = []
    act6 = action6.Action6()
    action6.free_parameters.save()

    result_list = []
    varact2parser = action2var.Varaction2Parser(0x0A)
    if all(x.supported_by_actionD(False) for x in produce.param_list):
        version = 0
        offset = 4
        for i, param in enumerate(produce.param_list):
            result, offset = actionD.write_action_value(
                param, action_list, act6, offset, 2 if i < 5 else 1)
            result_list.append(result.value)
    else:
        version = 1
        for i, param in enumerate(produce.param_list):
            if isinstance(param, expression.StorageOp) and param.name == 'LOAD_TEMP' and \
                    isinstance(param.register, expression.ConstantNumeric):
                # We can load a register directly
                result_list.append(
                    action2var.VarAction2Var(0x7D, 0, 0xFFFFFFFF,
                                             param.register.value))
            else:
                if len(varact2parser.var_list) != 0:
                    varact2parser.var_list.append(nmlop.VAL2)
                    varact2parser.var_list_size += 1
                varact2parser.parse_expr(
                    action2var.reduce_varaction2_expr(param, 0x0A))
                store_tmp = action2var.VarAction2StoreTempVar()
                result_list.append(action2var.VarAction2LoadTempVar(store_tmp))
                varact2parser.var_list.append(nmlop.STO_TMP)
                varact2parser.var_list.append(store_tmp)
                varact2parser.var_list_size += store_tmp.get_size(
                ) + 1  # Add 1 for operator

    if len(act6.modifications) > 0: action_list.append(act6)
    prod_action = Action2Production(produce.name.value, produce.pos, version,
                                    result_list[0:3], result_list[3:5],
                                    result_list[5])
    action_list.append(prod_action)

    if len(varact2parser.var_list) == 0:
        produce.set_action2(prod_action, 0x0A)
    else:
        # Create intermediate varaction2
        varaction2 = action2var.Action2Var(
            0x0A, '{}@registers'.format(produce.name.value), produce.pos, 0x89)
        varaction2.var_list = varact2parser.var_list
        action_list.extend(varact2parser.extra_actions)
        extra_act6 = action6.Action6()
        for mod in varact2parser.mods:
            extra_act6.modify_bytes(mod.param, mod.size, mod.offset + 4)
        if len(extra_act6.modifications) > 0: action_list.append(extra_act6)
        ref = expression.SpriteGroupRef(produce.name, [], None, prod_action)
        varaction2.ranges.append(
            action2var.VarAction2Range(expression.ConstantNumeric(0),
                                       expression.ConstantNumeric(0), ref, ''))
        varaction2.default_result = ref
        varaction2.default_comment = ''

        # Add two references (default + range)
        action2.add_ref(ref, varaction2)
        action2.add_ref(ref, varaction2)
        produce.set_action2(varaction2, 0x0A)
        action_list.append(varaction2)

    action6.free_parameters.restore()

    return action_list