1
1
forked from 0ad/0ad

# refactor sysdep API, split it into parts

- split up detect.cpp into snd, cpu, gfx (headers were already split)
- rename detect functions for more clarity (e.g. get_cur_vmode ->
gfx_get_video_mode)
- rename lib/res/sound/snd to snd_mgr to avoid conflict with
sysdep/snd.cpp
- waio: set errno in aio_rw (addresses bug #73)

This was SVN commit r3745.
This commit is contained in:
janwas 2006-04-10 20:12:25 +00:00
parent 674bbc3735
commit 34637ba5dc
25 changed files with 2555 additions and 2631 deletions

View File

@ -20,7 +20,7 @@
#include <string.h>
#include <stdio.h>
#include "detect.h"
#include "sysdep/gfx.h"
#include "res/graphics/ogl_tex.h"
#include "res/file/file.h"
#include "res/file/vfs.h"
@ -35,7 +35,7 @@
static void override_gl_upload_caps()
{
if(gfx_card[0] == '\0')
debug_warn("get_gfx_info must be called before ogl_tex_upload");
debug_warn("gfx_detect must be called before ogl_tex_upload");
if(!strcmp(gfx_card, "S3 SuperSavage/IXC 1014"))
{

View File

@ -1,204 +0,0 @@
// system detect
//
// Copyright (c) 2003 Jan Wassenberg
//
// This file is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// Contact info:
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
// things missing in POSIX, SDL, and OpenGL :P
// large platform-specific routines (e.g. CPU or gfx card info)
// are split out of here.
#include "precompiled.h"
#include "lib.h"
#include "posix.h"
#include "detect.h"
#include "timer.h"
#include "sdl.h"
#if CPU_IA32
#include "sysdep/ia32.h"
#endif
#if OS_WIN
extern LibError win_get_gfx_info();
extern LibError win_get_cpu_info();
extern LibError win_get_snd_info();
#elif OS_UNIX
extern LibError unix_get_cpu_info();
#endif
extern "C" LibError ogl_get_gfx_info();
//
// memory
//
size_t tot_mem = 0;
size_t avl_mem = 0;
size_t page_size = 0;
void get_mem_status()
{
#ifdef _SC_PAGESIZE
if(!page_size)
page_size = (size_t)sysconf(_SC_PAGESIZE);
#endif
// Sys V derived (GNU/Linux, Solaris)
#if defined(_SC_AVPHYS_PAGES)
tot_mem = sysconf(_SC_PHYS_PAGES ) * page_size;
avl_mem = sysconf(_SC_AVPHYS_PAGES) * page_size;
// BSD / Mac OS X
#elif defined(HW_PHYSMEM)
size_t len = sizeof(tot_mem);
int mib[2] = { CTL_HW, HW_PHYSMEM };
sysctl(mib, 2, &tot_mem, &len, 0, 0);
mib[1] = HW_USERMEM;
sysctl(mib, 2, &avl_mem, &len, 0, 0);
#endif
}
//
// graphics card
//
char gfx_card[GFX_CARD_LEN] = "";
char gfx_drv_ver[GFX_DRV_VER_LEN] = "";
int gfx_mem = -1; // [MiB]; approximate
// attempt to detect graphics card without OpenGL (in case ogl init fails,
// or we want more detailed info). gfx_card[] is unchanged on failure.
void get_gfx_info()
{
// TODO: add sizeof(FB)?
gfx_mem = (SDL_GetVideoInfo()->video_mem) / 1048576; // [MiB]
// try platform-specific version: they return more
// detailed information, and don't require OpenGL to be ready.
#if OS_WIN
if(win_get_gfx_info() < 0)
#endif
{
// the OpenGL version should always work, unless OpenGL isn't ready for use,
// or we were called between glBegin and glEnd.
ogl_get_gfx_info();
}
// remove crap from vendor names. (don't dare touch the model name -
// it's too risky, there are too many different strings)
#define SHORTEN(what, chars_to_keep)\
if(!strncmp(gfx_card, what, ARRAY_SIZE(what)-1))\
memmove(gfx_card+chars_to_keep, gfx_card+ARRAY_SIZE(what)-1, strlen(gfx_card)-(ARRAY_SIZE(what)-1)+1);
SHORTEN("ATI Technologies Inc.", 3);
SHORTEN("NVIDIA Corporation", 6);
SHORTEN("S3 Graphics", 2); // EnumDisplayDevices
SHORTEN("S3 Graphics, Incorporated", 2); // GL_VENDOR
#undef SHORTEN
}
//
// CPU
//
char cpu_type[CPU_TYPE_LEN] = ""; // processor brand string is <= 48 chars
double cpu_freq = 0.f;
// -1 if detect not yet called, or cannot be determined
int cpus = -1;
int cpu_ht_units = -1;
int cpu_cores = -1;
int cpu_speedstep = -1;
static void get_cpu_info()
{
#if OS_WIN
win_get_cpu_info();
#elif OS_UNIX
unix_get_cpu_info();
#endif
#if CPU_IA32
ia32_get_cpu_info();
#endif
}
void cpu_init()
{
#if CPU_IA32
// must come before any uses of ia32.asm, e.g. by get_cpu_info
ia32_init();
// no longer set 24 bit (float) precision by default: for
// very long game uptimes (> 1 day; e.g. dedicated server),
// we need full precision when calculating the time.
// if there's a spot where we want to speed up divides|sqrts,
// we can temporarily change precision there.
//ia32_control87(IA32_PC_24, IA32_MCW_PC);
// to help catch bugs, enable as many floating-point exceptions as
// possible. that means only zero-divide, because the JS engine is
// triggering the rest.
// note: passing a flag *disables* that exception.
ia32_control87(IA32_EM_INVALID|IA32_EM_DENORMAL|IA32_EM_OVERFLOW|IA32_EM_UNDERFLOW|IA32_EM_INEXACT, IA32_MCW_EM);
// no longer round toward zero (truncate). changing this setting
// resulted in much faster float->int casts, because the compiler
// could be told (via /QIfist) to use FISTP while still truncating
// the result as required by ANSI C. however, FPU calculation
// results were changed significantly, so it had to be disabled.
//ia32_control87(IA32_RC_CHOP, IA32_MCW_RC);
// If possible, hook up capability-sensitive assembler routines
ia32_hook_capabilities();
#endif
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
get_cpu_info();
}
//
// sound
//
char snd_card[SND_CARD_LEN];
char snd_drv_ver[SND_DRV_VER_LEN];
void get_snd_info()
{
#if OS_WIN
win_get_snd_info();
#else
// At least reset the values for unhandled platforms. Should perhaps do
// something like storing the OpenAL version or similar.
debug_assert(SND_CARD_LEN >= 8 && SND_DRV_VER_LEN >= 8); // protect strcpy
SAFE_STRCPY(snd_card, "Unknown");
SAFE_STRCPY(snd_drv_ver, "Unknown");
#endif
}

View File

@ -1,44 +0,0 @@
// system detect
//
// Copyright (c) 2003 Jan Wassenberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// Contact info:
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#ifndef __DETECT_H__
#define __DETECT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "sysdep/gfx.h"
#include "sysdep/os.h"
#include "sysdep/cpu.h"
#include "sysdep/snd.h"
#ifdef __cplusplus
}
#endif
#endif // #ifndef __DETECT_H__

View File

@ -26,7 +26,7 @@
#include "lib.h"
#include "sdl.h"
#include "ogl.h"
#include "detect.h"
#include "sysdep/gfx.h"
#include "debug.h"
#include "lib/res/h_mgr.h"
#include "lib/res/graphics/tex.h"
@ -332,6 +332,9 @@ int ogl_max_tex_size = -1; // [pixels]
int ogl_max_tex_units = -1; // limit on GL_TEXTUREn
// set sysdep/gfx.h gfx_card and gfx_drv_ver. called by gfx_detect.
//
// fails if OpenGL not ready for use.
// gfx_card and gfx_drv_ver are unchanged on failure.
LibError ogl_get_gfx_info()
{

View File

@ -152,8 +152,7 @@ extern const char* oglExtList(void);
extern int ogl_max_tex_size; // [pixels]
extern int ogl_max_tex_units; // limit on GL_TEXTUREn
// set detect.cpp gfx_card[] and gfx_drv_ver[].
// (called by detect.cpp get_gfx_info()).
// set sysdep/gfx.h gfx_card and gfx_drv_ver. called by gfx_detect.
//
// fails if OpenGL not ready for use.
// gfx_card and gfx_drv_ver are unchanged on failure.

View File

@ -20,7 +20,6 @@
#include "precompiled.h"
#include "lib.h"
#include "detect.h"
#include "adts.h"
#include "sysdep/sysdep.h"
#include "byte_order.h"

View File

@ -302,8 +302,8 @@ static void state_latch(OglTexState* ots)
//----------------------------------------------------------------------------
// ideally we would split OglTex into data and state objects as in
// snd.cpp's SndData / VSrc. this gives us the benefits of caching while
// still leaving each "instance" (state object, which owns a data reference)
// SndData / VSrc. this gives us the benefits of caching while still
// leaving each "instance" (state object, which owns a data reference)
// free to change its state. however, unlike in OpenAL, there is no state
// independent of the data object - all parameters are directly tied to the
// GL texture object. therefore, splitting them up is impossible.

File diff suppressed because it is too large Load Diff

View File

@ -1,269 +1,269 @@
// OpenAL sound engine
//
// Copyright (c) 2004-5 Jan Wassenberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// Contact info:
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#ifndef SND_H__
#define SND_H__
#include "../handle.h"
/*
[KEEP IN SYNC WITH WIKI]
overview
--------
this module provides a moderately high-level sound interface. basic usage
is opening a sound and requesting it be played; it is closed automatically
when playback has finished (fire and forget).
any number of sound play requests may be issued; the most 'important' ones
are actually played (necessary due to limited hardware mixing capacity).
3d positional sounds (heard to emanate from a given spot) are supported.
active sound instances are referenced by Handles, so changing volume etc.
during playback is possible (useful for fadeout).
sound setup
-----------
OpenAL provides portable access to the underlying sound hardware, and
falls back to software mixing if no acceleration is provided.
we allow the user to specify the device to use (in case the default
has problems) and maximum number of sources (to reduce mixing cost).
performance
-----------
much effort has been invested in efficiency: all sound data is cached,
so every open() after the first is effectively free. large sound files are
streamed from disk to reduce load time and memory usage. hardware mixing
resources are suballocated to avoid delays when starting to play.
therefore, the user can confidently fire off hundreds of sound requests.
finally, lengthy initialization steps are delayed until the sound engine
is actually needed (i.e. upon first open()). perceived startup time is
therefore reduced - the user sees e.g. our main menu earlier.
terminology
-----------
"hardware voice" refers to mixing resources on the DSP. strictly
speaking, we mean 'OpenAL source', but this term is more clear.
voice ~= source, unless expensive effects (e.g. EAX) are enabled.
note: software mixing usually doesn't have a fixed 'source' cap.
"gain" is quantified volume. 1 is unattenuated, 0.5 corresponds to -6 dB,
and 0 is silence. this can be set per-source as well as globally.
"position" of a sound is within the app's coordinate system,
the orientation of which is passed to snd_update.
"importance" of a sound derives from the app-assigned priority
(e.g. voiceover must not be skipped in favor of seagulls) and
distance from the listener. it's calculated by our prioritizer.
"virtual source" denotes a sound play request issued by the app.
this is in contrast to an actual AL source, which will be mixed
into the output channel. the most important VSrc receive an al_src.
"sound instances" store playback parameters (e.g. position), and
reference the (centrally cached) "sound data" that will be played.
*/
//
// device enumeration
//
// prepare to enumerate all device names (this resets the list returned by
// snd_dev_next). return 0 on success, otherwise -1 (only if the requisite
// OpenAL extension isn't available). on failure, a "cannot enum device"
// message should be presented to the user, and snd_dev_set need not be
// called; OpenAL will use its default device.
// may be called each time the device list is needed.
extern LibError snd_dev_prepare_enum();
// return the next device name, or 0 if all have been returned.
// do not call unless snd_dev_prepare_enum succeeded!
// not thread-safe! (static data from snd_dev_prepare_enum is used)
extern const char* snd_dev_next();
//
// sound system setup
//
// tell OpenAL to use the specified device in future.
// name = 0 reverts to OpenAL's default choice, which will also
// be used if this routine is never called.
//
// the device name is typically taken from a config file at init-time;
// the snd_dev* enumeration routines below are used to present a list
// of choices to the user in the options screen.
//
// if OpenAL hasn't yet been initialized (i.e. no sounds have been opened),
// this just stores the device name for use when init does occur.
// note: we can't check now if it's invalid (if so, init will fail).
// otherwise, we shut OpenAL down (thereby stopping all sounds) and
// re-initialize with the new device. that's fairly time-consuming,
// so preferably call this routine before sounds are loaded.
//
// return 0 on success, or the status returned by OpenAL re-init.
extern LibError snd_dev_set(const char* alc_new_dev_name);
// set maximum number of voices to play simultaneously,
// to reduce mixing cost on low-end systems.
// return 0 on success, or 1 if limit was ignored
// (e.g. if higher than an implementation-defined limit anyway).
extern LibError snd_set_max_voices(uint cap);
// set amplitude modifier, which is effectively applied to all sounds.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
extern LibError snd_set_master_gain(float gain);
//
// sound instance
//
// open and return a handle to a sound instance.
//
// if <snd_fn> is a text file (extension ".txt"), it is assumed
// to be a definition file containing the sound file name and
// its gain (0.0 .. 1.0).
// otherwise, <snd_fn> is taken to be the sound file name and
// gain is set to the default of 1.0 (no attenuation).
//
// is_stream (default false) forces the sound to be opened as a stream:
// opening is faster, it won't be kept in memory, but only one instance
// can be open at a time.
extern Handle snd_open(const char* snd_fn, bool stream = false);
// close the sound <hs> and set hs to 0. if it was playing,
// it will be stopped. sounds are closed automatically when done
// playing; this is provided for completeness only.
extern LibError snd_free(Handle& hs);
// request the sound <hs> be played. once done playing, the sound is
// automatically closed (allows fire-and-forget play code).
// if no hardware voice is available, this sound may not be played at all,
// or in the case of looped sounds, start later.
// priority (min 0 .. max 1, default 0) indicates which sounds are
// considered more important; this is attenuated by distance to the
// listener (see snd_update).
extern LibError snd_play(Handle hs, float priority = 0.0f);
// change 3d position of the sound source.
// if relative (default false), (x,y,z) is treated as relative to the
// listener; otherwise, it is the position in world coordinates.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern LibError snd_set_pos(Handle hs, float x, float y, float z, bool relative = false);
// change gain (amplitude modifier) of the sound source.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
//
// should not be called during a fade (see note in implementation);
// fails with invalid handle return if the sound has already been
// closed (e.g. it never played).
extern LibError snd_set_gain(Handle hs, float gain);
// change pitch shift of the sound source.
// 1.0 means no change; each reduction by 50% equals a pitch shift of
// -12 semitones (one octave). zero is invalid.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern LibError snd_set_pitch(Handle hs, float pitch);
// enable/disable looping on the sound source.
// used to implement variable-length sounds (e.g. while building).
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
//
// notes:
// - looping sounds are not discarded if they cannot be played for lack of
// a hardware voice at the moment play was requested.
// - once looping is again disabled and the sound has reached its end,
// the sound instance is freed automatically (as if never looped).
extern LibError snd_set_loop(Handle hs, bool loop);
enum FadeType
{
FT_NONE,
FT_LINEAR,
FT_EXPONENTIAL,
FT_S_CURVE,
FT_ABORT
};
// fade the sound source in or out over time.
// its gain starts at <initial_gain> (immediately) and is moved toward
// <final_gain> over <length> seconds. <type> determines the fade curve:
// linear, exponential or S-curve. for guidance on which to use, see
// http://www.transom.org/tools/editing_mixing/200309.stupidfadetricks.html
// you can also pass FT_ABORT to stop fading (if in progress) and
// set gain to the current <final_gain> parameter.
// special cases:
// - if <initial_gain> < 0 (an otherwise illegal value), the sound's
// current gain is used as the start value (useful for fading out).
// - if <final_gain> is 0, the sound is freed when the fade completes or
// is aborted, thus allowing fire-and-forget fadeouts. no cases are
// foreseen where this is undesirable, and it is easier to implement
// than an extra set-free-after-fade-flag function.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
//
// note that this function doesn't busy-wait until the fade is complete;
// any number of fades may be active at a time (allows cross-fading).
// each snd_update calculates a new gain value for all pending fades.
// it is safe to start another fade on the same sound source while
// one is already in progress; the old one will be discarded.
extern LibError snd_fade(Handle hvs, float initial_gain, float final_gain,
float length, FadeType type);
//
// sound engine
//
// (temporarily) disable all sound output. because it causes future snd_open
// calls to immediately abort before they demand-initialize OpenAL,
// startup is sped up considerably (500..1000ms). therefore, this must be
// called before the first snd_open to have any effect; otherwise, the
// cat will already be out of the bag and we debug_warn of it.
//
// rationale: this is a quick'n dirty way of speeding up startup during
// development without having to change the game's sound code.
//
// can later be called to reactivate sound; all settings ever changed
// will be applied and subsequent sound load / play requests will work.
extern LibError snd_disable(bool disabled);
// perform housekeeping (e.g. streaming); call once a frame.
//
// additionally, if any parameter is non-NULL, we set the listener
// position, look direction, and up vector (in world coordinates).
extern LibError snd_update(const float* pos, const float* dir, const float* up);
// free all resources and shut down the sound system.
// call before h_mgr_shutdown.
extern void snd_shutdown();
#endif // #ifndef SND_H__
// OpenAL sound engine
//
// Copyright (c) 2004-5 Jan Wassenberg
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// Contact info:
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#ifndef SND_MGR_H__
#define SND_MGR_H__
#include "../handle.h"
/*
[KEEP IN SYNC WITH WIKI]
overview
--------
this module provides a moderately high-level sound interface. basic usage
is opening a sound and requesting it be played; it is closed automatically
when playback has finished (fire and forget).
any number of sound play requests may be issued; the most 'important' ones
are actually played (necessary due to limited hardware mixing capacity).
3d positional sounds (heard to emanate from a given spot) are supported.
active sound instances are referenced by Handles, so changing volume etc.
during playback is possible (useful for fadeout).
sound setup
-----------
OpenAL provides portable access to the underlying sound hardware, and
falls back to software mixing if no acceleration is provided.
we allow the user to specify the device to use (in case the default
has problems) and maximum number of sources (to reduce mixing cost).
performance
-----------
much effort has been invested in efficiency: all sound data is cached,
so every open() after the first is effectively free. large sound files are
streamed from disk to reduce load time and memory usage. hardware mixing
resources are suballocated to avoid delays when starting to play.
therefore, the user can confidently fire off hundreds of sound requests.
finally, lengthy initialization steps are delayed until the sound engine
is actually needed (i.e. upon first open()). perceived startup time is
therefore reduced - the user sees e.g. our main menu earlier.
terminology
-----------
"hardware voice" refers to mixing resources on the DSP. strictly
speaking, we mean 'OpenAL source', but this term is more clear.
voice ~= source, unless expensive effects (e.g. EAX) are enabled.
note: software mixing usually doesn't have a fixed 'source' cap.
"gain" is quantified volume. 1 is unattenuated, 0.5 corresponds to -6 dB,
and 0 is silence. this can be set per-source as well as globally.
"position" of a sound is within the app's coordinate system,
the orientation of which is passed to snd_update.
"importance" of a sound derives from the app-assigned priority
(e.g. voiceover must not be skipped in favor of seagulls) and
distance from the listener. it's calculated by our prioritizer.
"virtual source" denotes a sound play request issued by the app.
this is in contrast to an actual AL source, which will be mixed
into the output channel. the most important VSrc receive an al_src.
"sound instances" store playback parameters (e.g. position), and
reference the (centrally cached) "sound data" that will be played.
*/
//
// device enumeration
//
// prepare to enumerate all device names (this resets the list returned by
// snd_dev_next). return 0 on success, otherwise -1 (only if the requisite
// OpenAL extension isn't available). on failure, a "cannot enum device"
// message should be presented to the user, and snd_dev_set need not be
// called; OpenAL will use its default device.
// may be called each time the device list is needed.
extern LibError snd_dev_prepare_enum();
// return the next device name, or 0 if all have been returned.
// do not call unless snd_dev_prepare_enum succeeded!
// not thread-safe! (static data from snd_dev_prepare_enum is used)
extern const char* snd_dev_next();
//
// sound system setup
//
// tell OpenAL to use the specified device in future.
// name = 0 reverts to OpenAL's default choice, which will also
// be used if this routine is never called.
//
// the device name is typically taken from a config file at init-time;
// the snd_dev* enumeration routines below are used to present a list
// of choices to the user in the options screen.
//
// if OpenAL hasn't yet been initialized (i.e. no sounds have been opened),
// this just stores the device name for use when init does occur.
// note: we can't check now if it's invalid (if so, init will fail).
// otherwise, we shut OpenAL down (thereby stopping all sounds) and
// re-initialize with the new device. that's fairly time-consuming,
// so preferably call this routine before sounds are loaded.
//
// return 0 on success, or the status returned by OpenAL re-init.
extern LibError snd_dev_set(const char* alc_new_dev_name);
// set maximum number of voices to play simultaneously,
// to reduce mixing cost on low-end systems.
// return 0 on success, or 1 if limit was ignored
// (e.g. if higher than an implementation-defined limit anyway).
extern LibError snd_set_max_voices(uint cap);
// set amplitude modifier, which is effectively applied to all sounds.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
extern LibError snd_set_master_gain(float gain);
//
// sound instance
//
// open and return a handle to a sound instance.
//
// if <snd_fn> is a text file (extension ".txt"), it is assumed
// to be a definition file containing the sound file name and
// its gain (0.0 .. 1.0).
// otherwise, <snd_fn> is taken to be the sound file name and
// gain is set to the default of 1.0 (no attenuation).
//
// is_stream (default false) forces the sound to be opened as a stream:
// opening is faster, it won't be kept in memory, but only one instance
// can be open at a time.
extern Handle snd_open(const char* snd_fn, bool stream = false);
// close the sound <hs> and set hs to 0. if it was playing,
// it will be stopped. sounds are closed automatically when done
// playing; this is provided for completeness only.
extern LibError snd_free(Handle& hs);
// request the sound <hs> be played. once done playing, the sound is
// automatically closed (allows fire-and-forget play code).
// if no hardware voice is available, this sound may not be played at all,
// or in the case of looped sounds, start later.
// priority (min 0 .. max 1, default 0) indicates which sounds are
// considered more important; this is attenuated by distance to the
// listener (see snd_update).
extern LibError snd_play(Handle hs, float priority = 0.0f);
// change 3d position of the sound source.
// if relative (default false), (x,y,z) is treated as relative to the
// listener; otherwise, it is the position in world coordinates.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern LibError snd_set_pos(Handle hs, float x, float y, float z, bool relative = false);
// change gain (amplitude modifier) of the sound source.
// must be non-negative; 1 -> unattenuated, 0.5 -> -6 dB, 0 -> silence.
//
// should not be called during a fade (see note in implementation);
// fails with invalid handle return if the sound has already been
// closed (e.g. it never played).
extern LibError snd_set_gain(Handle hs, float gain);
// change pitch shift of the sound source.
// 1.0 means no change; each reduction by 50% equals a pitch shift of
// -12 semitones (one octave). zero is invalid.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
extern LibError snd_set_pitch(Handle hs, float pitch);
// enable/disable looping on the sound source.
// used to implement variable-length sounds (e.g. while building).
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
//
// notes:
// - looping sounds are not discarded if they cannot be played for lack of
// a hardware voice at the moment play was requested.
// - once looping is again disabled and the sound has reached its end,
// the sound instance is freed automatically (as if never looped).
extern LibError snd_set_loop(Handle hs, bool loop);
enum FadeType
{
FT_NONE,
FT_LINEAR,
FT_EXPONENTIAL,
FT_S_CURVE,
FT_ABORT
};
// fade the sound source in or out over time.
// its gain starts at <initial_gain> (immediately) and is moved toward
// <final_gain> over <length> seconds. <type> determines the fade curve:
// linear, exponential or S-curve. for guidance on which to use, see
// http://www.transom.org/tools/editing_mixing/200309.stupidfadetricks.html
// you can also pass FT_ABORT to stop fading (if in progress) and
// set gain to the current <final_gain> parameter.
// special cases:
// - if <initial_gain> < 0 (an otherwise illegal value), the sound's
// current gain is used as the start value (useful for fading out).
// - if <final_gain> is 0, the sound is freed when the fade completes or
// is aborted, thus allowing fire-and-forget fadeouts. no cases are
// foreseen where this is undesirable, and it is easier to implement
// than an extra set-free-after-fade-flag function.
//
// may be called at any time; fails with invalid handle return if
// the sound has already been closed (e.g. it never played).
//
// note that this function doesn't busy-wait until the fade is complete;
// any number of fades may be active at a time (allows cross-fading).
// each snd_update calculates a new gain value for all pending fades.
// it is safe to start another fade on the same sound source while
// one is already in progress; the old one will be discarded.
extern LibError snd_fade(Handle hvs, float initial_gain, float final_gain,
float length, FadeType type);
//
// sound engine
//
// (temporarily) disable all sound output. because it causes future snd_open
// calls to immediately abort before they demand-initialize OpenAL,
// startup is sped up considerably (500..1000ms). therefore, this must be
// called before the first snd_open to have any effect; otherwise, the
// cat will already be out of the bag and we debug_warn of it.
//
// rationale: this is a quick'n dirty way of speeding up startup during
// development without having to change the game's sound code.
//
// can later be called to reactivate sound; all settings ever changed
// will be applied and subsequent sound load / play requests will work.
extern LibError snd_disable(bool disabled);
// perform housekeeping (e.g. streaming); call once a frame.
//
// additionally, if any parameter is non-NULL, we set the listener
// position, look direction, and up vector (in world coordinates).
extern LibError snd_update(const float* pos, const float* dir, const float* up);
// free all resources and shut down the sound system.
// call before h_mgr_shutdown.
extern void snd_shutdown();
#endif // #ifndef SND_MGR_H__

98
source/lib/sysdep/cpu.cpp Normal file
View File

@ -0,0 +1,98 @@
#include "precompiled.h"
#include "lib.h"
#if CPU_IA32
# include "sysdep/ia32.h"
#endif
char cpu_type[CPU_TYPE_LEN] = "";
double cpu_freq = 0.f;
// -1 if detect not yet called, or cannot be determined
int cpus = -1;
int cpu_ht_units = -1;
int cpu_cores = -1;
int cpu_speedstep = -1;
void cpu_init()
{
#if CPU_IA32
// must come before any uses of ia32.asm, e.g. by get_cpu_info
ia32_init();
// no longer set 24 bit (float) precision by default: for
// very long game uptimes (> 1 day; e.g. dedicated server),
// we need full precision when calculating the time.
// if there's a spot where we want to speed up divides|sqrts,
// we can temporarily change precision there.
//ia32_control87(IA32_PC_24, IA32_MCW_PC);
// to help catch bugs, enable as many floating-point exceptions as
// possible. that means only zero-divide, because the JS engine is
// triggering the rest.
// note: passing a flag *disables* that exception.
ia32_control87(IA32_EM_INVALID|IA32_EM_DENORMAL|IA32_EM_OVERFLOW|IA32_EM_UNDERFLOW|IA32_EM_INEXACT, IA32_MCW_EM);
// no longer round toward zero (truncate). changing this setting
// resulted in much faster float->int casts, because the compiler
// could be told (via /QIfist) to use FISTP while still truncating
// the result as required by ANSI C. however, FPU calculation
// results were changed significantly, so it had to be disabled.
//ia32_control87(IA32_RC_CHOP, IA32_MCW_RC);
// If possible, hook up capability-sensitive assembler routines
ia32_hook_capabilities();
#endif
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
#if OS_WIN
extern LibError win_get_cpu_info();
win_get_cpu_info();
#elif OS_UNIX
extern LibError unix_get_cpu_info();
unix_get_cpu_info();
#endif
#if CPU_IA32
ia32_get_cpu_info();
#endif
}
//
// memory
//
size_t tot_mem = 0;
size_t avl_mem = 0;
size_t page_size = 0;
void get_mem_status()
{
#ifdef _SC_PAGESIZE
if(!page_size)
page_size = (size_t)sysconf(_SC_PAGESIZE);
#endif
// Sys V derived (GNU/Linux, Solaris)
#if defined(_SC_AVPHYS_PAGES)
tot_mem = sysconf(_SC_PHYS_PAGES ) * page_size;
avl_mem = sysconf(_SC_AVPHYS_PAGES) * page_size;
// BSD / Mac OS X
#elif defined(HW_PHYSMEM)
size_t len = sizeof(tot_mem);
int mib[2] = { CTL_HW, HW_PHYSMEM };
sysctl(mib, 2, &tot_mem, &len, 0, 0);
mib[1] = HW_USERMEM;
sysctl(mib, 2, &avl_mem, &len, 0, 0);
#endif
}

View File

@ -1,12 +1,12 @@
#ifndef SYSDEP_CPU_H
#define SYSDEP_CPU_H
#ifndef CPU_H__
#define CPU_H__
#ifdef __cplusplus
extern "C" {
#endif
const size_t CPU_TYPE_LEN = 49; // processor brand string is <= 48 chars
const size_t CPU_TYPE_LEN = 49; // IA32 processor brand string is <= 48 chars
extern char cpu_type[CPU_TYPE_LEN];
extern double cpu_freq;
@ -24,6 +24,13 @@ extern int cpu_speedstep;
extern void cpu_init(void);
extern size_t tot_mem;
extern size_t avl_mem;
// updates *_mem above
extern void get_mem_status(void);
// atomic "compare and swap". compare the machine word at <location> against
// <expected>; if not equal, return false; otherwise, overwrite it with
// <new_value> and return true.
@ -59,4 +66,4 @@ extern void serialize();
}
#endif
#endif
#endif // #ifndef CPU_H__

43
source/lib/sysdep/gfx.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "precompiled.h"
#include "lib.h"
#include "sdl.h"
#include "gfx.h"
char gfx_card[GFX_CARD_LEN] = "";
char gfx_drv_ver[GFX_DRV_VER_LEN] = "";
int gfx_mem = -1; // [MiB]; approximate
extern "C" LibError ogl_get_gfx_info();
// detect graphics card and set the above information.
void gfx_detect()
{
// TODO: add sizeof(FB)?
gfx_mem = (SDL_GetVideoInfo()->video_mem) / 1048576; // [MiB]
// try platform-specific version: they return more
// detailed information, and don't require OpenGL to be ready.
#if OS_WIN
extern LibError win_get_gfx_info();
if(win_get_gfx_info() < 0)
#endif
{
// the OpenGL version should always work, unless OpenGL isn't ready for use,
// or we were called between glBegin and glEnd.
ogl_get_gfx_info();
}
// remove crap from vendor names. (don't dare touch the model name -
// it's too risky, there are too many different strings)
#define SHORTEN(what, chars_to_keep)\
if(!strncmp(gfx_card, what, ARRAY_SIZE(what)-1))\
memmove(gfx_card+chars_to_keep, gfx_card+ARRAY_SIZE(what)-1, strlen(gfx_card)-(ARRAY_SIZE(what)-1)+1);
SHORTEN("ATI Technologies Inc.", 3);
SHORTEN("NVIDIA Corporation", 6);
SHORTEN("S3 Graphics", 2); // returned by EnumDisplayDevices
SHORTEN("S3 Graphics, Incorporated", 2); // returned by GL_VENDOR
#undef SHORTEN
}

View File

@ -5,25 +5,26 @@
extern "C" {
#endif
// useful for choosing a video mode.
// if we fail, outputs are unchanged (assumed initialized to defaults)
extern LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq);
// useful for determining aspect ratio.
// if we fail, outputs are unchanged (assumed initialized to defaults)
extern LibError get_monitor_size(int& width_mm, int& height_mm);
const size_t GFX_CARD_LEN = 128;
extern char gfx_card[GFX_CARD_LEN]; // default: ""
const size_t GFX_DRV_VER_LEN = 256; // increased from 64 by joe cocovich to accomodate unused drivers still in registry
extern char gfx_drv_ver[GFX_DRV_VER_LEN]; // default: ""
extern int gfx_mem; // [MiB]; approximate
// attempt to detect graphics card without OpenGL (in case ogl init fails,
// or we want more detailed info). gfx_card[] is unchanged on failure.
extern void get_gfx_info(void);
// detect graphics card and set the above information.
extern void gfx_detect(void);
// useful for choosing a video mode.
// if we fail, outputs are unchanged (assumed initialized to defaults)
extern LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq);
// useful for determining aspect ratio.
// if we fail, outputs are unchanged (assumed initialized to defaults)
extern LibError gfx_get_monitor_size(int& width_mm, int& height_mm);
#ifdef __cplusplus
}

View File

@ -20,7 +20,6 @@
#include "lib.h"
#include "posix.h"
#include "ia32.h"
#include "detect.h"
#include "timer.h"
// HACK (see call to wtime_reset_impl)

View File

@ -1,9 +0,0 @@
//
// mem
//
extern size_t tot_mem;
extern size_t avl_mem;
// updates *_mem above
extern void get_mem_status(void);

21
source/lib/sysdep/snd.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "precompiled.h"
#include "lib.h"
#include "snd.h"
char snd_card[SND_CARD_LEN];
char snd_drv_ver[SND_DRV_VER_LEN];
void snd_detect()
{
#if OS_WIN
extern LibError win_get_snd_info();
win_get_snd_info();
#else
// At least reset the values for unhandled platforms. Should perhaps do
// something like storing the OpenAL version or similar.
debug_assert(SND_CARD_LEN >= 8 && SND_DRV_VER_LEN >= 8); // protect strcpy
SAFE_STRCPY(snd_card, "Unknown");
SAFE_STRCPY(snd_drv_ver, "Unknown");
#endif
}

View File

@ -1,5 +1,9 @@
#ifndef SYSDEP_SND_H__
#define SYSDEP_SND_H__
#ifndef SND_H__
#define SND_H__
#ifdef __cplusplus
extern "C" {
#endif
const size_t SND_CARD_LEN = 128;
extern char snd_card[SND_CARD_LEN];
@ -7,7 +11,12 @@ extern char snd_card[SND_CARD_LEN];
const size_t SND_DRV_VER_LEN = 256;
extern char snd_drv_ver[SND_DRV_VER_LEN];
// detect sound card and set the above information.
extern void snd_detect(void);
extern void get_snd_info(void);
#endif // #ifndef SYSDEP_SND_H__
#ifdef __cplusplus
}
#endif
#endif // #ifndef SND_H__

View File

@ -31,7 +31,7 @@
// useful for choosing a video mode. not called by detect().
// if we fail, outputs are unchanged (assumed initialized to defaults)
LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq)
{
Display* disp = XOpenDisplay(0);
if(!disp)
@ -65,7 +65,7 @@ LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
// useful for determining aspect ratio. not called by detect().
// if we fail, outputs are unchanged (assumed initialized to defaults)
LibError get_monitor_size(int& width_mm, int& height_mm)
LibError gfx_get_monitor_size(int& width_mm, int& height_mm)
{
Display* disp = XOpenDisplay(0);
if(!disp)

View File

@ -588,14 +588,15 @@ static int aio_rw(struct aiocb* cb)
else
ok = ReadFile(h, actual_buf, size32, &bytes_transferred, &r->ovl);
// "pending" isn't an error
if(GetLastError() == ERROR_IO_PENDING)
ok = true;
if(ok)
// check result.
// .. "pending" isn't an error
if(!ok && GetLastError() == ERROR_IO_PENDING)
ok = TRUE;
// .. translate from Win32 result code to POSIX
LibError err = LibError_from_win32(ok);
if(err == ERR_OK)
ret = 0;
else
debug_warn("waio failure");
LibError_set_errno(err);
done:
WIN_RESTORE_LAST_ERROR;

View File

@ -18,7 +18,8 @@
#include "precompiled.h"
#include "detect.h"
#include "sysdep/gfx.h"
#include "sysdep/snd.h"
#include "lib.h"
#include "lib/res/file/file.h" // file_enum
@ -92,7 +93,7 @@ static LibError import_EnumDisplayDevices()
// useful for choosing a video mode.
// if we fail, outputs are unchanged (assumed initialized to defaults)
LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq)
{
// don't use EnumDisplaySettingsW - BoundsChecker reports it causes
// a memory overrun (even if called as the very first thing, before
@ -121,7 +122,7 @@ LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
// useful for determining aspect ratio.
// if we fail, outputs are unchanged (assumed initialized to defaults)
LibError get_monitor_size(int& width_mm, int& height_mm)
LibError gfx_get_monitor_size(int& width_mm, int& height_mm)
{
// (DC for the primary monitor's entire screen)
HDC dc = GetDC(0);

View File

@ -21,7 +21,6 @@
#include "posix.h"
#include "adts.h"
#include "sysdep/ia32.h"
#include "detect.h"
#include "win_internal.h"

View File

@ -4,7 +4,7 @@
#include "ps/ConfigDB.h"
#include "ps/CConsole.h"
#include "lib/timer.h"
#include "lib/res/sound/snd.h"
#include "lib/res/sound/snd_mgr.h"
#include "lib/res/file/trace.h"
#include "lib/res/file/vfs_optimizer.h"
#include "Config.h"

View File

@ -3,15 +3,15 @@
#include "lib.h"
#include "lib/sdl.h"
#include "lib/ogl.h"
#include "lib/detect.h"
#include "lib/timer.h"
#include "lib/input.h"
#if CPU_IA32
# include "lib/sysdep/ia32.h"
#endif
#include "lib/sysdep/gfx.h"
#include "lib/res/res.h"
#include "lib/res/file/trace.h"
#include "lib/res/sound/snd.h"
#include "lib/res/sound/snd_mgr.h"
#include "lib/res/graphics/tex.h"
#include "lib/res/graphics/cursor.h"
@ -896,7 +896,7 @@ void Init(int argc, char* argv[], uint flags)
// preferred video mode = current desktop settings
// (command line params may override these)
get_cur_vmode(&g_xres, &g_yres, &g_bpp, &g_freq);
gfx_get_video_mode(&g_xres, &g_yres, &g_bpp, &g_freq);
new CProfileViewer;
new CProfileManager; // before any script code
@ -934,7 +934,7 @@ void Init(int argc, char* argv[], uint flags)
SetTextureQuality(quality);
// required by ogl_tex to detect broken gfx card/driver combos
get_gfx_info();
gfx_detect();
//-------------------------------------------------------------------------

View File

@ -4,7 +4,8 @@
#include "lib/res/file/vfs_path.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "lib/detect.h"
#include "lib/sysdep/gfx.h"
#include "lib/sysdep/snd.h"
#include "lib/res/res.h"
#include "lib/res/graphics/tex.h"
@ -42,8 +43,8 @@ void WriteSystemInfo()
{
TIMER("write_sys_info");
// get_cpu_info and get_gfx_info already called during init - see call site
get_snd_info();
// get_cpu_info and gfx_detect already called during init - see call site
snd_detect();
get_mem_status();
struct utsname un;

View File

@ -2,7 +2,7 @@
#include "JSI_Sound.h"
#include "Vector3D.h"
#include "lib/res/sound/snd.h"
#include "lib/res/sound/snd_mgr.h"
#include "lib/res/h_mgr.h" // h_filename