Skip to content

Commit

Permalink
Change: Create output with GRFv9 format.
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterN committed Jan 16, 2025
1 parent f2b775c commit 037368d
Show file tree
Hide file tree
Showing 112 changed files with 1,572 additions and 1,581 deletions.
7 changes: 3 additions & 4 deletions nml/actions/action0.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,7 @@ def write(self, file):
file.print_bytex(0)
file.print_bytex(self.feature)
file.print_byte(len(self.prop_list))
file.print_bytex(self.num_ids)
file.print_bytex(0xFF)
file.print_wordx(self.num_ids)
file.print_wordx(self.id)
file.newline()
for prop in self.prop_list:
Expand Down Expand Up @@ -1080,7 +1079,7 @@ def parse_sort_block(feature, vehid_list):
idx = len(vehid_list) - 1
while idx >= 0:
cur = vehid_list[idx]
prop = Action0Property(prop_num[feature], [last], 3)
prop = Action0Property(prop_num[feature], [last], 2)
action_list.append(Action0(feature, cur.value))
action_list[-1].prop_list.append(prop)
last = cur
Expand Down Expand Up @@ -1214,5 +1213,5 @@ def get_layout_action0(feature, id, layouts):
def get_copy_layout_action0(feature, id, source_id):
act0, offset = create_action0(feature, id, None, None)
act0.num_ids = 1
act0.prop_list.append(Action0Property(0x0A, source_id, 1 if source_id.value < 0xFF else 3))
act0.prop_list.append(Action0Property(0x0A, source_id, 2))
return [act0]
63 changes: 29 additions & 34 deletions nml/actions/action0properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,22 +305,17 @@ class VariableListProp(BaseAction0Property):
Property value that is a variable-length list of variable sized values, the list length is written before the data.
"""

def __init__(self, prop_num, data, size, extended):
def __init__(self, prop_num, data, size):
# data is a list, each element belongs to an item ID
# Each element in the list is a list of cargo types
self.prop_num = prop_num
self.data = data
self.size = size
self.extended = extended

def write(self, file):
file.print_bytex(self.prop_num)
for elem in self.data:
if self.extended:
file.print_bytex(0xFF)
file.print_word(len(elem))
else:
file.print_byte(len(elem))
file.print_word(len(elem))
for i, val in enumerate(elem):
if i % 8 == 0:
file.newline()
Expand All @@ -330,13 +325,17 @@ def write(self, file):
def get_size(self):
total_len = 1 # Prop number
for elem in self.data:
# For each item ID to set, make space for all values + 3 or 1 for the length
total_len += len(elem) * self.size + (3 if self.extended else 1)
# For each item ID to set, make space for all values + 2 for the length
total_len += len(elem) * self.size + 2
return total_len


def VariableByteListProp(prop_num, data, extended=False):
return VariableListProp(prop_num, data, 1, extended)
def VariableByteListProp(prop_num, data):
return VariableListProp(prop_num, data, 1)


def VariableWordListProp(prop_num, data):
return VariableListProp(prop_num, data, 2)


def ctt_list(prop_num, *values):
Expand All @@ -346,17 +345,13 @@ def ctt_list(prop_num, *values):
if not isinstance(value, Array):
raise generic.ScriptError("Value of cargolist property must be an array", value.pos)
return [
VariableByteListProp(
VariableWordListProp(
prop_num,
[[ctype.reduce_constant().value for ctype in single_item_array.values] for single_item_array in values],
)
]


def VariableWordListProp(num_prop, data, extended=False):
return VariableListProp(num_prop, data, 2, extended)


def accepted_cargos(prop_num, *values):
# values may have multiple entries, if more than one item ID is set (e.g. multitile houses)
# Each value is an expression.Array of cargo types and amount arrays
Expand Down Expand Up @@ -419,7 +414,7 @@ def prop_test(value):
# fmt: off
properties[0x00] = {
**general_veh_props,
"track_type": {"size": 1, "num": 0x05},
"track_type": {"size": 2, "num": 0x05},
"ai_special_flag": {"size": 1, "num": 0x08},
"speed": {
"size": 2,
Expand All @@ -437,7 +432,7 @@ def prop_test(value):
"sprite_id": {"size": 1, "num": 0x12},
"dual_headed": {"size": 1, "num": 0x13},
"cargo_capacity": {"size": 1, "num": 0x14},
"default_cargo_type": {"size": 1, "num": 0x15},
"default_cargo_type": {"size": 2, "num": 0x15},
"weight": two_byte_property(
0x16,
0x24,
Expand Down Expand Up @@ -510,8 +505,8 @@ def prop15_test(value):
# fmt: off
properties[0x01] = {
**general_veh_props,
"road_type": {"size": 1, "num": 0x05},
"tram_type": {"size": 1, "num": 0x05},
"road_type": {"size": 2, "num": 0x05},
"tram_type": {"size": 2, "num": 0x05},
"speed": roadveh_speed_prop(
{
"unit_type": "speed",
Expand All @@ -524,9 +519,9 @@ def prop15_test(value):
# 0B -0D don"t exist
"sprite_id": {"size": 1, "num": 0x0E},
"cargo_capacity": {"size": 1, "num": 0x0F},
"default_cargo_type": {"size": 1, "num": 0x10},
"default_cargo_type": {"size": 2, "num": 0x10},
"cost_factor": {"size": 1, "num": 0x11},
"sound_effect": {"size": 1, "num": 0x12},
"sound_effect": {"size": 2, "num": 0x12},
"power": {"size": 1, "num": 0x13, "unit_type": "power", "unit_conversion": (1, 10)},
"weight": {"size": 1, "num": 0x14, "unit_type": "weight", "unit_conversion": 4},
# 15 is set together with 08 (see above)
Expand Down Expand Up @@ -605,11 +600,11 @@ def prop23_test(value):
"adjust_value": lambda val, unit: ottd_display_speed(val, 1, 2, unit),
}
),
"default_cargo_type": {"size": 1, "num": 0x0C},
"default_cargo_type": {"size": 2, "num": 0x0C},
"cargo_capacity": {"size": 2, "num": 0x0D},
# 0E does not exist
"running_cost_factor": {"size": 1, "num": 0x0F},
"sound_effect": {"size": 1, "num": 0x10},
"sound_effect": {"size": 2, "num": 0x10},
# 11 (refittable cargo types) is removed, it is zeroed when setting a different refit property
# 12 (callback flags) is not set by user
"refit_cost": {"size": 1, "num": 0x13},
Expand Down Expand Up @@ -685,7 +680,7 @@ def aircraft_is_large(value):
"passenger_capacity": {"size": 2, "num": 0x0F},
# 10 does not exist
"mail_capacity": {"size": 1, "num": 0x11},
"sound_effect": {"size": 1, "num": 0x12},
"sound_effect": {"size": 2, "num": 0x12},
# 13 (refittable cargo types) is removed, it is zeroed when setting a different refit property
# 14 (callback flags) is not set by user
"refit_cost": {"size": 1, "num": 0x15},
Expand Down Expand Up @@ -763,7 +758,7 @@ def get_size(self):

def station_layouts(value):
if isinstance(value, ConstantNumeric):
return [Action0Property(0x0F, value, 1 if value.value < 0xFF else 3)]
return [Action0Property(0x0F, value, 2)]
if not isinstance(value, Array) or len(value.values) == 0:
raise generic.ScriptError("station_layouts must be an array of layouts, or the ID of a station", value.pos)
layouts = {}
Expand Down Expand Up @@ -799,7 +794,7 @@ def station_tile_flags(value):
if not isinstance(value, Array) or len(value.values) % 2 != 0:
raise generic.ScriptError("Flag list must be an array of even length", value.pos)
if len(value.values) > 8:
return [VariableByteListProp(0x1E, [[flags.reduce_constant().value for flags in value.values]], True)]
return [VariableByteListProp(0x1E, [[flags.reduce_constant().value for flags in value.values]])]
pylons = 0
wires = 0
blocked = 0
Expand Down Expand Up @@ -1128,13 +1123,13 @@ def __init__(self, sound_list):

def write(self, file):
file.print_bytex(0x15)
file.print_byte(len(self.sound_list))
file.print_word(len(self.sound_list))
for sound in self.sound_list:
sound.write(file, 1)
sound.write(file, 2)
file.newline()

def get_size(self):
return len(self.sound_list) + 2
return len(self.sound_list) + 3


def random_sounds(value):
Expand Down Expand Up @@ -1282,8 +1277,8 @@ def check_accept(acp):
has_inpmult = True

return [
VariableByteListProp(0x25, [output_cargos]),
VariableByteListProp(0x26, [input_cargos]),
VariableWordListProp(0x25, [output_cargos]),
VariableWordListProp(0x26, [input_cargos]),
VariableByteListProp(0x27, [prod_multipliers]),
IndustryInputMultiplierProp(0x28, input_multipliers if has_inpmult else []),
]
Expand Down Expand Up @@ -1502,14 +1497,14 @@ def __init__(self, prop_num, labels):

def write(self, file):
file.print_bytex(self.prop_num)
file.print_byte(len(self.labels))
file.print_word(len(self.labels))
for label in self.labels:
parse_string_to_dword(label) # Error if the wrong length or not ASCII
label.write(file, 4)
file.newline()

def get_size(self):
return len(self.labels) * 4 + 2
return len(self.labels) * 4 + 3


def label_list(value, prop_num, description):
Expand Down
12 changes: 6 additions & 6 deletions nml/actions/action1.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@ def __init__(self, feature, first_set, num_sets, num_ent):
def write(self, file):
if self.first_set == 0 and self.num_sets < 256:
# <Sprite-number> * <Length> 01 <feature> <num-sets> <num-ent>
file.start_sprite(6)
file.start_sprite(5)
file.print_bytex(1)
file.print_bytex(self.feature)
file.print_byte(self.num_sets)
file.print_varx(self.num_ent, 3)
file.print_wordx(self.num_ent)
file.newline()
file.end_sprite()
else:
# <Sprite-number> * <Length> 01 <feature> 00 <first_set> <num-sets> <num-ent>
file.start_sprite(12)
file.start_sprite(9)
file.print_bytex(1)
file.print_bytex(self.feature)
file.print_bytex(0)
file.print_varx(self.first_set, 3)
file.print_varx(self.num_sets, 3)
file.print_varx(self.num_ent, 3)
file.print_wordx(self.first_set)
file.print_wordx(self.num_sets)
file.print_wordx(self.num_ent)
file.newline()
file.end_sprite()

Expand Down
5 changes: 3 additions & 2 deletions nml/actions/action10.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
class Action10(base_action.BaseAction):
def __init__(self, label):
self.label = label
assert self.label >= 0x8000 and self.label <= 0xFFFF

def write(self, file):
file.start_sprite(2)
file.start_sprite(3)
file.print_bytex(0x10)
file.print_bytex(self.label)
file.print_wordx(self.label)
file.newline()
file.end_sprite()

Expand Down
16 changes: 8 additions & 8 deletions nml/actions/action12.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ def __init__(self, sets):

def write(self, file):
# <sprite-number> * <length> 12 <num-def> (<font> <num-char> <base-char>){n}
size = 2 + 4 * len(self.sets)
size = 3 + 7 * len(self.sets)
file.start_sprite(size)
file.print_bytex(0x12)
file.print_byte(len(self.sets))
file.print_word(len(self.sets))
file.newline()
for font_size, num_char, base_char in self.sets:
font_size.write(file, 1)
file.print_byte(num_char)
file.print_word(base_char)
file.print_word(num_char)
file.print_dword(base_char)
file.newline()
file.end_sprite()

Expand All @@ -58,17 +58,17 @@ def parse_action12(font_glyphs):
raise generic.ScriptError(
"Invalid value for parameter 'font_size' in font_glyph, valid values are 0, 1, 2", font_size.pos
)
if not (0 <= base_char.value <= 0xFFFF):
if not (0 <= base_char.value <= 0x1FFFFF):
raise generic.ScriptError(
"Invalid value for parameter 'base_char' in font_glyph, valid values are 0-0xFFFF", base_char.pos
"Invalid value for parameter 'base_char' in font_glyph, valid values are 0-0x1FFFFF", base_char.pos
)

real_sprite_list = real_sprite.parse_sprite_data(font_glyphs)
char = base_char.value
last_char = char + len(real_sprite_list)
if last_char > 0xFFFF:
if last_char > 0x1FFFFF:
raise generic.ScriptError(
"Character numbers in font_glyph block exceed the allowed range (0-0xFFFF)", font_glyphs.pos
"Character numbers in font_glyph block exceed the allowed range (0-0x1FFFFF)", font_glyphs.pos
)

sets = []
Expand Down
6 changes: 3 additions & 3 deletions nml/actions/action2.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from nml.actions import base_action
from nml.ast import base_statement, general

total_action2_ids = 0x100
total_action2_ids = 0x8000
free_action2_ids = list(range(0, total_action2_ids))

"""
Expand Down Expand Up @@ -122,10 +122,10 @@ def write_sprite_start(self, file, size, extra_comment=None):
if extra_comment:
for c in extra_comment:
file.comment(c)
file.start_sprite(size + 3)
file.start_sprite(size + 4)
file.print_bytex(2)
file.print_bytex(self.feature)
file.print_bytex(self.id)
file.print_wordx(self.id)

