mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2025-02-27 22:30:01 +00:00
Compare commits
4 commits
02a774e4ff
...
332a45cd64
Author | SHA1 | Date | |
---|---|---|---|
|
332a45cd64 | ||
|
23eb6b7eea | ||
|
169155953e | ||
|
41e737249e |
19 changed files with 431 additions and 63 deletions
|
@ -72,7 +72,7 @@ Saving and loading files, going from place to place, and pausing all happen in t
|
|||
#### Linux and Steam Deck Support
|
||||
A Linux binary is available for playing on most up-to-date distros, including on the Steam Deck.
|
||||
|
||||
To play on Steam Deck, extract the Linux build onto your deck. Then, in desktop mode, right click the Zelda64Recompiled executable file and select "Add to Steam" as shown. From there, you can return to Gaming mode and configure the controls as needed. See the [Steam Deck gyro aim FAQ section](#how-do-i-set-up-gyro-aiming-on-steam-deck) for more detailed instructions.
|
||||
To play on Steam Deck, extract the Linux build onto your deck. Then, in desktop mode, right click the Zelda64Recompiled executable file and select "Add to Steam". From there, you can return to Gaming mode and configure the controls as needed. See the [Steam Deck gyro aim FAQ section](#how-do-i-set-up-gyro-aiming-on-steam-deck) for more detailed instructions.
|
||||
|
||||
## Planned Features
|
||||
* Dual analog control scheme (with analog camera)
|
||||
|
@ -108,7 +108,6 @@ You'll probably also want to change the default behavior so that you don't need
|
|||
If you want to play a modded ROM or in another language, note that support for modding and other languages will be added to the project itself in the future and will not rely on you supplying a different ROM.
|
||||
|
||||
## Known Issues
|
||||
* The motion blur effect used by the game was capped to prevent ghosting at incredibly high framerates, which causes it to be less noticeable (this is only really noticeable above 120FPS). This may be fixed in the future by offering the option to render to an HDR framebuffer internally, which would allow it to be uncapped.
|
||||
* Intel GPUs on Linux may not currently work. If you have experience with Vulkan development on Linux, help here would be greatly appreciated!
|
||||
* The prebuilt Linux binary may not work correctly on some distributions of Linux. If you encounter such an issue, building the project locally yourself is recommended. A Flatpak or AppImage may be provided in the future to solve this issue. Adding the Linux version to Steam and setting "Steam Linux Runtime" as the compatibility tool or launching it via Gamescope may work around the issue. Alternatively, running the Windows version with Proton is known to work well and may also work around this issue.
|
||||
* Overlays such as MSI Afterburner and other software such as Wallpaper Engine can cause performance issues with this project that prevent the game from rendering correctly. Disabling such software is recommended.
|
||||
|
|
|
@ -7,30 +7,47 @@
|
|||
<!-- Options -->
|
||||
<div class="config__wrapper" data-event-mouseout="set_cur_config_index(-1)">
|
||||
<div class="config-option" data-event-mouseover="set_cur_config_index(0)">
|
||||
<label class="config-option__title">Main Volume</label>
|
||||
<div class="config-option__range-wrapper config-option__list">
|
||||
<label class="config-option__range-label">{{main_volume}}%</label>
|
||||
<input
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(0)"
|
||||
class="nav-vert"
|
||||
id="main_volume_input"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
style="flex: 1; margin: 0dp; nav-up: #tab_sound; nav-down: #bgm_volume_input;"
|
||||
data-value="main_volume"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="config-option" data-event-mouseover="set_cur_config_index(1)">
|
||||
<label class="config-option__title">Background Music Volume</label>
|
||||
<div class="config-option__range-wrapper config-option__list">
|
||||
<label class="config-option__range-label">{{bgm_volume}}%</label>
|
||||
<input
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(0)"
|
||||
data-event-focus="set_cur_config_index(1)"
|
||||
class="nav-vert"
|
||||
id="bgm_volume_input"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
style="flex: 1; margin: 0dp; nav-up: #tab_sound; nav-down: #lhb_on;"
|
||||
style="flex: 1; margin: 0dp; nav-up: #main_volume_input; nav-down: #lhb_on;"
|
||||
data-value="bgm_volume"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="config-option" data-event-mouseover="set_cur_config_index(1)">
|
||||
<div class="config-option" data-event-mouseover="set_cur_config_index(2)">
|
||||
<label class="config-option__title">Low Health Beeps</label>
|
||||
<div class="config-option__list">
|
||||
<input
|
||||
type="radio"
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(1)"
|
||||
data-event-focus="set_cur_config_index(2)"
|
||||
name="lhb"
|
||||
data-checked="low_health_beeps_enabled"
|
||||
value="1"
|
||||
|
@ -42,7 +59,7 @@
|
|||
<input
|
||||
type="radio"
|
||||
data-event-blur="set_cur_config_index(-1)"
|
||||
data-event-focus="set_cur_config_index(1)"
|
||||
data-event-focus="set_cur_config_index(2)"
|
||||
name="lhb"
|
||||
data-checked="low_health_beeps_enabled"
|
||||
value="0"
|
||||
|
@ -55,10 +72,13 @@
|
|||
</div>
|
||||
<!-- Descriptions -->
|
||||
<div class="config__wrapper">
|
||||
<p data-if="cur_config_index == 0">
|
||||
<p data-if="cur_config_index == 0">
|
||||
Controls the main volume of the game.
|
||||
</p>
|
||||
<p data-if="cur_config_index == 1">
|
||||
Controls the overall volume of background music.
|
||||
</p>
|
||||
<p data-if="cur_config_index == 1">
|
||||
<p data-if="cur_config_index == 2">
|
||||
Toggles whether or not the low-health beeping sound plays.
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
namespace recomp {
|
||||
void reset_sound_settings();
|
||||
void set_main_volume(int volume);
|
||||
int get_main_volume();
|
||||
void set_bgm_volume(int volume);
|
||||
int get_bgm_volume();
|
||||
void set_low_health_beeps_enabled(bool enabled);
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace ultramodern {
|
|||
void shutdown();
|
||||
void set_dummy_vi();
|
||||
uint32_t get_display_framerate();
|
||||
float get_resolution_scale();
|
||||
void load_shader_cache(std::span<const char> cache_binary);
|
||||
private:
|
||||
RT64SetupResult setup_result;
|
||||
|
@ -40,6 +41,7 @@ namespace ultramodern {
|
|||
|
||||
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
|
||||
bool RT64SamplePositionsSupported();
|
||||
bool RT64HighPrecisionFBEnabled();
|
||||
}
|
||||
|
||||
void set_rt64_hooks();
|
||||
|
|
2
lib/rt64
2
lib/rt64
|
@ -1 +1 @@
|
|||
Subproject commit 1dd801264dbbf7a2f4e8fc483d28664852f50082
|
||||
Subproject commit 64b9e166f75b4dc44a59983b67c3e9ecc1f4cfd7
|
|
@ -98,11 +98,20 @@ void Play_DrawMotionBlur(PlayState* this) {
|
|||
f32 exponent = 20.0f / recomp_get_target_framerate(gFramerateDivisor);
|
||||
f32 alpha_float = recomp_powf(alpha / 255.0f, exponent);
|
||||
// Clamp the blur alpha, which ensures that the output color converges to within a reasonable delta of the target color
|
||||
// when using an R8G8B8A8 framebuffer as RT64 currently does. Although this makes the effect less noticeable at high framerates,
|
||||
// when using an R8G8B8A8 framebuffer. Although this makes the effect less noticeable at high framerates,
|
||||
// not clamping leads to noticeable image retention.
|
||||
alpha_float = MIN(alpha_float, 0.825f);
|
||||
// Skip clamping if high precision framebuffers are in use, as there's no risk of ghosting with those.
|
||||
if (!recomp_high_precision_fb_enabled()) {
|
||||
alpha_float = MIN(alpha_float, 0.825f);
|
||||
}
|
||||
alpha = (s32)(alpha_float * 255.0f);
|
||||
|
||||
// @recomp Set the dither noise strength based on the resolution scale to make it easier to see at higher resolutions.
|
||||
float res_scale = recomp_get_resolution_scale();
|
||||
float dither_noise_strength = CLAMP(1.0 + (res_scale - 1.0f) / 8.0f, 1.0f, 2.0f);
|
||||
// recomp_printf("res scale: %5.3f dither noise strength: %5.3f\n", res_scale, dither_noise_strength);
|
||||
gEXSetDitherNoiseStrength(OVERLAY_DISP++, dither_noise_strength);
|
||||
|
||||
if (sMotionBlurStatus == MOTION_BLUR_PROCESS) {
|
||||
func_80170AE0(&this->pauseBgPreRender, &gfx, alpha);
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "patches.h"
|
||||
#include "transform_ids.h"
|
||||
#include "overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h"
|
||||
#include "overlays/actors/ovl_Eff_Stk/z_eff_stk.h"
|
||||
#include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h"
|
||||
#include "z64effect.h"
|
||||
|
||||
|
@ -392,51 +391,6 @@ void Effect_DrawAll(GraphicsContext* gfxCtx) {
|
|||
}
|
||||
}
|
||||
|
||||
extern Gfx object_stk2_DL_008920[];
|
||||
extern Gfx object_stk2_DL_008A38[];
|
||||
extern AnimatedMaterial object_stk2_Matanimheader_009F60[];
|
||||
|
||||
void EffStk_Draw(Actor* thisx, PlayState* play) {
|
||||
EffStk* this = (EffStk*)thisx;
|
||||
s32 pad;
|
||||
Camera* activeCam = GET_ACTIVE_CAM(play);
|
||||
Vec3f eye = activeCam->eye;
|
||||
Vec3f quakeOffset;
|
||||
|
||||
quakeOffset = Camera_GetQuakeOffset(activeCam);
|
||||
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
||||
Matrix_Translate(eye.x + quakeOffset.x, eye.y + quakeOffset.y, eye.z + quakeOffset.z, MTXMODE_NEW);
|
||||
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Translate(0.0f, 0.0f, this->unk148, MTXMODE_APPLY);
|
||||
|
||||
Mtx* mtx = Matrix_NewMtx(play->state.gfxCtx);
|
||||
|
||||
// @recomp Tag the transform. Do not allow edits as this will get edited by the billboard detection and we'll want to skip position during a camera cut too.
|
||||
if (camera_was_skipped()) {
|
||||
gEXMatrixGroupDecomposedSkipPosRot(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
AnimatedMat_DrawAlphaStep(play, Lib_SegmentedToVirtual(object_stk2_Matanimheader_009F60), 1.0f, this->unk144);
|
||||
gDPSetColorDither(POLY_XLU_DISP++, G_CD_NOISE);
|
||||
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_NOISE);
|
||||
gSPDisplayList(POLY_XLU_DISP++, object_stk2_DL_008920);
|
||||
gSPDisplayList(POLY_XLU_DISP++, object_stk2_DL_008A38);
|
||||
|
||||
// @recomp Pop the transform tag.
|
||||
gEXPopMatrixGroup(POLY_XLU_DISP++, G_MTX_MODELVIEW);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ CLEAR_TAG_EFFECT_AVAILABLE,
|
||||
/* 0x01 */ CLEAR_TAG_EFFECT_DEBRIS,
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
|
||||
#include "overlays/actors/ovl_En_Fall/z_en_fall.h"
|
||||
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
||||
#include "overlays/gamestates/ovl_daytelop/z_daytelop.h"
|
||||
#include "z64shrink_window.h"
|
||||
|
||||
#define PAGE_BG_WIDTH (PAGE_BG_COLS * PAGE_BG_QUAD_WIDTH)
|
||||
#define PAGE_BG_HEIGHT (PAGE_BG_ROWS * PAGE_BG_QUAD_HEIGHT)
|
||||
|
@ -330,3 +332,47 @@ s32 DemoEffect_OverrideLimbDrawTimewarp(PlayState* play, SkelCurve* skelCurve, s
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* gamestate_relocate(void* addr, GameStateId id) {
|
||||
GameStateOverlay* ovl = &gGameStateOverlayTable[id];
|
||||
if ((uintptr_t)addr >= 0x80800000) {
|
||||
return (void*)((uintptr_t)addr -
|
||||
(intptr_t)((uintptr_t)ovl->vramStart - (uintptr_t)ovl->loadedRamAddr));
|
||||
}
|
||||
else {
|
||||
recomp_printf("Not an overlay address!: 0x%08X 0x%08X 0x%08X\n", (u32)addr, (u32)ovl->vramStart, (u32)ovl->loadedRamAddr);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
void DayTelop_Main(GameState* thisx);
|
||||
void DayTelop_Destroy(GameState* thisx);
|
||||
void DayTelop_Noop(DayTelopState* this);
|
||||
void DayTelop_LoadGraphics(DayTelopState* this);
|
||||
|
||||
// @recomp Increase the length of the "Dawn of the X Day" screen to account for faster loading.
|
||||
void DayTelop_Init(GameState* thisx) {
|
||||
DayTelopState* this = (DayTelopState*)thisx;
|
||||
|
||||
GameState_SetFramerateDivisor(&this->state, 1);
|
||||
Matrix_Init(&this->state);
|
||||
ShrinkWindow_Destroy();
|
||||
View_Init(&this->view, this->state.gfxCtx);
|
||||
// @recomp Manual relocation, TODO remove when automated.
|
||||
this->state.main = (GameStateFunc)gamestate_relocate(DayTelop_Main, GAMESTATE_DAYTELOP);
|
||||
this->state.destroy = (GameStateFunc)gamestate_relocate(DayTelop_Destroy, GAMESTATE_DAYTELOP);
|
||||
// @recomp Add 120 extra frames (2 seconds with a frame divisor of 1) to account for faster loading.
|
||||
this->transitionCountdown = 260;
|
||||
this->fadeInState = DAYTELOP_HOURSTEXT_OFF;
|
||||
|
||||
if (gSaveContext.save.day < 9) {
|
||||
if (gSaveContext.save.day == 0) {
|
||||
Sram_ClearFlagsAtDawnOfTheFirstDay();
|
||||
}
|
||||
Sram_IncrementDay();
|
||||
}
|
||||
|
||||
DayTelop_Noop(this);
|
||||
DayTelop_LoadGraphics(this);
|
||||
Audio_PlaySfx(NA_SE_OC_TELOP_IMPACT);
|
||||
}
|
||||
|
|
|
@ -5,5 +5,7 @@
|
|||
|
||||
DECLARE_FUNC(float, recomp_get_aspect_ratio, float);
|
||||
DECLARE_FUNC(s32, recomp_get_target_framerate, s32);
|
||||
DECLARE_FUNC(s32, recomp_high_precision_fb_enabled);
|
||||
DECLARE_FUNC(float, recomp_get_resolution_scale);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.h"
|
||||
#include "overlays/actors/ovl_Oceff_Wipe6/z_oceff_wipe6.h"
|
||||
#include "overlays/actors/ovl_Oceff_Wipe7/z_oceff_wipe7.h"
|
||||
#include "overlays/actors/ovl_Eff_Stk/z_eff_stk.h"
|
||||
#include "transform_ids.h"
|
||||
|
||||
// @recomp Custom verts to extend the effects past the camera so they cover any aspect ratio.
|
||||
Vtx time_override_verts[156] = {
|
||||
|
@ -779,6 +781,204 @@ Gfx healing_override_dl[] = {
|
|||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
Vtx skull_kid_curse_1_override_verts[52] = { // 008A38
|
||||
{{ {71, 23, 0}, 0, {614, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {121, 88, 500}, 0, {716, 0}, {255, 255, 255, 255} }},
|
||||
{{ {44, 61, 0}, 0, {819, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {46, 143, 500}, 0, {921, 0}, {255, 255, 255, 255} }},
|
||||
{{ {0, 75, 0}, 0, {1024, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-46, 143, 500}, 0, {1126, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-44, 61, 0}, 0, {1228, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-121, 88, 500}, 0, {1331, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-71, 23, 0}, 0, {1433, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-150, 0, 500}, 0, {1536, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-71, -23, 0}, 0, {1638, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-121, -88, 500}, 0, {1740, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-44, -61, 0}, 0, {1843, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-46, -143, 500}, 0, {1945, 0}, {255, 255, 255, 255} }},
|
||||
{{ {0, -75, 0}, 0, {2048, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {0, -75, 0}, 0, {0, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {46, -143, 500}, 0, {102, 0}, {255, 255, 255, 255} }},
|
||||
{{ {44, -61, 0}, 0, {204, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {121, -88, 500}, 0, {307, 0}, {255, 255, 255, 255} }},
|
||||
{{ {71, -23, 0}, 0, {409, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {150, 0, 500}, 0, {512, 0}, {255, 255, 255, 255} }},
|
||||
{{ {248, 0, 1080}, 0, {580, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {200, 146, 1080}, 0, {782, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {200, 146, 1080}, 0, {782, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {76, 237, 1080}, 0, {989, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {76, 237, 1080}, 0, {988, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-76, 237, 1080}, 0, {1193, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-76, 237, 1080}, 0, {1194, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-200, 146, 1080}, 0, {1397, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-200, 146, 1080}, 0, {1397, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-248, 0, 1080}, 0, {1604, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-248, 0, 1080}, 0, {1604, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-121, -88, 500}, 0, {1740, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-248, 0, 1080}, 0, {1604, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-200, -146, 1080}, 0, {1806, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-44, -61, 0}, 0, {1843, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-46, -143, 500}, 0, {1945, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-200, -146, 1080}, 0, {1806, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {-76, -237, 1080}, 0, {2013, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {0, -75, 0}, 0, {2048, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {46, -143, 500}, 0, {2150, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-76, -237, 1080}, 0, {2012, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {76, -237, 1080}, 0, {2217, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {44, -61, 0}, 0, {204, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {46, -143, 500}, 0, {102, 0}, {255, 255, 255, 255} }},
|
||||
{{ {121, -88, 500}, 0, {307, 0}, {255, 255, 255, 255} }},
|
||||
{{ {76, -237, 1080}, 0, {170, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {200, -146, 1080}, 0, {373, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {71, -23, 0}, 0, {409, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {150, 0, 500}, 0, {512, 0}, {255, 255, 255, 255} }},
|
||||
{{ {200, -146, 1080}, 0, {373, -1192}, {255, 255, 255, 255} }},
|
||||
{{ {248, 0, 1080}, 0, {580, -1192}, {255, 255, 255, 255} }},
|
||||
};
|
||||
|
||||
extern u64 object_stk2_Tex_008B50[];
|
||||
extern u64 object_stk2_Tex_008B50[];
|
||||
|
||||
|
||||
Gfx skull_kid_curse_1_override_dl[] = { // 008A38
|
||||
gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON),
|
||||
gsDPPipeSync(),
|
||||
gsDPSetCombineLERP(TEXEL1, PRIMITIVE, PRIM_LOD_FRAC, TEXEL0, TEXEL1, 0, PRIM_LOD_FRAC, TEXEL0, PRIMITIVE,
|
||||
ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, SHADE, 0),
|
||||
gsDPSetPrimColor(0, 0x80, 255, 255, 100, 255),
|
||||
gsDPSetEnvColor(255, 0, 150, 255),
|
||||
gsDPSetRenderMode(G_RM_PASS, G_RM_ZB_XLU_SURF2),
|
||||
gsDPSetTextureLUT(G_TT_NONE),
|
||||
gsDPLoadTextureBlock(object_stk2_Tex_008B50, G_IM_FMT_I, G_IM_SIZ_8b, 32, 64, 0, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, 5, 6, 1, 15),
|
||||
gsDPLoadMultiBlock(object_stk2_Tex_008B50, 0x0000, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 64, 0, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, 5, 6, 15, 14),
|
||||
gsSPDisplayList(0x08000000),
|
||||
gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_SHADING_SMOOTH),
|
||||
gsSPVertex(skull_kid_curse_1_override_verts + 0, 32, 0),
|
||||
gsSP2Triangles(0, 1, 2, 0, 2, 3, 4, 0),
|
||||
gsSP2Triangles(4, 5, 6, 0, 6, 7, 8, 0),
|
||||
gsSP2Triangles(8, 9, 10, 0, 10, 11, 12, 0),
|
||||
gsSP2Triangles(12, 13, 14, 0, 15, 16, 17, 0),
|
||||
gsSP2Triangles(17, 18, 19, 0, 19, 20, 0, 0),
|
||||
gsSP2Triangles(0, 20, 1, 0, 1, 20, 21, 0),
|
||||
gsSP2Triangles(1, 21, 22, 0, 2, 1, 3, 0),
|
||||
gsSP2Triangles(3, 1, 23, 0, 3, 23, 24, 0),
|
||||
gsSP2Triangles(4, 3, 5, 0, 5, 3, 25, 0),
|
||||
gsSP2Triangles(5, 25, 26, 0, 6, 5, 7, 0),
|
||||
gsSP2Triangles(7, 5, 27, 0, 7, 27, 28, 0),
|
||||
gsSP2Triangles(8, 7, 9, 0, 9, 7, 29, 0),
|
||||
gsSP2Triangles(9, 29, 30, 0, 10, 9, 11, 0),
|
||||
gsSP1Triangle(11, 9, 31, 0),
|
||||
gsSPVertex(skull_kid_curse_1_override_verts + 32, 20, 0),
|
||||
gsSP2Triangles(0, 1, 2, 0, 3, 0, 4, 0),
|
||||
gsSP2Triangles(4, 0, 5, 0, 4, 5, 6, 0),
|
||||
gsSP2Triangles(7, 4, 8, 0, 8, 4, 9, 0),
|
||||
gsSP2Triangles(8, 9, 10, 0, 11, 12, 13, 0),
|
||||
gsSP2Triangles(13, 12, 14, 0, 13, 14, 15, 0),
|
||||
gsSP2Triangles(16, 13, 17, 0, 17, 13, 18, 0),
|
||||
gsSP1Triangle(17, 18, 19, 0),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
Vtx skull_kid_curse_2_override_verts[52] = { // 008920
|
||||
{{ {86, -28, 0}, 0, {409, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {180, 0, 500}, 0, {512, 0}, {255, 255, 255, 255} }},
|
||||
{{ {86, 28, 0}, 0, {614, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {53, -73, 0}, 0, {204, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {146, -106, 500}, 0, {307, 0}, {255, 255, 255, 255} }},
|
||||
{{ {0, -90, 0}, 0, {0, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {56, -171, 500}, 0, {102, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-53, -73, 0}, 0, {1843, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-56, -171, 500}, 0, {1945, 0}, {255, 255, 255, 255} }},
|
||||
{{ {0, -90, 0}, 0, {2048, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-86, -28, 0}, 0, {1638, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-146, -106, 500}, 0, {1740, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-86, 28, 0}, 0, {1433, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-180, 0, 500}, 0, {1536, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-53, 73, 0}, 0, {1228, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-146, 106, 500}, 0, {1331, 0}, {255, 255, 255, 255} }},
|
||||
{{ {0, 90, 0}, 0, {1024, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-56, 171, 500}, 0, {1126, 0}, {255, 255, 255, 255} }},
|
||||
{{ {53, 73, 0}, 0, {819, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {56, 171, 500}, 0, {921, 0}, {255, 255, 255, 255} }},
|
||||
{{ {146, 106, 500}, 0, {716, 0}, {255, 255, 255, 255} }},
|
||||
{{ {218, -159, 1080}, 0, {359, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {269, 0, 1080}, 0, {562, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {84, -256, 1080}, 0, {152, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {218, -159, 1080}, 0, {359, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {56, -171, 500}, 0, {2150, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-84, -256, 1080}, 0, {1996, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {84, -256, 1080}, 0, {2201, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-218, -159, 1080}, 0, {1792, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-84, -256, 1080}, 0, {1995, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-269, 0, 1080}, 0, {1586, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-218, -159, 1080}, 0, {1791, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-180, 0, 500}, 0, {1536, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-146, 106, 500}, 0, {1331, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-218, 159, 1080}, 0, {1383, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-269, 0, 1080}, 0, {1586, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-53, 73, 0}, 0, {1228, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {-56, 171, 500}, 0, {1126, 0}, {255, 255, 255, 255} }},
|
||||
{{ {-84, 256, 1080}, 0, {1176, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-218, 159, 1080}, 0, {1383, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {0, 90, 0}, 0, {1024, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {56, 171, 500}, 0, {921, 0}, {255, 255, 255, 255} }},
|
||||
{{ {84, 256, 1080}, 0, {972, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {-84, 256, 1080}, 0, {1177, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {53, 73, 0}, 0, {819, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {146, 106, 500}, 0, {716, 0}, {255, 255, 255, 255} }},
|
||||
{{ {218, 159, 1080}, 0, {768, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {84, 256, 1080}, 0, {971, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {86, 28, 0}, 0, {614, 1024}, {255, 255, 255, 0} }},
|
||||
{{ {180, 0, 500}, 0, {512, 0}, {255, 255, 255, 255} }},
|
||||
{{ {269, 0, 1080}, 0, {562, -1185}, {255, 255, 255, 255} }},
|
||||
{{ {218, 159, 1080}, 0, {767, -1185}, {255, 255, 255, 255} }},
|
||||
};
|
||||
|
||||
extern u64 object_stk2_Tex_009750[];
|
||||
extern u64 object_stk2_Tex_009350[];
|
||||
|
||||
Gfx skull_kid_curse_2_override_dl[] = { // 008920
|
||||
gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON),
|
||||
gsDPPipeSync(),
|
||||
gsDPSetCombineLERP(TEXEL1, PRIMITIVE, PRIM_LOD_FRAC, TEXEL0, TEXEL1, 0, PRIM_LOD_FRAC, TEXEL0, PRIMITIVE,
|
||||
ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, SHADE, 0),
|
||||
gsDPSetPrimColor(0, 0x80, 0, 0, 255, 255),
|
||||
gsDPSetEnvColor(0, 220, 0, 255),
|
||||
gsDPSetRenderMode(G_RM_PASS, G_RM_AA_ZB_XLU_INTER2),
|
||||
gsDPSetTextureLUT(G_TT_NONE),
|
||||
gsDPLoadTextureBlock(object_stk2_Tex_009750, G_IM_FMT_I, G_IM_SIZ_8b, 32, 64, 0, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_MIRROR | G_TX_WRAP, 5, 6, 15, 14),
|
||||
gsDPLoadMultiBlock(object_stk2_Tex_009350, 0x0100, 1, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, 5, 5, 15, 1),
|
||||
gsSPDisplayList(0x09000000),
|
||||
gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_SHADING_SMOOTH),
|
||||
gsSPVertex(skull_kid_curse_2_override_verts + 0, 32, 0),
|
||||
gsSP2Triangles(0, 1, 2, 0, 3, 4, 0, 0),
|
||||
gsSP2Triangles(5, 6, 3, 0, 7, 8, 9, 0),
|
||||
gsSP2Triangles(10, 11, 7, 0, 12, 13, 10, 0),
|
||||
gsSP2Triangles(14, 15, 12, 0, 16, 17, 14, 0),
|
||||
gsSP2Triangles(18, 19, 16, 0, 2, 20, 18, 0),
|
||||
gsSP2Triangles(0, 4, 1, 0, 1, 4, 21, 0),
|
||||
gsSP2Triangles(1, 21, 22, 0, 3, 6, 4, 0),
|
||||
gsSP2Triangles(4, 6, 23, 0, 4, 23, 24, 0),
|
||||
gsSP2Triangles(9, 8, 25, 0, 25, 8, 26, 0),
|
||||
gsSP2Triangles(25, 26, 27, 0, 7, 11, 8, 0),
|
||||
gsSP2Triangles(8, 11, 28, 0, 8, 28, 29, 0),
|
||||
gsSP2Triangles(10, 13, 11, 0, 11, 13, 30, 0),
|
||||
gsSP2Triangles(11, 30, 31, 0, 12, 15, 13, 0),
|
||||
gsSPVertex(skull_kid_curse_2_override_verts + 32, 20, 0),
|
||||
gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0),
|
||||
gsSP2Triangles(4, 5, 1, 0, 1, 5, 6, 0),
|
||||
gsSP2Triangles(1, 6, 7, 0, 8, 9, 5, 0),
|
||||
gsSP2Triangles(5, 9, 10, 0, 5, 10, 11, 0),
|
||||
gsSP2Triangles(12, 13, 9, 0, 9, 13, 14, 0),
|
||||
gsSP2Triangles(9, 14, 15, 0, 16, 17, 13, 0),
|
||||
gsSP2Triangles(13, 17, 18, 0, 13, 18, 19, 0),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
||||
// Sets the flag to 1 for any vertex that has an alpha of 255.
|
||||
void set_vertex_flags(Vtx* verts, s32 count) {
|
||||
for (s32 i = 0; i < count; i++) {
|
||||
|
@ -1249,3 +1449,48 @@ void OceffWipe7_Draw(Actor* thisx, PlayState* play) {
|
|||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
||||
extern AnimatedMaterial object_stk2_Matanimheader_009F60[];
|
||||
|
||||
// @recomp Patch the Skull Kid curse effect as well, which works similarly to the ocarina effects.
|
||||
// In this case, the patch also includes effect transform tagging patches.
|
||||
void EffStk_Draw(Actor* thisx, PlayState* play) {
|
||||
EffStk* this = (EffStk*)thisx;
|
||||
s32 pad;
|
||||
Camera* activeCam = GET_ACTIVE_CAM(play);
|
||||
Vec3f eye = activeCam->eye;
|
||||
Vec3f quakeOffset;
|
||||
|
||||
quakeOffset = Camera_GetQuakeOffset(activeCam);
|
||||
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
||||
Matrix_Translate(eye.x + quakeOffset.x, eye.y + quakeOffset.y, eye.z + quakeOffset.z, MTXMODE_NEW);
|
||||
Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Translate(0.0f, 0.0f, this->unk148, MTXMODE_APPLY);
|
||||
|
||||
Mtx* mtx = Matrix_NewMtx(play->state.gfxCtx);
|
||||
|
||||
// @recomp Tag the transform. Do not allow edits as this will get edited by the billboard detection and we'll want to skip position during a camera cut too.
|
||||
if (camera_was_skipped()) {
|
||||
gEXMatrixGroupDecomposedSkipPosRot(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
else {
|
||||
gEXMatrixGroupDecomposedNormal(POLY_XLU_DISP++, actor_transform_id(thisx), G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE);
|
||||
}
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
AnimatedMat_DrawAlphaStep(play, Lib_SegmentedToVirtual(object_stk2_Matanimheader_009F60), 1.0f, this->unk144);
|
||||
gDPSetColorDither(POLY_XLU_DISP++, G_CD_NOISE);
|
||||
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_NOISE);
|
||||
// @recomp Use the new DLs instead of the originals.
|
||||
gSPDisplayList(POLY_XLU_DISP++, skull_kid_curse_2_override_dl);
|
||||
gSPDisplayList(POLY_XLU_DISP++, skull_kid_curse_1_override_dl);
|
||||
|
||||
// @recomp Pop the transform tag.
|
||||
gEXPopMatrixGroup(POLY_XLU_DISP++, G_MTX_MODELVIEW);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
|
|
|
@ -52,3 +52,5 @@ osGetTime_recomp = 0x8F000088;
|
|||
recomp_autosave_enabled = 0x8F00008C;
|
||||
recomp_load_overlays = 0x8F000090;
|
||||
osInvalICache_recomp = 0x8F000094;
|
||||
recomp_high_precision_fb_enabled = 0x8F0000A8;
|
||||
recomp_get_resolution_scale = 0x8F0000AC;
|
||||
|
|
|
@ -24,6 +24,7 @@ constexpr auto api_default = ultramodern::GraphicsApi::Auto;
|
|||
constexpr auto ar_default = RT64::UserConfiguration::AspectRatio::Expand;
|
||||
constexpr auto msaa_default = RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||
constexpr auto rr_default = RT64::UserConfiguration::RefreshRate::Display;
|
||||
constexpr auto hpfb_default = ultramodern::HighPrecisionFramebuffer::Auto;
|
||||
constexpr int ds_default = 1;
|
||||
constexpr int rr_manual_default = 60;
|
||||
constexpr bool developer_mode_default = false;
|
||||
|
@ -93,6 +94,7 @@ namespace ultramodern {
|
|||
{"ar_option", config.ar_option},
|
||||
{"msaa_option", config.msaa_option},
|
||||
{"rr_option", config.rr_option},
|
||||
{"hpfb_option", config.hpfb_option},
|
||||
{"rr_manual_value", config.rr_manual_value},
|
||||
{"developer_mode", config.developer_mode},
|
||||
};
|
||||
|
@ -107,6 +109,7 @@ namespace ultramodern {
|
|||
config.ar_option = from_or_default(j, "ar_option", ar_default);
|
||||
config.msaa_option = from_or_default(j, "msaa_option", msaa_default);
|
||||
config.rr_option = from_or_default(j, "rr_option", rr_default);
|
||||
config.hpfb_option = from_or_default(j, "hpfb_option", hpfb_default);
|
||||
config.rr_manual_value = from_or_default(j, "rr_manual_value", rr_manual_default);
|
||||
config.developer_mode = from_or_default(j, "developer_mode", developer_mode_default);
|
||||
}
|
||||
|
@ -245,6 +248,7 @@ void reset_graphics_options() {
|
|||
new_config.ar_option = ar_default;
|
||||
new_config.msaa_option = msaa_default;
|
||||
new_config.rr_option = rr_default;
|
||||
new_config.hpfb_option = hpfb_default;
|
||||
new_config.rr_manual_value = rr_manual_default;
|
||||
new_config.developer_mode = developer_mode_default;
|
||||
ultramodern::set_graphics_config(new_config);
|
||||
|
@ -344,6 +348,7 @@ void load_controls_config(const std::filesystem::path& path) {
|
|||
void save_sound_config(const std::filesystem::path& path) {
|
||||
nlohmann::json config_json{};
|
||||
|
||||
config_json["main_volume"] = recomp::get_main_volume();
|
||||
config_json["bgm_volume"] = recomp::get_bgm_volume();
|
||||
config_json["low_health_beeps"] = recomp::get_low_health_beeps_enabled();
|
||||
|
||||
|
@ -357,8 +362,8 @@ void load_sound_config(const std::filesystem::path& path) {
|
|||
|
||||
config_file >> config_json;
|
||||
|
||||
|
||||
recomp::reset_sound_settings();
|
||||
call_if_key_exists(recomp::set_main_volume, config_json, "main_volume");
|
||||
call_if_key_exists(recomp::set_bgm_volume, config_json, "bgm_volume");
|
||||
call_if_key_exists(recomp::set_low_health_beeps_enabled, config_json, "low_health_beeps");
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "recomp_ui.h"
|
||||
#include "recomp_sound.h"
|
||||
#include "recomp_helpers.h"
|
||||
#include "rt64_layer.h"
|
||||
#include "../patches/input.h"
|
||||
#include "../patches/graphics.h"
|
||||
#include "../patches/sound.h"
|
||||
|
@ -78,7 +79,6 @@ extern "C" void recomp_get_targeting_mode(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return(ctx, static_cast<int>(recomp::get_targeting_mode()));
|
||||
}
|
||||
|
||||
|
||||
extern "C" void recomp_get_bgm_volume(uint8_t* rdram, recomp_context* ctx) {
|
||||
_return(ctx, recomp::get_bgm_volume() / 100.0f);
|
||||
}
|
||||
|
@ -102,3 +102,11 @@ extern "C" void recomp_load_overlays(uint8_t * rdram, recomp_context * ctx) {
|
|||
|
||||
load_overlays(rom, ram, size);
|
||||
}
|
||||
|
||||
extern "C" void recomp_high_precision_fb_enabled(uint8_t * rdram, recomp_context * ctx) {
|
||||
_return(ctx, static_cast<s32>(ultramodern::RT64HighPrecisionFBEnabled()));
|
||||
}
|
||||
|
||||
extern "C" void recomp_get_resolution_scale(uint8_t* rdram, recomp_context* ctx) {
|
||||
_return(ctx, ultramodern::get_resolution_scale());
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "recomp_input.h"
|
||||
#include "recomp_config.h"
|
||||
#include "recomp_game.h"
|
||||
#include "recomp_sound.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
@ -191,9 +192,10 @@ void queue_samples(int16_t* audio_data, size_t sample_count) {
|
|||
|
||||
// Convert the audio from 16-bit values to floats and swap the audio channels into the
|
||||
// swap buffer to correct for the address xor caused by endianness handling.
|
||||
float cur_main_volume = recomp::get_main_volume() / 100.0f; // Get the current main volume, normalized to 0.0-1.0.
|
||||
for (size_t i = 0; i < sample_count; i += input_channels) {
|
||||
swap_buffer[i + 0 + duplicated_input_frames * input_channels] = audio_data[i + 1] * (0.5f / 32768.0f);
|
||||
swap_buffer[i + 1 + duplicated_input_frames * input_channels] = audio_data[i + 0] * (0.5f / 32768.0f);
|
||||
swap_buffer[i + 0 + duplicated_input_frames * input_channels] = audio_data[i + 1] * (0.5f / 32768.0f) * cur_main_volume;
|
||||
swap_buffer[i + 1 + duplicated_input_frames * input_channels] = audio_data[i + 0] * (0.5f / 32768.0f) * cur_main_volume;
|
||||
}
|
||||
|
||||
// TODO handle cases where a chunk is smaller than the duplicated frame count.
|
||||
|
|
|
@ -354,10 +354,12 @@ void recomp::set_autosave_mode(recomp::AutosaveMode mode) {
|
|||
}
|
||||
|
||||
struct SoundOptionsContext {
|
||||
std::atomic<int> main_volume; // Option to control the volume of all sound
|
||||
std::atomic<int> bgm_volume;
|
||||
std::atomic<int> low_health_beeps_enabled; // RmlUi doesn't seem to like "true"/"false" strings for setting variants so an int is used here instead.
|
||||
void reset() {
|
||||
bgm_volume = 100;
|
||||
main_volume = 100;
|
||||
low_health_beeps_enabled = (int)true;
|
||||
}
|
||||
SoundOptionsContext() {
|
||||
|
@ -374,6 +376,17 @@ void recomp::reset_sound_settings() {
|
|||
}
|
||||
}
|
||||
|
||||
void recomp::set_main_volume(int volume) {
|
||||
sound_options_context.main_volume.store(volume);
|
||||
if (sound_options_model_handle) {
|
||||
sound_options_model_handle.DirtyVariable("main_volume");
|
||||
}
|
||||
}
|
||||
|
||||
int recomp::get_main_volume() {
|
||||
return sound_options_context.main_volume.load();
|
||||
}
|
||||
|
||||
void recomp::set_bgm_volume(int volume) {
|
||||
sound_options_context.bgm_volume.store(volume);
|
||||
if (sound_options_model_handle) {
|
||||
|
@ -852,6 +865,7 @@ public:
|
|||
|
||||
sound_options_model_handle = constructor.GetModelHandle();
|
||||
|
||||
bind_atomic(constructor, sound_options_model_handle, "main_volume", &sound_options_context.main_volume);
|
||||
bind_atomic(constructor, sound_options_model_handle, "bgm_volume", &sound_options_context.bgm_volume);
|
||||
bind_atomic(constructor, sound_options_model_handle, "low_health_beeps_enabled", &sound_options_context.low_health_beeps_enabled);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@ namespace ultramodern {
|
|||
Vulkan,
|
||||
OptionCount
|
||||
};
|
||||
enum class HighPrecisionFramebuffer {
|
||||
Auto,
|
||||
On,
|
||||
Off,
|
||||
OptionCount
|
||||
};
|
||||
|
||||
struct GraphicsConfig {
|
||||
Resolution res_option;
|
||||
|
@ -36,6 +42,7 @@ namespace ultramodern {
|
|||
RT64::UserConfiguration::AspectRatio ar_option;
|
||||
RT64::UserConfiguration::Antialiasing msaa_option;
|
||||
RT64::UserConfiguration::RefreshRate rr_option;
|
||||
HighPrecisionFramebuffer hpfb_option;
|
||||
int rr_manual_value;
|
||||
int ds_option;
|
||||
bool developer_mode;
|
||||
|
@ -68,6 +75,12 @@ namespace ultramodern {
|
|||
{ultramodern::GraphicsApi::D3D12, "D3D12"},
|
||||
{ultramodern::GraphicsApi::Vulkan, "Vulkan"},
|
||||
});
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::HighPrecisionFramebuffer, {
|
||||
{ultramodern::HighPrecisionFramebuffer::Auto, "Auto"},
|
||||
{ultramodern::HighPrecisionFramebuffer::On, "On"},
|
||||
{ultramodern::HighPrecisionFramebuffer::Off, "Off"},
|
||||
});
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -279,6 +279,7 @@ ultramodern::GraphicsConfig ultramodern::get_graphics_config() {
|
|||
}
|
||||
|
||||
std::atomic_uint32_t display_refresh_rate = 60;
|
||||
std::atomic<float> resolution_scale = 1.0f;
|
||||
|
||||
uint32_t ultramodern::get_target_framerate(uint32_t original) {
|
||||
ultramodern::GraphicsConfig graphics_config = ultramodern::get_graphics_config();
|
||||
|
@ -298,6 +299,10 @@ uint32_t ultramodern::get_display_refresh_rate() {
|
|||
return display_refresh_rate.load();
|
||||
}
|
||||
|
||||
float ultramodern::get_resolution_scale() {
|
||||
return resolution_scale.load();
|
||||
}
|
||||
|
||||
void ultramodern::load_shader_cache(std::span<const char> cache_data) {
|
||||
events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data});
|
||||
}
|
||||
|
@ -359,6 +364,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re
|
|||
events_context.vi.current_buffer = events_context.vi.next_buffer;
|
||||
rt64.update_screen(swap_action->origin);
|
||||
display_refresh_rate = rt64.get_display_framerate();
|
||||
resolution_scale = rt64.get_resolution_scale();
|
||||
}
|
||||
else if (const auto* config_action = std::get_if<UpdateConfigAction>(&action)) {
|
||||
ultramodern::GraphicsConfig new_config = cur_config;
|
||||
|
|
|
@ -11,6 +11,7 @@ ultramodern::RT64Context::~RT64Context() = default;
|
|||
|
||||
static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||
static bool sample_positions_supported = false;
|
||||
static bool high_precision_fb_enabled = false;
|
||||
|
||||
static uint8_t DMEM[0x1000];
|
||||
static uint8_t IMEM[0x1000];
|
||||
|
@ -58,6 +59,19 @@ RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampl
|
|||
return RT64::UserConfiguration::Antialiasing::None;
|
||||
}
|
||||
|
||||
RT64::UserConfiguration::InternalColorFormat to_rt64(ultramodern::HighPrecisionFramebuffer option) {
|
||||
switch (option) {
|
||||
case ultramodern::HighPrecisionFramebuffer::Off:
|
||||
return RT64::UserConfiguration::InternalColorFormat::Standard;
|
||||
case ultramodern::HighPrecisionFramebuffer::On:
|
||||
return RT64::UserConfiguration::InternalColorFormat::High;
|
||||
case ultramodern::HighPrecisionFramebuffer::Auto:
|
||||
return RT64::UserConfiguration::InternalColorFormat::Automatic;
|
||||
default:
|
||||
return RT64::UserConfiguration::InternalColorFormat::OptionCount;
|
||||
}
|
||||
}
|
||||
|
||||
void set_application_user_config(RT64::Application* application, const ultramodern::GraphicsConfig& config) {
|
||||
switch (config.res_option) {
|
||||
default:
|
||||
|
@ -95,6 +109,7 @@ void set_application_user_config(RT64::Application* application, const ultramode
|
|||
application->userConfig.antialiasing = config.msaa_option;
|
||||
application->userConfig.refreshRate = config.rr_option;
|
||||
application->userConfig.refreshRateTarget = config.rr_manual_value;
|
||||
application->userConfig.internalColorFormat = to_rt64(config.hpfb_option);
|
||||
}
|
||||
|
||||
ultramodern::RT64SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) {
|
||||
|
@ -216,6 +231,8 @@ ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle
|
|||
device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||
sample_positions_supported = false;
|
||||
}
|
||||
|
||||
high_precision_fb_enabled = app->shaderLibrary->usesHDR;
|
||||
}
|
||||
|
||||
void ultramodern::RT64Context::send_dl(const OSTask* task) {
|
||||
|
@ -261,6 +278,24 @@ uint32_t ultramodern::RT64Context::get_display_framerate() {
|
|||
return app->presentQueue->ext.sharedResources->swapChainRate;
|
||||
}
|
||||
|
||||
float ultramodern::RT64Context::get_resolution_scale() {
|
||||
constexpr int ReferenceHeight = 240;
|
||||
switch (app->userConfig.resolution) {
|
||||
case RT64::UserConfiguration::Resolution::WindowIntegerScale:
|
||||
if (app->sharedQueueResources->swapChainHeight > 0) {
|
||||
return std::max(float((app->sharedQueueResources->swapChainHeight + ReferenceHeight - 1) / ReferenceHeight), 1.0f);
|
||||
}
|
||||
else {
|
||||
return 1.0f;
|
||||
}
|
||||
case RT64::UserConfiguration::Resolution::Manual:
|
||||
return float(app->userConfig.resolutionMultiplier);
|
||||
case RT64::UserConfiguration::Resolution::Original:
|
||||
default:
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void ultramodern::RT64Context::load_shader_cache(std::span<const char> cache_binary) {
|
||||
// TODO figure out how to avoid a copy here.
|
||||
std::istringstream cache_stream{std::string{cache_binary.data(), cache_binary.size()}};
|
||||
|
@ -278,3 +313,7 @@ RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() {
|
|||
bool ultramodern::RT64SamplePositionsSupported() {
|
||||
return sample_positions_supported;
|
||||
}
|
||||
|
||||
bool ultramodern::RT64HighPrecisionFBEnabled() {
|
||||
return high_precision_fb_enabled;
|
||||
}
|
||||
|
|
|
@ -111,9 +111,9 @@ void sleep_milliseconds(uint32_t millis);
|
|||
void sleep_until(const std::chrono::high_resolution_clock::time_point& time_point);
|
||||
|
||||
// Graphics
|
||||
void get_window_size(uint32_t& width, uint32_t& height);
|
||||
uint32_t get_target_framerate(uint32_t original);
|
||||
uint32_t get_display_refresh_rate();
|
||||
float get_resolution_scale();
|
||||
void load_shader_cache(std::span<const char> cache_data);
|
||||
|
||||
// Audio
|
||||
|
|
Loading…
Add table
Reference in a new issue