Skip to content

Commit 6c9354e

Browse files
committed
Seems to finally be working!
1 parent f35c497 commit 6c9354e

File tree

4 files changed

+92
-66
lines changed

4 files changed

+92
-66
lines changed

Source/Managers/ActivityMan.cpp

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,13 @@ bool ActivityMan::SaveCurrentGame(const std::string& fileName) {
102102

103103
// See our content files to point to our save game location. This won't actually save a file here- but it allows us to set these up as in-memory ContentFiles on load
104104
// Meaning that our loading code doesn't need to care about whether it's loading a savegame or a file- it just sees it as an already loaded, cached bitmap
105+
modifiableScene->GetTerrain()->GetContentFile().SetIsMemoryFile(true);
105106
modifiableScene->GetTerrain()->GetContentFile().SetDataPath(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save Mat.png");
107+
108+
modifiableScene->GetTerrain()->GetFGSceneLayer()->GetContentFile().SetIsMemoryFile(true);
106109
modifiableScene->GetTerrain()->GetFGSceneLayer()->GetContentFile().SetDataPath(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save FG.png");
110+
111+
modifiableScene->GetTerrain()->GetBGSceneLayer()->GetContentFile().SetIsMemoryFile(true);
107112
modifiableScene->GetTerrain()->GetBGSceneLayer()->GetContentFile().SetDataPath(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save BG.png");
108113

109114
std::unique_ptr<std::stringstream> iniStream = std::make_unique<std::stringstream>();
@@ -223,44 +228,60 @@ bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) {
223228
char* buffer = nullptr;
224229

225230
auto unzipFileIntoBuffer = [&](std::string fullFileName) {
226-
unzLocateFile(zippedSaveFile, fullFileName.c_str(), nullptr);
231+
if (unzLocateFile(zippedSaveFile, fullFileName.c_str(), nullptr) == UNZ_END_OF_LIST_OF_FILE) {
232+
return false;
233+
}
234+
227235
unzOpenCurrentFile(zippedSaveFile);
228236
unzGetCurrentFileInfo(zippedSaveFile, &info, nullptr, 0, nullptr, 0, nullptr, 0);
229237

230238
buffer = (char*)malloc(info.uncompressed_size);
231239
if (!buffer) {
232240
// If this ever hits I've lost all faith in modern OSes, but alas when one is writing C, one must dance along
233241
RTEError::ShowMessageBox("Catastrophic failure! Failed to allocate memory for savegame");
242+
return false;
234243
}
235244

236245
unzReadCurrentFile(zippedSaveFile, buffer, info.uncompressed_size);
237246
unzCloseCurrentFile(zippedSaveFile);
238-
};
239247

240-
auto loadMemPngIntoBitmap = [](void* buffer, size_t size) {
241-
BITMAP* bitmap = nullptr; // just to help the compiler deduce the type, we can't early-return nullptr or it thiks we return std::nullptr_t
248+
return true;
249+
};
242250

251+
auto loadMemPng = [](void* buffer, size_t size) {
243252
SDL_IOStream* stream = SDL_IOFromConstMem(buffer, size);
244253
SDL_Surface* image = stream ? IMG_LoadPNG_IO(stream) : nullptr;
245-
if (!image) {
246-
return bitmap;
247-
}
248-
249254
SDL_CloseIO(stream);
250255

251-
bitmap = create_bitmap_ex(SDL_BITSPERPIXEL(image->format), image->w, image->h);
252-
253-
// Allegro doesn't align lines, SDL does 4byte alignment
254-
for (int y = 0; y < image->h; y++) {
255-
memcpy(bitmap->line[y],
256-
static_cast<unsigned char*>(image->pixels) + image->pitch * y,
257-
image->w * SDL_BYTESPERPIXEL(image->format));
258-
}
259-
256+
SDL_Palette* palette = ContentFile::DefaultPaletteToSDL();
257+
SDL_Surface* newImage = SDL_ConvertSurfaceAndColorspace(image, SDL_PIXELFORMAT_INDEX8, palette, SDL_COLORSPACE_UNKNOWN, 0);
258+
SDL_DestroyPalette(palette);
260259
SDL_DestroySurface(image);
261-
return bitmap;
260+
image = newImage;
261+
262+
free(buffer);
263+
return image;
262264
};
263265

266+
// Manually load all our bitmaps into our cache so the activity skips looking for the file and just gets it directly from us
267+
if (unzipFileIntoBuffer("Save Mat.png")) {
268+
ContentFile::ManuallyLoadDataPNG(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save Mat.png", loadMemPng(buffer, info.uncompressed_size));
269+
}
270+
271+
if (unzipFileIntoBuffer("Save FG.png")) {
272+
ContentFile::ManuallyLoadDataPNG(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save FG.png", loadMemPng(buffer, info.uncompressed_size));
273+
}
274+
275+
if (unzipFileIntoBuffer("Save BG.png")) {
276+
ContentFile::ManuallyLoadDataPNG(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save BG.png", loadMemPng(buffer, info.uncompressed_size));
277+
}
278+
279+
for (int i = 0; i < Activity::MaxTeamCount; ++i) {
280+
if (unzipFileIntoBuffer(std::format("Save UST%i.png", i))) {
281+
ContentFile::ManuallyLoadDataPNG(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + std::format("/Save UST%i", i), loadMemPng(buffer, info.uncompressed_size));
282+
}
283+
}
284+
264285
unzipFileIntoBuffer("Save.ini");
265286

266287
Reader reader(std::make_unique<std::istringstream>(buffer), filePath + "/Save.ini", true, nullptr, false);
@@ -288,30 +309,6 @@ bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) {
288309

289310
free(buffer);
290311

291-
int numberOfTeams = activity->m_TeamCount;
292-
293-
// Manually load all our bitmaps into our cache so the activity skips looking for the file and just gets it directly from us
294-
PALETTE palette;
295-
get_palette(palette);
296-
297-
unzipFileIntoBuffer("Save Mat.png");
298-
ContentFile::ManuallyLoadDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save Mat.png", loadMemPngIntoBitmap(buffer, info.uncompressed_size));
299-
free(buffer);
300-
301-
unzipFileIntoBuffer("Save FG.png");
302-
ContentFile::ManuallyLoadDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save FG.png", loadMemPngIntoBitmap(buffer, info.uncompressed_size));
303-
free(buffer);
304-
305-
unzipFileIntoBuffer("Save BG.png");
306-
ContentFile::ManuallyLoadDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save BG.png", loadMemPngIntoBitmap(buffer, info.uncompressed_size));
307-
free(buffer);
308-
309-
for (int i = 0; i < numberOfTeams; ++i) {
310-
unzipFileIntoBuffer(std::format("Save UST%i.png", i));
311-
ContentFile::ManuallyLoadDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + std::format("/Save UST%i", i), loadMemPngIntoBitmap(buffer, info.uncompressed_size));
312-
free(buffer);
313-
}
314-
315312
unzClose(zippedSaveFile);
316313

317314
// SetSceneToLoad() doesn't Clone(), but when the Activity starts, it will eventually call LoadScene(), which does a Clone() of scene internally.
@@ -324,14 +321,6 @@ bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) {
324321
// When this method exits, our Scene object will be destroyed, which will cause problems if you try to restart it. To avoid this, set the Scene to load to the preset object with the same name.
325322
g_SceneMan.SetSceneToLoad(originalScenePresetName, placeObjectsIfSceneIsRestarted, placeUnitsIfSceneIsRestarted);
326323

327-
// Clear out the cache, we don't need it anymore (and don't want a cache reload to look for this file thinking it really exists)
328-
ContentFile::ManuallyClearDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save Mat.png");
329-
ContentFile::ManuallyClearDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save FG.png");
330-
ContentFile::ManuallyClearDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + "/Save BG.png");
331-
for (int i = 0; i < numberOfTeams; ++i) {
332-
ContentFile::ManuallyClearDataBitmap(g_PresetMan.GetFullModulePath(c_UserScriptedSavesModuleName) + std::format("/Save UST%i.png", i));
333-
}
334-
335324
g_ConsoleMan.PrintString("SYSTEM: Game \"" + fileName + "\" loaded!");
336325

337326
return true;

Source/System/ContentFile.cpp

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ using namespace RTE;
1919
const std::string ContentFile::c_ClassName = "ContentFile";
2020

2121
std::array<std::unordered_map<std::string, BITMAP*>, ContentFile::BitDepths::BitDepthCount> ContentFile::s_LoadedBitmaps;
22+
std::unordered_map<std::string, SDL_Surface*> ContentFile::s_MemoryPNGs;
2223
std::unordered_map<std::string, FMOD::Sound*> ContentFile::s_LoadedSamples;
2324
std::unordered_map<size_t, std::string> ContentFile::s_PathHashes;
2425

@@ -30,6 +31,7 @@ void ContentFile::Clear() {
3031
m_FormattedReaderPosition.clear();
3132
m_DataPathAndReaderPosition.clear();
3233
m_DataModuleID = 0;
34+
m_IsMemoryPNG = false;
3335

3436
m_ImageFileInfo.fill(-1);
3537
}
@@ -60,7 +62,9 @@ void ContentFile::FreeAllLoaded() {
6062
int ContentFile::ReadProperty(const std::string_view& propName, Reader& reader) {
6163
StartPropertyList(return Serializable::ReadProperty(propName, reader));
6264

63-
MatchForwards("FilePath") MatchProperty("Path", { SetDataPath(reader.ReadPropValue()); });
65+
MatchForwards("FilePath")
66+
MatchProperty("Path", { SetDataPath(reader.ReadPropValue()); });
67+
MatchProperty("IsMemoryPNG", { reader >> m_IsMemoryPNG; });
6468

6569
EndPropertyList;
6670
}
@@ -71,6 +75,7 @@ int ContentFile::Save(Writer& writer) const {
7175
if (!m_DataPath.empty()) {
7276
writer.NewPropertyWithValue("FilePath", m_DataPath);
7377
}
78+
writer.NewPropertyWithValue("IsMemoryPNG", m_IsMemoryPNG);
7479

7580
return 0;
7681
}
@@ -110,6 +115,15 @@ int ContentFile::GetImageFileInfo(ImageFileInfoType infoTypeToGet) {
110115
}
111116
}
112117
if (fetchFileInfo) {
118+
if (m_IsMemoryPNG) {
119+
if (const SDL_Surface* png = s_MemoryPNGs[m_DataPath]) {
120+
m_ImageFileInfo[ImageFileInfoType::ImageBitDepth] = static_cast<int>(SDL_BITSPERPIXEL(png->format));
121+
m_ImageFileInfo[ImageFileInfoType::ImageWidth] = static_cast<int>(png->w);
122+
m_ImageFileInfo[ImageFileInfoType::ImageHeight] = static_cast<int>(png->h);
123+
return m_ImageFileInfo[infoTypeToGet];
124+
}
125+
}
126+
113127
FILE* imageFile = fopen(m_DataPath.c_str(), "rb");
114128
RTEAssert(imageFile, "Failed to open file prior to reading info of image file with following path and name:\n\n" + m_DataPath + "\n\nThe file may not exist or be corrupt.");
115129

@@ -182,18 +196,20 @@ void ContentFile::ReadAndStoreBMPFileInfo(FILE* imageFile) {
182196
}
183197
}
184198

185-
void ContentFile::ManuallyLoadDataBitmap(const std::string& filePath, BITMAP* bitmap, int conversionMode) {
186-
const int bitDepth = conversionMode == COLORCONV_8_TO_32 ? BitDepths::ThirtyTwo : BitDepths::Eight;
187-
s_LoadedBitmaps[bitDepth].try_emplace(filePath, bitmap);
188-
}
199+
void ContentFile::ManuallyLoadDataPNG(const std::string& filePath, SDL_Surface* surface) {
200+
s_MemoryPNGs[filePath] = surface;
189201

190-
void ContentFile::ManuallyClearDataBitmap(const std::string& filePath, int conversionMode) {
191-
const int bitDepth = conversionMode == COLORCONV_8_TO_32 ? BitDepths::ThirtyTwo : BitDepths::Eight;
192-
std::unordered_map<std::string, BITMAP*>::iterator foundBitmap = s_LoadedBitmaps[bitDepth].find(filePath);
193-
if (foundBitmap != s_LoadedBitmaps[bitDepth].end()) {
194-
delete (*foundBitmap).second;
195-
s_LoadedBitmaps[bitDepth].erase(filePath);
202+
int bitDepth = SDL_GetPixelFormatDetails(surface->format)->bits_per_pixel;
203+
BITMAP* bitmap = create_bitmap_ex(bitDepth, surface->w, surface->h);
204+
205+
// Allegro doesn't align lines, SDL does 4byte alignment
206+
for (int y = 0; y < surface->h; y++) {
207+
memcpy(bitmap->line[y],
208+
static_cast<unsigned char*>(surface->pixels) + surface->pitch * y,
209+
surface->w * SDL_BYTESPERPIXEL(surface->format));
196210
}
211+
212+
s_LoadedBitmaps[BitDepths::Eight].try_emplace(filePath, bitmap);
197213
}
198214

199215
void ContentFile::ReloadAllBitmaps() {
@@ -219,9 +235,22 @@ BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std
219235

220236
// Check if the file has already been read and loaded from the disk and, if so, use that data.
221237
std::unordered_map<std::string, BITMAP*>::iterator foundBitmap = s_LoadedBitmaps[bitDepth].find(dataPathToLoad);
222-
if (storeBitmap && foundBitmap != s_LoadedBitmaps[bitDepth].end()) {
223-
returnBitmap = (*foundBitmap).second;
224-
} else {
238+
if (foundBitmap != s_LoadedBitmaps[bitDepth].end()) {
239+
if (storeBitmap) {
240+
returnBitmap = (*foundBitmap).second;
241+
} else if (SDL_Surface* surface = s_MemoryPNGs[dataPathToLoad]) {
242+
std::unordered_map<std::string, BITMAP*>::iterator foundBitmap = s_LoadedBitmaps[BitDepths::Eight].find(dataPathToLoad);
243+
if (foundBitmap != s_LoadedBitmaps[BitDepths::Eight].end()) {
244+
returnBitmap = foundBitmap->second;
245+
s_LoadedBitmaps[BitDepths::Eight].erase(dataPathToLoad);
246+
}
247+
248+
SDL_DestroySurface(surface);
249+
s_MemoryPNGs.erase(dataPathToLoad);
250+
}
251+
}
252+
253+
if (returnBitmap == nullptr) {
225254
if (!System::PathExistsCaseSensitive(dataPathToLoad)) {
226255
const std::string dataPathWithoutExtension = dataPathToLoad.substr(0, dataPathToLoad.length() - m_DataPathExtension.length());
227256
const std::string altFileExtension = (m_DataPathExtension == ".png") ? ".bmp" : ".png";
@@ -241,6 +270,7 @@ BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std
241270
s_LoadedBitmaps[bitDepth].try_emplace(dataPathToLoad, returnBitmap);
242271
}
243272
}
273+
244274
return returnBitmap;
245275
}
246276

Source/System/ContentFile.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ namespace RTE {
8484
/// @param hash Hash value to get file path from.
8585
/// @return Path to ContentFile.
8686
static std::string GetPathFromHash(size_t hash) { return (s_PathHashes.find(hash) == s_PathHashes.end()) ? "" : s_PathHashes[hash]; }
87+
88+
/// Sets this ContentFile to be a memory file, meaning we won't try loading from disk and instead will let external code set us up.
89+
/// @param isMemoryFile Whether we'll be considered a memory file.
90+
void SetIsMemoryFile(bool isMemoryFile) { m_IsMemoryPNG = isMemoryFile; }
8791
#pragma endregion
8892

8993
#pragma region Logging
@@ -115,8 +119,7 @@ namespace RTE {
115119
#pragma endregion
116120

117121
#pragma region Data Handling
118-
static void ManuallyLoadDataBitmap(const std::string& filePath, BITMAP* bitmap, int conversionMode = 0);
119-
static void ManuallyClearDataBitmap(const std::string& filePath, int conversionMode = 0);
122+
static void ManuallyLoadDataPNG(const std::string& filePath, SDL_Surface* bitmap);
120123

121124
/// Reloads all BITMAPs in the cache from disk, allowing any changes to be reflected at runtime.
122125
static void ReloadAllBitmaps();
@@ -176,6 +179,7 @@ namespace RTE {
176179

177180
static std::unordered_map<size_t, std::string> s_PathHashes; //!< Static map containing the hash values of paths of all loaded data files.
178181
static std::array<std::unordered_map<std::string, BITMAP*>, BitDepths::BitDepthCount> s_LoadedBitmaps; //!< Static map containing all the already loaded BITMAPs and their paths for each bit depth.
182+
static std::unordered_map<std::string, SDL_Surface*> s_MemoryPNGs; //!< Static map containing in-memory PNG files for save/load
179183
static std::unordered_map<std::string, FMOD::Sound*> s_LoadedSamples; //!< Static map containing all the already loaded FSOUND_SAMPLEs and their paths.
180184

181185
std::string m_DataPath; //!< The path to this ContentFile's data file. In the case of an animation, this filename/name will be appended with 000, 001, 002 etc.
@@ -189,6 +193,7 @@ namespace RTE {
189193
std::string m_DataPathAndReaderPosition; //!< The path to this ContentFile's data file combined with the ini file and line it is being read from. This is used for logging.
190194

191195
int m_DataModuleID; //!< Data Module ID of where this was loaded from.
196+
bool m_IsMemoryPNG; //!< If true, we will not attempt to read this file on disk, and instead will let external code set us up.
192197

193198
#pragma region Image Info Getters
194199
/// Gets the specified image info from this ContentFile's data file on disk.

Source/System/Serializable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ namespace RTE {
4444

4545
#define MatchForwards(propertyName) \
4646
sm_Properties[propertyName] = __COUNTER__ + 1; \
47+
[[fallthrough]]; \
4748
case __COUNTER__:
4849

4950
#define MatchProperty(propertyName, matchedFunction) \
5051
sm_Properties[propertyName] = __COUNTER__ + 1; \
52+
[[fallthrough]]; \
5153
case __COUNTER__: \
5254
if (sm_Initialized) { \
5355
{matchedFunction}; \

0 commit comments

Comments
 (0)