Render simple safe mode screen

This commit is contained in:
Maschell
2024-08-09 19:43:11 +02:00
parent aa399bef0f
commit 89012aae29
6 changed files with 173 additions and 125 deletions

View File

@@ -1,6 +1,7 @@
#include "DrawUtils.h"
#include "dc.h"
#include "globals.h"
#include "logger.h"
#include "utils.h"
#include <avm/tv.h>
@@ -8,6 +9,8 @@
#include <coreinit/memory.h>
#include <coreinit/screen.h>
#include <cstdlib>
#include <memory/mappedmemory.h>
#include <padscore/kpad.h>
#include <png.h>
// buffer width
@@ -432,3 +435,121 @@ uint32_t DrawUtils::getTextWidth(const wchar_t *string) {
return width;
}
void DrawUtils::RenderScreen(const std::function<void()>& callback) {
gOnlyAcceptFromThread = OSGetCurrentThread();
bool wasHomeButtonMenuEnabled = OSIsHomeButtonMenuEnabled();
// Save copy of DC reg values
auto tvRender1 = DCReadReg32(SCREEN_TV, D1GRPH_CONTROL_REG);
auto tvRender2 = DCReadReg32(SCREEN_TV, D1GRPH_ENABLE_REG);
auto tvPitch1 = DCReadReg32(SCREEN_TV, D1GRPH_PITCH_REG);
auto tvPitch2 = DCReadReg32(SCREEN_TV, D1OVL_PITCH_REG);
auto drcRender1 = DCReadReg32(SCREEN_DRC, D1GRPH_CONTROL_REG);
auto drcRender2 = DCReadReg32(SCREEN_DRC, D1GRPH_ENABLE_REG);
auto drcPitch1 = DCReadReg32(SCREEN_DRC, D1GRPH_PITCH_REG);
auto drcPitch2 = DCReadReg32(SCREEN_DRC, D1OVL_PITCH_REG);
OSScreenInit();
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
void *screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
void *screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
bool skipScreen0Free = false;
bool skipScreen1Free = false;
bool doShutdownKPAD = false;
if (!screenbuffer0 || !screenbuffer1) {
if (screenbuffer0 == nullptr) {
if (gStoredTVBuffer.buffer_size >= screen_buf0_size) {
screenbuffer0 = gStoredTVBuffer.buffer;
skipScreen0Free = true;
DEBUG_FUNCTION_LINE_VERBOSE("Use storedTVBuffer");
}
}
if (screenbuffer1 == nullptr) {
if (gStoredDRCBuffer.buffer_size >= screen_buf1_size) {
screenbuffer1 = gStoredDRCBuffer.buffer;
skipScreen1Free = true;
DEBUG_FUNCTION_LINE_VERBOSE("Use storedDRCBuffer");
}
}
if (!screenbuffer0 || !screenbuffer1) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffers");
goto error_exit;
}
}
OSScreenSetBufferEx(SCREEN_TV, screenbuffer0);
OSScreenSetBufferEx(SCREEN_DRC, screenbuffer1);
// Clear screens
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
// Flip buffers
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
// Clear screens
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
// Flip buffers
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
OSScreenEnableEx(SCREEN_TV, 1);
OSScreenEnableEx(SCREEN_DRC, 1);
DrawUtils::initBuffers(screenbuffer0, screen_buf0_size, screenbuffer1, screen_buf1_size);
if (!DrawUtils::initFont()) {
DEBUG_FUNCTION_LINE_ERR("Failed to init Font");
goto error_exit;
}
// disable the home button menu to prevent opening it when exiting
OSEnableHomeButtonMenu(false);
KPADStatus status;
KPADError err;
if (KPADReadEx(WPAD_CHAN_0, &status, 0, &err) == 0 && err == KPAD_ERROR_UNINITIALIZED) {
doShutdownKPAD = true;
KPADInit();
}
callback();
if (doShutdownKPAD) {
KPADShutdown();
}
OSEnableHomeButtonMenu(wasHomeButtonMenuEnabled);
DrawUtils::deinitFont();
error_exit:
// Restore DC reg values
DCWriteReg32(SCREEN_TV, D1GRPH_CONTROL_REG, tvRender1);
DCWriteReg32(SCREEN_TV, D1GRPH_ENABLE_REG, tvRender2);
DCWriteReg32(SCREEN_TV, D1GRPH_PITCH_REG, tvPitch1);
DCWriteReg32(SCREEN_TV, D1OVL_PITCH_REG, tvPitch2);
DCWriteReg32(SCREEN_DRC, D1GRPH_CONTROL_REG, drcRender1);
DCWriteReg32(SCREEN_DRC, D1GRPH_ENABLE_REG, drcRender2);
DCWriteReg32(SCREEN_DRC, D1GRPH_PITCH_REG, drcPitch1);
DCWriteReg32(SCREEN_DRC, D1OVL_PITCH_REG, drcPitch2);
if (!skipScreen0Free && screenbuffer0) {
MEMFreeToMappedMemory(screenbuffer0);
}
if (!skipScreen1Free && screenbuffer1) {
MEMFreeToMappedMemory(screenbuffer1);
}
gOnlyAcceptFromThread = nullptr;
}

