From c94275852dbe3443bad92fe36e6d9553fa8014ff Mon Sep 17 00:00:00 2001 From: glx22 Date: Fri, 29 Sep 2023 02:16:50 +0200 Subject: [PATCH] Change: reduce register consumption for spritelayouts --- nml/actions/action2layout.py | 66 ++++++++++++++---------- regression/expected/026_asl.grf | Bin 2019 -> 1991 bytes regression/expected/026_asl.nfo | 24 ++++----- regression/expected/030_house.grf | Bin 14397 -> 14397 bytes regression/expected/030_house.nfo | 34 ++++++------ regression/expected/040_station.grf | Bin 1265 -> 1251 bytes regression/expected/040_station.nfo | 20 ++++--- regression/expected/example_station.grf | Bin 3927 -> 3927 bytes regression/expected/example_station.nfo | 4 +- 9 files changed, 78 insertions(+), 70 deletions(-) diff --git a/nml/actions/action2layout.py b/nml/actions/action2layout.py index 288222f8..33ec49f6 100644 --- a/nml/actions/action2layout.py +++ b/nml/actions/action2layout.py @@ -60,9 +60,10 @@ class Action2LayoutSpriteType: class Action2LayoutSprite: - def __init__(self, feature, type, pos=None, extra_dicts=None): + def __init__(self, feature, type, layout_registers=None, pos=None, extra_dicts=None): self.feature = feature self.type = type + self.layout_registers = layout_registers self.pos = pos self.extra_dicts = extra_dicts or [] self.params = { @@ -217,7 +218,10 @@ def create_register(self, name, value): store_tmp = None load_tmp = action2var.VarAction2Var(0x7D, 0, 0xFFFFFFFF, value.register.value) else: - store_tmp = action2var.VarAction2StoreTempVar() + if self.layout_registers is None: + store_tmp = action2var.VarAction2StoreTempVar() + else: + store_tmp = self.layout_registers.add(value) load_tmp = action2var.VarAction2LoadTempVar(store_tmp) self.params[name]["register"] = (load_tmp, store_tmp, value) @@ -387,10 +391,9 @@ def _validate_hide_sprite(self, name, value): class ParsedSpriteLayout: - def __init__(self, registers=None): + def __init__(self): self.ground_sprite = None self.building_sprites = [] - self.registers = registers or [] self.advanced = False def get_size(self): @@ -441,7 +444,7 @@ def write(self, file): sprite.write_registers(file) file.newline() - def process(self, spritelayout, feature, param_map, actions, var10map=None): + def process(self, spritelayout, feature, param_map, actions, layout_registers, var10map=None): if not isinstance(param_map, list): param_map = [param_map] @@ -474,10 +477,9 @@ def process(self, spritelayout, feature, param_map, actions, var10map=None): ), type.pos, ) - sprite = Action2LayoutSprite(feature, layout_sprite_types[type.value], pos, param_map) + sprite = Action2LayoutSprite(feature, layout_sprite_types[type.value], layout_registers, pos, param_map) for name, value in param_list: sprite.set_param(name, value) - self.registers.extend(sprite.get_all_registers()) if sprite.type == Action2LayoutSpriteType.GROUND: if self.ground_sprite is not None: raise generic.ScriptError("Sprite layout can have no more than one ground sprite", spritelayout.pos) @@ -490,7 +492,7 @@ def process(self, spritelayout, feature, param_map, actions, var10map=None): # no sprites defined at all, that's not very much. raise generic.ScriptError("Sprite layout requires at least one sprite", spritelayout.pos) # set to 0 for no ground sprite - self.ground_sprite = Action2LayoutSprite(feature, Action2LayoutSpriteType.GROUND) + self.ground_sprite = Action2LayoutSprite(feature, Action2LayoutSpriteType.GROUND, layout_registers) self.ground_sprite.set_param(expression.Identifier("sprite"), expression.ConstantNumeric(0)) self.advanced = any(x.is_advanced_sprite() for x in self.building_sprites + [self.ground_sprite]) @@ -510,17 +512,23 @@ def write_action_value(self, actions, act6, offset): return offset - def parse_registers(self, varact2parser): - if self.registers: - for register_info in self.registers: - reg, expr = register_info[1], register_info[2] - if reg is None: - continue - varact2parser.parse_expr(expr) - varact2parser.var_list.append(nmlop.STO_TMP) - varact2parser.var_list.append(reg) - varact2parser.var_list.append(nmlop.VAL2) - varact2parser.var_list_size += reg.get_size() + 2 + +class LayoutRegisters: + def __init__(self): + self.registers = {} + + def add(self, value): + if value not in self.registers: + self.registers[value] = action2var.VarAction2StoreTempVar() + return self.registers[value] + + def parse(self, varact2parser): + for expr, reg in self.registers.items(): + varact2parser.parse_expr(expr) + varact2parser.var_list.append(nmlop.STO_TMP) + varact2parser.var_list.append(reg) + varact2parser.var_list.append(nmlop.VAL2) + varact2parser.var_list_size += reg.get_size() + 2 def get_layout_action2s(spritelayout, feature): @@ -541,8 +549,9 @@ def get_layout_action2s(spritelayout, feature): param_map = (param_map, lambda name, value, pos: action2var.VarAction2LoadCallParam(value, name)) spritelayout.register_map[feature] = param_registers + layout_registers = LayoutRegisters() layout = ParsedSpriteLayout() - layout.process(spritelayout, feature, param_map, actions) + layout.process(spritelayout, feature, param_map, actions, layout_registers) action6.free_parameters.save() act6 = action6.Action6() @@ -562,7 +571,7 @@ def get_layout_action2s(spritelayout, feature): actions.append(layout_action) varact2parser = action2var.Varaction2Parser(feature) - layout.parse_registers(varact2parser) + layout_registers.parse(varact2parser) # Only continue if we actually needed any new registers if varact2parser.var_list: @@ -694,6 +703,7 @@ def parse_spriteset(name, args, pos, info): param_registers = [] parsed_layouts = [] varact2parser = action2var.Varaction2Parser(feature) + layout_registers = LayoutRegisters() for layout in layouts: spritelayout = ( @@ -703,22 +713,26 @@ def parse_spriteset(name, args, pos, info): raise generic.ScriptError("Expected a SpriteLayout", layout.pos) # Allocate registers - registers = [] param_map = {} for i, param in enumerate(spritelayout.param_list): reg = action2var.VarAction2CallParam(param.value) param_registers.append(reg) param_map[param.value] = reg store_tmp = action2var.VarAction2StoreCallParam(reg) - registers.append((reg, store_tmp, layout.param_list[i])) + varact2parser.parse_expr(layout.param_list[i]) + varact2parser.var_list.append(nmlop.STO_TMP) + varact2parser.var_list.append(store_tmp) + varact2parser.var_list.append(nmlop.VAL2) + varact2parser.var_list_size += store_tmp.get_size() + 2 param_map = [(param_map, lambda name, value, pos: action2var.VarAction2LoadCallParam(value, name))] param_map.extend(default_param) - layout = ParsedSpriteLayout(registers) - layout.process(spritelayout, feature, param_map, actions, var10map) - layout.parse_registers(varact2parser) + layout = ParsedSpriteLayout() + layout.process(spritelayout, feature, param_map, actions, layout_registers, var10map) parsed_layouts.append(layout) + layout_registers.parse(varact2parser) + actions.extend(action0.get_layout_action0(feature, id, parsed_layouts)) registers_ref = None diff --git a/regression/expected/026_asl.grf b/regression/expected/026_asl.grf index f688852f0910a74a2fdfdf380fdd1c356fba831c..8630aa03df784d85729c6165ce5fb1df4038a9f2 100644 GIT binary patch delta 131 zcmaFNf1ID2fx$haw85kJ&q!b!~6n_$fCWy-m r6J==H%)*?-WCcmQxo0 delta 147 zcmX@k|Cpbffx$h zfhle&1xBDKPi-rh%M0Q1Nh!2})Vd}72T~yAEI^t;N`ak+fdMGlj*v71GC?K)MLR&E ilMPr!G=Q8=5T~{WY$^-HRH)%RwVg1#Hos*GFa-cIGBhIq delta 115 zcmdm6u(x1CE2Cg*8v_t1GjK34a0{?^baqXi#+Wx*pGl6fWwIZWv|x+Ee<0wMQeXrs yGfx$h|PW8PWg% diff --git a/regression/expected/040_station.nfo b/regression/expected/040_station.nfo index 10289544..d3b96c0d 100644 --- a/regression/expected/040_station.nfo +++ b/regression/expected/040_station.nfo @@ -55,26 +55,24 @@ \dx0000842E \wx0000 \b0 \b0 \b0 \b16 \b5 \b2 \dx8000842D \wx0002 \b17 \b11 80 81 \dx00008430 \wx0000 \b0 \b11 \b0 \b16 \b5 \b2 -\dx8000842D \wx0042 \b17 \b10 80 82 01 +\dx8000842D \wx0042 \b17 \b10 80 81 01 \b68 \dx000003F3 \wx0000 \dx0000842F \wx0000 \b0 \b0 \b0 \b5 \b16 \b2 -\dx8000842D \wx0042 \b20 \b11 80 83 01 +\dx8000842D \wx0042 \b20 \b11 80 82 01 \dx0000842D \wx0000 \b11 \b0 \b0 \b5 \b16 \b2 -\dx8000842D \wx0042 \b20 \b10 80 84 03 +\dx8000842D \wx0042 \b20 \b10 80 83 03 // Name: Station Layout@registers - Id FF // a : register 80 -16 * 77 02 04 FD 89 -1A 20 \dx00000000 -\2sto 1A 20 \dx00000081 -\2r 1A 20 \dx00000000 -\2sto 1A 20 \dx00000082 -\2r 1A 20 \dx00000001 +16 * 63 02 04 FD 89 +1A 20 \dx00000001 \2sto 1A 20 \dx00000080 +\2r 1A 20 \dx00000000 +\2sto 1A 20 \dx00000081 \2r 7D 80 20 \dxFFFFFFFF // a -\2sto 1A 20 \dx00000083 +\2sto 1A 20 \dx00000082 \2r 1A 20 \dx00000001 -\2sto 1A 00 \dx00000084 +\2sto 1A 00 \dx00000083 \b0 \wx8000 // Return computed value diff --git a/regression/expected/example_station.grf b/regression/expected/example_station.grf index ba767de2c8f1861e737af13686b8956ab627f7f9..b0aca843275a72f2cbb8e78fffbd9be031b0cdf8 100644 GIT binary patch delta 27 hcmcaEcU^A7Y$h%#1qLAClTv7$Je^5n^I4`Y9sq9l2eAME delta 27 hcmcaEcU^A7Y^KR8nN+x>6c~VjPfDS2^GT*Y9sqi22fqLS diff --git a/regression/expected/example_station.nfo b/regression/expected/example_station.nfo index 0e8c930a..b5f73faa 100644 --- a/regression/expected/example_station.nfo +++ b/regression/expected/example_station.nfo @@ -92,13 +92,13 @@ 25 * 106 02 04 FC 89 1A 20 \dx00000000 \2sto 1A 20 \dx00000080 +\2r 1A 20 \dx00000000 +\2sto 1A 20 \dx00000081 \2r 7D 80 20 \dxFFFFFFFF // a \2+ 1A 20 \dx000007E6 \2sto 1A 20 \dx00000082 \2r 1A 20 \dx00000000 \2sto 1A 20 \dx00000083 -\2r 1A 20 \dx00000000 -\2sto 1A 20 \dx00000081 \2r 7D 81 20 \dxFFFFFFFF // a \2+ 1A 20 \dx000007E6 \2sto 1A 20 \dx00000084