diff --git a/src/core/Path.cpp b/src/core/Path.cpp index 65d0e8a830..234742ec36 100644 --- a/src/core/Path.cpp +++ b/src/core/Path.cpp @@ -74,6 +74,8 @@ namespace Path utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path) { + path = GetFileName(path); + const utf8 * lastDot = nullptr; const utf8 * ch = path; for (; *ch != '\0'; ch++) diff --git a/src/object/BannerObject.cpp b/src/object/BannerObject.cpp index 2eb25d1cbc..9f3860f079 100644 --- a/src/object/BannerObject.cpp +++ b/src/object/BannerObject.cpp @@ -29,7 +29,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void BannerObject::ReadLegacy(IStream * stream) +void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -39,11 +39,11 @@ void BannerObject::ReadLegacy(IStream * stream) _legacyType.banner.price = stream->ReadValue(); _legacyType.banner.scenery_tab_id = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); _sceneryTabEntry = stream->ReadValue(); - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void BannerObject::Load() diff --git a/src/object/BannerObject.h b/src/object/BannerObject.h index dfc4bd1558..ef4d417543 100644 --- a/src/object/BannerObject.h +++ b/src/object/BannerObject.h @@ -34,7 +34,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/EntranceObject.cpp b/src/object/EntranceObject.cpp index dc9cfcc9ab..00a41ea9fa 100644 --- a/src/object/EntranceObject.cpp +++ b/src/object/EntranceObject.cpp @@ -28,15 +28,15 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void EntranceObject::ReadLegacy(IStream * stream) +void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.string_idx = stream->ReadValue(); _legacyType.image_id = stream->ReadValue(); _legacyType.scrolling_mode = stream->ReadValue(); _legacyType.text_height = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(stream); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable()->Read(context, stream); } void EntranceObject::Load() diff --git a/src/object/EntranceObject.h b/src/object/EntranceObject.h index 781984cf55..bda8e873a8 100644 --- a/src/object/EntranceObject.h +++ b/src/object/EntranceObject.h @@ -33,7 +33,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/FootpathItemObject.cpp b/src/object/FootpathItemObject.cpp index e4f2e3c6b5..f8d5a8c352 100644 --- a/src/object/FootpathItemObject.cpp +++ b/src/object/FootpathItemObject.cpp @@ -28,7 +28,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void FootpathItemObject::ReadLegacy(IStream * stream) +void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -38,11 +38,11 @@ void FootpathItemObject::ReadLegacy(IStream * stream) _legacyType.path_bit.price = stream->ReadValue(); _legacyType.path_bit.scenery_tab_id = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); _sceneryTabEntry = stream->ReadValue(); - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void FootpathItemObject::Load() diff --git a/src/object/FootpathItemObject.h b/src/object/FootpathItemObject.h index 00f947b453..7da2cc9acb 100644 --- a/src/object/FootpathItemObject.h +++ b/src/object/FootpathItemObject.h @@ -34,7 +34,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/FootpathObject.cpp b/src/object/FootpathObject.cpp index 198d127e0e..f5657dd46b 100644 --- a/src/object/FootpathObject.cpp +++ b/src/object/FootpathObject.cpp @@ -29,7 +29,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void FootpathObject::ReadLegacy(IStream * stream) +void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.string_idx = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -39,8 +39,8 @@ void FootpathObject::ReadLegacy(IStream * stream) _legacyType.scrolling_mode = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(stream); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable()->Read(context, stream); } void FootpathObject::Load() diff --git a/src/object/FootpathObject.h b/src/object/FootpathObject.h index 2f6e385081..d0f9144ad2 100644 --- a/src/object/FootpathObject.h +++ b/src/object/FootpathObject.h @@ -33,7 +33,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/ImageTable.cpp b/src/object/ImageTable.cpp index 1b4ec16fa8..7d6ddb34b6 100644 --- a/src/object/ImageTable.cpp +++ b/src/object/ImageTable.cpp @@ -18,6 +18,7 @@ #include "../core/IStream.hpp" #include "../core/Memory.hpp" #include "ImageTable.h" +#include "Object.h" ImageTable::~ImageTable() { @@ -26,44 +27,51 @@ ImageTable::~ImageTable() _dataSize = 0; } -void ImageTable::Read(IStream * stream) +void ImageTable::Read(IReadObjectContext * context, IStream * stream) { - uint32 numImages = stream->ReadValue(); - uint32 imageDataSize = stream->ReadValue(); - - _dataSize = imageDataSize; - _data = Memory::Reallocate(_data, _dataSize); - - // Read g1 element headers - uintptr_t imageDataBase = (uintptr_t)_data; - for (uint32 i = 0; i < numImages; i++) + try { - rct_g1_element g1Element; + uint32 numImages = stream->ReadValue(); + uint32 imageDataSize = stream->ReadValue(); - uintptr_t imageDataOffset = (uintptr_t)stream->ReadValue(); - g1Element.offset = (uint8*)(imageDataBase + imageDataOffset); + _dataSize = imageDataSize; + _data = Memory::Reallocate(_data, _dataSize); - g1Element.width = stream->ReadValue(); - g1Element.height = stream->ReadValue(); - g1Element.x_offset = stream->ReadValue(); - g1Element.y_offset = stream->ReadValue(); - g1Element.flags = stream->ReadValue(); - g1Element.zoomed_offset = stream->ReadValue(); + // Read g1 element headers + uintptr_t imageDataBase = (uintptr_t)_data; + for (uint32 i = 0; i < numImages; i++) + { + rct_g1_element g1Element; - _entries.push_back(g1Element); + uintptr_t imageDataOffset = (uintptr_t)stream->ReadValue(); + g1Element.offset = (uint8*)(imageDataBase + imageDataOffset); + + g1Element.width = stream->ReadValue(); + g1Element.height = stream->ReadValue(); + g1Element.x_offset = stream->ReadValue(); + g1Element.y_offset = stream->ReadValue(); + g1Element.flags = stream->ReadValue(); + g1Element.zoomed_offset = stream->ReadValue(); + + _entries.push_back(g1Element); + } + + // Read g1 element data + size_t readBytes = (size_t)stream->TryRead(_data, _dataSize); + + // If data is shorter than expected (some custom objects are unfortunately like that) + size_t unreadBytes = _dataSize - readBytes; + if (unreadBytes > 0) + { + void * ptr = (void*)(((uintptr_t)_data) + readBytes); + Memory::Set(ptr, 0, unreadBytes); + + context->LogWarning(OBJECT_ERROR_BAD_IMAGE_TABLE, "Image table size shorter than expected."); + } } - - // Read g1 element data - size_t readBytes = (size_t)stream->TryRead(_data, _dataSize); - - // If data is shorter than expected (some custom objects are unfortunately like that) - size_t unreadBytes = _dataSize - readBytes; - if (unreadBytes > 0) + catch (Exception ex) { - void * ptr = (void*)(((uintptr_t)_data) + readBytes); - Memory::Set(ptr, 0, unreadBytes); - - Console::Error::WriteFormat("Warning: Image table size shorter than expected."); - Console::Error::WriteLine(); + context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Bad image table."); + throw; } } diff --git a/src/object/ImageTable.h b/src/object/ImageTable.h index 788501cf44..4692254625 100644 --- a/src/object/ImageTable.h +++ b/src/object/ImageTable.h @@ -24,6 +24,7 @@ extern "C" #include "../drawing/drawing.h" } +interface IReadObjectContext; interface IStream; class ImageTable @@ -36,7 +37,7 @@ private: public: ~ImageTable(); - void Read(IStream * stream); + void Read(IReadObjectContext * context, IStream * stream); const rct_g1_element * GetImages() const { return _entries.data(); } uint32 GetCount() const { return _entries.size(); }; }; \ No newline at end of file diff --git a/src/object/LargeSceneryObject.cpp b/src/object/LargeSceneryObject.cpp index bc0ef75a27..48353256f3 100644 --- a/src/object/LargeSceneryObject.cpp +++ b/src/object/LargeSceneryObject.cpp @@ -35,7 +35,7 @@ LargeSceneryObject::~LargeSceneryObject() Memory::Free(_tiles); } -void LargeSceneryObject::ReadLegacy(IStream * stream) +void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -49,7 +49,7 @@ void LargeSceneryObject::ReadLegacy(IStream * stream) _legacyType.large_scenery.var_11 = stream->ReadValue(); stream->Seek(5, STREAM_SEEK_CURRENT); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); _sceneryTabEntry = stream->ReadValue(); @@ -62,7 +62,7 @@ void LargeSceneryObject::ReadLegacy(IStream * stream) _tiles = ReadTiles(stream); - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void LargeSceneryObject::Load() diff --git a/src/object/LargeSceneryObject.h b/src/object/LargeSceneryObject.h index fa4b24bfe2..70b75d3b21 100644 --- a/src/object/LargeSceneryObject.h +++ b/src/object/LargeSceneryObject.h @@ -37,7 +37,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/Object.h b/src/object/Object.h index 358342ac6c..88eb3b349a 100644 --- a/src/object/Object.h +++ b/src/object/Object.h @@ -28,6 +28,14 @@ extern "C" interface IStream; struct ObjectRepositoryItem; +interface IReadObjectContext +{ + virtual ~IReadObjectContext() { } + + virtual void LogWarning(uint32 code, const utf8 * text) abstract; + virtual void LogError(uint32 code, const utf8 * text) abstract; +}; + class Object { private: @@ -48,7 +56,7 @@ public: const rct_object_entry * GetObjectEntry() const { return &_objectEntry; } virtual void * GetLegacyData() abstract; - virtual void ReadLegacy(IStream * stream) abstract; + virtual void ReadLegacy(IReadObjectContext * context, IStream * stream) abstract; virtual void Load() abstract; virtual void Unload() abstract; @@ -57,3 +65,14 @@ public: virtual void SetRepositoryItem(ObjectRepositoryItem * item) const { } }; + +enum OBJECT_ERROR : uint32 +{ + OBJECT_ERROR_OK, + OBJECT_ERROR_UNKNOWN, + OBJECT_ERROR_BAD_ENCODING, + OBJECT_ERROR_INVALID_PROPERTY, + OBJECT_ERROR_BAD_STRING_TABLE, + OBJECT_ERROR_BAD_IMAGE_TABLE, + OBJECT_ERROR_UNEXPECTED_EOF, +}; diff --git a/src/object/ObjectFactory.cpp b/src/object/ObjectFactory.cpp index 92169a99f9..4aa8eec4bb 100644 --- a/src/object/ObjectFactory.cpp +++ b/src/object/ObjectFactory.cpp @@ -18,6 +18,8 @@ #include "../core/FileStream.hpp" #include "../core/Memory.hpp" #include "../core/MemoryStream.h" +#include "../core/String.hpp" +#include "../core/Path.hpp" #include "BannerObject.h" #include "EntranceObject.h" #include "FootpathItemObject.h" @@ -38,6 +40,51 @@ extern "C" #include "../util/sawyercoding.h" } +class ReadObjectContext : public IReadObjectContext +{ +private: + utf8 * _objectName; + bool _wasWarning = false; + bool _wasError = false; + +public: + bool WasWarning() const { return _wasWarning; } + bool WasError() const { return _wasError; } + + ReadObjectContext(const utf8 * objectFileName) + { + _objectName = String::Duplicate(objectFileName); + } + + ~ReadObjectContext() override + { + Memory::Free(_objectName); + _objectName = nullptr; + } + + void LogWarning(uint32 code, const utf8 * text) override + { + _wasWarning = true; + + if (!String::IsNullOrEmpty(text)) + { + Console::Error::WriteFormat("[%s] Warning: %s", _objectName, text); + Console::Error::WriteLine(); + } + } + + void LogError(uint32 code, const utf8 * text) override + { + _wasError = true; + + if (!String::IsNullOrEmpty(text)) + { + Console::Error::WriteFormat("[%s] Error: %s", _objectName, text); + Console::Error::WriteLine(); + } + } +}; + namespace ObjectFactory { Object * CreateObjectFromLegacyFile(const utf8 * path) @@ -63,25 +110,40 @@ namespace ObjectFactory } else { + utf8 objectName[9] = { 0 }; + Memory::Copy(objectName, entry.name, 8); + + auto readContext = ReadObjectContext(objectName); try { bufferSize = sawyercoding_read_chunk_with_size(file, (uint8 *)buffer, bufferSize); if (bufferSize == SIZE_MAX) { - throw IOException("Error decoding data."); + readContext.LogError(OBJECT_ERROR_BAD_ENCODING, "Unable to decode chunk."); } - - buffer = Memory::Reallocate(buffer, bufferSize); - auto ms = MemoryStream(buffer, bufferSize); - result->ReadLegacy(&ms); - - Memory::Free(buffer); + else + { + buffer = Memory::Reallocate(buffer, bufferSize); + auto ms = MemoryStream(buffer, bufferSize); + result->ReadLegacy(&readContext, &ms); + } + } + catch (IOException ex) + { + // TODO check that ex is really EOF and not some other error + readContext.LogError(OBJECT_ERROR_UNEXPECTED_EOF, "Unexpectedly reached end of file."); } catch (Exception ex) { - Memory::Free(buffer); + readContext.LogError(OBJECT_ERROR_UNKNOWN, nullptr); + } + + Memory::Free(buffer); + if (readContext.WasError()) + { Console::Error::WriteFormat("Error reading object: '%s'", path); Console::Error::WriteLine(); + delete result; result = nullptr; } diff --git a/src/object/RideObject.cpp b/src/object/RideObject.cpp index 02572b67f2..482f66d2d2 100644 --- a/src/object/RideObject.cpp +++ b/src/object/RideObject.cpp @@ -43,19 +43,19 @@ RideObject::~RideObject() } } -void RideObject::ReadLegacy(IStream * stream) +void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { stream->Read(&_legacyType); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); - GetStringTable()->Read(stream, OBJ_STRING_ID_DESCRIPTION); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_DESCRIPTION); // TODO: Move to its own function when ride construction window is merged. if (gConfigInterface.select_by_track_type) { _legacyType.enabledTrackPieces = 0xFFFFFFFFFFFFFFFF; } - GetStringTable()->Read(stream, OBJ_STRING_ID_CAPACITY); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_CAPACITY); // Read preset colours, by default there are 32 _presetColours.count = stream->ReadValue(); @@ -79,7 +79,7 @@ void RideObject::ReadLegacy(IStream * stream) _peepLoadingPositions[i] = stream->ReadArray(numPeepLoadingPositions); } - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void RideObject::Load() diff --git a/src/object/RideObject.h b/src/object/RideObject.h index 171c84ea54..982907de96 100644 --- a/src/object/RideObject.h +++ b/src/object/RideObject.h @@ -36,7 +36,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/SceneryGroupObject.cpp b/src/object/SceneryGroupObject.cpp index d6173d4630..db06ad2c75 100644 --- a/src/object/SceneryGroupObject.cpp +++ b/src/object/SceneryGroupObject.cpp @@ -34,7 +34,7 @@ SceneryGroupObject::~SceneryGroupObject() Memory::Free(_items); } -void SceneryGroupObject::ReadLegacy(IStream * stream) +void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -45,9 +45,9 @@ void SceneryGroupObject::ReadLegacy(IStream * stream) _legacyType.pad_109 = stream->ReadValue(); _legacyType.var_10A = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); ReadItems(stream); - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); _legacyType.var_107 = _numItems; } diff --git a/src/object/SceneryGroupObject.h b/src/object/SceneryGroupObject.h index b21685173a..230cc632e4 100644 --- a/src/object/SceneryGroupObject.h +++ b/src/object/SceneryGroupObject.h @@ -36,7 +36,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/SmallSceneryObject.cpp b/src/object/SmallSceneryObject.cpp index d7d3ac2ecb..d025bcd274 100644 --- a/src/object/SmallSceneryObject.cpp +++ b/src/object/SmallSceneryObject.cpp @@ -34,7 +34,7 @@ SmallSceneryObject::~SmallSceneryObject() Memory::Free(_var10data); } -void SmallSceneryObject::ReadLegacy(IStream * stream) +void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -50,7 +50,7 @@ void SmallSceneryObject::ReadLegacy(IStream * stream) _legacyType.small_scenery.var_18 = stream->ReadValue(); _legacyType.small_scenery.scenery_tab_id = 0xFF; - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); _sceneryTabEntry = stream->ReadValue(); @@ -59,7 +59,7 @@ void SmallSceneryObject::ReadLegacy(IStream * stream) _var10data = ReadVar10(stream); } - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void SmallSceneryObject::Load() diff --git a/src/object/SmallSceneryObject.h b/src/object/SmallSceneryObject.h index a0bd022912..0420f70cc7 100644 --- a/src/object/SmallSceneryObject.h +++ b/src/object/SmallSceneryObject.h @@ -36,7 +36,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/StexObject.cpp b/src/object/StexObject.cpp index a7213eeec1..a535317fb2 100644 --- a/src/object/StexObject.cpp +++ b/src/object/StexObject.cpp @@ -29,7 +29,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_SCENARIO_DETAILS, }; -void StexObject::ReadLegacy(IStream * stream) +void StexObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.scenario_name = stream->ReadValue(); _legacyType.park_name = stream->ReadValue(); @@ -37,9 +37,9 @@ void StexObject::ReadLegacy(IStream * stream) _legacyType.var_06 = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(stream, OBJ_STRING_ID_SCENARIO_NAME); - GetStringTable()->Read(stream, OBJ_STRING_ID_PARK_NAME); - GetStringTable()->Read(stream, OBJ_STRING_ID_SCENARIO_DETAILS); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_SCENARIO_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_PARK_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_SCENARIO_DETAILS); } void StexObject::Load() diff --git a/src/object/StexObject.h b/src/object/StexObject.h index a5d58032e2..51e6f638f5 100644 --- a/src/object/StexObject.h +++ b/src/object/StexObject.h @@ -33,7 +33,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/StringTable.cpp b/src/object/StringTable.cpp index 943a960e04..0f1642d40f 100644 --- a/src/object/StringTable.cpp +++ b/src/object/StringTable.cpp @@ -18,6 +18,7 @@ #include "../core/IStream.hpp" #include "../core/String.hpp" #include "../localisation/LanguagePack.h" +#include "Object.h" #include "StringTable.h" constexpr uint8 RCT2_LANGUAGE_ID_ENGLISH_UK = 0; @@ -44,27 +45,35 @@ StringTable::~StringTable() } } -void StringTable::Read(IStream * stream, uint8 id) +void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8 id) { - uint8 languageId; - while ((languageId = stream->ReadValue()) != RCT2_LANGUAGE_ID_END) + try { - StringTableEntry entry; - entry.Id = id; - entry.LanguageId = languageId; - - char * win1252 = stream->ReadString(); - if (StringIsBlank(win1252)) + uint8 languageId; + while ((languageId = stream->ReadValue()) != RCT2_LANGUAGE_ID_END) { - entry.LanguageId = RCT2_LANGUAGE_ID_BLANK; + StringTableEntry entry; + entry.Id = id; + entry.LanguageId = languageId; + + char * win1252 = stream->ReadString(); + if (StringIsBlank(win1252)) + { + entry.LanguageId = RCT2_LANGUAGE_ID_BLANK; + } + + entry.Text = win1252_to_utf8_alloc(win1252); + Memory::Free(win1252); + + String::Trim(entry.Text); + + _strings.push_back(entry); } - - entry.Text = win1252_to_utf8_alloc(win1252); - Memory::Free(win1252); - - String::Trim(entry.Text); - - _strings.push_back(entry); + } + catch (Exception ex) + { + context->LogError(OBJECT_ERROR_BAD_STRING_TABLE, "Bad string table."); + throw; } Sort(); } diff --git a/src/object/StringTable.h b/src/object/StringTable.h index 48ff2b1826..38895a4c2e 100644 --- a/src/object/StringTable.h +++ b/src/object/StringTable.h @@ -19,6 +19,7 @@ #include #include "../common.h" +interface IReadObjectContext; interface IStream; struct StringTableEntry @@ -36,7 +37,7 @@ private: public: ~StringTable(); - void Read(IStream * stream, uint8 id); + void Read(IReadObjectContext * context, IStream * stream, uint8 id); const utf8 * GetString(uint8 id) const; private: diff --git a/src/object/WallObject.cpp b/src/object/WallObject.cpp index e8295adb0e..a88299dab2 100644 --- a/src/object/WallObject.cpp +++ b/src/object/WallObject.cpp @@ -29,7 +29,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void WallObject::ReadLegacy(IStream * stream) +void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.name = stream->ReadValue(); _legacyType.image = stream->ReadValue(); @@ -42,11 +42,11 @@ void WallObject::ReadLegacy(IStream * stream) _legacyType.wall.scenery_tab_id = stream->ReadValue(); _legacyType.wall.var_0D = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); _sceneryTabEntry = stream->ReadValue(); - GetImageTable()->Read(stream); + GetImageTable()->Read(context, stream); } void WallObject::Load() diff --git a/src/object/WallObject.h b/src/object/WallObject.h index 5d685a5e97..6b5e9820fc 100644 --- a/src/object/WallObject.h +++ b/src/object/WallObject.h @@ -34,7 +34,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; diff --git a/src/object/WaterObject.cpp b/src/object/WaterObject.cpp index 0f6b64429f..685484d227 100644 --- a/src/object/WaterObject.cpp +++ b/src/object/WaterObject.cpp @@ -28,7 +28,7 @@ enum OBJ_STRING_ID OBJ_STRING_ID_NAME, }; -void WaterObject::ReadLegacy(IStream * stream) +void WaterObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { _legacyType.string_idx = stream->ReadValue(); _legacyType.image_id = stream->ReadValue(); @@ -36,8 +36,8 @@ void WaterObject::ReadLegacy(IStream * stream) _legacyType.var_0A = stream->ReadValue(); _legacyType.var_0E = stream->ReadValue(); - GetStringTable()->Read(stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(stream); + GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable()->Read(context, stream); } void WaterObject::Load() diff --git a/src/object/WaterObject.h b/src/object/WaterObject.h index b288fc8b29..503e71bd13 100644 --- a/src/object/WaterObject.h +++ b/src/object/WaterObject.h @@ -33,7 +33,7 @@ public: void * GetLegacyData() override { return &_legacyType; } - void ReadLegacy(IStream * stream) override; + void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override;