Codechange: let NewGRF make use of SpriteFile instead of most of the FIO slot functions

(cherry picked from commit 10e35ca8e4)
pull/266/head
Rubidium 3 years ago committed by Jonathan G Rennison
parent 6bd12e24d7
commit eecf7c8525

@ -51,16 +51,15 @@ int _progsig_grf_file_index;
* Load an old fashioned GRF file. * Load an old fashioned GRF file.
* @param filename The name of the file to open. * @param filename The name of the file to open.
* @param load_index The offset of the first sprite. * @param load_index The offset of the first sprite.
* @param file_index The Fio offset to load the file in.
* @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @param needs_palette_remap Whether the colours in the GRF file need a palette remap.
* @return The number of loaded sprites. * @return The number of loaded sprites.
*/ */
static uint LoadGrfFile(const char *filename, uint load_index, int file_index, bool needs_palette_remap) static uint LoadGrfFile(const char *filename, uint load_index, bool needs_palette_remap)
{ {
uint load_index_org = load_index; uint load_index_org = load_index;
uint sprite_id = 0; uint sprite_id = 0;
SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); SpriteFile &file = OpenCachedSpriteFile(filename, BASESET_DIR, needs_palette_remap);
DEBUG(sprite, 2, "Reading grf-file '%s'", filename); DEBUG(sprite, 2, "Reading grf-file '%s'", filename);
@ -89,16 +88,15 @@ static uint LoadGrfFile(const char *filename, uint load_index, int file_index, b
* Load an old fashioned GRF file to replace already loaded sprites. * Load an old fashioned GRF file to replace already loaded sprites.
* @param filename The name of the file to open. * @param filename The name of the file to open.
* @param index_tbl The offsets of each of the sprites. * @param index_tbl The offsets of each of the sprites.
* @param file_index The Fio offset to load the file in.
* @param needs_palette_remap Whether the colours in the GRF file need a palette remap. * @param needs_palette_remap Whether the colours in the GRF file need a palette remap.
* @return The number of loaded sprites. * @return The number of loaded sprites.
*/ */
static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, int file_index, bool needs_palette_remap) static void LoadGrfFileIndexed(const char *filename, const SpriteID *index_tbl, bool needs_palette_remap)
{ {
uint start; uint start;
uint sprite_id = 0; uint sprite_id = 0;
SpriteFile &file = FioOpenFile(file_index, filename, BASESET_DIR, needs_palette_remap); SpriteFile &file = OpenCachedSpriteFile(filename, BASESET_DIR, needs_palette_remap);
DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename); DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename);
@ -173,14 +171,13 @@ void CheckExternalFiles()
/** Actually load the sprite tables. */ /** Actually load the sprite tables. */
static void LoadSpriteTables() static void LoadSpriteTables()
{ {
uint i = FIRST_GRF_SLOT;
const GraphicsSet *used_set = BaseGraphics::GetUsedSet(); const GraphicsSet *used_set = BaseGraphics::GetUsedSet();
LoadGrfFile(used_set->files[GFT_BASE].filename, 0, i++, (PAL_DOS != used_set->palette)); LoadGrfFile(used_set->files[GFT_BASE].filename, 0, PAL_DOS != used_set->palette);
/* Progsignal sprites. */ /* Progsignal sprites. */
_progsig_grf_file_index = i; //_progsig_grf_file_index = i;
LoadGrfFile("progsignals.grf", SPR_PROGSIGNAL_BASE, i++, false); LoadGrfFile("progsignals.grf", SPR_PROGSIGNAL_BASE, false);
/* Fill duplicate programmable pre-signal graphics sprite block */ /* Fill duplicate programmable pre-signal graphics sprite block */
for (uint i = 0; i < PROGSIGNAL_SPRITE_COUNT; i++) { for (uint i = 0; i < PROGSIGNAL_SPRITE_COUNT; i++) {
@ -188,7 +185,7 @@ static void LoadSpriteTables()
} }
/* Tracerestrict sprites. */ /* Tracerestrict sprites. */
LoadGrfFile("tracerestrict.grf", SPR_TRACERESTRICT_BASE, i++, false); LoadGrfFile("tracerestrict.grf", SPR_TRACERESTRICT_BASE, false);
/* Fill duplicate original signal graphics sprite block */ /* Fill duplicate original signal graphics sprite block */
for (uint i = 0; i < DUP_ORIGINAL_SIGNALS_SPRITE_COUNT; i++) { for (uint i = 0; i < DUP_ORIGINAL_SIGNALS_SPRITE_COUNT; i++) {
@ -201,7 +198,7 @@ static void LoadSpriteTables()
* has a few sprites less. However, we do not care about those missing * has a few sprites less. However, we do not care about those missing
* sprites as they are not shown anyway (logos in intro game). * sprites as they are not shown anyway (logos in intro game).
*/ */
LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, i++, (PAL_DOS != used_set->palette)); LoadGrfFile(used_set->files[GFT_LOGOS].filename, 4793, PAL_DOS != used_set->palette);
/* /*
* Load additional sprites for climates other than temperate. * Load additional sprites for climates other than temperate.
@ -212,15 +209,14 @@ static void LoadSpriteTables()
LoadGrfFileIndexed( LoadGrfFileIndexed(
used_set->files[GFT_ARCTIC + _settings_game.game_creation.landscape - 1].filename, used_set->files[GFT_ARCTIC + _settings_game.game_creation.landscape - 1].filename,
_landscape_spriteindexes[_settings_game.game_creation.landscape - 1], _landscape_spriteindexes[_settings_game.game_creation.landscape - 1],
i++, PAL_DOS != used_set->palette
(PAL_DOS != used_set->palette)
); );
} }
LoadGrfFile("innerhighlight.grf", SPR_ZONING_INNER_HIGHLIGHT_BASE, i++, false); LoadGrfFile("innerhighlight.grf", SPR_ZONING_INNER_HIGHLIGHT_BASE, false);
/* Load route step graphics */ /* Load route step graphics */
LoadGrfFile("route_step.grf", SPR_ROUTE_STEP_BASE, i++, false); LoadGrfFile("route_step.grf", SPR_ROUTE_STEP_BASE, false);
/* Initialize the unicode to sprite mapping table */ /* Initialize the unicode to sprite mapping table */
InitializeUnicodeGlyphMap(); InitializeUnicodeGlyphMap();
@ -257,7 +253,7 @@ static void LoadSpriteTables()
master->next = extra; master->next = extra;
_grfconfig = master; _grfconfig = master;
LoadNewGRF(SPR_NEWGRFS_BASE, i, 2); LoadNewGRF(SPR_NEWGRFS_BASE, 2);
uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE; uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE;
_missing_extra_graphics = GetSpriteCountForFile(used_set->files[GFT_EXTRA].filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); _missing_extra_graphics = GetSpriteCountForFile(used_set->files[GFT_EXTRA].filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE);
@ -267,14 +263,13 @@ static void LoadSpriteTables()
* Let's say everything which provides less than 500 sprites misses the rest intentionally. */ * Let's say everything which provides less than 500 sprites misses the rest intentionally. */
if (500 + _missing_extra_graphics > total_extra_graphics) _missing_extra_graphics = 0; if (500 + _missing_extra_graphics > total_extra_graphics) _missing_extra_graphics = 0;
_first_user_grf_file_index = i + 1; //_first_user_grf_file_index = i + 1;
_opengfx_grf_file_index = -1; //_opengfx_grf_file_index = -1;
uint index = i; for (GRFConfig *c = master; c != nullptr; c = c->next) {
for (GRFConfig *c = master; c != nullptr; c = c->next, index++) {
if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND || HasBit(c->flags, GCF_INIT_ONLY)) continue; if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND || HasBit(c->flags, GCF_INIT_ONLY)) continue;
if (c->ident.grfid == BSWAP32(0xFF4F4701)) { if (c->ident.grfid == BSWAP32(0xFF4F4701)) {
/* Detect OpenGFX GRF ID */ /* Detect OpenGFX GRF ID */
_opengfx_grf_file_index = index; //_opengfx_grf_file_index = index;
break; break;
} }
} }

@ -81,6 +81,7 @@ static uint32 _ttdpatch_flags[8];
GRFLoadedFeatures _loaded_newgrf_features; GRFLoadedFeatures _loaded_newgrf_features;
static const uint MAX_SPRITEGROUP = UINT8_MAX; ///< Maximum GRF-local ID for a spritegroup. static const uint MAX_SPRITEGROUP = UINT8_MAX; ///< Maximum GRF-local ID for a spritegroup.
static const uint MAX_GRF_COUNT = 256; ///< Maximum number of NewGRF files that could be loaded.
/** Base GRF ID for OpenTTD's base graphics GRFs. */ /** Base GRF ID for OpenTTD's base graphics GRFs. */
static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400); static const uint32 OPENTTD_GRAPHICS_BASE_GRF_ID = BSWAP32(0xFF4F5400);
@ -6565,19 +6566,20 @@ static void CfgApply(ByteReader *buf)
* to place where parameter is to be stored. */ * to place where parameter is to be stored. */
/* Preload the next sprite */ /* Preload the next sprite */
size_t pos = FioGetPos(); SpriteFile &file = *_cur.file;
uint32 num = _cur.file->GetContainerVersion() >= 2 ? FioReadDword() : FioReadWord(); size_t pos = file.GetPos();
uint8 type = FioReadByte(); uint32 num = file.GetContainerVersion() >= 2 ? file.ReadDword() : file.ReadWord();
uint8 type = file.ReadByte();
byte *preload_sprite = nullptr; byte *preload_sprite = nullptr;
/* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */ /* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */
if (type == 0xFF) { if (type == 0xFF) {
preload_sprite = MallocT<byte>(num); preload_sprite = MallocT<byte>(num);
FioReadBlock(preload_sprite, num); file.ReadBlock(preload_sprite, num);
} }
/* Reset the file position to the start of the next sprite */ /* Reset the file position to the start of the next sprite */
FioSeekTo(pos, SEEK_SET); file.SeekTo(pos, SEEK_SET);
if (type != 0xFF) { if (type != 0xFF) {
grfmsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)"); grfmsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)");
@ -6823,7 +6825,7 @@ static void SkipIf(ByteReader *buf)
if (choice != nullptr) { if (choice != nullptr) {
grfmsg(2, "SkipIf: Jumping to label 0x%0X at line %d, test was true", choice->label, choice->nfo_line); grfmsg(2, "SkipIf: Jumping to label 0x%0X at line %d, test was true", choice->label, choice->nfo_line);
FioSeekTo(choice->pos, SEEK_SET); _cur.file->SeekTo(choice->pos, SEEK_SET);
_cur.nfo_line = choice->nfo_line; _cur.nfo_line = choice->nfo_line;
return; return;
} }
@ -7663,7 +7665,7 @@ static void DefineGotoLabel(ByteReader *buf)
GRFLabel *label = MallocT<GRFLabel>(1); GRFLabel *label = MallocT<GRFLabel>(1);
label->label = nfo_label; label->label = nfo_label;
label->nfo_line = _cur.nfo_line; label->nfo_line = _cur.nfo_line;
label->pos = FioGetPos(); label->pos = _cur.file->GetPos();
label->next = nullptr; label->next = nullptr;
/* Set up a linked list of goto targets which we will search in an Action 0x7/0x9 */ /* Set up a linked list of goto targets which we will search in an Action 0x7/0x9 */
@ -7686,8 +7688,8 @@ static void DefineGotoLabel(ByteReader *buf)
static void ImportGRFSound(SoundEntry *sound) static void ImportGRFSound(SoundEntry *sound)
{ {
const GRFFile *file; const GRFFile *file;
uint32 grfid = FioReadDword(); uint32 grfid = _cur.file->ReadDword();
SoundID sound_id = FioReadWord(); SoundID sound_id = _cur.file->ReadWord();
file = GetFileByGRFID(grfid); file = GetFileByGRFID(grfid);
if (file == nullptr || file->sound_offset == 0) { if (file == nullptr || file->sound_offset == 0) {
@ -7747,6 +7749,8 @@ static void GRFSound(ByteReader *buf)
sound = GetSound(_cur.grffile->sound_offset); sound = GetSound(_cur.grffile->sound_offset);
} }
SpriteFile &file = *_cur.file;
byte grf_container_version = file.GetContainerVersion();
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
_cur.nfo_line++; _cur.nfo_line++;
@ -7754,22 +7758,21 @@ static void GRFSound(ByteReader *buf)
* While this is invalid, we do not check for this. But we should prevent it from causing bigger trouble */ * While this is invalid, we do not check for this. But we should prevent it from causing bigger trouble */
bool invalid = i >= _cur.grffile->num_sounds; bool invalid = i >= _cur.grffile->num_sounds;
size_t offs = FioGetPos(); size_t offs = file.GetPos();
byte grf_container_version = _cur.file->GetContainerVersion(); uint32 len = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord();
uint32 len = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); byte type = file.ReadByte();
byte type = FioReadByte();
if (grf_container_version >= 2 && type == 0xFD) { if (grf_container_version >= 2 && type == 0xFD) {
/* Reference to sprite section. */ /* Reference to sprite section. */
if (invalid) { if (invalid) {
grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)"); grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
FioSkipBytes(len); file.SkipBytes(len);
} else if (len != 4) { } else if (len != 4) {
grfmsg(1, "GRFSound: Invalid sprite section import"); grfmsg(1, "GRFSound: Invalid sprite section import");
FioSkipBytes(len); file.SkipBytes(len);
} else { } else {
uint32 id = FioReadDword(); uint32 id = file.ReadDword();
if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i); if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i);
} }
continue; continue;
@ -7777,17 +7780,17 @@ static void GRFSound(ByteReader *buf)
if (type != 0xFF) { if (type != 0xFF) {
grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping"); grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping");
FioSkipBytes(7); file.SkipBytes(7);
SkipSpriteData(*_cur.file, type, len - 8); SkipSpriteData(*_cur.file, type, len - 8);
continue; continue;
} }
if (invalid) { if (invalid) {
grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)"); grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
FioSkipBytes(len); file.SkipBytes(len);
} }
byte action = FioReadByte(); byte action = file.ReadByte();
switch (action) { switch (action) {
case 0xFF: case 0xFF:
/* Allocate sound only in init stage. */ /* Allocate sound only in init stage. */
@ -7798,23 +7801,23 @@ static void GRFSound(ByteReader *buf)
LoadGRFSound(offs, sound + i); LoadGRFSound(offs, sound + i);
} }
} }
FioSkipBytes(len - 1); // already read <action> file.SkipBytes(len - 1); // already read <action>
break; break;
case 0xFE: case 0xFE:
if (_cur.stage == GLS_ACTIVATION) { if (_cur.stage == GLS_ACTIVATION) {
/* XXX 'Action 0xFE' isn't really specified. It is only mentioned for /* XXX 'Action 0xFE' isn't really specified. It is only mentioned for
* importing sounds, so this is probably all wrong... */ * importing sounds, so this is probably all wrong... */
if (FioReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch"); if (file.ReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch");
ImportGRFSound(sound + i); ImportGRFSound(sound + i);
} else { } else {
FioSkipBytes(len - 1); // already read <action> file.SkipBytes(len - 1); // already read <action>
} }
break; break;
default: default:
grfmsg(1, "GRFSound: Unexpected Action %x found, skipping", action); grfmsg(1, "GRFSound: Unexpected Action %x found, skipping", action);
FioSkipBytes(len - 1); // already read <action> file.SkipBytes(len - 1); // already read <action>
break; break;
} }
} }
@ -9857,14 +9860,14 @@ static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage)
if (it == _grf_line_to_action6_sprite_override.end()) { if (it == _grf_line_to_action6_sprite_override.end()) {
/* No preloaded sprite to work with; read the /* No preloaded sprite to work with; read the
* pseudo sprite content. */ * pseudo sprite content. */
FioReadBlock(buf, num); _cur.file->ReadBlock(buf, num);
} else { } else {
/* Use the preloaded sprite data. */ /* Use the preloaded sprite data. */
buf = it->second; buf = it->second;
grfmsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data"); grfmsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data");
/* Skip the real (original) content of this action. */ /* Skip the real (original) content of this action. */
FioSeekTo(num, SEEK_CUR); _cur.file->SeekTo(num, SEEK_CUR);
} }
ByteReader br(buf, buf + num); ByteReader br(buf, buf + num);
@ -9891,48 +9894,20 @@ static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage)
} }
} }
/** /**
* Load a particular NewGRF. * Load a particular NewGRF from a SpriteFile.
* @param config The configuration of the to be loaded NewGRF. * @param config The configuration of the to be loaded NewGRF.
* @param file_index The Fio index of the first NewGRF to load. * @param stage The loading stage of the NewGRF.
* @param stage The loading stage of the NewGRF. * @param file The file to load the GRF data from.
* @param subdir The sub directory to find the NewGRF in.
*/ */
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir) static void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file)
{ {
const char *filename = config->filename; _cur.file = &file;
/* 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, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
* carried out. All others are ignored, because they only need to be
* processed once at initialization. */
if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
_cur.grffile = GetFileByFilename(filename);
if (_cur.grffile == nullptr) usererror("File '%s' lost in cache.\n", filename);
if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return;
}
if (file_index >= MAX_FILE_SLOTS) {
DEBUG(grf, 0, "'%s' is not loaded as the maximum number of file slots has been reached", filename);
config->status = GCS_DISABLED;
config->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
return;
}
_cur.file = &FioOpenFile(file_index, filename, subdir, config->palette & GRFP_USE_MASK);
config->full_filename = _cur.file->GetFilename();
_cur.grfconfig = config; _cur.grfconfig = config;
DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", config->GetDisplayPath()); DEBUG(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '%s'", config->GetDisplayPath());
byte grf_container_version = _cur.file->GetContainerVersion(); byte grf_container_version = file.GetContainerVersion();
if (grf_container_version == 0) { if (grf_container_version == 0) {
DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
return; return;
@ -9941,15 +9916,15 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
if (stage == GLS_INIT || stage == GLS_ACTIVATION) { if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
/* We need the sprite offsets in the init stage for NewGRF sounds /* We need the sprite offsets in the init stage for NewGRF sounds
* and in the activation stage for real sprites. */ * and in the activation stage for real sprites. */
ReadGRFSpriteOffsets(*_cur.file); ReadGRFSpriteOffsets(file);
} else { } else {
/* Skip sprite section offset if present. */ /* Skip sprite section offset if present. */
if (grf_container_version >= 2) FioReadDword(); if (grf_container_version >= 2) file.ReadDword();
} }
if (grf_container_version >= 2) { if (grf_container_version >= 2) {
/* Read compression value. */ /* Read compression value. */
byte compression = FioReadByte(); byte compression = file.ReadByte();
if (compression != 0) { if (compression != 0) {
DEBUG(grf, 7, "LoadNewGRFFile: Unsupported compression format"); DEBUG(grf, 7, "LoadNewGRFFile: Unsupported compression format");
return; return;
@ -9959,9 +9934,9 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
/* Skip the first sprite; we don't care about how many sprites this /* Skip the first sprite; we don't care about how many sprites this
* does contain; newest TTDPatches and George's longvehicles don't * does contain; newest TTDPatches and George's longvehicles don't
* neither, apparently. */ * neither, apparently. */
uint32 num = grf_container_version >= 2 ? FioReadDword() : FioReadWord(); uint32 num = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord();
if (num == 4 && FioReadByte() == 0xFF) { if (num == 4 && file.ReadByte() == 0xFF) {
FioReadDword(); file.ReadDword();
} else { } else {
DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format"); DEBUG(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
return; return;
@ -9971,8 +9946,8 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
ReusableBuffer<byte> buf; ReusableBuffer<byte> buf;
while ((num = (grf_container_version >= 2 ? FioReadDword() : FioReadWord())) != 0) { while ((num = (grf_container_version >= 2 ? file.ReadDword() : file.ReadWord())) != 0) {
byte type = FioReadByte(); byte type = file.ReadByte();
_cur.nfo_line++; _cur.nfo_line++;
if (type == 0xFF) { if (type == 0xFF) {
@ -9984,7 +9959,7 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
continue; continue;
} else { } else {
FioSkipBytes(num); file.SkipBytes(num);
} }
} else { } else {
if (_cur.skip_sprites == 0) { if (_cur.skip_sprites == 0) {
@ -9995,10 +9970,10 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
if (grf_container_version >= 2 && type == 0xFD) { if (grf_container_version >= 2 && type == 0xFD) {
/* Reference to data section. Container version >= 2 only. */ /* Reference to data section. Container version >= 2 only. */
FioSkipBytes(num); file.SkipBytes(num);
} else { } else {
FioSkipBytes(7); file.SkipBytes(7);
SkipSpriteData(*_cur.file, type, num - 8); SkipSpriteData(file, type, num - 8);
} }
} }
@ -10006,6 +9981,43 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage, S
} }
} }
/**
* Load a particular NewGRF.
* @param config The configuration of the to be loaded NewGRF.
* @param stage The loading stage of the NewGRF.
* @param subdir The sub directory to find the NewGRF in.
* @param temporary The NewGRF/sprite file is to be loaded temporarily and should be closed immediately,
* contrary to loading the SpriteFile and having it cached by the SpriteCache.
*/
void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
{
const char *filename = config->filename;
/* 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, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
* carried out. All others are ignored, because they only need to be
* processed once at initialization. */
if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
_cur.grffile = GetFileByFilename(filename);
if (_cur.grffile == nullptr) usererror("File '%s' lost in cache.\n", filename);
if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return;
}
bool needs_palette_remap = config->palette & GRFP_USE_MASK;
if (temporary) {
SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
LoadNewGRFFileFromFile(config, stage, temporarySpriteFile);
} else {
LoadNewGRFFileFromFile(config, stage, OpenCachedSpriteFile(filename, subdir, needs_palette_remap));
}
}
/** /**
* Relocates the old shore sprites at new positions. * Relocates the old shore sprites at new positions.
* *
@ -10301,10 +10313,9 @@ static void AfterLoadGRFs()
/** /**
* Load all the NewGRFs. * Load all the NewGRFs.
* @param load_index The offset for the first sprite to add. * @param load_index The offset for the first sprite to add.
* @param file_index The Fio index of the first NewGRF to load.
* @param num_baseset Number of NewGRFs at the front of the list to look up in the baseset dir instead of the newgrf dir. * @param num_baseset Number of NewGRFs at the front of the list to look up in the baseset dir instead of the newgrf dir.
*/ */
void LoadNewGRF(uint load_index, uint file_index, uint num_baseset) void LoadNewGRF(uint load_index, uint num_baseset)
{ {
/* In case of networking we need to "sync" the start values /* In case of networking we need to "sync" the start values
* so all NewGRFs are loaded equally. For this we use the * so all NewGRFs are loaded equally. For this we use the
@ -10366,15 +10377,14 @@ void LoadNewGRF(uint load_index, uint file_index, uint num_baseset)
} }
} }
uint slot = file_index; uint num_grfs = 0;
uint num_non_static = 0;
_cur.stage = stage; _cur.stage = stage;
for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) { for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue; if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue; if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue;
Subdirectory subdir = slot < file_index + num_baseset ? BASESET_DIR : NEWGRF_DIR; Subdirectory subdir = num_grfs < num_baseset ? BASESET_DIR : NEWGRF_DIR;
if (!FioCheckFileExists(c->filename, subdir)) { if (!FioCheckFileExists(c->filename, subdir)) {
DEBUG(grf, 0, "NewGRF file is missing '%s'; disabling", c->filename); DEBUG(grf, 0, "NewGRF file is missing '%s'; disabling", c->filename);
c->status = GCS_NOT_FOUND; c->status = GCS_NOT_FOUND;
@ -10383,16 +10393,15 @@ void LoadNewGRF(uint load_index, uint file_index, uint num_baseset)
if (stage == GLS_LABELSCAN) InitNewGRFFile(c); if (stage == GLS_LABELSCAN) InitNewGRFFile(c);
if (!HasBit(c->flags, GCF_STATIC) && !HasBit(c->flags, GCF_SYSTEM)) { if (num_grfs >= MAX_GRF_COUNT) {
if (slot == MAX_FILE_SLOTS) { DEBUG(grf, 0, "'%s' is not loaded as the maximum number of file slots has been reached", c->filename);
DEBUG(grf, 0, "'%s' is not loaded as the maximum number of non-static GRFs has been reached", c->filename); c->status = GCS_DISABLED;
c->status = GCS_DISABLED; c->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED);
c->error = new GRFError(STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED); continue;
continue;
}
num_non_static++;
} }
LoadNewGRFFile(c, slot++, stage, subdir); num_grfs++;
LoadNewGRFFile(c, stage, subdir, false);
if (stage == GLS_RESERVE) { if (stage == GLS_RESERVE) {
SetBit(c->flags, GCF_RESERVED); SetBit(c->flags, GCF_RESERVED);
} else if (stage == GLS_ACTIVATION) { } else if (stage == GLS_ACTIVATION) {

@ -312,8 +312,8 @@ static inline bool HasGrfMiscBit(GrfMiscBit bit)
/* Indicates which are the newgrf features currently loaded ingame */ /* Indicates which are the newgrf features currently loaded ingame */
extern GRFLoadedFeatures _loaded_newgrf_features; extern GRFLoadedFeatures _loaded_newgrf_features;
void LoadNewGRFFile(struct GRFConfig *config, uint file_index, GrfLoadingStage stage, Subdirectory subdir); void LoadNewGRFFile(struct GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary);
void LoadNewGRF(uint load_index, uint file_index, uint num_baseset); void LoadNewGRF(uint load_index, uint num_baseset);
void ReloadNewGRFData(); // in saveload/afterload.cpp void ReloadNewGRFData(); // in saveload/afterload.cpp
void ResetNewGRFData(); void ResetNewGRFData();
void ResetPersistentNewGRFData(); void ResetPersistentNewGRFData();

@ -465,7 +465,7 @@ bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir)
} }
/* Find and load the Action 8 information */ /* Find and load the Action 8 information */
LoadNewGRFFile(config, CONFIG_SLOT, GLS_FILESCAN, subdir); LoadNewGRFFile(config, GLS_FILESCAN, subdir, true);
config->SetSuitablePalette(); config->SetSuitablePalette();
config->FinalizeParameterInfo(); config->FinalizeParameterInfo();
@ -474,7 +474,7 @@ bool FillGRFDetails(GRFConfig *config, bool is_static, Subdirectory subdir)
if (is_static) { if (is_static) {
/* Perform a 'safety scan' for static GRFs */ /* Perform a 'safety scan' for static GRFs */
LoadNewGRFFile(config, CONFIG_SLOT, GLS_SAFETYSCAN, subdir); LoadNewGRFFile(config, GLS_SAFETYSCAN, subdir, true);
/* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */ /* GCF_UNSAFE is set if GLS_SAFETYSCAN finds unsafe actions */
if (HasBit(config->flags, GCF_UNSAFE)) return false; if (HasBit(config->flags, GCF_UNSAFE)) return false;

Loading…
Cancel
Save