#include #include #include #include #include "aspect_ratio_patches.h" using SVertexData = SWA::Sequence::Utility::CPlayMovieWrapper::CRender::SVertexData; // Update movie player aspect ratio. PPC_FUNC_IMPL(__imp__sub_82AE30D8); PPC_FUNC(sub_82AE30D8) { auto pViewportWidth = (be*)g_memory.Translate(ctx.r4.u32 + 0x14); auto pViewportHeight = (be*)g_memory.Translate(ctx.r4.u32 + 0x18); auto pTopLeft = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C); auto pTopRight = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData)); auto pBottomRight = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData) * 2); auto pBottomLeft = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData) * 3); auto quadWidth = std::fabs(pTopRight->X - pTopLeft->X) * ((float)*pViewportWidth / 2); auto quadHeight = std::fabs(pTopLeft->Y - pBottomLeft->Y) * ((float)*pViewportHeight / 2); auto movieAspectRatio = quadWidth / quadHeight; auto scaleU = 1.0f; auto scaleV = 1.0f; auto centreV = (pTopLeft->V + pBottomRight->V) / 2.0f; if (g_aspectRatio > movieAspectRatio) { scaleU = movieAspectRatio / g_aspectRatio; } else { scaleV = g_aspectRatio / movieAspectRatio; } float halfPixelX = 1.0f / Video::s_viewportWidth; float halfPixelY = 1.0f / Video::s_viewportHeight; pTopLeft->X = -1.0f - halfPixelX; pTopLeft->Y = 1.0f + halfPixelY; pTopLeft->U = (pTopLeft->U - centreV) / scaleU + centreV; pTopLeft->V = (pTopLeft->V - centreV) / scaleV + centreV; pTopRight->X = 1.0f - halfPixelX; pTopRight->Y = 1.0f + halfPixelY; pTopRight->U = (pTopRight->U - centreV) / scaleU + centreV; pTopRight->V = (pTopRight->V - centreV) / scaleV + centreV; pBottomLeft->X = -1.0f - halfPixelX; pBottomLeft->Y = -1.0f + halfPixelY; pBottomLeft->U = (pBottomLeft->U - centreV) / scaleU + centreV; pBottomLeft->V = (pBottomLeft->V - centreV) / scaleV + centreV; pBottomRight->X = 1.0f - halfPixelX; pBottomRight->Y = -1.0f + halfPixelY; pBottomRight->U = (pBottomRight->U - centreV) / scaleU + centreV; pBottomRight->V = (pBottomRight->V - centreV) / scaleV + centreV; __imp__sub_82AE30D8(ctx, base); } void RemoveMoviePlayerLetterboxMidAsmHook() {} bool MotionBlurMidAsmHook() { return Config::MotionBlur != EMotionBlur::Off; } // Hedgehog::MirageDebug::PrepareRenderPrimitive2D PPC_FUNC_IMPL(__imp__sub_830D25D8); PPC_FUNC(sub_830D25D8) { auto device = reinterpret_cast(base + PPC_LOAD_U32(ctx.r4.u32)); // Set first sampler to use linear filtering. // NOTE: We only check for height here since all 2D primitives get centered. if (Video::s_viewportHeight > 720) { device->samplerStates[0].data[3] = (device->samplerStates[0].data[3].get() & ~0x1f80000) | 0x1280000; device->dirtyFlags[3] = device->dirtyFlags[3].get() | 0x80000000ull; } __imp__sub_830D25D8(ctx, base); } // Rope renderables sometimes get bogus colors due to the material parameters of whatever // was rendered last leaking into their render state. We can reset them to fix it. static void SetDefaultMaterialParameters(GuestDevice* device) { const be diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; const be ambient[] = { 1.0f, 1.0f, 1.0f, 0.0f }; const be specular[] = { 0.9f, 0.9f, 0.9f, 0.0f }; memcpy(&device->pixelShaderFloatConstants[64], diffuse, sizeof(diffuse)); // g_Diffuse memcpy(&device->pixelShaderFloatConstants[68], ambient, sizeof(ambient)); // g_Ambient memcpy(&device->pixelShaderFloatConstants[72], specular, sizeof(specular)); // g_Specular device->dirtyFlags[1] = ~0ull; } // SWA::CRopeRenderable::Render PPC_FUNC_IMPL(__imp__sub_827CBF68); PPC_FUNC(sub_827CBF68) { SetDefaultMaterialParameters(reinterpret_cast(base + PPC_LOAD_U32(PPC_LOAD_U32(ctx.r4.u32)))); __imp__sub_827CBF68(ctx, base); } // SWA::CObjUpReel::CPrimitiveReel::Render PPC_FUNC_IMPL(__imp__sub_8260BBF8); PPC_FUNC(sub_8260BBF8) { SetDefaultMaterialParameters(reinterpret_cast(base + PPC_LOAD_U32(PPC_LOAD_U32(ctx.r4.u32)))); __imp__sub_8260BBF8(ctx, base); } // The pedestal in Gaia Temple is placed on an opaque mesh slot, despite using additive blending. // This somehow works. Except when the delta time is too stable, it flashes black for one frame. // We can fix it by detecting the asset runtime, and swapping the mesh slots to transparent by hand. // Hedgehog::Mirage::CModelData::Make PPC_FUNC_IMPL(__imp__sub_82E38650); PPC_FUNC(sub_82E38650) { if (ctx.r5.u32 == 0xBB90 && XXH3_64bits(base + ctx.r4.u32, ctx.r5.u32) == 0xB524C8C3B80C3F54) { // Mesh Count std::swap( *reinterpret_cast(base + ctx.r4.u32 + 0x18), *reinterpret_cast(base + ctx.r4.u32 + 0x20)); // Mesh Offset std::swap( *reinterpret_cast(base + ctx.r4.u32 + 0x1C), *reinterpret_cast(base + ctx.r4.u32 + 0x24)); } __imp__sub_82E38650(ctx, base); }