View File

@@ -2,11 +2,23 @@
#include "schrift.h"
#include <cstdint>
#include <functional>
// visible screen sizes
#define SCREEN_WIDTH 854
#define SCREEN_HEIGHT 480
#define COLOR_BACKGROUND Color(238, 238, 238, 255)
#define COLOR_BACKGROUND_WARN Color(255, 251, 4, 255)
#define COLOR_TEXT Color(51, 51, 51, 255)
#define COLOR_TEXT2 Color(72, 72, 72, 255)
#define COLOR_DISABLED Color(255, 0, 0, 255)
#define COLOR_BORDER Color(204, 204, 204, 255)
#define COLOR_BORDER_HIGHLIGHTED Color(0x3478e4FF)
#define COLOR_WHITE Color(0xFFFFFFFF)
#define COLOR_BLACK Color(0, 0, 0, 255)
#define COLOR_WARNING COLOR_BLACK
union Color {
explicit Color(const uint32_t color) {
this->color = color;
@@ -66,6 +78,8 @@ public:
static uint32_t getTextWidth(const wchar_t *string);
static void RenderScreen(const std::function<void()>& callback);
private:
static bool mIsBackBuffer;

View File

@@ -3,15 +3,6 @@
#include <cstdint>
#include <gx2/surface.h>
#define COLOR_BACKGROUND Color(238, 238, 238, 255)
#define COLOR_TEXT Color(51, 51, 51, 255)
#define COLOR_TEXT2 Color(72, 72, 72, 255)
#define COLOR_DISABLED Color(255, 0, 0, 255)
#define COLOR_BORDER Color(204, 204, 204, 255)
#define COLOR_BORDER_HIGHLIGHTED Color(0x3478e4FF)
#define COLOR_WHITE Color(0xFFFFFFFF)
#define COLOR_BLACK Color(0, 0, 0, 255)
#define MAX_BUTTONS_ON_SCREEN 8
struct StoredBuffer {

View File

@@ -151,6 +151,7 @@ ConfigSubState ConfigRenderer::UpdateStateMain(const Input &input) {
return SUB_STATE_RUNNING;
}
void ConfigRenderer::RenderStateMain() const {
auto &configs = GetConfigList();
@@ -212,7 +213,7 @@ void ConfigRenderer::RenderStateMain() const {
if (mSetActivePluginsMode) {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Activate | \uE045 Apply", true);
} else if (totalElementSize > 0) {
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Select", true);
DrawUtils::print(SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, "\ue000 Select | \uE002 Manage plugins", true);
}
// draw scroll indicator

View File

@@ -17,7 +17,6 @@
#include <algorithm>
#include <coreinit/title.h>
#include <globals.h>
#include <memory/mappedmemory.h>
#include <memory>
#include <sysapp/launch.h>
#include <vector>
@@ -275,120 +274,7 @@ void ConfigUtils::displayMenu() {
}
void ConfigUtils::openConfigMenu() {
gOnlyAcceptFromThread = OSGetCurrentThread();
const bool wasHomeButtonMenuEnabled = OSIsHomeButtonMenuEnabled();
// Save copy of DC reg values
const auto tvRender1 = DCReadReg32(SCREEN_TV, D1GRPH_CONTROL_REG);
const auto tvRender2 = DCReadReg32(SCREEN_TV, D1GRPH_ENABLE_REG);
const auto tvPitch1 = DCReadReg32(SCREEN_TV, D1GRPH_PITCH_REG);
const auto tvPitch2 = DCReadReg32(SCREEN_TV, D1OVL_PITCH_REG);
const auto drcRender1 = DCReadReg32(SCREEN_DRC, D1GRPH_CONTROL_REG);
const auto drcRender2 = DCReadReg32(SCREEN_DRC, D1GRPH_ENABLE_REG);
const auto drcPitch1 = DCReadReg32(SCREEN_DRC, D1GRPH_PITCH_REG);
const auto drcPitch2 = DCReadReg32(SCREEN_DRC, D1OVL_PITCH_REG);
OSScreenInit();
const uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
const uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
void *screenbuffer0 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf0_size, 0x100);
void *screenbuffer1 = MEMAllocFromMappedMemoryForGX2Ex(screen_buf1_size, 0x100);
bool skipScreen0Free = false;
bool skipScreen1Free = false;
bool doShutdownKPAD = false;
if (!screenbuffer0 || !screenbuffer1) {
if (screenbuffer0 == nullptr) {
if (gStoredTVBuffer.buffer_size >= screen_buf0_size) {
screenbuffer0 = gStoredTVBuffer.buffer;
skipScreen0Free = true;
DEBUG_FUNCTION_LINE_VERBOSE("Use storedTVBuffer");
}
}
if (screenbuffer1 == nullptr) {
if (gStoredDRCBuffer.buffer_size >= screen_buf1_size) {
screenbuffer1 = gStoredDRCBuffer.buffer;
skipScreen1Free = true;
DEBUG_FUNCTION_LINE_VERBOSE("Use storedDRCBuffer");
}
}
if (!screenbuffer0 || !screenbuffer1) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffers");
goto error_exit;
}
}
OSScreenSetBufferEx(SCREEN_TV, screenbuffer0);
OSScreenSetBufferEx(SCREEN_DRC, screenbuffer1);
// Clear screens
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
// Flip buffers
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
// Clear screens
OSScreenClearBufferEx(SCREEN_TV, 0);
OSScreenClearBufferEx(SCREEN_DRC, 0);
// Flip buffers
OSScreenFlipBuffersEx(SCREEN_TV);
OSScreenFlipBuffersEx(SCREEN_DRC);
OSScreenEnableEx(SCREEN_TV, 1);
OSScreenEnableEx(SCREEN_DRC, 1);
DrawUtils::initBuffers(screenbuffer0, screen_buf0_size, screenbuffer1, screen_buf1_size);
if (!DrawUtils::initFont()) {
DEBUG_FUNCTION_LINE_ERR("Failed to init Font");
goto error_exit;
}
// disable the home button menu to prevent opening it when exiting
OSEnableHomeButtonMenu(false);
KPADStatus status;
KPADError err;
if (KPADReadEx(WPAD_CHAN_0, &status, 0, &err) == 0 && err == KPAD_ERROR_UNINITIALIZED) {
doShutdownKPAD = true;
KPADInit();
}
displayMenu();
if (doShutdownKPAD) {
KPADShutdown();
}
OSEnableHomeButtonMenu(wasHomeButtonMenuEnabled);
DrawUtils::deinitFont();
error_exit:
// Restore DC reg values
DCWriteReg32(SCREEN_TV, D1GRPH_CONTROL_REG, tvRender1);
DCWriteReg32(SCREEN_TV, D1GRPH_ENABLE_REG, tvRender2);
DCWriteReg32(SCREEN_TV, D1GRPH_PITCH_REG, tvPitch1);
DCWriteReg32(SCREEN_TV, D1OVL_PITCH_REG, tvPitch2);
DCWriteReg32(SCREEN_DRC, D1GRPH_CONTROL_REG, drcRender1);
DCWriteReg32(SCREEN_DRC, D1GRPH_ENABLE_REG, drcRender2);
DCWriteReg32(SCREEN_DRC, D1GRPH_PITCH_REG, drcPitch1);
DCWriteReg32(SCREEN_DRC, D1OVL_PITCH_REG, drcPitch2);
if (!skipScreen0Free && screenbuffer0) {
MEMFreeToMappedMemory(screenbuffer0);
}
if (!skipScreen1Free && screenbuffer1) {
MEMFreeToMappedMemory(screenbuffer1);
}
gOnlyAcceptFromThread = nullptr;
DrawUtils::RenderScreen(&displayMenu);
}
void ConfigUtils::renderBasicScreen(std::string_view text) {