mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-06 11:07:18 -04:00
@@ -125,6 +125,7 @@ struct UserSettings {
|
||||
ConfigVar<int> shadowResolutionMultiplier;
|
||||
ConfigVar<bool> enableDepthOfField;
|
||||
ConfigVar<bool> enableMapBackground;
|
||||
ConfigVar<bool> disableCutscenePillarboxing;
|
||||
|
||||
// Audio
|
||||
ConfigVar<bool> noLowHpSound;
|
||||
|
||||
+80
-56
@@ -11234,6 +11234,62 @@ cXyz dCamera_c::Center() {
|
||||
return mCenter + mShake.field_0x24;
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
f32 get_target_trim_height(camera_process_class* i_this) {
|
||||
const auto camera = &i_this->mCamera;
|
||||
if (camera->mCurState != 2) {
|
||||
switch (camera->mTrimSize) {
|
||||
case 0:
|
||||
case 4:
|
||||
return 0.0f;
|
||||
case 1:
|
||||
return camera->mCamSetup.VistaTrimHeight();
|
||||
case 2:
|
||||
case 3:
|
||||
return camera->mCamSetup.CinemaScopeTrimHeight();
|
||||
default:
|
||||
return camera->mTrimHeight;
|
||||
}
|
||||
}
|
||||
return camera->mTrimHeight;
|
||||
}
|
||||
|
||||
void widezoom_correction(camera_process_class* i_this, float trim_height) {
|
||||
camera_class* camera = (camera_class*)i_this;
|
||||
dDlst_window_c* window = get_window(camera);
|
||||
view_port_class* viewport = window->getViewPort();
|
||||
|
||||
auto trim_width = 0.0f;
|
||||
|
||||
if (mDoGph_gInf_c::isWideZoom()) {
|
||||
const auto target_ar = FB_WIDTH_BASE / (FB_HEIGHT_BASE - trim_height * 2.0f);
|
||||
const auto target_ar_real =
|
||||
FB_WIDTH_BASE / (FB_HEIGHT_BASE - get_target_trim_height(i_this) * 2.0f);
|
||||
const auto current_ar = camera->view.aspect;
|
||||
|
||||
if (current_ar < target_ar) {
|
||||
trim_height = FB_HEIGHT_BASE / 2.0f * (1.0f - current_ar / target_ar);
|
||||
} else {
|
||||
trim_height = 0.0f;
|
||||
trim_width = FB_WIDTH_BASE / 2.0f * (1.0f - target_ar_real / current_ar);
|
||||
}
|
||||
|
||||
if (dusk::frame_interp::is_sim_frame()) {
|
||||
constexpr auto base_ar =
|
||||
static_cast<f32>(FB_WIDTH_BASE) / static_cast<f32>(FB_HEIGHT_BASE);
|
||||
const auto ar_corr = base_ar / std::min(current_ar, target_ar_real);
|
||||
camera->view.fovy =
|
||||
MTXRadToDeg(2.0f * atanf(tanf(MTXDegToRad(camera->view.fovy) * 0.5f) * ar_corr));
|
||||
}
|
||||
}
|
||||
|
||||
trim_width *= viewport->width / FB_WIDTH_BASE;
|
||||
trim_height *= viewport->height / FB_HEIGHT_BASE;
|
||||
window->setScissor(trim_width, trim_height, viewport->width - trim_width * 2.0f,
|
||||
viewport->height - trim_height * 2.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int camera_execute(camera_process_class* i_this) {
|
||||
preparation(i_this);
|
||||
|
||||
@@ -11254,6 +11310,28 @@ static int camera_execute(camera_process_class* i_this) {
|
||||
store(i_this);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
widezoom_correction(i_this, i_this->mCamera.TrimHeight());
|
||||
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
dusk::frame_interp::add_interpolation_callback([](bool _, void* pUserWork) {
|
||||
const auto i_this = static_cast<camera_process_class*>(pUserWork);
|
||||
const auto camera = &i_this->mCamera;
|
||||
|
||||
const auto trim_size = camera->mTrimSize;
|
||||
|
||||
if (camera->mCurState != 2 && trim_size >= 0 && trim_size <= 3) {
|
||||
// derive trim height at previous tick using current camera state
|
||||
const auto target = get_target_trim_height(i_this);
|
||||
const auto step = dusk::frame_interp::get_interpolation_step();
|
||||
const auto cur = camera->TrimHeight();
|
||||
const auto prev = (4.0f * cur - target) / 3.0f;
|
||||
const auto trim_height = prev + (cur - prev) * step;
|
||||
|
||||
widezoom_correction(i_this, trim_height);
|
||||
}
|
||||
}, i_this);
|
||||
}
|
||||
|
||||
// record new camera for our sim frame
|
||||
dusk::frame_interp::record_camera(i_this, get_camera_id(i_this));
|
||||
// interpolate the view now so that this sim frame's view matrix matches what
|
||||
@@ -11265,26 +11343,6 @@ static int camera_execute(camera_process_class* i_this) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
void set_ar_corrected_trim(dDlst_window_c* window, float trim_height) {
|
||||
const auto viewport = window->getViewPort();
|
||||
|
||||
if (mDoGph_gInf_c::isWideZoom()) {
|
||||
const auto target_ar = FB_WIDTH / (FB_HEIGHT - trim_height * 2.0f);
|
||||
const auto current_ar = mDoGph_gInf_c::m_safeWidthF / mDoGph_gInf_c::m_safeHeightF;
|
||||
|
||||
if (current_ar < target_ar) {
|
||||
trim_height = FB_HEIGHT / 2.0f * (1.0f - current_ar / target_ar);
|
||||
} else {
|
||||
trim_height = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
trim_height *= viewport->height / FB_HEIGHT;
|
||||
window->setScissor(0.0f, trim_height, viewport->width, viewport->height - trim_height * 2.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int camera_draw(camera_process_class* i_this) {
|
||||
camera_class* a_this = (camera_class*)i_this;
|
||||
dCamera_c* body = &i_this->mCamera;
|
||||
@@ -11337,42 +11395,8 @@ static int camera_draw(camera_process_class* i_this) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
set_ar_corrected_trim(window, body->TrimHeight());
|
||||
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
dusk::frame_interp::add_interpolation_callback([](bool _, void* pUserWork) {
|
||||
const auto i_this = static_cast<camera_process_class*>(pUserWork);
|
||||
const auto camera = &i_this->mCamera;
|
||||
|
||||
const auto trim_size = camera->mTrimSize;
|
||||
|
||||
if (camera->mCurState != 2 && trim_size >= 0 && trim_size <= 3) {
|
||||
// derive trim height at previous tick using current camera state
|
||||
f32 target;
|
||||
switch (trim_size) {
|
||||
case 0:
|
||||
target = 0.0f;
|
||||
break;
|
||||
case 1:
|
||||
target = camera->mCamSetup.VistaTrimHeight();
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
target = camera->mCamSetup.CinemaScopeTrimHeight();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto step = dusk::frame_interp::get_interpolation_step();
|
||||
const auto cur = camera->TrimHeight();
|
||||
const auto prev = (4.0f * cur - target) / 3.0f;
|
||||
const auto trim_height = prev + (cur - prev) * step;
|
||||
|
||||
set_ar_corrected_trim(get_window((camera_class*)i_this), trim_height);
|
||||
}
|
||||
}, i_this);
|
||||
}
|
||||
#else
|
||||
#if !TARGET_PC
|
||||
// trim handling moved to camera_execute for PC
|
||||
int trim_height = body->TrimHeight();
|
||||
|
||||
window->setScissor(0.0f, trim_height, FB_WIDTH, FB_HEIGHT - trim_height * 2.0f);
|
||||
|
||||
@@ -62,6 +62,7 @@ UserSettings g_userSettings = {
|
||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||
.enableDepthOfField {"game.enableDepthOfField", true},
|
||||
.enableMapBackground {"game.enableMapBackground", true},
|
||||
.disableCutscenePillarboxing {"game.disableCutscenePillarboxing", false},
|
||||
|
||||
// Audio
|
||||
.noLowHpSound {"game.noLowHpSound", false},
|
||||
@@ -184,6 +185,7 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.shadowResolutionMultiplier);
|
||||
Register(g_userSettings.game.enableDepthOfField);
|
||||
Register(g_userSettings.game.enableMapBackground);
|
||||
Register(g_userSettings.game.disableCutscenePillarboxing);
|
||||
Register(g_userSettings.game.enableFastIronBoots);
|
||||
Register(g_userSettings.game.canTransformAnywhere);
|
||||
Register(g_userSettings.game.freeMagicArmor);
|
||||
|
||||
@@ -738,6 +738,10 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
|
||||
{
|
||||
.key = "Enable Mini-Map Shadows",
|
||||
});
|
||||
config_bool_select(leftPane, rightPane, getSettings().game.disableCutscenePillarboxing,
|
||||
{
|
||||
.key = "Disable Cutscene Pillarboxing",
|
||||
});
|
||||
});
|
||||
|
||||
add_tab("Input", [this](Rml::Element* content) {
|
||||
|
||||
@@ -636,7 +636,7 @@ u8 mDoGph_gInf_c::isWide() {
|
||||
}
|
||||
|
||||
void mDoGph_gInf_c::setWideZoomProjection(Mtx44& m) {
|
||||
if (!isWideZoom()) {
|
||||
IF_NOT_DUSK(if (!isWideZoom())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -682,7 +682,7 @@ void mDoGph_gInf_c::setWideZoomProjection(Mtx44& m) {
|
||||
}
|
||||
|
||||
void mDoGph_gInf_c::setWideZoomLightProjection(Mtx& m) {
|
||||
if (!isWideZoom()) {
|
||||
IF_NOT_DUSK(if (!isWideZoom())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1189,14 +1189,24 @@ static void trimming(view_class* param_0, view_port_class* param_1) {
|
||||
ZoneScoped;
|
||||
UNUSED(param_0);
|
||||
|
||||
#if !TARGET_PC
|
||||
s16 y_orig = (int)param_1->y_orig & ~7;
|
||||
s16 y_orig_pos = y_orig < 0 ? 0 : y_orig;
|
||||
if ((y_orig_pos == 0) && (param_1->scissor.y_orig != param_1->y_orig ||
|
||||
(param_1->scissor.height != param_1->height)))
|
||||
#endif
|
||||
{
|
||||
#if TARGET_PC
|
||||
f32 sc_top = param_1->scissor.y_orig;
|
||||
f32 sc_bottom = param_1->scissor.y_orig + param_1->scissor.height;
|
||||
f32 sc_bottom = sc_top + param_1->scissor.height;
|
||||
|
||||
f32 sc_left = 0.0f;
|
||||
f32 sc_right = param_1->width;
|
||||
|
||||
if (!dusk::getSettings().game.disableCutscenePillarboxing) {
|
||||
sc_left = param_1->scissor.x_orig;
|
||||
sc_right = sc_left + param_1->scissor.width;
|
||||
}
|
||||
#else
|
||||
s32 sc_top = (int)param_1->scissor.y_orig;
|
||||
s32 sc_bottom = param_1->scissor.y_orig + param_1->scissor.height;
|
||||
@@ -1232,17 +1242,32 @@ static void trimming(view_class* param_0, view_port_class* param_1) {
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, DUSK_IF_ELSE(GX_F32, GX_RGBA4), 0);
|
||||
GXSetProjection(ortho, GX_ORTHOGRAPHIC);
|
||||
GXSetCurrentMtx(0);
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, 8);
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, DUSK_IF_ELSE(16, 8));
|
||||
|
||||
#if TARGET_PC
|
||||
// top trapezoid
|
||||
GXPosition3f32(0, 0, -5);
|
||||
GXPosition3f32(param_1->width, 0, -5);
|
||||
GXPosition3f32(param_1->width, sc_top, -5);
|
||||
GXPosition3f32(0, sc_top, -5);
|
||||
GXPosition3f32(0, sc_bottom, -5);
|
||||
GXPosition3f32(param_1->width, sc_bottom, -5);
|
||||
GXPosition3f32(sc_right, sc_top, -5);
|
||||
GXPosition3f32(sc_left, sc_top, -5);
|
||||
|
||||
// bottom trapezoid
|
||||
GXPosition3f32(sc_left, sc_bottom, -5);
|
||||
GXPosition3f32(sc_right, sc_bottom, -5);
|
||||
GXPosition3f32(param_1->width, param_1->height, -5);
|
||||
GXPosition3f32(0, param_1->height, -5);
|
||||
|
||||
// left trapezoid
|
||||
GXPosition3f32(0, 0, -5);
|
||||
GXPosition3f32(sc_left, sc_top, -5);
|
||||
GXPosition3f32(sc_left, sc_bottom, -5);
|
||||
GXPosition3f32(0, param_1->height, -5);
|
||||
|
||||
// right trapezoid
|
||||
GXPosition3f32(sc_right, sc_top, -5);
|
||||
GXPosition3f32(param_1->width, 0, -5);
|
||||
GXPosition3f32(param_1->width, param_1->height, -5);
|
||||
GXPosition3f32(sc_right, sc_bottom, -5);
|
||||
#else
|
||||
GXPosition3s16(0, 0, -5);
|
||||
GXPosition3s16(FB_WIDTH, 0, -5);
|
||||
|
||||
Reference in New Issue
Block a user