diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index 510aead7..3959562c 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -132,11 +132,52 @@ namespace IW3 }; typedef char cbrushedge_t; - typedef float vec2_t[2]; - typedef float vec3_t[3]; - typedef float vec4_t[4]; typedef tdef_align32(128) unsigned int raw_uint128; + union vec2_t + { + float v[2]; + + struct + { + float x; + float y; + }; + }; + + union vec3_t + { + struct + { + float x; + float y; + float z; + }; + + float v[3]; + }; + + union vec4_t + { + float v[4]; + + struct + { + float x; + float y; + float z; + float w; + }; + + struct + { + float r; + float g; + float b; + float a; + }; + }; + struct XModelPiece { XModel* model; @@ -214,7 +255,10 @@ namespace IW3 XAnimPartTransData u; }; - typedef tdef_align32(4) short XQuat[2]; + struct type_align(4) XQuat + { + int16_t value[4]; + }; union XAnimDynamicIndicesQuat { @@ -231,7 +275,7 @@ namespace IW3 union XAnimDeltaPartQuatData { XAnimDeltaPartQuatDataFrames frames; - int16_t frame0[2]; + XQuat frame0; }; struct XAnimDeltaPartQuat diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 03493a12..9636bdf2 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -161,9 +161,50 @@ namespace IW4 typedef tdef_align32(128) unsigned int raw_uint128; typedef unsigned char cbrushedge_t; typedef unsigned short r_index_t; - typedef float vec2_t[2]; - typedef float vec3_t[3]; - typedef float vec4_t[4]; + + union vec2_t + { + float v[2]; + + struct + { + float x; + float y; + }; + }; + + union vec3_t + { + struct + { + float x; + float y; + float z; + }; + + float v[3]; + }; + + union vec4_t + { + float v[4]; + + struct + { + float x; + float y; + float z; + float w; + }; + + struct + { + float r; + float g; + float b; + float a; + }; + }; struct PhysPreset { @@ -330,7 +371,10 @@ namespace IW4 uint16_t _2[1]; }; - typedef tdef_align32(4) short XQuat2[2]; + struct type_align(4) XQuat2 + { + int16_t value[2]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames2 { @@ -341,7 +385,7 @@ namespace IW4 union XAnimDeltaPartQuatData2 { XAnimDeltaPartQuatDataFrames2 frames; - int16_t frame0[2]; + XQuat2 frame0; }; struct XAnimDeltaPartQuat2 @@ -356,7 +400,10 @@ namespace IW4 uint16_t _2[1]; }; - typedef tdef_align32(4) short XQuat[4]; + struct type_align(4) XQuat + { + int16_t value[4]; + }; struct XAnimDeltaPartQuatDataFrames { @@ -367,7 +414,7 @@ namespace IW4 union XAnimDeltaPartQuatData { XAnimDeltaPartQuatDataFrames frames; - int16_t frame0[4]; + XQuat frame0; }; struct XAnimDeltaPartQuat diff --git a/src/Common/Game/IW5/IW5_Assets.h b/src/Common/Game/IW5/IW5_Assets.h index ef9a37b6..e4753a01 100644 --- a/src/Common/Game/IW5/IW5_Assets.h +++ b/src/Common/Game/IW5/IW5_Assets.h @@ -379,7 +379,10 @@ namespace IW5 uint16_t _2[1]; }; - typedef tdef_align32(4) short XQuat2[2]; + struct type_align(4) XQuat2 + { + int16_t value[2]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames2 { @@ -390,7 +393,7 @@ namespace IW5 union XAnimDeltaPartQuatData2 { XAnimDeltaPartQuatDataFrames2 frames; - short frame0[2]; + XQuat2 frame0; }; struct XAnimDeltaPartQuat2 @@ -405,7 +408,10 @@ namespace IW5 uint16_t _2[1]; }; - typedef tdef_align32(4) short XQuat[4]; + struct type_align(4) XQuat + { + int16_t value[4]; + }; struct XAnimDeltaPartQuatDataFrames { @@ -416,7 +422,7 @@ namespace IW5 union XAnimDeltaPartQuatData { XAnimDeltaPartQuatDataFrames frames; - short frame0[4]; + XQuat frame0; }; struct XAnimDeltaPartQuat diff --git a/src/Common/Game/T5/T5_Assets.h b/src/Common/Game/T5/T5_Assets.h index fa562d38..8ccbd52a 100644 --- a/src/Common/Game/T5/T5_Assets.h +++ b/src/Common/Game/T5/T5_Assets.h @@ -385,7 +385,10 @@ namespace T5 XAnimPartTransData u; }; - typedef tdef_align32(4) short XQuat[2]; + struct type_align(4) XQuat + { + int16_t value[4]; + }; union XAnimDynamicIndicesQuat { @@ -402,7 +405,7 @@ namespace T5 union XAnimDeltaPartQuatData { XAnimDeltaPartQuatDataFrames frames; - int16_t frame0[2]; + XQuat frame0; }; struct XAnimDeltaPartQuat diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index b607c7cc..4eec23ae 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -5650,7 +5650,10 @@ namespace T6 uint16_t _2[1]; }; - typedef tdef_align32(4) int16_t XQuat2[2]; + struct type_align(4) XQuat2 + { + int16_t value[2]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames2 { @@ -5676,7 +5679,10 @@ namespace T6 uint16_t _2[1]; }; - typedef tdef_align32(4) int16_t XQuat[4]; + struct type_align(4) XQuat + { + int16_t value[4]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames { diff --git a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp index 5434043a..e44ef3c2 100644 --- a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp @@ -382,8 +382,8 @@ namespace for (auto i = 0u; i < originalGraphKnotCount; i++) { const auto& commonKnot = graph.knots[i]; - originalGraphKnots[i][0] = static_cast(commonKnot.x); - originalGraphKnots[i][1] = static_cast(commonKnot.y); + originalGraphKnots[i].x = static_cast(commonKnot.x); + originalGraphKnots[i].y = static_cast(commonKnot.y); } graphKnots = originalGraphKnots; diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp index 0c894a2c..de40981f 100644 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp +++ b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.cpp @@ -1,6 +1,9 @@ #include "AssetDumperLoadedSound.h" #include "Sound/WavTypes.h" +#include "Sound/WavWriter.h" + +#include using namespace IW3; @@ -9,37 +12,22 @@ bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) return true; } -void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream) +void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) { - const auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF) + sizeof(uint32_t) + sizeof(WAV_WAVE_ID) + sizeof(WavChunkHeader) + sizeof(WavFormatChunkPcm) - + sizeof(WavChunkHeader) + sizeof(asset->sound.info.data_len); + const WavWriter writer(stream); - stream.write(reinterpret_cast(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF)); - stream.write(reinterpret_cast(&riffMasterChunkSize), sizeof(riffMasterChunkSize)); - stream.write(reinterpret_cast(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID)); + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; - const WavChunkHeader formatChunkHeader{WAV_CHUNK_ID_FMT, sizeof(WavFormatChunkPcm)}; - stream.write(reinterpret_cast(&formatChunkHeader), sizeof(formatChunkHeader)); - - WavFormatChunkPcm formatChunk{ - WavFormat::PCM, - static_cast(asset->sound.info.channels), - asset->sound.info.rate, - asset->sound.info.rate * asset->sound.info.channels * asset->sound.info.bits / 8, - static_cast(asset->sound.info.block_size), - static_cast(asset->sound.info.bits), - }; - stream.write(reinterpret_cast(&formatChunk), sizeof(formatChunk)); - - const WavChunkHeader dataChunkHeader{WAV_CHUNK_ID_DATA, asset->sound.info.data_len}; - stream.write(reinterpret_cast(&dataChunkHeader), sizeof(dataChunkHeader)); - stream.write(asset->sound.data, asset->sound.info.data_len); + writer.WritePcmHeader(metaData, asset->sound.info.data_len); + writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); } void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile("sound/" + asset->m_name); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); if (!assetFile) return; @@ -48,11 +36,11 @@ void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo< switch (static_cast(loadedSound->sound.info.format)) { case WavFormat::PCM: - DumpWavPcm(context, loadedSound, stream); + DumpWavPcm(loadedSound, stream); break; default: - printf("Unknown format %i for loaded sound: %s\n", loadedSound->sound.info.format, loadedSound->name); + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); break; } } diff --git a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h index f4be599e..239e3b5b 100644 --- a/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h +++ b/src/ObjWriting/Game/IW3/AssetDumpers/AssetDumperLoadedSound.h @@ -7,7 +7,7 @@ namespace IW3 { class AssetDumperLoadedSound final : public AbstractAssetDumper { - static void DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream); + static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); protected: bool ShouldDump(XAssetInfo* asset) override; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp index 3e65ea6a..7348db5e 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.cpp @@ -3,6 +3,8 @@ #include "Sound/WavTypes.h" #include "Sound/WavWriter.h" +#include + using namespace IW4; bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) @@ -10,12 +12,13 @@ bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) return true; } -void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream) +void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) { const WavWriter writer(stream); - const WavMetaData metaData{ - static_cast(asset->sound.info.channels), static_cast(asset->sound.info.rate), static_cast(asset->sound.info.bits)}; + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; writer.WritePcmHeader(metaData, asset->sound.info.data_len); writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); @@ -24,7 +27,7 @@ void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const Load void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile("sound/" + asset->m_name); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); if (!assetFile) return; @@ -33,11 +36,11 @@ void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo< switch (static_cast(loadedSound->sound.info.format)) { case WavFormat::PCM: - DumpWavPcm(context, loadedSound, stream); + DumpWavPcm(loadedSound, stream); break; default: - printf("Unknown format %i for loaded sound: %s\n", loadedSound->sound.info.format, loadedSound->name); + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); break; } } diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h index f3b3b486..8065af76 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperLoadedSound.h @@ -7,7 +7,7 @@ namespace IW4 { class AssetDumperLoadedSound final : public AbstractAssetDumper { - static void DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream); + static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); protected: bool ShouldDump(XAssetInfo* asset) override; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp index e95f3ef5..0d388e3c 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp @@ -231,8 +231,8 @@ namespace IW4 for (auto i = 0u; i < originalKnotCount; i++) { auto& knot = graph.knots[i]; - knot.x = originalKnots[i][0]; - knot.y = originalKnots[i][1]; + knot.x = originalKnots[i].x; + knot.y = originalKnots[i].y; } return graph; diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp index 54b79491..7cb254e2 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp +++ b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.cpp @@ -1,6 +1,9 @@ #include "AssetDumperLoadedSound.h" #include "Sound/WavTypes.h" +#include "Sound/WavWriter.h" + +#include using namespace IW5; @@ -9,35 +12,22 @@ bool AssetDumperLoadedSound::ShouldDump(XAssetInfo* asset) return true; } -void AssetDumperLoadedSound::DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream) +void AssetDumperLoadedSound::DumpWavPcm(const LoadedSound* asset, std::ostream& stream) { - const auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF) + sizeof(uint32_t) + sizeof(WAV_WAVE_ID) + sizeof(WavChunkHeader) + sizeof(WavFormatChunkPcm) - + sizeof(WavChunkHeader) + sizeof(asset->sound.info.data_len); + const WavWriter writer(stream); - stream.write(reinterpret_cast(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF)); - stream.write(reinterpret_cast(&riffMasterChunkSize), sizeof(riffMasterChunkSize)); - stream.write(reinterpret_cast(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID)); + const WavMetaData metaData{.channelCount = static_cast(asset->sound.info.channels), + .samplesPerSec = static_cast(asset->sound.info.rate), + .bitsPerSample = static_cast(asset->sound.info.bits)}; - const WavChunkHeader formatChunkHeader{WAV_CHUNK_ID_FMT, sizeof(WavFormatChunkPcm)}; - stream.write(reinterpret_cast(&formatChunkHeader), sizeof(formatChunkHeader)); - - WavFormatChunkPcm formatChunk{WavFormat::PCM, - static_cast(asset->sound.info.channels), - asset->sound.info.rate, - asset->sound.info.rate * asset->sound.info.channels * asset->sound.info.bits / 8, - static_cast(asset->sound.info.block_size), - static_cast(asset->sound.info.bits)}; - stream.write(reinterpret_cast(&formatChunk), sizeof(formatChunk)); - - const WavChunkHeader dataChunkHeader{WAV_CHUNK_ID_DATA, asset->sound.info.data_len}; - stream.write(reinterpret_cast(&dataChunkHeader), sizeof(dataChunkHeader)); - stream.write(asset->sound.data, asset->sound.info.data_len); + writer.WritePcmHeader(metaData, asset->sound.info.data_len); + writer.WritePcmData(asset->sound.data, asset->sound.info.data_len); } void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo* asset) { const auto* loadedSound = asset->Asset(); - const auto assetFile = context.OpenAssetFile("sound/" + asset->m_name); + const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name)); if (!assetFile) return; @@ -46,11 +36,11 @@ void AssetDumperLoadedSound::DumpAsset(AssetDumpingContext& context, XAssetInfo< switch (static_cast(loadedSound->sound.info.format)) { case WavFormat::PCM: - DumpWavPcm(context, loadedSound, stream); + DumpWavPcm(loadedSound, stream); break; default: - printf("Unknown format %i for loaded sound: %s\n", loadedSound->sound.info.format, loadedSound->name); + std::cerr << std::format("Unknown format {} for loaded sound: {}\n", loadedSound->sound.info.format, loadedSound->name); break; } } diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h index e99ca33b..4f575072 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h +++ b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperLoadedSound.h @@ -7,7 +7,7 @@ namespace IW5 { class AssetDumperLoadedSound final : public AbstractAssetDumper { - static void DumpWavPcm(AssetDumpingContext& context, const LoadedSound* asset, std::ostream& stream); + static void DumpWavPcm(const LoadedSound* asset, std::ostream& stream); protected: bool ShouldDump(XAssetInfo* asset) override; diff --git a/src/ObjWriting/Sound/WavWriter.cpp b/src/ObjWriting/Sound/WavWriter.cpp index 0cb51016..2d8bfe84 100644 --- a/src/ObjWriting/Sound/WavWriter.cpp +++ b/src/ObjWriting/Sound/WavWriter.cpp @@ -7,31 +7,31 @@ WavWriter::WavWriter(std::ostream& stream) void WavWriter::WritePcmHeader(const WavMetaData& metaData, const size_t dataLen) const { - constexpr auto riffMasterChunkSize = sizeof(WAV_CHUNK_ID_RIFF) + sizeof(uint32_t) + sizeof(WAV_WAVE_ID) + sizeof(WavChunkHeader) + sizeof(WavFormatChunkPcm) - + sizeof(WavChunkHeader) + sizeof(dataLen); + constexpr auto riffMasterChunkSize = static_cast(sizeof(WAV_CHUNK_ID_RIFF) + sizeof(uint32_t) + sizeof(WAV_WAVE_ID) + sizeof(WavChunkHeader) + + sizeof(WavFormatChunkPcm) + sizeof(WavChunkHeader) + sizeof(uint32_t)); m_stream.write(reinterpret_cast(&WAV_CHUNK_ID_RIFF), sizeof(WAV_CHUNK_ID_RIFF)); m_stream.write(reinterpret_cast(&riffMasterChunkSize), sizeof(riffMasterChunkSize)); m_stream.write(reinterpret_cast(&WAV_WAVE_ID), sizeof(WAV_WAVE_ID)); - constexpr WavChunkHeader formatChunkHeader{WAV_CHUNK_ID_FMT, sizeof(WavFormatChunkPcm)}; + constexpr WavChunkHeader formatChunkHeader{.chunkID = WAV_CHUNK_ID_FMT, .chunkSize = sizeof(WavFormatChunkPcm)}; m_stream.write(reinterpret_cast(&formatChunkHeader), sizeof(formatChunkHeader)); const WavFormatChunkPcm formatChunk{ - WavFormat::PCM, - static_cast(metaData.channelCount), - metaData.samplesPerSec, - metaData.samplesPerSec * metaData.channelCount * metaData.bitsPerSample / 8, - static_cast(metaData.channelCount * (metaData.bitsPerSample / 8)), - static_cast(metaData.bitsPerSample), + .wFormatTag = WavFormat::PCM, + .nChannels = static_cast(metaData.channelCount), + .nSamplesPerSec = metaData.samplesPerSec, + .nAvgBytesPerSec = metaData.samplesPerSec * metaData.channelCount * metaData.bitsPerSample / 8, + .nBlockAlign = static_cast(metaData.channelCount * (metaData.bitsPerSample / 8)), + .wBitsPerSample = static_cast(metaData.bitsPerSample), }; m_stream.write(reinterpret_cast(&formatChunk), sizeof(formatChunk)); - const WavChunkHeader dataChunkHeader{WAV_CHUNK_ID_DATA, static_cast(dataLen)}; + const WavChunkHeader dataChunkHeader{.chunkID = WAV_CHUNK_ID_DATA, .chunkSize = static_cast(dataLen)}; m_stream.write(reinterpret_cast(&dataChunkHeader), sizeof(dataChunkHeader)); } void WavWriter::WritePcmData(const void* data, const size_t dataLen) const { - m_stream.write(static_cast(data), dataLen); + m_stream.write(static_cast(data), static_cast(dataLen)); } diff --git a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp index 0a896c90..bec9c598 100644 --- a/src/ObjWriting/XModel/Gltf/GltfWriter.cpp +++ b/src/ObjWriting/XModel/Gltf/GltfWriter.cpp @@ -534,7 +534,8 @@ namespace const auto translation = Eigen::Translation3f(bone.globalOffset[0], bone.globalOffset[2], -bone.globalOffset[1]); const auto rotation = Eigen::Quaternionf(bone.globalRotation.w, bone.globalRotation.x, bone.globalRotation.z, -bone.globalRotation.y); - const auto inverseBindMatrix = (translation * rotation).matrix().inverse(); + const auto bindMatrix = (translation * rotation); + const auto inverseBindMatrix = bindMatrix.matrix().inverse(); // GLTF matrix is column major inverseBindMatrixData[0] = inverseBindMatrix(0, 0); diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp index 516494b6..7cfddc4d 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp @@ -189,13 +189,13 @@ bool MemberComputations::IsInRuntimeBlock() const return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::RUNTIME; } -bool MemberComputations::IsFirstMember() const +bool MemberComputations::IsFirstUsedMember() const { const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); return !parentUsedMembers.empty() && parentUsedMembers[0] == m_info; } -bool MemberComputations::IsLastMember() const +bool MemberComputations::IsLastUsedMember() const { const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); return !parentUsedMembers.empty() && parentUsedMembers[parentUsedMembers.size() - 1] == m_info; diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h index 5ced8c26..2ab179f6 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h @@ -25,8 +25,8 @@ public: [[nodiscard]] bool IsNotInDefaultNormalBlock() const; [[nodiscard]] bool IsInTempBlock() const; [[nodiscard]] bool IsInRuntimeBlock() const; - [[nodiscard]] bool IsFirstMember() const; - [[nodiscard]] bool IsLastMember() const; + [[nodiscard]] bool IsFirstUsedMember() const; + [[nodiscard]] bool IsLastUsedMember() const; [[nodiscard]] bool HasDynamicArraySize() const; [[nodiscard]] bool IsDynamicMember() const; [[nodiscard]] bool IsAfterPartialLoad() const; diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp index aec0c366..5f77f861 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp @@ -2,6 +2,7 @@ #include "Domain/Definition/ArrayDeclarationModifier.h" #include "Domain/Definition/PointerDeclarationModifier.h" +#include "Domain/Definition/TypedefDefinition.h" #include "MemberComputations.h" #include @@ -55,6 +56,18 @@ DeclarationModifier* DeclarationModifierComputations::GetNextDeclarationModifier return nullptr; } +std::vector DeclarationModifierComputations::GetAllDeclarationModifiers() const +{ + const auto& declarationModifiers = m_information->m_member->m_type_declaration->m_declaration_modifiers; + std::vector all; + all.reserve(declarationModifiers.size()); + + for (const auto& mod : declarationModifiers) + all.emplace_back(mod.get()); + + return all; +} + std::vector DeclarationModifierComputations::GetFollowingDeclarationModifiers() const { std::vector following; @@ -71,7 +84,7 @@ std::vector DeclarationModifierComputations::GetFollowingD return following; } -std::vector DeclarationModifierComputations::GetArrayIndices() const +const std::vector& DeclarationModifierComputations::GetArrayIndices() const { return m_modifier_indices; } @@ -241,6 +254,15 @@ const IEvaluation* DeclarationModifierComputations::GetDynamicArraySizeEvaluatio return dynamic_cast(declarationModifier)->m_dynamic_size_evaluation.get(); } +bool DeclarationModifierComputations::HasPointerModifier() const +{ + return std::ranges::any_of(m_information->m_member->m_type_declaration->m_declaration_modifiers, + [](const std::unique_ptr& modifier) + { + return modifier->GetType() == DeclarationModifierType::POINTER; + }); +} + unsigned DeclarationModifierComputations::GetAlignment() const { const auto following = GetFollowingDeclarationModifiers(); diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h index f01bd2e1..4f1e7e70 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h @@ -12,8 +12,9 @@ public: [[nodiscard]] DeclarationModifier* GetDeclarationModifier() const; [[nodiscard]] DeclarationModifier* GetNextDeclarationModifier() const; + [[nodiscard]] std::vector GetAllDeclarationModifiers() const; [[nodiscard]] std::vector GetFollowingDeclarationModifiers() const; - [[nodiscard]] std::vector GetArrayIndices() const; + [[nodiscard]] const std::vector& GetArrayIndices() const; [[nodiscard]] bool IsArray() const; [[nodiscard]] int GetArraySize() const; [[nodiscard]] bool HasDynamicArrayCount() const; @@ -26,6 +27,7 @@ public: [[nodiscard]] const IEvaluation* GetPointerArrayCountEvaluation() const; [[nodiscard]] bool IsDynamicArray() const; [[nodiscard]] const IEvaluation* GetDynamicArraySizeEvaluation() const; + [[nodiscard]] bool HasPointerModifier() const; [[nodiscard]] unsigned GetAlignment() const; private: diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp index 2d732aaf..5e434f75 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp @@ -26,6 +26,18 @@ MemberInformation* StructureComputations::GetDynamicMember() const return nullptr; } +bool StructureComputations::HasNonDynamicMember() const +{ + for (const auto& member : m_info->m_ordered_members) + { + const MemberComputations memberComputations(member.get()); + if (!memberComputations.ShouldIgnore() && !memberComputations.IsAfterPartialLoad()) + return true; + } + + return false; +} + std::vector StructureComputations::GetUsedMembers() const { std::vector members; @@ -49,3 +61,8 @@ std::vector StructureComputations::GetUsedMembers() const return members; } + +bool StructureComputations::IsInTempBlock() const +{ + return m_info->m_block != nullptr && m_info->m_block->m_type == FastFileBlockType::TEMP; +} diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h index 3c1009e5..2792bdb4 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h @@ -9,7 +9,9 @@ public: [[nodiscard]] bool IsAsset() const; [[nodiscard]] MemberInformation* GetDynamicMember() const; + [[nodiscard]] bool HasNonDynamicMember() const; [[nodiscard]] std::vector GetUsedMembers() const; + [[nodiscard]] bool IsInTempBlock() const; private: const StructureInformation* m_info; diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h b/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h index 86ea7049..073ae611 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h @@ -1,8 +1,8 @@ #pragma once -#include "Utils/ClassUtils.h" +#include -enum class DeclarationModifierType +enum class DeclarationModifierType : std::uint8_t { POINTER, ARRAY diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp index 7b5cafe2..a7aeb157 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp @@ -5,13 +5,13 @@ #include TypeDeclaration::TypeDeclaration(const DataDefinition* type) - : m_flags(0), - m_size(0), - m_alignment(0), - m_is_const(false), + : m_is_const(false), m_has_custom_bit_size(false), m_type(type), - m_custom_bit_size(0) + m_custom_bit_size(0), + m_flags(0), + m_size(0), + m_alignment(0) { assert(m_type != nullptr); } diff --git a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp new file mode 100644 index 00000000..cc30f874 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp @@ -0,0 +1,19 @@ +#include "Architecture.h" + +#include + +unsigned GetPointerSizeForArchitecture(const Architecture architecture) +{ + switch (architecture) + { + case Architecture::X86: + return sizeof(uint32_t); + + case Architecture::X64: + return sizeof(uint64_t); + + default: + assert(false); + return sizeof(uint32_t); + } +} diff --git a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h index 80d06532..ec02e787 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h +++ b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h @@ -1,6 +1,8 @@ #pragma once -enum class Architecture +#include + +enum class Architecture : std::uint8_t { UNKNOWN, X86, @@ -14,3 +16,5 @@ static constexpr Architecture OWN_ARCHITECTURE = Architecture::X64 #endif ; + +extern unsigned GetPointerSizeForArchitecture(Architecture architecture); diff --git a/src/ZoneCodeGeneratorLib/Domain/Information/StructureInformation.h b/src/ZoneCodeGeneratorLib/Domain/Information/StructureInformation.h index 9ede86df..ce353fde 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Information/StructureInformation.h +++ b/src/ZoneCodeGeneratorLib/Domain/Information/StructureInformation.h @@ -26,6 +26,7 @@ public: bool m_requires_marking; bool m_has_matching_cross_platform_structure; + bool m_embedded_reference_exists; bool m_non_embedded_reference_exists; bool m_single_pointer_reference_exists; bool m_array_pointer_reference_exists; diff --git a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp index c5ae8ff8..189c53c9 100644 --- a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp @@ -18,8 +18,10 @@ RenderingUsedType::RenderingUsedType(const DataDefinition* type, StructureInform { } -RenderingContext::RenderingContext(std::string game, std::vector fastFileBlocks) +RenderingContext::RenderingContext(std::string game, const Architecture gameArchitecture, std::vector fastFileBlocks) : m_game(std::move(game)), + m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE), + m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)), m_blocks(std::move(fastFileBlocks)), m_asset(nullptr), m_has_actions(false), @@ -190,7 +192,8 @@ bool RenderingContext::UsedTypeHasActions(const RenderingUsedType* usedType) con std::unique_ptr RenderingContext::BuildContext(const IDataRepository* repository, StructureInformation* asset) { - auto context = std::make_unique(RenderingContext(repository->GetGameName(), repository->GetAllFastFileBlocks())); + auto context = + std::make_unique(RenderingContext(repository->GetGameName(), repository->GetArchitecture(), repository->GetAllFastFileBlocks())); context->MakeAsset(repository, asset); context->CreateUsedTypeCollections(); diff --git a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h index 06ba68cb..d6587718 100644 --- a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h +++ b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h @@ -30,6 +30,8 @@ public: static std::unique_ptr BuildContext(const IDataRepository* repository, StructureInformation* asset); std::string m_game; + bool m_architecture_mismatch; + unsigned m_pointer_size; std::vector m_blocks; StructureInformation* m_asset; @@ -43,7 +45,7 @@ public: const FastFileBlock* m_default_temp_block; private: - RenderingContext(std::string game, std::vector fastFileBlocks); + RenderingContext(std::string game, Architecture gameArchitecture, std::vector fastFileBlocks); RenderingUsedType* AddUsedType(std::unique_ptr usedType); RenderingUsedType* GetBaseType(const IDataRepository* repository, MemberComputations* computations, RenderingUsedType* usedType); diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp index 6513a060..1a8ce438 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp @@ -136,18 +136,6 @@ std::string return str.str(); } -std::string BaseTemplate::MakeMemberAccess(const std::string& variableName, - StructureInformation* info, - const MemberInformation* member, - const DeclarationModifierComputations& modifier) -{ - std::ostringstream str; - str << variableName << "->" << member->m_member->m_name; - MakeArrayIndicesInternal(modifier, str); - - return str.str(); -} - std::string BaseTemplate::MakeTypeDecl(const TypeDeclaration* decl) { std::ostringstream str; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h index 5818957d..e9b8622a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h @@ -29,10 +29,6 @@ protected: static std::string MakeMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier); static std::string MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier); - static std::string MakeMemberAccess(const std::string& variableName, - StructureInformation* info, - const MemberInformation* member, - const DeclarationModifierComputations& modifier); static std::string MakeTypeDecl(const TypeDeclaration* decl); static std::string MakeFollowingReferences(const std::vector& modifiers); static std::string MakeArrayIndices(const DeclarationModifierComputations& modifierComputations); diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index 87181ba2..d3e0e752 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -6,6 +6,7 @@ #include "Utils/StringUtils.h" #include +#include #include namespace @@ -59,6 +60,23 @@ namespace m_intendation++; // Method Declarations + if (m_env.m_architecture_mismatch) + { + for (const auto* type : m_env.m_used_types) + { + if (ShouldGenerateFillMethod(*type)) + { + PrintFillStructMethodDeclaration(type->m_info); + } + } + for (const auto* type : m_env.m_used_types) + { + if (type->m_info && type->m_type == type->m_info->m_definition && StructureComputations(type->m_info).GetDynamicMember()) + { + PrintDynamicFillMethodDeclaration(type->m_info); + } + } + } for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists) @@ -97,7 +115,8 @@ namespace // Variable Declarations: type varType; for (const auto* type : m_env.m_used_types) { - if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) + if (type->m_info && !type->m_info->m_definition->m_anonymous + && (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset()) { LINE(VariableDecl(type->m_type)) } @@ -141,6 +160,7 @@ namespace LINE("") LINE("#include ") LINE("#include ") + LINE("#include ") LINE("") LINEF("using namespace {0};", m_env.m_game) @@ -149,6 +169,25 @@ namespace LINE("") PrintMainLoadMethod(); + if (m_env.m_architecture_mismatch) + { + for (const auto* type : m_env.m_used_types) + { + if (ShouldGenerateFillMethod(*type)) + { + LINE("") + PrintFillStructMethod(type->m_info); + } + } + for (const auto* type : m_env.m_used_types) + { + if (type->m_info && type->m_type == type->m_info->m_definition && StructureComputations(type->m_info).GetDynamicMember()) + { + LINE("") + PrintDynamicFillMethod(*type->m_info); + } + } + } for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists) @@ -212,6 +251,26 @@ namespace return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def)); } + bool ShouldGenerateFillMethod(const RenderingUsedType& type) + { + const auto isNotForeignAsset = type.m_is_context_asset || !type.m_info || !StructureComputations(type.m_info).IsAsset(); + const auto hasMismatchingStructure = + type.m_info && type.m_type == type.m_info->m_definition && !type.m_info->m_has_matching_cross_platform_structure; + const auto isEmbeddedDynamic = type.m_info && type.m_info->m_embedded_reference_exists && StructureComputations(type.m_info).GetDynamicMember(); + + return isNotForeignAsset && (hasMismatchingStructure || isEmbeddedDynamic); + } + + void PrintFillStructMethodDeclaration(const StructureInformation* info) const + { + LINEF("void FillStruct_{0}(const ZoneStreamFillReadAccessor& fillAccessor);", MakeSafeTypeName(info->m_definition)) + } + + void PrintDynamicFillMethodDeclaration(const StructureInformation* info) const + { + LINEF("size_t LoadDynamicFill_{0}(const ZoneStreamFillReadAccessor& parentFill);", MakeSafeTypeName(info->m_definition)) + } + void PrintHeaderPtrArrayLoadMethodDeclaration(const DataDefinition* def) const { LINEF("void LoadPtrArray_{0}(bool atStreamStart, size_t count);", MakeSafeTypeName(def)) @@ -297,9 +356,601 @@ namespace LINE("}") } + [[nodiscard]] size_t SizeForDeclModifierLevel(const MemberInformation& memberInfo, const size_t level) const + { + const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers; + if (declModifiers.empty()) + return memberInfo.m_member->m_type_declaration->GetSize(); + + if (level == 0) + return memberInfo.m_member->m_type_declaration->GetSize(); + + size_t currentSize = memberInfo.m_member->m_type_declaration->m_type->GetSize(); + const auto end = declModifiers.rbegin() + (declModifiers.size() - level); + for (auto i = declModifiers.rbegin(); i != end; ++i) + { + if ((*i)->GetType() == DeclarationModifierType::POINTER) + currentSize = m_env.m_pointer_size; + else + currentSize *= dynamic_cast(i->get())->m_size; + } + + return currentSize; + } + + [[nodiscard]] size_t + OffsetForMemberModifier(const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, const size_t nestedBaseOffset) const + { + size_t curOffset = memberInfo.m_member->m_offset; + + const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers; + auto curDeclModifier = declModifiers.begin(); + auto curLevel = 0u; + for (const auto index : modifier.GetArrayIndices()) + { + if (index > 0) + curOffset += index * SizeForDeclModifierLevel(memberInfo, curLevel + 1); + + curLevel++; + } + + return curOffset + nestedBaseOffset; + } + + void PrintFillStruct_Member_DynamicArray(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + + LINEF("const auto dynamicArraySize = static_cast({0});", MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) + LINE("if (dynamicArraySize > 0)") + LINE("{") + m_intendation++; + + const auto callFillForMember = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure; + + if (callFillForMember) + { + LINEF("{0} = &{1}[0];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + else + { + LINEF("fillAccessor.Fill({0}[0], {1});", MakeMemberAccess(&structInfo, &memberInfo, modifier), memberInfo.m_member->m_offset) + } + + LINEF("for (auto i = 1uz; i < dynamicArraySize; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + LINE("{") + m_intendation++; + if (callFillForMember) + { + LINEF("{0} = &{1}[i];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1} + i * {2}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + memberInfo.m_member->m_type_declaration->GetSize()) + } + else + { + LINEF("fillAccessor.Fill({0}[i], {1} + i * {2});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + memberInfo.m_member->m_type_declaration->GetSize()) + } + m_intendation--; + LINE("}") + + m_intendation--; + LINE("}") + } + + void PrintFillStruct_Member_PointerArray(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + if (modifier.IsArray()) + { + LINEF("for (auto i = 0u; i < std::extent_v; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + LINE("{") + m_intendation++; + + LINEF("fillAccessor.FillPtr({0}[i], {1} + {2} * i);", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + m_env.m_pointer_size) + + if (!StructureComputations(&structInfo).IsInTempBlock() + && (memberInfo.m_is_reusable || (memberInfo.m_type && StructureComputations(memberInfo.m_type).IsAsset()))) + { + LINEF("m_stream.AddPointerLookup(&{0}[i], fillAccessor.BlockBuffer({1} + {2} * i));", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + m_env.m_pointer_size) + } + + m_intendation--; + LINE("}") + } + else + { + LINEF("fillAccessor.FillPtr({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + + void PrintFillStruct_Member_EmbeddedArray(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + if (memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure) + { + LINEF("for (auto i = 0u; i < std::extent_v; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + LINE("{") + m_intendation++; + LINEF("{0} = &{1}[i];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1} + i * {2}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + memberInfo.m_member->m_type_declaration->m_type->GetSize()) + m_intendation--; + LINE("}") + } + else + { + LINEF("fillAccessor.FillArray({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + + void PrintFillStruct_Member_Embedded(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + const auto hasAnonymousType = memberInfo.m_type && memberInfo.m_type->m_definition->m_anonymous; + + if (!hasAnonymousType) + { + const auto hasMismatchingStructure = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure; + const auto hasDynamicMember = memberInfo.m_type && StructureComputations(memberInfo.m_type).GetDynamicMember(); + if (hasMismatchingStructure || hasDynamicMember) + { + LINEF("{0} = &{1};", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + else + { + LINEF("fillAccessor.Fill({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + else if (memberInfo.m_member->m_name.empty()) + { + const auto anonymousMemberOffset = memberInfo.m_member->m_offset + nestedBaseOffset; + for (const auto& anonymousMember : memberInfo.m_type->m_ordered_members) + { + PrintFillStruct_Member(structInfo, *anonymousMember, DeclarationModifierComputations(anonymousMember.get()), anonymousMemberOffset); + } + } + else + { + LINEF("#error Unsupported anonymous struct with name: {0}", memberInfo.m_member->m_name) + } + } + + void PrintFillStruct_Member_ReferenceArray(const StructureInformation& info, + const MemberInformation& member, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + for (const auto& entry : modifier.GetArrayEntries()) + { + PrintFillStruct_Member(info, member, entry, nestedBaseOffset); + } + } + + // nestedBaseOffset: Base offset in case member is part of a nested anonymous sub-struct + void PrintFillStruct_Member(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + if (modifier.IsDynamicArray()) + { + PrintFillStruct_Member_DynamicArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsSinglePointer() || modifier.IsArrayPointer()) + { + LINEF("fillAccessor.FillPtr({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + + if (!StructureComputations(&structInfo).IsInTempBlock() + && (memberInfo.m_is_reusable || (memberInfo.m_type && StructureComputations(memberInfo.m_type).IsAsset()))) + { + LINEF("m_stream.AddPointerLookup(&{0}, fillAccessor.BlockBuffer({1}));", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + else if (modifier.IsPointerArray()) + { + PrintFillStruct_Member_PointerArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsArray() && modifier.GetNextDeclarationModifier() == nullptr) + { + PrintFillStruct_Member_EmbeddedArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.GetDeclarationModifier() == nullptr) + { + PrintFillStruct_Member_Embedded(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsArray()) + { + PrintFillStruct_Member_ReferenceArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else + { + assert(false); + LINEF("#error PrintFillStruct_Member failed @ {0}", memberInfo.m_member->m_name) + } + } + + void PrintFillStruct_Member_Condition_Struct(const StructureInformation& structInfo, const MemberInformation& member) + { + if (member.m_condition) + { + LINEF("if ({0})", MakeEvaluation(member.m_condition.get())) + LINE("{") + m_intendation++; + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + else + { + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + } + } + + void PrintFillStruct_Member_Condition_Union(const StructureInformation& structInfo, const MemberInformation& member) + { + const MemberComputations computations(&member); + + if (computations.IsFirstUsedMember()) + { + if (member.m_condition) + { + LINEF("if ({0})", MakeEvaluation(member.m_condition.get())) + LINE("{") + m_intendation++; + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + else + { + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + } + } + else if (computations.IsLastUsedMember()) + { + if (member.m_condition) + { + LINEF("else if ({0})", MakeEvaluation(member.m_condition.get())) + LINE("{") + m_intendation++; + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + else + { + LINE("else") + LINE("{") + m_intendation++; + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + } + else + { + if (member.m_condition) + { + LINEF("else if ({0})", MakeEvaluation(member.m_condition.get())) + LINE("{") + m_intendation++; + + PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + else + { + LINEF("#error Middle member of union2 must have condition ({0})", member.m_member->m_name) + } + } + } + + void PrintFillStruct_Struct(const StructureInformation& info) + { + if (info.m_reusable_reference_exists) + { + LINEF("m_stream.AddPointerLookup({0}, fillAccessor.BlockBuffer(0));", MakeTypeVarName(info.m_definition)) + LINE("") + } + + const auto* dynamicMember = StructureComputations(&info).GetDynamicMember(); + + if (dynamicMember) + { + if (info.m_definition->GetType() == DataDefinitionType::UNION) + { + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore()) + continue; + + PrintFillStruct_Member_Condition_Union(info, *member); + } + } + else + { + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore() || member.get() == dynamicMember) + continue; + + PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u); + } + + PrintFillStruct_Member_Condition_Struct(info, *dynamicMember); + } + } + else + { + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore()) + continue; + + PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u); + } + } + } + + void PrintFillStructMethod(const StructureInformation* info) + { + LINEF("void {0}::FillStruct_{1}(const ZoneStreamFillReadAccessor& fillAccessor)", + LoaderClassName(m_env.m_asset), + MakeSafeTypeName(info->m_definition)) + + LINE("{") + m_intendation++; + + PrintFillStruct_Struct(*info); + + m_intendation--; + LINE("}") + } + + void PrintDynamicOversize_DynamicMember(const StructureInformation& info, const MemberInformation& member) const + { + const MemberComputations memberComputations(&member); + const DeclarationModifierComputations modifier(&member); + + if (memberComputations.HasDynamicArraySize()) + { + LINEF("const auto dynamicArrayEntries = static_cast({0});", MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) + LINEF("m_stream.AppendToFill(dynamicArrayEntries * {0});", member.m_member->m_type_declaration->m_type->GetSize()) + LINEF("return dynamicArrayEntries * sizeof({0}{1}) + offsetof({2}, {3});", + MakeTypeDecl(member.m_member->m_type_declaration.get()), + MakeFollowingReferences(modifier.GetAllDeclarationModifiers()), + info.m_definition->GetFullName(), + member.m_member->m_name) + } + else if (member.m_type && StructureComputations(member.m_type).GetDynamicMember()) + { + LINEF("return LoadDynamicFill_{0}(fillAccessor.AtOffset({1})) + offsetof({2}, {3});", + MakeSafeTypeName(member.m_type->m_definition), + member.m_member->m_offset, + info.m_definition->GetFullName(), + member.m_member->m_name) + } + else + { + LINEF("m_stream.AppendToFill({0});", member.m_member->m_type_declaration->GetSize()) + LINEF("return sizeof({0}{1}) + offsetof({2}, {3});", + MakeTypeDecl(member.m_member->m_type_declaration.get()), + MakeFollowingReferences(modifier.GetAllDeclarationModifiers()), + info.m_definition->GetFullName(), + member.m_member->m_name) + } + } + + void DynamicOverSize_Struct_Condition(const StructureInformation& info, const MemberInformation& member) + { + if (member.m_condition) + { + LINEF("if ({0})", MakeEvaluation(member.m_condition.get())) + LINE("{") + m_intendation++; + + PrintFillStruct_Member(info, member, DeclarationModifierComputations(&member), 0u); + + m_intendation--; + LINE("}") + } + else + { + + PrintFillStruct_Member(info, member, DeclarationModifierComputations(&member), 0u); + } + } + + void PrintDynamicOversize_Struct(const StructureInformation& info) + { + const StructureComputations structureComputations(&info); + const auto dynamicMember = structureComputations.GetDynamicMember(); + + LINEF("const auto fillAccessor = m_stream.AppendToFill({0}).AtOffset(parentFill.Offset());", dynamicMember->m_member->m_offset) + LINE("") + + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore() || computations.IsDynamicMember()) + continue; + + DynamicOverSize_Struct_Condition(info, *member); + } + + LINE("") + + PrintDynamicOversize_DynamicMember(info, *dynamicMember); + } + + void PrintDynamicOversize_Union(const StructureInformation& info) + { + LINE("const auto& fillAccessor = parentFill;") + + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore()) + continue; + + if (computations.IsFirstUsedMember()) + { + LINE("") + if (member->m_condition) + { + LINEF("if ({0})", MakeEvaluation(member->m_condition.get())) + LINE("{") + m_intendation++; + + PrintDynamicOversize_DynamicMember(info, *member); + + m_intendation--; + LINE("}") + } + else + { + PrintDynamicOversize_DynamicMember(info, *member); + } + } + else if (computations.IsLastUsedMember()) + { + if (member->m_condition) + { + LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) + LINE("{") + m_intendation++; + + PrintDynamicOversize_DynamicMember(info, *member); + + m_intendation--; + LINE("}") + } + else + { + LINE("else") + LINE("{") + m_intendation++; + + PrintDynamicOversize_DynamicMember(info, *member); + + m_intendation--; + LINE("}") + } + } + else + { + if (member->m_condition) + { + LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) + LINE("{") + m_intendation++; + + PrintDynamicOversize_DynamicMember(info, *member); + + m_intendation--; + LINE("}") + } + else + { + LINEF("#error Middle member of union must have condition ({0})", member->m_member->m_name) + } + } + } + } + + void PrintDynamicFillMethod(const StructureInformation& info) + { + LINEF("size_t {0}::LoadDynamicFill_{1}(const ZoneStreamFillReadAccessor& parentFill)", + LoaderClassName(m_env.m_asset), + MakeSafeTypeName(info.m_definition)) + + LINE("{") + m_intendation++; + + LINEF("{0} temp{1};", info.m_definition->GetFullName(), MakeSafeTypeName(info.m_definition)) + LINEF("{0} = &temp{1};", MakeTypeVarName(info.m_definition), MakeSafeTypeName(info.m_definition)) + + if (info.m_definition->GetType() == DataDefinitionType::UNION) + { + PrintDynamicOversize_Union(info); + } + else + { + PrintDynamicOversize_Struct(info); + } + + m_intendation--; + LINE("}") + } + void PrintLoadPtrArrayMethod_Loading(const DataDefinition* def, const StructureInformation* info) const { - LINEF("*{0} = m_stream->Alloc<{1}>({2});", MakeTypePtrVarName(def), def->GetFullName(), def->GetAlignment()) + if (info && !info->m_has_matching_cross_platform_structure && StructureComputations(info).GetDynamicMember()) + { + LINE("// Alloc first for alignment, then proceed to read as game does") + LINEF("m_stream.Alloc({0});", def->GetAlignment()) + LINEF("const auto allocSize = LoadDynamicFill_{0}(m_stream.LoadWithFill(0));", MakeSafeTypeName(def)) + LINEF("*{0} = static_cast<{1}*>(m_stream.AllocOutOfBlock(0, allocSize));", MakeTypePtrVarName(def), def->GetFullName()) + } + else + { + LINEF("*{0} = m_stream.{1}<{2}>({3});", + MakeTypePtrVarName(def), + m_env.m_architecture_mismatch ? "AllocOutOfBlock" : "Alloc", + def->GetFullName(), + def->GetAlignment()) + } if (info && !info->m_is_leaf) { @@ -308,7 +959,7 @@ namespace } else { - LINEF("m_stream->Load<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def)) + LINEF("m_stream.Load<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def)) } } @@ -320,14 +971,15 @@ namespace if (info && StructureComputations(info).IsAsset()) { - LINEF("{0} loader(m_zone, *m_stream);", LoaderClassName(info)) + LINEF("{0} loader(m_zone, m_stream);", LoaderClassName(info)) LINEF("loader.Load({0});", MakeTypePtrVarName(def)) } else { if (reusable) { - LINEF("if (*{0} == PTR_FOLLOWING)", MakeTypePtrVarName(def)) + LINEF("const auto zonePtrType = GetZonePointerType(*{0});", MakeTypePtrVarName(def)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING)", MakeTypePtrVarName(def)) LINE("{") m_intendation++; @@ -339,7 +991,14 @@ namespace LINE("{") m_intendation++; - LINEF("*{0} = m_stream->ConvertOffsetToPointer(*{0});", MakeTypePtrVarName(def)) + if (info && !info->m_has_matching_cross_platform_structure) + { + LINEF("*{0} = m_stream.ConvertOffsetToPointerLookup(*{0}).Expect();", MakeTypePtrVarName(def)) + } + else + { + LINEF("*{0} = m_stream.ConvertOffsetToPointerNative(*{0});", MakeTypePtrVarName(def)) + } m_intendation--; LINE("}") @@ -364,9 +1023,33 @@ namespace LINE("") LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream->Load<{0}*>({1}, count);", def->GetFullName(), MakeTypePtrVarName(def)) - m_intendation--; + + if (m_env.m_architecture_mismatch) + { + LINE("{") + m_intendation++; + LINEF("const auto ptrArrayFill = m_stream.LoadWithFill({0} * count);", m_env.m_pointer_size) + LINE("for (size_t index = 0; index < count; index++)") + LINE("{") + m_intendation++; + LINEF("ptrArrayFill.FillPtr({0}[index], {1} * index);", MakeTypePtrVarName(def), m_env.m_pointer_size) + + if (reusable || (info && StructureComputations(info).IsAsset())) + { + LINEF("m_stream.AddPointerLookup(&{0}[index], ptrArrayFill.BlockBuffer({1} * index));", MakeTypePtrVarName(def), m_env.m_pointer_size) + } + + m_intendation--; + LINE("}") + m_intendation--; + LINE("}") + } + else + { + m_intendation++; + LINEF("m_stream.Load<{0}*>({1}, count);", def->GetFullName(), MakeTypePtrVarName(def)) + m_intendation--; + } LINE("") LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) @@ -394,12 +1077,40 @@ namespace LINEF("assert({0} != nullptr);", MakeTypeVarName(def)) LINE("") LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream->Load<{0}>({1}, count);", def->GetFullName(), MakeTypeVarName(def)) - m_intendation--; + + if (info->m_has_matching_cross_platform_structure) + { + m_intendation++; + LINEF("m_stream.Load<{0}>({1}, count);", info->m_definition->GetFullName(), MakeTypeVarName(def)) + m_intendation--; + } + else + { + LINE("{") + m_intendation++; + + LINEF("const auto arrayFill = m_stream.LoadWithFill({0} * count);", def->GetSize()) + LINEF("auto* arrayStart = {0};", MakeTypeVarName(def)) + LINEF("auto* var = {0};", MakeTypeVarName(def)) + LINE("for (size_t index = 0; index < count; index++)") + LINE("{") + m_intendation++; + + LINEF("{0} = var;", MakeTypeVarName(info->m_definition)) + LINEF("FillStruct_{0}(arrayFill.AtOffset(0 + {1} * index));", info->m_definition->m_name, def->GetSize()) + LINE("var++;") + + m_intendation--; + LINE("}") + + LINEF("{0} = arrayStart;", MakeTypeVarName(def)) + + m_intendation--; + LINE("}") + } LINE("") - LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) + LINEF("auto* var = {0};", MakeTypeVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; @@ -422,7 +1133,7 @@ namespace { if (loadType == MemberLoadType::SINGLE_POINTER) { - LINEF("{0} loader(m_zone, *m_stream);", LoaderClassName(member->m_type)) + LINEF("{0} loader(m_zone, m_stream);", LoaderClassName(member->m_type)) LINEF("loader.Load(&{0});", MakeMemberAccess(info, member, modifier)) } else if (loadType == MemberLoadType::POINTER_ARRAY) @@ -472,7 +1183,7 @@ namespace } } - void LoadMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const + void LoadMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { const MemberComputations computations(member); if (member->m_type && !member->m_type->m_is_leaf && !computations.IsInRuntimeBlock()) @@ -494,9 +1205,23 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } + else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure && computations.IsInRuntimeBlock()) + { + LINEF("const auto runtimeArraySize = static_cast({0});", MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) + LINEF("const auto runtimeFill = m_stream.LoadWithFill({0} * runtimeArraySize);", member->m_member->m_type_declaration->m_type->GetSize()) + LINE("for (auto i = 0uz; i < runtimeArraySize; i++)") + LINE("{") + m_intendation++; + LINEF("{0} = &{1}[i];", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) + LINEF("FillStruct_{0}(runtimeFill.AtOffset(i * {1}));", + MakeSafeTypeName(member->m_member->m_type_declaration->m_type), + member->m_member->m_type_declaration->m_type->GetSize()) + m_intendation--; + LINE("}") + } else { - LINEF("m_stream->Load<{0}{1}>({2}, {3});", + LINEF("m_stream.Load<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), @@ -533,7 +1258,7 @@ namespace { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - if (computations.IsAfterPartialLoad()) + if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("LoadArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), arraySizeStr) } @@ -554,9 +1279,9 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } - else if (computations.IsAfterPartialLoad()) + else if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { - LINEF("m_stream->Load<{0}{1}>({2}, {3});", + LINEF("m_stream.Load<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), @@ -564,22 +1289,34 @@ namespace } } - void LoadMember_DynamicArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const + void LoadMember_DynamicArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { if (member->m_type && !member->m_type->m_is_leaf) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - LINEF("LoadArray_{0}(true, {1});", + LINEF("LoadArray_{0}({1}, {2});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), + m_env.m_architecture_mismatch ? "false" : "true", MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) } - else + else if (info->m_has_matching_cross_platform_structure) { - LINEF("m_stream->Load<{0}{1}>({2}, {3});", + if (m_env.m_architecture_mismatch) + { + LINE("if (atStreamStart)") + m_intendation++; + } + + LINEF("m_stream.Load<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) + + if (m_env.m_architecture_mismatch) + { + m_intendation--; + } } } @@ -590,7 +1327,7 @@ namespace { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - if (computations.IsAfterPartialLoad()) + if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("Load_{0}(true);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } @@ -611,9 +1348,9 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } - else if (computations.IsAfterPartialLoad()) + else if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { - LINEF("m_stream->Load<{0}{1}>(&{2});", + LINEF("m_stream.Load<{0}{1}>(&{2});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier)) @@ -626,6 +1363,7 @@ namespace if (member->m_type && !member->m_type->m_is_leaf && !computations.IsInRuntimeBlock()) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) + LINEF("Load_{0}(true);", MakeSafeTypeName(member->m_type->m_definition)) if (member->m_type->m_post_load_action) @@ -640,9 +1378,16 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } + else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure && computations.IsInRuntimeBlock()) + { + LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) + LINEF("FillStruct_{0}(m_stream.LoadWithFill({1}));", + MakeSafeTypeName(member->m_member->m_type_declaration->m_type), + member->m_member->m_type_declaration->m_type->GetSize()) + } else { - LINEF("m_stream->Load<{0}{1}>({2});", + LINEF("m_stream.Load<{0}{1}>({2});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier)) @@ -652,7 +1397,7 @@ namespace void LoadMember_TypeCheck(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, - const MemberLoadType loadType) const + const MemberLoadType loadType) { if (member->m_is_string) { @@ -722,6 +1467,19 @@ namespace return true; } + [[nodiscard]] bool ShouldAllocOutOfBlock(const MemberInformation& member, const MemberLoadType loadType) const + { + return m_env.m_architecture_mismatch + && ((member.m_type && !member.m_type->m_has_matching_cross_platform_structure) || loadType == MemberLoadType::POINTER_ARRAY); + } + + [[nodiscard]] bool + ShouldPreAllocDynamic(const MemberInformation& member, const DeclarationModifierComputations& modifier, const MemberLoadType loadType) const + { + return ShouldAllocOutOfBlock(member, loadType) && (modifier.IsSinglePointer() || modifier.IsPointerArray()) && member.m_type + && StructureComputations(member.m_type).GetDynamicMember(); + } + void LoadMember_Alloc(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, @@ -733,39 +1491,81 @@ namespace return; } - const MemberComputations computations(member); - if (computations.IsInTempBlock()) - { - LINEF("{0}* ptr = {1};", member->m_member->m_type_declaration->m_type->GetFullName(), MakeMemberAccess(info, member, modifier)) - } - const auto typeDecl = MakeTypeDecl(member->m_member->m_type_declaration.get()); const auto followingReferences = MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()); - // This used to use `alignof()` to calculate alignment but due to inconsistencies between compilers and bugs discovered in MSVC - // (Alignment specified via `__declspec(align())` showing as correct via intellisense but is incorrect when compiled for types that have a larger - // alignment than the specified value) this was changed to make ZoneCodeGenerator calculate what is supposed to be used as alignment when - // allocating. This is more reliable when being used with different compilers and the value used can be seen in the source code directly - if (member->m_alloc_alignment) + const auto allocOutOfBlock = ShouldAllocOutOfBlock(*member, loadType); + const auto preAllocDynamic = ShouldPreAllocDynamic(*member, modifier, loadType); + + if (preAllocDynamic) { - LINEF("{0} = m_stream->Alloc<{1}{2}>({3});", + LINE("// Alloc first for alignment, then proceed to read as game does") + if (member->m_alloc_alignment) + { + LINEF("m_stream.Alloc({0});", MakeEvaluation(member->m_alloc_alignment.get())) + } + else + { + LINEF("m_stream.Alloc({0});", modifier.GetAlignment()) + } + + LINEF("const auto allocSize = LoadDynamicFill_{0}(m_stream.LoadWithFill(0));", MakeSafeTypeName(member->m_type->m_definition)) + + // We do not align again, because we already did previously + LINEF("{0} = static_cast<{1}{2}*>(m_stream.AllocOutOfBlock(0, allocSize));", MakeMemberAccess(info, member, modifier), typeDecl, - followingReferences, - MakeEvaluation(member->m_alloc_alignment.get())) + followingReferences) } else { - LINEF("{0} = m_stream->Alloc<{1}{2}>({3});", MakeMemberAccess(info, member, modifier), typeDecl, followingReferences, modifier.GetAlignment()) + LINE_STARTF("{0} = m_stream.", MakeMemberAccess(info, member, modifier)) + if (allocOutOfBlock) + LINE_MIDDLE("AllocOutOfBlock") + else + LINE_MIDDLE("Alloc") + + LINE_MIDDLEF("<{0}{1}>(", typeDecl, followingReferences) + + // This used to use `alignof()` to calculate alignment but due to inconsistencies between compilers and bugs discovered in MSVC + // (Alignment specified via `__declspec(align())` showing as correct via intellisense but is incorrect when compiled for types that have a + // larger alignment than the specified value) this was changed to make ZoneCodeGenerator calculate what is supposed to be used as alignment when + // allocating. This is more reliable when being used with different compilers and the value used can be seen in the source code directly + if (member->m_alloc_alignment) + { + LINE_MIDDLE(MakeEvaluation(member->m_alloc_alignment.get())) + } + else + { + LINE_MIDDLEF("{0}", modifier.GetAlignment()) + } + + if (allocOutOfBlock && modifier.IsArrayPointer()) + LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) + else if (allocOutOfBlock && modifier.IsPointerArray()) + LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) + + LINE_END(");") } + const MemberComputations computations(member); if (computations.IsInTempBlock()) { LINE("") - LINEF("{0}** toInsert = nullptr;", member->m_member->m_type_declaration->m_type->GetFullName()) - LINE("if (ptr == PTR_INSERT)") + + if (m_env.m_architecture_mismatch) + LINE("uintptr_t toInsertLookupEntry = 0;") + else + LINEF("{0}** toInsert = nullptr;", member->m_member->m_type_declaration->m_type->GetFullName()) + + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("toInsert = m_stream->InsertPointer<{0}>();", member->m_member->m_type_declaration->m_type->GetFullName()) + + if (m_env.m_architecture_mismatch) + LINE("toInsertLookupEntry = m_stream.InsertPointerAliasLookup();") + else + LINEF("toInsert = m_stream.InsertPointerNative<{0}>();", member->m_member->m_type_declaration->m_type->GetFullName()) + m_intendation--; LINE("") } @@ -775,9 +1575,15 @@ namespace if (computations.IsInTempBlock()) { LINE("") - LINE("if (toInsert != nullptr)") + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("*toInsert = {0}->{1};", MakeTypeVarName(info->m_definition), member->m_member->m_name) + + if (m_env.m_architecture_mismatch) + LINEF( + "m_stream.SetInsertedPointerAliasLookup(toInsertLookupEntry, {0}->{1});", MakeTypeVarName(info->m_definition), member->m_member->m_name) + else + LINEF("*toInsert = {0}->{1};", MakeTypeVarName(info->m_definition), member->m_member->m_name) + m_intendation--; } } @@ -808,10 +1614,12 @@ namespace return; } + LINEF("const auto zonePtrType = GetZonePointerType({0});", MakeMemberAccess(info, member, modifier)) + const MemberComputations computations(member); if (computations.IsInTempBlock()) { - LINEF("if ({0} == PTR_FOLLOWING || {0} == PTR_INSERT)", MakeMemberAccess(info, member, modifier)) + LINE("if (zonePtrType == ZonePointerType::FOLLOWING || zonePtrType == ZonePointerType::INSERT)") LINE("{") m_intendation++; @@ -823,14 +1631,21 @@ namespace LINE("{") m_intendation++; - LINEF("{0} = m_stream->ConvertOffsetToAlias({0});", MakeMemberAccess(info, member, modifier)) + if (info->m_has_matching_cross_platform_structure) + { + LINEF("{0} = m_stream.ConvertOffsetToAliasNative({0});", MakeMemberAccess(info, member, modifier)) + } + else + { + LINEF("{0} = m_stream.ConvertOffsetToAliasLookup({0});", MakeMemberAccess(info, member, modifier)) + } m_intendation--; LINE("}") } else { - LINEF("if ({0} == PTR_FOLLOWING)", MakeMemberAccess(info, member, modifier)) + LINE("if (zonePtrType == ZonePointerType::FOLLOWING)") LINE("{") m_intendation++; @@ -842,7 +1657,28 @@ namespace LINE("{") m_intendation++; - LINEF("{0} = m_stream->ConvertOffsetToPointer({0});", MakeMemberAccess(info, member, modifier)) + if (ShouldAllocOutOfBlock(*member, loadType)) + { + LINE_STARTF("{0} = m_stream.ConvertOffsetToPointerLookup({0})", MakeMemberAccess(info, member, modifier)) + if (loadType == MemberLoadType::POINTER_ARRAY) + { + LINE_MIDDLEF(".OrNulled({0}uz * ({1}), sizeof({2}{3}) * ({1}), m_memory)", + member->m_member->m_type_declaration->GetSize(), + MakeEvaluation(modifier.GetPointerArrayCountEvaluation()), + MakeTypeDecl(member->m_member->m_type_declaration.get()), + MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers())) + } + else + { + LINE_MIDDLE(".Expect()") + } + + LINE_END(";") + } + else + { + LINEF("{0} = m_stream.ConvertOffsetToPointerNative({0});", MakeMemberAccess(info, member, modifier)) + } m_intendation--; LINE("}") @@ -896,14 +1732,14 @@ namespace const auto notInDefaultNormalBlock = computations.IsNotInDefaultNormalBlock(); if (notInDefaultNormalBlock) { - LINEF("m_stream->PushBlock({0});", member->m_fast_file_block->m_name) + LINEF("m_stream.PushBlock({0});", member->m_fast_file_block->m_name) } LoadMember_PointerCheck(info, member, modifier, loadType); if (notInDefaultNormalBlock) { - LINE("m_stream->PopBlock();") + LINE("m_stream.PopBlock();") } } @@ -986,7 +1822,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstMember()) + if (computations.IsFirstUsedMember()) { LINE("") if (member->m_condition) @@ -1005,7 +1841,7 @@ namespace LoadMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastMember()) + else if (computations.IsLastUsedMember()) { if (member->m_condition) { @@ -1070,36 +1906,58 @@ namespace { const StructureComputations computations(info); LINEF("void {0}::Load_{1}(const bool atStreamStart)", LoaderClassName(m_env.m_asset), info->m_definition->m_name) + LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypeVarName(info->m_definition)) const auto* dynamicMember = computations.GetDynamicMember(); - if (!(info->m_definition->GetType() == DataDefinitionType::UNION && dynamicMember)) + if (!info->m_has_matching_cross_platform_structure && dynamicMember && !info->m_non_embedded_reference_exists) + { + LINE("assert(!atStreamStart);") + } + else if (!(info->m_definition->GetType() == DataDefinitionType::UNION && dynamicMember)) { LINE("") LINE("if (atStreamStart)") - m_intendation++; - if (dynamicMember == nullptr) + m_intendation++; + if (info->m_has_matching_cross_platform_structure) { - LINEF("m_stream->Load<{0}>({1}); // Size: {2}", - info->m_definition->GetFullName(), - MakeTypeVarName(info->m_definition), - info->m_definition->GetSize()) + if (dynamicMember == nullptr) + { + LINEF("m_stream.Load<{0}>({1}); // Size: {2}", + info->m_definition->GetFullName(), + MakeTypeVarName(info->m_definition), + info->m_definition->GetSize()) + } + else + { + LINEF("m_stream.LoadPartial<{0}>({1}, offsetof({0}, {2}));", + info->m_definition->GetFullName(), + MakeTypeVarName(info->m_definition), + dynamicMember->m_member->m_name) + } } else { - LINEF("m_stream->LoadPartial<{0}>({1}, offsetof({0}, {2}));", - info->m_definition->GetFullName(), - MakeTypeVarName(info->m_definition), - dynamicMember->m_member->m_name) + if (dynamicMember == nullptr) + { + LINEF("FillStruct_{0}(m_stream.LoadWithFill({1}));", MakeSafeTypeName(info->m_definition), info->m_definition->GetSize()) + } + else if (info->m_non_embedded_reference_exists) + { + LINEF("FillStruct_{0}(m_stream.GetLastFill());", MakeSafeTypeName(info->m_definition)) + } + else + { + LINE("assert(false);") + } } - m_intendation--; } - else + else if (!m_env.m_architecture_mismatch) { LINE("assert(atStreamStart);") } @@ -1107,12 +1965,12 @@ namespace if (computations.IsAsset()) { LINE("") - LINEF("m_stream->PushBlock({0});", m_env.m_default_normal_block->m_name) + LINEF("m_stream.PushBlock({0});", m_env.m_default_normal_block->m_name) } else if (info->m_block) { LINE("") - LINEF("m_stream->PushBlock({0});", info->m_block->m_name) + LINEF("m_stream.PushBlock({0});", info->m_block->m_name) } for (const auto& member : info->m_ordered_members) @@ -1123,7 +1981,7 @@ namespace if (info->m_block || computations.IsAsset()) { LINE("") - LINE("m_stream->PopBlock();") + LINE("m_stream.PopBlock();") } m_intendation--; @@ -1140,15 +1998,22 @@ namespace LINEF("assert({0} != nullptr);", MakeTypePtrVarName(info->m_definition)) LINE("") - LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream->Load<{0}*>({1});", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) - m_intendation--; + if (!m_env.m_architecture_mismatch) + { + LINE("if (atStreamStart)") + m_intendation++; + LINEF("m_stream.Load<{0}*>({1});", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) + m_intendation--; + } + else + { + LINE("assert(!atStreamStart);") + } LINE("") if (inTemp) { - LINEF("m_stream->PushBlock({0});", m_env.m_default_temp_block->m_name) + LINEF("m_stream.PushBlock({0});", m_env.m_default_temp_block->m_name) LINE("") } @@ -1156,33 +2021,41 @@ namespace LINE("{") m_intendation++; + LINEF("const auto zonePtrType = GetZonePointerType(*{0});", MakeTypePtrVarName(info->m_definition)) if (inTemp) { - LINEF("if (*{0} == PTR_FOLLOWING || *{0} == PTR_INSERT)", MakeTypePtrVarName(info->m_definition)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING || zonePtrType == ZonePointerType::INSERT)", MakeTypePtrVarName(info->m_definition)) } else { - LINEF("if (*{0} == PTR_FOLLOWING)", MakeTypePtrVarName(info->m_definition)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING)", MakeTypePtrVarName(info->m_definition)) } LINE("{") m_intendation++; - if (inTemp) - { - LINEF("{0}* ptr = *{1};", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) - } - LINEF("*{0} = m_stream->Alloc<{1}>({2});", + LINEF("*{0} = m_stream.{1}<{2}>({3});", MakeTypePtrVarName(info->m_definition), + m_env.m_architecture_mismatch ? "AllocOutOfBlock" : "Alloc", info->m_definition->GetFullName(), info->m_definition->GetAlignment()) if (inTemp) { LINE("") - LINEF("{0}** toInsert = nullptr;", info->m_definition->GetFullName()) - LINE("if (ptr == PTR_INSERT)") + + if (m_env.m_architecture_mismatch) + LINE("uintptr_t toInsertLookupEntry = 0;") + else + LINEF("{0}** toInsert = nullptr;", info->m_definition->GetFullName()) + + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("toInsert = m_stream->InsertPointer<{0}>();", info->m_definition->GetFullName()) + + if (m_env.m_architecture_mismatch) + LINE("toInsertLookupEntry = m_stream.InsertPointerAliasLookup();") + else + LINEF("toInsert = m_stream.InsertPointerNative<{0}>();", info->m_definition->GetFullName()) + m_intendation--; } @@ -1222,9 +2095,14 @@ namespace LINE("") } - LINE("if (toInsert != nullptr)") + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("*toInsert = *{0};", MakeTypePtrVarName(info->m_definition)) + + if (m_env.m_architecture_mismatch) + LINEF("m_stream.SetInsertedPointerAliasLookup(toInsertLookupEntry, *{0});", MakeTypePtrVarName(info->m_definition)) + else + LINEF("*toInsert = *{0};", MakeTypePtrVarName(info->m_definition)) + m_intendation--; } @@ -1236,11 +2114,18 @@ namespace if (inTemp) { - LINEF("*{0} = m_stream->ConvertOffsetToAlias(*{0});", MakeTypePtrVarName(info->m_definition)) + if (info->m_has_matching_cross_platform_structure) + { + LINEF("*{0} = m_stream.ConvertOffsetToAliasNative(*{0});", MakeTypePtrVarName(info->m_definition)) + } + else + { + LINEF("*{0} = m_stream.ConvertOffsetToAliasLookup(*{0});", MakeTypePtrVarName(info->m_definition)) + } } else { - LINEF("*{0} = m_stream->ConvertOffsetToPointer(*{0});", MakeTypePtrVarName(info->m_definition)) + LINEF("*{0} = m_stream.ConvertOffsetToPointerNative(*{0});", MakeTypePtrVarName(info->m_definition)) } m_intendation--; @@ -1252,7 +2137,7 @@ namespace if (inTemp) { LINE("") - LINE("m_stream->PopBlock();") + LINE("m_stream.PopBlock();") } m_intendation--; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp index f3426a67..f5add84c 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp @@ -655,7 +655,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstMember()) + if (computations.IsFirstUsedMember()) { LINE("") if (member->m_condition) @@ -674,7 +674,7 @@ namespace MarkMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastMember()) + else if (computations.IsLastUsedMember()) { if (member->m_condition) { diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp index 44c5a98c..dc27cb35 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp @@ -874,7 +874,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstMember()) + if (computations.IsFirstUsedMember()) { LINE("") if (member->m_condition) @@ -893,7 +893,7 @@ namespace WriteMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastMember()) + else if (computations.IsLastUsedMember()) { if (member->m_condition) { diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp index 18527df9..449ead72 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp @@ -7,6 +7,7 @@ #include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/ParserFilesystemStream.h" #include "Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h" +#include "Parsing/PostProcessing/CrossPlatformStructurePostProcessor.h" #include "Parsing/PostProcessing/LeafsPostProcessor.h" #include "Parsing/PostProcessing/MarkingRequiredPostProcessor.h" #include "Parsing/PostProcessing/MemberLeafsPostProcessor.h" @@ -19,8 +20,8 @@ namespace { - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_NAME = "__zonecodegenerator"; - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_VALUE = "1"; + constexpr const char* ZONE_CODE_GENERATOR_DEFINE_NAME = "__zonecodegenerator"; + constexpr const char* ZONE_CODE_GENERATOR_DEFINE_VALUE = "1"; } // namespace CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) @@ -62,6 +63,7 @@ void CommandsFileReader::SetupStreamProxies() void CommandsFileReader::SetupPostProcessors() { // Order is important + m_post_processors.emplace_back(std::make_unique()); m_post_processors.emplace_back(std::make_unique()); m_post_processors.emplace_back(std::make_unique()); m_post_processors.emplace_back(std::make_unique()); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp index 605c9226..64ba8d46 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp @@ -9,7 +9,6 @@ #include "Parsing/Impl/ParserFilesystemStream.h" #include "Parsing/PostProcessing/CreateMemberInformationPostProcessor.h" #include "Parsing/PostProcessing/CreateStructureInformationPostProcessor.h" -#include "Parsing/PostProcessing/CrossPlatformStructurePostProcessor.h" #include "Parsing/PostProcessing/IPostProcessor.h" #include @@ -19,8 +18,8 @@ namespace { - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_NAME = "__zonecodegenerator"; - static constexpr const char* ZONE_CODE_GENERATOR_DEFINE_VALUE = "1"; + constexpr const char* ZONE_CODE_GENERATOR_DEFINE_NAME = "__zonecodegenerator"; + constexpr const char* ZONE_CODE_GENERATOR_DEFINE_VALUE = "1"; } // namespace HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) @@ -68,7 +67,6 @@ void HeaderFileReader::SetupPostProcessors() // Order is important m_post_processors.emplace_back(std::make_unique()); m_post_processors.emplace_back(std::make_unique()); - m_post_processors.emplace_back(std::make_unique()); } bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp index a79b262d..e6b9fdc3 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp @@ -12,22 +12,6 @@ namespace bool CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition); bool CalculateFields(IDataRepository* repository, TypeDeclaration* declaration); - unsigned GetPointerSizeForArchitecture(const Architecture architecture) - { - switch (architecture) - { - case Architecture::X86: - return sizeof(uint32_t); - - case Architecture::X64: - return sizeof(uint64_t); - - default: - assert(false); - return sizeof(uint32_t); - } - } - bool CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration) { auto hasPointerModifier = false; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp index a8dee352..2665a831 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp @@ -35,6 +35,9 @@ namespace if (computations.ShouldIgnore()) continue; + if (computations.IsArray() || member->m_member->m_type_declaration->m_declaration_modifiers.empty()) + member->m_type->m_embedded_reference_exists = true; + if (computations.ContainsNonEmbeddedReference()) member->m_type->m_non_embedded_reference_exists = true; diff --git a/src/ZoneCommon/Game/IW3/ZoneConstantsIW3.h b/src/ZoneCommon/Game/IW3/ZoneConstantsIW3.h index 45896c5e..e7efa17b 100644 --- a/src/ZoneCommon/Game/IW3/ZoneConstantsIW3.h +++ b/src/ZoneCommon/Game/IW3/ZoneConstantsIW3.h @@ -20,7 +20,7 @@ namespace IW3 static constexpr size_t AUTHED_CHUNK_SIZE = 0x2000; static constexpr unsigned AUTHED_CHUNK_COUNT_PER_GROUP = 256; - static constexpr int OFFSET_BLOCK_BIT_COUNT = 4; + static constexpr unsigned OFFSET_BLOCK_BIT_COUNT = 4u; static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL; }; } // namespace IW3 diff --git a/src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h b/src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h index 42a334cd..d405e4cf 100644 --- a/src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h +++ b/src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h @@ -43,7 +43,7 @@ namespace IW4 static constexpr size_t AUTHED_CHUNK_SIZE = 0x2000; static constexpr unsigned AUTHED_CHUNK_COUNT_PER_GROUP = 256; - static constexpr int OFFSET_BLOCK_BIT_COUNT = 4; + static constexpr unsigned OFFSET_BLOCK_BIT_COUNT = 4u; static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL; }; } // namespace IW4 diff --git a/src/ZoneCommon/Game/IW5/ZoneConstantsIW5.h b/src/ZoneCommon/Game/IW5/ZoneConstantsIW5.h index 27f6b9f5..0e56f83d 100644 --- a/src/ZoneCommon/Game/IW5/ZoneConstantsIW5.h +++ b/src/ZoneCommon/Game/IW5/ZoneConstantsIW5.h @@ -40,7 +40,7 @@ namespace IW5 static constexpr size_t AUTHED_CHUNK_SIZE = 0x2000; static constexpr unsigned AUTHED_CHUNK_COUNT_PER_GROUP = 256; - static constexpr int OFFSET_BLOCK_BIT_COUNT = 4; + static constexpr unsigned OFFSET_BLOCK_BIT_COUNT = 4u; static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL; }; } // namespace IW5 diff --git a/src/ZoneCommon/Game/T5/ZoneConstantsT5.h b/src/ZoneCommon/Game/T5/ZoneConstantsT5.h index 5b79dc2a..b36559ea 100644 --- a/src/ZoneCommon/Game/T5/ZoneConstantsT5.h +++ b/src/ZoneCommon/Game/T5/ZoneConstantsT5.h @@ -20,7 +20,7 @@ namespace T5 static constexpr size_t AUTHED_CHUNK_SIZE = 0x2000; static constexpr unsigned AUTHED_CHUNK_COUNT_PER_GROUP = 256; - static constexpr int OFFSET_BLOCK_BIT_COUNT = 3; + static constexpr unsigned OFFSET_BLOCK_BIT_COUNT = 3u; static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL; }; } // namespace T5 diff --git a/src/ZoneCommon/Game/T6/ZoneConstantsT6.h b/src/ZoneCommon/Game/T6/ZoneConstantsT6.h index d68535ca..10213294 100644 --- a/src/ZoneCommon/Game/T6/ZoneConstantsT6.h +++ b/src/ZoneCommon/Game/T6/ZoneConstantsT6.h @@ -27,7 +27,7 @@ namespace T6 static constexpr int XCHUNK_SIZE = 0x8000; static constexpr int XCHUNK_MAX_WRITE_SIZE = XCHUNK_SIZE - 0x40; static constexpr int VANILLA_BUFFER_SIZE = 0x80000; - static constexpr int OFFSET_BLOCK_BIT_COUNT = 3; + static constexpr unsigned OFFSET_BLOCK_BIT_COUNT = 3u; static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL; static constexpr size_t FILE_SUFFIX_ZERO_MIN_SIZE = 0x40; diff --git a/src/ZoneCommon/Zone/XBlock.cpp b/src/ZoneCommon/Zone/XBlock.cpp index f5825865..239ab536 100644 --- a/src/ZoneCommon/Zone/XBlock.cpp +++ b/src/ZoneCommon/Zone/XBlock.cpp @@ -1,34 +1,23 @@ #include "XBlock.h" -#include - -XBlock::XBlock(const std::string& name, const int index, const Type type) +XBlock::XBlock(std::string name, const unsigned index, const XBlockType type) + : m_name(std::move(name)), + m_index(index), + m_type(type), + m_buffer_size(0u) { - m_name = name; - m_index = index; - m_type = type; - m_buffer = nullptr; - m_buffer_size = 0; -} - -XBlock::~XBlock() -{ - delete[] m_buffer; - m_buffer = nullptr; } void XBlock::Alloc(const size_t blockSize) { - delete[] m_buffer; - if (blockSize > 0) { - m_buffer = new uint8_t[blockSize]; + m_buffer = std::make_unique(blockSize); m_buffer_size = blockSize; } else { - m_buffer = nullptr; + m_buffer.reset(); m_buffer_size = 0; } } diff --git a/src/ZoneCommon/Zone/XBlock.h b/src/ZoneCommon/Zone/XBlock.h index 8128864a..a1cb17c4 100644 --- a/src/ZoneCommon/Zone/XBlock.h +++ b/src/ZoneCommon/Zone/XBlock.h @@ -1,27 +1,29 @@ #pragma once + +#include #include +#include #include +enum class XBlockType : std::uint8_t +{ + BLOCK_TYPE_TEMP, + BLOCK_TYPE_RUNTIME, + BLOCK_TYPE_DELAY, + BLOCK_TYPE_NORMAL +}; + class XBlock { public: - enum class Type - { - BLOCK_TYPE_TEMP, - BLOCK_TYPE_RUNTIME, - BLOCK_TYPE_DELAY, - BLOCK_TYPE_NORMAL - }; + XBlock(std::string name, unsigned index, XBlockType type); + + void Alloc(size_t blockSize); std::string m_name; unsigned m_index; - Type m_type; + XBlockType m_type; - uint8_t* m_buffer; + std::unique_ptr m_buffer; size_t m_buffer_size; - - XBlock(const std::string& name, int index, Type type); - ~XBlock(); - - void Alloc(size_t blockSize); }; diff --git a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp index ed3e3909..02f9c444 100644 --- a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp +++ b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp @@ -32,8 +32,8 @@ using namespace IW3; -ContentLoader::ContentLoader(Zone& zone) - : ContentLoaderBase(zone), +ContentLoader::ContentLoader(Zone& zone, ZoneInputStream& stream) + : ContentLoaderBase(zone, stream), varXAsset(nullptr), varScriptStringList(nullptr) { @@ -41,16 +41,16 @@ ContentLoader::ContentLoader(Zone& zone) void ContentLoader::LoadScriptStringList(const bool atStreamStart) { - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - m_stream->Load(varScriptStringList); + m_stream.Load(varScriptStringList); if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); + varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -58,7 +58,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) m_zone.m_script_strings.InitializeForExistingZone(varScriptStringList->strings, static_cast(varScriptStringList->count)); } - m_stream->PopBlock(); + m_stream.PopBlock(); assert(m_zone.m_script_strings.Count() <= SCR_STRING_MAX + 1); } @@ -68,7 +68,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const #define LOAD_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ - Loader_##typeName loader(m_zone, *m_stream); \ + Loader_##typeName loader(m_zone, m_stream); \ loader.Load(&varXAsset->header.headerEntry); \ break; \ } @@ -79,7 +79,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset); + m_stream.Load(varXAsset); switch (varXAsset->type) { @@ -125,7 +125,7 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset, count); + m_stream.Load(varXAsset, count); for (size_t index = 0; index < count; index++) { @@ -134,26 +134,24 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count } } -void ContentLoader::Load(ZoneInputStream& stream) +void ContentLoader::Load() { - m_stream = &stream; - - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); XAssetList assetList{}; - m_stream->LoadDataRaw(&assetList, sizeof(assetList)); + m_stream.LoadDataRaw(&assetList, sizeof(assetList)); varScriptStringList = &assetList.stringList; LoadScriptStringList(false); if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream->Alloc(alignof(XAsset)); + assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } - m_stream->PopBlock(); + m_stream.PopBlock(); } diff --git a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.h b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.h index fb44f42d..32533a9d 100644 --- a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.h +++ b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.h @@ -9,9 +9,8 @@ namespace IW3 class ContentLoader final : public ContentLoaderBase, public IContentLoadingEntryPoint { public: - explicit ContentLoader(Zone& zone); - - void Load(ZoneInputStream& stream) override; + ContentLoader(Zone& zone, ZoneInputStream& stream); + void Load() override; private: void LoadScriptStringList(bool atStreamStart); diff --git a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp index 5de47662..553fe88c 100644 --- a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp +++ b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp @@ -44,15 +44,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -85,8 +85,15 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks()); // Start of the zone content - zoneLoader->AddLoadingStep( - step::CreateStepLoadZoneContent(std::make_unique(*zonePtr), ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK)); + zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( + [&zonePtr](ZoneInputStream& stream) + { + return std::make_unique(*zonePtr, stream); + }, + 32u, + ZoneConstants::OFFSET_BLOCK_BIT_COUNT, + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp index a15b7229..50650731 100644 --- a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp @@ -42,8 +42,9 @@ using namespace IW4; -ContentLoader::ContentLoader(Zone& zone) - : ContentLoaderBase(zone), +ContentLoader::ContentLoader(Zone& zone, ZoneInputStream& stream) + : ContentLoaderBase(zone, stream), + varXAssetList(nullptr), varXAsset(nullptr), varScriptStringList(nullptr) { @@ -51,16 +52,17 @@ ContentLoader::ContentLoader(Zone& zone) void ContentLoader::LoadScriptStringList(const bool atStreamStart) { - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); - - if (atStreamStart) - m_stream->Load(varScriptStringList); + assert(!atStreamStart); if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); +#ifdef ARCH_x86 + varScriptStringList->strings = m_stream.Alloc(4); +#else + varScriptStringList->strings = m_stream.AllocOutOfBlock(4, varScriptStringList->count); +#endif varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -68,8 +70,6 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) m_zone.m_script_strings.InitializeForExistingZone(varScriptStringList->strings, static_cast(varScriptStringList->count)); } - m_stream->PopBlock(); - assert(m_zone.m_script_strings.Count() <= SCR_STRING_MAX + 1); } @@ -78,7 +78,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const #define LOAD_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ - Loader_##typeName loader(m_zone, *m_stream); \ + Loader_##typeName loader(m_zone, m_stream); \ loader.Load(&varXAsset->header.headerEntry); \ break; \ } @@ -89,7 +89,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset); + m_stream.Load(varXAsset); switch (varXAsset->type) { @@ -145,35 +145,66 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset, count); + { +#ifdef ARCH_x86 + m_stream.Load(varXAsset, count); +#else + const auto fill = m_stream.LoadWithFill(8u * count); + + for (size_t index = 0; index < count; index++) + { + fill.Fill(varXAsset[index].type, 8u * index); + fill.FillPtr(varXAsset[index].header.data, 8u * index + 4u); + m_stream.AddPointerLookup(&varXAsset[index].header.data, fill.BlockBuffer(8u * index + 4u)); + } +#endif + } for (size_t index = 0; index < count; index++) { LoadXAsset(false); varXAsset++; + +#ifdef DEBUG_OFFSETS + m_stream.DebugOffsets(index); +#endif } } -void ContentLoader::Load(ZoneInputStream& stream) +void ContentLoader::Load() { - m_stream = &stream; - - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); - XAssetList assetList{}; - m_stream->LoadDataRaw(&assetList, sizeof(assetList)); + varXAssetList = &assetList; + +#ifdef ARCH_x86 + m_stream.LoadDataRaw(&assetList, sizeof(assetList)); +#else + const auto fillAccessor = m_stream.LoadWithFill(16u); + varScriptStringList = &varXAssetList->stringList; + fillAccessor.Fill(varScriptStringList->count, 0u); + fillAccessor.FillPtr(varScriptStringList->strings, 4u); + + fillAccessor.Fill(varXAssetList->assetCount, 8u); + fillAccessor.FillPtr(varXAssetList->assets, 12u); +#endif + + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); varScriptStringList = &assetList.stringList; LoadScriptStringList(false); if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream->Alloc(alignof(XAsset)); +#ifdef ARCH_x86 + assetList.assets = m_stream.Alloc(4); +#else + assetList.assets = m_stream.AllocOutOfBlock(4, assetList.assetCount); +#endif varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } - m_stream->PopBlock(); + m_stream.PopBlock(); } diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h index a3c30973..1c110cd8 100644 --- a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.h @@ -9,9 +9,8 @@ namespace IW4 class ContentLoader final : public ContentLoaderBase, public IContentLoadingEntryPoint { public: - explicit ContentLoader(Zone& zone); - - void Load(ZoneInputStream& stream) override; + explicit ContentLoader(Zone& zone, ZoneInputStream& stream); + void Load() override; private: void LoadScriptStringList(bool atStreamStart); @@ -19,6 +18,7 @@ namespace IW4 void LoadXAsset(bool atStreamStart) const; void LoadXAssetArray(bool atStreamStart, size_t count); + XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; }; diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp index 4cc808e0..514e290b 100644 --- a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -80,14 +80,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -207,8 +207,15 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks()); // Start of the zone content - zoneLoader->AddLoadingStep( - step::CreateStepLoadZoneContent(std::make_unique(*zonePtr), ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK)); + zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( + [zonePtr](ZoneInputStream& stream) + { + return std::make_unique(*zonePtr, stream); + }, + 32u, + ZoneConstants::OFFSET_BLOCK_BIT_COUNT, + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp index 2558ab88..c524d3b1 100644 --- a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp @@ -47,8 +47,8 @@ using namespace IW5; -ContentLoader::ContentLoader(Zone& zone) - : ContentLoaderBase(zone), +ContentLoader::ContentLoader(Zone& zone, ZoneInputStream& stream) + : ContentLoaderBase(zone, stream), varXAsset(nullptr), varScriptStringList(nullptr) { @@ -56,16 +56,16 @@ ContentLoader::ContentLoader(Zone& zone) void ContentLoader::LoadScriptStringList(const bool atStreamStart) { - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - m_stream->Load(varScriptStringList); + m_stream.Load(varScriptStringList); if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); + varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -73,7 +73,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) m_zone.m_script_strings.InitializeForExistingZone(varScriptStringList->strings, static_cast(varScriptStringList->count)); } - m_stream->PopBlock(); + m_stream.PopBlock(); assert(m_zone.m_script_strings.Count() <= SCR_STRING_MAX + 1); } @@ -83,7 +83,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const #define LOAD_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ - Loader_##typeName loader(m_zone, *m_stream); \ + Loader_##typeName loader(m_zone, m_stream); \ loader.Load(&varXAsset->header.headerEntry); \ break; \ } @@ -94,7 +94,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset); + m_stream.Load(varXAsset); switch (varXAsset->type) { @@ -154,7 +154,7 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(count == 0 || varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset, count); + m_stream.Load(varXAsset, count); for (size_t index = 0; index < count; index++) { @@ -163,26 +163,24 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count } } -void ContentLoader::Load(ZoneInputStream& stream) +void ContentLoader::Load() { - m_stream = &stream; - - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); XAssetList assetList{}; - m_stream->LoadDataRaw(&assetList, sizeof(assetList)); + m_stream.LoadDataRaw(&assetList, sizeof(assetList)); varScriptStringList = &assetList.stringList; LoadScriptStringList(false); if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream->Alloc(alignof(XAsset)); + assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } - m_stream->PopBlock(); + m_stream.PopBlock(); } diff --git a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.h b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.h index b06631a2..e618f44f 100644 --- a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.h +++ b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.h @@ -9,9 +9,8 @@ namespace IW5 class ContentLoader final : public ContentLoaderBase, public IContentLoadingEntryPoint { public: - explicit ContentLoader(Zone& zone); - - void Load(ZoneInputStream& stream) override; + explicit ContentLoader(Zone& zone, ZoneInputStream& stream); + void Load() override; private: void LoadScriptStringList(bool atStreamStart); diff --git a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp index 4e77a1ca..162fc445 100644 --- a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp @@ -63,15 +63,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -184,8 +184,15 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks()); // Start of the zone content - zoneLoader->AddLoadingStep( - step::CreateStepLoadZoneContent(std::make_unique(*zonePtr), ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK)); + zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( + [&zonePtr](ZoneInputStream& stream) + { + return std::make_unique(*zonePtr, stream); + }, + 32u, + ZoneConstants::OFFSET_BLOCK_BIT_COUNT, + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp b/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp index 2fe47338..9536f02a 100644 --- a/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp +++ b/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp @@ -39,8 +39,8 @@ using namespace T5; -ContentLoader::ContentLoader(Zone& zone) - : ContentLoaderBase(zone), +ContentLoader::ContentLoader(Zone& zone, ZoneInputStream& stream) + : ContentLoaderBase(zone, stream), varXAsset(nullptr), varScriptStringList(nullptr) { @@ -48,16 +48,16 @@ ContentLoader::ContentLoader(Zone& zone) void ContentLoader::LoadScriptStringList(const bool atStreamStart) { - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - m_stream->Load(varScriptStringList); + m_stream.Load(varScriptStringList); if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); + varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -65,7 +65,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) m_zone.m_script_strings.InitializeForExistingZone(varScriptStringList->strings, static_cast(varScriptStringList->count)); } - m_stream->PopBlock(); + m_stream.PopBlock(); assert(m_zone.m_script_strings.Count() <= SCR_STRING_MAX + 1); } @@ -75,7 +75,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const #define LOAD_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ - Loader_##typeName loader(m_zone, *m_stream); \ + Loader_##typeName loader(m_zone, m_stream); \ loader.Load(&varXAsset->header.headerEntry); \ break; \ } @@ -86,7 +86,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset); + m_stream.Load(varXAsset); switch (varXAsset->type) { @@ -138,7 +138,7 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset, count); + m_stream.Load(varXAsset, count); for (size_t index = 0; index < count; index++) { @@ -147,26 +147,24 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count } } -void ContentLoader::Load(ZoneInputStream& stream) +void ContentLoader::Load() { - m_stream = &stream; - - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); XAssetList assetList{}; - m_stream->LoadDataRaw(&assetList, sizeof(assetList)); + m_stream.LoadDataRaw(&assetList, sizeof(assetList)); varScriptStringList = &assetList.stringList; LoadScriptStringList(false); if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream->Alloc(alignof(XAsset)); + assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } - m_stream->PopBlock(); + m_stream.PopBlock(); } diff --git a/src/ZoneLoading/Game/T5/ContentLoaderT5.h b/src/ZoneLoading/Game/T5/ContentLoaderT5.h index 3fd035f4..1881cc57 100644 --- a/src/ZoneLoading/Game/T5/ContentLoaderT5.h +++ b/src/ZoneLoading/Game/T5/ContentLoaderT5.h @@ -9,9 +9,8 @@ namespace T5 class ContentLoader final : public ContentLoaderBase, public IContentLoadingEntryPoint { public: - explicit ContentLoader(Zone& zone); - - void Load(ZoneInputStream& stream) override; + explicit ContentLoader(Zone& zone, ZoneInputStream& stream); + void Load() override; private: void LoadScriptStringList(bool atStreamStart); diff --git a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp index e04c9ead..23331452 100644 --- a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp +++ b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp @@ -46,13 +46,13 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -85,8 +85,15 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks()); // Start of the zone content - zoneLoader->AddLoadingStep( - step::CreateStepLoadZoneContent(std::make_unique(*zonePtr), ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK)); + zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( + [&zonePtr](ZoneInputStream& stream) + { + return std::make_unique(*zonePtr, stream); + }, + 32u, + ZoneConstants::OFFSET_BLOCK_BIT_COUNT, + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp index 287da637..b551cd91 100644 --- a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp +++ b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp @@ -55,8 +55,8 @@ using namespace T6; -ContentLoader::ContentLoader(Zone& zone) - : ContentLoaderBase(zone), +ContentLoader::ContentLoader(Zone& zone, ZoneInputStream& stream) + : ContentLoaderBase(zone, stream), varXAsset(nullptr), varScriptStringList(nullptr) { @@ -64,16 +64,16 @@ ContentLoader::ContentLoader(Zone& zone) void ContentLoader::LoadScriptStringList(const bool atStreamStart) { - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - m_stream->Load(varScriptStringList); + m_stream.Load(varScriptStringList); if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream->Alloc(alignof(const char*)); + varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -81,7 +81,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) m_zone.m_script_strings.InitializeForExistingZone(varScriptStringList->strings, static_cast(varScriptStringList->count)); } - m_stream->PopBlock(); + m_stream.PopBlock(); assert(m_zone.m_script_strings.Count() <= SCR_STRING_MAX + 1); } @@ -91,7 +91,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const #define LOAD_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ - Loader_##typeName loader(m_zone, *m_stream); \ + Loader_##typeName loader(m_zone, m_stream); \ loader.Load(&varXAsset->header.headerEntry); \ break; \ } @@ -99,7 +99,7 @@ void ContentLoader::LoadXAsset(const bool atStreamStart) const assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset); + m_stream.Load(varXAsset); switch (varXAsset->type) { @@ -167,7 +167,7 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(varXAsset != nullptr); if (atStreamStart) - m_stream->Load(varXAsset, count); + m_stream.Load(varXAsset, count); for (size_t index = 0; index < count; index++) { @@ -176,35 +176,33 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count } } -void ContentLoader::Load(ZoneInputStream& stream) +void ContentLoader::Load() { - m_stream = &stream; - - m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); + m_stream.PushBlock(XFILE_BLOCK_VIRTUAL); XAssetList assetList{}; - m_stream->LoadDataRaw(&assetList, sizeof(assetList)); + m_stream.LoadDataRaw(&assetList, sizeof(assetList)); varScriptStringList = &assetList.stringList; LoadScriptStringList(false); if (assetList.depends != nullptr) { - assert(assetList.depends == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.depends) == ZonePointerType::FOLLOWING); - assetList.depends = m_stream->Alloc(alignof(const char*)); + assetList.depends = m_stream.Alloc(alignof(const char*)); varXString = assetList.depends; LoadXStringArray(true, assetList.dependCount); } if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream->Alloc(alignof(XAsset)); + assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } - m_stream->PopBlock(); + m_stream.PopBlock(); } diff --git a/src/ZoneLoading/Game/T6/ContentLoaderT6.h b/src/ZoneLoading/Game/T6/ContentLoaderT6.h index 1ef06b3a..acde76f7 100644 --- a/src/ZoneLoading/Game/T6/ContentLoaderT6.h +++ b/src/ZoneLoading/Game/T6/ContentLoaderT6.h @@ -9,9 +9,8 @@ namespace T6 class ContentLoader final : public ContentLoaderBase, public IContentLoadingEntryPoint { public: - explicit ContentLoader(Zone& zone); - - void Load(ZoneInputStream& stream) override; + explicit ContentLoader(Zone& zone, ZoneInputStream& stream); + void Load() override; private: void LoadScriptStringList(bool atStreamStart); diff --git a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp index e2bb2d24..cdc06d5d 100644 --- a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp @@ -93,14 +93,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlockType::BLOCK_TYPE_DELAY)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlockType::BLOCK_TYPE_DELAY)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -203,8 +203,15 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& zoneLoader->AddLoadingStep(step::CreateStepAllocXBlocks()); // Start of the zone content - zoneLoader->AddLoadingStep( - step::CreateStepLoadZoneContent(std::make_unique(*zonePtr), ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK)); + zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( + [&zonePtr](ZoneInputStream& stream) + { + return std::make_unique(*zonePtr, stream); + }, + 32u, + ZoneConstants::OFFSET_BLOCK_BIT_COUNT, + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); if (isSecure) { diff --git a/src/ZoneLoading/Loading/ContentLoaderBase.cpp b/src/ZoneLoading/Loading/ContentLoaderBase.cpp index 1b4420f6..31055ea4 100644 --- a/src/ZoneLoading/Loading/ContentLoaderBase.cpp +++ b/src/ZoneLoading/Loading/ContentLoaderBase.cpp @@ -1,23 +1,22 @@ #include "ContentLoaderBase.h" #include - -const void* ContentLoaderBase::PTR_FOLLOWING = reinterpret_cast(-1); -const void* ContentLoaderBase::PTR_INSERT = reinterpret_cast(-2); - -ContentLoaderBase::ContentLoaderBase(Zone& zone) - : varXString(nullptr), - m_zone(zone), - m_memory(zone.Memory()), - m_stream(nullptr) -{ -} +#include +#include ContentLoaderBase::ContentLoaderBase(Zone& zone, ZoneInputStream& stream) : varXString(nullptr), m_zone(zone), m_memory(zone.Memory()), - m_stream(&stream) + m_stream(stream), + + // -1 + m_zone_ptr_following( + reinterpret_cast(std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount()))), + + // -2 + m_zone_ptr_insert( + reinterpret_cast((std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount())) - 1u)) { } @@ -26,18 +25,18 @@ void ContentLoaderBase::LoadXString(const bool atStreamStart) const assert(varXString != nullptr); if (atStreamStart) - m_stream->Load(varXString); + m_stream.Load(varXString); if (*varXString != nullptr) { - if (*varXString == PTR_FOLLOWING) + if (GetZonePointerType(*varXString) == ZonePointerType::FOLLOWING) { - *varXString = m_stream->Alloc(alignof(const char)); - m_stream->LoadNullTerminated(const_cast(*varXString)); + *varXString = m_stream.Alloc(1); + m_stream.LoadNullTerminated(const_cast(*varXString)); } else { - *varXString = m_stream->ConvertOffsetToPointer(*varXString); + *varXString = m_stream.ConvertOffsetToPointerNative(*varXString); } } } @@ -46,8 +45,21 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t { assert(varXString != nullptr); +#ifdef ARCH_x86 if (atStreamStart) - m_stream->Load(varXString, count); + m_stream.Load(varXString, count); +#else + if (atStreamStart) + { + const auto fill = m_stream.LoadWithFill(4u * count); + + for (size_t index = 0; index < count; index++) + { + fill.FillPtr(varXString[index], 4u * index); + m_stream.AddPointerLookup(&varXString[index], fill.BlockBuffer(4u * index)); + } + } +#endif for (size_t index = 0; index < count; index++) { @@ -55,3 +67,13 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t varXString++; } } + +ZonePointerType ContentLoaderBase::GetZonePointerType(const void* zonePtr) const +{ + if (zonePtr == m_zone_ptr_following) + return ZonePointerType::FOLLOWING; + if (zonePtr == m_zone_ptr_insert) + return ZonePointerType::INSERT; + + return ZonePointerType::OFFSET; +} diff --git a/src/ZoneLoading/Loading/ContentLoaderBase.h b/src/ZoneLoading/Loading/ContentLoaderBase.h index 51fe7cc8..8093476d 100644 --- a/src/ZoneLoading/Loading/ContentLoaderBase.h +++ b/src/ZoneLoading/Loading/ContentLoaderBase.h @@ -3,12 +3,17 @@ #include "Zone/Stream/ZoneInputStream.h" #include "Zone/Zone.h" +#include + +enum class ZonePointerType : std::uint8_t +{ + FOLLOWING, + INSERT, + OFFSET +}; + class ContentLoaderBase { -protected: - static const void* PTR_FOLLOWING; - static const void* PTR_INSERT; - public: virtual ~ContentLoaderBase() = default; ContentLoaderBase(const ContentLoaderBase& other) = default; @@ -17,15 +22,25 @@ public: ContentLoaderBase& operator=(ContentLoaderBase&& other) noexcept = delete; protected: - explicit ContentLoaderBase(Zone& zone); ContentLoaderBase(Zone& zone, ZoneInputStream& stream); void LoadXString(bool atStreamStart) const; void LoadXStringArray(bool atStreamStart, size_t count); + [[nodiscard]] ZonePointerType GetZonePointerType(const void* zonePtr) const; + + template [[nodiscard]] ZonePointerType GetZonePointerType(T* zonePtr) const + { + return GetZonePointerType(reinterpret_cast(zonePtr)); + } + const char** varXString; Zone& m_zone; MemoryManager& m_memory; - ZoneInputStream* m_stream; + ZoneInputStream& m_stream; + +private: + const void* m_zone_ptr_following; + const void* m_zone_ptr_insert; }; diff --git a/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.cpp b/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.cpp new file mode 100644 index 00000000..66c6d92c --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.cpp @@ -0,0 +1,19 @@ +#include "InvalidLookupPositionException.h" + +#include + +InvalidLookupPositionException::InvalidLookupPositionException(block_t block, size_t offset) + : m_block(block), + m_offset(offset) +{ +} + +std::string InvalidLookupPositionException::DetailedMessage() +{ + return std::format("Zone tried to lookup at block {}, offset {} that was not recorded", m_block, m_offset); +} + +char const* InvalidLookupPositionException::what() const noexcept +{ + return "Zone tried to lookup at zone offset that is not recorded"; +} diff --git a/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.h b/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.h new file mode 100644 index 00000000..46447482 --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidLookupPositionException.h @@ -0,0 +1,19 @@ +#pragma once + +#include "LoadingException.h" +#include "Zone/ZoneTypes.h" + +#include + +class InvalidLookupPositionException final : public LoadingException +{ +public: + InvalidLookupPositionException(block_t block, size_t offset); + + std::string DetailedMessage() override; + char const* what() const noexcept override; + +private: + block_t m_block; + size_t m_offset; +}; diff --git a/src/ZoneLoading/Loading/IContentLoadingEntryPoint.h b/src/ZoneLoading/Loading/IContentLoadingEntryPoint.h index 25a8db46..fd01844b 100644 --- a/src/ZoneLoading/Loading/IContentLoadingEntryPoint.h +++ b/src/ZoneLoading/Loading/IContentLoadingEntryPoint.h @@ -1,7 +1,5 @@ #pragma once -#include "Zone/Stream/ZoneInputStream.h" - class IContentLoadingEntryPoint { public: @@ -12,5 +10,5 @@ public: IContentLoadingEntryPoint& operator=(const IContentLoadingEntryPoint& other) = default; IContentLoadingEntryPoint& operator=(IContentLoadingEntryPoint&& other) noexcept = default; - virtual void Load(ZoneInputStream& stream) = 0; + virtual void Load() = 0; }; diff --git a/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp b/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp index c4b9d59e..7e75ceca 100644 --- a/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp +++ b/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp @@ -4,7 +4,7 @@ namespace { - constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000; + constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000; // ~1GB class StepAllocXBlocks final : public ILoadingStep { diff --git a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp index 5b0ed359..80cb3591 100644 --- a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp +++ b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp @@ -7,32 +7,47 @@ namespace class StepLoadZoneContent final : public ILoadingStep { public: - StepLoadZoneContent(std::unique_ptr entryPoint, const int offsetBlockBitCount, const block_t insertBlock) - : m_content_loader(std::move(entryPoint)), + StepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, + const unsigned pointerBitCount, + const unsigned offsetBlockBitCount, + const block_t insertBlock, + MemoryManager& memory) + : m_entry_point_factory(std::move(entryPointFactory)), + m_pointer_bit_count(pointerBitCount), m_offset_block_bit_count(offsetBlockBitCount), - m_insert_block(insertBlock) + m_insert_block(insertBlock), + m_memory(memory) { } void PerformStep(ZoneLoader& zoneLoader, ILoadingStream& stream) override { - const auto inputStream = ZoneInputStream::Create(zoneLoader.m_blocks, stream, m_offset_block_bit_count, m_insert_block); + const auto inputStream = + ZoneInputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, zoneLoader.m_blocks, m_insert_block, stream, m_memory); - m_content_loader->Load(*inputStream); + const auto entryPoint = m_entry_point_factory(*inputStream); + assert(entryPoint); + + entryPoint->Load(); } private: - std::unique_ptr m_content_loader; - int m_offset_block_bit_count; + std::function(ZoneInputStream&)> m_entry_point_factory; + unsigned m_pointer_bit_count; + unsigned m_offset_block_bit_count; block_t m_insert_block; + MemoryManager& m_memory; }; } // namespace namespace step { - std::unique_ptr - CreateStepLoadZoneContent(std::unique_ptr entryPoint, const int offsetBlockBitCount, const block_t insertBlock) + std::unique_ptr CreateStepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, + const unsigned pointerBitCount, + const unsigned offsetBlockBitCount, + const block_t insertBlock, + MemoryManager& memory) { - return std::make_unique(std::move(entryPoint), offsetBlockBitCount, insertBlock); + return std::make_unique(std::move(entryPointFactory), pointerBitCount, offsetBlockBitCount, insertBlock, memory); } } // namespace step diff --git a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h index 2e1c2614..621fa2a2 100644 --- a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h +++ b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h @@ -2,11 +2,16 @@ #include "Loading/IContentLoadingEntryPoint.h" #include "Loading/ILoadingStep.h" +#include "Zone/Stream/ZoneInputStream.h" +#include #include namespace step { - std::unique_ptr - CreateStepLoadZoneContent(std::unique_ptr entryPoint, int offsetBlockBitCount, block_t insertBlock); + std::unique_ptr CreateStepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, + unsigned pointerBitCount, + unsigned offsetBlockBitCount, + block_t insertBlock, + MemoryManager& memory); } diff --git a/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp b/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp index 86e3343f..5e843841 100644 --- a/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp +++ b/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp @@ -8,27 +8,72 @@ #include #include +#include +#include #include +#include + +ZoneStreamFillReadAccessor::ZoneStreamFillReadAccessor(void* blockBuffer, const size_t bufferSize, const unsigned pointerByteCount, const size_t offset) + : m_block_buffer(blockBuffer), + m_buffer_size(bufferSize), + m_pointer_byte_count(pointerByteCount), + m_offset(offset) +{ + // Otherwise we cannot insert alias + assert(m_pointer_byte_count <= sizeof(uintptr_t)); +} + +ZoneStreamFillReadAccessor ZoneStreamFillReadAccessor::AtOffset(const size_t offset) const +{ + assert(offset <= m_buffer_size); + return ZoneStreamFillReadAccessor(static_cast(m_block_buffer) + offset, m_buffer_size - offset, m_pointer_byte_count, m_offset + offset); +} + +size_t ZoneStreamFillReadAccessor::Offset() const +{ + return m_offset; +} + +void* ZoneStreamFillReadAccessor::BlockBuffer(const size_t offset) const +{ + return static_cast(m_block_buffer) + offset; +} namespace { class XBlockInputStream final : public ZoneInputStream { public: - XBlockInputStream(std::vector& blocks, ILoadingStream& stream, const unsigned blockBitCount, const block_t insertBlock) + XBlockInputStream(const unsigned pointerBitCount, + const unsigned blockBitCount, + std::vector& blocks, + const block_t insertBlock, + ILoadingStream& stream, + MemoryManager& memory) : m_blocks(blocks), - m_stream(stream) + m_stream(stream), + m_memory(memory), + m_pointer_byte_count(pointerBitCount / 8u), + m_block_mask((std::numeric_limits::max() >> (sizeof(uintptr_t) * 8 - blockBitCount)) << (pointerBitCount - blockBitCount)), + m_block_shift(pointerBitCount - blockBitCount), + m_offset_mask(std::numeric_limits::max() >> (sizeof(uintptr_t) * 8 - (pointerBitCount - blockBitCount))), + m_last_fill_size(0) { + assert(pointerBitCount % 8u == 0u); + assert(insertBlock < static_cast(blocks.size())); + const auto blockCount = static_cast(blocks.size()); m_block_offsets = std::make_unique(blockCount); std::memset(m_block_offsets.get(), 0, sizeof(size_t) * blockCount); - m_block_bit_count = blockBitCount; - - assert(insertBlock < static_cast(blocks.size())); m_insert_block = blocks[insertBlock]; } + [[nodiscard]] unsigned GetPointerBitCount() const override + { + return m_pointer_byte_count * 8u; + } + void PushBlock(const block_t block) override { assert(block < static_cast(m_blocks.size())); @@ -38,7 +83,7 @@ namespace m_block_stack.push(newBlock); - if (newBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) m_temp_offsets.push(m_block_offsets[newBlock->m_index]); } @@ -54,7 +99,7 @@ namespace m_block_stack.pop(); // If the temp block is not used anymore right now, reset it to the buffer start since as the name suggests, the data inside is temporary. - if (poppedBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { m_block_offsets[poppedBlock->m_index] = m_temp_offsets.top(); m_temp_offsets.pop(); @@ -72,7 +117,7 @@ namespace auto* block = m_block_stack.top(); - Align(align); + Align(*block, align); if (m_block_offsets[block->m_index] > block->m_buffer_size) throw BlockOverflowException(block); @@ -80,6 +125,23 @@ namespace return &block->m_buffer[m_block_offsets[block->m_index]]; } + void* AllocOutOfBlock(const unsigned align, const size_t size) override + { + assert(!m_block_stack.empty()); + + if (m_block_stack.empty()) + return nullptr; + + auto* block = m_block_stack.top(); + + Align(*block, align); + + if (m_block_offsets[block->m_index] > block->m_buffer_size) + throw BlockOverflowException(block); + + return m_memory.AllocRaw(size); + } + void LoadDataRaw(void* dst, const size_t size) override { m_stream.Load(dst, size); @@ -87,50 +149,26 @@ namespace void LoadDataInBlock(void* dst, const size_t size) override { - assert(!m_block_stack.empty()); - - if (m_block_stack.empty()) - return; - - auto* block = m_block_stack.top(); - - if (block->m_buffer > dst || block->m_buffer + block->m_buffer_size < dst) - throw OutOfBlockBoundsException(block); - - if (static_cast(dst) + size > block->m_buffer + block->m_buffer_size) - throw BlockOverflowException(block); - - // Theoretically ptr should always be at the current block offset. - assert(dst == &block->m_buffer[m_block_offsets[block->m_index]]); - - switch (block->m_type) + // If no block has been pushed, load raw + if (!m_block_stack.empty()) { - case XBlock::Type::BLOCK_TYPE_TEMP: - case XBlock::Type::BLOCK_TYPE_NORMAL: - m_stream.Load(dst, size); - break; + auto* block = m_block_stack.top(); - case XBlock::Type::BLOCK_TYPE_RUNTIME: - memset(dst, 0, size); - break; + if (block->m_buffer.get() > dst || block->m_buffer.get() + block->m_buffer_size < dst) + throw OutOfBlockBoundsException(block); - case XBlock::Type::BLOCK_TYPE_DELAY: - assert(false); - break; + if (static_cast(dst) + size > block->m_buffer.get() + block->m_buffer_size) + throw BlockOverflowException(block); + + // Theoretically ptr should always be at the current block offset. + assert(dst == &block->m_buffer[m_block_offsets[block->m_index]]); + + LoadDataFromBlock(*block, dst, size); + } + else + { + m_stream.Load(dst, size); } - - IncBlockPos(size); - } - - void IncBlockPos(const size_t size) override - { - assert(!m_block_stack.empty()); - - if (m_block_stack.empty()) - return; - - const auto* block = m_block_stack.top(); - m_block_offsets[block->m_index] += size; } void LoadNullTerminated(void* dst) override @@ -142,14 +180,14 @@ namespace auto* block = m_block_stack.top(); - if (block->m_buffer > dst || block->m_buffer + block->m_buffer_size < dst) + if (block->m_buffer.get() > dst || block->m_buffer.get() + block->m_buffer_size < dst) throw OutOfBlockBoundsException(block); // Theoretically ptr should always be at the current block offset. assert(dst == &block->m_buffer[m_block_offsets[block->m_index]]); uint8_t byte; - auto offset = static_cast(static_cast(dst) - block->m_buffer); + auto offset = static_cast(static_cast(dst) - block->m_buffer.get()); do { if (offset >= block->m_buffer_size) @@ -162,32 +200,108 @@ namespace m_block_offsets[block->m_index] = offset; } - void** InsertPointer() override + ZoneStreamFillReadAccessor LoadWithFill(const size_t size) override { - m_block_stack.push(m_insert_block); + m_last_fill_size = size; - Align(alignof(void*)); + // If no block has been pushed, load raw + if (!m_block_stack.empty()) + { + const auto* block = m_block_stack.top(); + auto* blockBufferForFill = &block->m_buffer[m_block_offsets[block->m_index]]; - if (m_block_offsets[m_insert_block->m_index] + sizeof(void*) > m_insert_block->m_buffer_size) + LoadDataFromBlock(*block, blockBufferForFill, size); + + return ZoneStreamFillReadAccessor(blockBufferForFill, size, m_pointer_byte_count, 0); + } + + m_fill_buffer.resize(size); + m_stream.Load(m_fill_buffer.data(), size); + return ZoneStreamFillReadAccessor(m_fill_buffer.data(), size, m_pointer_byte_count, 0); + } + + ZoneStreamFillReadAccessor AppendToFill(const size_t appendSize) override + { + const auto appendOffset = m_last_fill_size; + m_last_fill_size += appendSize; + + // If no block has been pushed, load raw + if (!m_block_stack.empty()) + { + const auto* block = m_block_stack.top(); + auto* blockBufferForFill = &block->m_buffer[m_block_offsets[block->m_index]] - appendOffset; + LoadDataFromBlock(*block, &block->m_buffer[m_block_offsets[block->m_index]], appendSize); + + return ZoneStreamFillReadAccessor(blockBufferForFill, m_last_fill_size, m_pointer_byte_count, 0); + } + + m_fill_buffer.resize(appendOffset + appendSize); + m_stream.Load(m_fill_buffer.data() + appendOffset, appendSize); + return ZoneStreamFillReadAccessor(m_fill_buffer.data(), m_last_fill_size, m_pointer_byte_count, 0); + } + + ZoneStreamFillReadAccessor GetLastFill() override + { + assert(!m_fill_buffer.empty()); + + if (!m_block_stack.empty()) + { + const auto* block = m_block_stack.top(); + auto* blockBufferForFill = &block->m_buffer[m_block_offsets[block->m_index]] - m_last_fill_size; + + return ZoneStreamFillReadAccessor(blockBufferForFill, m_last_fill_size, m_pointer_byte_count, 0); + } + + assert(m_fill_buffer.size() == m_last_fill_size); + return ZoneStreamFillReadAccessor(m_fill_buffer.data(), m_last_fill_size, m_pointer_byte_count, 0); + } + + void* InsertPointerNative() override + { + // Alignment of pointer should always be its size + Align(*m_insert_block, m_pointer_byte_count); + + if (m_block_offsets[m_insert_block->m_index] + m_pointer_byte_count > m_insert_block->m_buffer_size) throw BlockOverflowException(m_insert_block); - auto* ptr = reinterpret_cast(&m_insert_block->m_buffer[m_block_offsets[m_insert_block->m_index]]); + auto* ptr = static_cast(&m_insert_block->m_buffer[m_block_offsets[m_insert_block->m_index]]); - IncBlockPos(sizeof(void*)); - - m_block_stack.pop(); + IncBlockPos(*m_insert_block, m_pointer_byte_count); return ptr; } - void* ConvertOffsetToPointer(const void* offset) override + uintptr_t InsertPointerAliasLookup() override + { + // Alignment of pointer should always be its size + Align(*m_insert_block, m_pointer_byte_count); + + if (m_block_offsets[m_insert_block->m_index] + m_pointer_byte_count > m_insert_block->m_buffer_size) + throw BlockOverflowException(m_insert_block); + + const auto blockNum = m_insert_block->m_index; + const auto blockOffset = static_cast(m_block_offsets[m_insert_block->m_index]); + const auto zonePtr = (static_cast(blockNum) << m_block_shift) | (blockOffset & m_offset_mask); + + IncBlockPos(*m_insert_block, m_pointer_byte_count); + + return zonePtr; + } + + void SetInsertedPointerAliasLookup(const uintptr_t zonePtr, void* value) override + { + assert((static_cast((zonePtr & m_block_mask) >> m_block_shift)) < m_blocks.size()); + m_alias_redirect_lookup.emplace(zonePtr, value); + } + + void* ConvertOffsetToPointerNative(const void* offset) override { // -1 because otherwise Block 0 Offset 0 would be just 0 which is already used to signalize a nullptr. // So all offsets are moved by 1. const auto offsetInt = reinterpret_cast(offset) - 1u; - const auto blockNum = static_cast(offsetInt >> (sizeof(offsetInt) * 8u - m_block_bit_count)); - const auto blockOffset = static_cast(offsetInt & (UINTPTR_MAX >> m_block_bit_count)); + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) throw InvalidOffsetBlockException(blockNum); @@ -200,13 +314,13 @@ namespace return &block->m_buffer[blockOffset]; } - void* ConvertOffsetToAlias(const void* offset) override + void* ConvertOffsetToAliasNative(const void* offset) override { // For details see ConvertOffsetToPointer const auto offsetInt = reinterpret_cast(offset) - 1u; - const auto blockNum = static_cast(offsetInt >> (sizeof(offsetInt) * 8u - m_block_bit_count)); - const auto blockOffset = static_cast(offsetInt & (UINTPTR_MAX >> m_block_bit_count)); + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) throw InvalidOffsetBlockException(blockNum); @@ -219,14 +333,124 @@ namespace return *reinterpret_cast(&block->m_buffer[blockOffset]); } - private: - void Align(const unsigned align) + void AddPointerLookup(void* alias, const void* blockPtr) override { assert(!m_block_stack.empty()); + const auto* block = m_block_stack.top(); + assert(blockPtr >= block->m_buffer.get() && blockPtr < block->m_buffer.get() + block->m_buffer_size); + // Non-normal blocks cannot be referenced via zone pointer anyway + if (block->m_type != XBlockType::BLOCK_TYPE_NORMAL) + return; + + const auto blockNum = block->m_index; + const auto blockOffset = static_cast(static_cast(blockPtr) - block->m_buffer.get()); + const auto zonePtr = (static_cast(blockNum) << m_block_shift) | (blockOffset & m_offset_mask); + m_pointer_redirect_lookup.emplace(zonePtr, alias); + } + + MaybePointerFromLookup ConvertOffsetToPointerLookup(const void* offset) override + { + // For details see ConvertOffsetToPointer + const auto offsetInt = reinterpret_cast(offset) - 1u; + + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); + + if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) + throw InvalidOffsetBlockException(blockNum); + + auto* block = m_blocks[blockNum]; + + if (block->m_buffer_size <= blockOffset + sizeof(void*)) + throw InvalidOffsetBlockOffsetException(block, blockOffset); + + const auto foundPointerLookup = m_pointer_redirect_lookup.find(offsetInt); + if (foundPointerLookup != m_pointer_redirect_lookup.end()) + return MaybePointerFromLookup(foundPointerLookup->second); + + return MaybePointerFromLookup(&block->m_buffer[blockOffset], blockNum, blockOffset); + } + + void* ConvertOffsetToAliasLookup(const void* offset) override + { + // For details see ConvertOffsetToPointer + const auto offsetInt = reinterpret_cast(offset) - 1u; + + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); + + if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) + throw InvalidOffsetBlockException(blockNum); + + auto* block = m_blocks[blockNum]; + + if (block->m_buffer_size <= blockOffset + sizeof(uintptr_t)) + throw InvalidOffsetBlockOffsetException(block, blockOffset); + + const auto foundAliasLookup = m_alias_redirect_lookup.find(offsetInt); + if (foundAliasLookup != m_alias_redirect_lookup.end()) + return foundAliasLookup->second; + + const auto foundPointerLookup = m_pointer_redirect_lookup.find(offsetInt); + if (foundPointerLookup != m_pointer_redirect_lookup.end()) + return *static_cast(foundPointerLookup->second); + + assert(false); + throw InvalidOffsetBlockOffsetException(block, blockOffset); + } + +#ifdef DEBUG_OFFSETS + void DebugOffsets(const size_t assetIndex) const override + { + std::ostringstream ss; + + ss << "Asset " << assetIndex; + for (const auto& block : m_blocks) + { + if (block->m_type != XBlockType::BLOCK_TYPE_NORMAL) + continue; + + ss << " " << m_block_offsets[block->m_index]; + } + + ss << "\n"; + std::cout << ss.str(); + } +#endif + + private: + void LoadDataFromBlock(const XBlock& block, void* dst, const size_t size) + { + switch (block.m_type) + { + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: + m_stream.Load(dst, size); + break; + + case XBlockType::BLOCK_TYPE_RUNTIME: + std::memset(dst, 0, size); + break; + + case XBlockType::BLOCK_TYPE_DELAY: + assert(false); + break; + } + + IncBlockPos(block, size); + } + + void IncBlockPos(const XBlock& block, const size_t size) + { + m_block_offsets[block.m_index] += size; + } + + void Align(const XBlock& block, const unsigned align) + { if (align > 0) { - const auto blockIndex = m_block_stack.top()->m_index; + const auto blockIndex = block.m_index; m_block_offsets[blockIndex] = utils::Align(m_block_offsets[blockIndex], static_cast(align)); } } @@ -238,12 +462,28 @@ namespace std::stack m_temp_offsets; ILoadingStream& m_stream; - unsigned m_block_bit_count; + MemoryManager& m_memory; + + unsigned m_pointer_byte_count; + uintptr_t m_block_mask; + unsigned m_block_shift; + uintptr_t m_offset_mask; XBlock* m_insert_block; + + std::vector m_fill_buffer; + size_t m_last_fill_size; + // These lookups map a block offset to a pointer in case of a platform mismatch + std::unordered_map m_pointer_redirect_lookup; + std::unordered_map m_alias_redirect_lookup; }; } // namespace -std::unique_ptr ZoneInputStream::Create(std::vector& blocks, ILoadingStream& stream, unsigned blockBitCount, block_t insertBlock) +std::unique_ptr ZoneInputStream::Create(const unsigned pointerBitCount, + const unsigned blockBitCount, + std::vector& blocks, + const block_t insertBlock, + ILoadingStream& stream, + MemoryManager& memory) { - return std::make_unique(blocks, stream, blockBitCount, insertBlock); + return std::make_unique(pointerBitCount, blockBitCount, blocks, insertBlock, stream, memory); } diff --git a/src/ZoneLoading/Zone/Stream/ZoneInputStream.h b/src/ZoneLoading/Zone/Stream/ZoneInputStream.h index 70acb592..f86c2e4c 100644 --- a/src/ZoneLoading/Zone/Stream/ZoneInputStream.h +++ b/src/ZoneLoading/Zone/Stream/ZoneInputStream.h @@ -1,26 +1,178 @@ #pragma once +#include "Loading/Exception/InvalidLookupPositionException.h" #include "Loading/ILoadingStream.h" +#include "Utils/MemoryManager.h" #include "Zone/Stream/IZoneStream.h" #include "Zone/XBlock.h" +#include +#include +#include #include +#include #include +// #define DEBUG_OFFSETS 1 + +class ZoneStreamFillReadAccessor +{ +public: + ZoneStreamFillReadAccessor(void* blockBuffer, size_t bufferSize, unsigned pointerByteCount, size_t offset); + + [[nodiscard]] ZoneStreamFillReadAccessor AtOffset(size_t offset) const; + [[nodiscard]] size_t Offset() const; + [[nodiscard]] void* BlockBuffer(size_t offset) const; + + template void Fill(T& value, const size_t offset) const + { + assert(offset + sizeof(T) <= m_buffer_size); + + value = *reinterpret_cast(static_cast(m_block_buffer) + offset); + } + + template void FillArray(T (&value)[S], const size_t offset) const + { + assert(offset + sizeof(T) * S <= m_buffer_size); + + std::memcpy(value, static_cast(m_block_buffer) + offset, sizeof(T) * S); + } + + template void FillPtr(T*& value, const size_t offset) const + { + assert(offset + m_pointer_byte_count <= m_buffer_size); + assert(m_pointer_byte_count <= sizeof(uintptr_t)); + + value = nullptr; + std::memcpy(&value, static_cast(m_block_buffer) + offset, m_pointer_byte_count); + } + +private: + void* m_block_buffer; + size_t m_buffer_size; + unsigned m_pointer_byte_count; + size_t m_offset; +}; + +template class MaybePointerFromLookup +{ +public: + explicit MaybePointerFromLookup(void* ptr) + : m_valid(true), + m_ptr(ptr), + m_block(0), + m_offset(0) + { + } + + MaybePointerFromLookup(void* ptr, const block_t block, const size_t offset) + : m_valid(false), + m_ptr(ptr), + m_block(block), + m_offset(offset) + { + } + + explicit MaybePointerFromLookup(const MaybePointerFromLookup& other) + : m_valid(other.m_valid), + m_ptr(static_cast(other.m_ptr)), + m_block(other.m_block), + m_offset(other.m_offset) + { + } + + [[nodiscard]] T* Expect() const + { + if (!m_valid) + throw InvalidLookupPositionException(m_block, m_offset); + + return static_cast(m_ptr); + } + + /** + * The original linker does an annoying optimization where ConvertOffsetToPointer makes structs + * reuse data across non-matching types. + * E.g. a pointer array reuses memory of a scriptstring array. + * Since cross-platform the sizes of the types do not match anymore, this has to be handled differently. + * The scenario seems to realistically only happen when the data is nulled so just alloc a nulled memory block. + * If this strategy fails, in the future it might need to realloc and load existing block data with fill. + */ + [[nodiscard]] T* OrNulled(const size_t gameSize, const size_t size, MemoryManager& memory) const + { + if (m_valid) + return static_cast(m_ptr); + + auto* result = static_cast(memory.AllocRaw(size)); + + // We expect the original game buffer to also have been nulled + assert(gameSize < size); + assert(memcmp(result, m_ptr, gameSize) == 0); + + return result; + } + + bool m_valid; + void* m_ptr; + block_t m_block; + size_t m_offset; +}; + class ZoneInputStream : public IZoneStream { public: + /** + * \brief Returns the configured bits that make up a pointer. + */ + [[nodiscard]] virtual unsigned GetPointerBitCount() const = 0; + + /** + * \brief Retrieves the new read position in the current block by aligning the position with the specified value and then returning the current read + * position in the block. + * \param align The alignment value that the read position is aligned with before being returned. This should typically be the alignment of the struct that + * should be read afterward. + * \return A pointer to the memory in which following load calls will load data to. + */ virtual void* Alloc(unsigned align) = 0; + /** + * \copydoc ZoneInputStream#Alloc(unsigned) + */ template T* Alloc(const unsigned align) { return static_cast(Alloc(align)); } + virtual void* AllocOutOfBlock(unsigned align, size_t size) = 0; + + /** + * \copydoc ZoneInputStream#AllocOutOfBlock(unsigned) + */ + template T* AllocOutOfBlock(const unsigned align, const size_t arraySize = 1u) + { + return static_cast(AllocOutOfBlock(align, sizeof(T) * arraySize)); + } + + /** + * \brief Loads data from the underlying stream without considering the current block or advancing the block position. + * The data is read directly to the specified location instead of block memory. + * \param dst The memory location to load data to. + * \param size The amount of data to load. + */ virtual void LoadDataRaw(void* dst, size_t size) = 0; + + /** + * \brief Loads data with the current blocks read operation into its block memory. + * Depending on the block type, the underlying stream might be read from or not. + * The current block position is advanced by the number of bytes read. + * The destination must be inside the current block's memory space, otherwise an exception is thrown. + * \param dst The destination where the data is loaded to. Must be inside the current block's memory bounds. + * \param size The amount of data to load. + */ virtual void LoadDataInBlock(void* dst, size_t size) = 0; - virtual void IncBlockPos(size_t size) = 0; virtual void LoadNullTerminated(void* dst) = 0; + virtual ZoneStreamFillReadAccessor LoadWithFill(size_t size) = 0; + virtual ZoneStreamFillReadAccessor AppendToFill(size_t appendSize) = 0; + virtual ZoneStreamFillReadAccessor GetLastFill() = 0; template void Load(T* dst) { @@ -37,26 +189,55 @@ public: LoadDataInBlock(const_cast(reinterpret_cast(dst)), size); } - virtual void** InsertPointer() = 0; + virtual void* InsertPointerNative() = 0; - template T** InsertPointer() + template T** InsertPointerNative() { - return reinterpret_cast(InsertPointer()); + return static_cast(InsertPointerNative()); } - virtual void* ConvertOffsetToPointer(const void* offset) = 0; + virtual uintptr_t InsertPointerAliasLookup() = 0; + virtual void SetInsertedPointerAliasLookup(uintptr_t lookupEntry, void* value) = 0; - template T* ConvertOffsetToPointer(T* offset) + virtual void* ConvertOffsetToPointerNative(const void* offset) = 0; + + template T* ConvertOffsetToPointerNative(T* offset) { - return static_cast(ConvertOffsetToPointer(static_cast(offset))); + return static_cast(ConvertOffsetToPointerNative(static_cast(offset))); } - virtual void* ConvertOffsetToAlias(const void* offset) = 0; + virtual void* ConvertOffsetToAliasNative(const void* offset) = 0; - template T* ConvertOffsetToAlias(T* offset) + template T* ConvertOffsetToAliasNative(T* offset) { - return static_cast(ConvertOffsetToAlias(static_cast(offset))); + return static_cast(ConvertOffsetToAliasNative(static_cast(offset))); } - static std::unique_ptr Create(std::vector& blocks, ILoadingStream& stream, unsigned blockBitCount, block_t insertBlock); + /** + * \brief Adds a lookup from a block pointer to out of block data + * \param redirectTo A pointer to the out of block data to redirect to + * \param redirectFrom A pointer to the block data to redirect from + */ + virtual void AddPointerLookup(void* redirectTo, const void* redirectFrom) = 0; + + virtual MaybePointerFromLookup ConvertOffsetToPointerLookup(const void* offset) = 0; + + template MaybePointerFromLookup ConvertOffsetToPointerLookup(T* offset) + { + return MaybePointerFromLookup(ConvertOffsetToPointerLookup(static_cast(offset))); + } + + virtual void* ConvertOffsetToAliasLookup(const void* offset) = 0; + + template T* ConvertOffsetToAliasLookup(T* offset) + { + return static_cast(ConvertOffsetToAliasLookup(static_cast(offset))); + } + +#ifdef DEBUG_OFFSETS + virtual void DebugOffsets(size_t assetIndex) const = 0; +#endif + + static std::unique_ptr Create( + unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, ILoadingStream& stream, MemoryManager& memory); }; diff --git a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp index 9fb99f06..2621980c 100644 --- a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp @@ -22,15 +22,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp index ede84059..0bb35364 100644 --- a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp @@ -24,14 +24,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp index 4ed62b7d..00338ed7 100644 --- a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp @@ -24,15 +24,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp index c96c6599..cd5ca5bf 100644 --- a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp +++ b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp @@ -22,13 +22,13 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp index ffa5edf6..3d0d1d70 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp @@ -29,14 +29,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlockType::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlockType::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp index a1f3760d..6eff9d3f 100644 --- a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp +++ b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp @@ -30,7 +30,7 @@ void InMemoryZoneOutputStream::PushBlock(const block_t block) m_block_stack.push(newBlock); - if (newBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { if (m_temp_sizes.empty()) m_temp_sizes.push(0); @@ -50,7 +50,7 @@ block_t InMemoryZoneOutputStream::PopBlock() m_block_stack.pop(); // If temp block is popped, see if its size is bigger than the current maximum temp size - if (poppedBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { const auto tempSize = m_temp_sizes.top(); m_temp_sizes.pop(); @@ -70,7 +70,7 @@ void InMemoryZoneOutputStream::Align(const int align) { auto* block = m_block_stack.top(); - if (block->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) m_temp_sizes.top() = (m_temp_sizes.top() + align - 1) / align * align; else block->m_buffer_size = (block->m_buffer_size + align - 1) / align * align; @@ -96,16 +96,16 @@ void* InMemoryZoneOutputStream::WriteDataInBlock(const void* src, const size_t s void* result = nullptr; switch (block->m_type) { - case XBlock::Type::BLOCK_TYPE_TEMP: - case XBlock::Type::BLOCK_TYPE_NORMAL: + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: result = m_zone_data->GetBufferOfSize(size); memcpy(result, src, size); break; - case XBlock::Type::BLOCK_TYPE_RUNTIME: + case XBlockType::BLOCK_TYPE_RUNTIME: break; - case XBlock::Type::BLOCK_TYPE_DELAY: + case XBlockType::BLOCK_TYPE_DELAY: assert(false); break; } @@ -122,7 +122,7 @@ void InMemoryZoneOutputStream::IncBlockPos(const size_t size) return; auto* block = m_block_stack.top(); - if (block->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) { m_temp_sizes.top() += size; } @@ -141,7 +141,7 @@ void InMemoryZoneOutputStream::WriteNullTerminated(const void* src) uintptr_t InMemoryZoneOutputStream::GetCurrentZonePointer() { assert(!m_block_stack.empty()); - assert(m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_NORMAL); + assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL); uintptr_t ptr = 0; ptr |= static_cast(m_block_stack.top()->m_index) << (sizeof(uintptr_t) * 8 - m_block_bit_count); @@ -168,7 +168,7 @@ void InMemoryZoneOutputStream::MarkFollowing(void** pPtr) { assert(!m_block_stack.empty()); assert(pPtr != nullptr); - *pPtr = m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; + *pPtr = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; } bool InMemoryZoneOutputStream::ReusableShouldWrite(void** pPtr, const size_t entrySize, const std::type_index type) @@ -202,7 +202,7 @@ void InMemoryZoneOutputStream::ReusableAddOffset(void* ptr, size_t size, size_t { assert(!m_block_stack.empty()); - const auto inTemp = m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_TEMP; + const auto inTemp = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP; auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer(); const auto foundEntriesForType = m_reusable_entries.find(type); if (foundEntriesForType == m_reusable_entries.end())