@@ -594,25 +594,122 @@ inline D3DXMATRIX* D3DXMatrixTranslation(D3DXMATRIX* pOut, float x, float y, flo
594594#endif // WWMATH_AVAILABLE
595595
596596// -----------------------------------------------------------------------------
597- // Shader Functions
597+ // Shader Functions (Precompiled Shaders)
598598// -----------------------------------------------------------------------------
599599
600600#ifdef __cplusplus
601601
602- // ID3DXBuffer interface stub
602+ // Forward declaration
603+ struct ID3DXBuffer ;
604+
605+ // Precompiled shader bytecode (generated from .psh files)
606+ namespace D3DXCompat_Shaders {
607+
608+ // Note: These are simplified PS 1.1 bytecode arrays
609+ // Generated by scripts/compile_shaders.py from scripts/shaders/water_shader*.psh files
610+ // May need validation/correction for production use
611+
612+ // River water shader (water_shader1.psh)
613+ static constexpr DWORD shader1_bytecode[] = {
614+ 0xFFFF0101 , 0x00000042 , 0x000F0300 , 0x00000042 ,
615+ 0x000F0301 , 0x00000042 , 0x000F0302 , 0x00000042 ,
616+ 0x000F0303 , 0x00000005 , 0x000F0000 , 0x000F0100 ,
617+ 0x000F0300 , 0x00000005 , 0x000F0001 , 0x000F0301 ,
618+ 0x000F0302 , 0x00000003 , 0x00070000 , 0x000F0000 ,
619+ 0x000F0303 , 0x40000005 , 0x00080000 , 0x000F0000 ,
620+ 0x000F0303 , 0x00000003 , 0x00070000 , 0x000F0000 ,
621+ 0x000F0001 , 0x0000FFFF ,
622+ };
623+
624+ // Water with environment mapping (water_shader2.psh)
625+ static constexpr DWORD shader2_bytecode[] = {
626+ 0xFFFF0101 , 0x00000042 , 0x000F0300 , 0x00000042 ,
627+ 0x000F0301 , 0x00000043 , 0x000F0302 , 0x000F0301 ,
628+ 0x00000005 , 0x000F0000 , 0x000F0100 , 0x000F0300 ,
629+ 0x00000005 , 0x00070001 , 0x000F0302 , 0x000F0200 ,
630+ 0x00000003 , 0x00070000 , 0x000F0000 , 0x000F0001 ,
631+ 0x0000FFFF ,
632+ };
633+
634+ // Trapezoid water shader (water_shader3.psh)
635+ static constexpr DWORD shader3_bytecode[] = {
636+ 0xFFFF0101 , 0x00000042 , 0x000F0300 , 0x00000042 ,
637+ 0x000F0301 , 0x00000042 , 0x000F0302 , 0x00000042 ,
638+ 0x000F0303 , 0x00000005 , 0x000F0000 , 0x000F0100 ,
639+ 0x000F0300 , 0x00000004 , 0x00070000 , 0x000F0301 ,
640+ 0x000F0302 , 0x000F0000 , 0x00000005 , 0x00070000 ,
641+ 0x000F0000 , 0x000F0303 , 0x0000FFFF ,
642+ };
643+
644+ } // namespace D3DXCompat_Shaders
645+
646+ // ID3DXBuffer interface definition
603647struct ID3DXBuffer
604648{
605- virtual HRESULT __stdcall QueryInterface (const IID & , void * * ) { return E_NOTIMPL ; }
606- virtual ULONG __stdcall AddRef () { return 1 ; }
607- virtual ULONG __stdcall Release () { return 0 ; }
608- virtual void * __stdcall GetBufferPointer () { return nullptr ; }
609- virtual DWORD __stdcall GetBufferSize () { return 0 ; }
649+ virtual HRESULT __stdcall QueryInterface (const IID&, void **) = 0;
650+ virtual ULONG __stdcall AddRef () = 0;
651+ virtual ULONG __stdcall Release () = 0;
652+ virtual void * __stdcall GetBufferPointer () = 0;
653+ virtual DWORD __stdcall GetBufferSize () = 0;
654+ };
655+
656+ // ID3DXBuffer implementation for shader bytecode
657+ class D3DXShaderBuffer : public ID3DXBuffer
658+ {
659+ private:
660+ const DWORD* m_pData;
661+ DWORD m_Size;
662+ mutable LONG m_RefCount;
663+
664+ public:
665+ D3DXShaderBuffer (const DWORD* pData, DWORD size)
666+ : m_pData(pData), m_Size(size), m_RefCount(1 ) {}
667+
668+ virtual ~D3DXShaderBuffer () {}
669+
670+ // IUnknown methods
671+ virtual HRESULT __stdcall QueryInterface (const IID& riid, void ** ppvObject)
672+ {
673+ if (!ppvObject) return E_POINTER;
674+ *ppvObject = nullptr ;
675+ return E_NOINTERFACE;
676+ }
677+
678+ virtual ULONG __stdcall AddRef ()
679+ {
680+ return InterlockedIncrement (&m_RefCount);
681+ }
682+
683+ virtual ULONG __stdcall Release ()
684+ {
685+ LONG ref = InterlockedDecrement (&m_RefCount);
686+ if (ref == 0 )
687+ delete this ;
688+ return ref;
689+ }
690+
691+ // ID3DXBuffer methods
692+ virtual void * __stdcall GetBufferPointer ()
693+ {
694+ return (void *)m_pData;
695+ }
696+
697+ virtual DWORD __stdcall GetBufferSize ()
698+ {
699+ return m_Size;
700+ }
610701};
611702
612703/* *
613704 * D3DXAssembleShader - Assemble shader from source
614705 *
615- * Stub implementation - returns error to indicate shader assembly not available.
706+ * Returns precompiled bytecode for known water shaders.
707+ * This implementation recognizes the three water shaders used by the game
708+ * and returns precompiled bytecode instead of performing runtime assembly.
709+ *
710+ * The bytecode is generated by a simplified PS 1.1 assembler and may need
711+ * validation. If issues occur, the game will gracefully fall back to
712+ * non-shader water rendering.
616713 */
617714inline HRESULT D3DXAssembleShader (
618715 const char * pSrcData,
@@ -622,9 +719,46 @@ inline HRESULT D3DXAssembleShader(
622719 ID3DXBuffer** ppCompiledShader,
623720 ID3DXBuffer** ppCompilationErrors)
624721{
625- // Stub: This function needs proper implementation
626- // For now, return error to indicate shader assembly not available
627- return E_NOTIMPL ;
722+ if (!pSrcData || !ppCompiledShader)
723+ return D3DERR_INVALIDCALL;
724+
725+ *ppCompiledShader = nullptr ;
726+ if (ppCompilationErrors)
727+ *ppCompilationErrors = nullptr ;
728+
729+ // Identify which shader is being assembled by matching key strings
730+ // This is safe because the game only assembles these specific shaders
731+
732+ // Shader 1: River water (has "+mul r0.a, r0, t3" - co-issued instruction)
733+ if (strstr (pSrcData, " +mul r0.a" ) != nullptr )
734+ {
735+ *ppCompiledShader = new D3DXShaderBuffer (
736+ D3DXCompat_Shaders::shader1_bytecode,
737+ sizeof (D3DXCompat_Shaders::shader1_bytecode));
738+ return S_OK;
739+ }
740+
741+ // Shader 2: Water with env mapping (has "texbem")
742+ if (strstr (pSrcData, " texbem" ) != nullptr )
743+ {
744+ *ppCompiledShader = new D3DXShaderBuffer (
745+ D3DXCompat_Shaders::shader2_bytecode,
746+ sizeof (D3DXCompat_Shaders::shader2_bytecode));
747+ return S_OK;
748+ }
749+
750+ // Shader 3: Trapezoid water (has "mad" instruction)
751+ if (strstr (pSrcData, " mad" ) != nullptr )
752+ {
753+ *ppCompiledShader = new D3DXShaderBuffer (
754+ D3DXCompat_Shaders::shader3_bytecode,
755+ sizeof (D3DXCompat_Shaders::shader3_bytecode));
756+ return S_OK;
757+ }
758+
759+ // Unknown shader - return error
760+ // The game will handle this gracefully and use fallback rendering
761+ return E_FAIL;
628762}
629763
630764#endif // __cplusplus
0 commit comments