Compare commits

...

5 Commits

Author SHA1 Message Date
Skyth 5e2dafd7a0 Delay creation of textures. 2025-02-02 23:53:14 +03:00
Skyth (Asilkan) aaad10d797 Implement copy bypass optimization. (#262)
* Initial work on copy bypass optimization.

* Force depth stencil textures to be transient.

* Get rid of texture copying for shadow maps.

* Move barrier populate function.

* Set viewport/scissor rect explicitly for MSAA depth resolve.
2025-02-02 21:29:47 +03:00
Skyth (Asilkan) 342d696f99 Implement vertical marquee fade. (#261) 2025-02-02 20:09:19 +03:00
Hyper 0426b79094 config: update key bindings enum template 2025-02-02 15:51:16 +00:00
Hyper 3497d9b34b CTitleStateIntro_patches: fixed message inconsistencies (#259) 2025-02-01 13:37:48 +00:00
14 changed files with 643 additions and 374 deletions
+11 -10
View File
@@ -1,15 +1,16 @@
#pragma once #pragma once
#define IMGUI_SHADER_MODIFIER_NONE 0 #define IMGUI_SHADER_MODIFIER_NONE 0
#define IMGUI_SHADER_MODIFIER_SCANLINE 1 #define IMGUI_SHADER_MODIFIER_SCANLINE 1
#define IMGUI_SHADER_MODIFIER_CHECKERBOARD 2 #define IMGUI_SHADER_MODIFIER_CHECKERBOARD 2
#define IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON 3 #define IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON 3
#define IMGUI_SHADER_MODIFIER_TEXT_SKEW 4 #define IMGUI_SHADER_MODIFIER_TEXT_SKEW 4
#define IMGUI_SHADER_MODIFIER_MARQUEE_FADE 5 #define IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE 5
#define IMGUI_SHADER_MODIFIER_GRAYSCALE 6 #define IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE 6
#define IMGUI_SHADER_MODIFIER_TITLE_BEVEL 7 #define IMGUI_SHADER_MODIFIER_GRAYSCALE 7
#define IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL 8 #define IMGUI_SHADER_MODIFIER_TITLE_BEVEL 8
#define IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL 9 #define IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL 9
#define IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL 10
#ifdef __cplusplus #ifdef __cplusplus
+9 -1
View File
@@ -135,7 +135,7 @@ float4 main(in Interpolators interpolators) : SV_Target
} }
} }
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_MARQUEE_FADE) if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE)
{ {
float minAlpha = saturate((interpolators.Position.x - g_PushConstants.BoundsMin.x) / g_PushConstants.Scale.x); float minAlpha = saturate((interpolators.Position.x - g_PushConstants.BoundsMin.x) / g_PushConstants.Scale.x);
float maxAlpha = saturate((g_PushConstants.BoundsMax.x - interpolators.Position.x) / g_PushConstants.Scale.x); float maxAlpha = saturate((g_PushConstants.BoundsMax.x - interpolators.Position.x) / g_PushConstants.Scale.x);
@@ -143,6 +143,14 @@ float4 main(in Interpolators interpolators) : SV_Target
color.a *= minAlpha; color.a *= minAlpha;
color.a *= maxAlpha; color.a *= maxAlpha;
} }
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
{
float minAlpha = saturate((interpolators.Position.y - g_PushConstants.BoundsMin.y) / g_PushConstants.Scale.y);
float maxAlpha = saturate((g_PushConstants.BoundsMax.y - interpolators.Position.y) / g_PushConstants.Scale.y);
color.a *= minAlpha;
color.a *= maxAlpha;
}
else if (any(g_PushConstants.BoundsMin != g_PushConstants.BoundsMax)) else if (any(g_PushConstants.BoundsMin != g_PushConstants.BoundsMax))
{ {
float2 factor = saturate((interpolators.Position.xy - g_PushConstants.BoundsMin) / (g_PushConstants.BoundsMax - g_PushConstants.BoundsMin)); float2 factor = saturate((interpolators.Position.xy - g_PushConstants.BoundsMin) / (g_PushConstants.BoundsMax - g_PushConstants.BoundsMin));
+2 -1
View File
@@ -7,7 +7,8 @@ void main(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 colo
if (position.y < g_PushConstants.Origin.y) if (position.y < g_PushConstants.Origin.y)
position.x += g_PushConstants.Scale.x; position.x += g_PushConstants.Scale.x;
} }
else if (g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_MARQUEE_FADE) else if (g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE &&
g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
{ {
position.xy = g_PushConstants.Origin + (position.xy - g_PushConstants.Origin) * g_PushConstants.Scale; position.xy = g_PushConstants.Origin + (position.xy - g_PushConstants.Origin) * g_PushConstants.Scale;
} }
+409 -177
View File
@@ -155,11 +155,11 @@ static GuestSurface* g_renderTarget;
static GuestSurface* g_depthStencil; static GuestSurface* g_depthStencil;
static RenderFramebuffer* g_framebuffer; static RenderFramebuffer* g_framebuffer;
static RenderViewport g_viewport(0.0f, 0.0f, 1280.0f, 720.0f); static RenderViewport g_viewport(0.0f, 0.0f, 1280.0f, 720.0f);
static bool g_halfPixel = true;
static PipelineState g_pipelineState; static PipelineState g_pipelineState;
static int32_t g_depthBias; static int32_t g_depthBias;
static float g_slopeScaledDepthBias; static float g_slopeScaledDepthBias;
static SharedConstants g_sharedConstants; static SharedConstants g_sharedConstants;
static GuestTexture* g_textures[16];
static RenderSamplerDesc g_samplerDescs[16]; static RenderSamplerDesc g_samplerDescs[16];
static bool g_scissorTestEnable = false; static bool g_scissorTestEnable = false;
static RenderRect g_scissorRect; static RenderRect g_scissorRect;
@@ -563,7 +563,8 @@ static void DestructTempResources()
if (texture->mappedMemory != nullptr) if (texture->mappedMemory != nullptr)
g_userHeap.Free(texture->mappedMemory); g_userHeap.Free(texture->mappedMemory);
g_textureDescriptorAllocator.free(texture->descriptorIndex); if (texture->descriptorIndex != NULL)
g_textureDescriptorAllocator.free(texture->descriptorIndex);
if (texture->patchedTexture != nullptr) if (texture->patchedTexture != nullptr)
g_textureDescriptorAllocator.free(texture->patchedTexture->descriptorIndex); g_textureDescriptorAllocator.free(texture->patchedTexture->descriptorIndex);
@@ -681,6 +682,9 @@ enum class CsdFilterState
static CsdFilterState g_csdFilterState; static CsdFilterState g_csdFilterState;
static ankerl::unordered_dense::set<GuestSurface*> g_pendingSurfaceCopies;
static ankerl::unordered_dense::set<GuestSurface*> g_pendingMsaaResolves;
enum class RenderCommandType enum class RenderCommandType
{ {
SetRenderState, SetRenderState,
@@ -694,6 +698,7 @@ enum class RenderCommandType
StretchRect, StretchRect,
SetRenderTarget, SetRenderTarget,
SetDepthStencilSurface, SetDepthStencilSurface,
ExecutePendingStretchRectCommands,
Clear, Clear,
SetViewport, SetViewport,
SetTexture, SetTexture,
@@ -710,7 +715,7 @@ enum class RenderCommandType
SetVertexShader, SetVertexShader,
SetStreamSource, SetStreamSource,
SetIndices, SetIndices,
SetPixelShader SetPixelShader,
}; };
struct RenderCommand struct RenderCommand
@@ -1465,6 +1470,8 @@ static void BeginCommandList()
g_sharedConstants.textureCubeIndices[i] = TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE; g_sharedConstants.textureCubeIndices[i] = TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE;
} }
memset(g_textures, 0, sizeof(g_textures));
if (Config::GITextureFiltering == EGITextureFiltering::Bicubic) if (Config::GITextureFiltering == EGITextureFiltering::Bicubic)
g_pipelineState.specConstants |= SPEC_CONSTANT_BICUBIC_GI_FILTER; g_pipelineState.specConstants |= SPEC_CONSTANT_BICUBIC_GI_FILTER;
else else
@@ -2409,9 +2416,12 @@ static std::atomic<bool> g_executedCommandList;
void Video::Present() void Video::Present()
{ {
RenderCommand cmd;
cmd.type = RenderCommandType::ExecutePendingStretchRectCommands;
g_renderQueue.enqueue(cmd);
DrawImGui(); DrawImGui();
RenderCommand cmd;
cmd.type = RenderCommandType::ExecuteCommandList; cmd.type = RenderCommandType::ExecuteCommandList;
g_renderQueue.enqueue(cmd); g_renderQueue.enqueue(cmd);
@@ -2497,7 +2507,7 @@ static void SetRootDescriptor(const UploadAllocation& allocation, size_t index)
} }
static void ProcExecuteCommandList(const RenderCommand& cmd) static void ProcExecuteCommandList(const RenderCommand& cmd)
{ {
if (g_swapChainValid) if (g_swapChainValid)
{ {
auto swapChainTexture = g_swapChain->getTexture(g_backBufferIndex); auto swapChainTexture = g_swapChain->getTexture(g_backBufferIndex);
@@ -2693,56 +2703,65 @@ static RenderFormat ConvertFormat(uint32_t format)
} }
} }
static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t depth, uint32_t levels, uint32_t usage, uint32_t format, uint32_t pool, uint32_t type) void GuestTexture::CreateTexture()
{ {
const auto texture = g_userHeap.AllocPhysical<GuestTexture>(type == 17 ? ResourceType::VolumeTexture : ResourceType::Texture);
RenderTextureDesc desc; RenderTextureDesc desc;
desc.dimension = texture->type == ResourceType::VolumeTexture ? RenderTextureDimension::TEXTURE_3D : RenderTextureDimension::TEXTURE_2D; desc.dimension = type == ResourceType::VolumeTexture ? RenderTextureDimension::TEXTURE_3D : RenderTextureDimension::TEXTURE_2D;
desc.width = width; desc.width = width;
desc.height = height; desc.height = height;
desc.depth = depth; desc.depth = depth;
desc.mipLevels = levels; desc.mipLevels = levels;
desc.arraySize = 1; desc.arraySize = 1;
desc.format = ConvertFormat(format); desc.format = format;
desc.flags = (desc.format == RenderFormat::D32_FLOAT) ? RenderTextureFlag::DEPTH_TARGET : RenderTextureFlag::NONE; desc.flags = (desc.format == RenderFormat::D32_FLOAT) ? RenderTextureFlag::DEPTH_TARGET : RenderTextureFlag::NONE;
texture->textureHolder = g_device->createTexture(desc); textureHolder = g_device->createTexture(desc);
texture->texture = texture->textureHolder.get(); texture = textureHolder.get();
RenderTextureViewDesc viewDesc; RenderTextureViewDesc viewDesc;
viewDesc.format = desc.format; viewDesc.format = desc.format;
viewDesc.dimension = texture->type == ResourceType::VolumeTexture ? RenderTextureViewDimension::TEXTURE_3D : RenderTextureViewDimension::TEXTURE_2D; viewDesc.dimension = type == ResourceType::VolumeTexture ? RenderTextureViewDimension::TEXTURE_3D : RenderTextureViewDimension::TEXTURE_2D;
viewDesc.mipLevels = levels; viewDesc.mipLevels = levels;
textureView = texture->createTextureView(viewDesc);
viewDimension = viewDesc.dimension;
descriptorIndex = g_textureDescriptorAllocator.allocate();
g_textureDescriptorSet->setTexture(descriptorIndex, texture, RenderTextureLayout::SHADER_READ, textureView.get());
#ifdef _DEBUG
texture->setName(fmt::format("Texture {:X}", g_memory.MapVirtual(this)));
#endif
}
static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t depth, uint32_t levels, uint32_t usage, uint32_t format, uint32_t pool, uint32_t type)
{
const auto texture = g_userHeap.AllocPhysical<GuestTexture>(type == 17 ? ResourceType::VolumeTexture : ResourceType::Texture);
texture->width = width;
texture->height = height;
texture->depth = depth;
texture->levels = levels;
texture->format = ConvertFormat(format);
switch (format) switch (format)
{ {
case D3DFMT_D24FS8: case D3DFMT_D24FS8:
case D3DFMT_D24S8: case D3DFMT_D24S8:
case D3DFMT_L8: case D3DFMT_L8:
case D3DFMT_L8_2: case D3DFMT_L8_2:
viewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::ONE); texture->componentMapping = RenderComponentMapping(RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::ONE);
break; break;
case D3DFMT_X8R8G8B8: case D3DFMT_X8R8G8B8:
viewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::G, RenderSwizzle::B, RenderSwizzle::A, RenderSwizzle::ONE); texture->componentMapping = RenderComponentMapping(RenderSwizzle::G, RenderSwizzle::B, RenderSwizzle::A, RenderSwizzle::ONE);
break; break;
} }
texture->textureView = texture->texture->createTextureView(viewDesc); // Render targets/depth stencil textures are lazily created to have VRAM savings when the copy bypass optimization manages to work.
if (usage == 0)
texture->width = width; texture->CreateTexture();
texture->height = height;
texture->depth = depth;
texture->format = desc.format;
texture->viewDimension = viewDesc.dimension;
texture->descriptorIndex = g_textureDescriptorAllocator.allocate();
g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture, RenderTextureLayout::SHADER_READ, texture->textureView.get());
#ifdef _DEBUG
texture->texture->setName(fmt::format("Texture {:X}", g_memory.MapVirtual(texture)));
#endif
return texture; return texture;
} }
@@ -2795,16 +2814,13 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for
surface->guestFormat = format; surface->guestFormat = format;
surface->sampleCount = desc.multisampling.sampleCount; surface->sampleCount = desc.multisampling.sampleCount;
if (desc.multisampling.sampleCount != RenderSampleCount::COUNT_1 && desc.format == RenderFormat::D32_FLOAT) RenderTextureViewDesc viewDesc;
{ viewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D;
RenderTextureViewDesc viewDesc; viewDesc.format = desc.format;
viewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D; viewDesc.mipLevels = 1;
viewDesc.format = RenderFormat::D32_FLOAT; surface->textureView = surface->textureHolder->createTextureView(viewDesc);
viewDesc.mipLevels = 1; surface->descriptorIndex = g_textureDescriptorAllocator.allocate();
surface->textureView = surface->textureHolder->createTextureView(viewDesc); g_textureDescriptorSet->setTexture(surface->descriptorIndex, surface->textureHolder.get(), RenderTextureLayout::SHADER_READ, surface->textureView.get());
surface->descriptorIndex = g_textureDescriptorAllocator.allocate();
g_textureDescriptorSet->setTexture(surface->descriptorIndex, surface->textureHolder.get(), RenderTextureLayout::SHADER_READ, surface->textureView.get());
}
#ifdef _DEBUG #ifdef _DEBUG
surface->texture->setName(fmt::format("{} {:X}", desc.flags & RenderTextureFlag::RENDER_TARGET ? "Render Target" : "Depth Stencil", g_memory.MapVirtual(surface))); surface->texture->setName(fmt::format("{} {:X}", desc.flags & RenderTextureFlag::RENDER_TARGET ? "Render Target" : "Depth Stencil", g_memory.MapVirtual(surface)));
@@ -2820,11 +2836,8 @@ static void FlushViewport()
if (g_dirtyStates.viewport) if (g_dirtyStates.viewport)
{ {
auto viewport = g_viewport; auto viewport = g_viewport;
if (g_halfPixel) viewport.x += 0.5f;
{ viewport.y += 0.5f;
viewport.x += 0.5f;
viewport.y += 0.5f;
}
if (viewport.minDepth > viewport.maxDepth) if (viewport.minDepth > viewport.maxDepth)
std::swap(viewport.minDepth, viewport.maxDepth); std::swap(viewport.minDepth, viewport.maxDepth);
@@ -2848,13 +2861,6 @@ static void FlushViewport()
} }
} }
static bool SetHalfPixel(bool enable)
{
bool oldValue = g_halfPixel;
SetDirtyValue(g_dirtyStates.viewport, g_halfPixel, enable);
return oldValue;
}
static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestTexture* texture) static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestTexture* texture)
{ {
RenderCommand cmd; RenderCommand cmd;
@@ -2864,105 +2870,43 @@ static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestText
g_renderQueue.enqueue(cmd); g_renderQueue.enqueue(cmd);
} }
static void SetTextureInRenderThread(uint32_t index, GuestTexture* texture);
static void SetSurface(uint32_t index, GuestSurface* surface);
static void ProcStretchRect(const RenderCommand& cmd) static void ProcStretchRect(const RenderCommand& cmd)
{ {
const auto& args = cmd.stretchRect; const auto& args = cmd.stretchRect;
const bool isDepthStencil = (args.flags & 0x4) != 0; const bool isDepthStencil = (args.flags & 0x4) != 0;
const auto surface = isDepthStencil ? g_depthStencil : g_renderTarget; const auto surface = isDepthStencil ? g_depthStencil : g_renderTarget;
const bool multiSampling = surface->sampleCount != RenderSampleCount::COUNT_1;
RenderTextureLayout srcLayout; // Erase previous pending command so it doesn't cause the texture to be overriden.
RenderTextureLayout dstLayout; if (args.texture->sourceSurface != nullptr)
args.texture->sourceSurface->destinationTextures.erase(args.texture);
if (multiSampling) args.texture->sourceSurface = surface;
surface->destinationTextures.emplace(args.texture);
// If the texture is assigned to any slots, set it again. This'll also push the barrier.
for (uint32_t i = 0; i < std::size(g_textures); i++)
{ {
if (isDepthStencil) if (g_textures[i] == args.texture)
{ {
srcLayout = RenderTextureLayout::SHADER_READ; // Set the original texture for MSAA textures as they always get resolved.
dstLayout = RenderTextureLayout::DEPTH_WRITE; if (surface->sampleCount != RenderSampleCount::COUNT_1)
} {
else SetTextureInRenderThread(i, args.texture);
{ g_pendingMsaaResolves.emplace(surface);
srcLayout = RenderTextureLayout::RESOLVE_SOURCE; }
dstLayout = RenderTextureLayout::RESOLVE_DEST; else
{
SetSurface(i, surface);
}
} }
} }
else
{
srcLayout = RenderTextureLayout::COPY_SOURCE;
dstLayout = RenderTextureLayout::COPY_DEST;
}
AddBarrier(surface, srcLayout); // Remember to clear later.
AddBarrier(args.texture, dstLayout); g_pendingSurfaceCopies.emplace(surface);
FlushBarriers();
auto& commandList = g_commandLists[g_frame];
if (multiSampling)
{
if (isDepthStencil)
{
uint32_t pipelineIndex = 0;
switch (g_depthStencil->sampleCount)
{
case RenderSampleCount::COUNT_2:
pipelineIndex = 0;
break;
case RenderSampleCount::COUNT_4:
pipelineIndex = 1;
break;
case RenderSampleCount::COUNT_8:
pipelineIndex = 2;
break;
default:
assert(false && "Unsupported MSAA sample count");
break;
}
if (args.texture->framebuffer == nullptr)
{
RenderFramebufferDesc desc;
desc.depthAttachment = args.texture->texture;
args.texture->framebuffer = g_device->createFramebuffer(desc);
}
if (g_framebuffer != args.texture->framebuffer.get())
{
commandList->setFramebuffer(args.texture->framebuffer.get());
g_framebuffer = args.texture->framebuffer.get();
}
bool oldHalfPixel = SetHalfPixel(false);
FlushViewport();
commandList->setPipeline(g_resolveMsaaDepthPipelines[pipelineIndex].get());
commandList->setGraphicsPushConstants(0, &g_depthStencil->descriptorIndex, 0, sizeof(uint32_t));
commandList->drawInstanced(6, 1, 0, 0);
g_dirtyStates.renderTargetAndDepthStencil = true;
g_dirtyStates.pipelineState = true;
if (g_vulkan)
{
g_dirtyStates.depthBias = true; // Static depth bias in MSAA pipeline invalidates dynamic depth bias.
g_dirtyStates.vertexShaderConstants = true;
}
SetHalfPixel(oldHalfPixel);
}
else
{
commandList->resolveTexture(args.texture->texture, surface->texture);
}
}
else
{
commandList->copyTexture(args.texture->texture, surface->texture);
}
AddBarrier(args.texture, RenderTextureLayout::SHADER_READ);
} }
static void SetDefaultViewport(GuestDevice* device, GuestSurface* surface) static void SetDefaultViewport(GuestDevice* device, GuestSurface* surface)
@@ -3028,6 +2972,179 @@ static void ProcSetDepthStencilSurface(const RenderCommand& cmd)
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.depthStencilFormat, args.depthStencil != nullptr ? args.depthStencil->format : RenderFormat::UNKNOWN); SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.depthStencilFormat, args.depthStencil != nullptr ? args.depthStencil->format : RenderFormat::UNKNOWN);
} }
static bool PopulateBarriersForStretchRect(GuestSurface* renderTarget, GuestSurface* depthStencil)
{
bool addedAny = false;
for (const auto surface : { renderTarget, depthStencil })
{
if (surface != nullptr && !surface->destinationTextures.empty())
{
const bool multiSampling = surface->sampleCount != RenderSampleCount::COUNT_1;
RenderTextureLayout srcLayout;
RenderTextureLayout dstLayout;
if (multiSampling)
{
if (surface == depthStencil)
{
srcLayout = RenderTextureLayout::SHADER_READ;
dstLayout = RenderTextureLayout::DEPTH_WRITE;
}
else
{
srcLayout = RenderTextureLayout::RESOLVE_SOURCE;
dstLayout = RenderTextureLayout::RESOLVE_DEST;
}
}
else
{
srcLayout = RenderTextureLayout::COPY_SOURCE;
dstLayout = RenderTextureLayout::COPY_DEST;
}
AddBarrier(surface, srcLayout);
for (const auto texture : surface->destinationTextures)
{
// Need to create here...
if (texture->textureHolder == nullptr)
texture->CreateTexture();
AddBarrier(texture, dstLayout);
}
addedAny = true;
}
}
return addedAny;
}
static void ExecutePendingStretchRectCommands(GuestSurface* renderTarget, GuestSurface* depthStencil)
{
auto& commandList = g_commandLists[g_frame];
for (const auto surface : { renderTarget, depthStencil })
{
if (surface != nullptr && !surface->destinationTextures.empty())
{
const bool multiSampling = surface->sampleCount != RenderSampleCount::COUNT_1;
for (const auto texture : surface->destinationTextures)
{
// The texture doesn't need to be created at this point,
// since the barrier call would have already done it.
if (multiSampling)
{
if (surface == depthStencil)
{
uint32_t pipelineIndex = 0;
switch (surface->sampleCount)
{
case RenderSampleCount::COUNT_2:
pipelineIndex = 0;
break;
case RenderSampleCount::COUNT_4:
pipelineIndex = 1;
break;
case RenderSampleCount::COUNT_8:
pipelineIndex = 2;
break;
default:
assert(false && "Unsupported MSAA sample count");
break;
}
if (texture->framebuffer == nullptr)
{
RenderFramebufferDesc desc;
desc.depthAttachment = texture->texture;
texture->framebuffer = g_device->createFramebuffer(desc);
}
if (g_framebuffer != texture->framebuffer.get())
{
commandList->setFramebuffer(texture->framebuffer.get());
g_framebuffer = texture->framebuffer.get();
}
commandList->setPipeline(g_resolveMsaaDepthPipelines[pipelineIndex].get());
commandList->setViewports(RenderViewport(0.0f, 0.0f, float(texture->width), float(texture->height), 0.0f, 1.0f));
commandList->setScissors(RenderRect(0, 0, texture->width, texture->height));
commandList->setGraphicsPushConstants(0, &surface->descriptorIndex, 0, sizeof(uint32_t));
commandList->drawInstanced(6, 1, 0, 0);
g_dirtyStates.renderTargetAndDepthStencil = true;
g_dirtyStates.viewport = true;
g_dirtyStates.pipelineState = true;
g_dirtyStates.scissorRect = true;
if (g_vulkan)
{
g_dirtyStates.depthBias = true; // Static depth bias in MSAA pipeline invalidates dynamic depth bias.
g_dirtyStates.vertexShaderConstants = true;
}
}
else
{
commandList->resolveTexture(texture->texture, surface->texture);
}
}
else
{
commandList->copyTexture(texture->texture, surface->texture);
}
texture->sourceSurface = nullptr;
// Check if any texture slots had this texture assigned, and make it point back at the original texture.
for (uint32_t i = 0; i < std::size(g_textures); i++)
{
if (g_textures[i] == texture)
SetTextureInRenderThread(i, texture);
}
}
surface->destinationTextures.clear();
}
}
}
static void ProcExecutePendingStretchRectCommands(const RenderCommand& cmd)
{
bool foundAny = false;
for (const auto surface : g_pendingSurfaceCopies)
{
// Depth stencil textures in this game are guaranteed to be transient.
if (surface->format != RenderFormat::D32_FLOAT)
foundAny |= PopulateBarriersForStretchRect(surface, nullptr);
}
if (foundAny)
{
FlushBarriers();
for (const auto surface : g_pendingSurfaceCopies)
{
if (surface->format != RenderFormat::D32_FLOAT)
ExecutePendingStretchRectCommands(surface, nullptr);
for (const auto texture : surface->destinationTextures)
texture->sourceSurface = nullptr;
surface->destinationTextures.clear();
}
}
g_pendingSurfaceCopies.clear();
g_pendingMsaaResolves.clear();
}
static void SetFramebuffer(GuestSurface* renderTarget, GuestSurface* depthStencil, bool settingForClear) static void SetFramebuffer(GuestSurface* renderTarget, GuestSurface* depthStencil, bool settingForClear)
{ {
if (settingForClear || g_dirtyStates.renderTargetAndDepthStencil) if (settingForClear || g_dirtyStates.renderTargetAndDepthStencil)
@@ -3106,6 +3223,12 @@ static void ProcClear(const RenderCommand& cmd)
{ {
const auto& args = cmd.clear; const auto& args = cmd.clear;
if (PopulateBarriersForStretchRect(g_renderTarget, g_depthStencil))
{
FlushBarriers();
ExecutePendingStretchRectCommands(g_renderTarget, g_depthStencil);
}
AddBarrier(g_renderTarget, RenderTextureLayout::COLOR_WRITE); AddBarrier(g_renderTarget, RenderTextureLayout::COLOR_WRITE);
AddBarrier(g_depthStencil, RenderTextureLayout::DEPTH_WRITE); AddBarrier(g_depthStencil, RenderTextureLayout::DEPTH_WRITE);
FlushBarriers(); FlushBarriers();
@@ -3194,22 +3317,59 @@ static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* textur
g_renderQueue.enqueue(cmd); g_renderQueue.enqueue(cmd);
} }
static void SetTextureInRenderThread(uint32_t index, GuestTexture* texture)
{
// Only may happen for render target/depth stencil textures.
if (texture != nullptr && texture->textureHolder == nullptr)
texture->CreateTexture();
AddBarrier(texture, RenderTextureLayout::SHADER_READ);
auto viewDimension = texture != nullptr ? texture->viewDimension : RenderTextureViewDimension::UNKNOWN;
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture2DIndices[index],
viewDimension == RenderTextureViewDimension::TEXTURE_2D ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[index], texture != nullptr &&
viewDimension == RenderTextureViewDimension::TEXTURE_3D ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[index], texture != nullptr &&
viewDimension == RenderTextureViewDimension::TEXTURE_CUBE ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE);
}
static void SetSurface(uint32_t index, GuestSurface* surface)
{
AddBarrier(surface, RenderTextureLayout::SHADER_READ);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture2DIndices[index], surface->descriptorIndex);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[index], uint32_t(TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D));
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[index], uint32_t(TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE));
}
static void ProcSetTexture(const RenderCommand& cmd) static void ProcSetTexture(const RenderCommand& cmd)
{ {
const auto& args = cmd.setTexture; const auto& args = cmd.setTexture;
AddBarrier(args.texture, RenderTextureLayout::SHADER_READ); // If a pending copy operation is detected, set the source surface. The indices will be fixed later if flushing is necessary.
bool shouldSetTexture = true;
auto viewDimension = args.texture != nullptr ? args.texture->viewDimension : RenderTextureViewDimension::UNKNOWN; if (args.texture != nullptr && args.texture->sourceSurface != nullptr)
{
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture2DIndices[args.index], // MSAA surfaces need to be resolved and cannot be used directly.
viewDimension == RenderTextureViewDimension::TEXTURE_2D ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_2D); if (args.texture->sourceSurface->sampleCount != RenderSampleCount::COUNT_1)
{
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[args.index], args.texture != nullptr && g_pendingMsaaResolves.emplace(args.texture->sourceSurface);
viewDimension == RenderTextureViewDimension::TEXTURE_3D ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D); }
else
{
SetSurface(args.index, args.texture->sourceSurface);
shouldSetTexture = false;
}
}
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[args.index], args.texture != nullptr && if (shouldSetTexture)
viewDimension == RenderTextureViewDimension::TEXTURE_CUBE ? args.texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE); SetTextureInRenderThread(args.index, args.texture);
g_textures[args.index] = args.texture;
} }
static void SetScissorRect(GuestDevice* device, GuestRect* rect) static void SetScissorRect(GuestDevice* device, GuestRect* rect)
@@ -3815,9 +3975,34 @@ static void FlushRenderStateForRenderThread()
auto renderTarget = g_pipelineState.colorWriteEnable ? g_renderTarget : nullptr; auto renderTarget = g_pipelineState.colorWriteEnable ? g_renderTarget : nullptr;
auto depthStencil = g_pipelineState.zEnable ? g_depthStencil : nullptr; auto depthStencil = g_pipelineState.zEnable ? g_depthStencil : nullptr;
bool foundAny = PopulateBarriersForStretchRect(renderTarget, depthStencil);
for (const auto surface : g_pendingMsaaResolves)
{
bool isDepthStencil = (surface->format == RenderFormat::D32_FLOAT);
foundAny |= PopulateBarriersForStretchRect(isDepthStencil ? nullptr : surface, isDepthStencil ? surface : nullptr);
}
if (foundAny)
{
FlushBarriers();
ExecutePendingStretchRectCommands(renderTarget, depthStencil);
for (const auto surface : g_pendingMsaaResolves)
{
bool isDepthStencil = (surface->format == RenderFormat::D32_FLOAT);
ExecutePendingStretchRectCommands(isDepthStencil ? nullptr : surface, isDepthStencil ? surface : nullptr);
}
}
if (!g_pendingMsaaResolves.empty())
g_pendingMsaaResolves.clear();
AddBarrier(renderTarget, RenderTextureLayout::COLOR_WRITE); AddBarrier(renderTarget, RenderTextureLayout::COLOR_WRITE);
AddBarrier(depthStencil, RenderTextureLayout::DEPTH_WRITE); AddBarrier(depthStencil, RenderTextureLayout::DEPTH_WRITE);
FlushBarriers(); FlushBarriers();
SetFramebuffer(renderTarget, depthStencil, false); SetFramebuffer(renderTarget, depthStencil, false);
FlushViewport(); FlushViewport();
@@ -4580,35 +4765,36 @@ static std::thread g_renderThread([]
auto& cmd = commands[i]; auto& cmd = commands[i];
switch (cmd.type) switch (cmd.type)
{ {
case RenderCommandType::SetRenderState: ProcSetRenderState(cmd); break; case RenderCommandType::SetRenderState: ProcSetRenderState(cmd); break;
case RenderCommandType::DestructResource: ProcDestructResource(cmd); break; case RenderCommandType::DestructResource: ProcDestructResource(cmd); break;
case RenderCommandType::UnlockTextureRect: ProcUnlockTextureRect(cmd); break; case RenderCommandType::UnlockTextureRect: ProcUnlockTextureRect(cmd); break;
case RenderCommandType::UnlockBuffer16: ProcUnlockBuffer16(cmd); break; case RenderCommandType::UnlockBuffer16: ProcUnlockBuffer16(cmd); break;
case RenderCommandType::UnlockBuffer32: ProcUnlockBuffer32(cmd); break; case RenderCommandType::UnlockBuffer32: ProcUnlockBuffer32(cmd); break;
case RenderCommandType::DrawImGui: ProcDrawImGui(cmd); break; case RenderCommandType::DrawImGui: ProcDrawImGui(cmd); break;
case RenderCommandType::ExecuteCommandList: ProcExecuteCommandList(cmd); break; case RenderCommandType::ExecuteCommandList: ProcExecuteCommandList(cmd); break;
case RenderCommandType::BeginCommandList: ProcBeginCommandList(cmd); break; case RenderCommandType::BeginCommandList: ProcBeginCommandList(cmd); break;
case RenderCommandType::StretchRect: ProcStretchRect(cmd); break; case RenderCommandType::StretchRect: ProcStretchRect(cmd); break;
case RenderCommandType::SetRenderTarget: ProcSetRenderTarget(cmd); break; case RenderCommandType::SetRenderTarget: ProcSetRenderTarget(cmd); break;
case RenderCommandType::SetDepthStencilSurface: ProcSetDepthStencilSurface(cmd); break; case RenderCommandType::SetDepthStencilSurface: ProcSetDepthStencilSurface(cmd); break;
case RenderCommandType::Clear: ProcClear(cmd); break; case RenderCommandType::ExecutePendingStretchRectCommands: ProcExecutePendingStretchRectCommands(cmd); break;
case RenderCommandType::SetViewport: ProcSetViewport(cmd); break; case RenderCommandType::Clear: ProcClear(cmd); break;
case RenderCommandType::SetTexture: ProcSetTexture(cmd); break; case RenderCommandType::SetViewport: ProcSetViewport(cmd); break;
case RenderCommandType::SetScissorRect: ProcSetScissorRect(cmd); break; case RenderCommandType::SetTexture: ProcSetTexture(cmd); break;
case RenderCommandType::SetSamplerState: ProcSetSamplerState(cmd); break; case RenderCommandType::SetScissorRect: ProcSetScissorRect(cmd); break;
case RenderCommandType::SetBooleans: ProcSetBooleans(cmd); break; case RenderCommandType::SetSamplerState: ProcSetSamplerState(cmd); break;
case RenderCommandType::SetVertexShaderConstants: ProcSetVertexShaderConstants(cmd); break; case RenderCommandType::SetBooleans: ProcSetBooleans(cmd); break;
case RenderCommandType::SetPixelShaderConstants: ProcSetPixelShaderConstants(cmd); break; case RenderCommandType::SetVertexShaderConstants: ProcSetVertexShaderConstants(cmd); break;
case RenderCommandType::AddPipeline: ProcAddPipeline(cmd); break; case RenderCommandType::SetPixelShaderConstants: ProcSetPixelShaderConstants(cmd); break;
case RenderCommandType::DrawPrimitive: ProcDrawPrimitive(cmd); break; case RenderCommandType::AddPipeline: ProcAddPipeline(cmd); break;
case RenderCommandType::DrawIndexedPrimitive: ProcDrawIndexedPrimitive(cmd); break; case RenderCommandType::DrawPrimitive: ProcDrawPrimitive(cmd); break;
case RenderCommandType::DrawPrimitiveUP: ProcDrawPrimitiveUP(cmd); break; case RenderCommandType::DrawIndexedPrimitive: ProcDrawIndexedPrimitive(cmd); break;
case RenderCommandType::SetVertexDeclaration: ProcSetVertexDeclaration(cmd); break; case RenderCommandType::DrawPrimitiveUP: ProcDrawPrimitiveUP(cmd); break;
case RenderCommandType::SetVertexShader: ProcSetVertexShader(cmd); break; case RenderCommandType::SetVertexDeclaration: ProcSetVertexDeclaration(cmd); break;
case RenderCommandType::SetStreamSource: ProcSetStreamSource(cmd); break; case RenderCommandType::SetVertexShader: ProcSetVertexShader(cmd); break;
case RenderCommandType::SetIndices: ProcSetIndices(cmd); break; case RenderCommandType::SetStreamSource: ProcSetStreamSource(cmd); break;
case RenderCommandType::SetPixelShader: ProcSetPixelShader(cmd); break; case RenderCommandType::SetIndices: ProcSetIndices(cmd); break;
default: assert(false && "Unrecognized render command type."); break; case RenderCommandType::SetPixelShader: ProcSetPixelShader(cmd); break;
default: assert(false && "Unrecognized render command type."); break;
} }
} }
@@ -6772,6 +6958,52 @@ PPC_FUNC(sub_825E2F78)
__imp__sub_825E2F78(ctx, base); __imp__sub_825E2F78(ctx, base);
} }
// Game shares surfaces with identical descriptions. We don't want to share shadow maps,
// so we can set its format to a depth format that still resolves to the same type in recomp,
// but manages to keep the surfaces actually separated in guest code.
void FxShadowMapInitMidAsmHook(PPCRegister& r11)
{
uint8_t* base = g_memory.base;
uint32_t surface = PPC_LOAD_U32(PPC_LOAD_U32(PPC_LOAD_U32(r11.u32 + 0x24) + 0x4));
PPC_STORE_U32(surface + 0x20, D3DFMT_D24FS8);
}
// Re-render objects in the terrain shadow map instead of copying the texture.
static bool g_jumpOverStretchRect;
void FxShadowMapNoTerrainMidAsmHook(PPCRegister& r4, PPCRegister& r30)
{
// Set the no terrain shadow map as the render target.
uint8_t* base = g_memory.base;
r4.u64 = PPC_LOAD_U32(r30.u32 + 0x58);
}
bool FxShadowMapMidAsmHook(PPCRegister& r4, PPCRegister& r5, PPCRegister& r6, PPCRegister& r30)
{
if (g_jumpOverStretchRect)
{
// Reset for the next time shadow maps get rendered.
g_jumpOverStretchRect = false;
// Jump over the stretch rect call.
return false;
}
else
{
// Mark to jump over the stretch call the next time.
g_jumpOverStretchRect = true;
// Jump to the beginning. Set registers accordingly to set the terrain shadow map as the render target.
uint8_t* base = g_memory.base;
r6.u64 = 0;
r5.u64 = 0;
r4.u64 = PPC_LOAD_U32(r30.u32 + 0x50);
return true;
}
}
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice); GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource); GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
+6
View File
@@ -154,10 +154,15 @@ struct GuestBaseTexture : GuestResource
struct GuestTexture : GuestBaseTexture struct GuestTexture : GuestBaseTexture
{ {
uint32_t depth = 0; uint32_t depth = 0;
uint32_t levels = 0;
RenderTextureViewDimension viewDimension = RenderTextureViewDimension::UNKNOWN; RenderTextureViewDimension viewDimension = RenderTextureViewDimension::UNKNOWN;
RenderComponentMapping componentMapping;
void* mappedMemory = nullptr; void* mappedMemory = nullptr;
std::unique_ptr<RenderFramebuffer> framebuffer; std::unique_ptr<RenderFramebuffer> framebuffer;
std::unique_ptr<GuestTexture> patchedTexture; std::unique_ptr<GuestTexture> patchedTexture;
struct GuestSurface* sourceSurface = nullptr;
void CreateTexture();
}; };
struct GuestLockedRect struct GuestLockedRect
@@ -205,6 +210,7 @@ struct GuestSurface : GuestBaseTexture
uint32_t guestFormat = 0; uint32_t guestFormat = 0;
ankerl::unordered_dense::map<const RenderTexture*, std::unique_ptr<RenderFramebuffer>> framebuffers; ankerl::unordered_dense::map<const RenderTexture*, std::unique_ptr<RenderFramebuffer>> framebuffers;
RenderSampleCounts sampleCount = RenderSampleCount::COUNT_1; RenderSampleCounts sampleCount = RenderSampleCount::COUNT_1;
ankerl::unordered_dense::set<GuestTexture*> destinationTextures;
}; };
enum GuestDeclType enum GuestDeclType
@@ -8,7 +8,7 @@
#include <user/paths.h> #include <user/paths.h>
#include <app.h> #include <app.h>
static bool g_faderBegun = false; static std::atomic<bool> g_faderBegun = false;
bool g_quitMessageOpen = false; bool g_quitMessageOpen = false;
static int g_quitMessageResult = -1; static int g_quitMessageResult = -1;
@@ -16,39 +16,29 @@ static int g_quitMessageResult = -1;
static std::atomic<bool> g_corruptSaveMessageOpen = false; static std::atomic<bool> g_corruptSaveMessageOpen = false;
static int g_corruptSaveMessageResult = -1; static int g_corruptSaveMessageResult = -1;
static bool g_corruptAchievementsMessageOpen = false; static std::atomic<bool> g_corruptAchievementsMessageOpen = false;
static int g_corruptAchievementsMessageResult = -1; static int g_corruptAchievementsMessageResult = -1;
static bool g_updateAvailableMessageOpen = false; static std::atomic<bool> g_updateAvailableMessageOpen = false;
static int g_updateAvailableMessageResult = -1; static int g_updateAvailableMessageResult = -1;
static bool ProcessQuitMessage() static bool ProcessQuitMessage()
{ {
if (g_corruptSaveMessageOpen)
return false;
if (!g_quitMessageOpen) if (!g_quitMessageOpen)
return false; return false;
if (g_faderBegun)
return true;
std::array<std::string, 2> options = { Localise("Common_Yes"), Localise("Common_No") }; std::array<std::string, 2> options = { Localise("Common_Yes"), Localise("Common_No") };
if (MessageWindow::Open(Localise("Title_Message_Quit"), &g_quitMessageResult, options, 1) == MSG_CLOSED) if (MessageWindow::Open(Localise("Title_Message_Quit"), &g_quitMessageResult, options, 1) == MSG_CLOSED)
{ {
switch (g_quitMessageResult) if (!g_quitMessageResult)
{ {
case 0: Fader::FadeOut(1, []() { App::Exit(); });
Fader::FadeOut(1, []() { App::Exit(); }); g_faderBegun = true;
g_faderBegun = true;
break;
case 1:
g_quitMessageOpen = false;
g_quitMessageResult = -1;
break;
} }
g_quitMessageOpen = false;
g_quitMessageResult = -1;
} }
return true; return true;
@@ -86,6 +76,7 @@ static bool ProcessCorruptAchievementsMessage()
AchievementManager::Save(true); AchievementManager::Save(true);
g_corruptAchievementsMessageOpen = false; g_corruptAchievementsMessageOpen = false;
g_corruptAchievementsMessageOpen.notify_one();
g_corruptAchievementsMessageResult = -1; g_corruptAchievementsMessageResult = -1;
} }
@@ -97,9 +88,6 @@ static bool ProcessUpdateAvailableMessage()
if (!g_updateAvailableMessageOpen) if (!g_updateAvailableMessageOpen)
return false; return false;
if (g_faderBegun)
return true;
std::array<std::string, 2> options = { Localise("Common_Yes"), Localise("Common_No") }; std::array<std::string, 2> options = { Localise("Common_Yes"), Localise("Common_No") };
if (MessageWindow::Open(Localise("Title_Message_UpdateAvailable"), &g_updateAvailableMessageResult, options) == MSG_CLOSED) if (MessageWindow::Open(Localise("Title_Message_UpdateAvailable"), &g_updateAvailableMessageResult, options) == MSG_CLOSED)
@@ -119,6 +107,7 @@ static bool ProcessUpdateAvailableMessage()
} }
g_updateAvailableMessageOpen = false; g_updateAvailableMessageOpen = false;
g_updateAvailableMessageOpen.notify_one();
g_updateAvailableMessageResult = -1; g_updateAvailableMessageResult = -1;
} }
@@ -137,6 +126,24 @@ PPC_FUNC(sub_822C55B0)
ctx.r3.u32 = 0; ctx.r3.u32 = 0;
} }
void PressStartSaveLoadThreadMidAsmHook()
{
if (UpdateChecker::check() == UpdateChecker::Result::UpdateAvailable)
{
g_updateAvailableMessageOpen = true;
g_updateAvailableMessageOpen.wait(true);
g_faderBegun.wait(true);
}
AchievementManager::Load();
if (AchievementManager::Status != EAchStatus::Success)
{
g_corruptAchievementsMessageOpen = true;
g_corruptAchievementsMessageOpen.wait(true);
}
}
// SWA::CTitleStateIntro::Update // SWA::CTitleStateIntro::Update
PPC_FUNC_IMPL(__imp__sub_82587E50); PPC_FUNC_IMPL(__imp__sub_82587E50);
PPC_FUNC(sub_82587E50) PPC_FUNC(sub_82587E50)
@@ -151,21 +158,7 @@ PPC_FUNC(sub_82587E50)
{ {
if (auto pInputState = SWA::CInputState::GetInstance()) if (auto pInputState = SWA::CInputState::GetInstance())
{ {
auto& rPadState = pInputState->GetPadState(); if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B))
auto isAccepted = rPadState.IsTapped(SWA::eKeyState_A) || rPadState.IsTapped(SWA::eKeyState_Start);
auto isDeclined = rPadState.IsTapped(SWA::eKeyState_B);
if (isAccepted)
{
g_updateAvailableMessageOpen = UpdateChecker::check() == UpdateChecker::Result::UpdateAvailable;
AchievementManager::Load();
if (AchievementManager::Status != EAchStatus::Success)
g_corruptAchievementsMessageOpen = true;
}
if (isDeclined)
g_quitMessageOpen = true; g_quitMessageOpen = true;
} }
+1 -1
View File
@@ -197,7 +197,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
ImVec2 marqueeMin = { textMarqueeX, min.y }; ImVec2 marqueeMin = { textMarqueeX, min.y };
ImVec2 marqueeMax = { max.x - Scale(10) /* timestamp margin X */, max.y }; ImVec2 marqueeMax = { max.x - Scale(10) /* timestamp margin X */, max.y };
SetMarqueeFade(marqueeMin, marqueeMax, Scale(32)); SetHorizontalMarqueeFade(marqueeMin, marqueeMax, Scale(32));
if (isSelected && textX + textSize.x >= max.x - Scale(10)) if (isSelected && textX + textSize.x >= max.x - Scale(10))
{ {
+14 -2
View File
@@ -80,7 +80,7 @@ void ResetTextSkew()
SetScale({ 1.0f, 1.0f }); SetScale({ 1.0f, 1.0f });
} }
void SetMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale) void SetHorizontalMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale)
{ {
auto callbackData = AddImGuiCallback(ImGuiCallback::SetMarqueeFade); auto callbackData = AddImGuiCallback(ImGuiCallback::SetMarqueeFade);
callbackData->setMarqueeFade.boundsMin[0] = min.x; callbackData->setMarqueeFade.boundsMin[0] = min.x;
@@ -88,10 +88,22 @@ void SetMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale)
callbackData->setMarqueeFade.boundsMax[0] = max.x; callbackData->setMarqueeFade.boundsMax[0] = max.x;
callbackData->setMarqueeFade.boundsMax[1] = max.y; callbackData->setMarqueeFade.boundsMax[1] = max.y;
SetShaderModifier(IMGUI_SHADER_MODIFIER_MARQUEE_FADE); SetShaderModifier(IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE);
SetScale({ fadeScale, 1.0f }); SetScale({ fadeScale, 1.0f });
} }
void SetVerticalMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale)
{
auto callbackData = AddImGuiCallback(ImGuiCallback::SetMarqueeFade);
callbackData->setMarqueeFade.boundsMin[0] = min.x;
callbackData->setMarqueeFade.boundsMin[1] = min.y;
callbackData->setMarqueeFade.boundsMax[0] = max.x;
callbackData->setMarqueeFade.boundsMax[1] = max.y;
SetShaderModifier(IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE);
SetScale({ 1.0f, fadeScale });
}
void ResetMarqueeFade() void ResetMarqueeFade()
{ {
ResetGradient(); ResetGradient();
+2 -1
View File
@@ -42,7 +42,8 @@ void SetOrigin(ImVec2 origin);
void SetScale(ImVec2 scale); void SetScale(ImVec2 scale);
void SetTextSkew(float yCenter, float skewScale); void SetTextSkew(float yCenter, float skewScale);
void ResetTextSkew(); void ResetTextSkew();
void SetMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale); void SetHorizontalMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale);
void SetVerticalMarqueeFade(ImVec2 min, ImVec2 max, float fadeScale);
void ResetMarqueeFade(); void ResetMarqueeFade();
void SetOutline(float outline); void SetOutline(float outline);
void ResetOutline(); void ResetOutline();
+1 -1
View File
@@ -797,7 +797,7 @@ static void DrawDescriptionContainer()
ImVec2 textMin = { g_aspectRatioOffsetX + Scale(CONTAINER_X), textPos.y }; ImVec2 textMin = { g_aspectRatioOffsetX + Scale(CONTAINER_X), textPos.y };
ImVec2 textMax = { g_aspectRatioOffsetX + Scale(CONTAINER_X) + Scale(CONTAINER_WIDTH), g_aspectRatioOffsetY + Scale(CONTAINER_Y) + Scale(CONTAINER_HEIGHT) }; ImVec2 textMax = { g_aspectRatioOffsetX + Scale(CONTAINER_X) + Scale(CONTAINER_WIDTH), g_aspectRatioOffsetY + Scale(CONTAINER_Y) + Scale(CONTAINER_HEIGHT) };
SetMarqueeFade(textMin, textMax, Scale(32)); SetHorizontalMarqueeFade(textMin, textMax, Scale(32));
DrawTextWithMarquee(g_seuratFont, fontSize, textPos, textMin, textMax, colWhite, g_creditsStr.c_str(), g_installerEndTime, 0.9, Scale(200)); DrawTextWithMarquee(g_seuratFont, fontSize, textPos, textMin, textMax, colWhite, g_creditsStr.c_str(), g_installerEndTime, 0.9, Scale(200));
ResetMarqueeFade(); ResetMarqueeFade();
} }
+136 -136
View File
@@ -39,7 +39,7 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons)
CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode) CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode)
{ {
{ "UNKNOWN", SDL_SCANCODE_UNKNOWN }, { "???", SDL_SCANCODE_UNKNOWN },
{ "A", SDL_SCANCODE_A }, { "A", SDL_SCANCODE_A },
{ "B", SDL_SCANCODE_B }, { "B", SDL_SCANCODE_B },
{ "C", SDL_SCANCODE_C }, { "C", SDL_SCANCODE_C },
@@ -83,17 +83,17 @@ CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode)
{ "SPACE", SDL_SCANCODE_SPACE }, { "SPACE", SDL_SCANCODE_SPACE },
{ "MINUS", SDL_SCANCODE_MINUS }, { "MINUS", SDL_SCANCODE_MINUS },
{ "EQUALS", SDL_SCANCODE_EQUALS }, { "EQUALS", SDL_SCANCODE_EQUALS },
{ "LEFTBRACKET", SDL_SCANCODE_LEFTBRACKET }, { "LEFT BRACKET", SDL_SCANCODE_LEFTBRACKET },
{ "RIGHTBRACKET", SDL_SCANCODE_RIGHTBRACKET }, { "RIGHT BRACKET", SDL_SCANCODE_RIGHTBRACKET },
{ "BACKSLASH", SDL_SCANCODE_BACKSLASH }, { "BACKSLASH", SDL_SCANCODE_BACKSLASH },
{ "NONUSHASH", SDL_SCANCODE_NONUSHASH }, { "NON-US HASH", SDL_SCANCODE_NONUSHASH },
{ "SEMICOLON", SDL_SCANCODE_SEMICOLON }, { "SEMICOLON", SDL_SCANCODE_SEMICOLON },
{ "APOSTROPHE", SDL_SCANCODE_APOSTROPHE }, { "APOSTROPHE", SDL_SCANCODE_APOSTROPHE },
{ "GRAVE", SDL_SCANCODE_GRAVE }, { "GRAVE", SDL_SCANCODE_GRAVE },
{ "COMMA", SDL_SCANCODE_COMMA }, { "COMMA", SDL_SCANCODE_COMMA },
{ "PERIOD", SDL_SCANCODE_PERIOD }, { "PERIOD", SDL_SCANCODE_PERIOD },
{ "SLASH", SDL_SCANCODE_SLASH }, { "SLASH", SDL_SCANCODE_SLASH },
{ "CAPSLOCK", SDL_SCANCODE_CAPSLOCK }, { "CAPS LOCK", SDL_SCANCODE_CAPSLOCK },
{ "F1", SDL_SCANCODE_F1 }, { "F1", SDL_SCANCODE_F1 },
{ "F2", SDL_SCANCODE_F2 }, { "F2", SDL_SCANCODE_F2 },
{ "F3", SDL_SCANCODE_F3 }, { "F3", SDL_SCANCODE_F3 },
@@ -106,40 +106,40 @@ CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode)
{ "F10", SDL_SCANCODE_F10 }, { "F10", SDL_SCANCODE_F10 },
{ "F11", SDL_SCANCODE_F11 }, { "F11", SDL_SCANCODE_F11 },
{ "F12", SDL_SCANCODE_F12 }, { "F12", SDL_SCANCODE_F12 },
{ "PRINTSCREEN", SDL_SCANCODE_PRINTSCREEN }, { "PRINT SCREEN", SDL_SCANCODE_PRINTSCREEN },
{ "SCROLLLOCK", SDL_SCANCODE_SCROLLLOCK }, { "SCROLL LOCK", SDL_SCANCODE_SCROLLLOCK },
{ "PAUSE", SDL_SCANCODE_PAUSE }, { "PAUSE", SDL_SCANCODE_PAUSE },
{ "INSERT", SDL_SCANCODE_INSERT }, { "INSERT", SDL_SCANCODE_INSERT },
{ "HOME", SDL_SCANCODE_HOME }, { "HOME", SDL_SCANCODE_HOME },
{ "PAGEUP", SDL_SCANCODE_PAGEUP }, { "PAGE UP", SDL_SCANCODE_PAGEUP },
{ "DELETE", SDL_SCANCODE_DELETE }, { "DELETE", SDL_SCANCODE_DELETE },
{ "END", SDL_SCANCODE_END }, { "END", SDL_SCANCODE_END },
{ "PAGEDOWN", SDL_SCANCODE_PAGEDOWN }, { "PAGE DOWN", SDL_SCANCODE_PAGEDOWN },
{ "RIGHT", SDL_SCANCODE_RIGHT }, { "RIGHT", SDL_SCANCODE_RIGHT },
{ "LEFT", SDL_SCANCODE_LEFT }, { "LEFT", SDL_SCANCODE_LEFT },
{ "DOWN", SDL_SCANCODE_DOWN }, { "DOWN", SDL_SCANCODE_DOWN },
{ "UP", SDL_SCANCODE_UP }, { "UP", SDL_SCANCODE_UP },
{ "NUMLOCKCLEAR", SDL_SCANCODE_NUMLOCKCLEAR }, { "NUM LOCK", SDL_SCANCODE_NUMLOCKCLEAR },
{ "KP_DIVIDE", SDL_SCANCODE_KP_DIVIDE }, { "KP DIVIDE", SDL_SCANCODE_KP_DIVIDE },
{ "KP_MULTIPLY", SDL_SCANCODE_KP_MULTIPLY }, { "KP MULTIPLY", SDL_SCANCODE_KP_MULTIPLY },
{ "KP_MINUS", SDL_SCANCODE_KP_MINUS }, { "KP MINUS", SDL_SCANCODE_KP_MINUS },
{ "KP_PLUS", SDL_SCANCODE_KP_PLUS }, { "KP PLUS", SDL_SCANCODE_KP_PLUS },
{ "KP_ENTER", SDL_SCANCODE_KP_ENTER }, { "KP ENTER", SDL_SCANCODE_KP_ENTER },
{ "KP_1", SDL_SCANCODE_KP_1 }, { "KP 1", SDL_SCANCODE_KP_1 },
{ "KP_2", SDL_SCANCODE_KP_2 }, { "KP 2", SDL_SCANCODE_KP_2 },
{ "KP_3", SDL_SCANCODE_KP_3 }, { "KP 3", SDL_SCANCODE_KP_3 },
{ "KP_4", SDL_SCANCODE_KP_4 }, { "KP 4", SDL_SCANCODE_KP_4 },
{ "KP_5", SDL_SCANCODE_KP_5 }, { "KP 5", SDL_SCANCODE_KP_5 },
{ "KP_6", SDL_SCANCODE_KP_6 }, { "KP 6", SDL_SCANCODE_KP_6 },
{ "KP_7", SDL_SCANCODE_KP_7 }, { "KP 7", SDL_SCANCODE_KP_7 },
{ "KP_8", SDL_SCANCODE_KP_8 }, { "KP 8", SDL_SCANCODE_KP_8 },
{ "KP_9", SDL_SCANCODE_KP_9 }, { "KP 9", SDL_SCANCODE_KP_9 },
{ "KP_0", SDL_SCANCODE_KP_0 }, { "KP 0", SDL_SCANCODE_KP_0 },
{ "KP_PERIOD", SDL_SCANCODE_KP_PERIOD }, { "KP PERIOD", SDL_SCANCODE_KP_PERIOD },
{ "NONUSBACKSLASH", SDL_SCANCODE_NONUSBACKSLASH }, { "NON-US BACKSLASH", SDL_SCANCODE_NONUSBACKSLASH },
{ "APPLICATION", SDL_SCANCODE_APPLICATION }, { "APPLICATION", SDL_SCANCODE_APPLICATION },
{ "POWER", SDL_SCANCODE_POWER }, { "POWER", SDL_SCANCODE_POWER },
{ "KP_EQUALS", SDL_SCANCODE_KP_EQUALS }, { "KP EQUALS", SDL_SCANCODE_KP_EQUALS },
{ "F13", SDL_SCANCODE_F13 }, { "F13", SDL_SCANCODE_F13 },
{ "F14", SDL_SCANCODE_F14 }, { "F14", SDL_SCANCODE_F14 },
{ "F15", SDL_SCANCODE_F15 }, { "F15", SDL_SCANCODE_F15 },
@@ -164,128 +164,128 @@ CONFIG_DEFINE_ENUM_TEMPLATE(SDL_Scancode)
{ "PASTE", SDL_SCANCODE_PASTE }, { "PASTE", SDL_SCANCODE_PASTE },
{ "FIND", SDL_SCANCODE_FIND }, { "FIND", SDL_SCANCODE_FIND },
{ "MUTE", SDL_SCANCODE_MUTE }, { "MUTE", SDL_SCANCODE_MUTE },
{ "VOLUMEUP", SDL_SCANCODE_VOLUMEUP }, { "VOLUME UP", SDL_SCANCODE_VOLUMEUP },
{ "VOLUMEDOWN", SDL_SCANCODE_VOLUMEDOWN }, { "VOLUME DOWN", SDL_SCANCODE_VOLUMEDOWN },
{ "KP_COMMA", SDL_SCANCODE_KP_COMMA }, { "KP COMMA", SDL_SCANCODE_KP_COMMA },
{ "KP_EQUALSAS400", SDL_SCANCODE_KP_EQUALSAS400 }, { "KP EQUALS AS400", SDL_SCANCODE_KP_EQUALSAS400 },
{ "INTERNATIONAL1", SDL_SCANCODE_INTERNATIONAL1 }, { "INTERNATIONAL 1", SDL_SCANCODE_INTERNATIONAL1 },
{ "INTERNATIONAL2", SDL_SCANCODE_INTERNATIONAL2 }, { "INTERNATIONAL 2", SDL_SCANCODE_INTERNATIONAL2 },
{ "INTERNATIONAL3", SDL_SCANCODE_INTERNATIONAL3 }, { "INTERNATIONAL 3", SDL_SCANCODE_INTERNATIONAL3 },
{ "INTERNATIONAL4", SDL_SCANCODE_INTERNATIONAL4 }, { "INTERNATIONAL 4", SDL_SCANCODE_INTERNATIONAL4 },
{ "INTERNATIONAL5", SDL_SCANCODE_INTERNATIONAL5 }, { "INTERNATIONAL 5", SDL_SCANCODE_INTERNATIONAL5 },
{ "INTERNATIONAL6", SDL_SCANCODE_INTERNATIONAL6 }, { "INTERNATIONAL 6", SDL_SCANCODE_INTERNATIONAL6 },
{ "INTERNATIONAL7", SDL_SCANCODE_INTERNATIONAL7 }, { "INTERNATIONAL 7", SDL_SCANCODE_INTERNATIONAL7 },
{ "INTERNATIONAL8", SDL_SCANCODE_INTERNATIONAL8 }, { "INTERNATIONAL 8", SDL_SCANCODE_INTERNATIONAL8 },
{ "INTERNATIONAL9", SDL_SCANCODE_INTERNATIONAL9 }, { "INTERNATIONAL 9", SDL_SCANCODE_INTERNATIONAL9 },
{ "LANG1", SDL_SCANCODE_LANG1 }, { "LANG 1", SDL_SCANCODE_LANG1 },
{ "LANG2", SDL_SCANCODE_LANG2 }, { "LANG 2", SDL_SCANCODE_LANG2 },
{ "LANG3", SDL_SCANCODE_LANG3 }, { "LANG 3", SDL_SCANCODE_LANG3 },
{ "LANG4", SDL_SCANCODE_LANG4 }, { "LANG 4", SDL_SCANCODE_LANG4 },
{ "LANG5", SDL_SCANCODE_LANG5 }, { "LANG 5", SDL_SCANCODE_LANG5 },
{ "LANG6", SDL_SCANCODE_LANG6 }, { "LANG 6", SDL_SCANCODE_LANG6 },
{ "LANG7", SDL_SCANCODE_LANG7 }, { "LANG 7", SDL_SCANCODE_LANG7 },
{ "LANG8", SDL_SCANCODE_LANG8 }, { "LANG 8", SDL_SCANCODE_LANG8 },
{ "LANG9", SDL_SCANCODE_LANG9 }, { "LANG 9", SDL_SCANCODE_LANG9 },
{ "ALTERASE", SDL_SCANCODE_ALTERASE }, { "ALT ERASE", SDL_SCANCODE_ALTERASE },
{ "SYSREQ", SDL_SCANCODE_SYSREQ }, { "SYS REQ", SDL_SCANCODE_SYSREQ },
{ "CANCEL", SDL_SCANCODE_CANCEL }, { "CANCEL", SDL_SCANCODE_CANCEL },
{ "CLEAR", SDL_SCANCODE_CLEAR }, { "CLEAR", SDL_SCANCODE_CLEAR },
{ "PRIOR", SDL_SCANCODE_PRIOR }, { "PRIOR", SDL_SCANCODE_PRIOR },
{ "RETURN2", SDL_SCANCODE_RETURN2 }, { "RETURN 2", SDL_SCANCODE_RETURN2 },
{ "SEPARATOR", SDL_SCANCODE_SEPARATOR }, { "SEPARATOR", SDL_SCANCODE_SEPARATOR },
{ "OUT", SDL_SCANCODE_OUT }, { "OUT", SDL_SCANCODE_OUT },
{ "OPER", SDL_SCANCODE_OPER }, { "OPER", SDL_SCANCODE_OPER },
{ "CLEARAGAIN", SDL_SCANCODE_CLEARAGAIN }, { "CLEAR AGAIN", SDL_SCANCODE_CLEARAGAIN },
{ "CRSEL", SDL_SCANCODE_CRSEL }, { "CR SEL", SDL_SCANCODE_CRSEL },
{ "EXSEL", SDL_SCANCODE_EXSEL }, { "EX SEL", SDL_SCANCODE_EXSEL },
{ "KP_00", SDL_SCANCODE_KP_00 }, { "KP 00", SDL_SCANCODE_KP_00 },
{ "KP_000", SDL_SCANCODE_KP_000 }, { "KP 000", SDL_SCANCODE_KP_000 },
{ "THOUSANDSSEPARATOR", SDL_SCANCODE_THOUSANDSSEPARATOR }, { "THOUSANDS SEPARATOR", SDL_SCANCODE_THOUSANDSSEPARATOR },
{ "DECIMALSEPARATOR", SDL_SCANCODE_DECIMALSEPARATOR }, { "DECIMAL SEPARATOR", SDL_SCANCODE_DECIMALSEPARATOR },
{ "CURRENCYUNIT", SDL_SCANCODE_CURRENCYUNIT }, { "CURRENCY UNIT", SDL_SCANCODE_CURRENCYUNIT },
{ "CURRENCYSUBUNIT", SDL_SCANCODE_CURRENCYSUBUNIT }, { "CURRENCY SUBUNIT", SDL_SCANCODE_CURRENCYSUBUNIT },
{ "KP_LEFTPAREN", SDL_SCANCODE_KP_LEFTPAREN }, { "KP LEFT PAREN", SDL_SCANCODE_KP_LEFTPAREN },
{ "KP_RIGHTPAREN", SDL_SCANCODE_KP_RIGHTPAREN }, { "KP RIGHT PAREN", SDL_SCANCODE_KP_RIGHTPAREN },
{ "KP_LEFTBRACE", SDL_SCANCODE_KP_LEFTBRACE }, { "KP LEFT BRACE", SDL_SCANCODE_KP_LEFTBRACE },
{ "KP_RIGHTBRACE", SDL_SCANCODE_KP_RIGHTBRACE }, { "KP RIGHT BRACE", SDL_SCANCODE_KP_RIGHTBRACE },
{ "KP_TAB", SDL_SCANCODE_KP_TAB }, { "KP TAB", SDL_SCANCODE_KP_TAB },
{ "KP_BACKSPACE", SDL_SCANCODE_KP_BACKSPACE }, { "KP BACKSPACE", SDL_SCANCODE_KP_BACKSPACE },
{ "KP_A", SDL_SCANCODE_KP_A }, { "KP A", SDL_SCANCODE_KP_A },
{ "KP_B", SDL_SCANCODE_KP_B }, { "KP B", SDL_SCANCODE_KP_B },
{ "KP_C", SDL_SCANCODE_KP_C }, { "KP C", SDL_SCANCODE_KP_C },
{ "KP_D", SDL_SCANCODE_KP_D }, { "KP D", SDL_SCANCODE_KP_D },
{ "KP_E", SDL_SCANCODE_KP_E }, { "KP E", SDL_SCANCODE_KP_E },
{ "KP_F", SDL_SCANCODE_KP_F }, { "KP F", SDL_SCANCODE_KP_F },
{ "KP_XOR", SDL_SCANCODE_KP_XOR }, { "KP XOR", SDL_SCANCODE_KP_XOR },
{ "KP_POWER", SDL_SCANCODE_KP_POWER }, { "KP POWER", SDL_SCANCODE_KP_POWER },
{ "KP_PERCENT", SDL_SCANCODE_KP_PERCENT }, { "KP PERCENT", SDL_SCANCODE_KP_PERCENT },
{ "KP_LESS", SDL_SCANCODE_KP_LESS }, { "KP LESS", SDL_SCANCODE_KP_LESS },
{ "KP_GREATER", SDL_SCANCODE_KP_GREATER }, { "KP GREATER", SDL_SCANCODE_KP_GREATER },
{ "KP_AMPERSAND", SDL_SCANCODE_KP_AMPERSAND }, { "KP AMPERSAND", SDL_SCANCODE_KP_AMPERSAND },
{ "KP_DBLAMPERSAND", SDL_SCANCODE_KP_DBLAMPERSAND }, { "KP DBL AMPERSAND", SDL_SCANCODE_KP_DBLAMPERSAND },
{ "KP_VERTICALBAR", SDL_SCANCODE_KP_VERTICALBAR }, { "KP VERTICAL BAR", SDL_SCANCODE_KP_VERTICALBAR },
{ "KP_DBLVERTICALBAR", SDL_SCANCODE_KP_DBLVERTICALBAR }, { "KP DBL VERTICAL BAR", SDL_SCANCODE_KP_DBLVERTICALBAR },
{ "KP_COLON", SDL_SCANCODE_KP_COLON }, { "KP COLON", SDL_SCANCODE_KP_COLON },
{ "KP_HASH", SDL_SCANCODE_KP_HASH }, { "KP HASH", SDL_SCANCODE_KP_HASH },
{ "KP_SPACE", SDL_SCANCODE_KP_SPACE }, { "KP SPACE", SDL_SCANCODE_KP_SPACE },
{ "KP_AT", SDL_SCANCODE_KP_AT }, { "KP AT", SDL_SCANCODE_KP_AT },
{ "KP_EXCLAM", SDL_SCANCODE_KP_EXCLAM }, { "KP EXCLAM", SDL_SCANCODE_KP_EXCLAM },
{ "KP_MEMSTORE", SDL_SCANCODE_KP_MEMSTORE }, { "KP MEM STORE", SDL_SCANCODE_KP_MEMSTORE },
{ "KP_MEMRECALL", SDL_SCANCODE_KP_MEMRECALL }, { "KP MEM RECALL", SDL_SCANCODE_KP_MEMRECALL },
{ "KP_MEMCLEAR", SDL_SCANCODE_KP_MEMCLEAR }, { "KP MEM CLEAR", SDL_SCANCODE_KP_MEMCLEAR },
{ "KP_MEMADD", SDL_SCANCODE_KP_MEMADD }, { "KP MEM ADD", SDL_SCANCODE_KP_MEMADD },
{ "KP_MEMSUBTRACT", SDL_SCANCODE_KP_MEMSUBTRACT }, { "KP MEM SUBTRACT", SDL_SCANCODE_KP_MEMSUBTRACT },
{ "KP_MEMMULTIPLY", SDL_SCANCODE_KP_MEMMULTIPLY }, { "KP MEM MULTIPLY", SDL_SCANCODE_KP_MEMMULTIPLY },
{ "KP_MEMDIVIDE", SDL_SCANCODE_KP_MEMDIVIDE }, { "KP MEM DIVIDE", SDL_SCANCODE_KP_MEMDIVIDE },
{ "KP_PLUSMINUS", SDL_SCANCODE_KP_PLUSMINUS }, { "KP PLUS/MINUS", SDL_SCANCODE_KP_PLUSMINUS },
{ "KP_CLEAR", SDL_SCANCODE_KP_CLEAR }, { "KP CLEAR", SDL_SCANCODE_KP_CLEAR },
{ "KP_CLEARENTRY", SDL_SCANCODE_KP_CLEARENTRY }, { "KP CLEAR ENTRY", SDL_SCANCODE_KP_CLEARENTRY },
{ "KP_BINARY", SDL_SCANCODE_KP_BINARY }, { "KP BINARY", SDL_SCANCODE_KP_BINARY },
{ "KP_OCTAL", SDL_SCANCODE_KP_OCTAL }, { "KP OCTAL", SDL_SCANCODE_KP_OCTAL },
{ "KP_DECIMAL", SDL_SCANCODE_KP_DECIMAL }, { "KP DECIMAL", SDL_SCANCODE_KP_DECIMAL },
{ "KP_HEXADECIMAL", SDL_SCANCODE_KP_HEXADECIMAL }, { "KP HEXADECIMAL", SDL_SCANCODE_KP_HEXADECIMAL },
{ "LCTRL", SDL_SCANCODE_LCTRL }, { "LEFT CTRL", SDL_SCANCODE_LCTRL },
{ "LSHIFT", SDL_SCANCODE_LSHIFT }, { "LEFT SHIFT", SDL_SCANCODE_LSHIFT },
{ "LALT", SDL_SCANCODE_LALT }, { "LEFT ALT", SDL_SCANCODE_LALT },
{ "LGUI", SDL_SCANCODE_LGUI }, { "LEFT SUPER", SDL_SCANCODE_LGUI },
{ "RCTRL", SDL_SCANCODE_RCTRL }, { "RIGHT CTRL", SDL_SCANCODE_RCTRL },
{ "RSHIFT", SDL_SCANCODE_RSHIFT }, { "RIGHT SHIFT", SDL_SCANCODE_RSHIFT },
{ "RALT", SDL_SCANCODE_RALT }, { "RIGHT ALT", SDL_SCANCODE_RALT },
{ "RGUI", SDL_SCANCODE_RGUI }, { "RIGHT SUPER", SDL_SCANCODE_RGUI },
{ "MODE", SDL_SCANCODE_MODE }, { "MODE", SDL_SCANCODE_MODE },
{ "AUDIONEXT", SDL_SCANCODE_AUDIONEXT }, { "AUDIO NEXT", SDL_SCANCODE_AUDIONEXT },
{ "AUDIOPREV", SDL_SCANCODE_AUDIOPREV }, { "AUDIO PREV", SDL_SCANCODE_AUDIOPREV },
{ "AUDIOSTOP", SDL_SCANCODE_AUDIOSTOP }, { "AUDIO STOP", SDL_SCANCODE_AUDIOSTOP },
{ "AUDIOPLAY", SDL_SCANCODE_AUDIOPLAY }, { "AUDIO PLAY", SDL_SCANCODE_AUDIOPLAY },
{ "AUDIOMUTE", SDL_SCANCODE_AUDIOMUTE }, { "AUDIO MUTE", SDL_SCANCODE_AUDIOMUTE },
{ "MEDIASELECT", SDL_SCANCODE_MEDIASELECT }, { "MEDIA SELECT", SDL_SCANCODE_MEDIASELECT },
{ "WWW", SDL_SCANCODE_WWW }, { "WWW", SDL_SCANCODE_WWW },
{ "MAIL", SDL_SCANCODE_MAIL }, { "MAIL", SDL_SCANCODE_MAIL },
{ "CALCULATOR", SDL_SCANCODE_CALCULATOR }, { "CALCULATOR", SDL_SCANCODE_CALCULATOR },
{ "COMPUTER", SDL_SCANCODE_COMPUTER }, { "COMPUTER", SDL_SCANCODE_COMPUTER },
{ "AC_SEARCH", SDL_SCANCODE_AC_SEARCH }, { "AC SEARCH", SDL_SCANCODE_AC_SEARCH },
{ "AC_HOME", SDL_SCANCODE_AC_HOME }, { "AC HOME", SDL_SCANCODE_AC_HOME },
{ "AC_BACK", SDL_SCANCODE_AC_BACK }, { "AC BACK", SDL_SCANCODE_AC_BACK },
{ "AC_FORWARD", SDL_SCANCODE_AC_FORWARD }, { "AC FORWARD", SDL_SCANCODE_AC_FORWARD },
{ "AC_STOP", SDL_SCANCODE_AC_STOP }, { "AC STOP", SDL_SCANCODE_AC_STOP },
{ "AC_REFRESH", SDL_SCANCODE_AC_REFRESH }, { "AC REFRESH", SDL_SCANCODE_AC_REFRESH },
{ "AC_BOOKMARKS", SDL_SCANCODE_AC_BOOKMARKS }, { "AC BOOKMARKS", SDL_SCANCODE_AC_BOOKMARKS },
{ "BRIGHTNESSDOWN", SDL_SCANCODE_BRIGHTNESSDOWN }, { "BRIGHTNESS DOWN", SDL_SCANCODE_BRIGHTNESSDOWN },
{ "BRIGHTNESSUP", SDL_SCANCODE_BRIGHTNESSUP }, { "BRIGHTNESS UP", SDL_SCANCODE_BRIGHTNESSUP },
{ "DISPLAYSWITCH", SDL_SCANCODE_DISPLAYSWITCH }, { "DISPLAY SWITCH", SDL_SCANCODE_DISPLAYSWITCH },
{ "KBDILLUMTOGGLE", SDL_SCANCODE_KBDILLUMTOGGLE }, { "KBD ILLUM TOGGLE", SDL_SCANCODE_KBDILLUMTOGGLE },
{ "KBDILLUMDOWN", SDL_SCANCODE_KBDILLUMDOWN }, { "KBD ILLUM DOWN", SDL_SCANCODE_KBDILLUMDOWN },
{ "KBDILLUMUP", SDL_SCANCODE_KBDILLUMUP }, { "KBD ILLUM UP", SDL_SCANCODE_KBDILLUMUP },
{ "EJECT", SDL_SCANCODE_EJECT }, { "EJECT", SDL_SCANCODE_EJECT },
{ "SLEEP", SDL_SCANCODE_SLEEP }, { "SLEEP", SDL_SCANCODE_SLEEP },
{ "APP1", SDL_SCANCODE_APP1 }, { "APP 1", SDL_SCANCODE_APP1 },
{ "APP2", SDL_SCANCODE_APP2 }, { "APP 2", SDL_SCANCODE_APP2 },
{ "AUDIOREWIND", SDL_SCANCODE_AUDIOREWIND }, { "AUDIO REWIND", SDL_SCANCODE_AUDIOREWIND },
{ "AUDIOFASTFORWARD", SDL_SCANCODE_AUDIOFASTFORWARD }, { "AUDIO FAST FORWARD", SDL_SCANCODE_AUDIOFASTFORWARD },
{ "SOFTLEFT", SDL_SCANCODE_SOFTLEFT }, { "SOFT LEFT", SDL_SCANCODE_SOFTLEFT },
{ "SOFTRIGHT", SDL_SCANCODE_SOFTRIGHT }, { "SOFT RIGHT", SDL_SCANCODE_SOFTRIGHT },
{ "CALL", SDL_SCANCODE_CALL }, { "CALL", SDL_SCANCODE_CALL },
{ "ENDCALL", SDL_SCANCODE_ENDCALL }, { "END CALL", SDL_SCANCODE_ENDCALL },
}; };
CONFIG_DEFINE_ENUM_TEMPLATE(EChannelConfiguration) CONFIG_DEFINE_ENUM_TEMPLATE(EChannelConfiguration)
-6
View File
@@ -1,12 +1,6 @@
#include "registry.h" #include "registry.h"
#include <os/process.h> #include <os/process.h>
#include <os/registry.h> #include <os/registry.h>
#include <user/config.h>
void Registry::Load()
{
}
void Registry::Save() void Registry::Save()
{ {
-1
View File
@@ -3,6 +3,5 @@
class Registry class Registry
{ {
public: public:
static void Load();
static void Save(); static void Save();
}; };
+22
View File
@@ -914,3 +914,25 @@ jump_address = 0x82AE2774
name = "ApplicationFrameLimiterMidAsmHook" name = "ApplicationFrameLimiterMidAsmHook"
address = 0x822C1064 address = 0x822C1064
jump_address = 0x822C111C jump_address = 0x822C111C
[[midasm_hook]]
name = "PressStartSaveLoadThreadMidAsmHook"
address = 0x822C4358
[[midasm_hook]]
name = "FxShadowMapInitMidAsmHook"
address = 0x82BAD8F4
registers = ["r11"]
[[midasm_hook]]
name = "FxShadowMapNoTerrainMidAsmHook"
address = 0x82BAD9EC
registers = ["r4", "r30"]
after_instruction = true
[[midasm_hook]]
name = "FxShadowMapMidAsmHook"
address = 0x82BADADC
registers = ["r4", "r5", "r6", "r30"]
jump_address_on_true = 0x82BAD9F0
jump_address_on_false = 0x82BADAFC