- config: all macros are defined as 1 / 0. testing with #if allows compiler warnings (testing undefined macro) to spot misspelled macros

- debug: add provision for naming threads. allows adding current thread
name to log messages and displays their names in the debugger.
- replaced various if(err < 0) complain() sequences with new variants of
CHECK_ERR (see lib.h)
- fixes to mmgr/VC debug alloc enable code
- improved h_mgr error reporting (now complains when h_free fails)
- US -> UK english (partial)
- fix tex_load double-free bug
- move win32 mouse cursor code into sysdep
- error dialog is now topmost to make sure it's visible (was a problem)
- handle WM_QUIT before displaying error dialog (makes sure it's shown)

also as in previous 3 revisions.

This was SVN commit r2588.
This commit is contained in:
janwas 2005-08-09 16:23:19 +00:00
parent 620c65722f
commit 5299dcad86
59 changed files with 1352 additions and 931 deletions

View File

@ -1,35 +1,71 @@
#ifndef CONFIG_H_INCLUDED
#define CONFIG_H_INCLUDED
// the config/have macros are always defined; their values (1 or 0) are
// tested with #if instead of #ifdef.
// this protects user code from typos such as #ifdef _MSC_VEER, which
// would silently remove code. instead, we will at least get "test of
// undefined macro" warnings here. not including this header also triggers
// such warnings, but won't happen often because we're included from PCH.
//-----------------------------------------------------------------------------
// user-specified configuration choices
//-----------------------------------------------------------------------------
#undef CONFIG_DISABLE_EXCEPTIONS
// allow override via compiler settings by checking #ifndef.
#undef CONFIG_USE_MMGR
// enable memory tracking (slow). see mmgr.cpp.
#ifndef CONFIG_USE_MMGR
# define CONFIG_USE_MMGR 0
#endif
// enable additional debug checks (very slow).
#ifndef CONFIG_PARANOIA
# define CONFIG_PARANOIA 0
#endif
// try to prevent any exceptions from being thrown - even by the C++
// standard library. useful only for performance tests.
#ifndef CONFIG_DISABLE_EXCEPTIONS
# define CONFIG_DISABLE_EXCEPTIONS 0
#endif
//-----------------------------------------------------------------------------
// auto-detect OS and platform via predefined macros
//-----------------------------------------------------------------------------
// get compiler versions with consistent names + format:
// (major*100 + minor), or 0 if not present. note that more than
// rationale:
// - these macros have consistent names and numerical values; using
// them saves other code from having to know the obscure predefined macros.
// - we'd like to use #if/#elif/#endif chains for e.g. OS_* to allow warning
// if none is selected, but there's no good way to #define all inapplicable
// settings to 0. doing so up front is hard to maintain and would require
// #undef before setting any one to 1. #ifndef afterwards for each setting
// is ugly and brittle as well. we therefore use #if/#else/#endif.
// compiler
// 0 if not present, or (major*100 + minor). note that more than
// one *_VERSION may be non-zero due to interoperability (e.g. ICC with MSC).
// .. ICC
#if defined(__INTEL_COMPILER)
# define ICC_VERSION __INTEL_COMPILER
#else
# define ICC_VERSION 0
#endif
// .. VC
#ifdef _MSC_VER
# define MSC_VERSION _MSC_VER
#else
# define MSC_VERSION 0
#endif
// .. ICC (VC-compatible)
#if defined(__INTEL_COMPILER)
# define ICC_VERSION __INTEL_COMPILER
#else
# define ICC_VERSION 0
#endif
// .. LCC (VC-compatible)
#if defined(__LCC__)
# define LCC_VERSION __LCC__
#else
# define LCC_VERSION 0
#endif
// .. GCC
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__*100 + __GNUC_MINOR__)
@ -37,10 +73,12 @@
# define GCC_VERSION 0
#endif
// STL
// .. pull in the Dinkumware header that defines _CPPLIB_VER
// (checked by STL implementation-specific code in debug_stl).
// .. Dinkumware
#if MSC_VERSION != 0
# include <yvals.h>
# include <yvals.h> // defines _CPPLIB_VER
#endif
#if defined(_CPPLIB_VER)
# define STL_DINKUMWARE _CPPLIB_VER
@ -48,119 +86,190 @@
# define STL_DINKUMWARE 0
#endif
// OS
// .. Windows
#if defined(_WIN32) || defined(WIN32)
# define OS_WIN
// .. Linux
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define OS_LINUX
# define OS_UNIX
// .. Mac OS X
#elif defined(MAC_OS_X
# define OS_MACOSX
# define OS_UNIX
// .. BSD
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# define OS_BSD
# define OS_UNIX
// .. Solaris
#elif defined(SOLARIS)
# define OS_SOLARIS
# define OS_UNIX
// .. BeOS
#elif defined(__BEOS__)
# define OS_BEOS
// .. Mac OS 9 or below
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define OS_MAC
// .. Amiga
#elif defined(__amigaos__)
# define OS_AMIGA
// .. Unix-based
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
# define OS_UNIX
// .. unknown
# define OS_WIN 1
#else
# error "unknown OS - add define here"
# define OS_WIN 0
#endif
// .. Linux
#if defined(linux) || defined(__linux) || defined(__linux__)
# define OS_LINUX 1
#else
# define OS_LINUX 0
#endif
// .. Mac OS X
#if defined(MAC_OS_X)
# define OS_MACOSX 1
#else
# define OS_MACOSX 0
#endif
// .. BSD
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# define OS_BSD 1
#else
# define OS_BSD 0
#endif
// .. Solaris
#if defined(SOLARIS)
# define OS_SOLARIS 1
#else
# define OS_SOLARIS 0
#endif
// .. BeOS
#if defined(__BEOS__)
# define OS_BEOS 1
#else
# define OS_BEOS 0
#endif
// .. Mac OS 9 or below
#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define OS_MAC 1
#else
# define OS_MAC 0
#endif
// .. Amiga
#if defined(__amigaos__)
# define OS_AMIGA 1
#else
# define OS_AMIGA 0
#endif
// .. Unix-based
#if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
# define OS_UNIX 1
#else
# define OS_UNIX 0
#endif
// .. convenience: additionally set OS_UNIX for Unix-based OSes
#if OS_LINUX || OS_MACOSX || OS_BSD || OS_SOLARIS
# undef OS_UNIX
# define OS_UNIX 1
#endif
// If these are already defined by someone else, assume they are also correct :P
#if !(defined(IS_LITTLE_ENDIAN) || defined(IS_BIG_ENDIAN))
// CPU
// .. IA-32
#if defined(__i386__) || defined(__i386) || defined(_M_IX86)
# define CPU_IA32 1
#else
# define CPU_IA32 0
#endif
// .. IA-64
#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64)
# define CPU_IA64 1
#else
# define CPU_IA64 0
#endif
// .. AMD64
#if defined(__amd64__) || defined(__amd64) || defined(_M_AMD64)
# define CPU_AMD64 1
#else
# define CPU_AMD64 0
#endif
// .. Alpha
#if defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA)
# define CPU_ALPHA 1
#else
# define CPU_ALPHA 0
#endif
// .. ARM
#if defined(__arm__)
# define CPU_ARM 1
#else
# define CPU_ARM 0
#endif
// .. MIPS
#if defined(__MIPSEL__)
# define CPU_MIPS 1
#else
# define CPU_MIPS 0
#endif
// byte order
# if defined(__i386__) || defined(__i386) || defined(_M_IX86) || \
defined(__ia64__) || defined(__ia64) || defined(_M_IA64) || \
defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) || \
defined(__arm__) || \
defined(__MIPSEL__) || \
defined(__LITTLE_ENDIAN__)
# define IS_LITTLE_ENDIAN
// if already defined by someone else, assume they are also correct :P
#ifndef BYTE_ORDER
# define LITTLE_ENDIAN 0x4321
# define BIG_ENDIAN 0x1234
# if CPU_IA32 || CPU_IA64 || CPU_AMD64 || CPU_ALPHA || CPU_ARM || CPU_MIPS || defined(__LITTLE_ENDIAN__)
# define BYTE_ORDER LITTLE_ENDIAN
# else
# define IS_BIG_ENDIAN
# define BYTE_ORDER BIG_ENDIAN
# endif
#endif
//-----------------------------------------------------------------------------
// auto-detect platform features, given the above information
//-----------------------------------------------------------------------------
// compiler support for C99
// (this is more convenient than testing __STDC_VERSION__ directly)
#undef HAVE_C99
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define HAVE_C99
# define HAVE_C99 1
#else
# define HAVE_C99 0
#endif
// gettimeofday()
#undef HAVE_GETTIMEOFDAY
#ifdef OS_UNIX
# define HAVE_GETTIMEOFDAY
#if OS_UNIX
# define HAVE_GETTIMEOFDAY 1
#else
# define HAVE_GETTIMEOFDAY 0
#endif
// clock_gettime()
#if OS_LINUX
# define HAVE_CLOCK_GETTIME 1
#else
# define HAVE_CLOCK_GETTIME 0
#endif
// X server
#undef HAVE_X
#ifdef OS_LINUX
# define HAVE_X
#if OS_LINUX
# define HAVE_X 1
#else
# define HAVE_X 0
#endif
// __asm{} blocks (Intel syntax)
#undef HAVE_ASM
#if MSC_VERSION != 0
# define HAVE_ASM
#if MSC_VERSION
# define HAVE_ASM 1
#else
# define HAVE_ASM 0
#endif
// precompiled headers (affects what precompiled.h pulls in; see there)
#undef HAVE_PCH
#if (MSC_VERSION != 0) || (GCC_VERSION > 304)
# define HAVE_PCH
#if MSC_VERSION || (GCC_VERSION > 304)
# define HAVE_PCH 1
#else
# define HAVE_PCH 0
#endif
// VC debug memory allocator / leak detector
#undef HAVE_VC_DEBUG_ALLOC
#if MSC_VERSION != 0
# define HAVE_VC_DEBUG_ALLOC
#endif
// .. only in full-debug mode;
#if defined(NDEBUG) || defined(TESTING)
# undef HAVE_VC_DEBUG_ALLOC
#endif
// .. require PCH, because it makes sure system headers are included before
// redefining new (otherwise, tons of errors result);
#if !defined(HAVE_PCH)
# undef HAVE_VC_DEBUG_ALLOC
#endif
// .. disable on ICC9, because the ICC 9.0.006 beta appears to generate
// incorrect code when we redefine new.
// TODO: remove when no longer necessary
#if ICC_VERSION == 900
# undef HAVE_VC_DEBUG_ALLOC
// notes:
// - PCH is required because it makes sure system headers are included
// before redefining new (otherwise, tons of errors result);
// - disabled on ICC9 because the ICC 9.0.006 beta appears to generate
// incorrect code when we redefine new.
// TODO: remove when no longer necessary
#if MSC_VERSION && \
(!defined(NDEBUG) || defined(TESTING)) && \
HAVE_PCH && \
ICC_VERSION != 900
# define HAVE_VC_DEBUG_ALLOC 1
#else
# define HAVE_VC_DEBUG_ALLOC 0
#endif
// nonstandard STL containers
#undef HAVE_STL_HASH
#undef HAVE_STL_SLIST
#define HAVE_STL_SLIST 0
#if STL_DINKUMWARE != 0
# define HAVE_STL_HASH
# define HAVE_STL_HASH 1
#else
# define HAVE_STL_HASH 0
#endif
#endif // #ifndef CONFIG_H_INCLUDED

View File

@ -23,11 +23,11 @@
#include "lib.h"
#include "debug.h"
#include "debug_stl.h"
#include "posix.h"
#include "nommgr.h"
// some functions here are called from within mmgr; disable its hooks
// so that our allocations don't cause infinite recursion.
// needed when writing crashlog
static const size_t LOG_CHARS = 16384;
wchar_t debug_log[LOG_CHARS];
@ -336,7 +336,7 @@ const char* debug_get_symbol_string(void* symbol, const char* name, const char*
//-----------------------------------------------------------------------------
ErrorReaction display_error(const wchar_t* description, int flags,
uint skip, void* context, const char* file, int line)
@ -408,7 +408,7 @@ ErrorReaction display_error(const wchar_t* description, int flags,
// disable memory-leak reporting to avoid a flood of warnings
// (lots of stuff will leak since we exit abnormally).
debug_heap_enable(DEBUG_HEAP_NONE);
#ifdef CONFIG_USE_MMGR
#if CONFIG_USE_MMGR
mmgr_set_options(0);
#endif
@ -432,4 +432,76 @@ ErrorReaction debug_assert_failed(const char* file, int line, const char* expr)
wchar_t buf[200];
swprintf(buf, ARRAY_SIZE(buf), L"Assertion failed in %hs, line %d: \"%hs\"", base_name, line, expr);
return display_error(buf, DE_ALLOW_SUPPRESS|DE_MANUAL_BREAK, skip, context, base_name, line);
}
}
//-----------------------------------------------------------------------------
// thread naming
//-----------------------------------------------------------------------------
// when debugging multithreading problems, logging the currently running
// thread is helpful; a user-specified name is easier to remember than just
// the thread handle. to that end, we provide a robust TLS mechanism that is
// much safer than the previous method of hijacking TIB.pvArbitrary.
//
// note: on Win9x thread "IDs" are pointers to the TIB xor-ed with an
// obfuscation value calculated at boot-time.
//
// __declspec(thread) et al. are now available on VC and newer GCC but we
// implement TLS manually (via pthread_setspecific) to ensure compatibility.
static pthread_key_t tls_key;
static pthread_once_t tls_once = PTHREAD_ONCE_INIT;
// provided for completeness and to avoid displaying bogus resource leaks.
static void tls_shutdown()
{
WARN_ERR(pthread_key_delete(tls_key));
tls_key = 0;
}
// (called via pthread_once from debug_set_thread_name)
static void tls_init()
{
WARN_ERR(pthread_key_create(&tls_key, 0)); // no dtor
// note: do not use atexit; this may be called before _cinit.
}
// set the current thread's name; it will be returned by subsequent calls to
// debug_get_thread_name.
//
// the string pointed to by <name> MUST remain valid throughout the
// entire program; best to pass a string literal. allocating a copy
// would be quite a bit more work due to cleanup issues.
//
// if supported on this platform, the debugger is notified of the new name;
// it will be displayed there instead of just the handle.
void debug_set_thread_name(const char* name)
{
WARN_ERR(pthread_once(&tls_once, tls_init));
WARN_ERR(pthread_setspecific(tls_key, name));
wdbg_set_thread_name(name);
}
// return the pointer assigned by debug_set_thread_name or 0 if
// that hasn't been done yet for this thread.
const char* debug_get_thread_name()
{
return (const char*)pthread_getspecific(tls_key);
}
void debug_shutdown()
{
tls_shutdown();
}

View File

