def register_names(self): for i, tracktype in enumerate(self.tracktype_list): if isinstance(tracktype, assignment.Assignment): name = tracktype.name val_list = [] for rt in tracktype.value: if isinstance(rt, expression.Identifier): val_list.append( expression.StringLiteral(rt.value, rt.pos)) else: val_list.append(rt) expression.parse_string_to_dword( val_list[-1] ) # we don't care about the result, only validate the input self.tracktype_list[i] = val_list if len( val_list) > 1 else val_list[0] else: name = tracktype if isinstance(tracktype, expression.Identifier): self.tracktype_list[i] = expression.StringLiteral( tracktype.value, tracktype.pos) expression.parse_string_to_dword( self.tracktype_list[i] ) # we don't care about the result, only validate the input self.tracktype_table[name.value] = i
def register_names(self): generic.OnlyOnce.enforce(self, "cargo table") for i, cargo in enumerate(self.cargo_list): if isinstance(cargo, expression.Identifier): self.cargo_list[i] = expression.StringLiteral( cargo.value, cargo.pos) expression.parse_string_to_dword( self.cargo_list[i] ) # we don't care about the result, only validate the input global_constants.cargo_numbers[self.cargo_list[i].value] = i
def pre_process(self): if len(self.args) not in (1, 2): raise generic.ScriptError("engine_override expects 1 or 2 parameters", self.pos) if len(self.args) == 1: try: self.source_grfid = expression.Identifier('GRFID').reduce(global_constants.const_list).value assert isinstance(self.source_grfid, int) except generic.ScriptError: raise generic.ScriptError("GRFID of this grf is required, but no grf-block is defined.", self.pos) else: self.source_grfid = expression.parse_string_to_dword(self.args[0].reduce(global_constants.const_list)) self.grfid = expression.parse_string_to_dword(self.args[-1].reduce(global_constants.const_list))
def pre_process(self): if None in (self.name, self.desc, self.grfid, self.version, self.min_compatible_version): raise generic.ScriptError("A GRF-block requires the 'name', 'desc', 'grfid', 'version' and 'min_compatible_version' properties to be set.", self.pos) self.grfid = self.grfid.reduce() global_constants.constant_numbers['GRFID'] = expression.parse_string_to_dword(self.grfid) self.name = self.name.reduce() if not isinstance(self.name, expression.String): raise generic.ScriptError("GRF-name must be a string", self.name.pos) grfstrings.validate_string(self.name) self.desc = self.desc.reduce() if not isinstance(self.desc, expression.String): raise generic.ScriptError("GRF-description must be a string", self.desc.pos) grfstrings.validate_string(self.desc) if self.url is not None: self.url = self.url.reduce() if not isinstance(self.url, expression.String): raise generic.ScriptError("URL must be a string", self.url.pos) grfstrings.validate_string(self.url) self.version = self.version.reduce_constant() self.min_compatible_version = self.min_compatible_version.reduce_constant() global param_stats param_num = 0 for param in self.params: param.pre_process(expression.ConstantNumeric(param_num)) param_num = param.num.value + 1 if param_num > param_stats[1]: raise generic.ScriptError("No free parameters available. Consider assigning <num> manually and combine multiple bool parameters into a single bitmask parameter using <bit>.", self.pos) if param_num > param_stats[0]: param_stats[0] = param_num
def preprocess_storageop(self, expr): assert isinstance(expr, expression.StorageOp) if expr.info["perm"] and self.var_feature not in (0x08, 0x0A, 0x0D): raise generic.ScriptError( "Persistent storage is not supported for feature '{}'".format(general.feature_name(self.var_feature)), expr.pos, ) if expr.info["store"]: op = nmlop.STO_PERM if expr.info["perm"] else nmlop.STO_TMP ret = expression.BinOp(op, expr.value, expr.register, expr.pos) else: var_num = 0x7C if expr.info["perm"] else 0x7D ret = expression.Variable(expression.ConstantNumeric(var_num), param=expr.register, pos=expr.pos) if expr.info["perm"] and self.var_feature == 0x08: # store grfid in register 0x100 for town persistent storage grfid = expression.ConstantNumeric( 0xFFFFFFFF if expr.grfid is None else expression.parse_string_to_dword(expr.grfid) ) store_op = nmlop.STO_TMP(grfid, 0x100, expr.pos) ret = nmlop.VAL2(store_op, ret) elif expr.grfid is not None: raise generic.ScriptError("Specifying a grfid is only possible for town persistent storage.", expr.pos) return ret
def get_tracktypelist_action(table_prop_id, cond_tracktype_not_defined, tracktype_list): action6.free_parameters.save() act6 = action6.Action6() action_list = [] action0, offset = create_action0(0x08, expression.ConstantNumeric(0), act6, action_list) id_table = [] offset += 1 # Skip property number for tracktype in tracktype_list: if isinstance(tracktype, expression.StringLiteral): id_table.append(tracktype) offset += 4 continue param, extra_actions = actionD.get_tmp_parameter( expression.ConstantNumeric( expression.parse_string_to_dword(tracktype[-1]))) action_list.extend(extra_actions) for idx in range(len(tracktype) - 2, -1, -1): val = expression.ConstantNumeric( expression.parse_string_to_dword(tracktype[idx])) action_list.append( action7.SkipAction(0x09, 0x00, 4, (cond_tracktype_not_defined, None), val.value, 1)) action_list.append( actionD.ActionD( expression.ConstantNumeric(param), expression.ConstantNumeric(0xFF), nmlop.ASSIGN, expression.ConstantNumeric(0xFF), val, )) act6.modify_bytes(param, 4, offset) id_table.append(expression.StringLiteral(r"\00\00\00\00", None)) offset += 4 action0.prop_list.append(IDListProp(table_prop_id, id_table)) action0.num_ids = len(tracktype_list) if len(act6.modifications) > 0: action_list.append(act6) action_list.append(action0) action6.free_parameters.restore() return action_list
def register_names(self): generic.OnlyOnce.enforce(self, "cargo table") for i, cargo in enumerate(self.cargo_list): if isinstance(cargo, expression.Identifier): self.cargo_list[i] = expression.StringLiteral( cargo.value, cargo.pos) expression.parse_string_to_dword( self.cargo_list[i] ) # we don't care about the result, only validate the input if self.cargo_list[i].value in global_constants.cargo_numbers: generic.print_warning( generic.Warning.GENERIC, "Duplicate entry in cargo table: {}".format( self.cargo_list[i].value), cargo.pos, ) else: global_constants.cargo_numbers[self.cargo_list[i].value] = i
def register_names(self): generic.OnlyOnce.enforce(self, "rail type table") global_constants.is_default_railtype_table = False global_constants.railtype_table.clear() for i, railtype in enumerate(self.railtype_list): if isinstance(railtype, assignment.Assignment): name = railtype.name val_list = [] for rt in railtype.value: if isinstance(rt, expression.Identifier): val_list.append(expression.StringLiteral(rt.value, rt.pos)) else: val_list.append(rt) expression.parse_string_to_dword(val_list[-1]) # we don't care about the result, only validate the input self.railtype_list[i] = val_list if len(val_list) > 1 else val_list[0] else: name = railtype if isinstance(railtype, expression.Identifier): self.railtype_list[i] = expression.StringLiteral(railtype.value, railtype.pos) expression.parse_string_to_dword(self.railtype_list[i]) # we don't care about the result, only validate the input global_constants.railtype_table[name.value] = i
def pre_process(self): # Parse (string-)expressions to integers self.grfid_list = [ expression.parse_string_to_dword(grfid.reduce()) for grfid in self.grfid_list ]
def parse_actionD(assignment): assignment.value.supported_by_actionD(True) if isinstance(assignment.param, expression.SpecialParameter): assignment.param, assignment.value = assignment.param.to_assignment(assignment.value) elif isinstance(assignment.param, expression.Identifier): if global_constants.identifier_refcount[assignment.param.value] == 0: # Named parameter is not referenced, ignoring return [] assignment.param = expression.Parameter( expression.ConstantNumeric(global_constants.named_parameters[assignment.param.value]), assignment.param.pos ) assert isinstance(assignment.param, expression.Parameter) if isinstance(assignment.value, expression.SpecialParameter): assignment.value = assignment.value.to_reading() if isinstance(assignment.value, expression.TernaryOp): return parse_ternary_op(assignment) if isinstance(assignment.value, expression.AbsOp): return parse_abs_op(assignment) if isinstance(assignment.value, expression.SpecialCheck): return parse_special_check(assignment) if isinstance(assignment.value, expression.GRMOp): return parse_grm(assignment) if isinstance(assignment.value, expression.BinOp): op = assignment.value.op if op == nmlop.HASBIT or op == nmlop.NOTHASBIT: return parse_hasbit(assignment) elif op == nmlop.MIN or op == nmlop.MAX: return parse_min_max(assignment) if isinstance(assignment.value, expression.Boolean): return parse_boolean(assignment) if isinstance(assignment.value, expression.Not): expr = nmlop.SUB(1, assignment.value.expr) assignment = ParameterAssignment(assignment.param, expr) if isinstance(assignment.value, expression.BinNot): expr = nmlop.SUB(0xFFFFFFFF, assignment.value.expr) assignment = ParameterAssignment(assignment.param, expr) action6.free_parameters.save() action_list = [] act6 = action6.Action6() assert isinstance(assignment.param, expression.Parameter) target = assignment.param.num if isinstance(target, expression.Parameter) and isinstance(target.num, expression.ConstantNumeric): act6.modify_bytes(target.num.value, 1, 1) target = expression.ConstantNumeric(0) elif not isinstance(target, expression.ConstantNumeric): tmp_param, tmp_param_actions = get_tmp_parameter(target) act6.modify_bytes(tmp_param, 1, 1) target = expression.ConstantNumeric(0) action_list.extend(tmp_param_actions) data = None # print assignment.value if isinstance(assignment.value, expression.ConstantNumeric): op = nmlop.ASSIGN param1 = expression.ConstantNumeric(0xFF) param2 = expression.ConstantNumeric(0) data = assignment.value elif isinstance(assignment.value, expression.Parameter): if isinstance(assignment.value.num, expression.ConstantNumeric): op = nmlop.ASSIGN param1 = assignment.value.num else: tmp_param, tmp_param_actions = get_tmp_parameter(assignment.value.num) act6.modify_bytes(tmp_param, 1, 3) action_list.extend(tmp_param_actions) op = nmlop.ASSIGN param1 = expression.ConstantNumeric(0) param2 = expression.ConstantNumeric(0) elif isinstance(assignment.value, expression.OtherGRFParameter): op = nmlop.ASSIGN if isinstance(assignment.value.num, expression.ConstantNumeric): param1 = assignment.value.num else: tmp_param, tmp_param_actions = get_tmp_parameter(assignment.value.num) act6.modify_bytes(tmp_param, 1, 3) action_list.extend(tmp_param_actions) param1 = expression.ConstantNumeric(0) param2 = expression.ConstantNumeric(0xFE) data = expression.ConstantNumeric(expression.parse_string_to_dword(assignment.value.grfid)) elif isinstance(assignment.value, expression.PatchVariable): op = nmlop.ASSIGN param1 = expression.ConstantNumeric(assignment.value.num) param2 = expression.ConstantNumeric(0xFE) data = expression.ConstantNumeric(0xFFFF) elif isinstance(assignment.value, expression.BinOp): op, expr1, expr2, extra_actions = transform_bin_op(assignment) action_list.extend(extra_actions) if isinstance(expr1, expression.ConstantNumeric): param1 = expression.ConstantNumeric(0xFF) data = expr1 elif isinstance(expr1, expression.Parameter) and isinstance(expr1.num, expression.ConstantNumeric): param1 = expr1.num else: tmp_param, tmp_param_actions = get_tmp_parameter(expr1) action_list.extend(tmp_param_actions) param1 = expression.ConstantNumeric(tmp_param) # We can use the data only for one for the parameters. # If the first parameter uses "data" we need a temp parameter for this one if isinstance(expr2, expression.ConstantNumeric) and data is None: param2 = expression.ConstantNumeric(0xFF) data = expr2 elif isinstance(expr2, expression.Parameter) and isinstance(expr2.num, expression.ConstantNumeric): param2 = expr2.num else: tmp_param, tmp_param_actions = get_tmp_parameter(expr2) action_list.extend(tmp_param_actions) param2 = expression.ConstantNumeric(tmp_param) else: raise generic.ScriptError("Invalid expression in argument assignment", assignment.value.pos) if len(act6.modifications) > 0: action_list.append(act6) action_list.append(ActionD(target, param1, op, param2, data)) action6.free_parameters.restore() return action_list