|
@@ -27,12 +27,13 @@
|
|
|
#include "date.h"
|
|
|
#include "currency.h"
|
|
|
#include "sound.h"
|
|
|
#include "newgrf_config.h"
|
|
|
#include "newgrf_sound.h"
|
|
|
#include "newgrf_spritegroup.h"
|
|
|
#include "helpers.hpp"
|
|
|
|
|
|
/* TTDPatch extended GRF format codec
|
|
|
* (c) Petr Baudis 2004 (GPL'd)
|
|
|
* Changes by Florian octo Forster are (c) by the OpenTTD development team.
|
|
|
*
|
|
|
* Contains portions of documentation by TTDPatch team.
|
|
@@ -539,13 +540,13 @@ static bool RoadVehicleChangeInfo(uint e
|
|
|
|
|
|
case 0x11: /* Cost factor */
|
|
|
FOR_EACH_OBJECT rvi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
|
|
|
break;
|
|
|
|
|
|
case 0x12: /* SFX */
|
|
|
FOR_EACH_OBJECT rvi[i].sfx = grf_load_byte(&buf);
|
|
|
FOR_EACH_OBJECT rvi[i].sfx = (SoundFx)grf_load_byte(&buf);
|
|
|
break;
|
|
|
|
|
|
case 0x13: /* Power in 10hp */
|
|
|
case 0x14: /* Weight in 1/4 tons */
|
|
|
case 0x15: /* Speed in mph*0.8 */
|
|
|
/* TODO: Support for road vehicles realistic power
|
|
@@ -624,13 +625,13 @@ static bool ShipVehicleChangeInfo(uint e
|
|
|
|
|
|
svi[i].image_index = spriteid;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case 0x09: /* Refittable */
|
|
|
FOR_EACH_OBJECT svi[i].refittable = grf_load_byte(&buf);
|
|
|
FOR_EACH_OBJECT svi[i].refittable = (grf_load_byte(&buf) != 0);
|
|
|
break;
|
|
|
|
|
|
case 0x0A: /* Cost factor */
|
|
|
FOR_EACH_OBJECT svi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
|
|
|
break;
|
|
|
|
|
@@ -663,13 +664,13 @@ static bool ShipVehicleChangeInfo(uint e
|
|
|
|
|
|
case 0x0F: /* Running cost factor */
|
|
|
FOR_EACH_OBJECT svi[i].running_cost = grf_load_byte(&buf);
|
|
|
break;
|
|
|
|
|
|
case 0x10: /* SFX */
|
|
|
FOR_EACH_OBJECT svi[i].sfx = grf_load_byte(&buf);
|
|
|
FOR_EACH_OBJECT svi[i].sfx = (SoundFx)grf_load_byte(&buf);
|
|
|
break;
|
|
|
|
|
|
case 0x11: /* Cargos available for refitting */
|
|
|
FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
|
|
|
break;
|
|
|
|
|
@@ -776,13 +777,13 @@ static bool AircraftVehicleChangeInfo(ui
|
|
|
|
|
|
case 0x11: /* Mail capacity */
|
|
|
FOR_EACH_OBJECT avi[i].mail_capacity = grf_load_byte(&buf);
|
|
|
break;
|
|
|
|
|
|
case 0x12: /* SFX */
|
|
|
FOR_EACH_OBJECT avi[i].sfx = grf_load_byte(&buf);
|
|
|
FOR_EACH_OBJECT avi[i].sfx = (SoundFx)grf_load_byte(&buf);
|
|
|
break;
|
|
|
|
|
|
case 0x13: /* Cargos available for refitting */
|
|
|
FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
|
|
|
break;
|
|
|
|
|
@@ -838,13 +839,13 @@ static bool StationChangeInfo(uint stid,
|
|
|
if (stid + numinfo > MAX_STATIONS) {
|
|
|
grfmsg(1, "StationChangeInfo: Station %u is invalid, max %u, ignoring", stid + numinfo, MAX_STATIONS);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/* Allocate station specs if necessary */
|
|
|
if (_cur_grffile->stations == NULL) _cur_grffile->stations = calloc(MAX_STATIONS, sizeof(*_cur_grffile->stations));
|
|
|
if (_cur_grffile->stations == NULL) CallocT(&_cur_grffile->stations, MAX_STATIONS);
|
|
|
|
|
|
statspec = &_cur_grffile->stations[stid];
|
|
|
|
|
|
if (prop != 0x08) {
|
|
|
/* Check that all stations we are modifying are defined. */
|
|
|
FOR_EACH_OBJECT {
|
|
@@ -858,13 +859,13 @@ static bool StationChangeInfo(uint stid,
|
|
|
switch (prop) {
|
|
|
case 0x08: /* Class ID */
|
|
|
FOR_EACH_OBJECT {
|
|
|
uint32 classid;
|
|
|
|
|
|
/* Property 0x08 is special; it is where the station is allocated */
|
|
|
if (statspec[i] == NULL) statspec[i] = calloc(1, sizeof(*statspec[i]));
|
|
|
if (statspec[i] == NULL) CallocT(&statspec[i], 1);
|
|
|
|
|
|
/* Swap classid because we read it in BE meaning WAYP or DFLT */
|
|
|
classid = grf_load_dword(&buf);
|
|
|
statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
|
|
|
}
|
|
|
break;
|
|
@@ -872,13 +873,13 @@ static bool StationChangeInfo(uint stid,
|
|
|
case 0x09: /* Define sprite layout */
|
|
|
FOR_EACH_OBJECT {
|
|
|
StationSpec *statspec = _cur_grffile->stations[stid + i];
|
|
|
uint t;
|
|
|
|
|
|
statspec->tiles = grf_load_extended(&buf);
|
|
|
statspec->renderdata = calloc(statspec->tiles, sizeof(*statspec->renderdata));
|
|
|
CallocT(&statspec->renderdata, statspec->tiles);
|
|
|
statspec->copied_renderdata = false;
|
|
|
|
|
|
for (t = 0; t < statspec->tiles; t++) {
|
|
|
DrawTileSprites *dts = &statspec->renderdata[t];
|
|
|
uint seq_count = 0;
|
|
|
|
|
@@ -887,13 +888,13 @@ static bool StationChangeInfo(uint stid,
|
|
|
if (dts->ground_sprite == 0) continue;
|
|
|
|
|
|
while (buf < *bufp + len) {
|
|
|
DrawTileSeqStruct *dtss;
|
|
|
|
|
|
// no relative bounding box support
|
|
|
dts->seq = realloc((void*)dts->seq, ++seq_count * sizeof(DrawTileSeqStruct));
|
|
|
ReallocT((DrawTileSeqStruct**)&dts->seq, ++seq_count);
|
|
|
dtss = (DrawTileSeqStruct*) &dts->seq[seq_count - 1];
|
|
|
|
|
|
dtss->delta_x = grf_load_byte(&buf);
|
|
|
if ((byte) dtss->delta_x == 0x80) break;
|
|
|
dtss->delta_y = grf_load_byte(&buf);
|
|
|
dtss->delta_z = grf_load_byte(&buf);
|
|
@@ -953,36 +954,35 @@ static bool StationChangeInfo(uint stid,
|
|
|
uint l, p;
|
|
|
|
|
|
if (length == 0 || number == 0) break;
|
|
|
|
|
|
//debug("l %d > %d ?", length, stat->lengths);
|
|
|
if (length > statspec->lengths) {
|
|
|
statspec->platforms = realloc(statspec->platforms, length);
|
|
|
ReallocT(&statspec->platforms, length);
|
|
|
memset(statspec->platforms + statspec->lengths, 0, length - statspec->lengths);
|
|
|
|
|
|
statspec->layouts = realloc(statspec->layouts, length * sizeof(*statspec->layouts));
|
|
|
ReallocT(&statspec->layouts, length);
|
|
|
memset(statspec->layouts + statspec->lengths, 0,
|
|
|
(length - statspec->lengths) * sizeof(*statspec->layouts));
|
|
|
|
|
|
statspec->lengths = length;
|
|
|
}
|
|
|
l = length - 1; // index is zero-based
|
|
|
|
|
|
//debug("p %d > %d ?", number, stat->platforms[l]);
|
|
|
if (number > statspec->platforms[l]) {
|
|
|
statspec->layouts[l] = realloc(statspec->layouts[l],
|
|
|
number * sizeof(**statspec->layouts));
|
|
|
ReallocT(&statspec->layouts[l], number);
|
|
|
// We expect NULL being 0 here, but C99 guarantees that.
|
|
|
memset(statspec->layouts[l] + statspec->platforms[l], 0,
|
|
|
(number - statspec->platforms[l]) * sizeof(**statspec->layouts));
|
|
|
|
|
|
statspec->platforms[l] = number;
|
|
|
}
|
|
|
|
|
|
p = 0;
|
|
|
layout = malloc(length * number);
|
|
|
MallocT(&layout, length * number);
|
|
|
for (l = 0; l < length; l++) {
|
|
|
for (p = 0; p < number; p++) {
|
|
|
layout[l * number + p] = grf_load_byte(&buf);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1072,26 +1072,26 @@ static bool BridgeChangeInfo(uint brid,
|
|
|
Bridge *bridge = &_bridge[brid + i];
|
|
|
byte tableid = grf_load_byte(&buf);
|
|
|
byte numtables = grf_load_byte(&buf);
|
|
|
|
|
|
if (bridge->sprite_table == NULL) {
|
|
|
/* Allocate memory for sprite table pointers and zero out */
|
|
|
bridge->sprite_table = calloc(7, sizeof(*bridge->sprite_table));
|
|
|
CallocT(bridge->sprite_table, 7);
|
|
|
}
|
|
|
|
|
|
for (; numtables-- != 0; tableid++) {
|
|
|
byte sprite;
|
|
|
|
|
|
if (tableid >= 7) { // skip invalid data
|
|
|
grfmsg(1, "BridgeChangeInfo: Table %d >= 7, skipping", tableid);
|
|
|
for (sprite = 0; sprite < 32; sprite++) grf_load_dword(&buf);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (bridge->sprite_table[tableid] == NULL) {
|
|
|
bridge->sprite_table[tableid] = malloc(32 * sizeof(**bridge->sprite_table));
|
|
|
MallocT(&bridge->sprite_table[tableid], 32);
|
|
|
}
|
|
|
|
|
|
for (sprite = 0; sprite < 32; sprite++)
|
|
|
bridge->sprite_table[tableid][sprite] = grf_load_dword(&buf);
|
|
|
}
|
|
|
}
|
|
@@ -1592,13 +1592,13 @@ static void NewSpriteGroup(byte *buf, in
|
|
|
feature = grf_load_byte(&buf);
|
|
|
setid = grf_load_byte(&buf);
|
|
|
type = grf_load_byte(&buf);
|
|
|
|
|
|
if (setid >= _cur_grffile->spritegroups_count) {
|
|
|
// Allocate memory for new sprite group references.
|
|
|
_cur_grffile->spritegroups = realloc(_cur_grffile->spritegroups, (setid + 1) * sizeof(*_cur_grffile->spritegroups));
|
|
|
ReallocT(&_cur_grffile->spritegroups, setid + 1);
|
|
|
// Initialise new space to NULL
|
|
|
for (; _cur_grffile->spritegroups_count < (setid + 1); _cur_grffile->spritegroups_count++)
|
|
|
_cur_grffile->spritegroups[_cur_grffile->spritegroups_count] = NULL;
|
|
|
}
|
|
|
|
|
|
switch (type) {
|
|
@@ -1637,24 +1637,24 @@ static void NewSpriteGroup(byte *buf, in
|
|
|
|
|
|
if (group->g.determ.num_adjusts > 0) {
|
|
|
check_length(bufend - buf, 2 + varsize + 3, "NewSpriteGroup (Deterministic) (3)");
|
|
|
}
|
|
|
|
|
|
group->g.determ.num_adjusts++;
|
|
|
group->g.determ.adjusts = realloc(group->g.determ.adjusts, group->g.determ.num_adjusts * sizeof(*group->g.determ.adjusts));
|
|
|
ReallocT(&group->g.determ.adjusts, group->g.determ.num_adjusts);
|
|
|
|
|
|
adjust = &group->g.determ.adjusts[group->g.determ.num_adjusts - 1];
|
|
|
|
|
|
/* The first var adjust doesn't have an operation specified, so we set it to add. */
|
|
|
adjust->operation = group->g.determ.num_adjusts == 1 ? DSGA_OP_ADD : grf_load_byte(&buf);
|
|
|
adjust->operation = group->g.determ.num_adjusts == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)grf_load_byte(&buf);
|
|
|
adjust->variable = grf_load_byte(&buf);
|
|
|
adjust->parameter = IS_BYTE_INSIDE(adjust->variable, 0x60, 0x80) ? grf_load_byte(&buf) : 0;
|
|
|
|
|
|
varadjust = grf_load_byte(&buf);
|
|
|
adjust->shift_num = GB(varadjust, 0, 5);
|
|
|
adjust->type = GB(varadjust, 6, 2);
|
|
|
adjust->type = (DeterministicSpriteGroupAdjustType)GB(varadjust, 6, 2);
|
|
|
adjust->and_mask = grf_load_var(varsize, &buf);
|
|
|
|
|
|
if (adjust->type != DSGA_TYPE_NONE) {
|
|
|
adjust->add_val = grf_load_var(varsize, &buf);
|
|
|
adjust->divmod_val = grf_load_var(varsize, &buf);
|
|
|
} else {
|
|
@@ -1663,13 +1663,13 @@ static void NewSpriteGroup(byte *buf, in
|
|
|
}
|
|
|
|
|
|
/* Continue reading var adjusts while bit 5 is set. */
|
|
|
} while (HASBIT(varadjust, 5));
|
|
|
|
|
|
group->g.determ.num_ranges = grf_load_byte(&buf);
|
|
|
group->g.determ.ranges = calloc(group->g.determ.num_ranges, sizeof(*group->g.determ.ranges));
|
|
|
CallocT(&group->g.determ.ranges, group->g.determ.num_ranges);
|
|
|
|
|
|
check_length(bufend - buf, 2 + (2 + 2 * varsize) * group->g.determ.num_ranges, "NewSpriteGroup (Deterministic)");
|
|
|
|
|
|
for (i = 0; i < group->g.determ.num_ranges; i++) {
|
|
|
group->g.determ.ranges[i].group = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
|
|
group->g.determ.ranges[i].low = grf_load_var(varsize, &buf);
|
|
@@ -1695,13 +1695,13 @@ static void NewSpriteGroup(byte *buf, in
|
|
|
|
|
|
triggers = grf_load_byte(&buf);
|
|
|
group->g.random.triggers = GB(triggers, 0, 7);
|
|
|
group->g.random.cmp_mode = HASBIT(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
|
|
|
group->g.random.lowest_randbit = grf_load_byte(&buf);
|
|
|
group->g.random.num_groups = grf_load_byte(&buf);
|
|
|
group->g.random.groups = calloc(group->g.random.num_groups, sizeof(*group->g.random.groups));
|
|
|
CallocT(&group->g.random.groups, group->g.random.num_groups);
|
|
|
|
|
|
check_length(bufend - buf, 2 * group->g.random.num_groups, "NewSpriteGroup (Randomized) (2)");
|
|
|
|
|
|
for (i = 0; i < group->g.random.num_groups; i++) {
|
|
|
group->g.random.groups[i] = GetGroupFromGroupID(setid, type, grf_load_word(&buf));
|
|
|
}
|
|
@@ -1735,14 +1735,14 @@ static void NewSpriteGroup(byte *buf, in
|
|
|
|
|
|
group = AllocateSpriteGroup();
|
|
|
group->type = SGT_REAL;
|
|
|
|
|
|
group->g.real.num_loaded = num_loaded;
|
|
|
group->g.real.num_loading = num_loading;
|
|
|
if (num_loaded > 0) group->g.real.loaded = calloc(num_loaded, sizeof(*group->g.real.loaded));
|
|
|
if (num_loading > 0) group->g.real.loading = calloc(num_loading, sizeof(*group->g.real.loading));
|
|
|
if (num_loaded > 0) CallocT(&group->g.real.loaded, num_loaded);
|
|
|
if (num_loading > 0) CallocT(&group->g.real.loading, num_loading);
|
|
|
|
|
|
grfmsg(6, "NewSpriteGroup: New SpriteGroup 0x%02X, %u views, %u loaded, %u loading",
|
|
|
setid, sprites, num_loaded, num_loading);
|
|
|
|
|
|
for (i = 0; i < num_loaded; i++) {
|
|
|
uint16 spriteid = grf_load_word(&buf);
|
|
@@ -1881,13 +1881,13 @@ static void FeatureMapSpriteGroup(byte *
|
|
|
if (_cur_grffile->spriteset_start == 0 || _cur_grffile->spritegroups == 0) {
|
|
|
grfmsg(1, "FeatureMapSpriteGroup: No sprite set to work on! Skipping");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!wagover && last_engines_count != idcount) {
|
|
|
last_engines = realloc(last_engines, idcount);
|
|
|
ReallocT(&last_engines, idcount);
|
|
|
last_engines_count = idcount;
|
|
|
}
|
|
|
|
|
|
if (wagover) {
|
|
|
if (last_engines_count == 0) {
|
|
|
grfmsg(0, "FeatureMapSpriteGroup: WagonOverride: No engine to do override with");
|
|
@@ -2232,13 +2232,13 @@ static uint32 GetParamVal(byte param, ui
|
|
|
return _traininfo_vehicle_pitch;
|
|
|
|
|
|
case 0x92: /* Game mode */
|
|
|
return _game_mode;
|
|
|
|
|
|
case 0x9A: /* Always -1 */
|
|
|
return -1;
|
|
|
return UINT_MAX;
|
|
|
|
|
|
case 0x9D: /* TTD Platform, 00=TTDPatch, 01=OpenTTD */
|
|
|
return 1;
|
|
|
|
|
|
case 0x9E: /* Miscellaneous GRF features */
|
|
|
return _misc_grf_features;
|
|
@@ -2246,13 +2246,13 @@ static uint32 GetParamVal(byte param, ui
|
|
|
default:
|
|
|
/* GRF Parameter */
|
|
|
if (param < 0x80) return _cur_grffile->param[param];
|
|
|
|
|
|
/* In-game variable. */
|
|
|
grfmsg(1, "Unsupported in-game variable 0x%02X", param);
|
|
|
return -1;
|
|
|
return UINT_MAX;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* Action 0x06 */
|
|
|
static void CfgApply(byte *buf, int len)
|
|
|
{
|
|
@@ -2271,13 +2271,13 @@ static void CfgApply(byte *buf, int len)
|
|
|
uint32 pos = FioGetPos();
|
|
|
uint16 num = FioReadWord();
|
|
|
uint8 type = FioReadByte();
|
|
|
|
|
|
/* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */
|
|
|
if (type == 0xFF) {
|
|
|
_preload_sprite = malloc(num);
|
|
|
MallocT(&_preload_sprite, num);
|
|
|
FioReadBlock(_preload_sprite, num);
|
|
|
}
|
|
|
|
|
|
/* Reset the file position to the start of the next sprite */
|
|
|
FioSeekTo(pos, SEEK_SET);
|
|
|
|
|
@@ -2785,13 +2785,13 @@ static void ParamSet(byte *buf, int len)
|
|
|
|
|
|
_skip_sprites = -1;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
grfmsg(1, "GRM: Unable to allocate %d vehicles", count);
|
|
|
src1 = -1;
|
|
|
src1 = UINT_MAX;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case 0x08: /* General sprites */
|
|
|
switch (op) {
|
|
@@ -3023,13 +3023,13 @@ static void DefineGotoLabel(byte *buf, i
|
|
|
|
|
|
GRFLabel *label;
|
|
|
|
|
|
check_length(len, 1, "DefineGotoLabel");
|
|
|
buf++; len--;
|
|
|
|
|
|
label = malloc(sizeof(*label));
|
|
|
MallocT(&label, 1);
|
|
|
label->label = grf_load_byte(&buf);
|
|
|
label->nfo_line = _nfo_line;
|
|
|
label->pos = FioGetPos();
|
|
|
label->next = NULL;
|
|
|
|
|
|
/* Set up a linked list of goto targets which we will search in an Action 0x7/0x9 */
|
|
@@ -3195,13 +3195,13 @@ static void LoadFontGlyph(byte *buf, int
|
|
|
|
|
|
num_def = grf_load_byte(&buf);
|
|
|
|
|
|
check_length(len, 1 + num_def * 4, "LoadFontGlyph");
|
|
|
|
|
|
for (i = 0; i < num_def; i++) {
|
|
|
FontSize size = grf_load_byte(&buf);
|
|
|
FontSize size = (FontSize)grf_load_byte(&buf);
|
|
|
uint8 num_char = grf_load_byte(&buf);
|
|
|
uint16 base_char = grf_load_word(&buf);
|
|
|
uint c;
|
|
|
|
|
|
grfmsg(7, "LoadFontGlyph: Loading %u glyph(s) at 0x%04X for size %u", num_char, base_char, size);
|
|
|
|
|
@@ -3486,13 +3486,13 @@ static void InitNewGRFFile(const GRFConf
|
|
|
/* We already loaded it once. */
|
|
|
newfile->sprite_offset = sprite_offset;
|
|
|
_cur_grffile = newfile;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
newfile = calloc(1, sizeof(*newfile));
|
|
|
CallocT(&newfile, 1);
|
|
|
|
|
|
if (newfile == NULL) error ("Out of memory");
|
|
|
|
|
|
newfile->filename = strdup(config->filename);
|
|
|
newfile->sprite_offset = sprite_offset;
|
|
|
|
|
@@ -3614,13 +3614,13 @@ static void DecodeSpecialSprite(uint num
|
|
|
byte* buf;
|
|
|
byte action;
|
|
|
|
|
|
if (_preload_sprite == NULL) {
|
|
|
/* No preloaded sprite to work with; allocate and read the
|
|
|
* pseudo sprite content. */
|
|
|
buf = malloc(num);
|
|
|
MallocT(&buf, num);
|
|
|
if (buf == NULL) error("DecodeSpecialSprite: Could not allocate memory");
|
|
|
FioReadBlock(buf, num);
|
|
|
} else {
|
|
|
/* Use the preloaded sprite data. */
|
|
|
buf = _preload_sprite;
|
|
|
_preload_sprite = NULL;
|
|
@@ -3767,6 +3767,7 @@ void LoadNewGRF(uint load_index, uint fi
|
|
|
|
|
|
// Pre-calculate all refit masks after loading GRF files
|
|
|
CalculateRefitMasks();
|
|
|
}
|
|
|
|
|
|
|
|
|
|