@ -20,7 +20,7 @@
#include "lib.h" // STMT
#include "sysdep/sysdep.h" // ErrorReaction
#ifdef _WIN32
#if OS_WIN
# include "sysdep/win/wdbg.h"
#else
# include "sysdep/unix/udbg.h"
@ -107,7 +107,7 @@ extern void debug_heap_enable(DebugHeapChecks what);
// the string can pass more information about the problem on to whomever
// is seeing the error.
//
// rationale: 0x55 and 0xaa have distinctive bit patterns and thus
// rationale: 0x55 and 0xAA are distinctive values and thus
// help debug the symbol engine.
#define debug_assert(expr) \
STMT(\
@ -117,7 +117,7 @@ STMT(\
switch(debug_assert_failed(__FILE__, __LINE__, #expr))\
{\
case ER_SUPPRESS:\
suppress__ = 0xaa;\
suppress__ = 0xAA;\
break;\
case ER_BREAK:\
debug_break();\
@ -142,8 +142,12 @@ extern enum ErrorReaction debug_assert_failed(const char* source_file, int line,
//-----------------------------------------------------------------------------
// show a dialog to make sure unexpected states in the program are noticed.
// this is less error-prone than debug_assert(!"text");
#define debug_warn(str) debug_assert(0 && (str))
// this is less error-prone than "debug_assert(0 && "text");" and avoids
// "conditional expression is constant" warnings. we'd really like to
// completely eliminate the problem; replacing 0 literals with extern
// volatile variables fools VC7 but isn't guaranteed to be free of overhead.
// we therefore just squelch the warning (unfortunately non-portable).
#define debug_warn(str) debug_assert((str) && 0)
// write to the debugger output window (may take ~1 ms!)
extern void debug_printf(const char* fmt, ...);
@ -247,9 +251,28 @@ typedef const u8* (*DebugIterator)(void* internal, size_t el_size);
extern void* debug_get_nth_caller(uint skip, void* context);
// return 1 if the pointer appears to be totally bogus, otherwise 0.
// this check is not authoritative in that the pointer may in truth
// be invalid regardless of the return value here, but can be used
// to filter out obviously wrong values in a portable manner.
extern int debug_is_bogus_pointer(const void* p);
// this check is not authoritative (the pointer may be "valid" but incorrect)
// but can be used to filter out obviously wrong values in a portable manner.
extern int debug_is_pointer_bogus(const void* p);
// set the current thread's name; it will be returned by subsequent calls to
// debug_get_thread_name.
//
// the string pointed to by <name> MUST remain valid throughout the
// entire program; best to pass a string literal. allocating a copy
// would be quite a bit more work due to cleanup issues.
//
// if supported on this platform, the debugger is notified of the new name;
// it will be displayed there instead of just the handle.
extern void debug_set_thread_name(const char* name);
// return the pointer assigned by debug_set_thread_name or 0 if
// that hasn't been done yet for this thread.
extern const char* debug_get_thread_name();
// call at exit to avoid leaks (not strictly necessary).
extern void debug_shutdown();
#endif // #ifndef DEBUG_H_INCLUDED

View File

@ -68,7 +68,7 @@ char* stl_simplify_name(char* name)
// for each character: (except those skipped as parts of strings)
for(;;)
{
int c = *(++src);
char c = *(++src);
// preincrement rationale: src++ with no further changes would
// require all comparisons to subtract 1. incrementing at the
// end of a loop would require a goto, instead of continue
@ -184,7 +184,7 @@ static bool container_valid(const void* front, size_t el_count)
if(el_count > 0x1000000)
return false;
if(debug_is_bogus_pointer(front))
if(debug_is_pointer_bogus(front))
return false;
return true;
@ -212,9 +212,8 @@ public:
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
@ -231,7 +230,7 @@ public:
};
*/
#ifndef OS_UNIX
#if !OS_UNIX
//
// standard containers
@ -270,9 +269,8 @@ public:
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
@ -295,23 +293,22 @@ public:
class Any_list : public std::list<int>
{
public:
bool valid(size_t el_size) const
bool valid(size_t UNUSED(el_size)) const
{
if(!container_valid(_Myhead, _Mysize))
return false;
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
class iter : public const_iterator
{
public:
const u8* deref_and_advance(size_t el_size)
const u8* deref_and_advance(size_t UNUSED(el_size))
{
const u8* p = (const u8*)&operator*();
++(*this);
@ -336,16 +333,17 @@ template<class _Traits> class Any_tree : public std::_Tree<_Traits>
}
public:
bool valid(size_t el_size) const
Any_tree() {}
bool valid(size_t UNUSED(el_size)) const
{
if(!container_valid(_Myhead, _Mysize))
return false;
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
@ -407,7 +405,7 @@ class Any_multiset: public Any_set
class Any_vector: public std::vector<int>
{
public:
bool valid(size_t el_size) const
bool valid(size_t UNUSED(el_size)) const
{
if(!container_valid(_Myfirst, _Mylast-_Myfirst))
return false;
@ -465,16 +463,15 @@ public:
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
class iter : public const_iterator
{
public:
const u8* deref_and_advance(size_t el_size)
const u8* deref_and_advance(size_t UNUSED(el_size))
{
const u8* p = (const u8*)&operator*();
++(*this);
@ -506,7 +503,7 @@ class Any_stack : public Any_deque
// nonstandard containers (will probably be part of C++0x)
//
#ifdef HAVE_STL_HASH
#if HAVE_STL_HASH
class Any_hash_map: public STL_HASH_MAP<int,int>
@ -520,16 +517,15 @@ public:
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
class iter : public const_iterator
{
public:
const u8* deref_and_advance(size_t el_size)
const u8* deref_and_advance(size_t UNUSED(el_size))
{
const u8* p = (const u8*)&operator*();
++(*this);
@ -555,16 +551,15 @@ public:
return true;
}
size_t el_count(size_t el_size) const
size_t el_count(size_t UNUSED(el_size)) const
{
UNUSED(el_size);
return size();
}
class iter : public const_iterator
{
public:
const u8* deref_and_advance(size_t el_size)
const u8* deref_and_advance(size_t UNUSED(el_size))
{
const u8* p = (const u8*)&operator*();
++(*this);
@ -580,7 +575,7 @@ class Any_hash_multiset : public Any_hash_set
#endif // HAVE_STL_HASH
#ifdef HAVE_STL_SLIST
#if HAVE_STL_SLIST
class Any_slist: public Any_list
@ -633,7 +628,7 @@ int stl_get_container_info(const char* type_name, const u8* p, size_t size,
// HACK: The debug_stl code breaks VS2005's STL badly, causing crashes in
// later pieces of code that try to manipulate the STL containers. Presumably
// it needs to be altered/rewritten to work happily with the new STL debug iterators.
#if defined(_MSC_VER) && _MSC_VER >= 1400
#if MSC_VERSION >= 1400
return -1;
#endif
@ -670,13 +665,13 @@ int stl_get_container_info(const char* type_name, const u8* p, size_t size,
CONTAINER(queue, "std::queue<*,std::deque<*> >")
CONTAINER(stack, "std::stack<*,std::deque<*> >")
// nonstandard containers (will probably be part of C++0x)
#ifdef HAVE_STL_HASH
#if HAVE_STL_HASH
CONTAINER(hash_map, STRINGIZE(STL_HASH_MAP) "<*>")
CONTAINER(hash_multimap, STRINGIZE(STL_HASH_MULTIMAP) "<*>")
CONTAINER(hash_set, STRINGIZE(STL_HASH_SET) "<*>")
CONTAINER(hash_multiset, STRINGIZE(STL_HASH_MULTISET) "<*>")
#endif
#ifdef HAVE_STL_SLIST
#if HAVE_STL_SLIST
CONTAINER(slist, STRINGIZE(STL_SLIST) "<*>")
#endif
@ -686,4 +681,5 @@ int stl_get_container_info(const char* type_name, const u8* p, size_t size,
return STL_CNT_INVALID;
return 0;
}
#endif

View File

@ -28,11 +28,11 @@
#include "timer.h"
#include "sdl.h"
#ifdef _M_IX86
#if CPU_IA32
extern void ia32_get_cpu_info();
#endif
#ifdef _WIN32
#if OS_WIN
extern int win_get_gfx_info();
extern int win_get_cpu_info();
extern int win_get_snd_info();
@ -58,13 +58,13 @@ void get_mem_status()
#endif
// Sys V derived (GNU/Linux, Solaris)
#ifdef _SC_AVPHYS_PAGES
#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 HAVE_SYSCTL && defined(HW_PHYSMEM)
#elif defined(HW_PHYSMEM)
size_t len = sizeof(tot_mem);
int mib[2] = { CTL_HW, HW_PHYSMEM };
@ -99,7 +99,7 @@ void get_gfx_info()
// try platform-specific versions first: they return more
// detailed information, and don't require OpenGL to be ready.
#ifdef _WIN32
#if OS_WIN
ret = win_get_gfx_info();
#endif
@ -129,11 +129,11 @@ int cpu_smp = -1;
void get_cpu_info()
{
#ifdef _WIN32
#if OS_WIN
win_get_cpu_info();
#endif
#ifdef _M_IX86
#if CPU_IA32
ia32_get_cpu_info();
#endif
}
@ -148,7 +148,7 @@ char snd_drv_ver[SND_DRV_VER_LEN];
void get_snd_info()
{
#ifdef _WIN32
#if OS_WIN
win_get_snd_info();
#else
// At least reset the values for unhandled platforms. Should perhaps do

View File

@ -1,5 +1,5 @@
#include <GL/glext.h>
#ifdef _WIN32
#if OS_WIN
# include <GL/wglext.h>
#endif
/*
@ -66,7 +66,7 @@ FUNC2(void, glCompressedTexSubImage2DARB, glCompressedTexSubImage2D, "1.3", (GLe
FUNC2(void, glCompressedTexSubImage1DARB, glCompressedTexSubImage1D, "1.3", (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid*))
FUNC2(void, glGetCompressedTexImageARB, glGetCompressedTexImage, "1.3", (GLenum, GLint, GLvoid*))
#ifdef _WIN32
#if OS_WIN
// WGL_EXT_swap_control
FUNC(int, wglSwapIntervalEXT, (int))
@ -81,4 +81,4 @@ FUNC(int, wglQueryPbufferARB, (HPBUFFERARB, int, int*))
FUNC(int, wglGetPixelFormatAttribivARB, (HDC, int, int, unsigned int, const int*, int*))
FUNC(int, wglGetPixelFormatAttribfvARB, (HDC, int, int, unsigned int, const int*, float*))
FUNC(int, wglChoosePixelFormatARB, (HDC, const int *, const float*, unsigned int, int*, unsigned int*))
#endif // _WIN32
#endif // OS_WIN

View File

@ -18,6 +18,8 @@
#include "precompiled.h"
#if 0
#include <algorithm>
#include <limits.h>
@ -580,3 +582,4 @@ bucket = prev_bucket;
}
}
*/
#endif

View File

@ -146,7 +146,7 @@ bool is_pow2(const long n)
int ilog2(const int n)
{
#ifdef _M_IX86
#if CPU_IA32
__asm
{
@ -266,6 +266,20 @@ i64 movsx_64le(const u8* p, size_t size)
}
// these avoid a common mistake in using >> (ANSI requires shift count be
// less than the bit width of the type).
u32 u64_hi(u64 x)
{
return (u32)(x >> 32);
}
u32 u64_lo(u64 x)
{
return (u32)(x & 0xffffffff);
}
// input in [0, 1); convert to u8 range
u8 fp_to_u8(double in)

View File

@ -67,21 +67,15 @@ scope
#define EXTERN_C extern
#endif
// tell STL not to generate exceptions, if compiling without exceptions
// (usually done for performance reasons).
#ifdef CONFIG_DISABLE_EXCEPTIONS
# ifdef _WIN32
# define _HAS_EXCEPTIONS 0
# else
# define STL_NO_EXCEPTIONS
# endif
#endif
#define STMT(STMT_code__) do { STMT_code__; } while(0)
// package code into a single statement.
// notes:
// - for(;;) { break; } and {} don't work because invocations of macros
// implemented with STMT often end with ";", thus breaking if() expressions.
// - we'd really like to eliminate "conditional expression is constant"
// warnings. replacing 0 literals with extern volatile variables fools
// VC7 but isn't guaranteed to be free of overhead. we will just
// squelch the warning (unfortunately non-portable).
#define STMT(STMT_code__) do { STMT_code__; } while(false)
// may be called at any time (in particular before main), but is not
// thread-safe. if that's important, use pthread_once() instead.
@ -105,7 +99,8 @@ STMT(\
// therefore known to fit; we still mask with UINT_MAX to avoid
// VC cast-to-smaller-type warnings.
#ifdef _WIN32
// if expression evaluates to a negative i64, warn user and return the number.
#if OS_WIN
#define CHECK_ERR(expression)\
STMT(\
i64 err__ = (i64)(expression);\
@ -138,17 +133,40 @@ STMT(\
return (int)(err__ & UINT_MAX);\
)
// if expression evaluates to a negative i64, warn user and throw the number.
#define THROW_ERR(expression)\
STMT(\
i64 err__ = (i64)(expression);\
if(err__ < 0)\
{\
debug_warn("FYI: CHECK_ERR reports that a function failed."\
debug_warn("FYI: THROW_ERR reports that a function failed."\
"feel free to ignore or suppress this warning.");\
throw (int)(err__ & UINT_MAX);\
}\
)
// if expression evaluates to a negative i64, warn user and just return
// (useful for void functions that must bail and complain)
#define WARN_ERR_RETURN(expression)\
STMT(\
i64 err__ = (i64)(expression);\
if(err__ < 0)\
{\
debug_warn("FYI: WARN_ERR_RETURN reports that a function failed."\
"feel free to ignore or suppress this warning.");\
return;\
}\
)
// if expression evaluates to a negative i64, warn user
// (this is similar to debug_assert but also works in release mode)
#define WARN_ERR(expression)\
STMT(\
i64 err__ = (i64)(expression);\
if(err__ < 0)\
debug_warn("FYI: WARN_ERR reports that a function failed."\
"feel free to ignore or suppress this warning.");\
)
@ -188,7 +206,7 @@ enum LibError
// .. feature won't be supported
ERR_NOT_SUPPORTED = -1025,
// file contents are damaged
// data (e.g. in file) is obviously incorrect
ERR_CORRUPTED = -1040,
ERR_UNKNOWN_FORMAT = -1050,
@ -198,12 +216,13 @@ enum LibError
// file + vfs
ERR_FILE_NOT_FOUND = -1200,
ERR_PATH_NOT_FOUND = -1201,
ERR_DIR_END = -1202,
ERR_EOF = -1203,
ERR_PATH_LENGTH = -1204,
ERR_NOT_FILE = -1205,
ERR_FILE_ACCESS = -1206,
ERR_IO = -1207,
ERR_PATH_LENGTH = -1202,
ERR_PATH_INVALID = -1203,
ERR_DIR_END = -1210,
ERR_NOT_FILE = -1220,
ERR_FILE_ACCESS = -1230,
ERR_IO = -1231,
ERR_EOF = -1232,
ERR_TEX_FMT_INVALID = -1300,
@ -225,10 +244,14 @@ enum LibError
// 2 ways of avoiding "unreferenced formal parameter" warnings:
// .. inside the function body, e.g. void f(int x) { UNUSED(x); }
#define UNUSED(param) (void)param;
// .. wrapped around the parameter name, e.g. void f(int UNUSEDPARAM(x))
#define UNUSEDPARAM(param)
// .. inside the function body, e.g. void f(int x) { UNUSED2(x); }
#define UNUSED2(param) (void)param;
// .. wrapped around the parameter name, e.g. void f(int UNUSED(x))
#define UNUSED(param)
#if MSC_VERSION
#define UNREACHABLE __assume(0)
#endif
#define ARRAY_SIZE(name) (sizeof(name) / sizeof(name[0]))
@ -270,7 +293,7 @@ const size_t MiB = 1ul << 20;
const size_t GiB = 1ul << 30;
#ifdef _WIN32
#if OS_WIN
#define DIR_SEP '\\'
#else
#define DIR_SEP '/'
@ -322,6 +345,12 @@ extern uint log2(uint x);
// multiple must be a power of two.
extern uintptr_t round_up(uintptr_t val, uintptr_t multiple);
// these avoid a common mistake in using >> (ANSI requires shift count be
// less than the bit width of the type).
extern u32 u64_hi(u64 x);
extern u32 u64_lo(u64 x);
extern u16 fp_to_u16(double in);
// return random integer in [0, limit).

View File

@ -149,16 +149,14 @@ static void tls_retire(void* tls_)
// (called via pthread_once from tls_get)
static void tls_init()
{
int ret = pthread_key_create(&tls_key, tls_retire);
debug_assert(ret == 0);
WARN_ERR(pthread_key_create(&tls_key, tls_retire));
}
// free all TLS info. called by smr_try_shutdown.
static void tls_shutdown()
{
int ret = pthread_key_delete(tls_key);
debug_assert(ret == 0);
WARN_ERR(pthread_key_delete(tls_key));
tls_key = 0;
while(tls_list)
@ -197,8 +195,7 @@ static TLS* tls_alloc()
if(!tls)
{
tls = (TLS*)-1;
int ret = pthread_setspecific(tls_key, tls);
debug_assert(ret == 0);
WARN_ERR(pthread_setspecific(tls_key, tls));
return tls;
}
tls->active = 1;
@ -216,8 +213,7 @@ static TLS* tls_alloc()
have_tls:
atomic_add(&active_threads, 1);
int ret = pthread_setspecific(tls_key, tls);
debug_assert(ret == 0);
WARN_ERR(pthread_setspecific(tls_key, tls));
return tls;
}
@ -226,8 +222,7 @@ have_tls:
// called from each lfl_* function, so don't waste any time.
static TLS* tls_get()
{
int ret = pthread_once(&tls_once, tls_init);
debug_assert(ret == 0);
WARN_ERR(pthread_once(&tls_once, tls_init));
// already allocated or tls_alloc failed.
TLS* tls = (TLS*)pthread_getspecific(tls_key);
@ -678,7 +673,7 @@ static LFList* chain(LFHash* hash, uintptr_t key)
int lfh_init(LFHash* hash, size_t num_entries)
{
hash->tbl = 0;
hash->mask = ~0;
hash->mask = ~0u;
if(!is_pow2((long)num_entries))
{
@ -767,12 +762,10 @@ static void basic_single_threaded_test()
int sig = 10;
LFList list;
err = lfl_init(&list);
debug_assert(err == 0);
WARN_ERR(lfl_init(&list));
LFHash hash;
err = lfh_init(&hash, 8);
debug_assert(err == 0);
WARN_ERR(lfh_init(&hash, 8));
// add some entries; store "signatures" (ascending int values)
for(uint i = 0; i < ENTRIES; i++)
@ -825,6 +818,8 @@ static pthread_mutex_t mutex; // protects <keys>
static void* thread_func(void* arg)
{
debug_set_thread_name("LF_test");
const uintptr_t thread_number = (uintptr_t)arg;
atomic_add(&num_active_threads, 1);
@ -933,12 +928,9 @@ static void multithreaded_torture_test()
const double end_time = get_time() + TEST_LENGTH;
is_complete = false;
err = lfl_init(&list);
debug_assert(err == 0);
err = lfh_init(&hash, 128);
debug_assert(err == 0);
err = pthread_mutex_init(&mutex, 0);
debug_assert(err == 0);
WARN_ERR(lfl_init(&list));
WARN_ERR(lfh_init(&hash, 128));
WARN_ERR(pthread_mutex_init(&mutex, 0));
// spin off test threads (many, to force preemption)
const uint NUM_THREADS = 16;
@ -957,8 +949,7 @@ static void multithreaded_torture_test()
lfl_free(&list);
lfh_free(&hash);
err = pthread_mutex_destroy(&mutex);
debug_assert(err == 0);
WARN_ERR(pthread_mutex_destroy(&mutex));
}

View File

@ -98,14 +98,6 @@ terminology
*/
// 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.
extern bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value);
#define CAS(l,o,n) CAS_((uintptr_t*)l, (uintptr_t)o, (uintptr_t)n)
//
// lock-free singly linked list
//

View File

@ -5,7 +5,7 @@
#include "precompiled.h"
#include "config.h"
#ifdef HAVE_ASM
#if HAVE_ASM
void memcpy_nt(void* dst, void* src, int len)
{
@ -65,4 +65,4 @@ write_loop:
}
}
#endif // #ifdef HAVE_ASM
#endif // #if HAVE_ASM

View File

@ -21,7 +21,7 @@
// for easy removal in release builds, so that we don't cause any overhead.
// note that any application calls to our functions must be removed also,
// but this is preferable to stubbing them out here ("least surprise").
#ifdef CONFIG_USE_MMGR
#if CONFIG_USE_MMGR
#include <stdio.h>
#include <stdlib.h>
@ -35,7 +35,7 @@
#include "mmgr.h"
#include "lib.h"
#include "posix.h"
#include "sysdep/debug.h"
#include "debug.h"
// remove macro hooks (we need to use the actual malloc/new etc. routines)
#include "nommgr.h"
@ -59,27 +59,20 @@ static void lock_init() throw()
static void lock_shutdown() throw()
{
int ret = pthread_mutex_destroy(&mutex);
debug_assert(ret == 0);
WARN_ERR(pthread_mutex_destroy(&mutex));
lock_initialized = false;
}
static void lock() throw()
{
if(lock_initialized)
{
int ret = pthread_mutex_lock(&mutex);
debug_assert(ret == 0);
}
WARN_ERR(pthread_mutex_lock(&mutex));
}
static void unlock() throw()
{
if(lock_initialized)
{
int ret = pthread_mutex_unlock(&mutex);
debug_assert(ret == 0);
}
WARN_ERR(pthread_mutex_unlock(&mutex));
}
@ -97,7 +90,7 @@ static void unlock() throw()
// user's buffer. pattern_set assumes it's an integral number of ulongs.
// enable all checks (slow!)
#ifdef PARANOIA
#if CONFIG_PARANOIA
static uint options = MMGR_ALL;
static const size_t padding_size = 256 * sizeof(ulong);
// normal settings
@ -1135,7 +1128,7 @@ fail:
void* realloc_dbg(const void* user_p, size_t user_size, AllocType type, const char* file, int line, const char* func, uint stack_frames)
{
void* ret = 0;
uint old_size = 0;
size_t old_size = 0;
debug_assert(type == AT_REALLOC);
@ -1388,4 +1381,4 @@ void operator delete[](void* p, const char* file, int line, const char* func) th
free_dbg(p, AT_DELETE_ARRAY, file,line,func, 1);
}
#endif // #ifdef CONFIG_USE_MMGR
#endif // #if CONFIG_USE_MMGR

View File

@ -16,19 +16,98 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
/*
// !!!!!!!!!! see user guide / documentation at end of file !!!!!!!!!!
purpose and history
-------------------
our goal is to expose any memory handling bugs in the application as
early as possible. various checks are performed upon each memory API call;
if all options are on, we can spot the following:
memory leaks, double-free, allocation over/underruns,
unused memory, and use-after-free.
this code started life as Paul Nettle's memory manager (available
at http:www.fluidstudios.com), and has been completely overhauled.
in particular, it is now thread-safe and modularized;
duplicated code has been eliminated.
instructions for integrating into your project
----------------------------------------------
1) #include this from all project source files [that will allocate memory].
doing so from the precompiled header is recommended, since the
compiler will make sure it has actually been included.
2) all system headers must be #include-d before this header, so that
we don't mess with any of their local operator new/delete.
3) if project source/headers also use local operator new/delete, #include
"nommgr.h" before that spot, and re-#include "mmgr.h" afterwards.
4) if using MFC:
- set linker option /FORCE - works around conflict between our global
operator new and that of MFC. be sure to check for other errors.
- remove any #define new DEBUG_NEW from all source files.
effects
-------
many bugs are caught and announced with no further changes
required, due to integrity checks inside the allocator.
at exit, three report files are generated: a listing of leaks,
various statistics (e.g. total unused memory), and the log.
this lists (depending on settings) all allocations, enter/exit
indications for our functions, and failure notifications.
digging deeper
--------------
when tracking down hard-to-find bugs, more stringent checks can be
activated via mmgr_set_option, or by changing the initial value of
options in mmgr.cpp. however, they slow down the app considerably
and need not always be enabled. see option declarations above.
you can also change padding_size in mmgr.cpp at compile-time to provide
more safety vs. overruns, at the cost of wasting lots of memory per
allocation (which must also be cleared). this is only done in
CONFIG_PARANOIA builds, because overruns seldom 'skip' padding.
finally, you can induce memory allocations to fail a certain percentage
of the time - this tests your application's error handling.
adjust the RANDOM_FAILURE #define in mmgr.cpp.
fixing your bugs
----------------
if this code crashes or fails an debug_assert, it is most likely due to a bug
in your application. consult the current Alloc for information;
search the log for its address to determine what operation failed,
and what piece of code owns the allocation.
if the cause isn't visible (i.e. the error is reported after the fact),
you can try activating the more stringent checks to catch the problem
earlier. you may also call the validation routines at checkpoints
in your code to narrow the cause down. if all else fails, break on
the allocation number to see what's happening.
good luck!
*/
#ifndef MMGR_H__
#define MMGR_H__
// provide for completely disabling the memory manager
// (e.g. when using other debug packages)
//
// note: checking here messes up include guard detection, but we need to
// cover both the guarded part (constants+externs) and the macros.
#ifdef CONFIG_USE_MMGR
#ifndef MMGR_H__
#define MMGR_H__
// note: this must go around the include-guarded part (constants+externs)
// as well as the macros. we don't want to mess up compiler include-guard
// optimizations, so duplicate this #if.
#if CONFIG_USE_MMGR
#include "lib/types.h"
@ -125,6 +204,7 @@ extern void operator delete[](void* p, const char* file, int line) throw();
extern void operator delete (void* p, const char* file, int line, const char* func) throw();
extern void operator delete[](void* p, const char* file, int line, const char* func) throw();
#endif // #if CONFIG_USE_MMGR
#endif // #ifdef MMGR_H__
@ -135,9 +215,14 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
#include "nommgr.h"
// MMGR version:
// (to simplify code that may either use mmgr or the VC debug heap,
// we support enabling/disabling both in this header)
#if CONFIG_USE_MMGR
// get rid of __FUNCTION__ unless we know the compiler supports it.
// (note: don't define if built-in - compiler will raise a warning)
#if !defined(_MSC_VER) && !defined(__GNUC__)
#if !MSC_VERSION && !GCC_VERSION
#define __FUNCTION__ 0
#endif
@ -154,83 +239,12 @@ extern void operator delete[](void* p, const char* file, int line, const char* f
#define wcsdup(p) mmgr_wcsdup_dbg(p, __FILE__,__LINE__,__FUNCTION__)
#define getcwd(p,size) mmgr_getcwd_dbg(p, size, __FILE__,__LINE__,__FUNCTION__)
#endif // #ifdef CONFIG_USE_MMGR
#elif HAVE_VC_DEBUG_ALLOC
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
// crtdbg.h didn't define "new" (probably for compatibility); do so now.
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
// purpose and history
// -------------------
// our goal is to expose any memory handling bugs in the application as
// early as possible. various checks are performed upon each memory API call;
// if all options are on, we can spot the following:
// memory leaks, double-free, allocation over/underruns,
// unused memory, and use-after-free.
//
// this code started life as Paul Nettle's memory manager (available
// at http://www.fluidstudios.com), and has been completely overhauled.
// in particular, it is now thread-safe and modularized;
// duplicated code has been eliminated.
//
//
// instructions for integrating into your project
// ----------------------------------------------
//
// 1) #include this from all project source files [that will allocate memory].
// doing so from the precompiled header is recommended, since the
// compiler will make sure it has actually been included.
// 2) all system headers must be #include-d before this header, so that
// we don't mess with any of their local operator new/delete.
// 3) if project source/headers also use local operator new/delete, #include
// "nommgr.h" before that spot, and re-#include "mmgr.h" afterwards.
//
// 4) if using MFC:
// - set linker option /FORCE - works around conflict between our global
// operator new and that of MFC. be sure to check for other errors.
// - remove any #define new DEBUG_NEW from all source files.
//
//
// effects
// -------
//
// many bugs are caught and announced with no further changes
// required, due to integrity checks inside the allocator.
//
// at exit, three report files are generated: a listing of leaks,
// various statistics (e.g. total unused memory), and the log.
// this lists (depending on settings) all allocations, enter/exit
// indications for our functions, and failure notifications.
//
//
// digging deeper
// --------------
//
// when tracking down hard-to-find bugs, more stringent checks can be
// activated via mmgr_set_option, or by changing the initial value of
// options in mmgr.cpp. however, they slow down the app considerably
// and need not always be enabled. see option declarations above.
//
// you can also change padding_size in mmgr.cpp at compile-time to provide
// more safety vs. overruns, at the cost of wasting lots of memory per
// allocation (which must also be cleared). this is only done in
// PARANOIA builds, because overruns seldom 'skip' padding.
//
// finally, you can induce memory allocations to fail a certain percentage
// of the time - this tests your application's error handling.
// adjust the RANDOM_FAILURE #define in mmgr.cpp.
//
//
// fixing your bugs
// ----------------
//
// if this code crashes or fails an debug_assert, it is most likely due to a bug
// in your application. consult the current Alloc for information;
// search the log for its address to determine what operation failed,
// and what piece of code owns the allocation.
//
// if the cause isn't visible (i.e. the error is reported after the fact),
// you can try activating the more stringent checks to catch the problem
// earlier. you may also call the validation routines at checkpoints
// in your code to narrow the cause down. if all else fails, break on
// the allocation number to see what's happening.
//
// good luck!
#endif // #if CONFIG_USE_MMGR

View File

@ -1,4 +1,6 @@
// remove all memory allocation "hooks"
// remove all of mmgr.h's memory allocation "hooks" -
// but only if we actually defined them!
#if CONFIG_USE_MMGR || HAVE_VC_DEBUG_ALLOC
#undef new
#undef delete
@ -10,3 +12,5 @@
#undef strdup
#undef wcsdup
#undef getcwd
#endif

View File

@ -48,7 +48,7 @@ need only be renamed (e.g. _open, _stat).
*/
#ifdef _WIN32
#if OS_WIN
#include "sysdep/win/wposix.h"
#include "sysdep/win/win.h"
@ -81,4 +81,4 @@ need only be renamed (e.g. _open, _stat).
#include <netinet/tcp.h>
#include <arpa/inet.h>
#endif // #ifdef _WIN32
#endif // #if OS_WIN

View File

@ -7,7 +7,7 @@
#include <sys/types.h>
#include <stddef.h>
#ifdef _WIN32
#if OS_WIN
# include "sysdep/win/wposix_types.h"
#else
// unix/linux/glibc/gcc says that this macro has to be defined when including
@ -16,4 +16,4 @@
# define __STDC_LIMIT_MACROS
# endif
# include <stdint.h>
#endif // #ifdef _WIN32
#endif // #if OS_WIN

View File

@ -8,17 +8,30 @@
//
// this policy yields the best compile performance with or without PCH.
#ifdef _MSC_VER
// must come before warning disables.
#include "lib/config.h"
// disable some common and annoying warnings
// (done as soon as possible so that headers below are covered)
#if MSC_VERSION
// .. temporarily disabled W4 (unimportant but ought to be fixed)
# pragma warning(disable:4201) // nameless struct (Matrix3D)
# pragma warning(disable:4244) // conversion from uintN to uint8
// .. permanently disabled W4
# pragma warning(disable:4127) // conditional expression is constant; rationale: see STMT in lib.h.
# pragma warning(disable:4996) // function is deprecated
# pragma warning(disable:4786) // identifier truncated to 255 chars
# if _MSC_VER >= 1400 // VS2005 code analysis warnings - disable the very frequent ones:
// .. VS2005 code analysis (very frequent ones)
# if MSC_VERSION >= 1400
# pragma warning(disable:6011) // dereferencing NULL pointer
# pragma warning(disable:6246) // local declaration hides declaration of the same name in outer scope
# endif
#endif
// make these available everywhere for convenience:
#include "lib/config.h"
//
// headers made available everywhere for convenience
//
#include "lib/types.h"
#include "lib/string_s.h" // CRT secure string
#include "lib/debug.h"
@ -33,15 +46,13 @@
// come before the memory tracker headers to avoid conflicts with their
// macros. therefore, they are always included, even if !HAVE_PCH.
#ifdef _WIN32
#include <crtdbg.h>
#if OS_WIN
# include <malloc.h>
#endif
#include <malloc.h>
#include <new>
#include <memory>
#include <cstring> // uses placement new
#include <string>
#include <valarray> // free() member function
//
@ -58,7 +69,7 @@
// not otherwise need some of these headers. therefore, do nothing and rely
// on all source files (additionally) including everything they need.
#ifdef HAVE_PCH
#if HAVE_PCH
// all new-form C library headers
#include <cassert>
@ -119,7 +130,7 @@
#include <valarray>
// STL extensions
#ifdef __GNUC__
#if GCC_VERSION
# include <ext/hash_map>
# include <ext/hash_set>
#else
@ -127,19 +138,17 @@
# include <hash_set>
#endif
// CStr is included very frequently, so a reasonable amount of time is saved
// by including it here. (~10% in a full rebuild, as of r2365)
// some other external libraries that are used in several places:
// .. CStr is included very frequently, so a reasonable amount of time is
// saved by including it here. (~10% in a full rebuild, as of r2365)
#include "ps/CStr.h"
// Some other external libraries that are used in several places:
#include "scripting/SpiderMonkey.h"
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
// (further headers to be precompiled go here)
#endif // #ifdef HAVE_PCH
#endif // #if HAVE_PCH
//
@ -150,17 +159,7 @@
// are hooked. placing in the precompiled header is more convenient than
// manually #including from every file, but requires that all system
// headers containing "new", "malloc" etc. come before this (see above).
// use custom memory tracker (lib/mmgr.cpp)
#if defined(CONFIG_USE_MMGR)
//
// note: mmgr.h activates mmgr or the VC debug heap or nothing depending
// on CONFIG_USE_MMGR and HAVE_VC_DEBUG_ALLOC settings.
# include "mmgr.h"
// use VC debug heap (superceded by mmgr; it remains for completeness)
#elif defined(HAVE_VC_DEBUG_ALLOC)
// can't define _CRTDBG_MAP_ALLOC because crtdbg.h has a broken 'new',
// so manually redefine the appropriate functions.
# define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
# define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
# define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__)
# define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__)
# define free(p) _free_dbg(p, _NORMAL_BLOCK)
#endif

View File

@ -5,13 +5,14 @@
#define USE_WINDOWS_CURSOR
#ifdef _WIN32
#if OS_WIN
#include "lib/sysdep/win/win_internal.h"
#endif
#include "res.h"
#include "ogl_tex.h"
#include "lib/ogl.h"
#include "sysdep/sysdep.h"
struct ogl_cursor {
Handle tex;
@ -37,7 +38,7 @@ struct ogl_cursor {
extern int g_mouse_x, g_mouse_y;
#ifdef _WIN32
#if OS_WIN
// On Windows, allow runtime choice between Windows cursors and OpenGL
// cursors (Windows = more responsive, OpenGL = more consistent with what
// the game sees)
@ -49,18 +50,18 @@ struct Cursor
};
char type; // 0 for OpenGL cursor, 1 for Windows cursor
};
#else // #ifdef _WIN32
#else // #if OS_WIN
struct Cursor
{
ogl_cursor* cursor; // font texture
};
#endif // #ifdef _WIN32 / #else
#endif // #if OS_WIN / #else
H_TYPE_DEFINE(Cursor);
static void Cursor_init(Cursor* c, va_list)
{
#ifdef _WIN32
#if OS_WIN
# ifdef USE_WINDOWS_CURSOR
c->type = 1;
# else
@ -74,14 +75,14 @@ static void Cursor_init(Cursor* c, va_list)
static void Cursor_dtor(Cursor* c)
{
#ifdef _WIN32
#if OS_WIN
if (c->type == 1)
{
if (c->wincursor)
DestroyIcon(c->wincursor);
}
else
#endif // _WIN32
#endif
{
if (c->cursor)
{
@ -92,100 +93,10 @@ static void Cursor_dtor(Cursor* c)
}
}
#ifdef _WIN32
static void* ptr_from_HICON(HICON hIcon)
{
return (void*)(uintptr_t)hIcon;
}
static HICON HICON_from_ptr(void* p)
{
return (HICON)(uintptr_t)p;
}
static int cursor_load(Handle ht, int hotspotx, int hotspoty, void** sysdep_cursor)
{
int ret = -1;
*sysdep_cursor = 0;
void* bgra_mem = 0;
{
// get format
int w, h, fmt, bpp;
const u8* imgdata;
CHECK_ERR(tex_info(ht, &w, &h, &fmt, &bpp, (void**)&imgdata));
if(bpp != 32 || (fmt != GL_BGRA && fmt != GL_RGBA))
{
debug_warn("Cursor texture not 32-bit RGBA/BGRA");
ret = ERR_TEX_FMT_INVALID;
goto fail;
}
// convert to BGRA if not already in that format (required by BMP)
if(fmt != GL_BGRA)
{
// don't convert in-place so we don't spoil someone else's
// use of the texture (however unlikely that may be).
bgra_mem = malloc(w*h*4);
if(!bgra_mem)
{
ret = ERR_NO_MEM;
goto fail;
}
const u8* src = imgdata;
u8* dst = (u8*)bgra_mem;
for(int i = 0; i < w*h; i++)
{
const u8 r = src[0], g = src[1], b = src[2], a = src[3];
dst[0] = b; dst[1] = g; dst[2] = r; dst[3] = a;
dst += 4;
src += 4;
}
imgdata = (const u8*)bgra_mem;
}
HBITMAP hbmColor = CreateBitmap(w, h, 1, 32, imgdata);
// CreateIconIndirect doesn't access it; we just need to pass
// an empty bitmap.
HBITMAP hbmMask = CreateBitmap(w, h, 1, 1, 0);
ICONINFO ii;
ii.fIcon = FALSE; // cursor
ii.xHotspot = hotspotx;
ii.yHotspot = hotspoty;
ii.hbmMask = hbmMask;
ii.hbmColor = hbmColor;
HICON hIcon = CreateIconIndirect(&ii);
// CreateIconIndirect makes copies, so we no longer need these.
DeleteObject(hbmMask);
DeleteObject(hbmColor);
if(!hIcon) // not INVALID_HANDLE_VALUE
{
debug_warn("cursor CreateIconIndirect failed");
goto fail;
}
*sysdep_cursor = ptr_from_HICON(hIcon);
ret = 0;
}
fail:
free(bgra_mem);
CHECK_ERR(ret);
return 0;
}
#endif
static int Cursor_reload(Cursor* c, const char* name, Handle)
{
char filename[VFS_MAX_PATH];
int ret;
// Load the .txt file containing the pixel offset of
// the cursor's hotspot (the bit of it that's
@ -209,18 +120,29 @@ static int Cursor_reload(Cursor* c, const char* name, Handle)
Handle ht = tex_load(filename);
CHECK_ERR(ht);
#ifdef _WIN32
#if OS_WIN
if (c->type == 1)
{
int err = cursor_load(ht, hotspotx, hotspoty, (void**)&c->wincursor);
if(err < 0)
int w, h, gl_fmt, bpp;
void* img;
if(tex_info(ht, &w, &h, &gl_fmt, &bpp, &img) < 0 ||
(bpp != 32 || gl_fmt != GL_RGBA))
{
debug_warn("Cursor_reload: invalid texture format");
ret = ERR_TEX_FMT_INVALID;
goto fail;
}
ret = cursor_create(w, h, img, hotspotx, hotspoty, (void**)&c->wincursor);
if(ret < 0)
{
fail:
tex_free(ht);
return err;
return ret;
}
}
else
#endif // _WIN32
#endif
{
int err = tex_upload(ht, GL_NEAREST);
CHECK_ERR(err);
@ -254,7 +176,7 @@ void cursor_draw(const char* name)
// Use 'null' to disable the cursor
if (!name)
{
#ifdef _WIN32
#if OS_WIN
SetCursor(LoadCursor(NULL, IDC_ARROW));
#endif
return;
@ -268,13 +190,13 @@ void cursor_draw(const char* name)
if (!c)
return;
#ifdef _WIN32
#if OS_WIN
if (c->type == 1)
{
SetCursor(c->wincursor);
}
else
#endif // _WIN32
#endif
{
c->cursor->draw(g_mouse_x, g_yres - g_mouse_y);
}

View File

@ -178,7 +178,7 @@ static i32 last_in_use = -1; // don't search unused entries
static HDATA* h_data_from_idx(const i32 idx)
{
// makes things *crawl*!
#ifdef PARANOIA
#if CONFIG_PARANOIA
debug_heap_check();
#endif
@ -283,7 +283,7 @@ static int alloc_idx(i32& idx, HDATA*& hd)
// add another
if(last_in_use >= hdata_cap)
{
debug_assert(!"alloc_idx: too many open handles (increase IDX_BITS)");
debug_warn("alloc_idx: too many open handles (increase IDX_BITS)");
return ERR_LIMIT;
}
idx = last_in_use+1; // just incrementing idx would start it at 1
@ -418,11 +418,22 @@ int h_free(Handle& h, H_Type type)
i32 idx = h_idx(h);
HDATA* hd = h_data_tag_type(h, type);
// wipe out the handle, to prevent reuse.
// wipe out the handle to prevent reuse but keep a copy for below.
const Handle h_copy = h;
h = 0;
// h was invalid
if(!hd)
return ERR_INVALID_HANDLE;
{
// 0-initialized or an error code; don't complain because this
// happens often and is harmless.
if(h_copy <= 0)
return 0;
// this was a valid handle but was probably freed in the meantime.
// complain because this probably indicates a bug somewhere.
CHECK_ERR(ERR_INVALID_HANDLE);
}
return h_free_idx(idx, hd);
}
@ -606,18 +617,21 @@ skip_alloc:
H_VTbl* vtbl = type;
int err;
// init
va_list args;
va_start(args, flags);
if(vtbl->init)
{
vtbl->init(hd->user, args);
}
va_end(args);
// reload
if(vtbl->reload)
{
// catch exception to simplify reload funcs - let them use new()
int err;
try
{
err = vtbl->reload(hd->user, fn, h);
@ -626,19 +640,20 @@ skip_alloc:
{
err = ERR_NO_MEM;
}
// reload failed; free the handle
if(err < 0)
{
// don't cache it - it's not valid
hd->keep_open = 0;
h_free(h, type);
return (Handle)err;
}
goto fail;
}
return h;
fail:
// reload failed; free the handle
hd->keep_open = 0; // disallow caching (since contents are invalid)
(void)h_free(h, type); // (h_free already does WARN_ERR)
// note: since some uses will always fail (e.g. loading sounds if
// g_Quickstart), do not complain here.
return (Handle)err;
}

View File

@ -45,7 +45,7 @@ typedef MemSrcMgr* SrcPtr;
* before any data is actually read.
*/
METHODDEF(void) init_source(j_decompress_ptr cinfo)
METHODDEF(void) init_source(j_decompress_ptr UNUSED(cinfo))
{
}
@ -134,7 +134,7 @@ METHODDEF(void) skip_input_data(j_decompress_ptr cinfo, long num_bytes)
* for error exit.
*/
METHODDEF(void) term_source(j_decompress_ptr cinfo)
METHODDEF(void) term_source(j_decompress_ptr UNUSED(cinfo))
{
/*
* no-op (we don't own the buffer and shouldn't,
@ -318,7 +318,7 @@ METHODDEF(void) term_destination(j_compress_ptr cinfo)
// make sure any data left in the buffer is written out
const size_t bytes_in_buf = OUTPUT_BUF_SIZE - dst->pub.free_in_buffer;
if(vfs_io(dst->hf, bytes_in_buf, (void**)&dst->buf) != bytes_in_buf)
if(vfs_io(dst->hf, bytes_in_buf, (void**)&dst->buf) != (ssize_t)bytes_in_buf)
ERREXIT(cinfo, JERR_FILE_WRITE);
// flush file, if necessary.

View File

@ -149,10 +149,8 @@ static void Mem_dtor(Mem* m)
// can't alloc here, because h_alloc needs the key when called
// (key == pointer we allocate)
static int Mem_reload(Mem* m, const char* fn, Handle hm)
static int Mem_reload(Mem* m, const char* UNUSED(fn), Handle hm)
{
UNUSED(fn);
set_alloc(m->raw_p, hm);
return 0;
}
@ -168,11 +166,8 @@ static int Mem_reload(Mem* m, const char* fn, Handle hm)
//////////////////////////////////////////////////////////////////////////////
static void heap_free(void* raw_p, size_t raw_size, uintptr_t ctx)
static void heap_free(void* raw_p, size_t UNUSED(raw_size), uintptr_t UNUSED(ctx))
{
UNUSED(raw_size);
UNUSED(ctx);
free(raw_p);
}
@ -187,16 +182,14 @@ static void* heap_alloc(size_t raw_size, uintptr_t& ctx)
//////////////////////////////////////////////////////////////////////////////
/*
static u8* pool;
static size_t pool_pos;
static const size_t POOL_CAP = 8*MiB; // TODO: user editable
static void pool_free(void* raw_p, size_t raw_size, uintptr_t ctx)
static void pool_free(void* UNUSED(raw_p), size_t raw_size, uintptr_t ctx)
{
UNUSED(raw_p);
size_t ofs = (size_t)ctx;
// at or beyond current next-alloc position: invalid
@ -213,7 +206,7 @@ static void pool_free(void* raw_p, size_t raw_size, uintptr_t ctx)
static void* pool_alloc(const size_t raw_size, uintptr_t& ctx)
{
ctx = ~0; // make sure it's invalid if we fail
ctx = ~0U; // make sure it's invalid if we fail
if(!pool)
{
@ -233,7 +226,7 @@ static void* pool_alloc(const size_t raw_size, uintptr_t& ctx)
void* raw_p = (u8*)pool + ctx;
return raw_p;
}
*/
//////////////////////////////////////////////////////////////////////////////

View File

@ -12,7 +12,7 @@
#include "ogghack.h"
#ifdef _MSC_VER
#if MSC_VERSION
# ifdef NDEBUG
# pragma comment(lib, "vorbisfile.lib")
# else
@ -78,12 +78,12 @@ size_t read_func(void* ptr, size_t elements, size_t el_size, void* datasource)
}
int seek_func(void* datasource, ogg_int64_t offset, int whence)
int seek_func(void* UNUSED(datasource), ogg_int64_t UNUSED(offset), int UNUSED(whence))
{
return -1; // libvorbisfile: indicate "not implemented"
}
int close_func(void* datasource)
int close_func(void* UNUSED(datasource))
{
return 0;
}
@ -128,7 +128,7 @@ void ogg_open(void* _o, ALenum& fmt, ALsizei& freq)
void* datasource = &o->incoming_bufs;
if(ov_open_callbacks(datasource, &o->oggStream, NULL, 0, cbs) < 0)
{
debug_assert(!"ov_open failed");
debug_warn("ov_open failed");
}
o->vorbisInfo = ov_info(&o->oggStream, -1);
@ -166,7 +166,7 @@ size_t ogg_read(void* _o, void* buf, size_t max_size)
if(result > 0)
bytes_written += result;
else if(result < 0)
debug_assert(!"ogg read error");
debug_warn("ogg read error");
// clean break - end of data
else
break;

View File

@ -28,9 +28,24 @@ static bool fmt_is_s3tc(GLenum fmt)
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return true;
default:
return false;
}
return false;
}
static bool filter_is_known(GLint filter)
{
switch(filter)
{
case GL_NEAREST:
case GL_LINEAR:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
return true;
}
return false;
}
@ -61,7 +76,7 @@ static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
{
const bool alpha = (flags & TEX_ALPHA) != 0;
const bool bgr = (flags & TEX_BGR ) != 0;
const bool gray = (flags & TEX_GRAY ) != 0;
const bool grey = (flags & TEX_GREY ) != 0;
const int dxt = flags & TEX_DXT;
// in case we fail
@ -101,6 +116,7 @@ static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
switch(bpp)
{
case 8:
debug_assert(grey);
*fmt = GL_LUMINANCE;
*int_fmt = high_quality? GL_LUMINANCE8 : GL_LUMINANCE4;
return 0;
@ -125,8 +141,7 @@ static int get_gl_fmt(int bpp, int flags, GLenum* fmt, GLenum* int_fmt)
return ERR_TEX_FMT_INVALID;
}
// unreachable
debug_assert(0);
UNREACHABLE;
}
@ -187,10 +202,8 @@ struct Tex
H_TYPE_DEFINE(Tex);
static void Tex_init(Tex* t, va_list args)
static void Tex_init(Tex* t, va_list UNUSED(args))
{
UNUSED(args);
// set to default (once)
t->filter = tex_filter;
}
@ -321,8 +334,10 @@ static int tex_validate(const uint line, const Tex* t)
// upload parameters, set by tex_upload(Handle), or 0
GLint filter = t->filter;
GLenum int_fmt = t->int_fmt;
// TODO: check if valid
if(filter != 0 && !filter_is_known(filter))
msg = "invalid filter";
// as with the texel format above, there is not anything we can do
// to verify t->int_fmt is correct (even 0 is valid).
if(msg)
{
@ -367,7 +382,7 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
GLenum fmt = t->fmt;
GLint filter = t->filter;
GLenum int_fmt = t->int_fmt;
void* tex_data = (char*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
void* tex_data = (u8*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
// does filter call for uploading mipmaps?
const bool need_mipmaps = filter_uses_mipmaps(filter);
@ -539,7 +554,7 @@ int tex_info(Handle ht, int* w, int* h, int* fmt, int* bpp, void** p)
if(bpp)
*bpp = t->ti.bpp;
if(p)
*p = mem_get_ptr(t->ti.hm);
*p = (u8*)mem_get_ptr(t->ti.hm) + t->ti.ofs;
return 0;
}

View File

@ -36,12 +36,12 @@
#endif
// for AL_FORMAT_VORBIS_EXT decl on Linux
#ifdef OS_LINUX
#if OS_LINUX
# include <AL/alexttypes.h>
#endif
// for DLL-load hack in alc_init
#ifdef _WIN32
#if OS_WIN
# include "sysdep/win/win_internal.h"
#endif
@ -49,7 +49,7 @@
#define OGG_HACK
#include "ogghack.h"
#ifdef _MSC_VER
#if MSC_VERSION
# pragma comment(lib, "openal32.lib")
# pragma comment(lib, "alut.lib") // alutLoadWAVMemory
#endif
@ -201,7 +201,7 @@ static int alc_init()
// thus speeding up startup by 100..400 ms. everything works ATM;
// hopefully, OpenAL doesn't rely on them actually being unloaded.
#ifdef _WIN32
#if OS_WIN
HMODULE dlls[3];
dlls[0] = LoadLibrary("wrap_oal.dll");
dlls[1] = LoadLibrary("setupapi.dll");
@ -213,7 +213,7 @@ static int alc_init()
// (it's not caused by the DLL load hack above). everything works and
// we can continue normally; we just need to catch it to prevent the
// unhandled exception filter from reporting it.
#ifdef _WIN32
#if OS_WIN
__try
{
alc_dev = alcOpenDevice((ALubyte*)alc_dev_name);
@ -245,7 +245,7 @@ static int alc_init()
}
// release DLL references, so BoundsChecker doesn't complain at exit.
#ifdef _WIN32
#if OS_WIN
for(int i = 0; i < ARRAY_SIZE(dlls); i++)
if(dlls[i] != INVALID_HANDLE_VALUE)
FreeLibrary(dlls[i]);

View File

@ -51,7 +51,7 @@ extern "C" {
EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo, void* p, size_t size);
EXTERN(void) jpeg_vfs_dst(j_compress_ptr cinfo, Handle hf);
}
# ifdef _MSC_VER
# if MSC_VERSION
# ifdef NDEBUG
# pragma comment(lib, "jpeg-6b.lib")
# else
@ -62,7 +62,7 @@ EXTERN(void) jpeg_vfs_dst(j_compress_ptr cinfo, Handle hf);
#ifndef NO_PNG
# ifdef _WIN32
# if OS_WIN
// to avoid conflicts, windows.h must not be included.
// libpng pulls it in for WINAPI; we prevent the include
// and define that here.
@ -71,19 +71,26 @@ EXTERN(void) jpeg_vfs_dst(j_compress_ptr cinfo, Handle hf);
# define WINAPIV __cdecl
// different header name, too.
# include <libpng13/png.h>
# ifdef _MSC_VER
# if MSC_VERSION
# ifdef NDEBUG
# pragma comment(lib, "libpng13.lib")
# else
# pragma comment(lib, "libpng13d.lib")
# endif // NDEBUG
# endif // _MSC_VER
# else // _WIN32
# endif // MSC_VERSION
# else // i.e. !OS_WIN
# include <png.h>
# endif // _WIN32
# endif // OS_WIN
#endif // NO_PNG
// squelch "dtor / setjmp interaction" warnings.
// all attempts to resolve the underlying problem failed; apparently
// the warning is generated if setjmp is used at all in C++ mode.
// (png_decode has no code that would trigger ctors/dtors, nor are any
// called in its prolog/epilog code).
#if MSC_VERSION
# pragma warning(disable: 4611)
#endif
#define CODEC(name) { name##_fmt, name##_ext, name##_decode, name##_encode, #name}
@ -298,23 +305,23 @@ static int write_img(const char* fn, const void* hdr, size_t hdr_size,
static int fmt_8_or_24_or_32(int bpp, int flags)
{
const bool alpha = (flags & TEX_ALPHA) != 0;
const bool gray = (flags & TEX_GRAY ) != 0;
const bool grey = (flags & TEX_GREY ) != 0;
const bool dxt = (flags & TEX_DXT ) != 0;
if(dxt)
return ERR_TEX_FMT_INVALID;
// if gray,
if(gray)
// if grey..
if(grey)
{
// and 8bpp / no alpha, it's ok.
if(bpp == 8 && !alpha)
return 0;
// .. otherwise, it's invalid
// otherwise, it's invalid.
return ERR_TEX_FMT_INVALID;
}
// it's not gray.
// it's not grey.
if(bpp == 24 && !alpha)
return 0;
@ -386,7 +393,7 @@ DDSURFACEDESC2;
static inline bool dds_fmt(const u8* ptr, size_t size)
{
UNUSED(size); // size >= 4, we only need 4 bytes
UNUSED2(size); // size >= 4, we only need 4 bytes
return *(u32*)ptr == FOURCC('D','D','S',' ');
}
@ -463,8 +470,8 @@ fail:
if(mipmaps)
flags |= TEX_MIPMAPS;
// if(file_size != hdr_size + img_size)
// err = "file size mismatch";
if(file_size < hdr_size + img_size)
err = "file size too small";
if(w % 4 || h % 4)
err = "image dimensions not padded to S3TC block size";
if(!w || !h)
@ -490,7 +497,7 @@ fail:
}
static int dds_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
static int dds_encode(TexInfo* UNUSED(t), const char* UNUSED(fn), u8* UNUSED(img), size_t UNUSED(img_size))
{
return ERR_NOT_IMPLEMENTED;
}
@ -512,7 +519,7 @@ static int dds_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
enum TgaImgType
{
TGA_TRUE_COLOR = 2, // uncompressed 24 or 32 bit direct RGB
TGA_GRAY = 3 // uncompressed 8 bit direct grayscale
TGA_GREY = 3 // uncompressed 8 bit direct greyscale
};
enum TgaImgDesc
@ -550,7 +557,7 @@ TgaHeader;
// we can only check if the first 4 bytes are valid
static inline bool tga_fmt(const u8* ptr, size_t size)
{
UNUSED(size);
UNUSED2(size); // size >= 4, we only need 4 bytes
TgaHeader* hdr = (TgaHeader*)ptr;
@ -558,8 +565,8 @@ static inline bool tga_fmt(const u8* ptr, size_t size)
if(hdr->color_map_type != 0)
return false;
// wrong color type (not uncompressed grayscale or RGB)
if(hdr->img_type != TGA_TRUE_COLOR && hdr->img_type != TGA_GRAY)
// wrong color type (not uncompressed greyscale or RGB)
if(hdr->img_type != TGA_TRUE_COLOR && hdr->img_type != TGA_GREY)
return false;
return true;
@ -604,6 +611,8 @@ fail:
int flags = 0;
if(alpha_bits != 0)
flags |= TEX_ALPHA;
if(bpp == 8)
flags |= TEX_GREY;
if(type == TGA_TRUE_COLOR)
flags |= TEX_BGR;
@ -636,8 +645,10 @@ static int tga_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
{
CHECK_ERR(fmt_8_or_24_or_32(t->bpp, t->flags));
TgaImgDesc img_desc = (t->flags & TEX_TOP_DOWN)? TGA_TOP_DOWN : TGA_BOTTOM_UP;
TgaImgType img_type = (t->flags & TEX_GRAY)? TGA_GRAY : TGA_TRUE_COLOR;
u8 img_desc = (t->flags & TEX_TOP_DOWN)? TGA_TOP_DOWN : TGA_BOTTOM_UP;
if(t->bpp == 32)
img_desc |= 8; // size of alpha channel
TgaImgType img_type = (t->flags & TEX_GREY)? TGA_GREY : TGA_TRUE_COLOR;
// transform
int transforms = t->flags;
@ -655,7 +666,7 @@ static int tga_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
t->w,
t->h,
t->bpp,
(u8)img_desc
img_desc
};
return write_img(fn, &hdr, sizeof(hdr), img, img_size);
}
@ -712,7 +723,7 @@ struct BmpHeader
static inline bool bmp_fmt(const u8* p, size_t size)
{
UNUSED(size); // size >= 4, we only need 2 bytes
UNUSED2(size); // size >= 4, we only need 2 bytes
// check header signature (bfType == "BM"?).
// we compare single bytes to be endian-safe.
@ -830,11 +841,9 @@ static int bmp_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
// assume bottom-up
static inline bool raw_fmt(const u8* p, size_t size)
// always returns true because this is the last registered codec.
static inline bool raw_fmt(const u8* UNUSED(p), size_t UNUSED(size))
{
UNUSED(p);
UNUSED(size)
return true;
}
@ -849,32 +858,33 @@ static int raw_decode(TexInfo* t, const char* fn, u8* file, size_t file_size)
{
// TODO: allow 8 bit format. problem: how to differentiate from 32? filename?
for(uint i = 2; i <= 4; i++)
// find a color depth that matches file_size
uint i, dim;
for(i = 2; i <= 4; i++)
{
const u32 dim = (u32)sqrtf((float)file_size/i);
if(dim*dim*i != file_size)
continue;
const int orientation = TEX_BOTTOM_UP;
u8* const img = file;
// formats are: GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA
int flags = (i == 3)? 0 : TEX_ALPHA;
t->ofs = 0;
t->w = dim;
t->h = dim;
t->bpp = i*8;
t->flags = flags;
const int transforms = orientation ^ global_orientation;
transform(t, img, transforms);
return 0;
dim = (uint)sqrtf((float)file_size/i);
if(dim*dim*i == file_size)
goto have_bpp;
}
debug_printf("raw_decode: %s: %s\n", fn, "no matching format found");
return -1;
return ERR_TEX_FMT_INVALID;
have_bpp:
const int orientation = TEX_BOTTOM_UP;
u8* const img = file;
// formats are: GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA
int flags = (i == 3)? 0 : TEX_ALPHA;
t->ofs = 0;
t->w = dim;
t->h = dim;
t->bpp = i*8;
t->flags = flags;
const int transforms = orientation ^ global_orientation;
return transform(t, img, transforms);
}
@ -904,7 +914,7 @@ static int raw_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
static inline bool png_fmt(const u8* ptr, size_t size)
{
UNUSED(size); // size >= 4, we only need 4 bytes
UNUSED2(size); // size >= 4, we only need 4 bytes
// don't use png_sig_cmp, so we don't pull in libpng for
// this check alone (it might not be used later).
@ -946,6 +956,67 @@ static void png_read(png_struct* png_ptr, u8* data, png_size_t length)
}
// split out of png_decode to simplify resource cleanup and avoid
// "dtor / setjmp interaction" warning.
static png_decode_impl(TexInfo* t, u8* file, size_t file_size,
png_structp png_ptr, png_infop info_ptr,
u8*& img, RowArray& rows, const char*& msg)
{
PngMemFile f = { file, file_size };
png_set_read_fn(png_ptr, &f, png_read);
// read header and determine format
png_read_info(png_ptr, info_ptr);
png_uint_32 w, h;
int bit_depth, color_type;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);
const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
const u32 bpp = (u32)(pitch / w * 8);
int flags = 0;
if(bpp == 32)
flags |= TEX_ALPHA;
// make sure format is acceptable
if(bit_depth != 8)
msg = "channel precision != 8 bits";
if(color_type & PNG_COLOR_MASK_PALETTE)
msg = "color type is invalid (must be direct color)";
if(msg)
return -1;
const size_t img_size = pitch * h;
Handle img_hm;
// cannot free old t->hm until after png_read_end,
// but need to set to this handle afterwards => need tmp var.
img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm);
if(!img)
return ERR_NO_MEM;
const int transforms = TEX_TOP_DOWN ^ global_orientation;
CHECK_ERR(alloc_rows(img, h, pitch, transforms, rows));
png_read_image(png_ptr, (png_bytepp)rows);
png_read_end(png_ptr, info_ptr);
// success; make sure all data was consumed.
debug_assert(f.p == file && f.size == file_size && f.pos == f.size);
// store image info
// .. transparently switch handles - free the old (compressed)
// buffer and replace it with the decoded-image memory handle.
mem_free_h(t->hm);
t->hm = img_hm;
t->ofs = 0; // libpng returns decoded image data; no header
t->w = w;
t->h = h;
t->bpp = bpp;
t->flags = flags;
return 0;
}
// limitation: palette images aren't supported
static int png_decode(TexInfo* t, const char* fn, u8* file, size_t file_size)
{
@ -957,10 +1028,9 @@ static int png_decode(TexInfo* t, const char* fn, u8* file, size_t file_size)
png_infop info_ptr = 0;
RowArray rows = 0;
// freed when fail is reached:
// freed if fail is reached:
u8* img = 0; // decompressed image memory
// allocate PNG structures; use default stderr and longjmp error handlers
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if(!png_ptr)
@ -972,72 +1042,19 @@ static int png_decode(TexInfo* t, const char* fn, u8* file, size_t file_size)
// setup error handling
if(setjmp(png_jmpbuf(png_ptr)))
{
// reached if PNG triggered a longjmp
fail:
mem_free(img);
debug_printf("png_decode: %s: %s\n", fn, msg? msg : "unknown");
if(!msg)
msg = "unknown error";
debug_printf("png_decode: %s: %s\n", fn, msg);
goto ret;
}
{
PngMemFile f = { file, file_size };
png_set_read_fn(png_ptr, &f, png_read);
// read header and determine format
png_read_info(png_ptr, info_ptr);
png_uint_32 w, h;
int bit_depth, color_type;
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);
const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
const u32 bpp = (u32)(pitch / w * 8);
int flags = 0;
if(bpp == 32)
flags |= TEX_ALPHA;
// make sure format is acceptable
if(bit_depth != 8)
msg = "channel precision != 8 bits";
if(color_type & PNG_COLOR_MASK_PALETTE)
msg = "color type is invalid (must be direct color)";
if(msg)
goto fail;
const size_t img_size = pitch * h;
Handle img_hm;
// cannot free old t->hm until after png_read_end,
// but need to set to this handle afterwards => need tmp var.
img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm);
if(!img)
{
err = ERR_NO_MEM;
goto fail;
}
const int transforms = TEX_TOP_DOWN ^ global_orientation;
int ret = alloc_rows(img, h, pitch, transforms, rows);
if(ret < 0)
{
err = ret;
goto fail;
}
png_read_image(png_ptr, (png_bytepp)rows);
png_read_end(png_ptr, info_ptr);
debug_assert(f.p == file && f.size == file_size && f.pos == f.size);
// store image info
mem_free_h(t->hm);
t->hm = img_hm;
t->ofs = 0; // libpng returns decoded image data; no header
t->w = w;
t->h = h;
t->bpp = bpp;
t->flags = flags;
err = 0;
}
err = png_decode_impl(t, file, file_size, png_ptr, info_ptr, img, rows, msg);
if(err < 0)
goto fail;
// shared cleanup
ret:
@ -1064,11 +1081,57 @@ static void png_flush(png_structp)
}
// limitation: palette images aren't supported
static int png_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
// split out of png_encode to simplify resource cleanup and avoid
// "dtor / setjmp interaction" warning.
static int png_encode_impl(TexInfo* t, const char* fn, u8* img,
png_structp png_ptr, png_infop info_ptr,
RowArray& rows, Handle& hf, const char*& msg)
{
UNUSED(img_size);
UNUSED2(msg); // we don't produce any error messages ATM.
const int png_transforms = (t->flags & TEX_BGR)? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY;
// PNG is native RGB.
const png_uint_32 w = t->w, h = t->h;
const size_t pitch = w * t->bpp / 8;
int color_type;
switch(t->flags & (TEX_GREY|TEX_ALPHA))
{
case TEX_GREY|TEX_ALPHA:
color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
break;
case TEX_GREY:
color_type = PNG_COLOR_TYPE_GRAY;
break;
case TEX_ALPHA:
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
break;
default:
color_type = PNG_COLOR_TYPE_RGB;
break;
}
hf = vfs_open(fn, FILE_WRITE|FILE_NO_AIO);
CHECK_ERR(hf);
png_set_write_fn(png_ptr, &hf, png_write, png_flush);
png_set_IHDR(png_ptr, info_ptr, w, h, 8, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
const int transforms = TEX_TOP_DOWN ^ t->flags;
CHECK_ERR(alloc_rows(img, h, pitch, transforms, rows));
png_set_rows(png_ptr, info_ptr, (png_bytepp)rows);
png_write_png(png_ptr, info_ptr, png_transforms, 0);
return 0;
}
// limitation: palette images aren't supported
static int png_encode(TexInfo* t, const char* fn, u8* img, size_t UNUSED(img_size))
{
const char* msg = 0;
int err = -1;
@ -1089,60 +1152,17 @@ static int png_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
// setup error handling
if(setjmp(png_jmpbuf(png_ptr)))
{
// reached if libpng triggered a longjmp
fail:
debug_printf("png_encode: %s: %s\n", fn, msg? msg : "unknown");
if(!msg)
msg = "unknown error";
debug_printf("png_encode: %s: %s\n", fn, msg);
goto ret;
}
{
const int png_transforms = (t->flags & TEX_BGR)? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY;
// PNG is native RGB.
const png_uint_32 w = t->w, h = t->h;
const size_t pitch = w * t->bpp / 8;
int color_type;
switch(t->flags & (TEX_GRAY|TEX_ALPHA))
{
case TEX_GRAY|TEX_ALPHA:
color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
break;
case TEX_GRAY:
color_type = PNG_COLOR_TYPE_GRAY;
break;
case TEX_ALPHA:
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
break;
default:
color_type = PNG_COLOR_TYPE_RGB;
break;
}
hf = vfs_open(fn, FILE_WRITE|FILE_NO_AIO);
if(hf < 0)
{
err = (int)hf;
goto fail;
}
png_set_write_fn(png_ptr, &hf, png_write, png_flush);
png_set_IHDR(png_ptr, info_ptr, w, h, 8, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
const int transforms = TEX_TOP_DOWN ^ t->flags;
int ret = alloc_rows(img, h, pitch, transforms, rows);
if(ret < 0)
{
err = ret;
goto fail;
}
png_set_rows(png_ptr, info_ptr, (png_bytepp)rows);
png_write_png(png_ptr, info_ptr, png_transforms, 0);
err = 0;
}
err = png_encode_impl(t, fn, img, png_ptr, info_ptr, rows, hf, msg);
if(err < 0)
goto fail;
// shared cleanup
ret:
@ -1234,6 +1254,8 @@ fail:
for(cmpt = 0; cmpt < num_cmpts; cmpt++)
jas_matrix_destroy(matr[cmpt]);
// .. transparently switch handles - free the old (compressed)
// buffer and replace it with the decoded-image memory handle.
mem_free_h(t->hm);
t->hm = img_hm;
@ -1265,7 +1287,7 @@ static int jp2_encode(TexInfo* t, const char* fn, const u8* img, size_t img_size
static inline bool jpg_fmt(const u8* p, size_t size)
{
UNUSED(size); // size >= 4, we only need 2 bytes
UNUSED2(size); // size >= 4, we only need 2 bytes
// JFIF requires SOI marker at start of stream.
// we compare single bytes to be endian-safe.
@ -1397,14 +1419,14 @@ fail:
// preliminary; set below to reflect output params
// make sure we get a color format we know
// (exception: if bpp = 8, go grayscale below)
// (exception: if bpp = 8, go greyscale below)
// necessary to support non-standard CMYK files written by Photoshop.
cinfo.out_color_space = JCS_RGB;
int flags = 0;
if(bpp == 8)
{
flags |= TEX_GRAY;
flags |= TEX_GREY;
cinfo.out_color_space = JCS_GRAYSCALE;
}
@ -1472,6 +1494,8 @@ fail:
debug_printf("jpg_decode: corrupt-data warning(s) occurred\n");
// store image info
// .. transparently switch handles - free the old (compressed)
// buffer and replace it with the decoded-image memory handle.
mem_free_h(t->hm);
t->hm = img_hm;
t->ofs = 0; // jpeg returns decoded image data; no header
@ -1497,7 +1521,7 @@ ret:
// limitation: palette images aren't supported
static int jpg_encode(TexInfo* t, const char* fn, u8* img, size_t img_size)
static int jpg_encode(TexInfo* t, const char* fn, u8* img, size_t UNUSED(img_size))
{
const char* msg = 0;
int err = -1;
@ -1675,7 +1699,7 @@ int tex_load_mem(Handle hm, const char* fn, TexInfo* t)
size_t size;
void* _p = mem_get_ptr(hm, &size);
// guarantee *_valid routines 4 header bytes
// guarantee is_fmt routines 4 header bytes
if(size < 4)
return ERR_CORRUPTED;
t->hm = hm;
@ -1687,18 +1711,13 @@ int tex_load_mem(Handle hm, const char* fn, TexInfo* t)
// find codec that understands the data, and decode
const Codec* c = codecs;
for(int i = 0; i < num_codecs; i++, c++)
{
if(c->is_fmt(p, size))
{
CHECK_ERR(c->decode(t, fn, p, size));
// HACK: check if the texture's data buffer is the IO buffer
// passed to us. if so, need to increment refcount so the
// caller's doesn't actually free it.
if(hm == t->hm)
h_add_ref(t->hm);
return 0;
}
}
return ERR_UNKNOWN_FORMAT;
}
@ -1711,7 +1730,8 @@ int tex_load(const char* fn, TexInfo* t)
Handle hm = vfs_load(fn, p, size);
RETURN_ERR(hm); // (need handle below; can't test return value directly)
int ret = tex_load_mem(hm, fn, t);
mem_free_h(hm);
// do not free hm! it either still holds the image data (i.e. texture
// wasn't compressed) or was replaced by a new buffer for the image data.
if(ret < 0)
memset(t, 0, sizeof(TexInfo));
return ret;

View File

@ -28,7 +28,7 @@ enum TexInfoFlags
TEX_DXT = 0x07, // mask; value = {1,3,5}
TEX_BGR = 0x08,
TEX_ALPHA = 0x10,
TEX_GRAY = 0x20,
TEX_GREY = 0x20,
// orientation - never returned by tex_load, since it automatically
// flips to match global orientation. these are passed to tex_write

View File

@ -47,7 +47,7 @@ struct UniFont
H_TYPE_DEFINE(UniFont);
static void UniFont_init(UniFont* f, va_list UNUSEDPARAM(args))
static void UniFont_init(UniFont* f, va_list UNUSED(args))
{
f->glyphs_id = new glyphmap_id;
f->glyphs_size = new glyphmap_size;
@ -62,7 +62,7 @@ static void UniFont_dtor(UniFont* f)
}
static int UniFont_reload(UniFont* f, const char* fn, Handle UNUSEDPARAM(h))
static int UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h))
{
// fn is the base filename, e.g. "console"
// The font definition file is "fonts/"+fn+".fnt" and the texture is "fonts/"+fn+".tga"

View File

@ -54,7 +54,7 @@
# define ZLIB_DLL
# include <zlib.h>
# ifdef _MSC_VER
# if MSC_VERSION
# ifdef NDEBUG
# pragma comment(lib, "zlib1.lib")
# else
@ -884,16 +884,8 @@ int inf_free_ctx(uintptr_t _ctx)
///////////////////////////////////////////////////////////////////////////////
enum ZFileFlags
{
// the ZFile has been successfully zip_map-ped.
// used to make sure the archive's mmap refcount remains balanced,
// i.e. no one double-frees the mapping.
ZF_HAS_MAPPING = 0x4000
};
// marker for ZFile struct, to make sure it's valid
#ifdef PARANOIA
#if CONFIG_PARANOIA
static const u32 ZFILE_MAGIC = FOURCC('Z','F','I','L');
#endif
@ -909,10 +901,6 @@ static int zfile_validate(uint line, ZFile* zf)
msg = "ZFile* parameter = 0";
err = ERR_INVALID_PARAM;
}
#ifdef PARANOIA
else if(zf->magic != ZFILE_MAGIC)
msg = "ZFile corrupted (magic field incorrect)";
#endif
#ifndef NDEBUG
// else if(!h_user_data(zf->ha, H_ZArchive))
// msg = "invalid archive handle";
@ -934,7 +922,7 @@ static int zfile_validate(uint line, ZFile* zf)
return err;
}
#define CHECK_ZFILE(f) CHECK_ERR(zfile_validate(__LINE__, f))
#define CHECK_ZFILE(f) RETURN_ERR(zfile_validate(__LINE__, f))
// convenience function, allows implementation change in ZFile.
@ -969,7 +957,7 @@ int zip_stat(Handle ha, const char* fn, struct stat* s)
// open file, and fill *zf with information about it.
// return < 0 on error (output param zeroed).
int zip_open(const Handle ha, const char* fn, ZFile* zf)
int zip_open(const Handle ha, const char* fn, int flags, ZFile* zf)
{
// zero output param in case we fail below.
memset(zf, 0, sizeof(ZFile));
@ -980,20 +968,16 @@ int zip_open(const Handle ha, const char* fn, ZFile* zf)
ZLoc loc;
// don't want ZFile to contain a ZEnt struct -
// its ucsize member must be 'loose' for compatibility with File.
// => need to copy ZEnt fields into ZFile.
CHECK_ERR(lookup_get_file_info(li, fn, &loc));
#ifdef PARANOIA
zf->magic = ZFILE_MAGIC;
#endif
zf->ucsize = loc.ucsize;
zf->ofs = loc.ofs;
zf->csize = loc.csize;
zf->ha = ha;
zf->inf_ctx = inf_init_ctx(zfile_compressed(zf));
// => need to copy ZLoc fields into ZFile.
RETURN_ERR(lookup_get_file_info(li, fn, &loc));
zf->flags = flags;
zf->ucsize = loc.ucsize;
zf->ofs = loc.ofs;
zf->csize = loc.csize;
zf->ha = ha;
zf->inf_ctx = inf_init_ctx(zfile_compressed(zf));
zf->is_mapped = 0;
CHECK_ZFILE(zf);
return 0;
@ -1029,13 +1013,13 @@ static const size_t CHUNK_SIZE = 16*KiB;
// begin transferring <size> bytes, starting at <ofs>. get result
// with zip_wait_io; when no longer needed, free via zip_discard_io.
int zip_start_io(ZFile* zf, off_t user_ofs, size_t max_output_size, void* user_buf, ZipIO* io)
int zip_start_io(ZFile* zf, off_t user_ofs, size_t max_output_size, void* user_buf, ZipIo* io)
{
// not needed, since ZFile tells us the last read offset in the file.
UNUSED(user_ofs);
UNUSED2(user_ofs);
// zero output param in case we fail below.
memset(io, 0, sizeof(ZipIO));
memset(io, 0, sizeof(ZipIo));
CHECK_ZFILE(zf);
H_DEREF(zf->ha, ZArchive, za);
@ -1089,7 +1073,7 @@ int zip_start_io(ZFile* zf, off_t user_ofs, size_t max_output_size, void* user_b
// indicates if the IO referenced by <io> has completed.
// return value: 0 if pending, 1 if complete, < 0 on error.
int zip_io_complete(ZipIO* io)
int zip_io_complete(ZipIo* io)
{
if(io->already_inflated)
return 1;
@ -1099,7 +1083,7 @@ int zip_io_complete(ZipIO* io)
// wait until the transfer <io> completes, and return its buffer.
// output parameters are zeroed on error.
int zip_wait_io(ZipIO* io, void*& buf, size_t& size)
int zip_wait_io(ZipIo* io, void*& buf, size_t& size)
{
buf = io->user_buf;
size = io->max_output_size;
@ -1113,9 +1097,11 @@ int zip_wait_io(ZipIO* io, void*& buf, size_t& size)
if(io->inf_ctx)
{
inf_set_dest(io->inf_ctx, buf, size);
ssize_t bytes_inflated = inf_inflate(io->inf_ctx, raw_buf, raw_size, true);
// true: we allocated the compressed data input buffer, and
// want it freed when it's consumed.
// we allocated the compressed data input buffer and
// want it freed when it's consumed.
const bool want_input_buf_freed = true;
ssize_t bytes_inflated = inf_inflate(io->inf_ctx, raw_buf, raw_size, want_input_buf_freed);
CHECK_ERR(bytes_inflated);
}
else
{
@ -1128,7 +1114,7 @@ int zip_wait_io(ZipIO* io, void*& buf, size_t& size)
// finished with transfer <io> - free its buffer (returned by zip_wait_io)
int zip_discard_io(ZipIO* io)
int zip_discard_io(ZipIo* io)
{
if(io->already_inflated)
return 0;
@ -1190,7 +1176,7 @@ ssize_t zip_read(ZFile* zf, off_t ofs, size_t size, void* p, FileIOCB cb, uintpt
{
CHECK_ZFILE(zf);
const bool compressed = zfile_compressed(zf);
//const bool compressed = zfile_compressed(zf);
H_DEREF(zf->ha, ZArchive, za);
@ -1286,7 +1272,7 @@ int zip_map(ZFile* zf, void*& p, size_t& size)
p = (char*)archive_p + zf->ofs;
size = zf->ucsize;
zf->flags |= ZF_HAS_MAPPING;
zf->is_mapped = 1;
return 0;
}
@ -1302,9 +1288,9 @@ int zip_unmap(ZFile* zf)
// make sure archive mapping refcount remains balanced:
// don't allow multiple|"false" unmaps.
if(!(zf->flags & ZF_HAS_MAPPING))
if(!zf->is_mapped)
return -1;
zf->flags &= ~ZF_HAS_MAPPING;
zf->is_mapped = 0;
H_DEREF(zf->ha, ZArchive, za);
return file_unmap(&za->f);

View File

@ -49,16 +49,11 @@ extern int zip_enum(const Handle ha, const FileCB cb, const uintptr_t user);
struct ZFile
{
#ifdef PARANOIA
u32 magic;
#endif
// keep offset of flags and size members in sync with struct File!
// it is accessed by VFS and must be the same for both (union).
// dirty, but necessary because VFile is pushing the HDATA size limit.
uint flags;
size_t ucsize;
// size of logical file
size_t ucsize; // uncompressed size
off_t ofs; // in archive
off_t csize;
@ -66,6 +61,11 @@ struct ZFile
Handle ha;
uintptr_t inf_ctx;
// this ZFile has been successfully zip_map-ped, i.e. reference
// count of the archive's mapping has been increased.
// we need to undo that when closing it.
uint is_mapped : 1;
};
// get file status (size, mtime). output param is zeroed on error.
@ -73,7 +73,7 @@ extern int zip_stat(Handle ha, const char* fn, struct stat* s);
// open file, and fill *zf with information about it.
// return < 0 on error (output param zeroed).
extern int zip_open(Handle ha, const char* fn, ZFile* zf);
extern int zip_open(Handle ha, const char* fn, int flags, ZFile* zf);
// close file.
extern int zip_close(ZFile* zf);
@ -83,9 +83,9 @@ extern int zip_close(ZFile* zf);
// asynchronous read
//
struct ZipIO
struct ZipIo
{
FileIO io;
FileIo io;
uintptr_t inf_ctx;
@ -97,18 +97,18 @@ struct ZipIO
// begin transferring <size> bytes, starting at <ofs>. get result
// with zip_wait_io; when no longer needed, free via zip_discard_io.
extern int zip_start_io(ZFile* zf, off_t ofs, size_t size, void* buf, ZipIO* io);
extern int zip_start_io(ZFile* zf, off_t ofs, size_t size, void* buf, ZipIo* io);
// indicates if the IO referenced by <io> has completed.
// return value: 0 if pending, 1 if complete, < 0 on error.
extern int zip_io_complete(ZipIO* io);
extern int zip_io_complete(ZipIo* io);
// wait until the transfer <io> completes, and return its buffer.
// output parameters are zeroed on error.
extern int zip_wait_io(ZipIO* io, void*& p, size_t& size);
extern int zip_wait_io(ZipIo* io, void*& p, size_t& size);
// finished with transfer <io> - free its buffer (returned by zip_wait_io)
extern int zip_discard_io(ZipIO* io);
extern int zip_discard_io(ZipIo* io);
//

View File

@ -3,7 +3,7 @@
#define SDL_BUTTON_INDEX_COUNT 5
#if defined(_WIN32) && !defined(NO_WSDL)
#if OS_WIN && !defined(NO_WSDL)
# include "sysdep/win/wsdl.h"
// The SDL_BUTTON_* enum is zero-based and in the range [0..4] in wsdl.h

View File

@ -78,7 +78,7 @@
// skip the functions on VC2005 (already provided there), but not our
// self-test and the t* defines (needed for test).
#if _MSC_VER < 1400
#if MSC_VERSION < 1400
// return length [in characters] of a string, not including the trailing
@ -200,7 +200,7 @@ int tcat_s(tchar* dst, size_t max_dst_chars, const tchar* src)
return tncat_s(dst, max_dst_chars, src, SIZE_MAX);
}
#endif // #if _MSC_VER < 1400
#endif // #if MSC_VERSION < 1400
//////////////////////////////////////////////////////////////////////////////

View File

@ -4,10 +4,10 @@
#include "posix_types.h" // size_t
// these are already shipped with VC2005
#if _MSC_VER < 1400
#if MSC_VERSION < 1400
// Conflicts with glibc definitions
#ifndef OS_UNIX
#if !OS_UNIX
// return length [in characters] of a string, not including the trailing
// null character. to protect against access violations, only the
// first <max_len> characters are examined; if the null character is
@ -53,6 +53,6 @@ extern int strcat_s(char* dst, size_t max_dst_chars, const char* src);
extern int wcscat_s(wchar_t* dst, size_t max_dst_chars, const wchar_t* src);
#endif // #if _MSC_VER < 1400
#endif // #if MSC_VERSION < 1400
#endif // #ifndef STRINGS_S_H__

View File

@ -31,6 +31,10 @@ extern void get_cpu_info(void);
// <new_value> and return true.
extern bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value);
// this is often used for pointers, so the macro coerces parameters to
// uinptr_t. invalid usage unfortunately also goes through without warnings.
// to catch cases where the caller has passed <expected> as <location> or
// similar mishaps, the implementation verifies <location> is a valid pointer.
#define CAS(l,o,n) CAS_((uintptr_t*)l, (uintptr_t)o, (uintptr_t)n)
extern void atomic_add(intptr_t* location, intptr_t increment);
@ -40,6 +44,19 @@ extern void mfence();
extern void serialize();
// Win32 CONTEXT field abstraction
// (there's no harm also defining this for other platforms)
#if CPU_AMD64
# define PC_ Rip
# define FP_ Rbp
# define SP_ Rsp
#elif CPU_IA32
# define PC_ Eip
# define FP_ Ebp
# define SP_ Esp
#endif
#ifdef __cplusplus
}
#endif

View File

@ -24,7 +24,7 @@
#include "timer.h"
// HACK (see call to wtime_reset_impl)
#ifdef _WIN32
#if OS_WIN
#include "win/wtime.h"
#endif
@ -35,10 +35,10 @@
#include <vector>
#include <algorithm>
#ifndef __GNUC__
#if HAVE_ASM
// replace pathetic MS libc implementation
#ifdef _WIN32
// replace pathetic MS libc implementation.
#if OS_WIN
double _ceil(double f)
{
double r;
@ -52,7 +52,7 @@ __asm
fstp [r]
}
UNUSED(f);
UNUSED2(f);
return r;
}
@ -94,8 +94,8 @@ __asm
pop eax
}
UNUSED(new_cw);
UNUSED(mask);
UNUSED2(new_cw);
UNUSED2(mask);
return 0;
}
@ -537,12 +537,12 @@ void ia32_get_cpu_info()
measure_cpu_freq();
// HACK: if _WIN32, the HRT makes its final implementation choice
// HACK: on Windows, the HRT makes its final implementation choice
// in the first calibrate call where cpu info is available.
// call wtime_reset_impl here to have that happen now,
// so app code isn't surprised by a timer change, although the HRT
// does try to keep the timer continuous.
#ifdef _WIN32
#if OS_WIN
wtime_reset_impl();
#endif
}
@ -575,7 +575,7 @@ bool __cdecl CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value)
{
// try to see if caller isn't passing in an address
// (CAS's arguments are silently casted)
ASSERT(location >= (uintptr_t*)0x10000);
ASSERT(!debug_is_pointer_bogus(location));
bool was_updated;
__asm
@ -624,7 +624,7 @@ void serialize()
__asm cpuid
}
#else // #ifndef __GNUC__
#else // i.e. #if !HAVE_ASM
bool CAS_(uintptr_t* location, uintptr_t expected, uintptr_t new_value)
{
@ -669,4 +669,4 @@ void serialize()
__asm__ __volatile__ ("cpuid");
}
#endif // #ifdef __GNUC__
#endif // #if HAVE_ASM

View File

@ -18,8 +18,8 @@
#ifndef IA32_H
#define IA32_H
#if !(defined(__GNUC__) && defined(i386)) && !defined(_M_IX86)
#error "including ia32.h without _M_IX86 (or both __GNUC__ and i386) defined"
#if !CPU_IA32
#error "including ia32.h without CPU_IA32=1
#endif
#include "lib/types.h"

View File

@ -5,7 +5,7 @@
#include <memory.h>
#include <stdarg.h>
#ifdef _MSC_VER
#if MSC_VERSION
double round(double x)
{
@ -15,7 +15,7 @@ double round(double x)
#endif
#ifndef HAVE_C99
#if !HAVE_C99
float fminf(float a, float b)
{

View File

@ -3,9 +3,9 @@
#include "config.h"
#if defined(OS_WIN)
#if OS_WIN
# include "win/win.h"
#elif defined(OS_UNIX)
#elif OS_UNIX
# include "unix/unix.h"
#endif
@ -13,10 +13,20 @@
extern "C" {
#endif
// compiling without exceptions (usually for performance reasons);
// tell STL not to generate any.
#if CONFIG_DISABLE_EXCEPTIONS
# if OS_WIN
# define _HAS_EXCEPTIONS 0
# else
# define STL_NO_EXCEPTIONS
# endif
#endif
// vsnprintf2: handles positional parameters and %lld.
// already available on *nix, emulated on Win32.
#ifdef _WIN32
#if OS_WIN
extern int vsnprintf2(char* buffer, size_t count, const char* format, va_list argptr);
#else
#define vsnprintf2 vsnprintf
@ -24,11 +34,22 @@ extern int vsnprintf2(char* buffer, size_t count, const char* format, va_list ar
// alloca: allocate on stack, automatically free, return 0 if out of mem.
// already available on *nix, emulated on Win32.
#ifdef _WIN32
#if OS_WIN
#undef alloca // from malloc.h
extern void* alloca(size_t size);
#endif
// finite: return 0 iff the given double is infinite or NaN.
#if OS_WIN
# define finite _finite
#else
# define finite __finite
#endif
//
// output
//
enum DisplayErrorFlags
{
@ -74,11 +95,35 @@ extern void display_msg(const char* caption, const char* msg);
extern void wdisplay_msg(const wchar_t* caption, const wchar_t* msg);
//
// clipboard
//
extern int clipboard_set(const wchar_t* text);
extern wchar_t* clipboard_get(void);
extern int clipboard_free(wchar_t* copy);
//
// mouse cursor
//
// creates a cursor from the given 32 bpp RGBA texture. hotspot (hx,hy) is
// the offset from its upper-left corner to the position where mouse clicks
// are registered.
// the cursor must be cursor_free-ed when no longer needed.
extern int cursor_create(int w, int h, void* img, int hx, int hy,
void** cursor);
// replaces the current system cursor with the one indicated. need only be
// called once per cursor; pass 0 to restore the default.
extern int cursor_set(void* cursor);
// destroys the indicated cursor and frees its resources. if it is
// currently the system cursor, the default cursor is restored first.
extern int cursor_free(void* cursor);
extern int get_executable_name(char* n_path, size_t buf_size);
// return filename of the module which contains address <addr>,
@ -89,16 +134,16 @@ wchar_t* get_module_filename(void* addr, wchar_t* path);
extern int pick_directory(char* n_path, size_t buf_size);
#ifdef _MSC_VER
#if MSC_VERSION
extern double round(double);
#endif
#ifndef HAVE_C99
#if !HAVE_C99
extern float fminf(float a, float b);
extern float fmaxf(float a, float b);
#endif
#ifndef _MSC_VER
#if !MSC_VERSION
#define stricmp strcasecmp
#define strnicmp strncasecmp
#endif
@ -112,7 +157,7 @@ extern float fmaxf(float a, float b);
// C++ linkage
// STL_HASH_MAP, STL_HASH_MULTIMAP, STL_HASH_SET
#ifdef __GNUC__
#if GCC_VERSION
// GCC
# include <ext/hash_map>
# include <ext/hash_set> // Probably?
@ -139,19 +184,19 @@ namespace __gnu_cxx
#else // !__GNUC__
# include <hash_map>
# include <hash_set>
# if defined(_MSC_VER) && (_MSC_VER >= 1300)
// VC7 or above
# if MSC_VERSION >= 1300
# define STL_HASH_MAP stdext::hash_map
# define STL_HASH_MULTIMAP stdext::hash_multimap
# define STL_HASH_SET stdext::hash_set
# define STL_HASH_MULTISET stdext::hash_multiset
# else
// VC6 and anything else (most likely name)
# else
# define STL_HASH_MAP std::hash_map
# define STL_HASH_MULTIMAP std::hash_multimap
# define STL_HASH_SET std::hash_set
# define STL_HASH_MULTISET std::hash_multiset
# endif // defined(_MSC_VER) && (_MSC_VER >= 1300)
# endif // MSC_VERSION >= 1300
#endif // !__GNUC__
#include "debug.h"

View File

@ -3,6 +3,7 @@
#include "error_dialog.h"
#include <windows.h>
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
@ -40,6 +41,7 @@ END
IDD_DIALOG1 DIALOGEX 0, 0, 328, 260
STYLE DS_SETFONT | DS_SETFOREGROUND | DS_FIXEDSYS | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_TOPMOST | WS_EX_APPWINDOW
CAPTION "Program Error"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN

View File

@ -271,7 +271,7 @@ extern "C" int vsnprintf2(TCHAR* buffer, size_t count, const TCHAR* format, va_l
if (chr == _T('I'))
{
debug_assert(! "MSVC-style \"%I64\" is not allowed!");
debug_warn("MSVC-style \"%I64\" is not allowed!");
}
if (is_lengthmod(chr))
@ -363,7 +363,7 @@ finished_reading:
if (s->length > 256)
{
if (s->length == 0x00006c6c)
#ifdef _MSC_VER
#if MSC_VERSION
newformat += "I64"; // MSVC compatibility
#else
newformat += "ll";
@ -399,7 +399,7 @@ finished_reading:
*/
// Because of those dangerous assumptions about varargs:
#ifndef _M_IX86
#if !CPU_IA32
#error SLIGHTLY FATAL ERROR: Only x86 is supported!
#endif
@ -420,7 +420,7 @@ finished_reading:
{
if (varsizes[i] <= 0)
{
debug_assert(! "Invalid variable type somewhere - make sure all variable things are positional and defined");
debug_warn("Invalid variable type somewhere - make sure all variable things are positional and defined");
return -1;
}
@ -442,7 +442,7 @@ finished_reading:
FormatVariable* s = static_cast<FormatVariable*>(*it);
if (s->position <= 0)
{
debug_assert(! "Invalid use of positional elements - make sure all variable things are positional and defined");
debug_warn("Invalid use of positional elements - make sure all variable things are positional and defined");
return -1;
}
newstack += std::string( stackitems[s->position-1].first, stackitems[s->position-1].second );

View File

@ -642,7 +642,7 @@ int aio_cancel(int fd, struct aiocb* cb)
{
// Win32 limitation: can't cancel single transfers -
// all pending reads on this file are cancelled.
UNUSED(cb);
UNUSED2(cb);
const HANDLE h = aio_h_get(fd);
if(h == INVALID_HANDLE_VALUE)
@ -671,7 +671,7 @@ int aio_write(struct aiocb* cb)
int lio_listio(int mode, struct aiocb* const cbs[], int n, struct sigevent* se)
{
UNUSED(se);
UNUSED2(se);
int err = 0;

View File

@ -217,7 +217,7 @@ static uintptr_t get_target_pc()
if(ret == (DWORD)-1)
{
debug_warn("get_target_pc: SuspendThread failed");
return -1;
return 0;
}
// note: we don't need to call more than once: this increments a DWORD
// 'suspend count'; target is guaranteed to be suspended unless
@ -236,15 +236,7 @@ static uintptr_t get_target_pc()
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL;
if(GetThreadContext(hThread, &context))
{
#if defined(_M_AMD64)
pc = context.Rip;
#elif defined(_M_IX86)
pc = context.Eip;
#else
# error "port CONTEXT"
#endif
}
pc = context.PC_;
/////////////////////////////////////////////
@ -259,9 +251,9 @@ static uintptr_t get_target_pc()
static pthread_t thread;
static sem_t exit_flag;
static void* prof_thread_func(void* data)
static void* prof_thread_func(void* UNUSED(data))
{
UNUSED(data);
debug_set_thread_name("profiler");
const long _1e6 = 1000000;
const long _1e9 = 1000000000;

View File

@ -28,7 +28,7 @@
#include "byte_order.h" // FOURCC
// optional: enables translation of the "unhandled exception" dialog.
#ifdef I18N
#if HAVE_I18N
#include "ps/i18n.h"
#endif
@ -68,7 +68,7 @@ static bool is_locked()
// program will terminate soon after. fixing this is hard and senseless.
static const wchar_t* translate(const wchar_t* text)
{
#ifdef HAVE_I18N
#if HAVE_I18N
// make sure i18n system is (already|still) initialized.
if(g_CurrentLocale)
{
@ -142,6 +142,37 @@ void debug_wprintf(const wchar_t* fmt, ...)
}
// inform the debugger of the current thread's description, which it then
// displays instead of just the thread handle.
void wdbg_set_thread_name(const char* name)
{
// we pass information to the debugger via a special exception it
// swallows. if not running under one, bail now to avoid
// "first chance exception" warnings.
if(!IsDebuggerPresent())
return;
// presented by Jay Bazuzi (from the VC debugger team) at TechEd 1999.
const struct ThreadNameInfo
{
DWORD type;
const char* name;
DWORD thread_id; // any valid ID or -1 for current thread
DWORD flags;
}
info = { 0x1000, name, (DWORD)-1, 0 };
__try
{
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// if we get here, apparently this hack is not longer supported.
debug_warn("TODO: find alternative thread name implementation");
}
}
//-----------------------------------------------------------------------------
// debug memory allocator
//-----------------------------------------------------------------------------
@ -169,41 +200,53 @@ void debug_heap_check()
// if not called, the default is DEBUG_HEAP_NONE, i.e. do nothing.
void debug_heap_enable(DebugHeapChecks what)
{
#ifdef HAVE_VC_DEBUG_ALLOC
// note: if MMGR is enabled, crtdbg.h will not have been included.
// in that case, we do nothing here - this interface is too basic to
// control mmgr; use its API instead.
#if !CONFIG_USE_MMGR && HAVE_VC_DEBUG_ALLOC
uint flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
switch(what)
{
case DEBUG_HEAP_NONE:
flags = 0;
// note: do not set flags to zero because we might trash some
// important flag value.
flags &= ~(_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
break;
case DEBUG_HEAP_NORMAL:
flags |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;
flags |= _CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF;
break;
case DEBUG_HEAP_ALL:
flags |= _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;
flags |= (_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_DELAY_FREE_MEM_DF |
_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
break;
default:
debug_assert("debug_heap_enable: invalid what");
}
_CrtSetDbgFlag(flags);
#else
UNUSED2(what);
#endif // HAVE_DEBUGALLOC
}
// return 1 if the pointer appears to be totally bogus, otherwise 0.
// this check is not authoritative in that the pointer may in truth
// be invalid regardless of the return value here, but can be used
// to filter out obviously wrong values in a portable manner.
int debug_is_bogus_pointer(const void* p)
// this check is not authoritative (the pointer may be "valid" but incorrect)
// but can be used to filter out obviously wrong values in a portable manner.
int debug_is_pointer_bogus(const void* p)
{
#ifdef _M_IX86
#if CPU_IA32
if(p < (void*)0x10000)
return true;
if(p >= (void*)(uintptr_t)0x80000000)
return true;
#endif
// note: we don't check alignment because nothing can be assumed about a
// pointer to the middle of a string and we mustn't reject valid pointers.
// nor do we bother checking the address against known stack/heap areas
// because that doesn't cover everything (e.g. DLLs, VirtualAlloc, etc.).
return IsBadReadPtr(p, 1) != 0;
}
@ -225,6 +268,8 @@ struct WhileSuspendedParam
static void* while_suspended_thread_func(void* user_arg)
{
debug_set_thread_name("suspender");
DWORD err;
WhileSuspendedParam* param = (WhileSuspendedParam*)user_arg;
@ -269,8 +314,7 @@ static int call_while_suspended(WhileSuspendedFunc func, void* user_arg)
WhileSuspendedParam param = { hThread, func, user_arg };
pthread_t thread;
err = pthread_create(&thread, 0, while_suspended_thread_func, &param);
debug_assert(err == 0);
WARN_ERR(pthread_create(&thread, 0, while_suspended_thread_func, &param));
void* ret;
err = pthread_join(thread, &ret);
@ -317,7 +361,7 @@ static const uint MAX_BREAKPOINTS = 4;
// remove all breakpoints enabled by debug_set_break from <context>.
// called while target is suspended.
static int brk_disable_all_in_ctx(BreakInfo* bi, CONTEXT* context)
static int brk_disable_all_in_ctx(BreakInfo* UNUSED(bi), CONTEXT* context)
{
context->Dr7 &= ~brk_all_local_enables;
return 0;
@ -405,20 +449,20 @@ static int brk_do_request(HANDLE hThread, void* arg)
goto fail;
}
#if defined(_M_IX86)
#if CPU_IA32
if(bi->want_all_disabled)
ret = brk_disable_all_in_ctx(bi, &context);
else
ret = brk_enable_in_ctx (bi, &context);
#else
#error "port"
#endif
if(!SetThreadContext(hThread, &context))
{
debug_warn("brk_do_request: SetThreadContext failed");
goto fail;
}
#else
#error "port"
#endif
return 0;
fail:
@ -781,7 +825,7 @@ struct XInfo
// (compiler-specific).
static bool isCppException(const EXCEPTION_RECORD* er)
{
#ifdef _MSC_VER
#if MSC_VERSION
// note: representation of 'msc' isn't specified, so use FOURCC
if(er->ExceptionCode != FOURCC(0xe0, 'm','s','c'))
return false;
@ -1026,7 +1070,7 @@ LONG WINAPI wdbg_exception_filter(EXCEPTION_POINTERS* ep)
swprintf(fmt, ARRAY_SIZE(fmt), L"%%%ds (%%%dh[^:]:%%d)", DBG_SYMBOL_LEN, DBG_FILE_LEN);
// bake in the string limits (future-proof)
(void)swscanf(locus, fmt, func_name, file, &line);
// don't care if all 3 fields were filled (they default to "?")
// don't care whether all 3 fields were filled (they default to "?")
wchar_t buf[500];
const wchar_t* msg_fmt =

View File

@ -18,18 +18,19 @@
#ifndef WDBG_H__
#define WDBG_H__
#include "lib/types.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
#if MSC_VERSION
# define debug_break() __asm { int 3 }
#else
# error "port this or define to implementation function"
#endif
// internal use only:
extern void wdbg_set_thread_name(const char* name);
#ifdef __cplusplus
}
#endif

View File

@ -40,7 +40,7 @@
#define PERFORM_SELF_TEST 0
#endif
#ifdef _MSC_VER
#if MSC_VERSION
#pragma comment(lib, "dbghelp.lib")
#pragma comment(lib, "oleaut32.lib") // VariantChangeType
#endif
@ -269,17 +269,8 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int*
// but WinXP SP2 and above require it be suspended.
// copy from CONTEXT to STACKFRAME64
#if defined(_M_AMD64)
# define PC_ Rip
# define FP_ Rbp
# define SP_ Rsp
#elif defined(_M_IX86)
# define PC_ Eip
# define FP_ Ebp
# define SP_ Esp
#endif
#ifdef _M_IX86
#if CPU_IA32
// optimized for size.
// this is the (so far) only case where __declspec(naked) is absolutely
@ -288,6 +279,8 @@ int debug_resolve_symbol(void* ptr_of_interest, char* sym_name, char* file, int*
// on us returning their correct values.
static __declspec(naked) void get_current_context(void* pcontext)
{
// squelch W4 unused paramter warning (it's accessed from asm)
UNUSED2(pcontext);
__asm
{
pushad
@ -357,7 +350,7 @@ rep stosd
}
}
#else // #ifdef _M_IX86
#else // #if CPU_IA32
static void get_current_context(CONTEXT* pcontext)
{
@ -810,7 +803,7 @@ static void seq_determine_formatting(size_t el_size, size_t el_count,
static int dump_sequence(DebugIterator el_iterator, void* internal,
size_t el_count, DWORD el_type_id, size_t el_size, DumpState state)
{
const u8* el_p;
const u8* el_p = 0; // avoid "uninitialized" warning
// special case: display as a string if the sequence looks to be text.
// do this only if container isn't empty because the otherwise the
@ -891,7 +884,7 @@ static int dump_array(const u8* p,
static int determine_symbol_address(DWORD id, DWORD type_id, const u8** pp)
static int determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const u8** pp)
{
const STACKFRAME64* sf = current_stackframe64;
@ -1030,6 +1023,11 @@ static int dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
return WDBG_TYPE_INFO_UNAVAILABLE;
const size_t size = (size_t)size_;
// single out() call. note: we pass a single u64 for all sizes,
// which will only work on little-endian systems.
// must be declared before goto to avoid W4 warning.
const wchar_t* fmt = L"";
u64 data = movzx_64le(p, size);
// if value is 0xCC..CC (uninitialized mem), we display as hex.
// the output would otherwise be garbage; this makes it obvious.
@ -1042,10 +1040,6 @@ static int dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
goto display_as_hex;
}
// single out() call. note: we pass a single u64 for all sizes,
// which will only work on little-endian systems.
const wchar_t* fmt = L"";
switch(base_type)
{
// boolean
@ -1171,12 +1165,16 @@ static int dump_sym_base_class(DWORD type_id, const u8* p, DumpState state)
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &base_class_type_id))
return WDBG_TYPE_INFO_UNAVAILABLE;
// this is a virtual base class. we can't display those because it'd
// require reading the VTbl, which is difficult given lack of documentation
// and just not worth it.
DWORD vptr_ofs;
if(SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_VIRTUALBASEPOINTEROFFSET, &vptr_ofs))
return WDBG_UNSUPPORTED;
return dump_sym(base_class_type_id, p, state);
// unsupported: virtual base classes would require reading the VTbl,
// which is difficult given lack of documentation and not worth it.
return 0;
}
@ -1213,7 +1211,7 @@ static int dump_sym_data(DWORD id, const u8* p, DumpState state)
//-----------------------------------------------------------------------------
static int dump_sym_enum(DWORD type_id, const u8* p, DumpState state)
static int dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state))
{
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
@ -1271,7 +1269,8 @@ static int dump_sym_enum(DWORD type_id, const u8* p, DumpState state)
//-----------------------------------------------------------------------------
static int dump_sym_function(DWORD type_id, const u8* p, DumpState state)
static int dump_sym_function(DWORD UNUSED(type_id), const u8* UNUSED(p),
DumpState UNUSED(state))
{
return WDBG_SUPPRESS_OUTPUT;
}
@ -1279,7 +1278,7 @@ static int dump_sym_function(DWORD type_id, const u8* p, DumpState state)
//-----------------------------------------------------------------------------
static int dump_sym_function_type(DWORD type_id, const u8* p, DumpState state)
static int dump_sym_function_type(DWORD UNUSED(type_id), const u8* p, DumpState UNUSED(state))
{
// this symbol gives class parent, return type, and parameter count.
// unfortunately the one thing we care about, its name,
@ -1342,7 +1341,7 @@ static int dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
// bail if it's obvious the pointer is bogus
// (=> can't display what it's pointing to)
if(debug_is_bogus_pointer(p))
if(debug_is_pointer_bogus(p))
return 0;
// avoid duplicates and circular references
@ -1527,8 +1526,8 @@ not_handle:
}
static int udt_dump_suppressed(const wchar_t* type_name, const u8* p, size_t size,
DumpState state, ULONG num_children, const DWORD* children)
static int udt_dump_suppressed(const wchar_t* type_name, const u8* UNUSED(p), size_t UNUSED(size),
DumpState state, ULONG UNUSED(num_children), const DWORD* UNUSED(children))
{
if(!udt_should_suppress(type_name))
return 1;
@ -1695,7 +1694,7 @@ done:
//-----------------------------------------------------------------------------
static int dump_sym_vtable(DWORD type_id, const u8* p, DumpState state)
static int dump_sym_vtable(DWORD UNUSED(type_id), const u8* UNUSED(p), DumpState UNUSED(state))
{
// unsupported (vtable internals are undocumented; too much work).
return WDBG_SUPPRESS_OUTPUT;
@ -1705,7 +1704,7 @@ static int dump_sym_vtable(DWORD type_id, const u8* p, DumpState state)
//-----------------------------------------------------------------------------
static int dump_sym_unknown(DWORD type_id, const u8* p, DumpState state)
static int dump_sym_unknown(DWORD type_id, const u8* UNUSED(p), DumpState UNUSED(state))
{
// redundant (already done in dump_sym), but this is rare.
DWORD type_tag;
@ -1770,7 +1769,7 @@ static int dump_sym(DWORD type_id, const u8* p, DumpState state)
// output the symbol's name and value via dump_sym*.
// called from dump_frame_cb for each local symbol; lock is held.
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
static BOOL CALLBACK dump_sym_cb(SYMBOL_INFO* sym, ULONG UNUSED(size), void* UNUSED(ctx))
{
out_latch_pos(); // see decl
mod_base = sym->ModBase;
@ -1813,9 +1812,8 @@ struct IMAGEHLP_STACK_FRAME2 : public IMAGEHLP_STACK_FRAME
};
// called by walk_stack for each stack frame
static int dump_frame_cb(const STACKFRAME64* sf, void* user_arg)
static int dump_frame_cb(const STACKFRAME64* sf, void* UNUSED(user_arg))
{
UNUSED(user_arg);
current_stackframe64 = sf;
void* func = (void*)sf->AddrPC.Offset;
@ -2082,13 +2080,13 @@ static void test_stl()
std::vector<double> v_double_empty;
std::queue<double> q_double_empty;
std::stack<double> st_double_empty;
#ifdef HAVE_STL_HASH
#if HAVE_STL_HASH
STL_HASH_MAP<double,double> hm_double_empty;
STL_HASH_MULTIMAP<double,std::wstring> hmm_double_empty;
STL_HASH_SET<double> hs_double_empty;
STL_HASH_MULTISET<double> hms_double_empty;
#endif
#ifdef HAVE_STL_SLIST
#if HAVE_STL_SLIST
STL_SLIST<double> sl_double_empty;
#endif
std::string str_empty;
@ -2106,13 +2104,13 @@ static void test_stl()
std::vector<double> v_double_uninit;
std::queue<double> q_double_uninit;
std::stack<double> st_double_uninit;
#ifdef HAVE_STL_HASH
#if HAVE_STL_HASH
STL_HASH_MAP<double,double> hm_double_uninit;
STL_HASH_MULTIMAP<double,std::wstring> hmm_double_uninit;
STL_HASH_SET<double> hs_double_uninit;
STL_HASH_MULTISET<double> hms_double_uninit;
#endif
#ifdef HAVE_STL_SLIST
#if HAVE_STL_SLIST
STL_SLIST<double> sl_double_uninit;
#endif
std::string str_uninit;
@ -2152,11 +2150,11 @@ static void test_addrs(int p_int, double p_double, char* p_pchar, uintptr_t p_ui
test_stl();
int uninit_int; UNUSED(uninit_int);
float uninit_float; UNUSED(uninit_float);
double uninit_double; UNUSED(uninit_double);
bool uninit_bool; UNUSED(uninit_bool);
HWND uninit_hwnd; UNUSED(uninit_hwnd);
int uninit_int; UNUSED2(uninit_int);
float uninit_float; UNUSED2(uninit_float);
double uninit_double; UNUSED2(uninit_double);
bool uninit_bool; UNUSED2(uninit_bool);
HWND uninit_hwnd; UNUSED2(uninit_hwnd);
}

View File

@ -255,14 +255,14 @@ FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh, HMODULE hmod) {
// Do the InterlockedExchange magic
//
#ifdef _M_IX86
#if CPU_IA32
#undef InterlockedExchangePointer
#define InterlockedExchangePointer(Target, Value) \
(PVOID)(uintptr_t)InterlockedExchange((PLONG)(Target), (LONG)(uintptr_t)(Value))
#if (_MSC_VER >= 1300)
#if MSC_VERSION >= 1300
typedef __w64 unsigned long *PULONG_PTR;
#else
typedef unsigned long *PULONG_PTR;

View File

@ -1,8 +1,8 @@
// RAGE! Win32 OpenGL headers are full of crap we have to emulate
// (must not include windows.h)
#ifndef _WIN32
#error "do not include if not compiling for Windows"
#if !OS_WIN
#error "wgl.h: do not include if not compiling for Windows"
#endif

View File

@ -27,7 +27,7 @@
#include "posix.h"
#include "error_dialog.h"
#ifdef _MSC_VER
#if MSC_VERSION
#pragma comment(lib, "shell32.lib") // for pick_directory SH* calls
#endif
@ -46,7 +46,7 @@ static BOOL CALLBACK is_this_our_window(HWND hWnd, LPARAM lParam)
{
DWORD pid;
DWORD tid = GetWindowThreadProcessId(hWnd, &pid);
UNUSED(tid); // the function can't fail
UNUSED2(tid); // the function can't fail
if(pid == GetCurrentProcessId())
{
@ -65,7 +65,7 @@ HWND win_get_app_main_window()
{
HWND our_window = 0;
DWORD ret = EnumWindows(is_this_our_window, (LPARAM)&our_window);
UNUSED(ret);
UNUSED2(ret);
// the callback returns FALSE when it has found the window
// (so as not to waste time); EnumWindows then returns 0.
// therefore, we can't check this; just return our_window.
@ -140,9 +140,8 @@ wchar_t* get_module_filename(void* addr, wchar_t* path)
static int CALLBACK browse_cb(HWND hWnd, unsigned int msg, LPARAM lParam, LPARAM ldata)
static int CALLBACK browse_cb(HWND hWnd, unsigned int msg, LPARAM UNUSED(lParam), LPARAM ldata)
{
UNUSED(lParam);
if(msg == BFFM_INITIALIZED)
{
const char* cur_dir = (const char*)ldata;
@ -397,15 +396,31 @@ static int CALLBACK error_dialog_proc(HWND hDlg, unsigned int msg, WPARAM wParam
// exits directly if 'exit' is clicked.
ErrorReaction display_error_impl(const wchar_t* text, int flags)
{
const DialogParams params = { text, flags };
// temporarily remove any pending quit message from the queue because
// it would prevent the dialog from being displayed (DialogBoxParam
// returns IDOK without doing anything). will be restored below.
// notes:
// - this isn't only relevant at exit - Windows also posts one if
// window init fails. therefore, it is important that errors can be
// displayed regardless.
// - by passing hWnd=0, we check all windows belonging to the current
// thread. there is no reason to use hWndParent below.
MSG msg;
BOOL quit_pending = PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE);
const HINSTANCE hInstance = GetModuleHandle(0);
LPCSTR lpTemplateName = MAKEINTRESOURCE(IDD_DIALOG1);
const DialogParams params = { text, flags };
// get the enclosing app's window handle. we can't just pass 0 or
// the desktop window because the dialog must be modal (the app
// must not crash/continue to run before it has been displayed).
const HWND hWndParent = win_get_app_main_window();
// can't just pass 0 or desktop because this dialog must be
// modal (the app must not crash/continue to run before this is seen).
INT_PTR ret = DialogBoxParam(hInstance, lpTemplateName, hWndParent, error_dialog_proc, (LPARAM)&params);
if(quit_pending)
PostQuitMessage((int)msg.wParam);
// failed; warn user and make sure we return an ErrorReaction.
if(ret == 0 || ret == -1)
{
@ -499,6 +514,127 @@ int clipboard_free(wchar_t* copy)
}
//-----------------------------------------------------------------------------
// mouse cursor
//-----------------------------------------------------------------------------
static void* ptr_from_HICON(HICON hIcon)
{
return (void*)(uintptr_t)hIcon;
}
static void* ptr_from_HCURSOR(HCURSOR hCursor)
{
return (void*)(uintptr_t)hCursor;
}
static HICON HICON_from_ptr(void* p)
{
return (HICON)(uintptr_t)p;
}
static HCURSOR HCURSOR_from_ptr(void* p)
{
return (HCURSOR)(uintptr_t)p;
}
// creates a cursor from the given 32 bpp RGBA texture. hotspot (hx,hy) is
// the offset from its upper-left corner to the position where mouse clicks
// are registered.
// the cursor must be cursor_free-ed when no longer needed.
int cursor_create(int w, int h, void* img, int hx, int hy,
void** cursor)
{
*cursor = 0;
// convert to BGRA (required by BMP).
// don't do this in-place so we don't spoil someone else's
// use of the texture (however unlikely that may be).
void* img_bgra = malloc(w*h*4);
if(!img_bgra)
return ERR_NO_MEM;
const u8* src = (const u8*)img;
u8* dst = (u8*)img_bgra;
for(int i = 0; i < w*h; i++)
{
const u8 r = src[0], g = src[1], b = src[2], a = src[3];
dst[0] = b; dst[1] = g; dst[2] = r; dst[3] = a;
dst += 4;
src += 4;
}
img = img_bgra;
// MSDN says selecting this HBITMAP into a DC is slower since we use
// CreateBitmap; bpp/format must be checked against those of the DC.
// this is the simplest way and we don't care about slight performance
// differences because this is typically only called once.
HBITMAP hbmColor = CreateBitmap(w, h, 1, 32, img_bgra);
free(img_bgra);
// CreateIconIndirect doesn't access it; we just need to pass
// an empty bitmap.
HBITMAP hbmMask = CreateBitmap(w, h, 1, 1, 0);
// create the cursor (really an icon; they differ only in
// fIcon and the hotspot definitions).
ICONINFO ii;
ii.fIcon = FALSE; // cursor
ii.xHotspot = hx;
ii.yHotspot = hy;
ii.hbmMask = hbmMask;
ii.hbmColor = hbmColor;
HICON hIcon = CreateIconIndirect(&ii);
// CreateIconIndirect makes copies, so we no longer need these.
DeleteObject(hbmMask);
DeleteObject(hbmColor);
if(!hIcon) // not INVALID_HANDLE_VALUE
{
debug_warn("cursor CreateIconIndirect failed");
return -1;
}
*cursor = ptr_from_HICON(hIcon);
return 0;
}
// replaces the current system cursor with the one indicated. need only be
// called once per cursor; pass 0 to restore the default.
int cursor_set(void* cursor)
{
// restore default cursor.
if(!cursor)
cursor = ptr_from_HCURSOR(LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW)));
(void)SetCursor(HCURSOR_from_ptr(cursor));
// return value (previous cursor) is useless.
return 0;
}
// destroys the indicated cursor and frees its resources. if it is
// currently the system cursor, the default cursor is restored first.
int cursor_free(void* cursor)
{
// bail now to prevent potential confusion below; there's nothing to do.
if(!cursor)
return 0;
// if the cursor being freed is active, restore the default arrow
// (just for safety).
if(ptr_from_HCURSOR(GetCursor()) == cursor)
WARN_ERR(cursor_set(0));
BOOL ok = DestroyIcon(HICON_from_ptr(cursor));
return ok? 0 : -1;
}
///////////////////////////////////////////////////////////////////////////////
//
// module init and shutdown mechanism
@ -659,9 +795,15 @@ static
#endif
void win_pre_main_init()
{
// enable FPU exceptions
#if CPU_IA32
const int bits = _EM_INVALID|_EM_DENORMAL|_EM_ZERODIVIDE|_EM_OVERFLOW|_EM_UNDERFLOW|_EM_INEXACT;
_control87(bits, _MCW_EM);
#endif
// enable memory tracking and leak detection;
// no effect if !defined(HAVE_VC_DEBUG_ALLOC).
#ifdef PARANOIA
// no effect if !HAVE_VC_DEBUG_ALLOC.
#if CONFIG_PARANOIA
debug_heap_enable(DEBUG_HEAP_ALL);
#elif !defined(NDEBUG)
debug_heap_enable(DEBUG_HEAP_NORMAL);

View File

@ -18,8 +18,8 @@
#ifndef WIN_H__
#define WIN_H__
#ifndef _WIN32
#error "including win.h without _WIN32 defined"
#if !OS_WIN
#error "win.h: do not include if not compiling for Windows"
#endif
#include "config.h"
@ -28,7 +28,7 @@
// provide C99 *snprintf functions if compiler doesn't already
// (MinGW does, VC7.1 doesn't).
#ifndef HAVE_C99
#if !HAVE_C99
# define snprintf _snprintf
# define swprintf _snwprintf
# define vsnprintf _vsnprintf

View File

@ -18,8 +18,8 @@
#ifndef WIN_INTERNAL_H
#define WIN_INTERNAL_H
#ifndef _WIN32
#error "including win_internal.h without _WIN32 defined"
#if !OS_WIN
#error "win_internal.h: do not include if not compiling for Windows"
#endif
#include "lib/types.h" // intptr_t
@ -134,7 +134,7 @@ typedef struct _MEMORYSTATUSEX
///////////////////////////////////////////////////////////////////////////////
// MinGW headers are already correct; only change on VC
#ifdef _MSC_VER
#if MSC_VERSION
#ifndef NTSTATUS
#define NTSTATUS long
@ -244,7 +244,7 @@ typedef struct _SYSTEM_POWER_INFORMATION
#define PO_TZ_INVALID_MODE 0 // The system does not support CPU throttling,
// or there is no thermal zone defined [..]
#endif // #ifdef _MSC_VER
#endif // #if MSC_VERSION
// neither VC7.1 nor MinGW define this
typedef struct _PROCESSOR_POWER_INFORMATION

View File

@ -58,7 +58,7 @@ extern "C" {
#define PATH_MAX 255
// Win32 MAX_PATH is 260
#ifdef _WIN32
#if OS_WIN
# ifndef SIZE_MAX // VC2005 already defines this in limits.h
# define SIZE_MAX 0xffffffff
# endif
@ -131,7 +131,7 @@ EWOULDBLOCK // Operation would block (may be the same value as EAGAIN]).
//
// already defined by MinGW
#ifdef _MSC_VER
#if MSC_VERSION
typedef unsigned int mode_t;
#endif
@ -144,7 +144,7 @@ typedef unsigned int mode_t;
// Extra hack for VC++ 2005, since it defines inline stat/fstat
// functions inside stat.h (which get confused by the
// macro-renaming of "stat")
# if _MSC_VER >= 1400
# if MSC_VERSION >= 1400
# define RC_INVOKED // stat.h only includes stat.inl if "!defined(RC_INVOKED) && !defined(__midl)"
# include <sys/stat.h>
# undef RC_INVOKED
@ -178,7 +178,6 @@ typedef void DIR;
struct dirent
{
ino_t d_ino;
char d_name[PATH_MAX+1];
};

View File

@ -7,27 +7,23 @@ typedef signed char int8_t;
typedef short int16_t;
// already defined by MinGW
#ifdef _MSC_VER
#if MSC_VERSION
typedef int int32_t;
#endif
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__LCC__)
#if MSC_VERSION || ICC_VERSION || LCC_VERSION
typedef __int64 int64_t;
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DMC__)
typedef long long int64_t;
#else
#error "port int64_t"
typedef long long int64_t;
#endif
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__LCC__)
#if MSC_VERSION || ICC_VERSION || LCC_VERSION
typedef unsigned __int64 uint64_t;
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DMC__)
typedef unsigned long long uint64_t;
#else
#error "port uint64_t"
typedef unsigned long long uint64_t;
#endif
// note: we used to define [u]intptr_t here (if not already done).

View File

@ -209,8 +209,7 @@ again:
void* tls = pthread_getspecific(key);
if(tls)
{
int ret = pthread_setspecific(key, 0);
debug_assert(ret == 0);
WARN_ERR(pthread_setspecific(key, 0));
dtor(tls);
had_valid_tls = true;
@ -257,10 +256,8 @@ static unsigned __stdcall thread_start(void* param)
}
int pthread_create(pthread_t* thread_id, const void* attr, void*(*func)(void*), void* user_arg)
int pthread_create(pthread_t* thread_id, const void* UNUSED(attr), void*(*func)(void*), void* user_arg)
{
UNUSED(attr);
// tell the trampoline above what to call.
// note: don't stack-allocate this, since the new thread might
// not be executed before we tear down our stack frame.
@ -387,10 +384,8 @@ int pthread_mutex_unlock(pthread_mutex_t* m)
// not implemented - pthread_mutex is based on CRITICAL_SECTION,
// which doesn't support timeouts. use sem_timedwait instead.
int pthread_mutex_timedlock(pthread_mutex_t* m, const struct timespec* abs_timeout)
int pthread_mutex_timedlock(pthread_mutex_t* UNUSED(m), const struct timespec* UNUSED(abs_timeout))
{
UNUSED(m);
UNUSED(abs_timeout);
return -ENOSYS;
}
@ -405,8 +400,9 @@ HANDLE sem_t_to_HANDLE(sem_t* sem)
int sem_init(sem_t* sem, int pshared, unsigned value)
{
UNUSED(pshared);
*sem = (uintptr_t)CreateSemaphore(0, (LONG)value, 0x7fffffff, 0);
SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES) };
sec.bInheritHandle = (BOOL)pshared;
*sem = (uintptr_t)CreateSemaphore(&sec, (LONG)value, 0x7fffffff, 0);
return 0;
}

View File

@ -49,7 +49,7 @@
// for easy removal of DirectDraw dependency (used to query total video mem)
#define DDRAW
#ifdef _MSC_VER
#if MSC_VERSION
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
@ -177,9 +177,9 @@ static LRESULT CALLBACK wndproc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPA
}
int SDL_EnableUNICODE(int enable)
// always on (we don't care about the extra overhead)
int SDL_EnableUNICODE(int UNUSED(enable))
{
UNUSED(enable)
return 1;
}
@ -478,13 +478,17 @@ static LRESULT CALLBACK keyboard_ll_hook(int nCode, WPARAM wParam, LPARAM lParam
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
DWORD vk = p->vkCode;
UNUSED2(vk);
// disabled - we want the normal Windows printscreen handling to
// remain so as not to confuse artists.
/*
// replace Windows PrintScreen handler
if(vk == VK_SNAPSHOT)
{
// check whether PrintScreen should be taking screenshots -- if
// not, allow the standard Windows clipboard to work
if(/*keyRespondsTo(HOTKEY_SCREENSHOT, SDLK_PRINT) &&*/ app_active)
if(app_active)
{
// send to wndproc
UINT msg = (UINT)wParam;
@ -496,6 +500,7 @@ static LRESULT CALLBACK keyboard_ll_hook(int nCode, WPARAM wParam, LPARAM lParam
return 1;
}
}
*/
}
// pass it on to other hook handlers
@ -505,7 +510,6 @@ static LRESULT CALLBACK keyboard_ll_hook(int nCode, WPARAM wParam, LPARAM lParam
static void enable_kbd_hook(bool enable)
{
/*
if(enable)
{
debug_assert(hKeyboard_LL_Hook == 0);
@ -518,7 +522,6 @@ static void enable_kbd_hook(bool enable)
UnhookWindowsHookEx(hKeyboard_LL_Hook);
hKeyboard_LL_Hook = 0;
}
*/
}
@ -582,10 +585,8 @@ static int wsdl_shutdown()
}
int SDL_Init(Uint32 flags)
int SDL_Init(Uint32 UNUSED(flags))
{
UNUSED(flags);
enable_kbd_hook(true);
return 0;
@ -843,7 +844,7 @@ void SDL_WM_SetCaption(const char* title, const char* icon)
{
SetWindowText(hWnd, title);
UNUSED(icon); // TODO: implement
UNUSED2(icon); // TODO: implement
}
@ -1094,11 +1095,8 @@ void glutMouseFunc(void (*func)(int, int, int, int))
void glutInit(int* argc, char* argv[])
void glutInit(int* UNUSED(argc), char* UNUSED(argv)[])
{
UNUSED(argc);
UNUSED(argv);
SDL_Init(0);
atexit(SDL_Quit);
}

View File

@ -136,7 +136,7 @@ extern int SDL_SetGamma(float r, float g, float b);
// Debug-mode ICC doesn't like the intrinsics, so only use them
// for MSVC and non-debug ICC.
#if defined(_MSC_VER) && !( defined(__INTEL_COMPILER) && !defined(NDEBUG) )
#if MSC_VERSION && !( defined(__INTEL_COMPILER) && !defined(NDEBUG) )
extern unsigned short _byteswap_ushort(unsigned short);
extern unsigned long _byteswap_ulong(unsigned long);
extern unsigned __int64 _byteswap_uint64(unsigned __int64);

View File

@ -24,7 +24,7 @@
#ifdef _MSC_VER
#if MSC_VERSION
#pragma comment(lib, "ws2_32.lib")
#endif

View File

@ -165,7 +165,7 @@ static int choose_impl()
if(overrides[impl] == HRT_FORCE)\
safe = true;
#if defined(_M_IX86) && !defined(NO_TSC)
#if CPU_IA32 && !defined(NO_TSC)
// CPU Timestamp Counter (incremented every clock)
// ns resolution, moderate precision (poor clock crystal?)
//
@ -201,7 +201,7 @@ static int choose_impl()
}
#endif // TSC
#if defined(_WIN32) && !defined(NO_QPC)
#if OS_WIN && !defined(NO_QPC)
// Windows QueryPerformanceCounter API
// implementations:
// - PIT on Win2k - 838 ns resolution, slow to read (~3 µs)
@ -295,13 +295,13 @@ static i64 ticks_lk()
switch(hrt_impl)
{
// TSC
#if defined(_M_IX86) && !defined(NO_TSC)
#if CPU_IA32 && !defined(NO_TSC)
case HRT_TSC:
return (i64)rdtsc();
#endif
// QPC
#if defined(_WIN32) && !defined(NO_QPC)
#if OS_WIN && !defined(NO_QPC)
case HRT_QPC:
{
LARGE_INTEGER i;
@ -312,7 +312,7 @@ static i64 ticks_lk()
#endif
// TGT
#ifdef _WIN32
#if OS_WIN
case HRT_GTC:
return (i64)GetTickCount();
#endif
@ -488,7 +488,7 @@ static const long safe_timer_freq = 1000;
static long safe_time()
{
#ifdef _WIN32
#if OS_WIN
return (long)GetTickCount();
#else
return (long)(clock() * 1000.0 / CLOCKS_PER_SEC);
@ -561,9 +561,9 @@ static void calibrate_lk()
static pthread_t thread;
static sem_t exit_flag;
static void* calibration_thread(void* data)
static void* calibration_thread(void* UNUSED(data))
{
UNUSED(data);
debug_set_thread_name("wtime");
for(;;)
{
@ -808,10 +808,8 @@ int nanosleep(const struct timespec* rqtp, struct timespec* /* rmtp */)
}
int gettimeofday(struct timeval* tv, void* tzp)
int gettimeofday(struct timeval* tv, void* UNUSED(tzp))
{
UNUSED(tzp);
const long us = (long)(time_ns() / 1000);
tv->tv_sec = (time_t) (us / _1e6);
tv->tv_usec = (suseconds_t)(us % _1e6);

View File

@ -18,9 +18,12 @@
#ifndef WTIME_H__
#define WTIME_H__
#define HAVE_CLOCK_GETTIME
#define HAVE_GETTIMEOFDAY
// advertise support for the timer routines we emulate; used by timer.cpp.
// #undef to avoid macro redefinition warning.
#undef HAVE_CLOCK_GETTIME
#define HAVE_CLOCK_GETTIME 1
#undef HAVE_GETTIMEOFDAY
#define HAVE_GETTIMEOFDAY 1
//
@ -70,7 +73,7 @@ extern int clock_gettime(clockid_t clock, struct timespec* ts);
extern int clock_getres(clockid_t clock, struct timespec* res);
// HACK: if _WIN32, the HRT makes its final implementation choice
// HACK: on Windows, the HRT makes its final implementation choice
// in the first calibrate call where cpu_freq is available.
// provide a routine that makes the choice when called,
// so app code isn't surprised by a timer change, although the HRT

View File

@ -36,7 +36,7 @@ double get_time()
{
double t;
#ifdef HAVE_CLOCK_GETTIME
#if HAVE_CLOCK_GETTIME
static struct timespec start = {0};
struct timespec ts;
@ -47,7 +47,7 @@ double get_time()
(void)clock_gettime(CLOCK_REALTIME, &ts);
t = (ts.tv_sec - start.tv_sec) + (ts.tv_nsec - start.tv_nsec)*1e-9;
#elif defined(HAVE_GETTIMEOFDAY)
#elif HAVE_GETTIMEOFDAY
static struct timeval start;
struct timeval cur;
@ -83,7 +83,7 @@ double timer_res()
double res = 0.0;
#ifdef HAVE_CLOCK_GETTIME
#if HAVE_CLOCK_GETTIME
struct timespec ts;
if(clock_getres(CLOCK_REALTIME, &ts) == 0)