(svn r2868) Change the way NewGRFs are loaded: The loading process i no longer bolted onto the normal graphics loading.
This has two major advantages: - Removal of a maze of global variables and distinction of cases from the sprite loading routines, which weren't directly related to the loading process in the first place - NewGRF actions no longer occupy sprite slots - for example when using DBSetXL this saves about 2000 slots! (you could regard this as a bug fix) If i didn't make a major mistake this change should have no negative effect on NewGRF support, please test!
This commit is contained in:
		
							
								
								
									
										110
									
								
								gfxinit.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								gfxinit.c
									
									
									
									
									
								
							@@ -14,23 +14,6 @@
 | 
				
			|||||||
#include "variables.h"
 | 
					#include "variables.h"
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SPRITE_CACHE_SIZE 1024*1024
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define WANT_NEW_LRU
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* These are used in newgrf.c: */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int _skip_sprites = 0; // XXX
 | 
					 | 
				
			||||||
int _replace_sprites_count[16]; // XXX
 | 
					 | 
				
			||||||
int _replace_sprites_offset[16]; // XXX
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const char* _cur_grffile; // XXX
 | 
					 | 
				
			||||||
int _loading_stage; // XXX
 | 
					 | 
				
			||||||
int _skip_specials; // XXX
 | 
					 | 
				
			||||||
