Skip to content

Commit 4545f11

Browse files
committed
Fix minimap, dialogue boxes, etc. alpha issues
1 parent 7de24c2 commit 4545f11

3 files changed

Lines changed: 90 additions & 3 deletions

File tree

resources/BreathOfTheWild_BetterVR/patch_Misc.asm

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,32 @@ moduleMatches = 0x6267BFD0
33

44
.origin = codecave
55

6+
; the game normally draws most of the UI on top of the 3D color buffer
7+
; the VR mod uses the alpha channel of the 2D UI as a mask to present a transparent version of the HUD on top of the 3D framebuffer
8+
; this patch basically fixes a few elements not using the right blending options
9+
; for example, the minimap, dialogue boxes and various other things to overwrite the alpha of previously rendered 2D elements
10+
; which cause gaps inside the image that's shown in VR
11+
hook_FixUIBlending:
12+
stwu r1, -0x10(r1)
13+
mflr r0
14+
stw r0, 0x14(r1)
15+
stw r3, 0xC(r1)
16+
stw r4, 0x8(r1)
17+
18+
bl import.coreinit.hook_FixUIBlending
19+
20+
bl import.gx2.GX2SetBlendControl
21+
22+
lwz r4, 0x8(r1)
23+
lwz r3, 0xC(r1)
24+
lwz r0, 0x14(r1)
25+
addi r1, r1, 0x10
26+
mtlr r0
27+
blr
28+
29+
0x03C58BF8 = bla hook_FixUIBlending
30+
0x03C58CC0 = bla hook_FixUIBlending
31+
0x03C58D68 = bla hook_FixUIBlending
632

733
; forces the player to always be guarding when the shield is drawn
834
; uses player rotation to determine the guard direction, not shield direction

