Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change: reduce register consumption for spritelayouts #306

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 40 additions & 26 deletions nml/actions/action2layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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]

Expand Down Expand Up @@ -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)
Expand All @@ -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])
Expand All @@ -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):
Expand All @@ -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()
Expand All @@ -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:
Expand Down Expand Up @@ -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 = (
Expand All @@ -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
Expand Down
Binary file modified regression/expected/026_asl.grf
Binary file not shown.
24 changes: 10 additions & 14 deletions regression/expected/026_asl.nfo
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,17 @@ F0 F1 F2 F3 F4 F5 00 00 00 00 00 00 00 00 00 FF
// Name: layout2 - feature 0F
10 * 38 02 0F FF \b66 \dx00000000 \wx0000
\dx80000000 \wx0002 \b0 \b0 \b0 \b16 \b16 \b16 80
\dx80018000 \wx000F \b0 \b0 \b0 \b16 \b16 \b16 81 83 82
\dx80018000 \wx000F \b0 \b0 \b0 \b16 \b16 \b16 82 81 81

// Name: layout2@registers - feature 0F
11 * 80 02 0F FF 89
11 * 66 02 0F FF 89
43 20 \dx000000FF
\2sto 1A 20 \dx00000080
\2r 1A 20 \dx00000001
\2sto 1A 20 \dx00000081
\2r 62 00 29 \dx00000001
\2^ 1A 20 \dx00000001
\2sto 1A 20 \dx00000081
\2r 1A 20 \dx00000001
\2sto 1A 20 \dx00000082
\2r 1A 20 \dx00000001
\2sto 1A 00 \dx00000083
\2sto 1A 00 \dx00000082
\b1
\wx00FF \dx00000000 \dx00000000
\wx00FF //
Expand Down Expand Up @@ -127,19 +125,17 @@ F0 F1 F2 F3 F4 F5 00 00 00 00 00 00 00 00 00 FF
// Name: layout2 - feature 11
19 * 38 02 11 FE \b66 \dx00000000 \wx0000
\dx80000000 \wx0002 \b0 \b0 \b0 \b16 \b16 \b16 80
\dx80018000 \wx000F \b0 \b0 \b0 \b16 \b16 \b16 81 83 82
\dx80018000 \wx000F \b0 \b0 \b0 \b16 \b16 \b16 82 81 81

// Name: layout2@registers - feature 11
20 * 80 02 11 FE 89
20 * 66 02 11 FE 89
44 20 \dx000000FF
\2sto 1A 20 \dx00000080
\2r 1A 20 \dx00000001
\2sto 1A 20 \dx00000081
\2r 60 00 29 \dx00000001
\2^ 1A 20 \dx00000001
\2sto 1A 20 \dx00000081
\2r 1A 20 \dx00000001
\2sto 1A 20 \dx00000082
\2r 1A 20 \dx00000001
\2sto 1A 00 \dx00000083
\2sto 1A 00 \dx00000082
\b1
\wx00FE \dx00000000 \dx00000000
\wx00FE //
Expand Down
Binary file modified regression/expected/030_house.grf
Binary file not shown.
34 changes: 17 additions & 17 deletions regression/expected/030_house.nfo
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ FF
// with_smoke : register 8C
22 * 49 02 07 FF \b67 \dx00000F8D \wx0000
\dxC0000000 \wx0002 \b0 \b0 80 83
\dx00000000 \wx0003 \b0 \b0 \b0 \b16 \b16 \b48 85 86
\dx00000000 \wx0023 \b8 \b0 \b0 \b11 \b16 \b7 88 89 8A
\dx00000000 \wx0003 \b0 \b0 \b0 \b16 \b16 \b48 86 84
\dx00000000 \wx0023 \b8 \b0 \b0 \b11 \b16 \b7 8A 87 88

// Name: brewery_sprite_layout@registers - feature 07
23 * 362 02 07 FF 89
Expand All @@ -74,37 +74,37 @@ FF
\2* 1A 20 \dx00000002
\2+ 7D 82 20 \dxFFFFFFFF
\2sto 1A 20 \dx00000083
\2r 43 20 \dx000000FF
\2cmp 1A 20 \dx00000004
\2& 1A 20 \dx00000001
\2* 1A 20 \dx00000003
\2+ 7D 8B 20 \dxFFFFFFFF // building_sprite
\2sto 1A 20 \dx00000084
\2r 40 20 \dx00000003
\2cmp 1A 20 \dx00000003
\2& 1A 20 \dx00000001
\2^ 1A 20 \dx00000001
\2sto 1A 20 \dx00000084
\2sto 1A 20 \dx00000085
\2r 7D 8B 20 \dxFFFFFFFF // building_sprite
\2cmp 1A 20 \dxFFFFFFFF
\2& 1A 20 \dx00000001
\2| 7D 84 20 \dxFFFFFFFF
\2| 7D 85 20 \dxFFFFFFFF
\2^ 1A 20 \dx00000001
\2sto 1A 20 \dx00000085
\2r 43 20 \dx000000FF
\2cmp 1A 20 \dx00000004
\2& 1A 20 \dx00000001
\2* 1A 20 \dx00000003
\2+ 7D 8B 20 \dxFFFFFFFF // building_sprite
\2sto 1A 20 \dx00000086
\2r 46 60 \dx000000FF \dxFFFFFFFF \dx00000004
\2+ 1A 20 \dx00000C07
\2sto 1A 20 \dx00000087
\2r 46 60 \dx000000FF \dx00000036 \dx00000001
\2sto 1A 20 \dx00000088
\2r 46 20 \dx000000FF
\2cmp 1A 20 \dx00000000
\2& 1A 20 \dx00000001
\2sto 1A 20 \dx00000087
\2sto 1A 20 \dx00000089
\2r 7D 8C 20 \dxFFFFFFFF // with_smoke
\2u< 1A 20 \dx00000001
\2^ 1A 20 \dx00000001
\2| 7D 87 20 \dxFFFFFFFF
\2| 7D 89 20 \dxFFFFFFFF
\2^ 1A 20 \dx00000001
\2sto 1A 20 \dx00000088
\2r 46 60 \dx000000FF \dxFFFFFFFF \dx00000004
\2+ 1A 20 \dx00000C07
\2sto 1A 20 \dx00000089
\2r 46 60 \dx000000FF \dx00000036 \dx00000001
\2sto 1A 00 \dx0000008A
\b1
\wx00FF \dx00000000 \dx00000000
Expand Down
Binary file modified regression/expected/040_station.grf
Binary file not shown.
20 changes: 9 additions & 11 deletions regression/expected/040_station.nfo
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Binary file modified regression/expected/example_station.grf
Binary file not shown.
4 changes: 2 additions & 2 deletions regression/expected/example_station.nfo
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down