Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nml for openSUSE:Factory checked in at 2024-03-02 23:24:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nml (Old) and /work/SRC/openSUSE:Factory/.nml.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nml" Sat Mar 2 23:24:13 2024 rev:26 rq:1154311 version:0.7.5 Changes: -------- --- /work/SRC/openSUSE:Factory/nml/nml.changes 2024-02-23 16:46:35.966099726 +0100 +++ /work/SRC/openSUSE:Factory/.nml.new.1770/nml.changes 2024-03-02 23:24:33.185732242 +0100 @@ -1,0 +2,18 @@ +Sat Mar 2 14:38:06 UTC 2024 - Jan Baier <[email protected]> + +- update to 0.7.5 + * Change: add constants GROUNDSPRITE_ROAD_X and GROUNDSPRITE_ROAD_Y by @andythenorth in https://github.com/OpenTTD/nml/pull/307 + * Fix: Register named parameters earlier by @glx22 in https://github.com/OpenTTD/nml/pull/301 + * Add: Support for build probability action CB 162 var10 0 (reverse rail vehicle) by @PeterN in https://github.com/OpenTTD/nml/pull/313 + * Fix cleanup leaving generated files behind by @matthijskooijman in https://github.com/OpenTTD/nml/pull/312 + * Change: Allow creating 32bpp-only NewGRFs by @PeterN in https://github.com/OpenTTD/nml/pull/314 + * Fix a9a1a3e: Don't use station properties 1C/1D for IDs 00-FF by @glx22 in https://github.com/OpenTTD/nml/pull/305 + * Add: [Dependabot] introduce Dependabot to keep our workflows up-to-date by @glx22 in https://github.com/OpenTTD/nml/pull/316 + * Upgrade: [Actions] Bump the actions group with 4 updates by @dependabot in https://github.com/OpenTTD/nml/pull/317 + * Add: Support for faster ship speed 23 and acceleration 24 (OTTD #10734) by @zephyris in https://github.com/OpenTTD/nml/pull/315 + * Update: changelog for 0.7.5 by @glx22 in https://github.com/OpenTTD/nml/pull/319 + * Add: Support town_production_effect and town_production_multiplier. by @PeterN in https://github.com/OpenTTD/nml/pull/318 + * Change: add --no-palette-validation optional arg by @andythenorth in https://github.com/OpenTTD/nml/pull/322 + * Update: changelog for 0.7.5 by @glx22 in https://github.com/OpenTTD/nml/pull/323 + +------------------------------------------------------------------- Old: ---- nml-0.7.4.tar.gz New: ---- nml-0.7.5.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nml.spec ++++++ --- /var/tmp/diff_new_pack.2vEDds/_old 2024-03-02 23:24:34.833791939 +0100 +++ /var/tmp/diff_new_pack.2vEDds/_new 2024-03-02 23:24:34.837792084 +0100 @@ -1,7 +1,7 @@ # # spec file for package nml # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: nml -Version: 0.7.4 +Version: 0.7.5 Release: 0 Summary: NewGRF Meta Language License: GPL-2.0-or-later ++++++ nml-0.7.4.tar.gz -> nml-0.7.5.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/Makefile new/nml-0.7.5/Makefile --- old/nml-0.7.4/Makefile 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/Makefile 2024-03-02 15:00:53.000000000 +0100 @@ -17,6 +17,8 @@ clean: $(MAKE) -C regression clean + # Clean extension put into root dir by --inplace + rm -f *.so flake: $(PYTHON) -m black --check $(BLACK_OPTIONS) nml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/PKG-INFO new/nml-0.7.5/PKG-INFO --- old/nml-0.7.4/PKG-INFO 2023-06-28 22:13:22.470080000 +0200 +++ new/nml-0.7.5/PKG-INFO 2024-03-02 15:01:15.859209800 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: nml -Version: 0.7.4 +Version: 0.7.5 Summary: An OpenTTD NewGRF compiler for the nml language Home-page: https://github.com/OpenTTD/nml Author: NML Development Team @@ -19,5 +19,7 @@ Classifier: Topic :: Software Development :: Compilers Requires-Python: >=3.5 License-File: LICENSE +Requires-Dist: Pillow>=3.4 +Requires-Dist: ply A tool to compile NewGRFs for OpenTTD from nml filesNML is a meta-language that aims to be a lot simpler to learn and use than nfo used traditionally to write NewGRFs. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/docs/changelog.txt new/nml-0.7.5/docs/changelog.txt --- old/nml-0.7.4/docs/changelog.txt 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/docs/changelog.txt 2024-03-02 15:00:53.000000000 +0100 @@ -1,3 +1,20 @@ +0.7.5 (2024-03-02) +------------------------------------------------------------------------ +This release restores compatibility for stations in OpenTTD <14. + +Support for NewGRF additions of OpenTTD 14: + - Change: add constants GROUNDSPRITE_ROAD_X and GROUNDSPRITE_ROAD_Y (#307) + - Add: Support for build probability action CB 162 var10 0 (reverse rail vehicle). (#313) + - Add: Support for faster ship speed 23 and acceleration 24 (#315) + - Add: Support town_production_effect and town_production_multiplier. (#318) + +Other changes and fixes: + - Fix: Register named parameters earlier (#301) + - Fix a9a1a3e: Don't use station properties 1C/1D for IDs 00-FF (#305) + - Change: Allow creating 32bpp-only NewGRFs (#314) + - Add: --no-palette-validation option to skip palette validation for sprites if the grf author doesn't need it (#322) + + 0.7.4 (2023-06-28) ------------------------------------------------------------------------ This release adds support for more strings and sloped one-way road markers. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/__version__.py new/nml-0.7.5/nml/__version__.py --- old/nml-0.7.4/nml/__version__.py 2023-06-28 22:13:22.000000000 +0200 +++ new/nml-0.7.5/nml/__version__.py 2024-03-02 15:01:15.000000000 +0100 @@ -1,2 +1,2 @@ # this file is autogenerated by setup.py -version = "0.7.4" +version = "0.7.5" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/actions/action0.py new/nml-0.7.5/nml/actions/action0.py --- old/nml-0.7.4/nml/actions/action0.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/actions/action0.py 2024-03-02 15:00:53.000000000 +0100 @@ -597,6 +597,14 @@ if "custom_function" in prop_info: props = prop_info["custom_function"](*value_list) else: + + def apply_threshold(value): + if not isinstance(value, tuple): + return value + assert len(value) == 3 + threshold, below, above = value + return below if id.value < threshold else above + # First process each element in the value_list final_values = [] for i, value in enumerate(value_list): @@ -629,10 +637,7 @@ raise generic.ScriptError( "String used as value for non-string property: " + str(prop_info["num"]), value.pos ) - string_range = prop_info["string"] - if isinstance(string_range, tuple): - threshold, below, above = string_range - string_range = below if id.value < threshold else above + string_range = apply_threshold(prop_info["string"]) stringid, string_actions = action4.get_string_action4s(feature, string_range, value, id) value = expression.ConstantNumeric(stringid) action_list_append.extend(string_actions) @@ -646,8 +651,9 @@ final_values.append(value) # Now, write a single Action0 Property with all of these values - if prop_info["num"] != -1: - props = [Action0Property(prop_info["num"], final_values, prop_info["size"])] + prop_num = apply_threshold(prop_info["num"]) + if prop_num != -1: + props = [Action0Property(prop_num, final_values, prop_info["size"])] else: props = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/actions/action0properties.py new/nml-0.7.5/nml/actions/action0properties.py --- old/nml-0.7.4/nml/actions/action0properties.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/actions/action0properties.py 2024-03-02 15:00:53.000000000 +0100 @@ -116,6 +116,7 @@ # 'string', if set, means that the value of the property should be a string. # The value of characteristic indicates the string range to use (usually 0xD0 or 0xDC) # If set to None, the string will use the ID of the item (used for vehicle names) +# It can also be a (threshold, below, above) tuple to select range depending on ID # # 'string_literal', if set, indicates that the value of the property should # be a literal (quoted) string. The value of the characteristic is equal to @@ -155,6 +156,7 @@ # 'num' is the Action0 property number of the action 0 property, as given by the # nfo specs. If set to -1, no action0 property will be generated. If # 'custom_function' is set, this value is not needed and can be left out. +# It can also be a (threshold, below, above) tuple to set 'num' depending on ID. # # 'size' is the size (in bytes) of the resulting action 0 property. Valid # values are 1 (byte), 2 (word) or 4 (dword). For other (or variable) sizes, @@ -542,19 +544,39 @@ return nmlop.SUB(255, value).reduce() +def ship_speed_prop(prop_info): + # prop 0B value is min(value, 255) + def prop0B_value(value): + return nmlop.MIN(value, 0xFF).reduce() + + # prop 23 value is min(value, 65535) + def prop23_value(value): + return nmlop.MIN(value, 0xFFFF).reduce() + + # prop 23 should not be set if value(prop0B_value) <= 255. + def prop23_test(value): + return isinstance(value, ConstantNumeric) and value.value >= 0xFF + + prop0B = {"size": 1, "num": 0x0B, "value_function": prop0B_value} + prop23 = {"size": 2, "num": 0x23, "value_function": prop23_value, "test_function": prop23_test} + for key in prop_info: + prop0B[key] = prop23[key] = prop_info[key] + return [prop0B, prop23] + + # fmt: off properties[0x02] = { **general_veh_props, "sprite_id": {"size": 1, "num": 0x08}, "is_refittable": {"size": 1, "num": 0x09}, "cost_factor": {"size": 1, "num": 0x0A}, - "speed": { - "size": 1, - "num": 0x0B, - "unit_type": "speed", - "unit_conversion": (10000, 1397), - "adjust_value": lambda val, unit: ottd_display_speed(val, 1, 2, unit), - }, + "speed": ship_speed_prop( + { + "unit_type": "speed", + "unit_conversion": (10000, 1397), + "adjust_value": lambda val, unit: ottd_display_speed(val, 1, 2, unit), + } + ), "default_cargo_type": {"size": 1, "num": 0x0C}, "cargo_capacity": {"size": 2, "num": 0x0D}, # 0E does not exist @@ -595,6 +617,7 @@ ], "variant_group": {"size": 2, "num": 0x20}, "extra_flags": {"size": 4, "num": 0x21}, + "acceleration": {"size": 1, "num": 0x24}, } # fmt: on @@ -706,8 +729,8 @@ # 19 (road routing) reserved for future use # 1A (advanced sprite layout) is implemented elsewhere # 1B (minimum bridge height) JGR only - "name": {"size": 2, "num": 0x1C, "string": (256, 0xC5, 0xDC), "required": True}, - "classname": {"size": 2, "num": 0x1D, "string": 0xDC}, + "name": {"size": 2, "num": (256, -1, 0x1C), "string": (256, 0xC5, 0xDC), "required": True}, + "classname": {"size": 2, "num": (256, -1, 0x1D), "string": (256, 0xC4, 0xDC)}, } # fmt: on @@ -1240,6 +1263,8 @@ "units_of_cargo": {"num": 0x1B, "size": 2, "string": 0xDC}, "items_of_cargo": {"num": 0x1C, "size": 2, "string": 0xDC}, "capacity_multiplier": {"num": 0x1D, "size": 2, "unit_conversion": 0x100}, + "town_production_effect": {"num": 0x1E, "size": 1}, + "town_production_multiplier": {"num": 0x1F, "size": 2, "unit_conversion": 0x100}, } # fmt: on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/actions/action3_callbacks.py new/nml-0.7.5/nml/actions/action3_callbacks.py --- old/nml-0.7.4/nml/actions/action3_callbacks.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/actions/action3_callbacks.py 2024-03-02 15:00:53.000000000 +0100 @@ -71,6 +71,7 @@ 'cargo_age_period' : {'type': 'cb', 'num': 0x36, 'var10': 0x2B}, 'curve_speed_mod' : {'type': 'cb', 'num': 0x36, 'var10': 0x2E}, 'create_effect' : {'type': 'cb', 'num': 0x160}, + 'reverse_build_probability' : {'type': 'cb', 'num': 0x162, 'var10': 0x00}, } callbacks[0x00].update(general_vehicle_cbs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/actions/actionD.py new/nml-0.7.5/nml/actions/actionD.py --- old/nml-0.7.4/nml/actions/actionD.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/actions/actionD.py 2024-03-02 15:00:53.000000000 +0100 @@ -91,16 +91,9 @@ self.param = param self.value = value - def pre_process(self): - self.value = self.value.reduce(global_constants.const_list) - + def register_names(self): self.param = self.param.reduce(global_constants.const_list, unknown_id_fatal=False) - if isinstance(self.param, expression.SpecialParameter): - if not self.param.can_assign(): - raise generic.ScriptError( - "Trying to assign a value to the read-only variable '{}'".format(self.param.name), self.param.pos - ) - elif isinstance(self.param, expression.Identifier): + if isinstance(self.param, expression.Identifier): if global_constants.identifier_refcount[self.param.value] == 0: generic.print_warning( generic.Warning.OPTIMISATION, @@ -110,6 +103,17 @@ return num = action6.free_parameters.pop_unique(self.pos) global_constants.named_parameters[self.param.value] = num + + def pre_process(self): + self.value = self.value.reduce(global_constants.const_list) + + if isinstance(self.param, expression.SpecialParameter): + if not self.param.can_assign(): + raise generic.ScriptError( + "Trying to assign a value to the read-only variable '{}'".format(self.param.name), self.param.pos + ) + elif isinstance(self.param, expression.Identifier): + return elif not isinstance(self.param, expression.Parameter): raise generic.ScriptError("Left side of an assignment must be a parameter.", self.param.pos) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/ast/alt_sprites.py new/nml-0.7.5/nml/ast/alt_sprites.py --- old/nml-0.7.4/nml/ast/alt_sprites.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/ast/alt_sprites.py 2024-03-02 15:00:53.000000000 +0100 @@ -13,28 +13,9 @@ with NML; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.""" -from nml import expression, generic +from nml import expression, generic, global_constants from nml.ast import base_statement, sprite_container -""" -Store if there are any 32bpp sprites, -if so ask to enable the 32bpp blitter via action14 -""" -any_32bpp_sprites = False - -zoom_levels = { - "ZOOM_LEVEL_NORMAL": 0, - "ZOOM_LEVEL_IN_4X": 1, - "ZOOM_LEVEL_IN_2X": 2, - "ZOOM_LEVEL_OUT_2X": 3, - "ZOOM_LEVEL_OUT_4X": 4, - "ZOOM_LEVEL_OUT_8X": 5, -} -allow_extra_zoom = True - -bit_depths = {"BIT_DEPTH_8BPP": 8, "BIT_DEPTH_32BPP": 32.0} -allow_32bpp = True - class AltSpritesBlock(base_statement.BaseStatement): """ @@ -73,22 +54,21 @@ if not isinstance(self.name, expression.Identifier): raise generic.ScriptError("alternative_sprites parameter 1 'name' must be an identifier", self.name.pos) - if isinstance(param_list[1], expression.Identifier) and param_list[1].value in zoom_levels: - self.zoom_level = zoom_levels[param_list[1].value] + if isinstance(param_list[1], expression.Identifier) and param_list[1].value in global_constants.zoom_levels: + self.zoom_level = global_constants.zoom_levels[param_list[1].value] else: raise generic.ScriptError( "value for alternative_sprites parameter 2 'zoom level' is not a valid zoom level", param_list[1].pos ) - if isinstance(param_list[2], expression.Identifier) and param_list[2].value in bit_depths: - self.bit_depth = bit_depths[param_list[2].value] + if isinstance(param_list[2], expression.Identifier) and param_list[2].value in global_constants.bit_depths: + self.bit_depth = global_constants.bit_depths[param_list[2].value] else: raise generic.ScriptError( "value for alternative_sprites parameter 3 'bit depth' is not a valid bit depthl", param_list[2].pos ) - global any_32bpp_sprites if self.bit_depth == 32: - any_32bpp_sprites = allow_32bpp + global_constants.any_32bpp_sprites = global_constants.allow_32bpp if len(param_list) >= 4: self.image_file = param_list[3].reduce() @@ -113,7 +93,9 @@ self.sprite_list = sprite_list def pre_process(self): - if (self.bit_depth == 32 and not allow_32bpp) or (self.zoom_level != 0 and not allow_extra_zoom): + if (self.bit_depth == 32 and not global_constants.allow_32bpp) or ( + self.zoom_level != 0 and not global_constants.allow_extra_zoom + ): return block = sprite_container.SpriteContainer.resolve_sprite_block(self.name) block.add_sprite_data( @@ -140,8 +122,8 @@ def __str__(self): params = [ self.name, - generic.reverse_lookup(zoom_levels, self.zoom_level), - generic.reverse_lookup(bit_depths, self.bit_depth), + generic.reverse_lookup(global_constants.zoom_levels, self.zoom_level), + generic.reverse_lookup(global_constants.bit_depths, self.bit_depth), ] if self.image_file is not None: params.append(self.image_file) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/ast/spriteblock.py new/nml-0.7.5/nml/ast/spriteblock.py --- old/nml-0.7.4/nml/ast/spriteblock.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/ast/spriteblock.py 2024-03-02 15:00:53.000000000 +0100 @@ -87,26 +87,62 @@ class SpriteSet(spriteset_base_class, sprite_container.SpriteContainer): def __init__(self, param_list, sprite_list, pos): base_statement.BaseStatement.__init__(self, "spriteset", pos, False, False) - if not (1 <= len(param_list) <= 2): - raise generic.ScriptError("Spriteset requires 1 or 2 parameters, encountered " + str(len(param_list)), pos) + if not (1 <= len(param_list) <= 5): + raise generic.ScriptError("Spriteset requires 1 to 5 parameters, encountered " + str(len(param_list)), pos) name = param_list[0] if not isinstance(name, expression.Identifier): raise generic.ScriptError("Spriteset parameter 1 'name' should be an identifier", name.pos) sprite_container.SpriteContainer.__init__(self, "spriteset", name) self.initialize(name) + self.zoom_level = 0 + self.bit_depth = 8 + self.image_file = None + + if len(param_list) >= 3: + if isinstance(param_list[1], expression.Identifier) and param_list[1].value in global_constants.zoom_levels: + self.zoom_level = global_constants.zoom_levels[param_list[1].value] + else: + raise generic.ScriptError( + "value for Spriteset-block parameter 2 'zoom level' is not a valid zoom level", param_list[1].pos + ) + if isinstance(param_list[2], expression.Identifier) and param_list[2].value in global_constants.bit_depths: + self.bit_depth = global_constants.bit_depths[param_list[2].value] + else: + raise generic.ScriptError( + "value for Spriteset-block parameter 3 'bit depth' is not a valid bit depth", param_list[2].pos + ) - if len(param_list) >= 2: + if len(param_list) >= 4: + self.image_file = param_list[3].reduce() + if not isinstance(self.image_file, expression.StringLiteral): + raise generic.ScriptError( + "Spriteset-block parameter 4 'file' must be a string literal", self.image_file.pos + ) + elif len(param_list) >= 2: self.image_file = param_list[1].reduce() if not isinstance(self.image_file, expression.StringLiteral): raise generic.ScriptError( "Spriteset-block parameter 2 'file' must be a string literal", self.image_file.pos ) + + if self.bit_depth == 32: + global_constants.any_32bpp_sprites = global_constants.allow_32bpp + + if len(param_list) >= 5: + self.mask_file = param_list[4].reduce() + if not isinstance(self.mask_file, expression.StringLiteral): + raise generic.ScriptError( + "Spriteset-block parameter 5 'mask_file' must be a string literal", self.mask_file.pos + ) + if not self.bit_depth == 32: + raise generic.ScriptError("A mask file may only be specified for 32 bpp sprites.", self.mask_file.pos) else: - self.image_file = None + self.mask_file = None + self.sprite_list = sprite_list self.action1_num = None # set number in action1 self.labels = {} # mapping of real sprite labels to offsets - self.add_sprite_data(self.sprite_list, self.image_file, pos) + self.add_sprite_data(self.sprite_list, self.image_file, pos, self.zoom_level, self.bit_depth, self.mask_file) def pre_process(self): spriteset_base_class.pre_process(self) @@ -137,8 +173,16 @@ return [] def __str__(self): - filename = (", " + str(self.image_file)) if self.image_file is not None else "" - ret = "spriteset({}{}) {{\n".format(self.name, filename) + params = [ + self.name, + generic.reverse_lookup(global_constants.zoom_levels, self.zoom_level), + generic.reverse_lookup(global_constants.bit_depths, self.bit_depth), + ] + if self.image_file is not None: + params.append(self.image_file) + if self.mask_file is not None: + params.append(self.mask_file) + ret = "spriteset({}) {{\n".format(", ".join(str(p) for p in params)) for sprite in self.sprite_list: ret += "\t{}\n".format(str(sprite)) ret += "}\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/global_constants.py new/nml-0.7.5/nml/global_constants.py --- old/nml-0.7.4/nml/global_constants.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/global_constants.py 2024-03-02 15:00:53.000000000 +0100 @@ -347,6 +347,8 @@ # ground sprite IDs "GROUNDSPRITE_RAIL_Y" : 1011, "GROUNDSPRITE_RAIL_X" : 1012, + "GROUNDSPRITE_ROAD_Y" : 1332, + "GROUNDSPRITE_ROAD_X" : 1333, "GROUNDSPRITE_CONCRETE" : 1420, "GROUNDSPRITE_CLEARED" : 3924, "GROUNDSPRITE_GRASS_1_3" : 3943, @@ -905,6 +907,11 @@ "TOWNGROWTH_FOOD" : 0x0B, "TOWNGROWTH_NONE" : 0xFF, + # Town production effect on cargo + "TOWNPRODUCTION_PASSENGERS" : 0x00, + "TOWNPRODUCTION_MAIL" : 0x02, + "TOWNPRODUCTION_NONE" : 0xFF, + # Cargo callbacks "CARGO_CB_PROFIT" : 0x01, "CARGO_CB_STATION_RATING" : 0x02, @@ -1407,6 +1414,27 @@ named_parameters = {} spritegroups = {"CB_FAILED": "CB_FAILED"} +zoom_levels = { + "ZOOM_LEVEL_NORMAL": 0, + "ZOOM_LEVEL_IN_4X": 1, + "ZOOM_LEVEL_IN_2X": 2, + "ZOOM_LEVEL_OUT_2X": 3, + "ZOOM_LEVEL_OUT_4X": 4, + "ZOOM_LEVEL_OUT_8X": 5, +} + +bit_depths = {"BIT_DEPTH_8BPP": 8, "BIT_DEPTH_32BPP": 32.0} + +""" +Store if there are any 32bpp sprites, +if so ask to enable the 32bpp blitter via action14 +""" +any_32bpp_sprites = False + +allow_extra_zoom = True + +allow_32bpp = True + const_list = [ (constant_numbers, constant_number), (global_parameters, param_from_info), @@ -1422,6 +1450,8 @@ (config_flags, config_flag), (unified_maglev_var, unified_maglev), (spritegroups, create_spritegroup_ref), + zoom_levels, + bit_depths, ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml/main.py new/nml-0.7.5/nml/main.py --- old/nml-0.7.4/nml/main.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/nml/main.py 2024-03-02 15:00:53.000000000 +0100 @@ -47,7 +47,7 @@ real_sprite, sprite_count, ) -from nml.ast import alt_sprites, grf +from nml.ast import grf try: from PIL import Image @@ -89,6 +89,7 @@ debug_parser=False, allow_extra_zoom=True, allow_32bpp=True, + disable_palette_validation=False, ) opt_parser.add_option("-d", "--debug", action="store_true", dest="debug", help="write the AST to stdout") opt_parser.add_option("-s", "--stack", action="store_true", dest="stack", help="Dump stack when an error occurs") @@ -224,6 +225,12 @@ "--no-extra-zoom", action="store_false", dest="allow_extra_zoom", help="Skip extra zoom alternative sprites" ) opt_parser.add_option("--no-32bpp", action="store_false", dest="allow_32bpp", help="Skip 32bpp alternative sprites") + opt_parser.add_option( + "--no-palette-validation", + action="store_true", + dest="disable_palette_validation", + help="Disable palette validation for sprites", + ) opts, args = opt_parser.parse_args(argv) @@ -231,8 +238,8 @@ generic.Warning.disabled = opts.disable_warning generic.set_cache_root_dir(None if opts.no_cache else opts.cache_dir) spritecache.keep_orphaned = opts.keep_orphaned - alt_sprites.allow_extra_zoom = opts.allow_extra_zoom - alt_sprites.allow_32bpp = opts.allow_32bpp + global_constants.allow_extra_zoom = opts.allow_extra_zoom + global_constants.allow_32bpp = opts.allow_32bpp opts.outputfile_given = ( opts.grf_filename or opts.nfo_filename or opts.nml_filename or opts.dep_filename or opts.outputs @@ -348,6 +355,7 @@ opts.md5_filename, opts.rebuild_parser, opts.debug_parser, + opts.disable_palette_validation, ) input.close() @@ -370,6 +378,7 @@ md5_filename, rebuild_parser, debug_parser, + disable_palette_validation, ): """ Compile an NML file. @@ -513,40 +522,47 @@ generic.print_error("PIL (python-imaging) wasn't found, no support for using graphics") sys.exit(3) - generic.print_progress("Checking palette of source images ...") - used_palette = forced_palette - last_file = None - for f_pair in sprite_files: - # Palette is defined by mask_file, if present. Otherwise by the main file. - f = f_pair[1] - if f is None: - f = f_pair[0] - - try: - with Image.open(generic.find_file(f)) as im: - # Verify the image is running in Palette mode, if not, skip this file. - if im.mode != "P": - continue - pal = palette.validate_palette(im, f) - except IOError as ex: - raise generic.ImageError(str(ex), f) - - if forced_palette != "ANY" and pal != forced_palette and not (forced_palette == "DEFAULT" and pal == "LEGACY"): - raise generic.ImageError( - "Image has '{}' palette, but you forced the '{}' palette".format(pal, used_palette), f - ) - if used_palette == "ANY": - used_palette = pal - elif pal != used_palette: - if used_palette in ("LEGACY", "DEFAULT") and pal in ("LEGACY", "DEFAULT"): - used_palette = "DEFAULT" - else: + if not disable_palette_validation: + generic.print_progress("Checking palette of source images ...") + + last_file = None + for f_pair in sprite_files: + # Palette is defined by mask_file, if present. Otherwise by the main file. + f = f_pair[1] + if f is None: + f = f_pair[0] + + try: + with Image.open(generic.find_file(f)) as im: + # Verify the image is running in Palette mode, if not, skip this file. + if im.mode != "P": + continue + pal = palette.validate_palette(im, f) + except IOError as ex: + raise generic.ImageError(str(ex), f) + + if ( + forced_palette != "ANY" + and pal != forced_palette + and not (forced_palette == "DEFAULT" and pal == "LEGACY") + ): raise generic.ImageError( - "Image has '{}' palette, but \"{}\" has the '{}' palette".format(pal, last_file, used_palette), f + "Image has '{}' palette, but you forced the '{}' palette".format(pal, used_palette), f ) - last_file = f + + if used_palette == "ANY": + used_palette = pal + elif pal != used_palette: + if used_palette in ("LEGACY", "DEFAULT") and pal in ("LEGACY", "DEFAULT"): + used_palette = "DEFAULT" + else: + raise generic.ImageError( + "Image has '{}' palette, but \"{}\" has the '{}' palette".format(pal, last_file, used_palette), + f, + ) + last_file = f palette_bytes = {"LEGACY": "W", "DEFAULT": "D", "ANY": "A"} if used_palette in palette_bytes: @@ -566,7 +582,7 @@ encoder.open(sprite_files) # If there are any 32bpp sprites hint to openttd that we'd like a 32bpp blitter - if alt_sprites.any_32bpp_sprites: + if global_constants.any_32bpp_sprites: grf.set_preferred_blitter("3") generic.print_progress("Linking actions ...") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml.egg-info/PKG-INFO new/nml-0.7.5/nml.egg-info/PKG-INFO --- old/nml-0.7.4/nml.egg-info/PKG-INFO 2023-06-28 22:13:22.000000000 +0200 +++ new/nml-0.7.5/nml.egg-info/PKG-INFO 2024-03-02 15:01:15.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: nml -Version: 0.7.4 +Version: 0.7.5 Summary: An OpenTTD NewGRF compiler for the nml language Home-page: https://github.com/OpenTTD/nml Author: NML Development Team @@ -19,5 +19,7 @@ Classifier: Topic :: Software Development :: Compilers Requires-Python: >=3.5 License-File: LICENSE +Requires-Dist: Pillow>=3.4 +Requires-Dist: ply A tool to compile NewGRFs for OpenTTD from nml filesNML is a meta-language that aims to be a lot simpler to learn and use than nfo used traditionally to write NewGRFs. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/nml.egg-info/SOURCES.txt new/nml-0.7.5/nml.egg-info/SOURCES.txt --- old/nml-0.7.4/nml.egg-info/SOURCES.txt 2023-06-28 22:13:22.000000000 +0200 +++ new/nml-0.7.5/nml.egg-info/SOURCES.txt 2024-03-02 15:01:15.000000000 +0100 @@ -209,6 +209,7 @@ regression/038_optimised_scope.nml regression/039_storage.nml regression/040_station.nml +regression/041_articulated_tram_32bpp.nml regression/Makefile regression/arctic_railwagons.pcx regression/beef.wav @@ -224,6 +225,7 @@ regression/opengfx_trains_start.pcx regression/station.png regression/temperate_railwagons.png +regression/tram_foster_express.32.png regression/tram_foster_express.png regression/expected/001_action8.grf regression/expected/001_action8.nfo @@ -305,6 +307,8 @@ regression/expected/039_storage.nfo regression/expected/040_station.grf regression/expected/040_station.nfo +regression/expected/041_articulated_tram_32bpp.grf +regression/expected/041_articulated_tram_32bpp.nfo regression/expected/example_industry.grf regression/expected/example_industry.nfo regression/expected/example_object.grf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/040_station.nml new/nml-0.7.5/regression/040_station.nml --- old/nml-0.7.4/regression/040_station.nml 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/regression/040_station.nml 2024-03-02 15:00:53.000000000 +0100 @@ -103,7 +103,7 @@ } } -item (FEAT_STATIONS, basic_station) { +item (FEAT_STATIONS, basic_station, 255) { property { class : "TEST"; classname: string(STR_STATION_TEST_CLASS); @@ -128,7 +128,7 @@ } } -item (FEAT_STATIONS, basic_station_copied_layout) { +item (FEAT_STATIONS, basic_station_copied_layout, 256) { property { class : "TEST"; classname: string(STR_STATION_TEST_CLASS); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/041_articulated_tram_32bpp.nml new/nml-0.7.5/regression/041_articulated_tram_32bpp.nml --- old/nml-0.7.4/regression/041_articulated_tram_32bpp.nml 1970-01-01 01:00:00.000000000 +0100 +++ new/nml-0.7.5/regression/041_articulated_tram_32bpp.nml 2024-03-02 15:00:53.000000000 +0100 @@ -0,0 +1,63 @@ +/* +A simple articulated tram, graphics from OpenGFX+rv +Code is modified in some places for testing reasons. +*/ + +grf { + grfid: "NML\41"; + name: string(STR_REGRESSION_NAME); + desc: string(STR_REGRESSION_DESC); + version: 0; + min_compatible_version: 0; +} + +template tmpl_tram(x, y) { + [ x, y, 8, 18, -3, -10] + [ 16 + x, y, 20, 18, -14, -5] + [ 48 + x, y, 28, 15, -14, -8] + [ 96 + x, y, 20, 18, -6, -7] + [128 + x, y, 8, 18, -3, -10] + [144 + x, y, 20, 18, -14, -9] + [176 + x, y, 28, 15, -14, -8] + [224 + x, y, 20, 18, -6, -7] +} +spriteset(foster_express_set, ZOOM_LEVEL_NORMAL, BIT_DEPTH_32BPP, "tram_foster_express.32.png") { + tmpl_tram(48,1) +} + +switch(FEAT_ROADVEHS, SELF, foster_express_articulated_parts, extra_callback_info1) { + 1..3: return foster_express_tram; + return 0xFF; +} + + +item(FEAT_ROADVEHS, foster_express_tram, 88) { + property { + name: string(STR_NAME_FOSTER_TURBO_TRAM); + climates_available: ALL_CLIMATES; + model_life: 40; // years + vehicle_life: 30; // years + introduction_date: date(1965,1,1); + reliability_decay: 1; + running_cost_base: RUNNING_COST_ROADVEH; // Default road vehicle running cost base + running_cost_factor: 135; + cost_factor: 143; + speed: 317 mph; + power: 220 hp; + weight: 22 ton; + sprite_id: SPRITE_ID_NEW_ROADVEH; // We have our own sprites + loading_speed: 16; // loading speed + tractive_effort_coefficient: 0.3; + air_drag_coefficient: 0.5; + cargo_capacity: 45; // passengers + refittable_cargo_classes: bitmask(CC_PASSENGERS); // Allow passengers (and tourists) + non_refittable_cargo_classes: NO_CARGO_CLASS; // Disallow other cargos + cargo_allow_refit: []; + default_cargo_type: DEFAULT_CARGO_FIRST_REFITTABLE; + misc_flags: bitmask(ROADVEH_FLAG_TRAM); // This is a tram + } + graphics { + articulated_part: foster_express_articulated_parts; + foster_express_set; + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/Makefile new/nml-0.7.5/regression/Makefile --- old/nml-0.7.4/regression/Makefile 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/regression/Makefile 2024-03-02 15:00:53.000000000 +0100 @@ -50,4 +50,4 @@ $(_V) diff expected/[email protected] output2/[email protected] clean: - $(_V) rm -rf output nml_output output2 + $(_V) rm -rf output nml_output output2 .nmlcache Binary files old/nml-0.7.4/regression/expected/040_station.grf and new/nml-0.7.5/regression/expected/040_station.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/expected/040_station.nfo new/nml-0.7.5/regression/expected/040_station.nfo --- old/nml-0.7.4/regression/expected/040_station.nfo 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/regression/expected/040_station.nfo 2024-03-02 15:00:53.000000000 +0100 @@ -16,40 +16,40 @@ 00 00 2 * 52 08 08 "NML\40" "NML regression test" 00 "A test newgrf testing NML" 00 -3 * 11 04 04 FF 01 \wxDC00 "Test" 00 +3 * 27 04 04 FF 02 \wxDC00 "Test" 00 "Basic station 2" 00 4 * 16 00 08 \b1 02 FF \wx0000 09 "COAL" "LVST" -5 * 27 00 04 \b6 01 FF \wx0000 +5 * 21 00 04 \b4 01 FF \wx00FF 08 "TEST" -1D \wxDC00 -1C \wxC500 13 18 12 \dx00000002 0C F0 -6 * 20 04 04 FF 01 \wxC500 "Basic station" 00 +6 * 11 04 04 FF 01 \wxC4FF "Test" 00 + +7 * 20 04 04 FF 01 \wxC5FF "Basic station" 00 -7 * 6 01 04 \b2 FF \wx0002 +8 * 6 01 04 \b2 FF \wx0002 -8 station.png 8bpp 1 1 5 5 -2 -2 normal -9 station.png 8bpp 7 1 5 5 -2 -2 normal +9 station.png 8bpp 1 1 5 5 -2 -2 normal +10 station.png 8bpp 7 1 5 5 -2 -2 normal -10 station.png 8bpp 2 2 3 3 -1 -1 normal -11 station.png 8bpp 8 2 3 3 -1 -1 normal +11 station.png 8bpp 2 2 3 3 -1 -1 normal +12 station.png 8bpp 8 2 3 3 -1 -1 normal // Name: station_spriteset - feature 04 -12 * 7 02 04 FF \b0 \b1 +13 * 7 02 04 FF \b0 \b1 \w0 // Name: station_spriteset2 - feature 04 -13 * 7 02 04 FE \b0 \b1 +14 * 7 02 04 FE \b0 \b1 \w1 -14 * 114 00 04 \b1 01 FF \wx0000 +15 * 114 00 04 \b1 01 FF \wx00FF 1A \b2 \b68 \dx000003F4 \wx0000 \dx0000842E \wx0000 \b0 \b0 \b0 \b16 \b5 \b2 @@ -62,9 +62,9 @@ \dx0000842D \wx0000 \b11 \b0 \b0 \b5 \b16 \b2 \dx8000842D \wx0042 \b20 \b10 80 84 03 -// Name: Station Layout@registers - Id 00 +// Name: Station Layout@registers - Id FF // a : register 80 -15 * 77 02 04 FD 89 +16 * 77 02 04 FD 89 1A 20 \dx00000000 \2sto 1A 20 \dx00000081 \2r 1A 20 \dx00000000 @@ -78,8 +78,8 @@ \b0 \wx8000 // Return computed value -// Name: Station Layout@prepare - Id 00 -16 * 34 02 04 FC 89 +// Name: Station Layout@prepare - Id FF +17 * 34 02 04 FC 89 1A 20 \dx00000000 \2sto 1A 20 \dx00000000 \2r 1A 20 \dx00000001 @@ -88,9 +88,9 @@ \wx8000 // Return computed value // Name: @action3_0 -17 * 49 02 04 FB 89 -7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id 00 -\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id 00 +18 * 49 02 04 FB 89 +7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id FF +\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id FF \2r 10 00 \dx000000FF \b2 \wx8000 \dx00000002 \dx00000002 // return 0; @@ -98,9 +98,9 @@ \wx00FF // station_spriteset; // Name: @action3_1 -18 * 49 02 04 FA 89 -7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id 00 -\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id 00 +19 * 49 02 04 FA 89 +7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id FF +\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id FF \2r 10 00 \dx000000FF \b2 \wx00FF \dx00000001 \dx00000001 // station_spriteset; @@ -108,9 +108,9 @@ \wx00FE // station_spriteset2; // Name: @action3_2 -19 * 49 02 04 FC 89 -7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id 00 -\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id 00 +20 * 49 02 04 FC 89 +7E FC 20 \dxFFFFFFFF // Station Layout@prepare - Id FF +\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id FF \2r 10 00 \dx000000FF \b2 \wx8000 \dx00000002 \dx00000002 // return 0; @@ -118,42 +118,42 @@ \wx00FF // station_spriteset; // Name: @action3_3 -20 * 55 02 04 F9 89 +21 * 55 02 04 F9 89 1A 20 \dx00000003 \2sto 1A 20 \dx00000003 -\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id 00 +\2r 7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id FF \2r 10 00 \dx000000FF \b2 \wx8000 \dx00000002 \dx00000002 // return 0; \wx00FE \dx00000003 \dx00000003 // station_spriteset2; \wx00FF // station_spriteset; -21 * 9 00 04 \b1 01 FF \wx0000 +22 * 9 00 04 \b1 01 FF \wx00FF 0B 08 // Name: @return_action_0 -22 * 20 02 04 F8 89 +23 * 20 02 04 F8 89 43 38 \dx0000000F \2+ 43 1C \dx0000000F \b0 \wx8000 // Return computed value // Name: @action3_4 -23 * 23 02 04 F8 89 +24 * 23 02 04 F8 89 0C 00 \dx0000FFFF \b1 \wx00F8 \dx00000142 \dx00000142 // return (var[0x43, 24, 15] + var[0x43, 28, 15]) \wx00FB // @action3_0; // Name: @return_action_1 -24 * 20 02 04 F7 89 +25 * 20 02 04 F7 89 43 38 \dx0000000F \2+ 43 1C \dx0000000F \b0 \wx8000 // Return computed value // Name: @action3_5 -25 * 33 02 04 F7 89 +26 * 33 02 04 F7 89 0C 00 \dx0000FFFF \b2 \wx00FA \dx00000000 \dx00000000 // @action3_1; @@ -161,35 +161,33 @@ \wx00FB // @action3_0; // Name: @return_action_2 -26 * 20 02 04 FA 89 +27 * 20 02 04 FA 89 43 38 \dx0000000F \2+ 43 1C \dx0000000F \b0 \wx8000 // Return computed value // Name: @action3_6 -27 * 33 02 04 FB 89 +28 * 33 02 04 FB 89 0C 00 \dx0000FFFF \b2 \wx00FC \dx00000000 \dx00000000 // @action3_2; \wx00FA \dx00000142 \dx00000142 // return (var[0x43, 24, 15] + var[0x43, 28, 15]) \wx00FB // @action3_0; -28 * 16 03 04 01 00 \b3 +29 * 18 03 04 01 FF \wx00FF \b3 00 \wx00F7 // @action3_5; 01 \wx00FB // @action3_6; FF \wx00F9 // @action3_3; \wx00F8 // @action3_4; -29 * 18 00 04 \b3 01 FF \wx0001 +30 * 18 00 04 \b3 01 FF \wx0100 08 "TEST" 1D \wxDC00 -1C \wxC501 - -30 * 22 04 04 FF 01 \wxC501 "Basic station 2" 00 +1C \wxDC01 -31 * 9 00 04 \b1 01 FF \wx0001 -0A 00 +31 * 9 00 04 \b1 01 FF \wx0100 +0A FF // Name: @CB_FAILED_REAL04 32 * 7 02 04 F8 \b0 \b1 @@ -205,13 +203,13 @@ // Name: @action3_7 34 * 41 02 04 F8 89 -7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id 00 +7E FD 20 \dxFFFFFFFF // Station Layout@registers - Id FF \2r 10 00 \dx000000FF \b2 \wx00FF \dx00000001 \dx00000001 // station_spriteset; \wx00FE \dx00000003 \dx00000003 // station_spriteset2; \wx00F8 // @CB_FAILED04; -35 * 7 03 04 01 01 \b0 +35 * 9 03 04 01 FF \wx0100 \b0 \wx00F8 // @action3_7; Binary files old/nml-0.7.4/regression/expected/041_articulated_tram_32bpp.grf and new/nml-0.7.5/regression/expected/041_articulated_tram_32bpp.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/expected/041_articulated_tram_32bpp.nfo new/nml-0.7.5/regression/expected/041_articulated_tram_32bpp.nfo --- old/nml-0.7.4/regression/expected/041_articulated_tram_32bpp.nfo 1970-01-01 01:00:00.000000000 +0100 +++ new/nml-0.7.5/regression/expected/041_articulated_tram_32bpp.nfo 2024-03-02 15:00:53.000000000 +0100 @@ -0,0 +1,83 @@ +// Automatically generated by GRFCODEC. Do not modify! +// (Info version 32) +// Escapes: 2+ 2- 2< 2> 2u< 2u> 2/ 2% 2u/ 2u% 2* 2& 2| 2^ 2sto = 2s 2rst = 2r 2psto 2ror = 2rot 2cmp 2ucmp 2<< 2u>> 2>> +// Escapes: 71 70 7= 7! 7< 7> 7G 7g 7gG 7GG 7gg 7c 7C +// Escapes: D= = DR D+ = DF D- = DC Du* = DM D* = DnF Du<< = DnC D<< = DO D& D| Du/ D/ Du% D% +// Format: spritenum imagefile depth xpos ypos xsize ysize xrel yrel zoom flags + +0 * 4 \d18 + +1 * 54 14 "C" "INFO" +"B" "VRSN" \w4 \dx00000000 +"B" "MINV" \w4 \dx00000000 +"B" "NPAR" \w1 00 +"B" "PALS" \w1 "A" +"B" "BLTR" \w1 "3" +00 +00 +2 * 52 08 08 "NML\41" "NML regression test" 00 "A test newgrf testing NML" 00 +// Name: foster_express_articulated_parts +3 * 23 02 01 FF 89 +10 00 \dxFFFFFFFF +\b1 +\wx8058 \dx00000001 \dx00000003 // 1 .. 3: return 88; +\wx80FF // default: return 255; + +4 * 74 00 01 \b25 01 FF \wx0058 +06 0F +04 28 +03 1E +1F \dx000AF386 +02 01 +0A \dx00004C48 +09 87 +11 8F +08 FF +15 FE +13 16 +14 58 +0E FF +07 10 +18 4D +19 80 +0F 2D +1D \wx0001 +16 \dx00000000 +1E \wx0000 +16 \dx00000000 +24 \b0 +16 \dx00000000 +10 FF +1C 01 + +5 * 25 04 01 7F 01 FF \wx0058 "Foster Turbo Tram" 00 + +6 * 6 01 01 \b1 FF \wx0008 + +7 tram_foster_express.32.png 32bpp 48 1 8 18 -3 -10 normal +8 tram_foster_express.32.png 32bpp 64 1 20 18 -14 -5 normal +9 tram_foster_express.32.png 32bpp 96 1 28 15 -14 -8 normal +10 tram_foster_express.32.png 32bpp 144 1 20 18 -6 -7 normal +11 tram_foster_express.32.png 32bpp 176 1 8 18 -3 -10 normal +12 tram_foster_express.32.png 32bpp 192 1 20 18 -14 -9 normal +13 tram_foster_express.32.png 32bpp 224 1 28 15 -14 -8 normal +14 tram_foster_express.32.png 32bpp 272 1 20 18 -6 -7 normal + +// Name: foster_express_set - feature 01 +15 * 9 02 01 FE \b1 \b1 +\w0 +\w0 + +16 * 9 00 01 \b1 01 FF \wx0058 +17 10 + +// Name: @action3_0 +17 * 23 02 01 FE 89 +0C 00 \dx0000FFFF +\b1 +\wx00FF \dx00000016 \dx00000016 // foster_express_articulated_parts; +\wx00FE // foster_express_set; + +18 * 9 03 01 01 FF \wx0058 \b0 +\wx00FE // @action3_0; + Binary files old/nml-0.7.4/regression/expected/example_station.grf and new/nml-0.7.5/regression/expected/example_station.grf differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/regression/expected/example_station.nfo new/nml-0.7.5/regression/expected/example_station.nfo --- old/nml-0.7.4/regression/expected/example_station.nfo 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/regression/expected/example_station.nfo 2024-03-02 15:00:53.000000000 +0100 @@ -16,59 +16,57 @@ 00 00 2 * 193 08 08 "NML\06" "NML Example NewGRF: Station" 00 "\8ENML Example NewGRF: Station\0D\98This NewGRF is intended to provide a coding example for the high-level NewGRF-coding language NML.\0DConversion of CHIPS Cow pens." 00 -3 * 18 04 04 FF 01 \wxDC00 "NML Example" 00 - // param[126] = param[161] -4 * 5 0D 7E \D= A1 00 +3 * 5 0D 7E \D= A1 00 // param[127] = (param[126] - 302012611) -5 * 9 0D 7F \D- 7E FF \dx120058C3 +4 * 9 0D 7F \D- 7E FF \dx120058C3 // param[127] = (param[127] << -31) -6 * 9 0D 7F \Du<< 7F FF \dxFFFFFFE1 +5 * 9 0D 7F \Du<< 7F FF \dxFFFFFFE1 -7 * 9 09 7F 04 \7= \dx00000000 01 +6 * 9 09 7F 04 \7= \dx00000000 01 -8 * 19 0B 03 7F 06 "1.2.0 (r22723)" 00 +7 * 19 0B 03 7F 06 "1.2.0 (r22723)" 00 -9 * 12 00 08 \b1 01 FF \wx0000 +8 * 12 00 08 \b1 01 FF \wx0000 09 "LVST" -10 * 6 01 04 \b3 FF \wx0002 +9 * 6 01 04 \b3 FF \wx0002 -11 cows_cargo.png 8bpp 10 10 64 65 -31 -34 normal -12 cows_cargo.png 8bpp 220 10 64 65 -31 -34 normal +10 cows_cargo.png 8bpp 10 10 64 65 -31 -34 normal +11 cows_cargo.png 8bpp 220 10 64 65 -31 -34 normal -13 cows_cargo.png 8bpp 80 10 64 65 -31 -34 normal -14 cows_cargo.png 8bpp 290 10 64 65 -31 -34 normal +12 cows_cargo.png 8bpp 80 10 64 65 -31 -34 normal +13 cows_cargo.png 8bpp 290 10 64 65 -31 -34 normal -15 cows_cargo.png 8bpp 150 10 64 65 -31 -34 normal -16 cows_cargo.png 8bpp 360 10 64 65 -31 -34 normal +14 cows_cargo.png 8bpp 150 10 64 65 -31 -34 normal +15 cows_cargo.png 8bpp 360 10 64 65 -31 -34 normal // Name: cow_pen_1 - feature 04 -17 * 11 02 04 FF \b2 \b1 +16 * 11 02 04 FF \b2 \b1 \w0 \w1 \w2 // Name: cow_pen_2 - feature 04 -18 * 13 02 04 FE \b3 \b1 +17 * 13 02 04 FE \b3 \b1 \w0 \w1 \w2 \w2 // Name: random_cow_pen -19 * 11 02 04 FE 80 00 \b16 02 +18 * 11 02 04 FE 80 00 \b16 02 \wx00FF // (1/2) -> (1/2): cow_pen_1; \wx00FE // (1/2) -> (1/2): cow_pen_2; -20 * 27 00 04 \b7 01 FF \wx0000 +19 * 21 00 04 \b5 01 FF \wx0000 08 "NML_" -1D \wxDC00 -1C \wxC500 10 \wx00A0 11 00 14 FF 15 FF +20 * 18 04 04 FF 01 \wxC400 "NML Example" 00 + 21 * 21 04 04 FF 01 \wxC500 "CHIPS Cow pens" 00 // Name: cow_pen_half - feature 04 Binary files old/nml-0.7.4/regression/tram_foster_express.32.png and new/nml-0.7.5/regression/tram_foster_express.32.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nml-0.7.4/setup.py new/nml-0.7.5/setup.py --- old/nml-0.7.4/setup.py 2023-06-28 22:12:57.000000000 +0200 +++ new/nml-0.7.5/setup.py 2024-03-02 15:00:53.000000000 +0100 @@ -1,7 +1,9 @@ #!/usr/bin/env python3 -from setuptools import Extension, find_packages, setup -from setuptools.command.build_py import build_py +from setuptools import Distribution, Extension, find_packages, setup + +import contextlib +import os try: # Update the version by querying git if possible. @@ -15,8 +17,12 @@ NML_VERSION = version_info.get_nml_version() +default_dist = Distribution() +default_build_py = default_dist.get_command_class('build_py') +default_clean = default_dist.get_command_class('clean') + -class NMLBuildPy(build_py): +class NMLBuildPy(default_build_py): def run(self): # Create a parser so that nml/generated/{parse,lex}tab.py are generated. from nml import parser @@ -26,6 +32,18 @@ super().run() +class NMLClean(default_clean): + def run(self): + # Remove python files generated by custom build command above + with contextlib.suppress(FileNotFoundError): + os.remove('nml/generated/parsetab.py') + with contextlib.suppress(FileNotFoundError): + os.remove('nml/generated/lextab.py') + + # Then continue with the normal setuptools build. + super().run() + + setup( name="nml", version=NML_VERSION, @@ -60,5 +78,5 @@ "Pillow>=3.4", "ply", ], - cmdclass={"build_py": NMLBuildPy}, + cmdclass={"build_py": NMLBuildPy, 'clean': NMLClean}, )
