mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 17:49:53 -10:00
Conflicts: .gitignore code/Makefile.am code/ai/ai.h code/ai/ai_profiles.cpp code/ai/ai_profiles.h code/ai/aibig.cpp code/ai/aicode.cpp code/ai/aiturret.cpp code/asteroid/asteroid.cpp code/asteroid/asteroid.h code/bmpman/bm_internal.h code/bmpman/bmpman.cpp code/bmpman/bmpman.h code/camera/camera.cpp code/camera/camera.h code/cfile/cfile.cpp code/cmdline/cmdline.cpp code/cmdline/cmdline.h code/controlconfig/controlsconfig.h code/controlconfig/controlsconfigcommon.cpp code/cutscene/movie.cpp code/cutscene/oggplayer.cpp code/debugconsole/consoleparse.cpp code/fred2/campaigneditordlg.cpp code/fred2/fred.cpp code/fred2/fred.rc code/fred2/missionsave.cpp code/fred2/resource.h code/fred2/sexp_tree.cpp code/fred2/sexp_tree.h code/fred2/shipflagsdlg.cpp code/fred2/shipflagsdlg.h code/fred2/shiptexturesdlg.cpp code/fred2/voiceactingmanager.cpp code/freespace2/freespace.cpp code/freespace2/freespace.rc code/gamehelp/contexthelp.cpp code/globalincs/alphacolors.cpp code/globalincs/alphacolors.h code/globalincs/version.h code/globalincs/vmallocator.h code/globalincs/windebug.cpp code/graphics/2d.cpp code/graphics/font.cpp code/graphics/generic.cpp code/graphics/generic.h code/graphics/grinternal.h code/graphics/gropengl.cpp code/graphics/gropengldraw.cpp code/graphics/gropenglextension.h code/graphics/gropenglpostprocessing.cpp code/graphics/gropenglstate.cpp code/graphics/gropenglstate.h code/graphics/gropengltexture.cpp code/graphics/gropengltnl.cpp code/hud/hud.cpp code/hud/hud.h code/hud/hudconfig.cpp code/hud/hudlock.cpp code/hud/hudmessage.cpp code/hud/hudparse.cpp code/hud/hudreticle.cpp code/hud/hudreticle.h code/hud/hudshield.cpp code/hud/hudsquadmsg.cpp code/hud/hudtarget.cpp code/hud/hudtarget.h code/hud/hudtargetbox.cpp code/inetfile/cftp.cpp code/inetfile/chttpget.cpp code/io/joy.cpp code/io/joy_ff.cpp code/io/key.cpp code/io/keycontrol.cpp code/io/mouse.cpp code/io/timer.cpp code/localization/localize.cpp code/localization/localize.h code/math/fvi.cpp code/math/vecmat.cpp code/menuui/credits.cpp code/menuui/mainhallmenu.cpp code/menuui/mainhallmenu.h code/menuui/optionsmenumulti.cpp code/menuui/playermenu.cpp code/mission/missionbriefcommon.cpp code/mission/missioncampaign.cpp code/mission/missiongoals.h code/mission/missionmessage.cpp code/mission/missionparse.cpp code/mission/missionparse.h code/missionui/missionbrief.cpp code/missionui/missioncmdbrief.cpp code/missionui/missiondebrief.cpp code/missionui/missionscreencommon.cpp code/missionui/missionshipchoice.cpp code/missionui/missionweaponchoice.cpp code/missionui/redalert.cpp code/missionui/redalert.h code/mod_table/mod_table.cpp code/mod_table/mod_table.h code/model/model.h code/model/modelcollide.cpp code/model/modelinterp.cpp code/model/modelread.cpp code/network/multi.cpp code/network/multi_dogfight.cpp code/network/multi_ingame.cpp code/network/multi_log.cpp code/network/multi_rate.cpp code/network/multiteamselect.cpp code/network/multiui.cpp code/network/multiutil.cpp code/network/stand_gui-unix.cpp code/object/collideshipship.cpp code/object/collideshipweapon.cpp code/object/object.cpp code/object/object.h code/object/objectsnd.cpp code/object/objectsort.cpp code/osapi/osapi.cpp code/osapi/osapi_unix.cpp code/osapi/outwnd.h code/parse/generic_log.cpp code/parse/lua.cpp code/parse/parselo.cpp code/parse/parselo.h code/parse/scripting.cpp code/parse/scripting.h code/parse/sexp.cpp code/parse/sexp.h code/physics/physics.cpp code/pilotfile/csg.cpp code/pilotfile/csg_convert.cpp code/pilotfile/pilotfile.cpp code/pilotfile/pilotfile_convert.h code/playerman/playercontrol.cpp code/radar/radardradis.cpp code/radar/radardradis.h code/radar/radarsetup.cpp code/radar/radarsetup.h code/ship/ship.cpp code/ship/ship.h code/ship/shipfx.cpp code/ship/shiphit.cpp code/sound/audiostr.cpp code/sound/ds.cpp code/sound/openal.cpp code/sound/rtvoice.cpp code/sound/sound.cpp code/sound/voicerec.cpp code/stats/medals.cpp code/stats/medals.h code/stats/scoring.cpp code/ui/ui.h code/weapon/beam.cpp code/weapon/weapon.h code/weapon/weapons.cpp code/wxfred2/aboutbox.cpp code/wxfred2/campaigneditor.cpp code/wxfred2/campaigneditor.h code/wxfred2/commandbriefingeditor.cpp code/wxfred2/debriefingeditor.cpp code/wxfred2/fredframe.cpp code/wxfred2/fredframe.h code/wxfred2/missionspecseditor.cpp code/wxfred2/missionspecseditor.h code/wxfred2/voiceactingmanagereditor.cpp code/wxfred2/wxfred.xrc code/wxfred2/wxfred2.cpp code/wxfred2/wxfred2.h configure.ac fs2open.Doxyfile jansson/LICENSE jansson/dump.c jansson/hashtable.c jansson/hashtable.h jansson/jansson.h jansson/jansson_config.h jansson/jansson_private.h jansson/load.c jansson/memory.c jansson/pack_unpack.c jansson/strbuffer.c jansson/strbuffer.h jansson/strconv.c jansson/utf.c jansson/utf.h jansson/value.c libpng/png.c libpng/png.h libpng/pngconf.h libpng/pngdebug.h libpng/pngerror.c libpng/pngget.c libpng/pnginfo.h libpng/pnglibconf.h libpng/pngmem.c libpng/pngpread.c libpng/pngpriv.h libpng/pngread.c libpng/pngrio.c libpng/pngrtran.c libpng/pngrutil.c libpng/pngset.c libpng/pngstruct.h libpng/pngtrans.c libpng/pngwio.c libpng/pngwrite.c libpng/pngwtran.c libpng/pngwutil.c projects/Eclipse/Freespace2/.project projects/MSVC_2005/Fred2.vcproj projects/MSVC_2005/Freespace2.sln projects/MSVC_2005/Freespace2.vcproj projects/MSVC_2005/code.vcproj projects/MSVC_2005/wxFRED2.vcproj projects/MSVC_2008/Fred2.vcproj projects/MSVC_2008/Freespace2.doxproj projects/MSVC_2008/Freespace2.vcproj projects/MSVC_2008/code.vcproj projects/MSVC_2010/Fred2.vcxproj projects/MSVC_2010/Freespace2.vcxproj projects/MSVC_2010/code.vcxproj projects/MSVC_2010/code.vcxproj.filters projects/MSVC_2010/wxFRED2.vcxproj projects/MSVC_2011/Fred2.vcxproj projects/MSVC_2011/Freespace2.vcxproj projects/MSVC_2011/code.vcxproj projects/MSVC_2011/code.vcxproj.filters projects/MSVC_2011/wxFRED2.vcxproj projects/MSVC_2013/Fred2.vcxproj projects/MSVC_2013/Freespace2.vcxproj projects/MSVC_2013/code.vcxproj projects/MSVC_2013/code.vcxproj.filters projects/MSVC_2013/libjpeg.vcxproj projects/MSVC_2013/liblua.vcxproj projects/MSVC_2013/libpng.vcxproj projects/MSVC_2013/wxFRED2.vcxproj projects/MSVC_2013/zlib.vcxproj projects/MSVC_6/Fred2.dsp projects/MSVC_6/Freespace2.dsp projects/MSVC_6/code.dsp projects/MSVC_6/wxFRED2.dsp projects/Xcode/English.lproj/InfoPlist.strings projects/Xcode/FS2_Open.xcodeproj/project.pbxproj projects/Xcode4/English.lproj/InfoPlist.strings projects/Xcode4/FS2_Open.xcodeproj/project.pbxproj projects/Xcode4/Frameworks.tgz projects/codeblocks/Freespace2/Freespace2.cbp zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/crc32.h zlib/deflate.c zlib/deflate.h zlib/infback.c zlib/inffast.c zlib/inffixed.h zlib/inflate.c zlib/inftrees.c zlib/trees.c zlib/uncompr.c zlib/zconf.h zlib/zlib.h zlib/zutil.c zlib/zutil.h
417 lines
7.4 KiB
C++
417 lines
7.4 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include "globalincs/pstypes.h"
|
|
#include "io/timer.h"
|
|
#include "graphics/2d.h"
|
|
#include "globalincs/alphacolors.h"
|
|
|
|
#define THREADED // to use the proper set of macros
|
|
#include "osapi/osapi.h" // for multi-thread macros
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
#define USE_TIMING
|
|
#endif
|
|
|
|
static int Timer_inited = 0;
|
|
|
|
static SDL_mutex* Timer_lock;
|
|
|
|
void timer_close()
|
|
{
|
|
if ( Timer_inited ) {
|
|
Timer_inited = 0;
|
|
SDL_DestroyMutex( Timer_lock );
|
|
}
|
|
}
|
|
|
|
void timer_init()
|
|
{
|
|
if ( !Timer_inited ) {
|
|
Timer_lock = SDL_CreateMutex();
|
|
|
|
Timer_inited = 1;
|
|
|
|
atexit(timer_close);
|
|
}
|
|
}
|
|
|
|
static uint timer_get()
|
|
{
|
|
return SDL_GetTicks();
|
|
}
|
|
|
|
|
|
fix timer_get_fixed_seconds()
|
|
{
|
|
if (!Timer_inited) {
|
|
Int3(); // Make sure you call timer_init before anything that uses timer functions!
|
|
return 0;
|
|
}
|
|
|
|
longlong a = timer_get();
|
|
|
|
a *= 65536;
|
|
|
|
return (fix)(a / 1000);
|
|
}
|
|
|
|
fix timer_get_fixed_secondsX()
|
|
{
|
|
return timer_get_fixed_seconds();
|
|
}
|
|
|
|
fix timer_get_approx_seconds()
|
|
{
|
|
return timer_get_fixed_seconds();
|
|
}
|
|
|
|
int timer_get_seconds()
|
|
{
|
|
if (!Timer_inited) {
|
|
Int3();
|
|
return 0;
|
|
}
|
|
|
|
return (timer_get() / 1000);
|
|
}
|
|
|
|
int timer_get_milliseconds()
|
|
{
|
|
if (!Timer_inited) {
|
|
Int3(); // Make sure you call timer_init before anything that uses timer functions!
|
|
return 0;
|
|
}
|
|
|
|
return timer_get();
|
|
}
|
|
|
|
int timer_get_microseconds()
|
|
{
|
|
if (!Timer_inited) {
|
|
Int3(); // Make sure you call timer_init before anything that uses timer functions!
|
|
return 0;
|
|
}
|
|
|
|
return timer_get() * 1000;
|
|
}
|
|
|
|
// 0 means invalid,
|
|
// 1 means always return true
|
|
// 2 and above actually check the time
|
|
int timestamp_ticker = 2;
|
|
|
|
void timestamp_reset()
|
|
{
|
|
timestamp_ticker = 2;
|
|
}
|
|
|
|
// Restrict all time values between 0 and MAX_TIME
|
|
// so we don't have to use UINTs to calculate rollover.
|
|
// For debugging & testing, you could set this to
|
|
// something like 1 minute (6000).
|
|
#define MAX_TIME (INT_MAX/2)
|
|
|
|
void timestamp_inc(float frametime)
|
|
{
|
|
timestamp_ticker += (int)(frametime*TIMESTAMP_FREQUENCY);
|
|
|
|
if ( timestamp_ticker > MAX_TIME ) {
|
|
timestamp_ticker = 2; // Roll!
|
|
}
|
|
|
|
if (timestamp_ticker < 2 ) {
|
|
mprintf(("Whoa!!! timestamp_ticker < 2 -- resetting to 2!!!\n"));
|
|
timestamp_ticker = 2;
|
|
}
|
|
}
|
|
|
|
int timestamp(int delta_ms )
|
|
{
|
|
int t2;
|
|
if (delta_ms < 0 ) return 0;
|
|
if (delta_ms == 0 ) return 1;
|
|
t2 = timestamp_ticker + delta_ms;
|
|
if ( t2 > MAX_TIME ) {
|
|
// wrap!!!
|
|
t2 = delta_ms - (MAX_TIME-timestamp_ticker);
|
|
}
|
|
if (t2 < 2 ) t2 = 2; // hack??
|
|
return t2;
|
|
}
|
|
|
|
// Returns milliseconds until timestamp will elapse.
|
|
// Negative value gives milliseconds ago that timestamp elapsed.
|
|
int timestamp_until(int stamp)
|
|
{
|
|
// JAS: FIX
|
|
// HACK!! This doesn't handle rollover!
|
|
// (Will it ever happen?)
|
|
|
|
return stamp - timestamp_ticker;
|
|
|
|
/*
|
|
uint delta;
|
|
|
|
delta = stamp - timestamp_ticker;
|
|
|
|
|
|
if (delta > UINT_MAX/2)
|
|
delta = UINT_MAX - delta + 1;
|
|
else if (delta < - ( (int) (UINT_MAX/2)))
|
|
delta = UINT_MAX + delta + 1;
|
|
|
|
return delta;
|
|
*/
|
|
}
|
|
|
|
// alternate timestamp functions. The way these work is you call xtimestamp() to get the
|
|
// current counter value, and then call
|
|
int timestamp()
|
|
{
|
|
return timestamp_ticker;
|
|
}
|
|
|
|
int timestamp_has_time_elapsed(int stamp, int time)
|
|
{
|
|
int t;
|
|
|
|
if (time <= 0)
|
|
return 1;
|
|
|
|
t = stamp + time;
|
|
if (t <= timestamp_ticker)
|
|
return 1; // if we are unlucky enough to have it wrap on us, this will assume time has elapsed.
|
|
|
|
return 0;
|
|
}
|
|
|
|
// timing functions -------------------------------------------------------------------------------
|
|
|
|
#define MAX_TIMING_EVENTS 15
|
|
|
|
// timing struct
|
|
#ifdef USE_TIMING
|
|
|
|
typedef struct timing {
|
|
char name[64];
|
|
int microseconds_total;
|
|
int start;
|
|
int ref_count;
|
|
} timing;
|
|
|
|
timing Timing_frame;
|
|
timing Timing_events[MAX_TIMING_EVENTS];
|
|
int Timing_event_count = 0;
|
|
|
|
#endif
|
|
|
|
// lookup a timing event
|
|
int timing_event_lookup(char *event_name)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return -1;
|
|
#else
|
|
int idx;
|
|
|
|
// sanity
|
|
if(event_name == NULL){
|
|
return -1;
|
|
}
|
|
|
|
// look through all events
|
|
for(idx=0; idx<MAX_TIMING_EVENTS; idx++){
|
|
if(!stricmp(Timing_events[idx].name, event_name)){
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
// start timing frame stuff
|
|
void timing_frame_start()
|
|
{
|
|
#ifndef USE_TIMING
|
|
return;
|
|
#else
|
|
int idx;
|
|
|
|
// restart the frame
|
|
Timing_event_count = 0;
|
|
Timing_frame.start = timer_get_microseconds();
|
|
for(idx=0; idx<MAX_TIMING_EVENTS; idx++){
|
|
Timing_events[idx].microseconds_total = 0;
|
|
strcpy_s(Timing_events[idx].name, "");
|
|
Timing_events[idx].ref_count = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// done timing the frame
|
|
void timing_frame_stop()
|
|
{
|
|
#ifndef USE_TIMING
|
|
return;
|
|
#else
|
|
int stop_time;
|
|
|
|
// stop time
|
|
stop_time = timer_get_microseconds();
|
|
|
|
// calc times
|
|
Timing_frame.microseconds_total = stop_time - Timing_frame.start;
|
|
#endif
|
|
}
|
|
|
|
// get the total frame time in microseconds
|
|
int timing_frame_total()
|
|
{
|
|
#ifndef USE_TIMING
|
|
return 0;
|
|
#else
|
|
return Timing_frame.microseconds_total;
|
|
#endif
|
|
}
|
|
|
|
// time an individual event
|
|
void timing_event_start(char *event_name)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return;
|
|
#else
|
|
int event;
|
|
|
|
// sanity
|
|
if(event_name == NULL){
|
|
return;
|
|
}
|
|
|
|
// try and find the event
|
|
event = timing_event_lookup(event_name);
|
|
|
|
// if we already have one
|
|
if(event != -1){
|
|
Assert(Timing_events[event].ref_count == 0);
|
|
Timing_events[event].start = timer_get_microseconds();
|
|
Timing_events[event].ref_count++;
|
|
}
|
|
// if we need to add a new one
|
|
else {
|
|
if(Timing_event_count < MAX_TIMING_EVENTS){
|
|
strcpy_s(Timing_events[Timing_event_count].name, event_name);
|
|
Timing_events[Timing_event_count].start = timer_get_microseconds();
|
|
Timing_events[Timing_event_count++].ref_count++;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// stop timing an event
|
|
void timing_event_stop(char *event_name)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return;
|
|
#else
|
|
int event;
|
|
|
|
// sanity
|
|
if(event_name == NULL){
|
|
return;
|
|
}
|
|
|
|
// try and find the event
|
|
event = timing_event_lookup(event_name);
|
|
|
|
// if we already have one
|
|
if(event != -1){
|
|
Assert(Timing_events[event].ref_count == 1);
|
|
Timing_events[event].microseconds_total += timer_get_microseconds() - Timing_events[event].start;
|
|
Timing_events[event].ref_count--;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// get the total time for an event in microseconds
|
|
int timing_event_total(char *event_name)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return -1;
|
|
#else
|
|
int event;
|
|
|
|
// sanity
|
|
if(event_name == NULL){
|
|
return -1;
|
|
}
|
|
|
|
// try and find the event
|
|
event = timing_event_lookup(event_name);
|
|
if(event == -1){
|
|
return -1;
|
|
}
|
|
|
|
return Timing_events[event].microseconds_total;
|
|
#endif
|
|
}
|
|
|
|
// get the percentage of total frametime for the event (0.0 to 1.0)
|
|
float timing_event_pct(char *event_name)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return 0.0f;
|
|
#else
|
|
int event;
|
|
|
|
// sanity
|
|
if(event_name == NULL){
|
|
return -1.0f;
|
|
}
|
|
|
|
// try and find the event
|
|
event = timing_event_lookup(event_name);
|
|
if(event == -1){
|
|
return -1.0f;
|
|
}
|
|
|
|
return (float)((double)Timing_events[event].microseconds_total / (double)Timing_frame.microseconds_total);
|
|
#endif
|
|
}
|
|
|
|
// display timing
|
|
void timing_display(int x, int y)
|
|
{
|
|
#ifndef USE_TIMING
|
|
return;
|
|
#else
|
|
int idx;
|
|
|
|
int line_height = gr_get_font_height() + 1;
|
|
|
|
gr_set_color_fast(&Color_bright_blue);
|
|
|
|
// total time
|
|
gr_printf_no_resize(x, y, "Total time %f\n", (float)timing_frame_total() / 1000000.0f);
|
|
y += line_height;
|
|
|
|
// each event percentage
|
|
for(idx=0; idx<Timing_event_count; idx++){
|
|
gr_printf_no_resize(x, y, "%s: %f\n", Timing_events[idx].name, timing_event_pct(Timing_events[idx].name));
|
|
y += line_height;
|
|
}
|
|
#endif
|
|
}
|