(svn r4439) - NewGRF: Add support for Action 0x10. This also required an extra pre-stage (before initialize and activation) to scan the GRF file for GOTO labels. Big thanks for peter1138 for the guidance and answers, as well as parts of the code.

pull/155/head
Darkvater 18 years ago
parent fd8e02119c
commit cd25cba992

@ -38,7 +38,7 @@ static GRFFile *_cur_grffile;
GRFFile *_first_grffile;
static int _cur_spriteid;
static int _cur_stage;
static int _nfo_line;
static uint32 _nfo_line;
/* 32 * 8 = 256 flags. Apparently TTDPatch uses this many.. */
static uint32 _ttdpatch_flags[8];
@ -1849,6 +1849,8 @@ static void SkipIf(byte *buf, int len)
uint32 param_val = 0;
uint32 cond_val = 0;
bool result;
GRFLabel *label;
GRFLabel *choice = NULL;
check_length(len, 6, "SkipIf");
param = buf[1];
@ -1947,6 +1949,30 @@ static void SkipIf(byte *buf, int len)
}
numsprites = grf_load_byte(&buf);
/* numsprites can be a GOTO label if it has been defined in the GRF
* file. The jump will always be the first matching label that follows
* the current nfo_line. If no matching label is found, the first matching
* label in the file is used. */
for (label = _cur_grffile->label; label != NULL; label = label->next) {
if (label->label != numsprites) continue;
/* Remember a goto before the current line */
if (choice == NULL) choice = label;
/* If we find a label here, this is definitely good */
if (label->nfo_line > _nfo_line) {
choice = label;
break;
}
}
if (choice != NULL) {
grfmsg(GMS_NOTICE, "Jumping to label 0x%0X at line %d, test was true.", choice->label, choice->nfo_line);
FioSeekTo(choice->pos, SEEK_SET);
_nfo_line = choice->nfo_line;
return;
}
grfmsg(GMS_NOTICE, "Skipping %d sprites, test was true.", numsprites);
_skip_sprites = numsprites;
if (_skip_sprites == 0) {
@ -2065,6 +2091,12 @@ static void GRFComment(byte *buf, int len)
/* <0C> [<ignored...>]
*
* V ignored Anything following the 0C is ignored */
static char comment[256];
if (len == 1) return;
ttd_strlcpy(comment, buf + 1, minu(sizeof(comment), len));
grfmsg(GMS_NOTICE, "GRFComment: %s", comment);
}
/* Action 0x0D */
@ -2278,6 +2310,36 @@ static void GRFInhibit(byte *buf, int len)
}
}
static void DefineGotoLabel(byte *buf, int len)
{
/* <10> <label> [<comment>]
*
* B label The label to define
* V comment Optional comment - ignored */
GRFLabel *label;
check_length(len, 1, "GRFLabel");
buf++; len--;
label = malloc(sizeof(*label));
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 */
if (_cur_grffile->label == NULL) {
_cur_grffile->label = label;
} else {
/* Attach the label to the end of the list */
GRFLabel *l;
for (l = _cur_grffile->label; l->next != NULL; l = l->next);
l->next = label;
}
grfmsg(GMS_NOTICE, "DefineGotoLabel: GOTO target with label 0x%X", label->label);
}
static void InitializeGRFSpecial(void)
{
@ -2410,6 +2472,19 @@ static void ResetNewGRFData(void)
AddTypeToEngines();
}
/** Reset all NewGRFData that was used only while processing data */
static void ClearTemporaryNewGRFData(void)
{
/* Clear the GOTO labels used for GRF processing */
GRFLabel *l;
for (l = _cur_grffile->label; l != NULL;) {
GRFLabel *l2 = l->next;
free(l);
l = l2;
}
_cur_grffile->label = NULL;
}
static void InitNewGRFFile(const char* filename, int sprite_offset)
{
GRFFile *newfile;
@ -2482,14 +2557,18 @@ static void DecodeSpecialSprite(uint num, uint stage)
{
/* XXX: There is a difference between staged loading in TTDPatch and
* here. In TTDPatch, for some reason actions 1 and 2 are carried out
* during stage 0, whilst action 3 is carried out during stage 1 (to
* during stage 1, whilst action 3 is carried out during stage 2 (to
* "resolve" cargo IDs... wtf). This is a little problem, because cargo
* IDs are valid only within a given set (action 1) block, and may be
* overwritten after action 3 associates them. But overwriting happens
* in an earlier stage than associating, so... We just process actions
* 1 and 2 in stage 1 now, let's hope that won't get us into problems.
* 1 and 2 in stage 2 now, let's hope that won't get us into problems.
* --pasky */
uint32 action_mask = (stage == 0) ? 0x0001FB40 : 0x0001FFBF;
/* We need a pre-stage to set up GOTO labels of Action 0x10 because the grf
* is not in memory and scanning the file every time would be too expensive.
* In other stages we skip action 0x10 since it's already dealt with. */
static const uint32 action_mask[] = {0x10000, 0x0000FB40, 0x0000FFBF};
static const SpecialSpriteHandler handlers[] = {
/* 0x00 */ VehicleChangeInfo,
/* 0x01 */ NewSpriteSet,
@ -2507,7 +2586,7 @@ static void DecodeSpecialSprite(uint num, uint stage)
/* 0x0D */ ParamSet,
/* 0x0E */ GRFInhibit,
/* 0x0F */ NULL, // TODO implement
/* 0x10 */ NULL // TODO implement
/* 0x10 */ DefineGotoLabel,
};
byte* buf = malloc(num);
@ -2520,7 +2599,7 @@ static void DecodeSpecialSprite(uint num, uint stage)
if (action >= lengthof(handlers)) {
DEBUG(grf, 7) ("Skipping unknown action 0x%02X", action);
} else if (!HASBIT(action_mask, action)) {
} else if (!HASBIT(action_mask[stage], action)) {
DEBUG(grf, 7) ("Skipping action 0x%02X in stage %d", action, stage);
} else if (handlers[action] == NULL) {
DEBUG(grf, 7) ("Skipping unsupported Action 0x%02X", action);
@ -2548,7 +2627,7 @@ static void LoadNewGRFFile(const char* filename, uint file_index, uint stage)
if (stage != 0) {
_cur_grffile = GetFileByFilename(filename);
if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename);
if (!(_cur_grffile->flags & 0x0001)) return;
if (stage > 1 && !(_cur_grffile->flags & 0x0001)) return;
}
FioOpenFile(file_index, filename);
@ -2624,7 +2703,7 @@ void LoadNewGRF(uint load_index, uint file_index)
* in each loading stage, (try to) open each file specified in the config
* and load information from it. */
_custom_sprites_base = load_index;
for (stage = 0; stage < 2; stage++) {
for (stage = 0; stage <= 2; stage++) {
uint slot = file_index;
uint j;
@ -2637,6 +2716,7 @@ void LoadNewGRF(uint load_index, uint file_index)
}
if (stage == 0) InitNewGRFFile(_newgrf_files[j], _cur_spriteid);
LoadNewGRFFile(_newgrf_files[j], slot++, stage);
if (stage == 2) ClearTemporaryNewGRFData();
DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index);
}
}

@ -6,6 +6,13 @@
#include "sprite.h"
#include "station.h"
typedef struct GRFLabel {
byte label;
uint32 nfo_line;
uint32 pos;
struct GRFLabel *next;
} GRFLabel;
typedef struct GRFFile GRFFile;
struct GRFFile {
char *filename;
@ -39,6 +46,8 @@ struct GRFFile {
uint32 param[0x80];
uint param_end; /// one more than the highest set parameter
GRFLabel *label; ///< Pointer to the first label. This is a linked list, not an array.
};
extern GRFFile *_first_grffile;

Loading…
Cancel
Save