mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-11-08 05:55:07 +01:00
Fix displaying the config menu when using 480i + 4:3 or 576i as output resolution
This commit is contained in:
parent
43a18b56d7
commit
d1cfff4861
@ -76,6 +76,7 @@ WUMS_APPLICATION_STARTS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OSReport("Running WiiUPluginLoaderBackend " VERSION_FULL "\n");
|
OSReport("Running WiiUPluginLoaderBackend " VERSION_FULL "\n");
|
||||||
|
gStoredTVBuffer = {};
|
||||||
|
|
||||||
gUsedRPLs.clear();
|
gUsedRPLs.clear();
|
||||||
|
|
||||||
|
@ -2,15 +2,14 @@
|
|||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include <avm/tv.h>
|
||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include <coreinit/memory.h>
|
#include <coreinit/memory.h>
|
||||||
#include <coreinit/screen.h>
|
#include <coreinit/screen.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
|
|
||||||
// buffer width
|
// buffer width
|
||||||
#define TV_WIDTH 0x500
|
|
||||||
#define DRC_WIDTH 0x380
|
#define DRC_WIDTH 0x380
|
||||||
|
|
||||||
bool DrawUtils::isBackBuffer;
|
bool DrawUtils::isBackBuffer;
|
||||||
@ -19,15 +18,98 @@ uint8_t *DrawUtils::tvBuffer = nullptr;
|
|||||||
uint32_t DrawUtils::tvSize = 0;
|
uint32_t DrawUtils::tvSize = 0;
|
||||||
uint8_t *DrawUtils::drcBuffer = nullptr;
|
uint8_t *DrawUtils::drcBuffer = nullptr;
|
||||||
uint32_t DrawUtils::drcSize = 0;
|
uint32_t DrawUtils::drcSize = 0;
|
||||||
|
uint32_t DrawUtils::usedTVWidth = 1280;
|
||||||
|
float DrawUtils::usedTVScale = 1.5f;
|
||||||
static SFT pFont = {};
|
static SFT pFont = {};
|
||||||
|
|
||||||
static Color font_col(0xFFFFFFFF);
|
static Color font_col(0xFFFFFFFF);
|
||||||
|
|
||||||
|
#define __SetDCPitchReg ((void (*)(uint32_t, uint32_t))(0x101C400 + 0x1e714))
|
||||||
|
|
||||||
|
extern "C" uint32_t __OSPhysicalToEffectiveUncached(uint32_t);
|
||||||
|
|
||||||
|
static uint32_t __ReadReg32(uint32_t index) {
|
||||||
|
if (OSIsECOMode()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto regs = (uint32_t *) __OSPhysicalToEffectiveUncached(0xc200000);
|
||||||
|
return regs[index];
|
||||||
|
}
|
||||||
|
|
||||||
void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_, uint32_t drcSize_) {
|
void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_, uint32_t drcSize_) {
|
||||||
DrawUtils::tvBuffer = (uint8_t *) tvBuffer_;
|
DrawUtils::tvBuffer = (uint8_t *) tvBuffer_;
|
||||||
DrawUtils::tvSize = tvSize_;
|
DrawUtils::tvSize = tvSize_;
|
||||||
DrawUtils::drcBuffer = (uint8_t *) drcBuffer_;
|
DrawUtils::drcBuffer = (uint8_t *) drcBuffer_;
|
||||||
DrawUtils::drcSize = drcSize_;
|
DrawUtils::drcSize = drcSize_;
|
||||||
|
|
||||||
|
bool bigScale = true;
|
||||||
|
switch (TVEGetCurrentPort()) {
|
||||||
|
case TVE_PORT_HDMI:
|
||||||
|
bigScale = true;
|
||||||
|
break;
|
||||||
|
case TVE_PORT_COMPONENT:
|
||||||
|
case TVE_PORT_COMPOSITE:
|
||||||
|
case TVE_PORT_SCART:
|
||||||
|
bigScale = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVMTvResolution tvResolution = AVM_TV_RESOLUTION_720P;
|
||||||
|
if (AVMGetTVScanMode(&tvResolution)) {
|
||||||
|
switch (tvResolution) {
|
||||||
|
case AVM_TV_RESOLUTION_480P:
|
||||||
|
case AVM_TV_RESOLUTION_720P:
|
||||||
|
case AVM_TV_RESOLUTION_720P_3D:
|
||||||
|
case AVM_TV_RESOLUTION_1080I:
|
||||||
|
case AVM_TV_RESOLUTION_1080P:
|
||||||
|
case AVM_TV_RESOLUTION_576P:
|
||||||
|
case AVM_TV_RESOLUTION_720P_50HZ:
|
||||||
|
case AVM_TV_RESOLUTION_1080I_50HZ:
|
||||||
|
case AVM_TV_RESOLUTION_1080P_50HZ:
|
||||||
|
bigScale = true;
|
||||||
|
break;
|
||||||
|
case AVM_TV_RESOLUTION_576I:
|
||||||
|
case AVM_TV_RESOLUTION_480I:
|
||||||
|
case AVM_TV_RESOLUTION_480I_PAL60:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tvScanBufferWidth = __ReadReg32(0x184d + SCREEN_TV * 0x200);
|
||||||
|
|
||||||
|
if (tvScanBufferWidth == 640) { // 480i/480p/576i 4:3
|
||||||
|
DrawUtils::usedTVWidth = 640;
|
||||||
|
__SetDCPitchReg(SCREEN_TV, 640);
|
||||||
|
DrawUtils::usedTVScale = bigScale ? 0.75 : 0.75f;
|
||||||
|
} else if (tvScanBufferWidth == 854) { // 480i/480p/576i 16:9
|
||||||
|
DrawUtils::usedTVWidth = 896;
|
||||||
|
__SetDCPitchReg(SCREEN_TV, 896);
|
||||||
|
DrawUtils::usedTVScale = bigScale ? 1.0 : 1.0f;
|
||||||
|
} else if (tvScanBufferWidth == 1280) { // 720p 16:9
|
||||||
|
DrawUtils::usedTVWidth = 1280;
|
||||||
|
__SetDCPitchReg(SCREEN_TV, 1280);
|
||||||
|
if (bigScale) {
|
||||||
|
DrawUtils::usedTVScale = 1.5;
|
||||||
|
} else {
|
||||||
|
DrawUtils::usedTVScale = 0.75f;
|
||||||
|
if (tvResolution == AVM_TV_RESOLUTION_480I_PAL60 || tvResolution == AVM_TV_RESOLUTION_480I) {
|
||||||
|
AVMTvAspectRatio tvAspectRatio;
|
||||||
|
if (AVMGetTVAspectRatio(&tvAspectRatio) && tvAspectRatio == AVM_TV_ASPECT_RATIO_16_9) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("force big scaling for 480i + 16:9");
|
||||||
|
DrawUtils::usedTVScale = 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tvScanBufferWidth == 1920) { // 1080i/1080p 16:9
|
||||||
|
DrawUtils::usedTVWidth = 1920;
|
||||||
|
__SetDCPitchReg(SCREEN_TV, 1920);
|
||||||
|
DrawUtils::usedTVScale = bigScale ? 2.25 : 1.125f;
|
||||||
|
} else {
|
||||||
|
DrawUtils::usedTVWidth = tvScanBufferWidth;
|
||||||
|
__SetDCPitchReg(SCREEN_TV, tvScanBufferWidth);
|
||||||
|
DrawUtils::usedTVScale = 1.0f;
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Unknown tv width detected, config menu might not show properly");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawUtils::beginDraw() {
|
void DrawUtils::beginDraw() {
|
||||||
@ -83,17 +165,10 @@ void DrawUtils::drawPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t USED_TV_WIDTH = TV_WIDTH;
|
|
||||||
float scale = 1.5f;
|
|
||||||
if (DrawUtils::tvSize == 0x00FD2000) {
|
|
||||||
USED_TV_WIDTH = 1920;
|
|
||||||
scale = 2.25f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// scale and put pixel in the tv buffer
|
// scale and put pixel in the tv buffer
|
||||||
for (uint32_t yy = (y * scale); yy < ((y * scale) + (uint32_t) scale); yy++) {
|
for (uint32_t yy = (y * DrawUtils::usedTVScale); yy < ((y * DrawUtils::usedTVScale) + (uint32_t) DrawUtils::usedTVScale); yy++) {
|
||||||
for (uint32_t xx = (x * scale); xx < ((x * scale) + (uint32_t) scale); xx++) {
|
for (uint32_t xx = (x * DrawUtils::usedTVScale); xx < ((x * DrawUtils::usedTVScale) + (uint32_t) DrawUtils::usedTVScale); xx++) {
|
||||||
uint32_t i = (xx + yy * USED_TV_WIDTH) * 4;
|
uint32_t i = (xx + yy * DrawUtils::usedTVWidth) * 4;
|
||||||
if (i + 3 < tvSize / 2) {
|
if (i + 3 < tvSize / 2) {
|
||||||
if (isBackBuffer) {
|
if (isBackBuffer) {
|
||||||
i += tvSize / 2;
|
i += tvSize / 2;
|
||||||
|
@ -73,4 +73,6 @@ private:
|
|||||||
static uint32_t tvSize;
|
static uint32_t tvSize;
|
||||||
static uint8_t *drcBuffer;
|
static uint8_t *drcBuffer;
|
||||||
static uint32_t drcSize;
|
static uint32_t drcSize;
|
||||||
|
static uint32_t usedTVWidth;
|
||||||
|
static float usedTVScale;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "utils/input/VPADInput.h"
|
#include "utils/input/VPADInput.h"
|
||||||
#include "utils/input/WPADInput.h"
|
#include "utils/input/WPADInput.h"
|
||||||
|
|
||||||
|
#include <avm/tv.h>
|
||||||
#include <coreinit/screen.h>
|
#include <coreinit/screen.h>
|
||||||
#include <gx2/display.h>
|
#include <gx2/display.h>
|
||||||
#include <memory/mappedmemory.h>
|
#include <memory/mappedmemory.h>
|
||||||
@ -225,12 +226,42 @@ void ConfigUtils::displayMenu() {
|
|||||||
WUPSConfigAPIBackend::Intern::CleanAllHandles();
|
WUPSConfigAPIBackend::Intern::CleanAllHandles();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __SetDCPitchReg ((void (*)(uint32_t, uint32_t))(0x101C400 + 0x1e714))
|
extern "C" uint32_t __OSPhysicalToEffectiveUncached(uint32_t);
|
||||||
|
|
||||||
|
static uint32_t __ReadReg32(uint32_t index) {
|
||||||
|
if (OSIsECOMode()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto regs = (uint32_t *) __OSPhysicalToEffectiveUncached(0xc200000);
|
||||||
|
return regs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __WriteReg32(uint32_t index, uint32_t val) {
|
||||||
|
if (OSIsECOMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto regs = (uint32_t *) __OSPhysicalToEffectiveUncached(0xc200000);
|
||||||
|
regs[index] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void (*real_GX2SetTVBuffer)(void *buffer, uint32_t buffer_size, int32_t tv_render_mode, GX2SurfaceFormat format, GX2BufferingMode buffering_mode);
|
||||||
|
extern "C" void (*real_GX2SetDRCBuffer)(void *buffer, uint32_t buffer_size, uint32_t drc_mode, GX2SurfaceFormat surface_format, GX2BufferingMode buffering_mode);
|
||||||
|
|
||||||
void ConfigUtils::openConfigMenu() {
|
void ConfigUtils::openConfigMenu() {
|
||||||
gOnlyAcceptFromThread = OSGetCurrentThread();
|
gOnlyAcceptFromThread = OSGetCurrentThread();
|
||||||
bool wasHomeButtonMenuEnabled = OSIsHomeButtonMenuEnabled();
|
bool wasHomeButtonMenuEnabled = OSIsHomeButtonMenuEnabled();
|
||||||
|
|
||||||
|
// Save copy of DC reg values
|
||||||
|
auto tvRender1 = __ReadReg32(0x1841 + SCREEN_TV * 0x200);
|
||||||
|
auto tvRender2 = __ReadReg32(0x1840 + SCREEN_TV * 0x200);
|
||||||
|
auto tvPitch1 = __ReadReg32(0x1848 + SCREEN_TV * 0x200);
|
||||||
|
auto tvPitch2 = __ReadReg32(0x1866 + SCREEN_TV * 0x200);
|
||||||
|
auto drcRender1 = __ReadReg32(0x1841 + SCREEN_DRC * 0x200);
|
||||||
|
auto drcRender2 = __ReadReg32(0x1840 + SCREEN_DRC * 0x200);
|
||||||
|
auto drcPitch1 = __ReadReg32(0x1848 + SCREEN_DRC * 0x200);
|
||||||
|
auto drcPitch2 = __ReadReg32(0x1866 + SCREEN_DRC * 0x200);
|
||||||
|
|
||||||
OSScreenInit();
|
OSScreenInit();
|
||||||
|
|
||||||
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
|
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
|
||||||
@ -238,11 +269,6 @@ void ConfigUtils::openConfigMenu() {
|
|||||||
void *screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
|
void *screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
|
||||||
void *screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
|
void *screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
|
||||||
|
|
||||||
// Fix the TV buffer pitch if a 1080p buffer is used.
|
|
||||||
if (screen_buf0_size == 0x00FD2000) {
|
|
||||||
__SetDCPitchReg(SCREEN_TV, 1920);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool skipScreen0Free = false;
|
bool skipScreen0Free = false;
|
||||||
bool skipScreen1Free = false;
|
bool skipScreen1Free = false;
|
||||||
bool doShutdownKPAD = false;
|
bool doShutdownKPAD = false;
|
||||||
@ -271,8 +297,13 @@ void ConfigUtils::openConfigMenu() {
|
|||||||
OSScreenSetBufferEx(SCREEN_TV, screenbuffer0);
|
OSScreenSetBufferEx(SCREEN_TV, screenbuffer0);
|
||||||
OSScreenSetBufferEx(SCREEN_DRC, screenbuffer1);
|
OSScreenSetBufferEx(SCREEN_DRC, screenbuffer1);
|
||||||
|
|
||||||
OSScreenEnableEx(SCREEN_TV, 1);
|
// Clear screens
|
||||||
OSScreenEnableEx(SCREEN_DRC, 1);
|
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||||
|
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
||||||
|
|
||||||
|
// Flip buffers
|
||||||
|
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||||
|
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||||
|
|
||||||
// Clear screens
|
// Clear screens
|
||||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
OSScreenClearBufferEx(SCREEN_TV, 0);
|
||||||
@ -282,6 +313,9 @@ void ConfigUtils::openConfigMenu() {
|
|||||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
OSScreenFlipBuffersEx(SCREEN_TV);
|
||||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
OSScreenFlipBuffersEx(SCREEN_DRC);
|
||||||
|
|
||||||
|
OSScreenEnableEx(SCREEN_TV, 1);
|
||||||
|
OSScreenEnableEx(SCREEN_DRC, 1);
|
||||||
|
|
||||||
DrawUtils::initBuffers(screenbuffer0, screen_buf0_size, screenbuffer1, screen_buf1_size);
|
DrawUtils::initBuffers(screenbuffer0, screen_buf0_size, screenbuffer1, screen_buf1_size);
|
||||||
if (!DrawUtils::initFont()) {
|
if (!DrawUtils::initFont()) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to init Font");
|
DEBUG_FUNCTION_LINE_ERR("Failed to init Font");
|
||||||
@ -309,16 +343,17 @@ void ConfigUtils::openConfigMenu() {
|
|||||||
DrawUtils::deinitFont();
|
DrawUtils::deinitFont();
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
|
// Restore DC reg values
|
||||||
|
__WriteReg32(0x1841 + SCREEN_TV * 0x200, tvRender1);
|
||||||
|
__WriteReg32(0x1840 + SCREEN_TV * 0x200, tvRender2);
|
||||||
|
__WriteReg32(0x1848 + SCREEN_TV * 0x200, tvPitch1);
|
||||||
|
__WriteReg32(0x1866 + SCREEN_TV * 0x200, tvPitch2);
|
||||||
|
|
||||||
if (gStoredTVBuffer.buffer != nullptr) {
|
__WriteReg32(0x1841 + SCREEN_DRC * 0x200, drcRender1);
|
||||||
GX2SetTVBuffer(gStoredTVBuffer.buffer, gStoredTVBuffer.buffer_size, static_cast<GX2TVRenderMode>(gStoredTVBuffer.mode),
|
__WriteReg32(0x1840 + SCREEN_DRC * 0x200, drcRender2);
|
||||||
gStoredTVBuffer.surface_format, gStoredTVBuffer.buffering_mode);
|
__WriteReg32(0x1848 + SCREEN_DRC * 0x200, drcPitch1);
|
||||||
}
|
__WriteReg32(0x1866 + SCREEN_DRC * 0x200, drcPitch2);
|
||||||
|
|
||||||
if (gStoredDRCBuffer.buffer != nullptr) {
|
|
||||||
GX2SetDRCBuffer(gStoredDRCBuffer.buffer, gStoredDRCBuffer.buffer_size, static_cast<GX2DrcRenderMode>(gStoredDRCBuffer.mode),
|
|
||||||
gStoredDRCBuffer.surface_format, gStoredDRCBuffer.buffering_mode);
|
|
||||||
}
|
|
||||||
if (!skipScreen0Free && screenbuffer0) {
|
if (!skipScreen0Free && screenbuffer0) {
|
||||||
MEMFreeToMappedMemory(screenbuffer0);
|
MEMFreeToMappedMemory(screenbuffer0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user