diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index dbe8af58..8744adf5 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -48,6 +48,8 @@ If you have questions concerning this license or the applicable additional terms #include "../sys/sys_savegame.h" +#include "idlib/sys/sys_defines.h" + #if defined( _DEBUG ) #define BUILD_DEBUG "-debug" #else @@ -113,8 +115,8 @@ idGameEdit* gameEdit = NULL; idCommonLocal commonLocal; idCommon* common = &commonLocal; - -idCVar com_skipIntroVideos( "com_skipIntroVideos", "0", CVAR_BOOL , "skips intro videos" ); +// RB: defaulted this to 1 because we don't have a sound for the intro .bik video +idCVar com_skipIntroVideos( "com_skipIntroVideos", "1", CVAR_BOOL , "skips intro videos" ); // For doom classic struct Globals; @@ -900,14 +902,101 @@ void idCommonLocal::RenderBink( const char* path ) material->Parse( materialText.c_str(), materialText.Length(), false ); material->ResetCinematicTime( Sys_Milliseconds() ); - while( Sys_Milliseconds() <= material->GetCinematicStartTime() + material->CinematicLength() ) + // RB: FFmpeg might return the wrong play length so I changed the intro video to play max 30 seconds until finished + int cinematicLength = 30000; //material->CinematicLength(); + int mouseEvents[MAX_MOUSE_EVENTS][2]; + + bool escapeEvent = false; + while( ( Sys_Milliseconds() <= ( material->GetCinematicStartTime() + cinematicLength ) ) && material->CinematicIsPlaying() ) { renderSystem->DrawStretchPic( chop, 0, imageWidth, renderSystem->GetVirtualHeight(), 0, 0, 1, 1, material ); const emptyCommand_t* cmd = renderSystem->SwapCommandBuffers( &time_frontend, &time_backend, &time_shadows, &time_gpu ); renderSystem->RenderCommandBuffers( cmd ); + Sys_GenerateEvents(); + + // queue system events ready for polling + Sys_GetEvent(); + + // RB: allow to escape video by pressing anything + int numKeyEvents = Sys_PollKeyboardInputEvents(); + if( numKeyEvents > 0 ) + { + for( int i = 0; i < numKeyEvents; i++ ) + { + int key; + bool state; + + if( Sys_ReturnKeyboardInputEvent( i, key, state ) ) + { + if( key == K_ESCAPE && state == true ) + { + escapeEvent = true; + } + break; + } + } + + Sys_EndKeyboardInputEvents(); + } + + int numMouseEvents = Sys_PollMouseInputEvents( mouseEvents ); + if( numMouseEvents > 0 ) + { + for( int i = 0; i < numMouseEvents; i++ ) + { + int action = mouseEvents[i][0]; + switch( action ) + { + case M_ACTION1: + case M_ACTION2: + case M_ACTION3: + case M_ACTION4: + case M_ACTION5: + case M_ACTION6: + case M_ACTION7: + case M_ACTION8: + escapeEvent = true; + break; + + default: // some other undefined button + break; + } + } + } + + int numJoystickEvents = Sys_PollJoystickInputEvents( 0 ); + if( numJoystickEvents > 0 ) + { + for( int i = 0; i < numJoystickEvents; i++ ) + { + int action; + int value; + + if( Sys_ReturnJoystickInputEvent( i, action, value ) ) + { + if( action >= J_ACTION1 && action <= J_ACTION_MAX ) + { + if( value != 0 ) + { + escapeEvent = true; + break; + } + } + } + } + + Sys_EndJoystickInputEvents(); + } + + if( escapeEvent ) + { + break; + } + Sys_Sleep( 10 ); } + // RB end material->MakeDefault(); } @@ -1933,12 +2022,7 @@ CONSOLE_COMMAND( testSIMD, "test SIMD code", NULL ) // RB begin CONSOLE_COMMAND( testFormattingSizes, "test printf format security", 0 ) { -#ifdef _MSC_VER - common->Printf( " sizeof( int32 ): %Iu bytes\n", sizeof( int32 ) ); - common->Printf( " sizeof( int64 ): %Iu bytes\n", sizeof( int64 ) ); -#else - common->Printf( " sizeof( int32 ): %zu bytes\n", sizeof( int32 ) ); - common->Printf( " sizeof( int64 ): %zu bytes\n", sizeof( int64 ) ); -#endif + common->Printf( " sizeof( int32 ): %" PRIuSIZE " bytes\n", sizeof( int32 ) ); + common->Printf( " sizeof( int64 ): %" PRIuSIZE " bytes\n", sizeof( int64 ) ); } -// RB end \ No newline at end of file +// RB end diff --git a/neo/framework/File.cpp b/neo/framework/File.cpp index 7bb61ce8..0684de3e 100644 --- a/neo/framework/File.cpp +++ b/neo/framework/File.cpp @@ -31,6 +31,7 @@ If you have questions concerning this license or the applicable additional terms #pragma hdrstop #include "Unzip.h" +#include "idlib/sys/sys_defines.h" /* ================= @@ -844,11 +845,7 @@ int idFile_Memory::Write( const void* buffer, int len ) { if( maxSize != 0 ) { -#ifdef _MSC_VER - common->Error( "idFile_Memory::Write: exceeded maximum size %Iu", maxSize ); -#else - common->Error( "idFile_Memory::Write: exceeded maximum size %zu", maxSize ); -#endif + common->Error( "idFile_Memory::Write: exceeded maximum size %" PRIuSIZE "", maxSize ); return 0; } int extra = granularity * ( 1 + alloc / granularity ); @@ -934,13 +931,7 @@ void idFile_Memory::PreAllocate( size_t len ) { if( maxSize != 0 ) { -// RB begin -#ifdef _MSC_VER - idLib::Error( "idFile_Memory::SetLength: exceeded maximum size %Iu", maxSize ); -#else - idLib::Error( "idFile_Memory::SetLength: exceeded maximum size %zu", maxSize ); -#endif -// RB end + idLib::Error( "idFile_Memory::SetLength: exceeded maximum size %" PRIuSIZE "", maxSize ); } char* newPtr = ( char* )Mem_Alloc( len, TAG_IDFILE ); if( allocated > 0 ) @@ -1126,13 +1117,7 @@ void idFile_Memory::TruncateData( size_t len ) { if( len > allocated ) { -// RB begin -#ifdef _MSV_VER - idLib::Error( "idFile_Memory::TruncateData: len (%Iu) exceeded allocated size (%Iu)", len, allocated ); -#else - idLib::Error( "idFile_Memory::TruncateData: len (%zu) exceeded allocated size (%zu)", len, allocated ); -#endif -// RB end + idLib::Error( "idFile_Memory::TruncateData: len (%" PRIuSIZE ") exceeded allocated size (%" PRIuSIZE ")", len, allocated ); } else { @@ -2126,5 +2111,3 @@ CONSOLE_COMMAND( testEndianNessReset, "Tests the read/write compatibility betwee { fileSystem->RemoveFile( testEndianNessFilename ); } - - diff --git a/neo/framework/Zip.cpp b/neo/framework/Zip.cpp index 4246d520..fb1eca30 100644 --- a/neo/framework/Zip.cpp +++ b/neo/framework/Zip.cpp @@ -36,6 +36,7 @@ Contains external code for building ZipFiles. */ #include "Zip.h" +#include "idlib/sys/sys_defines.h" // #undef STDC @@ -504,13 +505,7 @@ bool idZipBuilder::CreateZipFileFromFiles( const idList< idFile_Memory* >& srcFi errcode = zipWriteInFileInZip( zf, buffer.Ptr(), ( unsigned int )bytesRead ); if( errcode != ZIP_OK ) { -// RB begin -#ifdef _MSC_VER - idLib::Warning( "Error writing to zipfile (%Iu bytes)!", bytesRead ); -#else - idLib::Warning( "Error writing to zipfile (%zu bytes)!", bytesRead ); -#endif -// RB end + idLib::Warning( "Error writing to zipfile (%" PRIuSIZE " bytes)!", bytesRead ); continue; } } @@ -618,13 +613,7 @@ bool idZipBuilder::AddFile( zipFile zf, idFile_Memory* src, bool deleteFile ) errcode = zipWriteInFileInZip( zf, buffer.Ptr(), ( unsigned int )bytesRead ); if( errcode != ZIP_OK ) { -// RB begin -#ifdef _MSC_VER - idLib::Warning( "Error writing to zipfile (%Iu bytes)!", bytesRead ); -#else - idLib::Warning( "Error writing to zipfile (%zu bytes)!", bytesRead ); -#endif -// RB end + idLib::Warning( "Error writing to zipfile (%" PRIuSIZE " bytes)!", bytesRead ); continue; } } diff --git a/neo/idlib/sys/sys_defines.h b/neo/idlib/sys/sys_defines.h index 11d3fee8..82940727 100644 --- a/neo/idlib/sys/sys_defines.h +++ b/neo/idlib/sys/sys_defines.h @@ -257,3 +257,22 @@ extern volatile int ignoredReturnValue; #define MIN_UNSIGNED_TYPE( x ) 0 #endif + + +/* + * Macros for format conversion specifications for integer arguments of type + * size_t or ssize_t. + */ +#ifdef _MSV_VER + +#define PRIiSIZE "Ii" +#define PRIuSIZE "Iu" +#define PRIxSIZE "Ix" + +#else // ifdef _MSV_VER + +#define PRIiSIZE "zi" +#define PRIuSIZE "zu" +#define PRIxSIZE "zx" + +#endif // ifdef _MSV_VER diff --git a/neo/libs/zlib/trees.c b/neo/libs/zlib/trees.c index b9c72b4c..1cbe076c 100644 --- a/neo/libs/zlib/trees.c +++ b/neo/libs/zlib/trees.c @@ -35,6 +35,7 @@ /* #define GEN_TREES_H */ #include "deflate.h" +#include "idlib/sys/sys_defines.h" #ifdef DEBUG # include @@ -940,17 +941,9 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; -// RB begin -#ifdef _MSC_VER - Tracev((stderr, "\nopt %Iu(%Iu) stat %Iu(%Iu) stored %Iu lit %u ", + Tracev((stderr, "\nopt %" PRIuSIZE "(%" PRIuSIZE ") stat %" PRIuSIZE "(%" PRIuSIZE ") stored %" PRIuSIZE " lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); -#else - Tracev((stderr, "\nopt %zu(%zu) stat %zu(%zu) stored %zu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); -#endif -// RB end if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { @@ -1009,7 +1002,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) Tracev((stderr,"\ncomprlen %Iu(%Iu) ", s->compressed_len>>3, s->compressed_len-7*last)); #else - Tracev((stderr,"\ncomprlen %zu(%zu) ", s->compressed_len>>3, + Tracev((stderr,"\ncomprlen %" PRIuSIZE "(%" PRIuSIZE ") ", s->compressed_len>>3, s->compressed_len-7*last)); #endif // RB end diff --git a/neo/renderer/Cinematic.cpp b/neo/renderer/Cinematic.cpp index 733098a1..dbe48c2c 100644 --- a/neo/renderer/Cinematic.cpp +++ b/neo/renderer/Cinematic.cpp @@ -75,6 +75,9 @@ public: virtual bool InitFromFile( const char* qpath, bool looping ); virtual cinData_t ImageForTime( int milliseconds ); virtual int AnimationLength(); + // RB begin + bool IsPlaying() const; + // RB end virtual void Close(); virtual void ResetTime( int time ); @@ -89,7 +92,7 @@ private: AVCodecContext* dec_ctx; SwsContext* img_convert_ctx; bool hasFrame; - long FramePos; + long framePos; cinData_t ImageForTimeFFMPEG( int milliseconds ); bool InitFromFFMPEGFile( const char* qpath, bool looping ); @@ -359,6 +362,13 @@ void idCinematic::Close() { } +// RB begin +bool idCinematic::IsPlaying() const +{ + return false; +} +// RB end + //=========================================== @@ -511,19 +521,25 @@ bool idCinematicLocal::InitFromFFMPEGFile( const char* qpath, bool amilooping ) float durationSec = static_cast( fmt_ctx->streams[video_stream_index]->duration ) * static_cast( ticksPerFrame ) / static_cast( avr.den ); animationLength = durationSec * 1000; frameRate = av_q2d( fmt_ctx->streams[video_stream_index]->r_frame_rate ); - startTime = 0; buf = NULL; hasFrame = false; - FramePos = -1; + framePos = -1; common->Warning( "%dx%d, %f FPS, %f sec", CIN_WIDTH, CIN_HEIGHT, frameRate, durationSec ); image = ( byte* )Mem_Alloc( CIN_WIDTH * CIN_HEIGHT * 4 * 2, TAG_CINEMATIC ); avpicture_fill( ( AVPicture* )frame2, image, PIX_FMT_BGR32, CIN_WIDTH, CIN_HEIGHT ); if( img_convert_ctx ) + { sws_freeContext( img_convert_ctx ); + } img_convert_ctx = sws_getContext( dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt, CIN_WIDTH, CIN_HEIGHT, PIX_FMT_BGR32, SWS_BICUBIC, NULL, NULL, NULL ); status = FMV_PLAY; + + startTime = 0; ImageForTime( 0 ); status = ( looping ) ? FMV_PLAY : FMV_IDLE; + + //startTime = Sys_Milliseconds(); + return true; } #endif @@ -536,10 +552,19 @@ idCinematicLocal::FFMPEGReset #if defined(USE_FFMPEG) void idCinematicLocal::FFMPEGReset() { - startTime = 0; - FramePos = -1; - av_seek_frame( fmt_ctx, video_stream_index, 0, 0 ); - status = FMV_LOOPED; + // RB: don't reset startTime here because that breaks video replays in the PDAs + //startTime = 0; + + framePos = -1; + + if( av_seek_frame( fmt_ctx, video_stream_index, 0, 0 ) >= 0 ) + { + status = FMV_LOOPED; + } + else + { + status = FMV_EOF; + } } #endif @@ -683,6 +708,13 @@ int idCinematicLocal::AnimationLength() return animationLength; } +// RB begin +bool idCinematicLocal::IsPlaying() const +{ + return ( status == FMV_PLAY ); +} +// RB end + /* ============== idCinematicLocal::ResetTime @@ -840,6 +872,12 @@ cinData_t idCinematicLocal::ImageForTimeFFMPEG( int thisTime ) return cinData; } + if( !fmt_ctx ) + { + // RB: .bik requested but not found + return cinData; + } + if( ( !hasFrame ) || startTime == -1 ) { if( startTime == -1 ) @@ -849,10 +887,18 @@ cinData_t idCinematicLocal::ImageForTimeFFMPEG( int thisTime ) startTime = thisTime; } - long DesiredFrame = ( ( thisTime - startTime ) * frameRate ) / 1000; - if( DesiredFrame < 0 ) DesiredFrame = 0; - if( DesiredFrame < FramePos ) FFMPEGReset(); - if( hasFrame && DesiredFrame == FramePos ) + long desiredFrame = ( ( thisTime - startTime ) * frameRate ) / 1000; + if( desiredFrame < 0 ) + { + desiredFrame = 0; + } + + if( desiredFrame < framePos ) + { + FFMPEGReset(); + } + + if( hasFrame && desiredFrame == framePos ) { cinData.imageWidth = CIN_WIDTH; cinData.imageHeight = CIN_HEIGHT; @@ -862,22 +908,23 @@ cinData_t idCinematicLocal::ImageForTimeFFMPEG( int thisTime ) } AVPacket packet; - while( FramePos < DesiredFrame ) + while( framePos < desiredFrame ) { int frameFinished = 0; - //Do a single frame by getting packets until we have a full frame + + // Do a single frame by getting packets until we have a full frame while( !frameFinished ) { - //if we got to the end or failed + // if we got to the end or failed if( av_read_frame( fmt_ctx, &packet ) < 0 ) { - //can't read any more, set to EOF + // can't read any more, set to EOF status = FMV_EOF; if( looping ) { - DesiredFrame = 0; + desiredFrame = 0; FFMPEGReset(); - FramePos = -1; + framePos = -1; startTime = thisTime; if( av_read_frame( fmt_ctx, &packet ) < 0 ) { @@ -901,8 +948,10 @@ cinData_t idCinematicLocal::ImageForTimeFFMPEG( int thisTime ) // Free the packet that was allocated by av_read_frame av_free_packet( &packet ); } - FramePos++; + + framePos++; } + // We have reached the desired frame // Convert the image from its native format to RGB sws_scale( img_convert_ctx, frame->data, frame->linesize, 0, dec_ctx->height, frame2->data, frame2->linesize ); @@ -912,6 +961,7 @@ cinData_t idCinematicLocal::ImageForTimeFFMPEG( int thisTime ) img->UploadScratch( image, CIN_WIDTH, CIN_HEIGHT ); hasFrame = true; cinData.image = img; + return cinData; } #endif diff --git a/neo/renderer/Cinematic.h b/neo/renderer/Cinematic.h index f12b47a1..98670395 100644 --- a/neo/renderer/Cinematic.h +++ b/neo/renderer/Cinematic.h @@ -89,6 +89,10 @@ public: // returns the length of the animation in milliseconds virtual int AnimationLength(); + // RB: let us know wether this video went EOF or is still active + virtual bool IsPlaying() const; + // RB end + // the pointers in cinData_t will remain valid until the next UpdateForTime() call virtual cinData_t ImageForTime( int milliseconds ); diff --git a/neo/renderer/Material.cpp b/neo/renderer/Material.cpp index 1b354229..de6a0022 100644 --- a/neo/renderer/Material.cpp +++ b/neo/renderer/Material.cpp @@ -3157,6 +3157,18 @@ int idMaterial::GetCinematicStartTime() const return -1; } +// RB: added because we can't rely on the FFmpeg feedback how long a video really is +bool idMaterial::CinematicIsPlaying() const +{ + if( !stages || !stages[0].texture.cinematic ) + { + return 0; + } + + return stages[0].texture.cinematic->IsPlaying(); +} +// RB end + /* ================== idMaterial::CheckForConstantRegisters diff --git a/neo/renderer/Material.h b/neo/renderer/Material.h index 25ddd204..2213d3fc 100644 --- a/neo/renderer/Material.h +++ b/neo/renderer/Material.h @@ -739,6 +739,10 @@ public: void UpdateCinematic( int time ) const; + // RB: added because we can't rely on the FFmpeg feedback how long a video really is + bool CinematicIsPlaying() const; + // RB end + //------------------------------------------------------------------ // gets an image for the editor to use diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index dd416495..d81a7913 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -295,7 +295,7 @@ static void R_CheckPortableExtensions() } // RB: Mesa support - if( idStr::Icmpn( glConfig.renderer_string, "Mesa", 4 ) == 0 || idStr::Icmpn( glConfig.renderer_string, "X.org", 4 ) == 0 ) + if( idStr::Icmpn( glConfig.renderer_string, "Mesa", 4 ) == 0 || idStr::Icmpn( glConfig.renderer_string, "X.org", 5 ) == 0 ) { glConfig.driverType = GLDRV_OPENGL_MESA; }