OpenBarnyard
 
Loading...
Searching...
No Matches
ABINKMoviePlayer.cpp
Go to the documentation of this file.
1#include "pch.h"
2
3#ifdef TOSHI_SKU_WINDOWS
5#endif // TOSHI_SKU_WINDOWS
6
7#include "ABINKMoviePlayer.h"
8
9#include <Toshi/TSystem.h>
11
12#include <fmod/fmod.h>
13
14//-----------------------------------------------------------------------------
15// Enables memory debugging.
16// Note: Should be the last include!
17//-----------------------------------------------------------------------------
18#include <Core/TMemoryDebugOn.h>
19
21
23
25{
26 m_Bink = TNULL;
27 m_bPlaying = TFALSE;
28 m_bPaused = TFALSE;
29 m_bVisible = TFALSE;
30 m_pSurface = TNULL;
31 m_iNumRects = 0;
32}
33
35{
36 BinkSetMemory(
37 []( unsigned int size ) {
38 return TMalloc( size );
39 },
40 []( void* ptr ) {
41 TFree( ptr );
42 }
43 );
44
45 int iOutput = FSOUND_GetOutput();
46
47 if ( iOutput == FSOUND_OUTPUT_WINMM )
48 {
49 BinkSetSoundSystem( BinkOpenWaveOut, 0 );
50 }
51 else if ( iOutput == FSOUND_OUTPUT_DSOUND )
52 {
53 auto outHandle = FSOUND_GetOutputHandle();
54
55 if ( outHandle )
56 {
57 BinkSetSoundSystem( BinkOpenDirectSound, TREINTERPRETCAST( int, outHandle ) );
58 }
59 }
60
61 return TTRUE;
62}
63
65{
66 if ( !IsMoviePlaying() )
67 {
68 return TTRUE;
69 }
70
71 if ( m_Bink->LastFrameNum == m_Bink->Frames )
72 {
73 StopMovie();
74 return TTRUE;
75 }
76
77 if ( g_oSystemManager.IsPaused() )
78 {
79 if ( !m_bPaused )
80 {
81 BinkPause( m_Bink, 1 );
82 BinkSetSoundOnOff( m_Bink, 0 );
83 m_bPaused = TTRUE;
84 }
85 }
86 else
87 {
88 if ( m_bPaused )
89 {
90 BinkPause( m_Bink, 0 );
91 BinkSetSoundOnOff( m_Bink, 1 );
92 m_bPaused = TFALSE;
93 }
94 }
95
96 auto iWaitRes = BinkWait( m_Bink );
97
98 if ( iWaitRes == 0 )
99 {
100 if ( BinkDoFrame( m_Bink ) == 0 )
101 {
102 if ( !m_bVideoFitsBackBuffer || !m_pSurface )
103 {
104 if ( !m_pRects )
105 {
106 if ( !CreateSurfaces() )
107 {
108 return TTRUE;
109 }
110
111 m_eFormat |= 0x80000000;
112 }
113 }
114
115 auto ppRenderSurface = &m_pSurface;
116
117 if ( m_bVideoFitsBackBuffer ||
118 TSTATICCAST( TTextureResourceHAL, m_pRects[ 0 ].pTexture )->GetD3DTexture()->GetSurfaceLevel( 0, ppRenderSurface ) == S_OK )
119 {
120 D3DLOCKED_RECT rect;
121 if ( S_OK == ( *ppRenderSurface )->LockRect( &rect, TNULL, 0 ) )
122 {
123 BinkCopyToBuffer( m_Bink, rect.pBits, rect.Pitch, m_Bink->Height, 0, 0, m_eFormat );
124 m_eFormat &= 0x7fffffff;
125 ( *ppRenderSurface )->UnlockRect();
126
127 if ( !m_bVideoFitsBackBuffer )
128 {
129 ( *ppRenderSurface )->Release();
130 ( *ppRenderSurface ) = TNULL;
131 }
132 }
133 }
134 }
135
136 BinkNextFrame( m_Bink );
137 }
138
139 m_bVisible = TTRUE;
140 return TTRUE;
141}
142
146
147TBOOL ABINKMoviePlayer::PlayMovie( const TCHAR* a_szFileName, TUINT32 a_Unk )
148{
149 TVALIDPTR( a_szFileName );
150
151 SetMovieFile( a_szFileName );
152 m_Bink = BinkOpen( m_szMoviePath, 0 );
153
154 if ( m_Bink != TNULL )
155 {
156 if ( !CreateSurfaces() )
157 {
158 BinkClose( m_Bink );
159 m_Bink = TNULL;
160 return TFALSE;
161 }
162
163 m_bPlaying = TTRUE;
164 m_bVisible = TFALSE;
165 m_bPaused = TFALSE;
166 OnUpdate( 0.0f );
167 }
168
169 return m_Bink != TNULL;
170}
171
172TBOOL ABINKMoviePlayer::CreateSurfaces()
173{
174 auto pRender = TRenderD3DInterface::Interface();
175 auto pDevice = pRender->GetDirect3DDevice();
176
177 IDirect3DSurface8* pSurface;
178 auto hRes = pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pSurface );
179
180 if ( hRes == S_OK )
181 {
182 D3DSURFACE_DESC desc;
183 hRes = pSurface->GetDesc( &desc );
184
185 if ( hRes == S_OK )
186 {
187 switch ( desc.Format )
188 {
189 case D3DFMT_R8G8B8:
190 m_eFormat = 1;
191 break;
192 case D3DFMT_A8R8G8B8:
193 m_eFormat = 5;
194 break;
195 case D3DFMT_X8R8G8B8:
196 m_eFormat = 3;
197 break;
198 case D3DFMT_R5G6B5:
199 m_eFormat = 10;
200 break;
201 case D3DFMT_X1R5G5B5:
202 m_eFormat = 9;
203 break;
204 case D3DFMT_A1R5G5B5:
205 m_eFormat = 8;
206 break;
207 case D3DFMT_A4R4G4B4:
208 m_eFormat = 7;
209 break;
210 }
211 }
212
213 if ( desc.Width == m_Bink->Width && desc.Height == m_Bink->Height )
214 {
215 m_bVideoFitsBackBuffer = TTRUE;
216 hRes = pDevice->CreateImageSurface( desc.Width, desc.Height, desc.Format, &m_pSurface );
217 }
218 else
219 {
220 m_bVideoFitsBackBuffer = TFALSE;
221 CreateAGUISurfaces( desc.Width, desc.Height, desc.Format );
222 }
223
224 pSurface->Release();
225 }
226
227 return hRes == S_OK;
228}
229
231{
232 if ( m_Bink )
233 {
234 BinkClose( m_Bink );
235 m_Bink = TNULL;
236 DestroySurfaces();
237 }
238
239 m_bPlaying = TFALSE;
240 m_bVisible = TFALSE;
241 m_bPaused = TFALSE;
242}
243
245{
246 m_bPaused = a_bPause;
247}
248
250{
251 return m_bPlaying;
252}
253
255{
256 return m_bPaused;
257}
258
260{
261 if ( IsMoviePlaying() && m_bVisible )
262 {
264
265 if ( m_bVideoFitsBackBuffer )
266 {
267 IDirect3DSurface8* pSurface;
268 auto hRes = pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pSurface );
269
270 if ( hRes == S_OK )
271 {
272 pDevice->CopyRects( m_pSurface, TNULL, 0, pSurface, TNULL );
273 pSurface->Release();
274 }
275 }
276 else
277 {
278 auto pRender = AGUI2::GetRenderer();
279
280 pRender->BeginScene();
281
282 for ( TINT i = 0; i < m_iNumRects; i++ )
283 {
284 pRender->SetMaterial( m_pRects[ i ].pMaterial );
285 pRender->RenderRectangle( m_pRects[ i ].Pos1, m_pRects[ i ].Pos2, m_pRects[ i ].UV1, m_pRects[ i ].UV2 );
286 }
287
288 pRender->EndScene();
289 }
290 }
291}
292
294{
295 TStringManager::String8Format( m_szMoviePath, sizeof( m_szMoviePath ), "Data/Movies/%s.bik", a_szFile );
296}
297
298TBOOL ABINKMoviePlayer::CreateAGUISurfaces( TUINT a_uiWidth, TUINT a_uiHeight, D3DFORMAT a_eFormat )
299{
301
302 D3DCAPS8 caps;
303 auto hRes = pDevice->GetDeviceCaps( &caps );
304
305 if ( hRes == S_OK )
306 {
307 TUINT uiWidth = m_Bink->Width;
308 TUINT uiHeight = m_Bink->Height;
309 TUINT uiMaxTextureWidth = caps.MaxTextureWidth;
310 TUINT uiMaxTextureHeight = caps.MaxTextureHeight;
311
312 m_iNumRects = ( ( uiHeight - 1 ) + uiMaxTextureHeight ) / uiMaxTextureHeight * ( ( uiWidth - 1 ) + uiMaxTextureWidth ) / uiMaxTextureWidth;
313 m_pRects = new Rect[ m_iNumRects ];
314
316
317 TFLOAT fWidth, fHeight;
318 AGUI2::GetSingleton()->GetDimensions( fWidth, fHeight );
319
320 TFLOAT fScaleX = a_uiWidth / ( ( pDisplayParams->uiWidth / fWidth ) * m_Bink->Width );
321 TFLOAT fScaleY = a_uiHeight / ( ( pDisplayParams->uiHeight / fHeight ) * m_Bink->Height );
322
324
325 if ( a_eFormat == D3DFMT_A8R8G8B8 )
326 {
327 eFormat = TTEXTURERESOURCEFORMAT::R8G8B8A8;
328 }
329 else if ( a_eFormat == D3DFMT_X8R8G8B8 )
330 {
331 eFormat = TTEXTURERESOURCEFORMAT::R8G8B8;
332 }
333 else if ( a_eFormat == D3DFMT_A1R5G5B5 )
334 {
335 eFormat = TTEXTURERESOURCEFORMAT::R5G5B5A1;
336 }
337 else
338 {
339 return TFALSE;
340 }
341
342 TFLOAT fVideoWidth = TMath::Abs( TFLOAT( m_Bink->Width ) );
343 TFLOAT fVideoHeight = TMath::Abs( TFLOAT( m_Bink->Height ) );
344
345 TUINT uiPosY = 0;
346 TUINT uiRectIndex = 0;
347
348 TUINT uiLeftHeight = uiHeight;
349 while ( 0 < TINT( uiLeftHeight ) )
350 {
351 TUINT uiRectHeight = TMath::Min( uiLeftHeight, uiMaxTextureHeight );
352 uiWidth = m_Bink->Width;
353
354 TUINT uiPosX = 0;
355 TUINT uiLeftWidth = m_Bink->Width;
356
357 while ( 0 < TINT( uiLeftWidth ) )
358 {
359 TUINT uiRectWidth = TMath::Min( uiLeftWidth, uiMaxTextureWidth );
360 TBOOL bCreated = m_pRects[ uiRectIndex ].Create(
361 uiPosX,
362 uiPosY,
363 uiRectWidth,
364 uiRectHeight,
365 ( uiPosX + fVideoWidth * -0.5f ) * fScaleX,
366 ( uiPosY + fVideoHeight * -0.5f ) * fScaleY,
367 uiRectWidth * fScaleX,
368 uiRectHeight * fScaleY,
369 eFormat
370 );
371
372 if ( !bCreated )
373 {
374 TASSERT( TFALSE, "ABINKMoviePlayer: Unable to create rectangle" );
375 delete[] m_pRects;
376 m_pRects = TNULL;
377 return TFALSE;
378 }
379
380 uiPosX += TMath::Min( uiWidth, uiMaxTextureWidth );
381
382 uiLeftWidth -= uiRectWidth;
383 uiRectIndex++;
384 }
385
386 uiPosY += uiRectHeight;
387 uiLeftHeight -= uiRectHeight;
388 }
389 }
390
391 return hRes == S_OK;
392}
393
394void ABINKMoviePlayer::DestroySurfaces()
395{
396 if ( m_pSurface )
397 {
398 m_pSurface->Release();
399 m_pSurface = TNULL;
400 }
401
402 delete[] m_pRects;
403 m_pRects = TNULL;
404 m_iNumRects = 0;
405}
406
407ABINKMoviePlayer::Rect::~Rect()
408{
409 if ( pMaterial )
410 {
411 AGUI2::GetRenderer()->DestroyMaterial( pMaterial );
412 pMaterial = TNULL;
413 }
414
415 if ( pTexture )
416 {
417 pTexture->DestroyResource();
418 pTexture = TNULL;
419 }
420
421 delete[] pData;
422 pData = TNULL;
423}
424
425TBOOL ABINKMoviePlayer::Rect::Create( int a_iPosX, int a_iPosY, int a_iWidth, int a_iHeight, TFLOAT a_iRenderPos1X, TFLOAT a_iRenderPos1Y, TFLOAT a_iRenderWidth, TFLOAT a_iRenderHeight, TTEXTURERESOURCEFORMAT a_eFormat )
426{
427 iPosY = a_iPosY;
428 iPosX = a_iPosX;
429 iWidth = a_iWidth;
430 iHeight = a_iHeight;
431 Pos1 = { a_iRenderPos1X, a_iRenderPos1Y };
432 Pos2 = { a_iRenderPos1X + a_iRenderWidth, a_iRenderPos1Y + a_iRenderHeight };
433
434 TUINT32 uiWidth = TMath::RoundToNextPowerOfTwo( a_iWidth );
435 TUINT32 uiHeight = TMath::RoundToNextPowerOfTwo( a_iHeight );
436 TINT iPixelSize;
437
438 if ( a_eFormat == TTEXTURERESOURCEFORMAT::Unknown )
439 {
440 return TFALSE;
441 }
442 else if ( a_eFormat == TTEXTURERESOURCEFORMAT::R8G8B8A8 || a_eFormat == TTEXTURERESOURCEFORMAT::R8G8B8 )
443 {
444 iPixelSize = 4;
445 }
446 else if ( a_eFormat == TTEXTURERESOURCEFORMAT::R5G5B5A1 )
447 {
448 iPixelSize = 2;
449 }
450 else
451 {
452 return TFALSE;
453 }
454
455 auto uiDataSize = iPixelSize * uiWidth * uiHeight;
456 pData = new TUINT8[ uiDataSize ];
457 auto pTexFactory = TRenderInterface::GetSingleton()->GetSystemResource<TTextureFactory>( SYSRESOURCE_TEXTUREFACTORY );
458
459 pTexture = pTexFactory->CreateEx( pData, uiDataSize, uiWidth, uiHeight, 1, a_eFormat, 4 );
460 pTexture->SetAddressing( ADDRESSINGMODE_CLAMP );
461
462 pMaterial = AGUI2::GetRenderer()->CreateMaterial( pTexture );
463 pMaterial->SetBlendState( 0 );
464
465 UV1 = { 0.0f, 0.0f };
466 UV2 = { TFLOAT( a_iWidth ) / uiWidth, TFLOAT( a_iHeight ) / uiHeight };
467
468 return TTRUE;
469}
void * TMalloc(TSIZE a_uiSize, Toshi::TMemory::MemBlock *a_pMemBlock, const TCHAR *a_szFileName, TINT a_iLineNum)
Allocates memory from a specific memory block.
Definition TMemory.cpp:973
void TFree(void *a_pMem)
Frees previously allocated memory.
Definition TMemory.cpp:1054
@ SYSRESOURCE_TEXTUREFACTORY
Definition TRender.h:20
@ ADDRESSINGMODE_CLAMP
Definition TRender.h:42
#define TASSERT(X,...)
Definition Defines.h:138
#define TSTATICCAST(POINTERTYPE, VALUE)
Definition Defines.h:69
#define TREINTERPRETCAST(TYPE, VALUE)
Definition Defines.h:68
#define TOSHI_NAMESPACE_USING
Definition Defines.h:46
#define TVALIDPTR(PTR)
Definition Defines.h:139
#define TDEFINE_CLASS(...)
Definition TObject.h:120
unsigned int TUINT
Definition Typedefs.h:8
char TCHAR
Definition Typedefs.h:20
uint8_t TUINT8
Definition Typedefs.h:17
float TFLOAT
Definition Typedefs.h:4
#define TNULL
Definition Typedefs.h:23
uint32_t TUINT32
Definition Typedefs.h:13
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
TSystemManager g_oSystemManager
Definition TSystem.cpp:15
TFORCEINLINE TFLOAT Abs(TFLOAT fVal)
Definition TMathInline.h:63
constexpr TUINT RoundToNextPowerOfTwo(TUINT a_uiValue)
Definition TMathInline.h:71
TFORCEINLINE const T & Min(const T &a, const T &b)
TFORCEINLINE IDirect3DDevice8 * GetDirect3DDevice() const
Gets the Direct3D device.
static TFORCEINLINE TRenderD3DInterface * Interface()
Gets the render interface singleton.
virtual DISPLAYPARAMS * GetCurrentDisplayParams() OVERRIDE
Gets the current display parameters.
T * GetSystemResource(SYSRESOURCE systemResource)
static TFORCEINLINE TRenderInterface * GetSingleton()
Definition TSingleton.h:49
static void String8Format(TCHAR *str, TINT size, const TCHAR *format,...)
static AGUI2Renderer * GetRenderer()
Definition AGUI2.cpp:239
void SetBlendState(TUINT a_eBlendState)
virtual AGUI2Material * CreateMaterial(const TCHAR *a_szTextureName)=0
virtual void DestroyMaterial(AGUI2Material *a_pMaterial)=0
virtual void Render(TFLOAT a_fDeltaTime) override
virtual void SetMovieFile(const TCHAR *a_szFile)
virtual TBOOL IsMoviePaused() override
virtual TBOOL IsMoviePlaying() override
virtual TBOOL OnCreate() override
virtual void StopMovie() override
virtual void PauseMovie(TBOOL a_bPause) override
virtual void OnDestroy() override
virtual TBOOL PlayMovie(const TCHAR *a_szFileName, TUINT32 a_Unk) override
virtual TBOOL OnUpdate(TFLOAT a_fDeltaTime) override