Skip to content

Commit

Permalink
Refactor DC register access
Browse files Browse the repository at this point in the history
  • Loading branch information
Maschell committed May 10, 2024
1 parent 6db59dc commit 4c1131b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 57 deletions.
25 changes: 7 additions & 18 deletions source/utils/DrawUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "DrawUtils.h"

#include "dc.h"
#include "logger.h"
#include "utils.h"
#include <avm/tv.h>
Expand All @@ -24,18 +25,6 @@ static SFT pFont = {};

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_) {
DrawUtils::tvBuffer = (uint8_t *) tvBuffer_;
DrawUtils::tvSize = tvSize_;
Expand Down Expand Up @@ -75,19 +64,19 @@ void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_,
}
}

auto tvScanBufferWidth = __ReadReg32(0x184d + SCREEN_TV * 0x200);
auto tvScanBufferWidth = DCReadReg32(SCREEN_TV, D1GRPH_X_END_REG);

if (tvScanBufferWidth == 640) { // 480i/480p/576i 4:3
DrawUtils::usedTVWidth = 640;
__SetDCPitchReg(SCREEN_TV, 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);
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);
SetDCPitchReg(SCREEN_TV, 1280);
if (bigScale) {
DrawUtils::usedTVScale = 1.5;
} else {
Expand All @@ -102,11 +91,11 @@ void DrawUtils::initBuffers(void *tvBuffer_, uint32_t tvSize_, void *drcBuffer_,
}
} else if (tvScanBufferWidth == 1920) { // 1080i/1080p 16:9
DrawUtils::usedTVWidth = 1920;
__SetDCPitchReg(SCREEN_TV, 1920);
SetDCPitchReg(SCREEN_TV, 1920);
DrawUtils::usedTVScale = bigScale ? 2.25 : 1.125f;
} else {
DrawUtils::usedTVWidth = tvScanBufferWidth;
__SetDCPitchReg(SCREEN_TV, tvScanBufferWidth);
SetDCPitchReg(SCREEN_TV, tvScanBufferWidth);
DrawUtils::usedTVScale = 1.0f;
DEBUG_FUNCTION_LINE_WARN("Unknown tv width detected, config menu might not show properly");
}
Expand Down
58 changes: 19 additions & 39 deletions source/utils/config/ConfigUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "ConfigUtils.h"
#include "../../globals.h"
#include "../DrawUtils.h"
#include "../dc.h"
#include "../logger.h"
#include "ConfigRenderer.h"
#include "config/WUPSConfigAPI.h"
Expand Down Expand Up @@ -236,41 +237,20 @@ void ConfigUtils::displayMenu() {
}
}

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() {
gOnlyAcceptFromThread = OSGetCurrentThread();
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);
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();

Expand Down Expand Up @@ -354,15 +334,15 @@ void ConfigUtils::openConfigMenu() {

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);

__WriteReg32(0x1841 + SCREEN_DRC * 0x200, drcRender1);
__WriteReg32(0x1840 + SCREEN_DRC * 0x200, drcRender2);
__WriteReg32(0x1848 + SCREEN_DRC * 0x200, drcPitch1);
__WriteReg32(0x1866 + SCREEN_DRC * 0x200, drcPitch2);
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);
Expand Down
36 changes: 36 additions & 0 deletions source/utils/dc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#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);
}

0 comments on commit 4c1131b

Please sign in to comment.