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},
 )

Reply via email to