From da450c0d07ccd2f4b8315e09906ff57e73d69b74 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 16 Jan 2024 18:05:52 +0100 Subject: [PATCH] Temporarly load menu cache dump from bin to enrich menu --- src/ObjLoading/Cache/AbstractCacheReader.cpp | 41 +++ src/ObjLoading/Cache/AbstractCacheReader.h | 23 ++ .../IW4/AssetLoaders/AssetLoaderMenuList.cpp | 138 +++++++++ .../Game/IW4/Cache/MenuCacheReader.cpp | 288 ++++++++++++++++++ .../Game/IW4/Cache/MenuCacheReader.h | 26 ++ src/ObjWriting/Cache/AbstractCacheWriter.cpp | 2 +- .../Game/IW4/Cache/MenuCacheWriter.cpp | 22 +- 7 files changed, 528 insertions(+), 12 deletions(-) create mode 100644 src/ObjLoading/Cache/AbstractCacheReader.cpp create mode 100644 src/ObjLoading/Cache/AbstractCacheReader.h create mode 100644 src/ObjLoading/Game/IW4/Cache/MenuCacheReader.cpp create mode 100644 src/ObjLoading/Game/IW4/Cache/MenuCacheReader.h diff --git a/src/ObjLoading/Cache/AbstractCacheReader.cpp b/src/ObjLoading/Cache/AbstractCacheReader.cpp new file mode 100644 index 00000000..02d6256f --- /dev/null +++ b/src/ObjLoading/Cache/AbstractCacheReader.cpp @@ -0,0 +1,41 @@ +#include "AbstractCacheReader.h" + +using namespace cache; + +AbstractCacheReader::AbstractCacheReader(std::istream& stream, MemoryManager& memory) + : m_memory(memory), + m_stream(stream) +{ +} + +void AbstractCacheReader::Read(void* data, const size_t dataSize) const +{ + m_stream.read(static_cast(data), dataSize); + + const auto readCount = m_stream.gcount(); + if (readCount != dataSize) + { + const auto pos = m_stream.tellg(); + throw std::exception("Bad read"); + } +} + +bool AbstractCacheReader::ReadBool() const +{ + uint8_t value; + Read(&value, sizeof(value)); + + return value != 0; +} + +const char* AbstractCacheReader::ReadString() const +{ + uint16_t len = 0; + Read(&len, sizeof(len)); + + auto* str = static_cast(m_memory.Alloc(static_cast(len) + 1)); + Read(str, len); + str[len] = '\0'; + + return str; +} diff --git a/src/ObjLoading/Cache/AbstractCacheReader.h b/src/ObjLoading/Cache/AbstractCacheReader.h new file mode 100644 index 00000000..a8e79bb7 --- /dev/null +++ b/src/ObjLoading/Cache/AbstractCacheReader.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Utils/ClassUtils.h" +#include "Utils/MemoryManager.h" + +#include + +namespace cache +{ + class AbstractCacheReader + { + protected: + AbstractCacheReader(std::istream& stream, MemoryManager& memory); + + void Read(void* data, size_t dataSize) const; + const char* ReadString() const; + + _NODISCARD bool ReadBool() const; + + MemoryManager& m_memory; + std::istream& m_stream; + }; +} // namespace cache diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp index b9745dc7..7478bfac 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderMenuList.cpp @@ -1,5 +1,6 @@ #include "AssetLoaderMenuList.h" +#include "Game/IW4/Cache/MenuCacheReader.h" #include "Game/IW4/IW4.h" #include "Game/IW4/Menu/MenuConversionZoneStateIW4.h" #include "Game/IW4/Menu/MenuConverterIW4.h" @@ -14,6 +15,141 @@ using namespace IW4; namespace IW4 { + void EnrichMenu(ISearchPath* searchPath, menuDef_t* menu, MemoryManager* memory) + { + std::ostringstream ss; + ss << "menubin/" << menu->window.name << ".bin"; + const auto file = searchPath->Open(ss.str()); + + if (!file.IsOpen()) + return; + + const MenuCacheReader reader(*file.m_stream, *memory, menu->expressionData); + const auto readMenu = reader.ReadMenu(); + + // const auto* globalAsset = GlobalAssetPool::GetAssetByName(menu->window.name); + // const auto* readMenu = globalAsset->Asset(); + +#define COPY(p, a, b) (a)->p = (b)->p +#define MEMCOPY(p, a, b) memcpy(&a->p, &b->p, sizeof(a->p)) + + COPY(window.name, menu, readMenu); + COPY(window.rect, menu, readMenu); + COPY(window.rectClient, menu, readMenu); + COPY(window.group, menu, readMenu); + COPY(window.style, menu, readMenu); + COPY(window.border, menu, readMenu); + COPY(window.ownerDraw, menu, readMenu); + COPY(window.ownerDrawFlags, menu, readMenu); + COPY(window.borderSize, menu, readMenu); + COPY(window.staticFlags, menu, readMenu); + COPY(window.dynamicFlags[0], menu, readMenu); + COPY(window.nextTime, menu, readMenu); + MEMCOPY(window.foreColor, menu, readMenu); + MEMCOPY(window.backColor, menu, readMenu); + MEMCOPY(window.borderColor, menu, readMenu); + MEMCOPY(window.outlineColor, menu, readMenu); + MEMCOPY(window.disableColor, menu, readMenu); + COPY(font, menu, readMenu); + COPY(fullScreen, menu, readMenu); + COPY(fontIndex, menu, readMenu); + COPY(cursorItem[0], menu, readMenu); + COPY(fadeCycle, menu, readMenu); + COPY(fadeClamp, menu, readMenu); + COPY(fadeAmount, menu, readMenu); + COPY(fadeInAmount, menu, readMenu); + COPY(blurRadius, menu, readMenu); + COPY(onOpen, menu, readMenu); + COPY(onClose, menu, readMenu); + COPY(onCloseRequest, menu, readMenu); + COPY(onESC, menu, readMenu); + COPY(onKey, menu, readMenu); + COPY(visibleExp, menu, readMenu); + COPY(allowedBinding, menu, readMenu); + COPY(soundName, menu, readMenu); + COPY(imageTrack, menu, readMenu); + MEMCOPY(focusColor, menu, readMenu); + COPY(rectXExp, menu, readMenu); + COPY(rectYExp, menu, readMenu); + COPY(rectWExp, menu, readMenu); + COPY(rectHExp, menu, readMenu); + COPY(openSoundExp, menu, readMenu); + COPY(closeSoundExp, menu, readMenu); + MEMCOPY(scaleTransition, menu, readMenu); + MEMCOPY(alphaTransition, menu, readMenu); + MEMCOPY(xTransition, menu, readMenu); + MEMCOPY(yTransition, menu, readMenu); + + const auto itemCount = std::min(menu->itemCount, readMenu->itemCount); + for (auto i = 0; i < itemCount; i++) + { + auto* item = menu->items[i]; + const auto* readItem = readMenu->items[i]; + + COPY(window.name, item, readItem); + COPY(window.rect, item, readItem); + COPY(window.rectClient, item, readItem); + COPY(window.group, item, readItem); + COPY(window.style, item, readItem); + COPY(window.border, item, readItem); + COPY(window.ownerDraw, item, readItem); + COPY(window.ownerDrawFlags, item, readItem); + COPY(window.borderSize, item, readItem); + COPY(window.staticFlags, item, readItem); + COPY(window.dynamicFlags[0], item, readItem); + COPY(window.nextTime, item, readItem); + MEMCOPY(window.foreColor, item, readItem); + MEMCOPY(window.backColor, item, readItem); + MEMCOPY(window.borderColor, item, readItem); + MEMCOPY(window.outlineColor, item, readItem); + MEMCOPY(window.disableColor, item, readItem); + MEMCOPY(textRect[0], item, readItem); + COPY(type, item, readItem); + COPY(dataType, item, readItem); + COPY(alignment, item, readItem); + COPY(fontEnum, item, readItem); + COPY(textAlignMode, item, readItem); + COPY(textalignx, item, readItem); + COPY(textaligny, item, readItem); + COPY(textscale, item, readItem); + COPY(textStyle, item, readItem); + COPY(gameMsgWindowIndex, item, readItem); + COPY(gameMsgWindowMode, item, readItem); + COPY(text, item, readItem); + COPY(itemFlags, item, readItem); + COPY(mouseEnterText, item, readItem); + COPY(mouseExitText, item, readItem); + COPY(mouseEnter, item, readItem); + COPY(mouseExit, item, readItem); + COPY(action, item, readItem); + COPY(accept, item, readItem); + COPY(onFocus, item, readItem); + COPY(leaveFocus, item, readItem); + COPY(dvar, item, readItem); + COPY(dvarTest, item, readItem); + COPY(onKey, item, readItem); + COPY(enableDvar, item, readItem); + COPY(localVar, item, readItem); + COPY(dvarFlags, item, readItem); + COPY(special, item, readItem); + COPY(cursorPos[0], item, readItem); + COPY(imageTrack, item, readItem); + COPY(visibleExp, item, readItem); + COPY(disabledExp, item, readItem); + COPY(textExp, item, readItem); + COPY(materialExp, item, readItem); + MEMCOPY(glowColor, item, readItem); + COPY(decayActive, item, readItem); + COPY(fxBirthTime, item, readItem); + COPY(fxLetterTime, item, readItem); + COPY(fxDecayStartTime, item, readItem); + COPY(fxDecayDuration, item, readItem); + COPY(lastSoundPlayedTime, item, readItem); + } + + std::cout << "Enriched \"" << menu->window.name << "\"!\n"; + } + class MenuLoader { public: @@ -56,6 +192,8 @@ namespace IW4 return false; } + EnrichMenu(searchPath, menuAsset, memory); + menus.push_back(menuAsset); auto* menuAssetInfo = manager->AddAsset(ASSET_TYPE_MENU, menu->m_name, menuAsset, std::move(converter.GetDependencies()), std::vector()); diff --git a/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.cpp b/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.cpp new file mode 100644 index 00000000..283091fc --- /dev/null +++ b/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.cpp @@ -0,0 +1,288 @@ +#include "MenuCacheReader.h" + +using namespace IW4; + +MenuCacheReader::MenuCacheReader(std::istream& stream, MemoryManager& memory, ExpressionSupportingData* supportingData) + : AbstractCacheReader(stream, memory), + m_supporting_data(supportingData) +{ +} + +Statement_s* MenuCacheReader::ReadStatement() const +{ + auto* statement = static_cast(m_memory.Alloc(sizeof(Statement_s))); + Read(statement, sizeof(Statement_s)); + + if (statement->entries && statement->numEntries > 0) + { + statement->entries = static_cast(m_memory.Alloc(sizeof(expressionEntry) * statement->numEntries)); + Read(statement->entries, sizeof(expressionEntry) * statement->numEntries); + + for (auto i = 0; i < statement->numEntries; i++) + { + auto& entry = statement->entries[i]; + if (entry.type == EET_OPERAND) + { + if (entry.data.operand.dataType == VAL_STRING) + { + if (entry.data.operand.internals.stringVal.string) + entry.data.operand.internals.stringVal.string = ReadString(); + } + else if (entry.data.operand.dataType == VAL_FUNCTION) + { + if (entry.data.operand.internals.function) + entry.data.operand.internals.function = ReadStatement(); + } + } + } + } + + statement->supportingData = m_supporting_data; + + return statement; +} + +ItemKeyHandler* MenuCacheReader::ReadItemKeyHandler() const +{ + auto* itemKeyHandler = static_cast(m_memory.Alloc(sizeof(ItemKeyHandler))); + Read(itemKeyHandler, sizeof(ItemKeyHandler)); + + if (itemKeyHandler->action) + itemKeyHandler->action = ReadMenuEventHandlerSet(); + + if (itemKeyHandler->next) + itemKeyHandler->next = ReadItemKeyHandler(); + + return itemKeyHandler; +} + +MenuEventHandler* MenuCacheReader::ReadMenuEventHandler() const +{ + auto* menuEventHandler = static_cast(m_memory.Alloc(sizeof(MenuEventHandler))); + Read(menuEventHandler, sizeof(MenuEventHandler)); + + switch (menuEventHandler->eventType) + { + case EVENT_UNCONDITIONAL: + if (menuEventHandler->eventData.unconditionalScript) + menuEventHandler->eventData.unconditionalScript = ReadString(); + break; + + case EVENT_IF: + if (menuEventHandler->eventData.conditionalScript) + { + auto* conditionalScript = static_cast(m_memory.Alloc(sizeof(ConditionalScript))); + if (ReadBool()) + conditionalScript->eventHandlerSet = ReadMenuEventHandlerSet(); + else + conditionalScript->eventHandlerSet = nullptr; + + if (ReadBool()) + conditionalScript->eventExpression = ReadStatement(); + else + conditionalScript->eventExpression = nullptr; + + menuEventHandler->eventData.conditionalScript = conditionalScript; + } + break; + + case EVENT_ELSE: + if (menuEventHandler->eventData.elseScript) + menuEventHandler->eventData.elseScript = ReadMenuEventHandlerSet(); + break; + + case EVENT_SET_LOCAL_VAR_BOOL: + case EVENT_SET_LOCAL_VAR_FLOAT: + case EVENT_SET_LOCAL_VAR_INT: + case EVENT_SET_LOCAL_VAR_STRING: + if (menuEventHandler->eventData.setLocalVarData) + { + auto* setLocalVarData = static_cast(m_memory.Alloc(sizeof(SetLocalVarData))); + if (ReadBool()) + setLocalVarData->localVarName = ReadString(); + + if (ReadBool()) + setLocalVarData->expression = ReadStatement(); + else + setLocalVarData->expression = nullptr; + menuEventHandler->eventData.setLocalVarData = setLocalVarData; + } + break; + + default: + break; + } + + return menuEventHandler; +} + +MenuEventHandlerSet* MenuCacheReader::ReadMenuEventHandlerSet() const +{ + auto* menuEventHandlerSet = static_cast(m_memory.Alloc(sizeof(MenuEventHandlerSet))); + Read(menuEventHandlerSet, sizeof(MenuEventHandlerSet)); + + if (menuEventHandlerSet->eventHandlers) + { + menuEventHandlerSet->eventHandlers = + static_cast(m_memory.Alloc(sizeof(MenuEventHandler*) * menuEventHandlerSet->eventHandlerCount)); + for (auto i = 0; i < menuEventHandlerSet->eventHandlerCount; i++) + { + if (ReadBool()) + menuEventHandlerSet->eventHandlers[i] = ReadMenuEventHandler(); + else + menuEventHandlerSet->eventHandlers[i] = nullptr; + } + } + + return menuEventHandlerSet; +} + +void MenuCacheReader::ReadWindowDef(windowDef_t& windowDef) const +{ + if (windowDef.name) + windowDef.name = ReadString(); + + if (windowDef.group) + windowDef.group = ReadString(); + + // background +} + +itemDef_s* MenuCacheReader::ReadItem() const +{ + auto* item = static_cast(m_memory.Alloc(sizeof(itemDef_s))); + Read(item, sizeof(itemDef_s)); + + ReadWindowDef(item->window); + + if (item->text) + item->text = ReadString(); + + if (item->mouseEnterText) + item->mouseEnterText = ReadMenuEventHandlerSet(); + + if (item->mouseExitText) + item->mouseExitText = ReadMenuEventHandlerSet(); + + if (item->mouseEnter) + item->mouseEnter = ReadMenuEventHandlerSet(); + + if (item->mouseExit) + item->mouseExit = ReadMenuEventHandlerSet(); + + if (item->action) + item->action = ReadMenuEventHandlerSet(); + + if (item->accept) + item->accept = ReadMenuEventHandlerSet(); + + if (item->onFocus) + item->onFocus = ReadMenuEventHandlerSet(); + + if (item->leaveFocus) + item->leaveFocus = ReadMenuEventHandlerSet(); + + if (item->dvar) + item->dvar = ReadString(); + + if (item->dvarTest) + item->dvarTest = ReadString(); + + if (item->onKey) + item->onKey = ReadItemKeyHandler(); + + if (item->enableDvar) + item->enableDvar = ReadString(); + + if (item->localVar) + item->localVar = ReadString(); + + // focusSound + + // itemDefData + + // floatExpressions + + if (item->visibleExp) + item->visibleExp = ReadStatement(); + + if (item->disabledExp) + item->disabledExp = ReadStatement(); + + if (item->textExp) + item->textExp = ReadStatement(); + + if (item->materialExp) + item->materialExp = ReadStatement(); + + return item; +} + +menuDef_t* MenuCacheReader::ReadMenu() const +{ + auto* menu = static_cast(m_memory.Alloc(sizeof(menuDef_t))); + Read(menu, sizeof(menuDef_t)); + + menu->expressionData = m_supporting_data; + + ReadWindowDef(menu->window); + + if (menu->font) + menu->font = ReadString(); + + if (menu->onOpen) + menu->onOpen = ReadMenuEventHandlerSet(); + + if (menu->onClose) + menu->onClose = ReadMenuEventHandlerSet(); + + if (menu->onCloseRequest) + menu->onCloseRequest = ReadMenuEventHandlerSet(); + + if (menu->onESC) + menu->onESC = ReadMenuEventHandlerSet(); + + if (menu->onKey) + menu->onKey = ReadItemKeyHandler(); + + if (menu->visibleExp) + menu->visibleExp = ReadStatement(); + + if (menu->allowedBinding) + menu->allowedBinding = ReadString(); + + if (menu->soundName) + menu->soundName = ReadString(); + + if (menu->rectXExp) + menu->rectXExp = ReadStatement(); + + if (menu->rectYExp) + menu->rectYExp = ReadStatement(); + + if (menu->rectWExp) + menu->rectWExp = ReadStatement(); + + if (menu->rectHExp) + menu->rectHExp = ReadStatement(); + + if (menu->openSoundExp) + menu->openSoundExp = ReadStatement(); + + if (menu->closeSoundExp) + menu->closeSoundExp = ReadStatement(); + + if (menu->items) + { + menu->items = static_cast(m_memory.Alloc(sizeof(itemDef_s*) * menu->itemCount)); + for (auto i = 0; i < menu->itemCount; i++) + { + if (ReadBool()) + menu->items[i] = ReadItem(); + else + menu->items[i] = nullptr; + } + } + + return menu; +} diff --git a/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.h b/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.h new file mode 100644 index 00000000..1b87adc8 --- /dev/null +++ b/src/ObjLoading/Game/IW4/Cache/MenuCacheReader.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Cache/AbstractCacheReader.h" +#include "Game/IW4/IW4.h" +#include "Utils/ClassUtils.h" + +namespace IW4 +{ + class MenuCacheReader final : public cache::AbstractCacheReader + { + public: + MenuCacheReader(std::istream& stream, MemoryManager& memory, ExpressionSupportingData* supportingData); + + _NODISCARD Statement_s* ReadStatement() const; + _NODISCARD ItemKeyHandler* ReadItemKeyHandler() const; + _NODISCARD MenuEventHandler* ReadMenuEventHandler() const; + _NODISCARD MenuEventHandlerSet* ReadMenuEventHandlerSet() const; + + void ReadWindowDef(windowDef_t& windowDef) const; + + _NODISCARD itemDef_s* ReadItem() const; + _NODISCARD menuDef_t* ReadMenu() const; + + ExpressionSupportingData* m_supporting_data; + }; +} // namespace IW4 diff --git a/src/ObjWriting/Cache/AbstractCacheWriter.cpp b/src/ObjWriting/Cache/AbstractCacheWriter.cpp index 872968ef..27914ba6 100644 --- a/src/ObjWriting/Cache/AbstractCacheWriter.cpp +++ b/src/ObjWriting/Cache/AbstractCacheWriter.cpp @@ -17,7 +17,7 @@ void AbstractCacheWriter::WriteString(const char* str) const if (!str) return; - const auto len = strnlen(str, 0xFFFF); + const auto len = static_cast(strnlen(str, 0xFFFF)); Write(&len, sizeof(len)); Write(str, len); } diff --git a/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp index 477d9ae1..f72aa4e1 100644 --- a/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp +++ b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp @@ -7,17 +7,6 @@ MenuCacheWriter::MenuCacheWriter(std::ostream& stream) { } -void MenuCacheWriter::WriteItemKeyHandler(const ItemKeyHandler& itemKeyHandler) const -{ - Write(&itemKeyHandler, sizeof(ItemKeyHandler)); - - if (itemKeyHandler.action) - WriteMenuEventHandlerSet(*itemKeyHandler.action); - - if (itemKeyHandler.next) - WriteItemKeyHandler(*itemKeyHandler.next); -} - void MenuCacheWriter::WriteStatement(const Statement_s& statement) const { Write(&statement, sizeof(Statement_s)); @@ -47,6 +36,17 @@ void MenuCacheWriter::WriteStatement(const Statement_s& statement) const // supportingData } +void MenuCacheWriter::WriteItemKeyHandler(const ItemKeyHandler& itemKeyHandler) const +{ + Write(&itemKeyHandler, sizeof(ItemKeyHandler)); + + if (itemKeyHandler.action) + WriteMenuEventHandlerSet(*itemKeyHandler.action); + + if (itemKeyHandler.next) + WriteItemKeyHandler(*itemKeyHandler.next); +} + void MenuCacheWriter::WriteMenuEventHandler(const MenuEventHandler& menuEventHandler) const { Write(&menuEventHandler, sizeof(MenuEventHandler));