diff --git a/source-code/source/plugins/TLAC/Components/DrawText.h b/source-code/source/plugins/TLAC/Components/Drawing.h similarity index 67% rename from source-code/source/plugins/TLAC/Components/DrawText.h rename to source-code/source/plugins/TLAC/Components/Drawing.h index 6ae3487..7a17d16 100644 --- a/source-code/source/plugins/TLAC/Components/DrawText.h +++ b/source-code/source/plugins/TLAC/Components/Drawing.h @@ -65,17 +65,20 @@ namespace TLAC::Components FontInfo*(*getFont)(FontInfo* fi, uint32_t id) = (FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510; void(*fontSize)(FontInfo* fi, float width, float height) = (void(*)(FontInfo* fi, float width, float height))0x140199e60; - struct DrawTextParams + struct DrawParams { - uint32_t textColour; // RGBA byte array?, so set as 0xAABBGGRR - uint32_t strokeColour; // ?? RGBA byte array?, so set as 0xAABBGGRR + uint32_t colour; // RGBA byte array?, so set as 0xAABBGGRR + uint32_t fillColour; // ?? RGBA byte array?, so set as 0xAABBGGRR uint8_t unk08; - uint8_t padding09[0x3]; + uint8_t unk09[0x3]; uint32_t unk0c; uint32_t unk10; uint32_t unk14; uint32_t unk18; - uint64_t unk1c; + uint32_t layer; // 8 seems similar to default but higher + // 0x19 is startup screen + // I noticed some use different scaling + uint32_t unk20; uint32_t unk24; uint32_t unk28; float xBegin; // ? @@ -87,16 +90,17 @@ namespace TLAC::Components FontInfo* font; uint16_t unk50; - DrawTextParams(FontInfo* fi) + DrawParams(FontInfo* fi) { - textColour = 0xffffffff; - strokeColour = 0xff808080; + colour = 0xffffffff; + fillColour = 0xff808080; // except it's not? unk08 = 0; unk0c = 0; unk10 = 0; unk14 = 0; unk18 = 0; - unk1c = 0x7; + layer = 0x7; + unk20 = 0x0; unk24 = 0xd; unk28 = 0; xBegin = 0; @@ -108,9 +112,9 @@ namespace TLAC::Components unk50 = 0x25a1; } - DrawTextParams() + DrawParams() { - DrawTextParams((FontInfo*)0x140eda860); + DrawParams((FontInfo*)0x140eda860); } }; @@ -176,20 +180,37 @@ namespace TLAC::Components } }; */ - // flags aren't really known, but 1 == normal, 2 == right align?, 8 == centered - void drawText(DrawTextParams* dtParam, uint32_t flags, std::string str) + enum drawTextFlags : uint32_t { - ((void(*)(DrawTextParams*, uint32_t, const char*, int64_t))0x140198500)(dtParam, flags, str.c_str(), str.length()); + DRAWTEXT_PARAGRAPH = 1, //? + DRAWTEXT_ALIGN_RIGHT = 2, + DRAWTEXT_ALIGN_CENTRE = 8, + DRAWTEXT_STROKE = 0x10000, + }; + + void drawText(DrawParams* dtParam, drawTextFlags flags, std::string str) + { + ((void(*)(DrawParams*, uint32_t, const char*, int64_t))0x140198500)(dtParam, flags, str.c_str(), str.length()); } - void drawTextW(DrawTextParams* dtParam, uint32_t flags, std::wstring str) + void drawTextW(DrawParams* dtParam, drawTextFlags flags, std::wstring str) { const wchar_t* ptrs[2]; ptrs[0] = str.c_str(); ptrs[1] = (wchar_t*)((uint64_t)ptrs[0] + str.length() * 2); - ((void(*)(DrawTextParams*, uint32_t, const wchar_t**))0x140198380)(dtParam, flags, &ptrs[0]); + ((void(*)(DrawParams*, uint32_t, const wchar_t**))0x140198380)(dtParam, flags, &ptrs[0]); } - //void(*drawTextW)(DrawTextParams* dtParam, uint32_t flags, MsStringW str) = (void(*)(DrawTextParams* dtParam, uint32_t flags, MsStringW str))0x140198380; + //void(*drawTextW)(DrawParams* dtParam, drawTextFlags flags, MsStringW str) = (void(*)(DrawParams* dtParam, drawTextFlags flags, MsStringW str))0x140198380; + + struct RectangleBounds + { + float x; + float y; + float width; + float height; + }; + void(*fillRectangle)(DrawParams* dtParam, RectangleBounds* rect) = (void(*)(DrawParams* dtParam, RectangleBounds* rect))0x140198d80; + void(*drawRectangle)(DrawParams* dtParam, RectangleBounds* rect) = (void(*)(DrawParams* dtParam, RectangleBounds* rect))0x140198320; #pragma pack(pop) } \ No newline at end of file diff --git a/source-code/source/plugins/TLAC/Components/Pause.cpp b/source-code/source/plugins/TLAC/Components/Pause.cpp index 8d198c0..820d368 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.cpp +++ b/source-code/source/plugins/TLAC/Components/Pause.cpp @@ -1,17 +1,23 @@ #include "Pause.h" #include "../Constants.h" #include "GameState.h" -#include "DrawText.h" +#include "Drawing.h" #include "Input/InputState.h" #include "GL/glut.h" +#include "detours.h" #include #include namespace TLAC::Components { bool Pause::isPaused = false; + bool Pause::giveUp = false; + bool Pause::showUI = true; + unsigned int Pause::menuPos = 0; std::vector Pause::origAetMovOp; + std::vector Pause::origFramespeedOp; std::vector Pause::streamPlayStates; + bool(*divaGiveUpFunc)(void*) = (bool(*)(void* cls))GIVEUP_FUNC_ADDRESS; Pause::Pause() { @@ -30,6 +36,14 @@ namespace TLAC::Components { origAetMovOp.resize(8); memcpy(&origAetMovOp[0], aetMovPatchAddress, 8); + + origFramespeedOp.resize(4); + memcpy(&origFramespeedOp[0], framespeedPatchAddress, 4); + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)divaGiveUpFunc, hookedGiveUpFunc); + DetourTransactionCommit(); } void Pause::Update() @@ -66,6 +80,7 @@ namespace TLAC::Components if (inputState->Released.Buttons & JVS_CIRCLE) menuItems[menuPos].second(); + // swallow all button inputs if paused inputState->Tapped.Buttons = JVS_NONE; inputState->DoubleTapped.Buttons = JVS_NONE; @@ -92,11 +107,69 @@ namespace TLAC::Components { if (isPaused && showUI) { + // setup draw objects FontInfo fontInfo(0x11); - fontInfo.setSize(menuTextSize, menuTextSize); - DrawTextParams dtParams(&fontInfo); + DrawParams dtParams(&fontInfo); + dtParams.layer = 0x19; // same as startup screen - dtParams.strokeColour = 0xff000000; + + // bg rect + RectangleBounds rect; + rect = { 0, 0, 1280, 720 }; + dtParams.colour = 0x80000000; + dtParams.fillColour = 0x80000000; + fillRectangle(&dtParams, &rect); + + + // pause icon + const int pauseWidth = 80; + const int pauseHeight = 110; + const int pauseGap = 20; + const int pausePosX = 32; + const int pausePosY = 32; + const int pausePartWidth = (pauseWidth - pauseGap) / 2; + + const int pauseX1 = pausePosX; + const int pauseX2 = pausePosX + pausePartWidth + pauseGap; + const int pauseY1 = pausePosY; + + dtParams.colour = 0x80ffffff; + dtParams.fillColour = 0x80ffffff; + rect = { pauseX1, pauseY1, pausePartWidth, pauseHeight }; + fillRectangle(&dtParams, &rect); + rect = { pauseX2, pauseY1, pausePartWidth, pauseHeight }; + fillRectangle(&dtParams, &rect); + + + // selection cursor + int selectBoxOrigin = menuY - menuItemHeight * (menuItems.size() / 2.0) - (menuItemHeight - menuTextSize) / 2; + int selectBoxPos = selectBoxOrigin + menuItemHeight * menuPos; + const float selectBoxWidth = 200; + const float selectBoxHeight = menuItemHeight; + const float selectBoxThickness = 2; + + const float selectBoxX1 = menuX - selectBoxWidth / 2; + const float selectBoxX2 = selectBoxX1 + selectBoxWidth - selectBoxThickness; + const float selectBoxY1 = selectBoxPos; + const float selectBoxY2 = selectBoxY1 + selectBoxThickness; + const float selectBoxY3 = selectBoxY1 + selectBoxHeight - selectBoxThickness; + const float selectBoxSideHeight = selectBoxHeight - 2 * selectBoxThickness; + + // dirty hack using fillRectangle to get thickness (idk how to set it or it isn't possible to with drawRectangle) + dtParams.colour = 0xc0ffff00; + dtParams.fillColour = 0xc0ffff00; + rect = { selectBoxX1, selectBoxY1, selectBoxWidth, selectBoxThickness }; // top + fillRectangle(&dtParams, &rect); + rect = { selectBoxX1, selectBoxY3, selectBoxWidth, selectBoxThickness }; // bottom + fillRectangle(&dtParams, &rect); + rect = { selectBoxX1, selectBoxY2, selectBoxThickness, selectBoxSideHeight }; + fillRectangle(&dtParams, &rect); + rect = { selectBoxX2, selectBoxY2, selectBoxThickness, selectBoxSideHeight }; + fillRectangle(&dtParams, &rect); + + + // menu + fontInfo.setSize(menuTextSize, menuTextSize); dtParams.xBegin = menuX; dtParams.yBegin = menuY - menuItemHeight * (menuItems.size() / 2.0); @@ -106,126 +179,26 @@ namespace TLAC::Components std::pair &item = menuItems[i]; if (i == menuPos) - dtParams.textColour = 0xffffff00; + dtParams.colour = 0xffffff00; else - dtParams.textColour = 0xffffffff; + dtParams.colour = 0xffffffff; dtParams.xCurrent = dtParams.xBegin; dtParams.yCurrent = dtParams.yBegin; - drawText(&dtParams, 8, item.first); + drawText(&dtParams, (drawTextFlags)(DRAWTEXT_ALIGN_CENTRE), item.first); dtParams.yBegin += menuItemHeight; } + + // key legend fontInfo.setSize(18, 18); dtParams.xBegin = menuX; dtParams.yBegin = 600; dtParams.xCurrent = dtParams.xBegin; dtParams.yCurrent = dtParams.yBegin; - - dtParams.textColour = 0xffffffff; - - drawTextW(&dtParams, 8, L"○:Select ×:Close L/R:Move □:Hide Menu"); - } - } - - void Pause::UpdatePostDraw() - { - if (isPaused && showUI) - { - // this isn't imgui code, but I probably wouldn't have gotten this working properly if I didn't reference it, so... umm... yeah lol - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - - int width = glutGet(GLUT_WINDOW_WIDTH); - int height = glutGet(GLUT_WINDOW_HEIGHT); - - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, 1280, 720, 0, -1.0f, +1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glBegin(GL_QUADS); - glBindTexture(GL_TEXTURE_2D, 0); - - glColor4ub(0, 0, 0, 64); - glVertex2i(0, 0); - glVertex2i(1280, 0); - glVertex2i(1280, 720); - glVertex2i(0, 720); - - const int pauseWidth = 80; - const int pauseHeight = 110; - const int pauseGap = 20; - const int pausePosX = 32; - const int pausePosY = 32; - - const int pauseX1 = pausePosX; - const int pauseX2 = pauseX1 + (pauseWidth - pauseGap) / 2; - const int pauseX3 = pauseX2 + pauseGap; - const int pauseX4 = pauseX1 + pauseWidth; - - const int pauseY1 = pausePosY; - const int pauseY2 = pauseY1 + pauseHeight; - - glColor4ub(255, 255, 255, 127); - glVertex2i(pauseX1, pauseY1); - glVertex2i(pauseX2, pauseY1); - glVertex2i(pauseX2, pauseY2); - glVertex2i(pauseX1, pauseY2); - glVertex2i(pauseX3, pauseY1); - glVertex2i(pauseX4, pauseY1); - glVertex2i(pauseX4, pauseY2); - glVertex2i(pauseX3, pauseY2); - - glEnd(); - glBegin(GL_QUAD_STRIP); - - int selectBoxOrigin = menuY - menuItemHeight * (menuItems.size() / 2.0) - (menuItemHeight - menuTextSize) / 2; - int selectBoxPos = selectBoxOrigin + menuItemHeight * menuPos; - const int selectBoxWidth = 200; - const int selectBoxHeight = menuItemHeight; - const int selectBoxThickness = 2; - - const int selectBoxX1 = menuX - selectBoxWidth / 2; - const int selectBoxX4 = selectBoxX1 + selectBoxWidth; - const int selectBoxX2 = selectBoxX1 + selectBoxThickness; - const int selectBoxX3 = selectBoxX4 - selectBoxThickness; - - const int selectBoxY1 = selectBoxPos; - const int selectBoxY4 = selectBoxY1 + selectBoxHeight; - const int selectBoxY2 = selectBoxY1 + selectBoxThickness; - const int selectBoxY3 = selectBoxY4 - selectBoxThickness; - - glColor4ub(0, 255, 255, 127); - glVertex2i(selectBoxX2, selectBoxY2); - glVertex2i(selectBoxX1, selectBoxY1); - glVertex2i(selectBoxX3, selectBoxY2); - glVertex2i(selectBoxX4, selectBoxY1); - glVertex2i(selectBoxX3, selectBoxY3); - glVertex2i(selectBoxX4, selectBoxY4); - glVertex2i(selectBoxX2, selectBoxY3); - glVertex2i(selectBoxX1, selectBoxY4); - glVertex2i(selectBoxX2, selectBoxY2); - glVertex2i(selectBoxX1, selectBoxY1); - - glEnd(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); + dtParams.colour = 0xffffffff; + drawTextW(&dtParams, (drawTextFlags)(DRAWTEXT_ALIGN_CENTRE), L"○:Select ×:Close L/R:Move □:Hide Menu"); } } @@ -249,10 +222,10 @@ namespace TLAC::Components if (pause) { - *(float*)FRAME_SPEED_ADDRESS = 0.0f; // todo: hook getFrameSpeed so this can't be screwed up ((void(*)())DSC_PAUSE_FUNC_ADDRESS)(); InjectCode(aetMovPatchAddress, { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }); + InjectCode(framespeedPatchAddress, { 0x0f, 0x57, 0xc0, 0xc3 }); // XORPS XMM0,XMM0; RET for (int i = 0; i < nAudioStreams; i++) { @@ -264,13 +237,16 @@ namespace TLAC::Components *playstate = 0; } + + menuPos = 0; + showUI = true; } else { - *(float*)FRAME_SPEED_ADDRESS = 1.0f; ((void(*)())DSC_UNPAUSE_FUNC_ADDRESS)(); InjectCode(aetMovPatchAddress, origAetMovOp); + InjectCode(framespeedPatchAddress, origFramespeedOp); for (int i = 0; i < nAudioStreams; i++) { @@ -283,6 +259,25 @@ namespace TLAC::Components isPaused = pause; } + bool Pause::hookedGiveUpFunc(void* cls) + { + if (giveUp) + { + giveUp = false; + setPaused(false); + return true; + } + else + { + if (divaGiveUpFunc(cls)) + { + setPaused(false); + return true; + } + } + return false; + } + void Pause::InjectCode(void* address, const std::vector data) { const size_t byteCount = data.size() * sizeof(uint8_t); diff --git a/source-code/source/plugins/TLAC/Components/Pause.h b/source-code/source/plugins/TLAC/Components/Pause.h index 70a3c18..747d116 100644 --- a/source-code/source/plugins/TLAC/Components/Pause.h +++ b/source-code/source/plugins/TLAC/Components/Pause.h @@ -1,4 +1,5 @@ #pragma once +#include "../Constants.h" #include "EmulatorComponent.h" #include @@ -16,31 +17,39 @@ namespace TLAC::Components virtual void Update() override; virtual void UpdatePostInput() override; virtual void UpdateDrawSprites() override; - virtual void UpdatePostDraw() override; static bool isPaused; + static bool giveUp; + static void setPaused(bool pause); private: // this is a mess of static so that menuItems can work static bool isPauseKeyTapped(); static bool isUnpauseKeyTapped(); - static void setPaused(bool pause); static std::vector streamPlayStates; static void InjectCode(void* address, const std::vector data); static std::vector origAetMovOp; static constexpr uint8_t* aetMovPatchAddress = (uint8_t*)0x1401703b3; + static std::vector origFramespeedOp; + static constexpr uint8_t* framespeedPatchAddress = (uint8_t*)0x140192D50; + + static bool hookedGiveUpFunc(void* cls); + static const int menuX = 640; static const int menuY = 360; static const int menuItemHeight = 36; static const int menuTextSize = 24; - bool showUI = true; - unsigned int menuPos = 0; + static bool showUI; + static unsigned int menuPos; + static void unpause() { setPaused(false); }; + static void giveup() { giveUp = true; }; + std::vector> menuItems = { std::pair(std::string("RESUME"), &unpause), - //std::pair(std::string("GIVE UP"), &unpause), + std::pair(std::string("GIVE UP"), &giveup), }; }; } diff --git a/source-code/source/plugins/TLAC/Constants.h b/source-code/source/plugins/TLAC/Constants.h index 6714d3b..cfe2a8e 100644 --- a/source-code/source/plugins/TLAC/Constants.h +++ b/source-code/source/plugins/TLAC/Constants.h @@ -111,6 +111,10 @@ constexpr uint64_t DSC_START_SYS_TIME_ADDRESS_2 = 0x0000000140D0B568; constexpr uint64_t DSC_PAUSE_FUNC_ADDRESS = 0x00000001401295C0; constexpr uint64_t DSC_UNPAUSE_FUNC_ADDRESS = 0x0000000140129590; +constexpr uint64_t PV_GAME_BASE_ADDRESS = 0x0000000140C94380; +constexpr uint64_t GIVEUP_FUNC_ADDRESS = 0x000000014010EF00; + + #define XINPUT_A 0x00 #define XINPUT_B 0x01 #define XINPUT_X 0x02 diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj b/source-code/source/plugins/TLAC/TLAC.vcxproj index 4ba0caf..2c61ae9 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj @@ -111,7 +111,7 @@ - + diff --git a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters index 0d80993..6ec4726 100644 --- a/source-code/source/plugins/TLAC/TLAC.vcxproj.filters +++ b/source-code/source/plugins/TLAC/TLAC.vcxproj.filters @@ -198,7 +198,7 @@ Header Files - + Header Files