def skip_action7(self):
return False
Expand Down
6 changes: 3 additions & 3 deletions nml/actions/action2production.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@ def write(self, file):
file.print_varx(val, cargo_size)
file.print_bytex(values[-1])
elif self.version == 2:
size = 4 + 2 * (len(self.sub_in) + len(self.add_out))
size = 4 + 3 * (len(self.sub_in) + len(self.add_out))
action2.Action2.write_sprite_start(self, file, size)
file.print_bytex(self.version)
file.print_byte(len(self.sub_in))
for cargoindex, value in self.sub_in:
file.print_bytex(cargoindex)
file.print_wordx(cargoindex)
file.print_bytex(value.parameter)
file.print_byte(len(self.add_out))
for cargoindex, value in self.add_out:
file.print_bytex(cargoindex)
file.print_wordx(cargoindex)
file.print_bytex(value.parameter)
file.print_bytex(self.again.parameter)
file.newline()
Expand Down
4 changes: 2 additions & 2 deletions nml/actions/action2random.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ def prepare_output(self, sprite_num):

def write(self, file):
# <type> [<count>] <random-triggers> <randbit> <nrand> <set-ids>
size = 4 + 2 * self.nrand + (self.count is not None)
size = 5 + 2 * self.nrand + (self.count is not None)
action2.Action2.write_sprite_start(self, file, size)
file.print_bytex(self.type_byte)
if self.count is not None:
file.print_bytex(self.count)
file.print_bytex(self.triggers)
file.print_byte(self.randbit)
file.print_bytex(self.nrand)
file.print_wordx(self.nrand)
file.newline()

for choice in self.choices:
Expand Down
Loading

0 comments on commit 037368d

Please sign in to comment.