mirror of
https://github.com/thug1src/thug.git
synced 2024-12-03 13:26:47 +00:00
427 lines
11 KiB
C++
427 lines
11 KiB
C++
/*****************************************************************************
|
|
** **
|
|
** Neversoft Entertainment **
|
|
** **
|
|
** Copyright (C) 1999 - All Rights Reserved **
|
|
** **
|
|
******************************************************************************
|
|
** **
|
|
** Project: GEL (Game Engine Library) **
|
|
** **
|
|
** Module: Main Loop (ML) **
|
|
** **
|
|
** File name: mainloop.cpp **
|
|
** **
|
|
** Created: 05/27/99 - mjb **
|
|
** **
|
|
** Description: Main loop and support code **
|
|
** **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Includes **
|
|
*****************************************************************************/
|
|
|
|
#include <gel/mainloop.h>
|
|
|
|
#include <core/defines.h>
|
|
#include <core/singleton.h>
|
|
#include <core/task.h>
|
|
|
|
#include <gfx/nx.h>
|
|
|
|
#ifndef __PLAT_WN32__
|
|
#include <sys/profiler.h>
|
|
#endif
|
|
|
|
#include <gel/scripting/symboltable.h>
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
#include <gel/collision/batchtricoll.h>
|
|
#include <gel/soundfx/ngps/p_sfx.h>
|
|
|
|
namespace NxPs2
|
|
{
|
|
void WaitForRendering();
|
|
void StuffAfterGSFinished();
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
** DBG Information **
|
|
*****************************************************************************/
|
|
|
|
Dbg_DefineProject( GEL, "GEL Library" )
|
|
|
|
namespace Mdl
|
|
{
|
|
void Rail_DebugRender(); // for debugging
|
|
}
|
|
|
|
namespace Mlp
|
|
{
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
** Externals **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Defines **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Types **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Data **
|
|
*****************************************************************************/
|
|
|
|
DefineSingletonClass( Manager, "Main Loop Manager" );
|
|
|
|
/*****************************************************************************
|
|
** Public Data **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Prototypes **
|
|
*****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
** Private Functions **
|
|
*****************************************************************************/
|
|
|
|
Manager::Manager( void )
|
|
{
|
|
|
|
|
|
start_render_hook = NULL;
|
|
end_render_hook = NULL;
|
|
done = false;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
Manager::~Manager( void )
|
|
{
|
|
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
inline void Manager::service_system( void )
|
|
{
|
|
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 255, 0, 0 );
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
|
|
system_task_stack.Process (currently_profiling);
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext();
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
inline void Manager::game_logic( void )
|
|
{
|
|
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 0, 255, 0 );
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
|
|
// printf ("\nTiming Logic\n");
|
|
logic_task_stack.Process(currently_profiling);
|
|
|
|
// printf ("\nDumping Task List\n\n");
|
|
// logic_task_stack.Dump();
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext();
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
inline void Manager::render_frame( void )
|
|
{
|
|
|
|
|
|
// printf ("############################## render_frame #############################\n");
|
|
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 0, 0, 255 );
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
|
|
# ifdef __PLAT_NGC__
|
|
if( start_render_hook )
|
|
{
|
|
start_render_hook->Call();
|
|
}
|
|
if( !display_tasks_paused )
|
|
{
|
|
display_task_stack.Process( currently_profiling );
|
|
}
|
|
# else
|
|
if (!display_tasks_paused)
|
|
{
|
|
// If paused don't call the start_render_hook
|
|
// as this clears the none-visible frame buffer
|
|
// which will result in a flash when display is unpaused
|
|
if ( start_render_hook ) // set up for rendering
|
|
{
|
|
start_render_hook->Call();
|
|
}
|
|
|
|
// printf ("\nTiming render\n");
|
|
|
|
display_task_stack.Process(currently_profiling); // service rendering routines
|
|
}
|
|
# endif // __PLAT_NGC__
|
|
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext();
|
|
Sys::CPUProfiler->PushContext( 255, 255, 0 );
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
|
|
if ( end_render_hook ) // end rendering
|
|
{
|
|
end_render_hook->Call();
|
|
}
|
|
#ifndef __PLAT_WN32__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext();
|
|
# endif // __USE_PROFILER__
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
** Public Functions **
|
|
*****************************************************************************/
|
|
|
|
void Manager::MainLoop( void )
|
|
{
|
|
|
|
|
|
bool old_flag = done; // push the current done flag
|
|
|
|
done = false;
|
|
|
|
while ( !done )
|
|
{
|
|
|
|
if (trigger_profiling)
|
|
{
|
|
printf ("\nProfiling.....Start of main loop\n\n");
|
|
trigger_profiling--;
|
|
currently_profiling = 1;
|
|
}
|
|
|
|
|
|
#ifndef __PLAT_WN32__
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
// for profiling on the PS2, we do a bit of the code from sPreRender here
|
|
// so we can time the final waiting for GS
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 0,0,255 ); // blue = wait for VU/DMA/GPU to finish
|
|
# endif
|
|
NxPs2::WaitForRendering(); // PS2 Specific, wait for prior frame's DMA to finish
|
|
NxPs2::StuffAfterGSFinished(); // PS2 Specific, DMA altering stuff run after previous frame's DMA finished
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext( );
|
|
Sys::CPUProfiler->PushContext( 128,0,0 ); // red = wait for vblank
|
|
# endif
|
|
int framerate = Script::GetInteger(0x3214c818/*"lock_framerate"*/);
|
|
if (framerate) // normal vsync
|
|
{
|
|
static uint64 next_vblanks= 0;
|
|
// Still call VSync, as it updates some functions
|
|
Tmr::VSync();
|
|
while (Tmr::GetVblanks()<next_vblanks)
|
|
{
|
|
// just hanging until vblanks gets big enough
|
|
}
|
|
next_vblanks = Tmr::GetVblanks() + framerate;
|
|
}
|
|
else
|
|
{
|
|
Tmr::VSync1();
|
|
}
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext( );
|
|
# endif
|
|
#endif
|
|
#ifndef __PLAT_NGC__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::Profiler::sStartFrame();
|
|
# endif
|
|
#endif
|
|
|
|
Nx::CEngine::sPreRender(); // start rendering previous frame's DMA list
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
Sfx::CSpuManager::sUpdateStatus(); // Garrett: This should go into some system task, but I'll put it here for now
|
|
#endif
|
|
|
|
// Sys::Profiler::sStartFrame();
|
|
#endif
|
|
|
|
#ifdef __PLAT_NGC__
|
|
# ifdef __USE_PROFILER__
|
|
Sys::Profiler::sStartFrame();
|
|
# endif
|
|
# endif
|
|
|
|
service_system();
|
|
|
|
#if defined(__PLAT_NGPS__) && defined(BATCH_TRI_COLLISION)
|
|
// Enable VU0 collision
|
|
bool got_vu0 = Nx::CBatchTriCollMan::sUseVU0Micro();
|
|
Dbg_Assert(got_vu0);
|
|
#endif
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
// snProfSetRange( -1, (void*)0, (void*)-1);
|
|
// snProfSetFlagValue(0x01);
|
|
#endif
|
|
|
|
game_logic();
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
// snProfSetRange( 4, (void*)NULL, (void*)-1);
|
|
#endif
|
|
|
|
|
|
#if defined(__PLAT_NGPS__) && defined(BATCH_TRI_COLLISION)
|
|
// Disable VU0 collision
|
|
if (got_vu0)
|
|
{
|
|
Nx::CBatchTriCollMan::sDisableVU0Micro();
|
|
}
|
|
#endif
|
|
|
|
#ifndef __PLAT_WN32__
|
|
// Display the memory contents, (if memview is active)
|
|
MemView_Display();
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 255, 255, 0 ); // yellow = render world
|
|
# endif
|
|
|
|
#ifdef __PLAT_NGPS__
|
|
// snProfSetRange( -1, (void*)0, (void*)-1);
|
|
// snProfSetFlagValue(0x01);
|
|
#endif
|
|
|
|
Nx::CEngine::sRenderWorld();
|
|
#ifdef __PLAT_NGC__
|
|
#ifdef __USE_PROFILER__
|
|
Sys::Render_Profiler();
|
|
#endif
|
|
#endif
|
|
// Mick: bit of a patch here, we need some better debug hooks
|
|
Mdl::Rail_DebugRender();
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PushContext( 0, 0, 0 ); // Black (Under Yellow) = sPostRender
|
|
# endif // __USE_PROFILER__
|
|
Nx::CEngine::sPostRender(); // Previous frames profiler is rendered here
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext( );
|
|
# endif
|
|
|
|
|
|
|
|
|
|
# ifdef __USE_PROFILER__
|
|
Sys::CPUProfiler->PopContext( );
|
|
# endif
|
|
Tmr::OncePerRender();
|
|
#ifdef __PLAT_NGPS__
|
|
// snProfSetRange( 4, (void*)NULL, (void*)-1);
|
|
#endif
|
|
#endif
|
|
|
|
currently_profiling = false;
|
|
|
|
}
|
|
|
|
done = old_flag;
|
|
}
|
|
|
|
void Manager::ProfileTasks(int n)
|
|
{
|
|
trigger_profiling = n;
|
|
currently_profiling = 0;
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
void Manager::QuitLoop( void )
|
|
{
|
|
|
|
|
|
Dbg_Notify( "Exiting..." );
|
|
|
|
done = true;
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
void Manager::DoGameLogic( void )
|
|
{
|
|
game_logic();
|
|
}
|
|
|
|
/******************************************************************/
|
|
/* */
|
|
/* */
|
|
/******************************************************************/
|
|
|
|
} // namespace Mlp
|
|
|