Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix displaying the region free splash screen in 576i and 480i #32

Merged
merged 3 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ cmake-build-debug/
*.wps
*.elf
CMakeLists.txt
*.zip
2 changes: 1 addition & 1 deletion src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <coreinit/mcp.h>
#include <optional>

#define VERSION "v0.2.5"
#define VERSION "v0.2.6"
#define VERSION_FULL VERSION VERSION_EXTRA

enum Languages {
Expand Down
22 changes: 16 additions & 6 deletions src/utils/ConfigUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,6 @@ void ConfigUtils::displayMenu() {
int32_t curRegionIndex = region_map_to_index[curSelectedRegion];
int32_t curLangIndex = lang_map_to_index[curSelectedLanguage];

KPADInit();
WPADEnableURCC(true);

while (true) {
buttonsTriggered = 0;
buttonsReleased = 0;
Expand Down Expand Up @@ -325,9 +322,6 @@ void ConfigUtils::displayMenu() {
redraw = false;
}
}
KPADShutdown();
// This disconnects any Pro Controllers...
//WPADEnableURCC(false);

DrawUtils::beginDraw();
DrawUtils::clear(COLOR_BLACK);
Expand All @@ -341,6 +335,7 @@ void ConfigUtils::openConfigMenu() {
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
void *screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
void *screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
bool doShutdownKPAD = false;

if (!screenbuffer0 || !screenbuffer1) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffers");
Expand All @@ -367,8 +362,23 @@ void ConfigUtils::openConfigMenu() {
goto error_exit;
}


KPADStatus status;
KPADError err;
if (KPADReadEx(WPAD_CHAN_0, &status, 0, &err) == 0 && err == KPAD_ERROR_UNINITIALIZED) {
doShutdownKPAD = true;
KPADInit();
WPADEnableURCC(true);
}

displayMenu();

if (doShutdownKPAD) {
// This disconnects any Pro Controllers...
//WPADEnableURCC(false);
KPADShutdown();
}

DrawUtils::deinitFont();

error_exit:
Expand Down
97 changes: 81 additions & 16 deletions src/utils/DrawUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
#include "DrawUtils.h"
#include "dc.h"
#include "logger.h"
#include "utils.h"
#include <avm/config.h>
#include <coreinit/cache.h>
#include <coreinit/memory.h>
#include <coreinit/screen.h>
#include <cstdlib>
#include <png.h>

// buffer width
#define TV_WIDTH 0x500
#define DRC_WIDTH 0x380

bool DrawUtils::isBackBuffer;

uint8_t *DrawUtils::tvBuffer = nullptr;
uint32_t DrawUtils::tvSize = 0;
uint8_t *DrawUtils::drcBuffer = nullptr;
uint32_t DrawUtils::drcSize = 0;
static SFT pFont = {};
uint8_t *DrawUtils::tvBuffer = nullptr;
uint32_t DrawUtils::tvSize = 0;
uint8_t *DrawUtils::drcBuffer = nullptr;
uint32_t DrawUtils::drcSize = 0;
uint32_t DrawUtils::usedTVWidth = 0;
float DrawUtils::usedTVScale = 1.5f;
static SFT pFont = {};

static Color font_col(0xFFFFFFFF);

Expand All @@ -26,6 +29,75 @@ void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_,
DrawUtils::tvSize = tvSize_;
DrawUtils::drcBuffer = (uint8_t *) drcBuffer_;
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 = DCReadReg32(SCREEN_TV, D1GRPH_X_END_REG);

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() {
Expand Down Expand Up @@ -77,17 +149,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
for (uint32_t yy = (y * scale); yy < ((y * scale) + (uint32_t) scale); yy++) {
for (uint32_t xx = (x * scale); xx < ((x * scale) + (uint32_t) scale); xx++) {
uint32_t i = (xx + yy * USED_TV_WIDTH) * 4;
for (uint32_t yy = (y * DrawUtils::usedTVScale); yy < ((y * DrawUtils::usedTVScale) + (uint32_t) DrawUtils::usedTVScale); yy++) {
for (uint32_t xx = (x * DrawUtils::usedTVScale); xx < ((x * DrawUtils::usedTVScale) + (uint32_t) DrawUtils::usedTVScale); xx++) {
uint32_t i = (xx + yy * DrawUtils::usedTVWidth) * 4;
if (i + 3 < tvSize / 2) {
if (isBackBuffer) {
i += tvSize / 2;
Expand Down
2 changes: 2 additions & 0 deletions src/utils/DrawUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,6 @@ class DrawUtils {
static uint32_t tvSize;
static uint8_t *drcBuffer;
static uint32_t drcSize;
static uint32_t usedTVWidth;
static float usedTVScale;
};
35 changes: 35 additions & 0 deletions src/utils/dc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <coreinit/debug.h>
#include <coreinit/screen.h>

extern "C" uint32_t __OSPhysicalToEffectiveUncached(uint32_t);

static inline uint32_t DCReadReg32(OSScreenID screen, uint32_t index) {
if (OSIsECOMode()) {
return 0;
}
auto regs = (uint32_t *) __OSPhysicalToEffectiveUncached(0xc200000);
return regs[index + (screen * 0x200)];
}

static inline void DCWriteReg32(OSScreenID screen, uint32_t index, uint32_t val) {
if (OSIsECOMode()) {
return;
}
auto regs = (uint32_t *) __OSPhysicalToEffectiveUncached(0xc200000);
regs[index + (screen * 0x200)] = val;
}

// https://www.x.org/docs/AMD/old/42589_rv630_rrg_1.01o.pdf (reg id in document / 4)
#define D1GRPH_ENABLE_REG 0x1840
#define D1GRPH_CONTROL_REG 0x1841
#define D1GRPH_PITCH_REG 0x1848
#define D1OVL_PITCH_REG 0x1866
#define D1GRPH_X_END_REG 0x184d
#define D1GRPH_Y_END_REG 0x184e

static inline void SetDCPitchReg(OSScreenID screen, uint16_t pitch) {
DCWriteReg32(screen, D1GRPH_PITCH_REG, pitch);
DCWriteReg32(screen, D1OVL_PITCH_REG, pitch);
}