src/hooking/cemu_hooks.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,15 @@ class CemuHooks {
5858
osLib_registerHLEFunction("coreinit", "hook_InjectXRInput", &hook_InjectXRInput);
5959
osLib_registerHLEFunction("coreinit", "hook_XRRumble_VPADControlMotor", &hook_XRRumble_VPADControlMotor);
6060
osLib_registerHLEFunction("coreinit", "hook_XRRumble_VPADStopMotor", &hook_XRRumble_VPADStopMotor);
61+
osLib_registerHLEFunction("coreinit", "hook_FixLadder", &hook_FixLadder);
6162

62-
// Logging/Debugging Hooks
63+
// Misc. Hooks
6364
osLib_registerHLEFunction("coreinit", "hook_OSReportToConsole", &hook_OSReportToConsole);
6465
osLib_registerHLEFunction("coreinit", "hook_DropWeaponLogging", &hook_DropWeaponLogging);
6566
osLib_registerHLEFunction("coreinit", "hook_ModifyHandModelAccessSearch", &hook_ModifyHandModelAccessSearch);
6667
osLib_registerHLEFunction("coreinit", "hook_CreateNewScreen", &hook_CreateNewScreen);
68+
osLib_registerHLEFunction("coreinit", "hook_FixUIBlending", &hook_FixUIBlending);
6769
osLib_registerHLEFunction("coreinit", "hook_RouteActorJob", &hook_RouteActorJob);
68-
osLib_registerHLEFunction("coreinit", "hook_FixLadder", &hook_FixLadder);
6970
};
7071
~CemuHooks() {
7172
FreeLibrary(m_cemuHandle);
@@ -232,11 +233,12 @@ class CemuHooks {
232233
static void hook_XRRumble_VPADControlMotor(PPCInterpreter_t* hCPU);
233234
static void hook_XRRumble_VPADStopMotor(PPCInterpreter_t* hCPU);
234235

235-
// Logging/Debugging Hooks
236+
// Misc Hooks
236237
static void hook_OSReportToConsole(PPCInterpreter_t* hCPU);
237238
static void hook_DropWeaponLogging(PPCInterpreter_t* hCPU);
238239
static void hook_ModifyHandModelAccessSearch(PPCInterpreter_t* hCPU);
239240
static void hook_CreateNewScreen(PPCInterpreter_t* hCPU);
241+
static void hook_FixUIBlending(PPCInterpreter_t* hCPU);
240242
static void hook_RouteActorJob(PPCInterpreter_t* hCPU);
241243

242244
public:

src/hooking/weapon.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,65 @@ void CemuHooks::hook_CreateNewScreen(PPCInterpreter_t* hCPU) {
242242
}
243243
}
244244

245+
246+
enum class GX2_BLENDFACTOR {
247+
ZERO = 0x00,
248+
ONE = 0x01,
249+
SRC_COLOR = 0x02,
250+
ONE_MINUS_SRC_COLOR = 0x03,
251+
SRC_ALPHA = 0x04,
252+
ONE_MINUS_SRC_ALPHA = 0x05,
253+
DST_ALPHA = 0x06,
254+
ONE_MINUS_DST_ALPHA = 0x07,
255+
DST_COLOR = 0x08,
256+
ONE_MINUS_DST_COLOR = 0x09,
257+
SRC_ALPHA_SATURATE = 0x0A,
258+
BOTH_SRC_ALPHA = 0x0B,
259+
BOTH_INV_SRC_ALPHA = 0x0C,
260+
CONST_COLOR = 0x0D,
261+
ONE_MINUS_CONST_COLOR = 0x0E,
262+
SRC1_COLOR = 0x0F,
263+
INV_SRC1_COLOR = 0x10,
264+
SRC1_ALPHA = 0x11,
265+
INV_SRC1_ALPHA = 0x12,
266+
CONST_ALPHA = 0x13,
267+
ONE_MINUS_CONST_ALPHA = 0x14
268+
};
269+
270+
enum class GX2_COMBINEFUNC {
271+
DST_PLUS_SRC = 0,
272+
SRC_MINUS_DST = 1,
273+
MIN_DST_SRC = 2,
274+
MAX_DST_SRC = 3,
275+
DST_MINUS_SRC = 4
276+
};
277+
278+
void CemuHooks::hook_FixUIBlending(PPCInterpreter_t* hCPU) {
279+
hCPU->instructionPointer = hCPU->sprNew.LR;
280+
281+
uint32_t renderTargetIndex = hCPU->gpr[3];
282+
GX2_BLENDFACTOR colorSrcFactor = (GX2_BLENDFACTOR)hCPU->gpr[4];
283+
GX2_BLENDFACTOR colorDstFactor = (GX2_BLENDFACTOR)hCPU->gpr[5];
284+
GX2_COMBINEFUNC colorCombineFunc = (GX2_COMBINEFUNC)hCPU->gpr[6];
285+
uint32_t separateAlphaBlend = hCPU->gpr[7];
286+
GX2_BLENDFACTOR alphaSrcFactor = (GX2_BLENDFACTOR)hCPU->gpr[8];
287+
GX2_BLENDFACTOR alphaDstFactor = (GX2_BLENDFACTOR)hCPU->gpr[9];
288+
GX2_COMBINEFUNC alphaCombineFunc = (GX2_COMBINEFUNC)hCPU->gpr[10];
289+
290+
{
291+
bool matchesColorSettings = colorSrcFactor == GX2_BLENDFACTOR::DST_COLOR && colorDstFactor == GX2_BLENDFACTOR::SRC_ALPHA && colorCombineFunc == GX2_COMBINEFUNC::DST_PLUS_SRC;
292+
bool matchesAlpha = alphaSrcFactor == GX2_BLENDFACTOR::SRC_ALPHA && alphaDstFactor == GX2_BLENDFACTOR::ONE_MINUS_SRC_ALPHA && alphaCombineFunc == GX2_COMBINEFUNC::DST_PLUS_SRC;
293+
294+
if (matchesColorSettings && matchesAlpha) {
295+
hCPU->gpr[7] = 1;
296+
hCPU->gpr[8] = std::to_underlying(GX2_BLENDFACTOR::ZERO);
297+
hCPU->gpr[9] = std::to_underlying(GX2_BLENDFACTOR::DST_ALPHA);
298+
299+
//Log::print<VERBOSE>("FixUIBlending called with renderTargetIndex: {}, colorSrcFactor: {}, colorDstFactor: {}, colorCombineFunc: {}, separateAlphaBlend: {}, alphaSrcFactor: {}, alphaDstFactor: {}, alphaCombineFunc: {}", renderTargetIndex, std::to_underlying(colorSrcFactor), std::to_underlying(colorDstFactor), std::to_underlying(colorCombineFunc), separateAlphaBlend, std::to_underlying(alphaSrcFactor), std::to_underlying(alphaDstFactor), std::to_underlying(alphaCombineFunc));
300+
}
301+
}
302+
}
303+
245304
// todo: this function does nothing, we use ChangeWeaponMtx instead
246305
void CemuHooks::hook_DropEquipment(PPCInterpreter_t* hCPU) {
247306
hCPU->instructionPointer = hCPU->sprNew.LR;

0 commit comments

Comments
 (0)