diff --git a/config/373307D9/objects.json b/config/373307D9/objects.json index 55e608de..1a233396 100644 --- a/config/373307D9/objects.json +++ b/config/373307D9/objects.json @@ -454,7 +454,7 @@ "system/movie/Movie.cpp": "Matching", "system/movie/MovieImpl.cpp": "Matching", "system/movie/MovieSys.cpp": "Matching", - "system/movie/Splash.cpp": "NonMatching", + "system/movie/Splash.cpp": "Matching", "system/movie/TexMovie.cpp": "Matching", "system/moviebink/BinkMovieImpl.cpp": "NonMatching", "system/moviebink/BinkMovieImpl_Xbox.cpp": "MISSING", diff --git a/config/373307D9/symbols.txt b/config/373307D9/symbols.txt index c4a8a5c2..885542ee 100644 --- a/config/373307D9/symbols.txt +++ b/config/373307D9/symbols.txt @@ -180417,7 +180417,7 @@ merged_82AF65E8 = .text:0x82AF65E8; // type:function size:0x5C scope:global ??1?$CSPGUIDPtrHash@PAVCFEClassInfo@NUISPEECH@@@NUISPEECH@@UAA@XZ = .text:0x82AF6648; // type:function size:0x5C scope:global ?DestroyValue@?$CSPGUIDPtrHash@PAVCFEClassInfo@NUISPEECH@@@NUISPEECH@@MBAXPAVCFEClassInfo@2@@Z = .text:0x82AF66A8; // type:function size:0x18 scope:global merged_82AF66C0 = .text:0x82AF66C0; // type:function size:0x230 scope:global -merged_82AF68F0 = .text:0x82AF68F0; // type:function size:0x8 scope:global +merged_Get0x3C = .text:0x82AF68F0; // type:function size:0x8 scope:global ?Reset@CFEWaveStreamDecoder@NUISPEECH@@UAAJXZ = .text:0x82AF68F8; // type:function size:0x30 scope:global merged_82AF6928 = .text:0x82AF6928; // type:function size:0x5C scope:global ?CreateDecoder@CFEWaveStreamCoder@NUISPEECH@@UAAPAVCFEStreamDecoder@2@XZ = .text:0x82AF6988; // type:function size:0x94 scope:global diff --git a/src/macros.h b/src/macros.h index 6005b344..69e302a1 100644 --- a/src/macros.h +++ b/src/macros.h @@ -10,6 +10,9 @@ #define SEH_TRY __try #define SEH_EXCEPT __except #define SEH_FINALLY __finally + +#define ALIGN(x) __declspec(align(x)) +#define INTRIN __declspec(intrin_type) #else #define CDECL #define STDCALL @@ -18,6 +21,9 @@ #define SEH_TRY try #define SEH_EXCEPT catch #define SEH_FINALLY ; + +#define ALIGN(x) alignas(x) +#define INTRIN #endif // #define ROTATE_LEFT(x, i) (((x) << (i)) | ((x) >> ((sizeof((x)) * 8) - (i)))) diff --git a/src/system/movie/Splash.cpp b/src/system/movie/Splash.cpp index 5eb97deb..c4acfb4d 100644 --- a/src/system/movie/Splash.cpp +++ b/src/system/movie/Splash.cpp @@ -61,7 +61,7 @@ void Splash::Suspend() { } else { WaitForState(kSuspended); } - unk200.Reset(); + unk_0xC8.Reset(); } } @@ -202,6 +202,60 @@ void Splash::Poll() { } } +void Splash::Draw() { + if (unk18.SplitMs() <= mSplashTime) { + if (!unk5c || unk50 != nullptr || unk54 != nullptr) { + if (unk54 != nullptr) { + TheTaskMgr.Poll(); + unk48->Poll(); + } + if (unk50 != nullptr) { + if (MainThread()) { + float allowance = unk50->GetMovie().MsPerFrame() - 1.0f; + if (unk_0xC8.Running() != 0 && unk_0xC8.SplitMs() < allowance) { + return; + } + unk_0xC8.Restart(); + } + if (unk50->GetMovie().Poll() == false) { + mSplashTime = 0; + return; + } + } + for (int i = 0; i < 2; i++) { + TheRnd.BeginDrawing(); + unk4c->Select(); + unk48->DrawShowing(); + TheRnd.EndDrawing(); + if (unk50 != nullptr) + break; + if (unk54 != nullptr) + break; + } + if (unk50 == nullptr && unk54 == nullptr) { + TheNgRnd.Suspend(); + } + unk5c = true; + } + int synctime = 0; + if (!MainThread()) { + synctime = mSplashTime - int(unk18.SplitMs()); + if (unk50 != nullptr) { + float allowance = unk50->GetMovie().MsPerFrame() - 1.0f; + if (int(allowance) < synctime) { + synctime = allowance; + } + if (synctime < 0) { + synctime = 0; + } + } else if (unk54 != nullptr) { + synctime = 16; + } + unk90.Wait(synctime); + } + } +} + bool Splash::SetMutableState(Splash::SplashState state) { MILO_ASSERT(state <= kResumed, 0x13b); CritSecTracker tracker(&unk6c); @@ -231,7 +285,8 @@ bool Splash::SetImmutableState(Splash::SplashState state) { void Splash::WaitForState(Splash::SplashState state) { MILO_ASSERT_FMT(unk64, "Can't WaitForState"); - while (mState != state && (state != kResumed || mState <= kResumed)) { + while (mState != state + && (state != kResumed || (volatile SplashState)mState <= kResumed)) { MainThread() ? unk8c.Wait(-1) : unk90.Wait(-1); } } diff --git a/src/system/movie/Splash.h b/src/system/movie/Splash.h index 86a1fda9..4d3bf98d 100644 --- a/src/system/movie/Splash.h +++ b/src/system/movie/Splash.h @@ -63,7 +63,7 @@ class Splash { CriticalSection unk98; std::list mPreparedScreens; // 0xb8 std::list unkc0; - Timer unk200; + Timer unk_0xC8; void *mThreadStack; protected: diff --git a/src/system/moviebink/BinkMovieImpl.cpp b/src/system/moviebink/BinkMovieImpl.cpp index 396024b9..78acad9d 100644 --- a/src/system/moviebink/BinkMovieImpl.cpp +++ b/src/system/moviebink/BinkMovieImpl.cpp @@ -741,7 +741,23 @@ void BinkMovieImpl::FinishOpen() { BinkSetSoundOnOff(mBink, unk27 == 0); BINKSUMMARY summary; BinkGetSummary(mBink, &summary); - + mAspect = float(summary.Width) / summary.Height; + int width_low_4 = summary.Width % 16; + if (summary.Height % 16 != 0 || width_low_4 != 0) { + int height_low_4 = summary.Height % 16; + int width_fixed = summary.Width; + width_fixed += width_low_4 != 0 ? 16 - width_low_4 : 0; + int height_fixed = summary.Height; + height_fixed += height_low_4 != 0 ? 16 - height_low_4 : 0; + MILO_FAIL( + "Bink movie %s must have multiples of 16 for its width and height.\nTry changing from %d x %d to %d x %d.", + mName.c_str(), + summary.Width, + summary.Height, + width_fixed, + height_fixed + ); + } SetRect(); SetPaused(true); } diff --git a/src/system/synth360/GainEffect.cpp b/src/system/synth360/GainEffect.cpp index 57909dd7..c01c9f59 100644 --- a/src/system/synth360/GainEffect.cpp +++ b/src/system/synth360/GainEffect.cpp @@ -1,4 +1,7 @@ #include "synth360/GainEffect.h" +#include "vectorintrinsics.h" +#include +#include float GainEffect::sGain = 1; @@ -6,3 +9,38 @@ GainEffect::GainEffect() { GainEffectParams p; SetParameters(&p, sizeof(p)); } + +void GainEffect::DoProcess( + const GainEffectParams &, float *samples, uint samplect, uint channelct +) { + uint data_count = samplect * channelct; + XMVECTOR *samples_simd = reinterpret_cast(samples); + XMVECTOR gain; + gain.v[0] = sGain; + for (int i = 0; i < 3; i++) { + gain.u[i + 1] = gain.u[i]; + } + float *endpoint = samples + data_count; + if (samples >= endpoint) + return; + int i = 0; + uint pass_count = + reinterpret_cast(endpoint) - reinterpret_cast(samples) - 1; + pass_count /= sizeof(XMVECTOR) * 4; + pass_count++; + do { // why like this...? + XMVECTOR v0 = __lvx(samples_simd + i, 0x00); + XMVECTOR v1 = __lvx(samples_simd + i, 0x10); + XMVECTOR v2 = __lvx(samples_simd + i, 0x20); + XMVECTOR v3 = __lvx(samples_simd + i, 0x30); + v0 = __vmulfp(v0, gain); + v1 = __vmulfp(v1, gain); + v2 = __vmulfp(v2, gain); + v3 = __vmulfp(v3, gain); + __stvx(v0, samples_simd + i, 0x00); + __stvx(v1, samples_simd + i, 0x10); + __stvx(v2, samples_simd + i, 0x20); + __stvx(v3, samples_simd + i, 0x30); + i += 4; + } while (--pass_count); +} diff --git a/src/system/synth360/SampleInst.cpp b/src/system/synth360/SampleInst.cpp index 474be79c..9e4f9797 100644 --- a/src/system/synth360/SampleInst.cpp +++ b/src/system/synth360/SampleInst.cpp @@ -3,6 +3,8 @@ #include "synth/FxSend.h" #include "synth360/SynthSample.h" #include "synth360/FxSend.h" +#include "xdk/win_types.h" +#include "xdk/xaudio2/xaudio2.h" SampleInst360::SampleInst360(SynthSample360 *sample, bool loop, int loopStart, int loopEnd) : SampleInst(sample), @@ -33,6 +35,28 @@ float SampleInst360::ElapsedTime() { return samples / rate; } +float SampleInst360::GetProgress() { + XAUDIO2_VOICE_STATE state; + mVoice->GetVoice()->GetState(&state, 0); + SIZE_T samples = state.SamplesPlayed; + if (mVoice->GetLoopStart() >= 0) { + int sample_start = mVoice->GetSampleStart(); + samples -= sample_start; + int loop_start = mVoice->GetLoopStart(); + int loop_end = mVoice->GetLoopEnd(); + if (loop_end == -1) { + loop_end = mVoice->GetSampleCount(); + } + int loop_size = loop_end - loop_start; + int loop_count = samples / loop_size; + samples -= loop_count * loop_size; + samples += sample_start; + } + float len = mSample->LengthMs(); + float rate = mSample->GetSampleRate(); + return (samples * 1000.0f) / (rate * len); +} + void SampleInst360::StartImpl() { mVoice->Start(); } void SampleInst360::StopImpl(bool b1) { mVoice->Stop(b1); } void SampleInst360::SetVolumeImpl(float f1) { mVoice->SetVolume(f1); } diff --git a/src/system/synth360/Voice.h b/src/system/synth360/Voice.h index 4a7b0558..77ad0265 100644 --- a/src/system/synth360/Voice.h +++ b/src/system/synth360/Voice.h @@ -42,6 +42,10 @@ class Voice { void Start(); IXAudio2SourceVoice *GetVoice() { return mPoolVoice.voice; } + int GetSampleStart() const { return mSampleStart; } + int GetSampleCount() const { return mNumSamples; } + int GetLoopStart() const { return mLoopStart; } + int GetLoopEnd() const { return mLoopEnd; } void SetAttackRate(float r) { unk30 = r; } void SetReleaseRate(float r) { unk34 = r; } void SetUnk50(int i) { unk50 = i; } diff --git a/src/xdk/LIBCMT/vectorintrinsics.h b/src/xdk/LIBCMT/vectorintrinsics.h index 2839221b..ac26fd29 100644 --- a/src/xdk/LIBCMT/vectorintrinsics.h +++ b/src/xdk/LIBCMT/vectorintrinsics.h @@ -1,7 +1,9 @@ #pragma once +#include "macros.h" + // A C representation of a VMX register. -typedef struct __declspec(intrin_type) __declspec(align(16)) __vector4 { /* Size=0x10 */ +typedef struct INTRIN ALIGN(16) __vector4 { /* Size=0x10 */ union { /* 0x0000 */ float vector4_f32[4]; /* 0x0000 */ unsigned int vector4_u32[4]; @@ -119,6 +121,9 @@ XMVECTOR __vmaddfp(XMVECTOR mul1, XMVECTOR mul2, XMVECTOR addend); // Vector128 Splat Word XMVECTOR __vspltw(XMVECTOR vSrcA, unsigned int uImmed); +// Vector128 Multiply Floating-Point +XMVECTOR __vmulfp(XMVECTOR vSrcA, XMVECTOR vSrcB); + #ifdef __cplusplus } #endif