mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r556) -newgrf: Some seemingly proper support for loading stages of grf files (octo & pasky).
This commit is contained in:
parent
2ab4669251
commit
76341a9173
82
grfspecial.c
82
grfspecial.c
|
@ -30,6 +30,7 @@ struct GRFFile {
|
||||||
|
|
||||||
static struct GRFFile *_cur_grffile, *_first_grffile;
|
static struct GRFFile *_cur_grffile, *_first_grffile;
|
||||||
static int _cur_spriteid;
|
static int _cur_spriteid;
|
||||||
|
static int _cur_stage;
|
||||||
|
|
||||||
static int32 _paramlist[0x7f];
|
static int32 _paramlist[0x7f];
|
||||||
static int _param_max;
|
static int _param_max;
|
||||||
|
@ -77,7 +78,8 @@ do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
static byte INLINE grf_load_byte(byte **buf) {
|
static byte INLINE grf_load_byte(byte **buf)
|
||||||
|
{
|
||||||
return *(*buf)++;
|
return *(*buf)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,19 +117,16 @@ static struct GRFFile *GetFileByGRFID(uint32 grfid)
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static struct GRFFile *GetFileByFilename(const char *filename)
|
||||||
/* Will be used very soon. */
|
|
||||||
static struct GRFFile *GetFileByFilename(char *filename)
|
|
||||||
{
|
{
|
||||||
struct GRFFile *file;
|
struct GRFFile *file;
|
||||||
|
|
||||||
file = _first_grffile;
|
file = _first_grffile;
|
||||||
while ((file != NULL) && strcmp(file->filename, filename))
|
while ((file != NULL) && strcmp(file->filename, filename))
|
||||||
file = retval->next;
|
file = file->next;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
|
typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
|
||||||
|
@ -900,7 +899,6 @@ static void SkipIf(byte *buf, int len)
|
||||||
* B condition-type
|
* B condition-type
|
||||||
* V value
|
* V value
|
||||||
* B num-sprites */
|
* B num-sprites */
|
||||||
/* TODO: We only support few tests. */
|
|
||||||
/* TODO: More params. More condition types. */
|
/* TODO: More params. More condition types. */
|
||||||
uint8 param;
|
uint8 param;
|
||||||
uint8 paramsize;
|
uint8 paramsize;
|
||||||
|
@ -933,8 +931,7 @@ static void SkipIf(byte *buf, int len)
|
||||||
param_val = _opt.landscape;
|
param_val = _opt.landscape;
|
||||||
break;
|
break;
|
||||||
case 0x84:
|
case 0x84:
|
||||||
/* XXX: This should be always true (at least until we get multiple loading stages?). */
|
param_val = _cur_stage;
|
||||||
param_val = 1;
|
|
||||||
break;
|
break;
|
||||||
case 0x85:
|
case 0x85:
|
||||||
param_val = _ttdpatch_flags[cond_val / 0x20];
|
param_val = _ttdpatch_flags[cond_val / 0x20];
|
||||||
|
@ -1231,7 +1228,6 @@ static void GRFInhibit(byte *buf, int len)
|
||||||
* B num Number of GRFIDs that follow
|
* B num Number of GRFIDs that follow
|
||||||
* D grfids GRFIDs of the files to deactivate */
|
* D grfids GRFIDs of the files to deactivate */
|
||||||
/* XXX: Should we handle forward deactivations? */
|
/* XXX: Should we handle forward deactivations? */
|
||||||
/* XXX: Even so will fully work only with stages support. */
|
|
||||||
|
|
||||||
byte num;
|
byte num;
|
||||||
int i;
|
int i;
|
||||||
|
@ -1271,7 +1267,8 @@ static void InitializeGRFSpecial(void)
|
||||||
| (1 << 0x17); /* newstartyear */
|
| (1 << 0x17); /* newstartyear */
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitNewGRFFile(const char *filename, int sprite_offset) {
|
void InitNewGRFFile(const char *filename, int sprite_offset)
|
||||||
|
{
|
||||||
struct GRFFile *newfile;
|
struct GRFFile *newfile;
|
||||||
|
|
||||||
newfile = malloc(sizeof(struct GRFFile));
|
newfile = malloc(sizeof(struct GRFFile));
|
||||||
|
@ -1297,12 +1294,12 @@ void InitNewGRFFile(const char *filename, int sprite_offset) {
|
||||||
|
|
||||||
/* Here we perform initial decoding of some special sprites (as are they
|
/* Here we perform initial decoding of some special sprites (as are they
|
||||||
* described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
|
* described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
|
||||||
* partial implementation yet; also, we ignore the stages stuff). */
|
* partial implementation yet). */
|
||||||
/* XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
|
/* XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
|
||||||
* a crafted invalid GRF file. We should tell that to the user somehow, or
|
* a crafted invalid GRF file. We should tell that to the user somehow, or
|
||||||
* better make this more robust in the future. */
|
* better make this more robust in the future. */
|
||||||
|
|
||||||
void DecodeSpecialSprite(int num, int spriteid)
|
void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage)
|
||||||
{
|
{
|
||||||
#define NUM_ACTIONS 0xF
|
#define NUM_ACTIONS 0xF
|
||||||
static const SpecialSpriteHandler handlers[NUM_ACTIONS] = {
|
static const SpecialSpriteHandler handlers[NUM_ACTIONS] = {
|
||||||
|
@ -1334,17 +1331,70 @@ void DecodeSpecialSprite(int num, int spriteid)
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cur_stage = stage;
|
||||||
_cur_spriteid = spriteid;
|
_cur_spriteid = spriteid;
|
||||||
|
|
||||||
for (i = 0; i != num; i++)
|
for (i = 0; i != num; i++)
|
||||||
buf[i] = FioReadByte();
|
buf[i] = FioReadByte();
|
||||||
|
|
||||||
action = buf[0];
|
action = buf[0];
|
||||||
if (action < NUM_ACTIONS) {
|
|
||||||
if (_cur_grffile->flags & 0x0001)
|
/* XXX: Action 0x03 is temporarily processed together with actions 0x01
|
||||||
|
* and 0x02 before it is fixed to be reentrant (probably storing the
|
||||||
|
* superset information in {struct GRFFile}). --pasky */
|
||||||
|
|
||||||
|
if (stage == 0) {
|
||||||
|
/* During initialization, actions 0, 3, 4, 5 and 7 are ignored. */
|
||||||
|
|
||||||
|
if ((action == 0x00) /*|| (action == 0x03)*/ || (action == 0x04)
|
||||||
|
|| (action == 0x05) || (action == 0x07)) {
|
||||||
|
DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 0, Skipped", action);
|
||||||
|
/* Do nothing. */
|
||||||
|
|
||||||
|
} else if (action < NUM_ACTIONS) {
|
||||||
|
DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 0", action);
|
||||||
|
handlers[action](buf, num);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (stage == 1) {
|
||||||
|
/* A .grf file is activated only if it was active when the game was
|
||||||
|
* started. If a game is loaded, only its active .grfs will be
|
||||||
|
* reactivated, unless "loadallgraphics on" is used. A .grf file is
|
||||||
|
* considered active if its action 8 has been processed, i.e. its
|
||||||
|
* action 8 hasn't been skipped using an action 7.
|
||||||
|
*
|
||||||
|
* During activation, only actions 0, 3, 4, 5, 7, 8, 9 and 0A are
|
||||||
|
* carried out. All others are ignored, because they only need to be
|
||||||
|
* processed once at initialization. */
|
||||||
|
|
||||||
|
if ((_cur_grffile == NULL) || strcmp(_cur_grffile->filename, filename))
|
||||||
|
_cur_grffile = GetFileByFilename(filename);
|
||||||
|
|
||||||
|
if (_cur_grffile == NULL)
|
||||||
|
error("File ``%s'' lost in cache.\n", filename);
|
||||||
|
|
||||||
|
if (!(_cur_grffile->flags & 0x0001)) {
|
||||||
|
DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1, Not activated", action);
|
||||||
|
/* Do nothing. */
|
||||||
|
|
||||||
|
} else if ((action == 0x00) /*|| (action == 0x03)*/ || (action == 0x04) || (action == 0x05)
|
||||||
|
|| (action == 0x07) || (action == 0x08) || (action == 0x09) || (action == 0x0A)) {
|
||||||
|
DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1", action);
|
||||||
handlers[action](buf, num);
|
handlers[action](buf, num);
|
||||||
|
|
||||||
|
} else if (action < NUM_ACTIONS) {
|
||||||
|
DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1, Skipped", action);
|
||||||
|
/* Do nothing. */
|
||||||
|
|
||||||
|
} else {
|
||||||
|
grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
|
error("Invalid stage %d", stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
|
@ -19,6 +19,8 @@ int _skip_sprites = 0;
|
||||||
int _replace_sprites_count[16];
|
int _replace_sprites_count[16];
|
||||||
int _replace_sprites_offset[16];
|
int _replace_sprites_offset[16];
|
||||||
|
|
||||||
|
static const char *_cur_grffile;
|
||||||
|
static int _loading_stage;
|
||||||
static int _skip_specials;
|
static int _skip_specials;
|
||||||
static SpriteHdr _cur_sprite;
|
static SpriteHdr _cur_sprite;
|
||||||
|
|
||||||
|
@ -85,7 +87,7 @@ static const uint16 * const _slopes_spriteindexes[] = {
|
||||||
static void CompactSpriteCache();
|
static void CompactSpriteCache();
|
||||||
|
|
||||||
void InitNewGRFFile(const char *filename, int sprite_offset);
|
void InitNewGRFFile(const char *filename, int sprite_offset);
|
||||||
void DecodeSpecialSprite(int num, int load_index);
|
void DecodeSpecialSprite(const char *filename, int num, int load_index, int stage);
|
||||||
|
|
||||||
static void ReadSpriteHeaderSkipData(int num, int load_index)
|
static void ReadSpriteHeaderSkipData(int num, int load_index)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +112,7 @@ static void ReadSpriteHeaderSkipData(int num, int load_index)
|
||||||
if (_skip_specials || deaf) {
|
if (_skip_specials || deaf) {
|
||||||
FioSkipBytes(num);
|
FioSkipBytes(num);
|
||||||
} else {
|
} else {
|
||||||
DecodeSpecialSprite(num, load_index);
|
DecodeSpecialSprite(_cur_grffile, num, load_index, _loading_stage);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -311,6 +313,7 @@ static int LoadNewGrfFile(const char *filename, int load_index, int file_index)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
FioOpenFile(file_index, filename);
|
FioOpenFile(file_index, filename);
|
||||||
|
_cur_grffile = filename;
|
||||||
_skip_specials = 0;
|
_skip_specials = 0;
|
||||||
_skip_sprites = 0;
|
_skip_sprites = 0;
|
||||||
|
|
||||||
|
@ -772,6 +775,8 @@ static void LoadSpriteTables()
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
|
_loading_stage = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note for developers:
|
* Note for developers:
|
||||||
* Keep in mind that when you add a LoadGrfIndexed in the 'if'-section below
|
* Keep in mind that when you add a LoadGrfIndexed in the 'if'-section below
|
||||||
|
@ -789,6 +794,8 @@ static void LoadSpriteTables()
|
||||||
// So just load all files from disk..
|
// So just load all files from disk..
|
||||||
|
|
||||||
int load_index = 0;
|
int load_index = 0;
|
||||||
|
int old_load_index = 0;
|
||||||
|
|
||||||
for(i=0; _filename_list[i] != NULL; i++) {
|
for(i=0; _filename_list[i] != NULL; i++) {
|
||||||
load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i);
|
load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i);
|
||||||
}
|
}
|
||||||
|
@ -805,11 +812,23 @@ static void LoadSpriteTables()
|
||||||
|
|
||||||
load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1;
|
load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1;
|
||||||
|
|
||||||
for(j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++) {
|
|
||||||
|
/* Load newgrf sprites */
|
||||||
|
|
||||||
|
_loading_stage = 0;
|
||||||
|
old_load_index = load_index;
|
||||||
|
|
||||||
|
for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++) {
|
||||||
InitNewGRFFile(_newgrf_files[j], load_index);
|
InitNewGRFFile(_newgrf_files[j], load_index);
|
||||||
load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
|
load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_loading_stage = 1;
|
||||||
|
load_index = old_load_index;
|
||||||
|
for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++)
|
||||||
|
load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
|
||||||
|
|
||||||
|
|
||||||
// If needed, save the cache to file
|
// If needed, save the cache to file
|
||||||
HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false);
|
HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue