1
0
forked from 0ad/0ad

fixed some signed/unsigned warnings; added gamma control via SDL

This was SVN commit r258.
This commit is contained in:
janwas 2004-05-24 20:25:48 +00:00
parent cf5e2524c2
commit df6fceba62
13 changed files with 1137 additions and 787 deletions

View File

@ -58,7 +58,40 @@ u32 fnv_hash(const void* buf, const size_t len)
}
// FNV1-A hash - good for strings.
// if len = 0 (default), treat buf as a C-string;
// otherwise, hash <len> bytes of buf.
u64 fnv_hash64(const void* buf, const size_t len)
{
u64 h = 0xCBF29CE484222325;
// give distinct values for different length 0 buffers.
// value taken from FNV; it has no special significance.
const u8* p = (const u8*)buf;
// expected case: string
if(!len)
{
while(*p)
{
h ^= *p++;
h *= 0x100000001B3;
}
}
else
{
size_t bytes_left = len;
while(bytes_left != 0)
{
h ^= *p++;
h *= 0x100000001B3;
bytes_left--;
}
}
return h;
}
void bswap32(const u8* data, int cnt)
@ -173,6 +206,26 @@ float fminf(float a, float b)
long round(double x)
{
return (long)(x + 0.5);
}
// input in [0, 1); convert to u16 range
u16 fp_to_u16(double in)
{
if(!(0 <= in && in < 1.0))
{
debug_warn("clampf not in [0,1)");
return 65535;
}
long l = round(in * 65535.0);
assert((unsigned long)l <= 65535);
return (u16)l;
}
// big endian!
void base32(const int len, const u8* in, u8* out)

View File

@ -32,6 +32,7 @@
// if len = 0 (default), treat buf as a C-string;
// otherwise, hash <len> bytes of buf.
extern u32 fnv_hash(const void* buf, const size_t len = 0);
extern u64 fnv_hash64(const void* buf, const size_t len);
// hash (currently FNV) of a filename
typedef u32 FnHash;
@ -104,6 +105,8 @@ extern float fminf(float, float);
extern long round(double);
extern u16 fp_to_u16(double in);
// big endian!
extern void base32(const int len, const u8* in, u8* out);

View File

@ -22,3 +22,5 @@
#include <algorithm>
#include <numeric>
#pragma warning(disable:4996)

View File

@ -5,4 +5,12 @@
int res_reload(const char* const fn)
{
return h_reload(fn);
}
}
// purpose of this routine (intended to be called once a frame):
// file notification may come at any time. by forcing the reloads
// to take place here, we don't require everything to be thread-safe.

View File

@ -96,10 +96,14 @@ __asm
long cpu_caps = 0;
long cpu_ext_caps = 0;
int tsc_is_safe = -1;
static char cpu_vendor[13];
static int family, model; // used to detect cpu_type
int tsc_is_safe = -1;
static int have_brand_string = 0;
// int instead of bool for easier setting from asm
// optimized for size
@ -148,11 +152,11 @@ __asm
mov esi, 0x80000000
mov eax, esi
cpuid
cmp eax, esi
jbe no_ext_funcs
lea esi, [esi+4]
cmp eax, esi
jb no_brand_str
cmp eax, esi ; max ext <= 0x80000000?
jbe no_ext_funcs ; yes - no ext funcs at all
lea esi, [esi+4] ; esi = 0x80000004
cmp eax, esi ; max ext < 0x80000004?
jb no_brand_str ; yes - brand string not available, skip
; get CPU brand string (>= Athlon XP, P4)
mov edi, offset cpu_type
@ -171,6 +175,8 @@ $1: lea eax, [ebp+esi] ; 0x80000002 .. 4
jle $1
; (already 0 terminated)
mov [have_brand_string], ebp ; ebp = 1 = true
no_brand_str:
; get extended feature flags
@ -194,8 +200,54 @@ void ia32_get_cpu_info()
if(cpu_caps == 0) // cpuid not supported - can't do the rest
return;
// cpu_type set from brand string - clean it up some
if(strcmp(cpu_type, "unknown") != 0)
// fall back to manual detect of CPU type if it didn't supply
// a brand string, or if the brand string is useless (i.e. "Unknown").
if(!have_brand_string || strncmp(cpu_type, "Unknow", 6) == 0)
// we use an extra flag to detect if we got the brand string:
// safer than comparing against the default name, which may change.
//
// some older boards reprogram the brand string with
// "Unknow[n] CPU Type" on CPUs the BIOS doesn't recognize.
// in that case, we ignore the brand string and detect manually.
{
// AMD
if(!strcmp(cpu_vendor, "AuthenticAMD"))
{
// everything else is either too old, or should have a brand string.
if(family == 6)
{
if(model == 3 || model == 7)
strcpy(cpu_type, "AMD Duron");
else if(model <= 5)
strcpy(cpu_type, "AMD Athlon");
else
{
if(cpu_ext_caps & EXT_MP_CAPABLE)
strcpy(cpu_type, "AMD Athlon MP");
else
strcpy(cpu_type, "AMD Athlon XP");
}
}
}
// Intel
else if(!strcmp(cpu_vendor, "GenuineIntel"))
{
// everything else is either too old, or should have a brand string.
if(family == 6)
{
if(model == 1)
strcpy(cpu_type, "Intel Pentium Pro");
else if(model == 3 || model == 5)
strcpy(cpu_type, "Intel Pentium II");
else if(model == 6)
strcpy(cpu_type, "Intel Celeron");
else
strcpy(cpu_type, "Intel Pentium III");
}
}
}
// we have a valid brand string; try to pretty it up some
else
{
// strip (tm) from Athlon string
if(!strncmp(cpu_type, "AMD Athlon(tm)", 14))
@ -209,22 +261,11 @@ void ia32_get_cpu_info()
if(sscanf(cpu_type, " Intel(R) Pentium(R) 4 CPU %fGHz", &a) == 1)
strcpy(cpu_type, "Intel Pentium 4");
}
// detect cpu_type ourselves
else
{
// AMD
if(!strcmp(cpu_vendor, "AuthenticAMD"))
{
if(family == 6)
strcpy(cpu_type, (model == 3)? "AMD Duron" : "AMD Athlon");
}
// Intel
else if(!strcmp(cpu_vendor, "GenuineIntel"))
{
if(family == 6 && model >= 7)
strcpy(cpu_type, "Intel Pentium III / Celeron");
}
}
//
// measure CPU frequency
//
// .. get old policy and priority
int old_policy;

View File

@ -52,8 +52,9 @@ enum
extern long cpu_caps;
// define instead of enum to avoid stupid sign conversion warning
#define EXT_3DNOW_PRO BIT(30)
#define EXT_3DNOW BIT(31)
#define EXT_MP_CAPABLE BIT(19)
#define EXT_3DNOW_PRO BIT(30)
#define EXT_3DNOW BIT(31)
extern long cpu_ext_caps;

View File

@ -29,10 +29,11 @@
// powrprof is loaded manually - we only need 1 function.
#endif
#include "Tlhelp32.h"
// EnumDisplayDevices is not available on Win95 or NT.
// try to import it manually here; return -1 if not available.
// note: FreeLibrary at exit avoids BoundsChecker resource leak warnings.
static BOOL (WINAPI *pEnumDisplayDevicesA)(void*, DWORD, void*, DWORD);
static int import_EnumDisplayDevices()
{
@ -40,7 +41,10 @@ static int import_EnumDisplayDevices()
{
static HMODULE hUser32Dll = LoadLibrary("user32.dll");
*(void**)&pEnumDisplayDevicesA = GetProcAddress(hUser32Dll, "EnumDisplayDevicesA");
ONCE(atexit2(FreeLibrary, (uintptr_t)hUser32Dll, CC_STDCALL_1));
FreeLibrary(hUser32Dll);
// make sure the reference is released so BoundsChecker
// doesn't complain. it won't actually be unloaded anyway -
// there is at least one other reference.
}
return pEnumDisplayDevicesA? 0 : -1;
@ -94,21 +98,53 @@ int win_get_gfx_card()
}
/*
get ogl client DLL name
enum loaded dlls
ogl must be running; ambiguous (need to eliminate MCD and opengl32.dll)
*/
// no .dll appended
//
static int get_ogl_drv_name(char* const ogl_drv_name, const size_t max_name_len)
{
int ret = -1;
HKEY hkOglDrivers;
const char* key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers";
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_ENUMERATE_SUB_KEYS, &hkOglDrivers) != 0)
return -1;
char key_name[32];
DWORD key_name_len = sizeof(key_name);
if(RegEnumKeyEx(hkOglDrivers, 0, key_name, &key_name_len, 0, 0, 0, 0) == 0)
{
HKEY hkClass;
if(RegOpenKeyEx(hkOglDrivers, key_name, 0, KEY_QUERY_VALUE, &hkClass) == 0)
{
DWORD size = (DWORD)max_name_len;
if(RegQueryValueEx(hkClass, "Dll", 0, 0, (LPBYTE)ogl_drv_name, &size) == 0)
ret = 0; // success
RegCloseKey(hkClass);
}
}
RegCloseKey(hkOglDrivers);
return ret;
}
// split out so we can return on failure, instead of goto
// method: http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/009679.html
int win_get_gfx_drv()
{
// get driver DLL name
DEVMODEA dm;
// note: dmDriverVersion is not what we're looking for
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
// note: dmSize isn't the first member!
if(!EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm))
return -1;
char drv_name[CCHDEVICENAME+5]; // we add ".dll"
strcpy(drv_name, (const char*)dm.dmDeviceName);
strcat(drv_name, ".dll");
/* want ogl icd, instead of 2d driver */
char ogl_drv_name[MAX_PATH];
CHECK_ERR(get_ogl_drv_name(ogl_drv_name, sizeof(ogl_drv_name)));
// don't want to return 0 on success - we'd need to duplicate free(buf).
// instead, set this variable and return that.
@ -116,21 +152,21 @@ int win_get_gfx_drv()
// read the DLL's version info
DWORD unused;
DWORD ver_size = GetFileVersionInfoSize(drv_name, &unused);
const DWORD ver_size = GetFileVersionInfoSize(ogl_drv_name, &unused);
if(!ver_size)
return -1;
void* buf = malloc(ver_size);
void* const buf = malloc(ver_size);
if(!buf)
return -1;
if(GetFileVersionInfo(drv_name, 0, ver_size, buf))
if(GetFileVersionInfo(ogl_drv_name, 0, ver_size, buf))
{
u16* lang; // -> 16 bit language ID, 16 bit codepage
uint lang_len;
BOOL ok = VerQueryValue(buf, "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
const BOOL ok = VerQueryValue(buf, "\\VarFileInfo\\Translation", (void**)&lang, &lang_len);
if(ok && lang && lang_len == 4)
{
char subblock[64];
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\ProductName", lang[0], lang[1]);
sprintf(subblock, "\\StringFileInfo\\%04X%04X\\FileVersion", lang[0], lang[1]);
const char* ver;
uint ver_len;
if(VerQueryValue(buf, subblock, (void**)&ver, &ver_len))

View File

@ -17,9 +17,90 @@
#include "precompiled.h"
#include "res/res.h"
#include "wfam.h"
#include "win_internal.h"
#if 0
static const size_t CHANGE_BUF_SIZE = 15000;
// better be enough - if too small, we miss changes made to a directory.
// don't worry about size: the user only passes around a pointer
// to this struct, due to the pImpl idiom. this is heap-allocated.
struct FAMRequest_
{
std::string dir_name;
HANDLE hDir;
// history to detect series of notifications, so we can skip
// redundant reloads (slow)
std::string last_path;
DWORD last_action; // FILE_ACTION_* codes or 0
DWORD last_ticks; // timestamp via GetTickCount
OVERLAPPED ovl;
// we don't use any of its fields.
// overlapped I/O completation notification is via IOCP.
// rationale: see below.
char changes[CHANGE_BUF_SIZE];
FAMRequest_(const char* _dir_name)
: dir_name(_dir_name), last_path("")
{
last_action = 0;
last_ticks = 0;
memset(&ovl, 0, sizeof(ovl));
// changes[] doesn't need init
}
};
// don't worry about size: the user only passes around a pointer
// to this struct, due to the pImpl idiom. this is heap-allocated.
struct FAMConnection_
{
std::string app_name;
HANDLE hIOCP;
// queue necessary - race condition if pass to app and re-issue
// needs to be FIFO, and don't want to constantly shuffle items (can be rather large)
// around => list
typedef std::list<FAMEvent> Events;
Events pending_events;
// list of all pending requests to detect duplicates and
// for easier cleanup. only store pointer in container -
// they're not copy-equivalent.
typedef std::map<std::string, FAMRequest*> Requests;
typedef Requests::iterator RequestIt;
Requests requests;
FAMConnection_(const char* _app_name)
: app_name(_app_name)
{
hIOCP = 0;
// not INVALID_HANDLE_VALUE! (CreateIoCompletionPort requirement)
}
~FAMConnection_()
{
CloseHandle(hIOCP);
hIOCP = INVALID_HANDLE_VALUE;
// container holds dynamically allocated Watch structs
// for(WatchIt it = watches.begin(); it != watches.end(); ++it)
// delete it->second;
}
};
#include "sysdep/win/win_internal.h"
// rationale for using I/O completion ports for notification:
@ -43,118 +124,158 @@
// IOCPs work well and are elegant; have not yet noticed any drawbacks.
static HANDLE hIOCP = 0;
// not INVALID_HANDLE_VALUE! (CreateIoCompletionPort requirement)
static const size_t WATCH_BUF_SIZE = 16384;
// better be enough - if too small, we miss changes made to a directory.
// ReadDirectoryChangesW must be called again after each time it returns data,
// so we need to pass this struct to the notification "callback".
// we do this implicitly with the guarantee that &ovl = &Watch (verified via
// assert). rationale: the Key param is already in use (tells the callback to
// call RDC - see KEY_ADD_WATCH_ONLY); this way of passing the parameter is
// cleaner IMO than stuffing the address in an unused member of OVERLAPPED.
struct Watch
{
OVERLAPPED ovl;
// we don't use any of its fields.
void* buf;
HANDLE hDir;
bool watch_subdirs;
// history to detect series of notifications, so we can skip
// redundant reloads (slow)
std::string last_path;
DWORD last_action; // FILE_ACTION_* codes or 0
DWORD last_ticks; // timestamp via GetTickCount
// so we need to pass along the associated Request.
// since we issue RDC immediately, instead of sending a bogus packet
// to the IOCP that triggers the issue, we don't need the key parameter
// for anything - use it to pass along the Request.
// cleaner than assuming &ovl = &Request, or stuffing it in an unused
// member of OVERLAPPED.
Watch(HANDLE hDir, bool watch_subdirs)
{
this->hDir = hDir;
this->watch_subdirs = watch_subdirs;
buf = mem_alloc(WATCH_BUF_SIZE, 32);
// ReadDirectoryChangesW requirement: at least 4-byte alignment.
memset(&ovl, 0, sizeof(ovl));
last_action = 0;
}
~Watch()
{
// mem_free(buf);
// FIXME: mem has already shut down when this is called.
CancelIo(hDir);
CloseHandle(hDir);
hDir = INVALID_HANDLE_VALUE;
}
};
// don't store directly in container - not copy-equivalent.
typedef std::map<std::string, Watch*> Watches;
typedef Watches::iterator WatchIt;
static Watches watches;
static void cleanup(void)
{
CloseHandle(hIOCP);
// container holds dynamically allocated Watch structs
for(WatchIt it = watches.begin(); it != watches.end(); ++it)
delete it->second;
}
int dir_watch_abort(const char* const dir)
{
// find watch
const std::string dir_s(dir);
/* const std::string dir_s(dir);
WatchIt it = watches.find(dir_s);
if(it == watches.end())
return -1;
delete it->second;
watches.erase(it);
*/
return 0;
}
// it's nice to have only 1 call site of ReadDirectoryChangesW, namely
// in the notification "callback". posting an event to the IOCP with
// KEY_ADD_WATCH_ONLY tells it to call RDC; normal events pass KEY_NORMAL.
static enum
// it'd be nice to have only 1 call site of ReadDirectoryChangesW, namely
// in the notification "callback". however, posting a dummy event to the IOCP
// and having the callback issue RDC is a bit ugly, and loses changes made
// before the poll routine is first called.
static int dir_watch_issue(FAMRequest_* fr)
{
KEY_NORMAL,
KEY_ADD_WATCH_ONLY
};
// (re-)request change notification from now on
const DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_CREATION;
BOOL ret = ReadDirectoryChangesW(fr->hDir, fr->changes, CHANGE_BUF_SIZE, FALSE, filter, 0, &fr->ovl, 0);
return ret? 0 : -1;
}
int dir_add_watch(const char* const dir, const bool watch_subdirs)
{
ONCE(atexit2(cleanup));
return 0;
}
void FAMCancelMonitor(FAMConnection*, FAMRequest* req)
{
}
void wfam_shutdown()
{
}
int FAMOpen2(FAMConnection* const fc, const char* app_name)
{
try
{
fc->internal = new FAMConnection_(app_name);
}
catch(std::bad_alloc)
{
fc->internal = 0;
}
// either (VC6) new returned 0, or we caught bad_alloc => fail.
if(!fc->internal)
return -1;
return 0;
}
int FAMClose(FAMConnection* const fc)
{
FAMConnection_*& fc_ = (FAMConnection_*)fc->internal;
if(!fc_)
{
debug_warn("FAMClose: already closed");
return -1;
}
delete fc_;
fc_ = 0;
return 0;
}
int FAMMonitorDirectory(FAMConnection* fc, char* dir, FAMRequest* fr, void* user)
{
FAMConnection_* fc_ = (FAMConnection_*)fc->internal;
/*
// make sure dir is not already being watched
const std::string dir_s(dir);
WatchIt it = watches.find(dir_s);
if(it != watches.end())
return -1;
*/
HANDLE hDir = INVALID_HANDLE_VALUE;
HANDLE& hIOCP = fc_->hIOCP;
// open handle to directory
const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
const HANDLE hDir = CreateFile(dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
hDir = CreateFile(dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
if(hDir == INVALID_HANDLE_VALUE)
return -1;
@ -162,105 +283,139 @@ int dir_add_watch(const char* const dir, const bool watch_subdirs)
hIOCP = CreateIoCompletionPort(hDir, hIOCP, KEY_NORMAL, 0);
if(hIOCP == 0 || hIOCP == INVALID_HANDLE_VALUE)
{
fail:
CloseHandle(hDir);
return -1;
}
// insert
Watch* const w = new Watch(hDir, watch_subdirs);
watches[dir_s] = w;
// tell the notification "callback" to actually add the watch
const DWORD bytes_transferred = 0;
PostQueuedCompletionStatus(hIOCP, bytes_transferred, KEY_ADD_WATCH_ONLY, &w->ovl);
dir_watch_issue(w);
return 0;
}
static int dir_changed(const FILE_NOTIFY_INFORMATION*, Watch*);
// purpose of this routine (intended to be called once a frame):
// file notification may come at any time. by forcing the reloads
// to take place here, we don't require everything to be thread-safe.
//
// added bonus: can actually "poll" for changes here - obviates a worker
// thread, mutex, and 2 queues.
int allow_reload()
static int extract_events(FAMConnection* conn, FAMRequest* req)
{
// deque and process all pending IOCP packets
FAMConnection_ conn_ = (FAMConnection_*)conn->internal;
const FILE_NOTIFY_INFORMATION* fni = (const FILE_NOTIFY_INFORMATION*)req->changes;
Events& events = fc_->pending_events;
FAMEvent event_template;
event_template.conn = conn;
event_template.req = req;
// for every packet in buffer: (there's at least one)
for(;;)
{
// check for change_notification or add_watch packets
DWORD bytes_transferred; // unused
ULONG_PTR key;
OVERLAPPED* povl;
BOOL got_packet = GetQueuedCompletionStatus(hIOCP, &bytes_transferred, &key, &povl, 0);
if(!got_packet)
break;
// many apps save by creating a temp file, deleting the original,
// and renaming the temp file. that leads to 2 reloads, which is slow.
// try to detect this case with a simple state machine - we assume
// the notification order is always the same.
// retrieve the corresponding Watch
// (see Watch definition for rationale)
Watch* const w = (Watch*)povl;
assert(offsetof(struct Watch, ovl) == 0);
// TODO:
// (re-)request change notification from now on
const DWORD filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_CREATION;
ReadDirectoryChangesW(w->hDir, w->buf, WATCH_BUF_SIZE, TRUE, filter, 0, &w->ovl, 0);
const char* actions[] = { "", "FILE_ACTION_ADDED", "FILE_ACTION_REMOVED", "FILE_ACTION_MODIFIED", "FILE_ACTION_RENAMED_OLD_NAME", "FILE_ACTION_RENAMED_NEW_NAME" };
const char* action = actions[fni->Action];
// dir_add_watch requests the watch be added;
// we didn't actually receive any change notification
if(key == KEY_ADD_WATCH_ONLY)
continue;
FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)w->buf;
for(;;)
// convert Windows BSTR-style path to
// portable C string path for the resource manager.
// HACK: convert in place, we copy it into
char fn[MAX_PATH];
char* p = fn;
const int num_chars = fni->FileNameLength/2;
for(int i = 0; i < num_chars; i++)
{
dir_changed(fni, w);
DWORD ofs = fni->NextEntryOffset;
// this was the last entry
if(!ofs)
break;
// advance to next FILE_NOTIFY_INFORMATION (variable length)
(char*&)fni += ofs;
char c = (char)fni->FileName[i];
if(c == '\\')
c = '/';
*p++ = c;
}
*p = '\0';
// don't want to expose details
events.push_back(event_template);
const DWORD ofs = fni->NextEntryOffset;
// advance to next FILE_NOTIFY_INFORMATION (variable length)
if(ofs)
(char*&)fni += ofs;
// this was the last entry - no more elements left in buffer.
else
break;
}
return 0;
}
int dir_changed(const FILE_NOTIFY_INFORMATION* const fni, Watch* const w)
{
// many apps save by creating a temp file, deleting the original,
// and renaming the temp file. that leads to 2 reloads, which is slow.
// try to detect this case with a simple state machine - we assume
// the notification order is always the same.
// TODO:
const char* actions[] = { "", "FILE_ACTION_ADDED", "FILE_ACTION_REMOVED", "FILE_ACTION_MODIFIED", "FILE_ACTION_RENAMED_OLD_NAME", "FILE_ACTION_RENAMED_NEW_NAME" };
const char* action = actions[fni->Action];
// convert Windows BSTR-style path to
// portable C string path for the resource manager.
char fn[MAX_PATH];
char* p = fn;
const int num_chars = fni->FileNameLength/2;
for(int i = 0; i < num_chars; i++)
{
char c = (char)fni->FileName[i];
if(c == '\\')
c = '/';
*p++ = c;
}
*p = '\0';
res_reload(fn);
return 0;
}
int FAMPending(FAMConnection* fc)
{
FAMConnection_* const fc_ = (FAMConnection_*)fc->internal;
Events& pending_events = fc_->pending_events;
if(!pending_events.empty())
return 1;
// check if new buffer has been filled
DWORD bytes_transferred; // unused
ULONG_PTR key;
OVERLAPPED* povl;
BOOL got_packet = GetQueuedCompletionStatus(fc_->hIOCP, &bytes_transferred, &key, &povl, 0);
if(!got_packet)
return 0;
CHECK_ERR(extract_events(conn, req));
// dir_watch_issue(buf);
fc->fni = (FILE_NOTIFY_INFORMATION*)w->buf;
return 1;
}
int FAMNextEvent(FAMConnection* const fc, FAMEvent* const fe)
{
FAMConnection_* const fc_ = (FAMConnection_*)fc->internal;
Events& pending_events = fc_->pending_events;
if(!fe)
{
debug_warn("FAMNextEvent: fe = 0");
return ERR_INVALID_PARAM;
}
if(pending_events.empty())
{
debug_warn("FAMNextEvent: no pending events");
return -1;
}
*fe = pending_events.front();
pending_events.pop_front();
return 0;
}
#endif

View File

@ -466,6 +466,41 @@ inline void SDL_GL_SwapBuffers()
}
static int calc_gamma(float gamma, u16* ramp)
{
if(gamma <= 0.0f)
return ERR_INVALID_PARAM;
// identity
// (special-case it to make sure we get the exact value)
if(gamma == 1.0f)
{
for(u16 i = 0; i < 256; i++)
ramp[i] = (i << 8);
return 0;
}
const double inv_gamma = 1.0 / gamma;
for(int i = 0; i < 256; i++)
{
const double frac = i / 256.0;
// make sure pow arg types are unambiguous
ramp[i] = fp_to_u16(pow(frac, inv_gamma));
// 8.8 fixed point
}
return 0;
}
int SDL_SetGamma(float r, float g, float b)
{
u16 ramp[3][256];
CHECK_ERR(calc_gamma(r, ramp[0]));
CHECK_ERR(calc_gamma(g, ramp[1]));
CHECK_ERR(calc_gamma(b, ramp[2]));
return SetDeviceGammaRamp(hDC, ramp)? 0 : -1;
}

View File

@ -87,7 +87,7 @@ extern int SDL_KillThread(SDL_Thread*);
extern int __stdcall SDL_WarpMouse(int, int);
extern int SDL_SetGamma(float r, float g, float b);
/* macros */

File diff suppressed because it is too large Load Diff

View File

@ -400,16 +400,9 @@ ostream &operator<<(ostream &os, CStr &Str)
size_t CStr::GetHashCode() const
{
// FNV-1 hash for 64 bit integers.
size_t hash = 14695981039346656037;
const char* data = m_String.data();
for( int t = 0; t < m_String.length(); t++ )
{
hash *= 1099511628211;
hash ^= *(data++);
}
return( hash );
return (size_t)fnv_hash64(m_String.data(), m_String.length());
// janwas asks: do we care about the hash being 64 bits?
// it is truncated here on 32-bit systems; why go 64 bit at all?
}
uint CStr::GetSerializedLength() const

View File

@ -18,7 +18,7 @@ using namespace std;
// use GetDouble and type-cast it to <<type>>
#define FUNC_IMPL_CAST_GETDOUBLE(func_name,type) \
_bool CParserValue::func_name(type &ret) \
bool CParserValue::func_name(type &ret) \
{ \
_double d; \
if (GetDouble(d)) \
@ -31,7 +31,7 @@ _bool CParserValue::func_name(type &ret) \
// Get%type% from the CParserValue
// func_name must belong to CParserFile
#define FUNC_IMPL_GETARG(func_name, get_name, type) \
_bool CParserLine::func_name(const _int & arg, type &ret) \
bool CParserLine::func_name(const int & arg, type &ret) \
{ \
if (GetArgCount() <= arg) \
return false; \
@ -42,15 +42,15 @@ _bool CParserLine::func_name(const _int & arg, type &ret) \
// Function definitions
//-------------------------------------------------
static _bool _IsStrictNameChar(const _char& c);
static _bool _IsValueChar(const _char& c);
static bool _IsStrictNameChar(const _char& c);
static bool _IsValueChar(const _char& c);
// Functions used for checking a character if it belongs to a value
// or not
// Checks ident
static _bool _IsStrictNameChar(const _char& c)
static bool _IsStrictNameChar(const _char& c)
{
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
@ -58,7 +58,7 @@ static _bool _IsStrictNameChar(const _char& c)
}
// Checks value
static _bool _IsValueChar(const _char& c)
static bool _IsValueChar(const _char& c)
{
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
@ -80,7 +80,7 @@ CParserValue::~CParserValue()
// Parse the string in Value to different types
// bool
_bool CParserValue::GetBool(_bool &ret)
bool CParserValue::GetBool(bool &ret)
{
// TODO Raj Add or remove some? I can make it all lowercase
// first so True and TRUE also works, or you could just
@ -111,16 +111,16 @@ _bool CParserValue::GetBool(_bool &ret)
}
// double
_bool CParserValue::GetDouble(_double &ret)
bool CParserValue::GetDouble(_double &ret)
{
// locals
_double TempRet = 0.0;
_int Size = m_String.size();
_int i;
_bool AtLeastOne = false; // Checked if at least one of the loops
int Size = m_String.size();
int i;
bool AtLeastOne = false; // Checked if at least one of the loops
// run, otherwise "." would parse OK
_int DecimalPos;
_bool Negative = false; // "-" is found
int DecimalPos;
bool Negative = false; // "-" is found
// Check if '-' is found
if (m_String[0]=='-')
@ -180,7 +180,7 @@ _bool CParserValue::GetDouble(_double &ret)
}
// string - only return m_String, can't fail
_bool CParserValue::GetString(std::string &ret)
bool CParserValue::GetString(std::string &ret)
{
ret = m_String;
return true;
@ -192,7 +192,7 @@ _bool CParserValue::GetString(std::string &ret)
FUNC_IMPL_CAST_GETDOUBLE(GetFloat, _float)
FUNC_IMPL_CAST_GETDOUBLE(GetChar, _char)
FUNC_IMPL_CAST_GETDOUBLE(GetShort, _short)
FUNC_IMPL_CAST_GETDOUBLE(GetInt, _int)
FUNC_IMPL_CAST_GETDOUBLE(GetInt, int)
FUNC_IMPL_CAST_GETDOUBLE(GetLong, _long)
FUNC_IMPL_CAST_GETDOUBLE(GetUnsignedShort, _ushort)
FUNC_IMPL_CAST_GETDOUBLE(GetUnsignedInt, _uint)
@ -264,7 +264,7 @@ CParserLine::~CParserLine()
}
// Clear arguments (deleting m_Memory
_bool CParserLine::ClearArguments()
bool CParserLine::ClearArguments()
{
// Now we can actually clear it
m_Arguments.clear();
@ -275,10 +275,10 @@ _bool CParserLine::ClearArguments()
// it just checks if argument isn't out of range, and
// then it uses the the respective function in CParserValue
FUNC_IMPL_GETARG(GetArgString, GetString, string)
FUNC_IMPL_GETARG(GetArgBool, GetBool, _bool)
FUNC_IMPL_GETARG(GetArgBool, GetBool, bool)
FUNC_IMPL_GETARG(GetArgChar, GetChar, _char)
FUNC_IMPL_GETARG(GetArgShort, GetShort, _short)
FUNC_IMPL_GETARG(GetArgInt, GetInt, _int)
FUNC_IMPL_GETARG(GetArgInt, GetInt, int)
FUNC_IMPL_GETARG(GetArgLong, GetLong, _long)
FUNC_IMPL_GETARG(GetArgUnsignedShort, GetUnsignedShort, _ushort)
FUNC_IMPL_GETARG(GetArgUnsignedInt, GetUnsignedInt, _uint)
@ -293,7 +293,7 @@ FUNC_IMPL_GETARG(GetArgDouble, GetDouble, _double)
// ex:
// variable = 5 => variable, =, 5
// CallFunc(4,2) => CallFunc, 4, 2
_bool CParserLine::ParseString(const CParser& Parser, string strLine)
bool CParserLine::ParseString(const CParser& Parser, string strLine)
{
// Don't process empty string
if (strLine == string())
@ -303,13 +303,13 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
}
// Locals
_bool Extract=false;
_int ExtractPos=0;
bool Extract=false;
int ExtractPos=0;
_char Buffer[256];
_char Letter[] = {'\0','\0'}; // Letter as string
vector<string> Segments;
string strSub;
_int i;
int i;
// Set result to false, then if a match is found, turn it true
m_ParseOK = false;
@ -343,7 +343,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
if (strLine[i] == '\"')
{
// Extract a string, search for another "
_int pos = strLine.find("\"", i+1);
int pos = strLine.find("\"", i+1);
// If matching can't be found,
// the parsing will fail!
@ -419,23 +419,23 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
// * * * *
// Locals
_int Progress; // progress in Segments index
_int Lane=0; // Have many alternative routes we are in
_bool Match; // If a task-type match has been found
int Progress; // progress in Segments index
int Lane=0; // Have many alternative routes we are in
bool Match; // If a task-type match has been found
// The vector of these three represents the different lanes
// LastValidProgress[1] takes you back to lane 1 and how
// the variables was set at that point
vector<_int> LastValidProgress; // When diving into a dynamic argument store store
vector<int> LastValidProgress; // When diving into a dynamic argument store store
// the last valid so you can go back to it
vector<_int> LastValidArgCount; // If an alternative route turns out to fail, we
vector<int> LastValidArgCount; // If an alternative route turns out to fail, we
// need to know the amount of arguments on the last
// valid position, so we can remove them.
vector<_bool> LastValidMatch; // Match at that point
_bool BlockAltNode = false; // If this turns true, the alternative route
vector<bool> LastValidMatch; // Match at that point
bool BlockAltNode = false; // If this turns true, the alternative route
// tested was not a success, and the settings
// should be set back in order to test the
// next node instead
_bool LookNoFurther = false; // If this turns true, it means a definite match has been
bool LookNoFurther = false; // If this turns true, it means a definite match has been
// found and no further looking is required
CParserTaskTypeNode *CurNode=NULL; // Current node on task type
CParserTaskTypeNode *PrevNode=NULL; // Last node
@ -626,7 +626,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
{
// Store argument in CParserValue!
CParserValue value;
_int i;
int i;
switch(CurNode->m_Type)
{
@ -754,7 +754,7 @@ _bool CParserLine::ParseString(const CParser& Parser, string strLine)
// if _minus is found as argument, remove it and add "-" to the one after that
// note, it's easier if std::iterator isn't used here
for (i=1; i<GetArgCount(); ++i)
for (i=1; i<(int)GetArgCount(); ++i)
{
if (m_Arguments[i-1].m_String == "_minus")
{
@ -793,18 +793,18 @@ CParser::~CParser()
// A task-type is a string representing the acquired syntax when parsing
// This function converts that string into a binary tree, making it easier
// and faster to later parse.
_bool CParser::InputTaskType(const string& strName, const string& strSyntax)
bool CParser::InputTaskType(const string& strName, const string& strSyntax)
{
// Locals
CParserTaskType TaskType; // Object we acquire to create
_char Buffer[REGULAR_MAX_LENGTH];
_int ExtractPos = 0;
_bool Extract = false;
_bool Error = false;
_int i;
_bool ConstructNew = false; // If it's the first input, then don't
// construct a new node, because we
// we already have m_BaseNode
CParserTaskType TaskType; // Object we acquire to create
char Buffer[REGULAR_MAX_LENGTH];
size_t ExtractPos = 0;
bool Extract = false;
bool Error = false;
int i;
bool ConstructNew = false; // If it's the first input, then don't
// construct a new node, because we
// we already have m_BaseNode
// Construct base node
TaskType.m_BaseNode = new CParserTaskTypeNode();
@ -837,7 +837,7 @@ _bool CParser::InputTaskType(const string& strName, const string& strSyntax)
CurNode->m_AltNode->m_ParentNode = CurNode;
// It's repeatable
CurNode->m_AltNodeRepeatable = _bool(strSyntax[i]==START_DYNAMIC);
CurNode->m_AltNodeRepeatable = bool(strSyntax[i]==START_DYNAMIC);
// Set to current
CurNode = CurNode->m_AltNode;
@ -974,7 +974,7 @@ _bool CParser::InputTaskType(const string& strName, const string& strSyntax)
}
// Now try finding the second ')'
_int Pos = strSyntax.find(")", ExtractPos+5);
size_t Pos = strSyntax.find(")", ExtractPos+5);
// Check if ')' exists at all
if (Pos == string::npos)