add pause menu (with one option)

this is pretty annoying becuase it requires drawing the overlay after drawing text..
it's probably not a bad idea to ship a new text renderer so some of the dodginess can be avoided
This commit is contained in:
somewhatlurker
2019-10-20 02:49:54 +11:00
parent d768fa40f3
commit 3c7768c147
11 changed files with 350 additions and 13 deletions
@@ -143,6 +143,14 @@ namespace TLAC::Components
}
}
void ComponentsManager::UpdateDrawSprites()
{
for (auto& component : components)
{
component->UpdateDrawSprites();
}
}
void ComponentsManager::UpdatePostDraw()
{
for (auto& component : components)
@@ -28,6 +28,7 @@ namespace TLAC::Components
void Update();
void UpdateInput();
void UpdatePostInput();
void UpdateDrawSprites();
void UpdatePostDraw();
void OnFocusGain();
void OnFocusLost();
@@ -0,0 +1,195 @@
#pragma once
#include <stdint.h>
#include <string>
namespace TLAC::Components
{
#pragma pack(push, 1)
struct RawFont
{
uint32_t sprId; // ?
uint8_t width1; // glyph?
uint8_t height1; // glyph?
uint8_t width2; // advance?
uint8_t height2; // advance?
uint8_t metric08; // or flag?
uint8_t metric09; // or flag?
uint8_t padding0a[0x06];
float metric08divby09;
uint64_t _0x10;
int64_t dataBegin;
int64_t dataEnd;
int64_t dataCapacityEnd;
uint8_t padding38[0x8];
};
struct RawFontHolderIdk // ...SeemsPrettyPointlessTbh
{
RawFont* rawfont;
uint16_t width1;
uint16_t height1;
uint16_t zero1; // ?
uint16_t zero2; // ?
uint8_t zero3; // some kind of flag, but seems unused
};
struct FontInfo
{
uint32_t fontId;
uint8_t padding04[0x4];
RawFont* rawfont;
uint16_t flag10; // (zero3 != 0 && padding38[0] != 0) ? 2 : (metric08 != metric09 ? 1 : 0)
uint8_t padding12[0x02];
float width1;
float height1;
float width2;
float height2;
float userSizeWidth;
float userSizeHeight;
float userSizeWidthMultiplier; // userSizeWidth / width1
float userSizeHeightMultiplier; // userSizeHeight / width2
float zero1; // ?
float zero2; // ?
void setSize(float width, float height)
{
((void(*)(FontInfo* fi, float width, float height))0x140199e60)(this, width, height);
}
FontInfo(uint32_t id)
{
((FontInfo*(*)(FontInfo* fi, uint32_t id))0x140196510)(this, id);
}
};
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
{
uint32_t textColour; // RGBA byte array?, so set as 0xAABBGGRR
uint32_t strokeColour; // ?? RGBA byte array?, so set as 0xAABBGGRR
uint8_t unk08;
uint8_t padding09[0x3];
uint32_t unk0c;
uint32_t unk10;
uint32_t unk14;
uint32_t unk18;
uint64_t unk1c;
uint32_t unk24;
uint32_t unk28;
float xBegin; // ?
float yBegin; // ?
float xCurrent; // ?
float yCurrent; // ?
uint8_t padding3c[0x4];
uint64_t unk40;
FontInfo* font;
uint16_t unk50;
DrawTextParams(FontInfo* fi)
{
textColour = 0xffffffff;
strokeColour = 0xff808080;
unk08 = 0;
unk0c = 0;
unk10 = 0;
unk14 = 0;
unk18 = 0;
unk1c = 0x7;
unk24 = 0xd;
unk28 = 0;
xBegin = 0;
yBegin = 0;
xCurrent = 0;
yCurrent = 0;
unk40 = 0;
font = fi;
unk50 = 0x25a1;
}
DrawTextParams()
{
DrawTextParams((FontInfo*)0x140eda860);
}
};
/* struct MsString {
union {
char* string_ptr;
char string_buf[16];
};
uint64_t len;
uint64_t bufsize;
char* GetCharBuf()
{
if (bufsize > 0xf && string_ptr != nullptr)
return string_ptr;
else
return string_buf;
};
void SetCharBuf(char* newcontent)
{
len = strlen(newcontent);
bufsize = len;
if (len > 0xf)
{
string_ptr = strdup(newcontent);
}
else
{
strcpy_s(string_buf, newcontent);
}
}
}; */
/* struct MsStringW {
union {
wchar_t* string_ptr;
wchar_t string_buf[8];
};
uint64_t len;
uint64_t bufsize;
wchar_t* GetCharBuf()
{
if (bufsize > 0x7 && string_ptr != nullptr)
return string_ptr;
else
return string_buf;
};
void SetCharBuf(wchar_t* newcontent)
{
len = wcslen(newcontent);
bufsize = len;
if (len > 0xf)
{
string_ptr = wcsdup(newcontent);
}
else
{
wcscpy_s(string_buf, newcontent);
}
}
}; */
// flags aren't really known, but 1 == normal, 2 == right align?, 8 == centered
void drawText(DrawTextParams* dtParam, uint32_t flags, std::string str)
{
((void(*)(DrawTextParams*, uint32_t, const char*, int64_t))0x140198500)(dtParam, flags, str.c_str(), str.length());
}
void drawTextW(DrawTextParams* dtParam, uint32_t 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(*drawTextW)(DrawTextParams* dtParam, uint32_t flags, MsStringW str) = (void(*)(DrawTextParams* dtParam, uint32_t flags, MsStringW str))0x140198380;
#pragma pack(pop)
}
@@ -17,6 +17,7 @@ namespace TLAC::Components
virtual void UpdateInput() {};
virtual void UpdatePostInput() {};
virtual void UpdateDrawSprites() {};
virtual void UpdatePostDraw() {};
virtual void OnFocusGain() {};
virtual void OnFocusLost() {};
@@ -13,6 +13,7 @@
#include "../../Utilities/EnumBitwiseOperations.h"
#include "../../FileSystem/ConfigFile.h"
#include "../GameState.h"
#include "../Pause.h"
const std::string KEY_CONFIG_FILE_NAME = "keyconfig.ini";
@@ -236,13 +237,13 @@ namespace TLAC::Components
{
JvsButtons buttons = JVS_NONE;
if (!(*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_MAIN) &&
if ((Pause::isPaused || !(*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_MAIN)) &&
buttonTestFunc(MenuLBinding))
{
buttons |= JVS_L;
return buttons;
}
if (!(*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_MAIN) &&
if ((Pause::isPaused || !(*(GameState*)CURRENT_GAME_STATE_ADDRESS == GS_GAME && *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS == SUB_GAME_MAIN)) &&
buttonTestFunc(MenuRBinding))
{
buttons |= JVS_R;
@@ -1,8 +1,9 @@
#include "Pause.h"
#include "../Constants.h"
#include "GameState.h"
#include "DrawText.h"
#include "Input/InputState.h"
#include "GL\glut.h"
#include "GL/glut.h"
#include <windows.h>
#include <vector>
@@ -41,7 +42,7 @@ namespace TLAC::Components
if (isPaused)
{
// exit pause if key is tapped or no longer in game somehow
if (isPauseKeyTapped() || *(GameState*)CURRENT_GAME_STATE_ADDRESS != GS_GAME || *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS != SUB_GAME_MAIN)
if (isUnpauseKeyTapped() || *(GameState*)CURRENT_GAME_STATE_ADDRESS != GS_GAME || *(SubGameState*)CURRENT_GAME_SUB_STATE_ADDRESS != SUB_GAME_MAIN)
{
setPaused(false);
}
@@ -60,6 +61,11 @@ namespace TLAC::Components
menuPos %= menuItems.size();
// actually use released when unpausing from a face button so it doesn't trigger input
// (this can trigger an unpause too)
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;
@@ -82,6 +88,47 @@ namespace TLAC::Components
}
}
void Pause::UpdateDrawSprites()
{
if (isPaused && showUI)
{
FontInfo fontInfo(0x11);
fontInfo.setSize(menuTextSize, menuTextSize);
DrawTextParams dtParams(&fontInfo);
dtParams.strokeColour = 0xff000000;
dtParams.xBegin = menuX;
dtParams.yBegin = menuY - menuItemHeight * (menuItems.size() / 2.0);
for (int i = 0; i < menuItems.size(); i++)
{
std::pair<std::string, void(*)()> &item = menuItems[i];
if (i == menuPos)
dtParams.textColour = 0xffffff00;
else
dtParams.textColour = 0xffffffff;
dtParams.xCurrent = dtParams.xBegin;
dtParams.yCurrent = dtParams.yBegin;
drawText(&dtParams, 8, item.first);
dtParams.yBegin += menuItemHeight;
}
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)
@@ -111,24 +158,69 @@ namespace TLAC::Components
glBegin(GL_QUADS);
glBindTexture(GL_TEXTURE_2D, 0);
glColor4ub(0, 0, 0, 127);
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(560, 250);
glVertex2i(620, 250);
glVertex2i(620, 470);
glVertex2i(560, 470);
glVertex2i(660, 250);
glVertex2i(720, 250);
glVertex2i(720, 470);
glVertex2i(660, 470);
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);
@@ -142,6 +234,13 @@ namespace TLAC::Components
return ((InputState*)(*(uint64_t*)INPUT_STATE_PTR_ADDRESS))->Tapped.Buttons & JVS_START;
}
bool Pause::isUnpauseKeyTapped()
{
// actually use released when unpausing from a face button so it doesn't trigger input
return ((InputState*)(*(uint64_t*)INPUT_STATE_PTR_ADDRESS))->Tapped.Buttons & JVS_START ||
((InputState*)(*(uint64_t*)INPUT_STATE_PTR_ADDRESS))->Released.Buttons & JVS_CROSS;
}
void Pause::setPaused(bool pause)
{
uint64_t audioMixerAddr = *(uint64_t*)(AUDIO_MAIN_CLASS_ADDRESS + 0x70);
@@ -15,12 +15,14 @@ namespace TLAC::Components
virtual void Initialize(ComponentsManager*) override;
virtual void Update() override;
virtual void UpdatePostInput() override;
virtual void UpdateDrawSprites() override;
virtual void UpdatePostDraw() override;
static bool isPaused;
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<bool> streamPlayStates;
static void InjectCode(void* address, const std::vector<uint8_t> data);
@@ -28,11 +30,17 @@ namespace TLAC::Components
static std::vector<uint8_t> origAetMovOp;
static constexpr uint8_t* aetMovPatchAddress = (uint8_t*)0x1401703b3;
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 void unpause() { setPaused(false); };
std::vector<std::pair<std::string, void(*)()>> menuItems = {
std::pair<std::string, void(*)()>(std::string("RESUME"), &unpause),
//std::pair<std::string, void(*)()>(std::string("GIVE UP"), &unpause),
};
};
}
@@ -8,6 +8,7 @@ constexpr uint8_t JNE_OPCODE = 0x85;
//constexpr uint64_t ENGINE_UPDATE_HOOK_TARGET_ADDRESS = 0x000000014018CC40;
constexpr uint64_t ENGINE_UPDATE_INPUT_ADDRESS = 0x000000014018CBB0;
constexpr uint64_t ENGINE_DRAW_SPRITES_ADDRESS = 0x0000000140500EA0;
constexpr uint64_t ENGINE_FINISH_DRAW_ADDRESS = 0x0000000140192730;
constexpr uint64_t CURRENT_GAME_STATE_ADDRESS = 0x0000000140EDA810;
@@ -111,6 +111,7 @@
<ClInclude Include="Components\ComponentsManager.h" />
<ClInclude Include="Components\CustomPlayerData.h" />
<ClInclude Include="Components\DebugComponent.h" />
<ClInclude Include="Components\DrawText.h" />
<ClInclude Include="Components\EmulatorComponent.h" />
<ClInclude Include="Components\FastLoader.h" />
<ClInclude Include="Components\FrameRateManager.h" />
@@ -198,6 +198,9 @@
<ClInclude Include="Components\Pause.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Components\DrawText.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -19,6 +19,7 @@
#pragma comment(lib, "detours.lib")
void(__cdecl* divaEngineUpdate)() = (void(__cdecl*)())0x14018CC40;
void(__cdecl* divaEngineDrawSprites)(void* addr, int idk) = (void(__cdecl*)(void* addr, int idk))ENGINE_DRAW_SPRITES_ADDRESS;
void(__cdecl* divaEngineFinishDraw)() = (void(__cdecl*)())ENGINE_FINISH_DRAW_ADDRESS;
LRESULT CALLBACK MessageWindowProcessCallback(HWND, UINT, WPARAM, LPARAM);
@@ -127,6 +128,11 @@ namespace TLAC
ComponentsManager.OnFocusLost();
}
void UpdateDrawSprites()
{
ComponentsManager.UpdateDrawSprites();
}
void UpdatePostDraw()
{
ComponentsManager.UpdatePostDraw();
@@ -348,6 +354,13 @@ void hookedEngineUpdate()
//divaEngineUpdate();
}
void hookedEngineDrawSprites(void* addr, int idk)
{
divaEngineDrawSprites(addr, idk);
if (idk == 0x0a)
TLAC::UpdateDrawSprites();
}
void hookedEngineFinishDraw()
{
TLAC::UpdatePostDraw();
@@ -374,6 +387,12 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)divaEngineUpdate, hookedEngineUpdate);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)divaEngineDrawSprites, hookedEngineDrawSprites);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)divaEngineFinishDraw, hookedEngineFinishDraw);