uint16 _custom_sprites_base; // XXX
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct MD5File {
 | 
					typedef struct MD5File {
 | 
				
			||||||
	const char * const filename;     // filename
 | 
						const char * const filename;     // filename
 | 
				
			||||||
	const md5_byte_t hash[16]; // md5 sum of the file
 | 
						const md5_byte_t hash[16]; // md5 sum of the file
 | 
				
			||||||
@@ -58,17 +41,12 @@ static const SpriteID * const _slopes_spriteindexes[] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int LoadGrfFile(const char *filename, int load_index, int file_index)
 | 
					static uint LoadGrfFile(const char* filename, uint load_index, int file_index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int load_index_org = load_index;
 | 
						uint load_index_org = load_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FioOpenFile(file_index, filename);
 | 
						FioOpenFile(file_index, filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Thou shalt use LoadNewGrfFile() if thou loadeth a GRF file that
 | 
					 | 
				
			||||||
	 * might contain some special sprites. */
 | 
					 | 
				
			||||||
	_skip_specials = 1;
 | 
					 | 
				
			||||||
	_skip_sprites = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	DEBUG(spritecache, 2) ("Reading grf-file ``%s''", filename);
 | 
						DEBUG(spritecache, 2) ("Reading grf-file ``%s''", filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (LoadNextSprite(load_index, file_index)) {
 | 
						while (LoadNextSprite(load_index, file_index)) {
 | 
				
			||||||
@@ -82,61 +60,18 @@ static int LoadGrfFile(const char *filename, int load_index, int file_index)
 | 
				
			|||||||
	return load_index - load_index_org;
 | 
						return load_index - load_index_org;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int LoadNewGrfFile(const char *filename, int load_index, int file_index)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	FioOpenFile(file_index, filename);
 | 
					 | 
				
			||||||
	_cur_grffile = filename;
 | 
					 | 
				
			||||||
	_skip_specials = 0;
 | 
					 | 
				
			||||||
	_skip_sprites = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	DEBUG(spritecache, 2) ("Reading newgrf-file ``%s'' [offset: %u]",
 | 
					 | 
				
			||||||
			filename, load_index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Skip the first sprite; we don't care about how many sprites this
 | 
					 | 
				
			||||||
	 * does contain; newest TTDPatches and George's longvehicles don't
 | 
					 | 
				
			||||||
	 * neither, apparently. */
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		int length;
 | 
					 | 
				
			||||||
		byte type;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		length = FioReadWord();
 | 
					 | 
				
			||||||
		type = FioReadByte();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (length == 4 && type == 0xFF) {
 | 
					 | 
				
			||||||
			FioReadDword();
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			error("Custom .grf has invalid format.");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; LoadNextSprite(load_index + i, file_index); i++) {
 | 
					 | 
				
			||||||
		if (load_index + i >= MAX_SPRITES)
 | 
					 | 
				
			||||||
			error("Too many sprites (0x%X). Recompile with higher MAX_SPRITES value or remove some custom GRF files.",
 | 
					 | 
				
			||||||
			      load_index + i);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Clean up. */
 | 
					 | 
				
			||||||
	_skip_sprites = 0;
 | 
					 | 
				
			||||||
	memset(_replace_sprites_count, 0, sizeof(_replace_sprites_count));
 | 
					 | 
				
			||||||
	memset(_replace_sprites_offset, 0, sizeof(_replace_sprites_offset));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return i;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void LoadGrfIndexed(const char* filename, const SpriteID* index_tbl, int file_index)
 | 
					static void LoadGrfIndexed(const char* filename, const SpriteID* index_tbl, int file_index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int start;
 | 
						uint start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FioOpenFile(file_index, filename);
 | 
						FioOpenFile(file_index, filename);
 | 
				
			||||||
	_skip_specials = 1;
 | 
					 | 
				
			||||||
	_skip_sprites = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DEBUG(spritecache, 2) ("Reading indexed grf-file ``%s''", filename);
 | 
						DEBUG(spritecache, 2) ("Reading indexed grf-file ``%s''", filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (; (start = *index_tbl++) != 0xffff;) {
 | 
						for (; (start = *index_tbl++) != 0xffff;) {
 | 
				
			||||||
		int end = *index_tbl++;
 | 
							uint end = *index_tbl++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (start == 0xfffe) { // skip sprites (amount in second var)
 | 
							if (start == 0xfffe) { // skip sprites (amount in second var)
 | 
				
			||||||
			SkipSprites(end);
 | 
								SkipSprites(end);
 | 
				
			||||||
		} else { // load sprites and use indexes from start to end
 | 
							} else { // load sprites and use indexes from start to end
 | 
				
			||||||
@@ -153,8 +88,6 @@ static void LoadGrfIndexed(const char *filename, const SpriteID *index_tbl, int
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static byte _sprite_page_to_load = 0xFF;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define OPENTTD_SPRITES_COUNT 100
 | 
					#define OPENTTD_SPRITES_COUNT 100
 | 
				
			||||||
static const SpriteID _openttd_grf_indexes[] = {
 | 
					static const SpriteID _openttd_grf_indexes[] = {
 | 
				
			||||||
	SPR_OPENTTD_BASE + 0, SPR_OPENTTD_BASE + 7, // icons etc
 | 
						SPR_OPENTTD_BASE + 0, SPR_OPENTTD_BASE + 7, // icons etc
 | 
				
			||||||
@@ -170,7 +103,6 @@ static const SpriteID _openttd_grf_indexes[] = {
 | 
				
			|||||||
	0xffff,
 | 
						0xffff,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* FUNCTIONS FOR CHECKING MD5 SUMS OF GRF FILES */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Check that the supplied MD5 hash matches that stored for the supplied filename */
 | 
					/* Check that the supplied MD5 hash matches that stored for the supplied filename */
 | 
				
			||||||
static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
 | 
					static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
 | 
				
			||||||
@@ -269,21 +201,15 @@ void CheckExternalFiles(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static byte _sprite_page_to_load = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void LoadSpriteTables(void)
 | 
					static void LoadSpriteTables(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int load_index = 0;
 | 
						uint load_index = 0;
 | 
				
			||||||
	uint i;
 | 
						uint i;
 | 
				
			||||||
	uint j;
 | 
					 | 
				
			||||||
	const FileList *files; // list of grf files to be loaded. Either Windows files or DOS files
 | 
						const FileList *files; // list of grf files to be loaded. Either Windows files or DOS files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_loading_stage = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * TODO:
 | 
					 | 
				
			||||||
	 *   I think we can live entirely without Indexed GRFs, but I have to
 | 
					 | 
				
			||||||
	 *   invest that further. --octo
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	files = _use_dos_palette? &files_dos : &files_win;
 | 
						files = _use_dos_palette? &files_dos : &files_win;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; files->basic[i].filename != NULL; i++) {
 | 
						for (i = 0; files->basic[i].filename != NULL; i++) {
 | 
				
			||||||
@@ -310,23 +236,7 @@ static void LoadSpriteTables(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1;
 | 
						load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LoadNewGRF(load_index, i);
 | 
				
			||||||
	/* Load newgrf sprites
 | 
					 | 
				
			||||||
	 * in each loading stage, (try to) open each file specified in the config
 | 
					 | 
				
			||||||
	 * and load information from it. */
 | 
					 | 
				
			||||||
	_custom_sprites_base = load_index;
 | 
					 | 
				
			||||||
	for (_loading_stage = 0; _loading_stage < 2; _loading_stage++) {
 | 
					 | 
				
			||||||
		load_index = _custom_sprites_base;
 | 
					 | 
				
			||||||
		for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++) {
 | 
					 | 
				
			||||||
			if (!FiosCheckFileExists(_newgrf_files[j])) {
 | 
					 | 
				
			||||||
				// TODO: usrerror()
 | 
					 | 
				
			||||||
				error("NewGRF file missing: %s", _newgrf_files[j]);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (_loading_stage == 0) InitNewGRFFile(_newgrf_files[j], load_index);
 | 
					 | 
				
			||||||
			load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
 | 
					 | 
				
			||||||
			DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										288
									
								
								newgrf.c
									
									
									
									
									
								
							
							
						
						
									
										288
									
								
								newgrf.c
									
									
									
									
									
								
							@@ -10,6 +10,7 @@
 | 
				
			|||||||
#include "fileio.h"
 | 
					#include "fileio.h"
 | 
				
			||||||
#include "functions.h"
 | 
					#include "functions.h"
 | 
				
			||||||
#include "engine.h"
 | 
					#include "engine.h"
 | 
				
			||||||
 | 
					#include "spritecache.h"
 | 
				
			||||||
#include "station.h"
 | 
					#include "station.h"
 | 
				
			||||||
#include "sprite.h"
 | 
					#include "sprite.h"
 | 
				
			||||||
#include "newgrf.h"
 | 
					#include "newgrf.h"
 | 
				
			||||||
@@ -25,9 +26,9 @@
 | 
				
			|||||||
 * served as subject to the initial testing of this codec. */
 | 
					 * served as subject to the initial testing of this codec. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int _skip_sprites;
 | 
					uint16 _custom_sprites_base;
 | 
				
			||||||
extern int _replace_sprites_count[16];
 | 
					static int _skip_sprites; // XXX
 | 
				
			||||||
extern int _replace_sprites_offset[16];
 | 
					static uint _file_index; // XXX
 | 
				
			||||||
extern int _traininfo_vehicle_pitch;
 | 
					extern int _traininfo_vehicle_pitch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GRFFile *_cur_grffile;
 | 
					static GRFFile *_cur_grffile;
 | 
				
			||||||
@@ -1156,14 +1157,29 @@ static void NewSpriteSet(byte *buf, int len)
 | 
				
			|||||||
	 *                         different sprites that make up a station */
 | 
						 *                         different sprites that make up a station */
 | 
				
			||||||
	/* TODO: No stations support. */
 | 
						/* TODO: No stations support. */
 | 
				
			||||||
	uint8 feature;
 | 
						uint8 feature;
 | 
				
			||||||
 | 
						uint num_sets;
 | 
				
			||||||
 | 
						uint num_ents;
 | 
				
			||||||
 | 
						uint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	check_length(len, 4, "NewSpriteSet");
 | 
						check_length(len, 4, "NewSpriteSet");
 | 
				
			||||||
	feature = buf[1];
 | 
						feature = buf[1];
 | 
				
			||||||
 | 
						num_sets = buf[2];
 | 
				
			||||||
 | 
						num_ents = buf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_cur_grffile->spriteset_start = _cur_spriteid + 1;
 | 
						_cur_grffile->spriteset_start = _cur_spriteid;
 | 
				
			||||||
	_cur_grffile->spriteset_feature = feature;
 | 
						_cur_grffile->spriteset_feature = feature;
 | 
				
			||||||
	_cur_grffile->spriteset_numsets = buf[2];
 | 
						_cur_grffile->spriteset_numsets = num_sets;
 | 
				
			||||||
	_cur_grffile->spriteset_numents = buf[3];
 | 
						_cur_grffile->spriteset_numents = num_ents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DEBUG(grf, 7) (
 | 
				
			||||||
 | 
							"New sprite set at %d of type %d, "
 | 
				
			||||||
 | 
							"consisting of %d sets with %d views each (total %d)",
 | 
				
			||||||
 | 
							_cur_spriteid, feature, num_sets, num_ents, num_sets * num_ents
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num_sets * num_ents; i++) {
 | 
				
			||||||
 | 
							LoadNextSprite(_cur_spriteid++, _file_index);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Action 0x02 */
 | 
					/* Action 0x02 */
 | 
				
			||||||
@@ -1790,7 +1806,7 @@ static void SkipIf(byte *buf, int len)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	numsprites = grf_load_byte(&buf);
 | 
						numsprites = grf_load_byte(&buf);
 | 
				
			||||||
	grfmsg(GMS_NOTICE, "Skipping %d->+%d sprites, test was true.", _cur_spriteid - _cur_grffile->sprite_offset, numsprites);
 | 
						grfmsg(GMS_NOTICE, "Skipping %d sprites, test was true.", numsprites);
 | 
				
			||||||
	_skip_sprites = numsprites;
 | 
						_skip_sprites = numsprites;
 | 
				
			||||||
	if (_skip_sprites == 0) {
 | 
						if (_skip_sprites == 0) {
 | 
				
			||||||
		/* Zero means there are no sprites to skip, so
 | 
							/* Zero means there are no sprites to skip, so
 | 
				
			||||||
@@ -1838,27 +1854,23 @@ static void SpriteReplace(byte *buf, int len)
 | 
				
			|||||||
	 * B num-sprites   How many sprites are in this set
 | 
						 * B num-sprites   How many sprites are in this set
 | 
				
			||||||
	 * W first-sprite  First sprite number to replace */
 | 
						 * W first-sprite  First sprite number to replace */
 | 
				
			||||||
	uint8 num_sets;
 | 
						uint8 num_sets;
 | 
				
			||||||
	int i;
 | 
						uint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buf++; /* skip action byte */
 | 
						buf++; /* skip action byte */
 | 
				
			||||||
	num_sets = grf_load_byte(&buf);
 | 
						num_sets = grf_load_byte(&buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (num_sets > 16) {
 | 
						for (i = 0; i < num_sets; i++) {
 | 
				
			||||||
		grfmsg(GMS_ERROR, "SpriteReplace: Too many sets (%d), taking only the first 16!", num_sets);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < 16; i++) {
 | 
					 | 
				
			||||||
		if (i < num_sets) {
 | 
					 | 
				
			||||||
		uint8 num_sprites = grf_load_byte(&buf);
 | 
							uint8 num_sprites = grf_load_byte(&buf);
 | 
				
			||||||
		uint16 first_sprite = grf_load_word(&buf);
 | 
							uint16 first_sprite = grf_load_word(&buf);
 | 
				
			||||||
 | 
							uint j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			_replace_sprites_count[i] = num_sprites;
 | 
							grfmsg(GMS_NOTICE,
 | 
				
			||||||
			_replace_sprites_offset[i] = first_sprite;
 | 
								"SpriteReplace: [Set %d] Changing %d sprites, beginning with %d",
 | 
				
			||||||
			grfmsg(GMS_NOTICE, "SpriteReplace: [Set %d] Changing %d sprites, beginning with %d",
 | 
								i, num_sprites, first_sprite
 | 
				
			||||||
					i, num_sprites, first_sprite);
 | 
							);
 | 
				
			||||||
		} else {
 | 
					
 | 
				
			||||||
			_replace_sprites_count[i] = 0;
 | 
							for (j = 0; j < num_sprites; j++) {
 | 
				
			||||||
			_replace_sprites_offset[i] = 0;
 | 
								LoadNextSprite(first_sprite + j, _file_index); // XXX
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2090,7 +2102,7 @@ static void InitializeGRFSpecial(void)
 | 
				
			|||||||
	                   | (1 << 0x17); /* newstartyear */
 | 
						                   | (1 << 0x17); /* newstartyear */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void InitNewGRFFile(const char *filename, int sprite_offset)
 | 
					static void InitNewGRFFile(const char* filename, int sprite_offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GRFFile *newfile;
 | 
						GRFFile *newfile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2126,45 +2138,8 @@ void InitNewGRFFile(const char *filename, int sprite_offset)
 | 
				
			|||||||
/* 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. */
 | 
				
			||||||
 | 
					static void DecodeSpecialSprite(const char* filename, uint num, uint stage)
 | 
				
			||||||
void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#define NUM_ACTIONS 0xF
 | 
					 | 
				
			||||||
	static const SpecialSpriteHandler handlers[NUM_ACTIONS] = {
 | 
					 | 
				
			||||||
		/* 0x0 */ VehicleChangeInfo,
 | 
					 | 
				
			||||||
		/* 0x1 */ NewSpriteSet,
 | 
					 | 
				
			||||||
		/* 0x2 */ NewSpriteGroup,
 | 
					 | 
				
			||||||
		/* 0x3 */ NewVehicle_SpriteGroupMapping,
 | 
					 | 
				
			||||||
		/* 0x4 */ VehicleNewName,
 | 
					 | 
				
			||||||
		/* 0x5 */ GraphicsNew,
 | 
					 | 
				
			||||||
		/* 0x6 */ CfgApply,
 | 
					 | 
				
			||||||
		/* 0x7 */ SkipIf,
 | 
					 | 
				
			||||||
		/* 0x8 */ GRFInfo,
 | 
					 | 
				
			||||||
		/* 0x9 */ SkipIf,
 | 
					 | 
				
			||||||
		/* 0xa */ SpriteReplace,
 | 
					 | 
				
			||||||
		/* 0xb */ GRFError,
 | 
					 | 
				
			||||||
		/* 0xc */ GRFComment,
 | 
					 | 
				
			||||||
		/* 0xd */ ParamSet,
 | 
					 | 
				
			||||||
		/* 0xe */ GRFInhibit,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	static bool initialized = false;
 | 
					 | 
				
			||||||
	byte action;
 | 
					 | 
				
			||||||
	byte *buf = malloc(num);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buf == NULL) error("DecodeSpecialSprite: Could not allocate memory");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!initialized) {
 | 
					 | 
				
			||||||
		InitializeGRFSpecial();
 | 
					 | 
				
			||||||
		initialized = true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_cur_stage = stage;
 | 
					 | 
				
			||||||
	_cur_spriteid = spriteid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	FioReadBlock(buf, num);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	action = buf[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* XXX: There is a difference between staged loading in TTDPatch and
 | 
						/* XXX: There is a difference between staged loading in TTDPatch and
 | 
				
			||||||
	 * here.  In TTDPatch, for some reason actions 1 and 2 are carried out
 | 
						 * 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 0, whilst action 3 is carried out during stage 1 (to
 | 
				
			||||||
@@ -2174,31 +2149,63 @@ void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage)
 | 
				
			|||||||
	 * in an earlier stage than associating, so...  We just process actions
 | 
						 * 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 1 now, let's hope that won't get us into problems.
 | 
				
			||||||
	 * --pasky */
 | 
						 * --pasky */
 | 
				
			||||||
 | 
						uint32 action_mask = (stage == 0) ? 0x0001FF40 : 0x0001FFBF;
 | 
				
			||||||
 | 
						static const SpecialSpriteHandler handlers[] = {
 | 
				
			||||||
 | 
							/* 0x00 */ VehicleChangeInfo,
 | 
				
			||||||
 | 
							/* 0x01 */ NewSpriteSet,
 | 
				
			||||||
 | 
							/* 0x02 */ NewSpriteGroup,
 | 
				
			||||||
 | 
							/* 0x03 */ NewVehicle_SpriteGroupMapping,
 | 
				
			||||||
 | 
							/* 0x04 */ VehicleNewName,
 | 
				
			||||||
 | 
							/* 0x05 */ GraphicsNew,
 | 
				
			||||||
 | 
							/* 0x06 */ CfgApply,
 | 
				
			||||||
 | 
							/* 0x07 */ SkipIf,
 | 
				
			||||||
 | 
							/* 0x08 */ GRFInfo,
 | 
				
			||||||
 | 
							/* 0x09 */ SkipIf,
 | 
				
			||||||
 | 
							/* 0x0A */ SpriteReplace,
 | 
				
			||||||
 | 
							/* 0x0B */ GRFError,
 | 
				
			||||||
 | 
							/* 0x0C */ GRFComment,
 | 
				
			||||||
 | 
							/* 0x0D */ ParamSet,
 | 
				
			||||||
 | 
							/* 0x0E */ GRFInhibit,
 | 
				
			||||||
 | 
							/* 0x0F */ NULL, // TODO implement
 | 
				
			||||||
 | 
							/* 0x10 */ NULL  // TODO implement
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (stage == 0) {
 | 
						byte* buf = malloc(num);
 | 
				
			||||||
		switch (action) {
 | 
						byte action;
 | 
				
			||||||
			case 0x00:
 | 
					 | 
				
			||||||
			case 0x01:
 | 
					 | 
				
			||||||
			case 0x02:
 | 
					 | 
				
			||||||
			case 0x03:
 | 
					 | 
				
			||||||
			case 0x04:
 | 
					 | 
				
			||||||
			case 0x05:
 | 
					 | 
				
			||||||
			case 0x07:
 | 
					 | 
				
			||||||
				/* During initialization, these actions are ignored. */
 | 
					 | 
				
			||||||
				DEBUG (grf, 7) (
 | 
					 | 
				
			||||||
					"DecodeSpecialSprite: Action: %x, Stage 0, Skipped", action);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			default:
 | 
						if (buf == NULL) error("DecodeSpecialSprite: Could not allocate memory");
 | 
				
			||||||
				if (action < NUM_ACTIONS) {
 | 
					
 | 
				
			||||||
					DEBUG (grf, 7) ("DecodeSpecialSprite: Action: %x, Stage 0", action);
 | 
						FioReadBlock(buf, num);
 | 
				
			||||||
 | 
						action = buf[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (action >= lengthof(handlers)) {
 | 
				
			||||||
 | 
							DEBUG(grf, 7) ("Skipping unknown action 0x%02X", action);
 | 
				
			||||||
 | 
							free(buf);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!HASBIT(action_mask, action)) {
 | 
				
			||||||
 | 
							DEBUG(grf, 7) ("Skipping action 0x%02X in stage %d", action, stage);
 | 
				
			||||||
 | 
							free(buf);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (handlers[action] == NULL) {
 | 
				
			||||||
 | 
							DEBUG(grf, 7) ("Skipping unsupported Action 0x%02X", action);
 | 
				
			||||||
 | 
							free(buf);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DEBUG(grf, 7) ("Handling action 0x%02X in stage %d", action, stage);
 | 
				
			||||||
	handlers[action](buf, num);
 | 
						handlers[action](buf, num);
 | 
				
			||||||
				} else {
 | 
						free(buf);
 | 
				
			||||||
					grfmsg(GMS_WARN,
 | 
					 | 
				
			||||||
						"Unknown special sprite action %x, skipping.", action);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
	} else if (stage == 1) {
 | 
					
 | 
				
			||||||
 | 
					static void LoadNewGRFFile(const char* filename, uint file_index, uint stage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint16 num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* A .grf file is activated only if it was active when the game was
 | 
						/* 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
 | 
						 * started.  If a game is loaded, only its active .grfs will be
 | 
				
			||||||
	 * reactivated, unless "loadallgraphics on" is used.  A .grf file is
 | 
						 * reactivated, unless "loadallgraphics on" is used.  A .grf file is
 | 
				
			||||||
@@ -2208,48 +2215,93 @@ void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage)
 | 
				
			|||||||
	 * During activation, only actions 0, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
 | 
						 * During activation, only actions 0, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
 | 
				
			||||||
	 * carried out.  All others are ignored, because they only need to be
 | 
						 * carried out.  All others are ignored, because they only need to be
 | 
				
			||||||
	 * processed once at initialization.  */
 | 
						 * processed once at initialization.  */
 | 
				
			||||||
 | 
						if (stage != 0) {
 | 
				
			||||||
		if (_cur_grffile == NULL || strcmp(_cur_grffile->filename, filename) != 0)
 | 
					 | 
				
			||||||
		_cur_grffile = GetFileByFilename(filename);
 | 
							_cur_grffile = GetFileByFilename(filename);
 | 
				
			||||||
 | 
							if (_cur_grffile == NULL) error("File ``%s'' lost in cache.\n", filename);
 | 
				
			||||||
		if (_cur_grffile == NULL)
 | 
							if (!(_cur_grffile->flags & 0x0001)) return;
 | 
				
			||||||
			error("File ``%s'' lost in cache.\n", filename);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (_cur_grffile->flags & 0x0001) {
 | 
					 | 
				
			||||||
			switch (action) {
 | 
					 | 
				
			||||||
				case 0x00:
 | 
					 | 
				
			||||||
				case 0x01:
 | 
					 | 
				
			||||||
				case 0x02:
 | 
					 | 
				
			||||||
				case 0x03:
 | 
					 | 
				
			||||||
				case 0x04:
 | 
					 | 
				
			||||||
				case 0x05:
 | 
					 | 
				
			||||||
				case 0x07:
 | 
					 | 
				
			||||||
				case 0x08:
 | 
					 | 
				
			||||||
				case 0x09:
 | 
					 | 
				
			||||||
				case 0x0A:
 | 
					 | 
				
			||||||
				case 0x0B:
 | 
					 | 
				
			||||||
					DEBUG (grf, 7) ("DecodeSpecialSprite: Action: %x, Stage 1", action);
 | 
					 | 
				
			||||||
					handlers[action](buf, num);
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					if (action < NUM_ACTIONS) {
 | 
					 | 
				
			||||||
						DEBUG (grf, 7) (
 | 
					 | 
				
			||||||
							"DecodeSpecialSprite: Action: %x, Stage 1, Skipped", action);
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						grfmsg(GMS_WARN,
 | 
					 | 
				
			||||||
							"Unknown special sprite action %x, skipping.", action);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
					break;
 | 
					
 | 
				
			||||||
 | 
						FioOpenFile(file_index, filename);
 | 
				
			||||||
 | 
						_file_index = file_index; // XXX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DEBUG(grf, 7) ("Reading NewGRF-file '%s'", filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Skip the first sprite; we don't care about how many sprites this
 | 
				
			||||||
 | 
						 * does contain; newest TTDPatches and George's longvehicles don't
 | 
				
			||||||
 | 
						 * neither, apparently. */
 | 
				
			||||||
 | 
						if (FioReadWord() == 4 && FioReadByte() == 0xFF) {
 | 
				
			||||||
 | 
							FioReadDword();
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							error("Custom .grf has invalid format.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_skip_sprites = 0; // XXX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((num = FioReadWord()) != 0) {
 | 
				
			||||||
 | 
							byte type = FioReadByte();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type == 0xFF) {
 | 
				
			||||||
 | 
								if (_skip_sprites == 0) {
 | 
				
			||||||
 | 
									DecodeSpecialSprite(filename, num, stage);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									FioSkipBytes(num);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			DEBUG (grf, 7) (
 | 
								if (_skip_sprites == 0) DEBUG(grf, 7) ("Skipping unexpected sprite");
 | 
				
			||||||
				"DecodeSpecialSprite: Action: %x, Stage 1, Not activated", action);
 | 
					
 | 
				
			||||||
		}
 | 
								FioSkipBytes(7);
 | 
				
			||||||
 | 
								num -= 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (type & 2) {
 | 
				
			||||||
 | 
									FioSkipBytes(num);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
		error("Invalid stage %d", stage);
 | 
									while (num > 0) {
 | 
				
			||||||
 | 
										int8 i = FioReadByte();
 | 
				
			||||||
 | 
										if (i >= 0) {
 | 
				
			||||||
 | 
											num -= i;
 | 
				
			||||||
 | 
											FioSkipBytes(i);
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											i = -(i >> 3);
 | 
				
			||||||
 | 
											num -= i;
 | 
				
			||||||
 | 
											FioReadByte();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(buf);
 | 
							if (_skip_sprites > 0) _skip_sprites--;
 | 
				
			||||||
#undef NUM_ACTIONS
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoadNewGRF(uint load_index, uint file_index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static bool initialized = false; // XXX yikes
 | 
				
			||||||
 | 
						uint stage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!initialized) {
 | 
				
			||||||
 | 
							InitializeGRFSpecial();
 | 
				
			||||||
 | 
							initialized = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Load newgrf sprites
 | 
				
			||||||
 | 
						 * 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++) {
 | 
				
			||||||
 | 
							uint j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_cur_stage = stage;
 | 
				
			||||||
 | 
							_cur_spriteid = load_index;
 | 
				
			||||||
 | 
							for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j] != NULL; j++) {
 | 
				
			||||||
 | 
								if (!FiosCheckFileExists(_newgrf_files[j])) {
 | 
				
			||||||
 | 
									// TODO: usrerror()
 | 
				
			||||||
 | 
									error("NewGRF file missing: %s", _newgrf_files[j]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (stage == 0) InitNewGRFFile(_newgrf_files[j], _cur_spriteid);
 | 
				
			||||||
 | 
								LoadNewGRFFile(_newgrf_files[j], file_index++, stage); // XXX different file indices in both stages?
 | 
				
			||||||
 | 
								DEBUG(spritecache, 2) ("Currently %i sprites are loaded", load_index);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								newgrf.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								newgrf.h
									
									
									
									
									
								
							@@ -39,9 +39,8 @@ struct GRFFile {
 | 
				
			|||||||
extern int _grffile_count;
 | 
					extern int _grffile_count;
 | 
				
			||||||
extern GRFFile *_first_grffile;
 | 
					extern GRFFile *_first_grffile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void InitNewGRFFile(const char *filename, int sprite_offset);
 | 
					 | 
				
			||||||
void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoadNewGRF(uint load_index, uint file_index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* NEWGRF_H */
 | 
					#endif /* NEWGRF_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,25 +7,12 @@
 | 
				
			|||||||
#include "spritecache.h"
 | 
					#include "spritecache.h"
 | 
				
			||||||
#include "table/sprites.h"
 | 
					#include "table/sprites.h"
 | 
				
			||||||
#include "fileio.h"
 | 
					#include "fileio.h"
 | 
				
			||||||
#include "newgrf.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SPRITE_CACHE_SIZE 1024*1024
 | 
					#define SPRITE_CACHE_SIZE 1024*1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define WANT_NEW_LRU
 | 
					#define WANT_NEW_LRU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* These are used in newgrf.c: */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int _skip_sprites; // XXX
 | 
					 | 
				
			||||||
extern int _replace_sprites_count[16]; // XXX
 | 
					 | 
				
			||||||
extern int _replace_sprites_offset[16]; // XXX
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern const char* _cur_grffile; // XXX
 | 
					 | 
				
			||||||
extern int _loading_stage; // XXX
 | 
					 | 
				
			||||||
extern int _skip_specials; // XXX
 | 
					 | 
				
			||||||
static Sprite _cur_sprite; // XXX
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void* _sprite_ptr[MAX_SPRITES];
 | 
					static void* _sprite_ptr[MAX_SPRITES];
 | 
				
			||||||
static uint32 _sprite_file_pos[MAX_SPRITES];
 | 
					static uint32 _sprite_file_pos[MAX_SPRITES];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -47,33 +34,16 @@ static int _compact_cache_counter;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void CompactSpriteCache(void);
 | 
					static void CompactSpriteCache(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool ReadSpriteHeaderSkipData(int load_index)
 | 
					static bool ReadSpriteHeaderSkipData(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint16 num = FioReadWord();
 | 
						uint16 num = FioReadWord();
 | 
				
			||||||
	byte type;
 | 
						byte type;
 | 
				
			||||||
	int deaf = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (num == 0) return false;
 | 
						if (num == 0) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_skip_sprites) {
 | 
					 | 
				
			||||||
		if (_skip_sprites > 0)
 | 
					 | 
				
			||||||
			_skip_sprites--;
 | 
					 | 
				
			||||||
		deaf = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	type = FioReadByte();
 | 
						type = FioReadByte();
 | 
				
			||||||
	_cur_sprite.info = type;
 | 
					 | 
				
			||||||
	if (type == 0xFF) {
 | 
						if (type == 0xFF) {
 | 
				
			||||||
		/* We need to really skip only special sprites in the deaf
 | 
					 | 
				
			||||||
		 * mode.  It won't hurt to proceed regular sprites as usual
 | 
					 | 
				
			||||||
		 * because if no special sprite referencing to them is
 | 
					 | 
				
			||||||
		 * processed, they themselves are never referenced and loaded
 | 
					 | 
				
			||||||
		 * on their own. */
 | 
					 | 
				
			||||||
		if (_skip_specials || deaf) {
 | 
					 | 
				
			||||||
		FioSkipBytes(num);
 | 
							FioSkipBytes(num);
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			DecodeSpecialSprite(_cur_grffile, num, load_index, _loading_stage);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -169,35 +139,7 @@ bool LoadNextSprite(int load_index, byte file_index)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	uint32 file_pos = FioGetPos() | (file_index << 24);
 | 
						uint32 file_pos = FioGetPos() | (file_index << 24);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ReadSpriteHeaderSkipData(load_index)) return false;
 | 
						if (!ReadSpriteHeaderSkipData()) return false;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (_replace_sprites_count[0] > 0 && _cur_sprite.info != 0xFF) {
 | 
					 | 
				
			||||||
		int count = _replace_sprites_count[0];
 | 
					 | 
				
			||||||
		int offset = _replace_sprites_offset[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		_replace_sprites_offset[0]++;
 | 
					 | 
				
			||||||
		_replace_sprites_count[0]--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((offset + count) <= MAX_SPRITES) {
 | 
					 | 
				
			||||||
			load_index = offset;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			DEBUG(spritecache, 1) ("Sprites to be replaced are out of range: %x+%x",
 | 
					 | 
				
			||||||
					count, offset);
 | 
					 | 
				
			||||||
			_replace_sprites_offset[0] = 0;
 | 
					 | 
				
			||||||
			_replace_sprites_count[0] = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (_replace_sprites_count[0] == 0) {
 | 
					 | 
				
			||||||
			int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			for (i = 0; i < 15; i++) {
 | 
					 | 
				
			||||||
				_replace_sprites_count[i] = _replace_sprites_count[i + 1];
 | 
					 | 
				
			||||||
				_replace_sprites_offset[i] = _replace_sprites_offset[i + 1];
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_replace_sprites_count[i] = 0;
 | 
					 | 
				
			||||||
			_replace_sprites_offset[i] = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_sprite_file_pos[load_index] = file_pos;
 | 
						_sprite_file_pos[load_index] = file_pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -216,7 +158,7 @@ bool LoadNextSprite(int load_index, byte file_index)
 | 
				
			|||||||
void SkipSprites(uint count)
 | 
					void SkipSprites(uint count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	for (; count > 0; --count) {
 | 
						for (; count > 0; --count) {
 | 
				
			||||||
		if (!ReadSpriteHeaderSkipData(MAX_SPRITES - 1)) return;
 | 
							if (!ReadSpriteHeaderSkipData()) return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user