1
0
forked from 0ad/0ad

fix for vc7 (incomplete type in container). also some updates to vfs

This was SVN commit r221.
This commit is contained in:
janwas 2004-05-08 01:11:51 +00:00
parent df282bb714
commit f383cfd4a8
32 changed files with 395 additions and 626 deletions

View File

@ -1,6 +1,7 @@
#include "precompiled.h"
#include "adts.h"
#include <cassert>
template<class T, int max_items> class DynArray
{

View File

@ -1,11 +1,10 @@
#ifndef ADTS_H__
#define ADTS_H__
#include "precompiled.h"
#include "lib.h"
#include <list>
#include <map>
#include <cassert>
@ -135,7 +134,7 @@ public:
{
if(find_line(id))
{
assert(0 && "assign: id already in cache!");
debug_warn("assign: id already in cache!");
return 0;
}
@ -150,7 +149,7 @@ public:
// all are locked and cannot be displaced.
// caller should grow() enough lines so that this never happens.
assert(0 && "assign: all lines locked - grow() more lines");
debug_warn("assign: all lines locked - grow() more lines");
return 0;
have_line:
@ -170,7 +169,7 @@ public:
// invalid: id 0 denotes not-yet-associated lines
if(id == 0)
{
assert(0 && "retrieve: id 0 not allowed");
debug_warn("retrieve: id 0 not allowed");
return 0;
}
Line* l = find_line(id);
@ -264,7 +263,7 @@ public:
if(!res.second)
{
assert(0 && "add: already in container");
debug_warn("add: already in container");
return 0;
}

View File

@ -20,16 +20,15 @@
// large platform-specific routines (e.g. CPU or gfx card info)
// are split out of here.
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include "precompiled.h"
#include "lib.h"
#include "detect.h"
#include "timer.h"
#ifdef _M_IX86
# include "sysdep/ia32.h"
#endif
#include "timer.h"
extern int win_get_gfx_card();
extern int win_get_gfx_drv();

View File

@ -32,7 +32,7 @@ extern int get_cur_resolution(int& xres, int& yres);
// useful for determining aspect ratio. not called by detect().
// if we fail, outputs are unchanged (assumed initialized to defaults)
extern int get_monitor_size(int& width_cm, int& height_cm);
extern int get_monitor_size(int& width_mm, int& height_mm);

View File

@ -18,8 +18,7 @@
* http://www.stud.uni-karlsruhe.de/~urkt/
*/
#include <stdio.h>
#include <stdlib.h>
#include "precompiled.h"
#include "input.h"

View File

@ -14,12 +14,11 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "precompiled.h"
#include "types.h"
#include "lib.h"
#include <cassert>
#include <cstdlib>
// more powerful atexit, with 0 or 1 parameters.
// callable before libc initialized, frees up the real atexit table,
@ -37,7 +36,7 @@
// - call atexit (our exit handler would be called before its handler,
// so we may have shut down something important already).
const int MAX_EXIT_FUNCS = 8;
const int MAX_EXIT_FUNCS = 32;
static struct ExitFunc
@ -74,7 +73,7 @@ static void call_exit_funcs(void)
break;
#endif
default:
assert(0 && "call_exit_funcs: invalid calling convention in ExitFunc!");
debug_warn("call_exit_funcs: invalid calling convention in ExitFunc!");
}
p++;
}
@ -86,7 +85,7 @@ int atexit2(void* func, uintptr_t arg, CallConvention cc)
{
if(num_exit_funcs >= MAX_EXIT_FUNCS)
{
assert("atexit2: too many functions registered. increase MAX_EXIT_FUNCS");
debug_warn("atexit2: too many functions registered. increase MAX_EXIT_FUNCS");
return -1;
}
ExitFunc* p = &exit_funcs[num_exit_funcs++];

View File

@ -108,6 +108,9 @@ enum LibError
#define debug_warn(str) assert(0 && (str))
// converts 4 character string to u32 for easy comparison

View File

@ -4,6 +4,8 @@
* src and len must be multiples of CHUNK_SIZE.
*/
#include "precompiled.h"
#if _MSC_VER >= 0x1300
void memcpy_nt(void* dst, void* src, int len)

View File

@ -16,11 +16,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cassert>
#include <cstdlib>
#include <cmath>
#include <string.h>
#include "precompiled.h"
#include "lib.h"
#include "misc.h"

View File

@ -1,6 +1,4 @@
#include <cassert>
#include <cstring>
#include <cstdio>
#include "precompiled.h"
#include "sdl.h"
#include "ogl.h"

View File

@ -17,6 +17,8 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "precompiled.h"
#include "lib.h"
#include "file.h"
#include "h_mgr.h"
@ -24,12 +26,6 @@
#include "detect.h"
#include "adts.h"
#include <cassert>
#include <vector>
#include <functional>
#include <algorithm>
// block := power-of-two sized chunk of a file.
// all transfers are expanded to naturally aligned, whole blocks
@ -110,7 +106,7 @@ int file_set_root_dir(const char* argv0, const char* root_dir)
static bool already_attempted;
if(already_attempted)
{
assert(0 && "vfs_set_root called more than once");
debug_warn("vfs_set_root called more than once");
return -1;
}
already_attempted = true;
@ -166,7 +162,7 @@ typedef DirEnts::iterator DirEntsIt;
static bool dirent_less(DirEnt& d1, DirEnt& d2)
{ return d1.name.compare(d2.name) < 0; }
int file_enum_dirents(const char* dir, DirEntCB cb, uintptr_t user)
int file_enum(const char* dir, FileCB cb, uintptr_t user)
{
char n_path[PATH_MAX+1];
n_path[PATH_MAX] = '\0';
@ -321,7 +317,7 @@ static int file_validate(const uint line, File* const f)
// failed somewhere - err is the error code,
// or -1 if not set specifically above.
debug_out("file_validate at line %d failed: %s\n", line, msg);
assert(0 && "file_validate failed");
debug_warn("file_validate failed");
return err;
}
@ -336,7 +332,7 @@ do\
while(0);
int file_open(const char* p_fn, int flags, File* f)
int file_open(const char* p_fn, uint flags, File* f)
{
memset(f, 0, sizeof(File));
@ -422,12 +418,12 @@ int ll_start_io(File* f, size_t ofs, size_t size, void* p, ll_cb* lcb)
if(size == 0)
{
assert(0 && "ll_start_io: size = 0 - why?");
debug_warn("ll_start_io: size = 0 - why?");
return ERR_INVALID_PARAM;
}
if(ofs >= f->size)
{
assert(0 && "ll_start_io: ofs beyond f->size");
debug_warn("ll_start_io: ofs beyond f->size");
return -1;
}
@ -537,7 +533,7 @@ static void* block_alloc(const u64 id)
for(size_t i = 0; i < num_blocks; i++)
{
if(c.grow(p) < 0)
assert(0 && "block_alloc: Cache::grow failed!");
debug_warn("block_alloc: Cache::grow failed!");
// currently can't fail.
p = (char*)p + BLOCK_SIZE;
}
@ -551,7 +547,7 @@ static void* block_alloc(const u64 id)
void* block = *entry;
if(c.lock(id, true) < 0)
assert(0 && "block_alloc: Cache::lock failed!");
debug_warn("block_alloc: Cache::lock failed!");
// can't happen: only cause is tag not found, but we successfully
// added it above. if it did fail, that'd be bad: we leak the block,
// and/or the buffer may be displaced while in use. hence, assert.
@ -747,7 +743,7 @@ static int io_free(Handle hio)
if(io->pending)
{
assert(0 && "io_free: IO pending");
debug_warn("io_free: IO pending");
return -1;
}
@ -783,7 +779,7 @@ struct FindBlock : public std::binary_function<Handle, u64, bool>
IO* io = (IO*)h_user_data(hio, H_IO);
if(!io)
{
assert(0 && "invalid handle in all_ios list!");
debug_warn("invalid handle in all_ios list!");
return false;
}
return io->block_id == block_id;
@ -823,12 +819,12 @@ Handle file_start_io(File* f, size_t user_ofs, size_t user_size, void* user_p)
if(user_size == 0)
{
assert(0 && "file_start_io: user_size = 0 - why?");
debug_warn("file_start_io: user_size = 0 - why?");
return ERR_INVALID_PARAM;
}
if(user_ofs >= f->size)
{
assert(0 && "file_start_io: user_ofs beyond f->size");
debug_warn("file_start_io: user_ofs beyond f->size");
return -1;
}
@ -1026,7 +1022,7 @@ debug_out("file_io fd=%d size=%d ofs=%d\n", f->fd, raw_size, raw_ofs);
// temp buffer OR supposed to be allocated here: invalid
if(!p || !*p)
{
assert(0 && "file_io: write to file from 0 buffer");
debug_warn("file_io: write to file from 0 buffer");
return ERR_INVALID_PARAM;
}
}

View File

@ -66,13 +66,13 @@ enum FILE_CB_FLAGS
extern int file_set_root_dir(const char* argv0, const char* root);
typedef int(*DirEntCB)(const char* name, uint flags, ssize_t size, uintptr_t user);
typedef int(*FileCB)(const char* name, uint flags, ssize_t size, uintptr_t user);
extern int file_enum_dirents(const char* dir, DirEntCB cb, uintptr_t user);
extern int file_enum(const char* dir, FileCB cb, uintptr_t user);
extern int file_stat(const char* path, struct stat*);
extern int file_open(const char* fn, int flags, File* f);
extern int file_open(const char* fn, uint flags, File* f);
extern int file_close(File* f);
extern int file_map(File* f, void*& p, size_t& size);

View File

@ -18,10 +18,7 @@
* http://www.stud.uni-karlsruhe.de/~urkt/
*/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "precompiled.h"
#include "lib.h"
#include "mem.h"

View File

@ -16,11 +16,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <climits>
#include "precompiled.h"
#include "lib.h"
#include "misc.h"
@ -377,17 +373,17 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
// verify type
if(!type)
{
assert(0 && "h_alloc: type param is 0");
debug_warn("h_alloc: type param is 0");
return 0;
}
if(type->user_size > HDATA_USER_SIZE)
{
assert(0 && "h_alloc: type's user data is too large for HDATA");
debug_warn("h_alloc: type's user data is too large for HDATA");
return 0;
}
if(type->name == 0)
{
assert(0 && "h_alloc: type's name field is 0");
debug_warn("h_alloc: type's name field is 0");
return 0;
}
@ -414,7 +410,7 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
hd = h_data(h, type);
if(hd->refs == REF_MAX)
{
assert(0 && "h_alloc: too many references to a handle - increase REF_BITS");
debug_warn("h_alloc: too many references to a handle - increase REF_BITS");
return 0;
}
hd->refs++;
@ -431,7 +427,7 @@ Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
static u32 tag;
if(++tag >= TAG_MASK)
{
assert(0 && "h_alloc: tag overflow - allocations are no longer unique."\
debug_warn("h_alloc: tag overflow - allocations are no longer unique."\
"may not notice stale handle reuse. increase TAG_BITS.");
tag = 1;
}
@ -485,7 +481,7 @@ int h_reload(const char* fn)
{
if(!fn)
{
assert(0 && "h_reload: fn = 0");
debug_warn("h_reload: fn = 0");
return ERR_INVALID_PARAM;
}

View File

@ -248,7 +248,7 @@ guide to defining and using resources
struct Res1
{
void* data1; // data loaded from file
int flags; // set when resource is created
uint flags; // set when resource is created
};
3) build its vtbl:

View File

@ -1,7 +1,6 @@
// malloc layer for less fragmentation, alignment, and automatic release
#include <cstdlib>
#include <cassert>
#include "precompiled.h"
#include "lib.h"
#include "types.h"
@ -71,7 +70,7 @@ static void* pool_alloc(const size_t size, const uint align, uintptr_t& ctx, MEM
if(ofs+size > POOL_CAP)
{
assert(0 && "pool_alloc: not enough memory in pool");
debug_warn("pool_alloc: not enough memory in pool");
return 0;
}
@ -102,7 +101,7 @@ static PtrToH& get_ptr_to_h()
if(!_ptr_to_h)
{
if(has_shutdown)
assert("mem.cpp: ptr -> handle lookup used after module shutdown");
debug_warn("mem.cpp: ptr -> handle lookup used after module shutdown");
// crash + burn
_ptr_to_h = new PtrToH;
@ -131,7 +130,7 @@ static Handle remove_alloc(void* p)
PtrToH::iterator it = ptr_to_h.find(p);
if(it == ptr_to_h.end())
{
assert("remove_alloc: pointer not in map");
debug_warn("remove_alloc: pointer not in map");
return 0;
}
@ -213,7 +212,7 @@ Handle mem_assign(void* p, size_t size, uint flags /* = 0 */, MEM_DTOR dtor /* =
if(!p || !size)
{
assert(0 && "mem_assign: invalid p or size");
debug_warn("mem_assign: invalid p or size");
return 0;
}
@ -240,7 +239,7 @@ void* mem_alloc(size_t size, const uint align, uint flags, Handle* phm)
if(size == 0)
{
assert(0 && "mem_alloc: why is size = 0?");
debug_warn("mem_alloc: why is size = 0?");
size = 1;
}

View File

@ -0,0 +1 @@
#include "precompiled.h"

View File

@ -18,11 +18,7 @@
// supported formats: DDS, TGA, PNG, JP2, BMP, RAW
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include "precompiled.h"
#include "lib.h"
#include "vfs.h"
@ -491,7 +487,8 @@ static inline bool png_valid(const u8* ptr, size_t size)
// requirement: direct color
static int png_load(const char* fn, const u8* ptr, size_t size, Tex* t)
{
const char* err = 0;
const char* msg = 0;
int err = -1;
// allocate PNG structures
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
@ -500,19 +497,22 @@ static int png_load(const char* fn, const u8* ptr, size_t size, Tex* t)
png_infop info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr)
{
png_destroy_read_struct(&png_ptr, 0, 0);
return ERR_NO_MEM;
err = ERR_NO_MEM;
goto fail;
}
// setup error handling
if(setjmp(png_jmpbuf(png_ptr)))
{
fail:
debug_out("png_load: %s: %s\n", fn, err? err : "");
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return -1;
debug_out("png_load: %s: %s\n", fn, msg? msg : "unknown");
goto ret;
}
u8** rows;
{
MemRange mr = { ptr, size };
png_set_read_fn(png_ptr, &mr, png_read_fn);
@ -529,15 +529,17 @@ fail:
const u32 ofs = 0; // libpng returns decoded image data; no header
if(prec != 8)
err = "channel precision != 8 bits";
msg = "channel precision != 8 bits";
if(fmt == ~0)
err = "color type is invalid (must be direct color)";
if(err)
msg = "color type is invalid (must be direct color)";
if(msg)
{
err = -1;
goto fail;
}
// allocate mem for image - rows point into buffer (sequential)
// .. (rows is freed in png_destroy_read_struct)
u8** rows = (u8**)png_malloc(png_ptr, (h+1)*sizeof(void*));
rows = (u8**)malloc((h+1)*sizeof(void*));
if(!rows)
goto fail;
size_t img_size = pitch * (h+1);
@ -554,8 +556,8 @@ fail:
png_read_image(png_ptr, rows);
png_read_end(png_ptr, 0);
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
png_read_end(png_ptr, info_ptr);
mem_free_h(t->hm);
@ -566,7 +568,16 @@ fail:
t->ofs = ofs;
t->hm = img_hm;
return 0;
err = 0;
}
// shared cleanup
ret:
free(rows);
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
return err;
}
#endif
@ -765,7 +776,7 @@ int tex_bind(const Handle h)
#ifndef NDEBUG
if(!t->id)
{
assert(0 && "tex_bind: Tex.id is not a valid texture");
debug_warn("tex_bind: Tex.id is not a valid texture");
return -1;
}
#endif
@ -842,7 +853,7 @@ int tex_upload(const Handle ht, int filter, int int_fmt)
assert(0);
}
debug_out("tex_upload: %s: %s\n", fn, err);
assert(0 && "tex_upload failed");
debug_warn("tex_upload failed");
return -1;
}

View File

@ -17,10 +17,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include "precompiled.h"
#include "lib.h"
#include "file.h"
@ -30,12 +27,6 @@
#include "mem.h"
#include "adts.h"
#include <string>
#include <vector>
#include <stack>
#include <map>
#include <list>
#include <algorithm>
// currently not thread safe, but that will most likely change
// (if prefetch thread is to be used).
@ -160,7 +151,7 @@ static int path_validate(const uint line, const char* const path)
// or -1 if not set specifically above.
fail:
debug_out("path_validate at line %d failed: %s", err);
assert(0 && "path_validate failed");
debug_warn("path_validate failed");
return err;
ok:
@ -173,97 +164,49 @@ ok:
///////////////////////////////////////////////////////////////////////////////
//
// file location
// "file system" (tree structure; stores location of each file)
//
///////////////////////////////////////////////////////////////////////////////
// the VFS stores the location (archive or directory) of each file;
// this allows multiple search paths without having to check each one
// when opening a file (slow).
//
// one Loc is allocated for each archive or directory mounted, and all
// real subdirectories; all files in an archive share the same location.
// one Loc is allocated for each archive or directory mounted.
// therefore, files only /point/ to a (possibly shared) Loc.
// if a file's location changes (e.g. after mounting a higher-priority
// directory), the VFS entry will point to the new Loc; the priority
// of both locations is unchanged.
//
// allocate via loc_create, passing the location. do not free!
// allocate via mnt_create, passing the location. do not free!
// we keep track of all Locs allocated; they are freed at exit,
// and by loc_free_all (useful when rebuilding the VFS).
// and by mnt_free_all (useful when rebuilding the VFS).
// this is much easier and safer than walking the VFS tree and
// freeing every location we find.
struct Loc;
typedef std::vector<Loc*> Locs;
// not many instances and allocated via new =>
// don't worry about struct size / alignment.
// not many instances => don't worry about struct size / alignment.
struct Loc
{
Handle ha;
Handle archive;
std::string path;
std::string dir;
uint pri;
Loc(Handle _ha, const char* _path, uint _pri)
: ha(_ha), path(_path), pri(_pri)
{
ONCE(atexit2(loc_free_all));
// add to list for later deletion
locs.push_back(this);
}
friend int loc_free_all();
private:
static Locs locs;
Loc() {}
Loc(Handle _archive, const char* _dir, uint _pri)
: archive(_archive), dir(_dir), pri(_pri) {}
};
Locs Loc::locs;
static inline void loc_free(Loc* const loc)
{ delete loc; }
static int loc_free_all()
{
// we don't expect many Locs to be added (one per loose-file dir
// or archive), so don't worry about reallocating memory.
// return value is also irrelevant - can't fail as currently implemented.
Locs& locs = Loc::locs;
std::for_each(locs.begin(), locs.end(), loc_free);
// could use smart ptr (boost or loki) instead, but this'll do
locs.clear();
return 0;
}
// wrapper on top of new + ctor to emphasize that
// the caller must not free the Loc pointer.
// (if they do, VFS entries point to freed memory => disaster)
static Loc* loc_create(const Handle ha, const char* const path, const uint pri)
{
return new Loc(ha, path, pri);
}
///////////////////////////////////////////////////////////////////////////////
//
// "file system" (tree structure; stores location of each file)
//
///////////////////////////////////////////////////////////////////////////////
struct VDir;
typedef std::map<std::string, VDir> SubDirs;
typedef std::map<std::string, VDir*> SubDirs;
typedef SubDirs::iterator SubDirIt;
typedef std::map<std::string, Loc*> Files;
@ -317,20 +260,21 @@ struct VDir
return it->second;
}
VDir* subdir_add(const char* fn, VDir& _dir)
VDir* subdir_add(const char* name)
{
std::string _fn(fn);
_dir.v_name = _fn;
VDir* vdir = new VDir;
std::string _name(name);
vdir->v_name = _name;
std::pair<std::string, VDir> item = std::make_pair(_fn, _dir);
std::pair<std::string, VDir*> item = std::make_pair(_name, vdir);
std::pair<SubDirIt, bool> res;
res = subdirs.insert(item);
// already in container
if(!res.second)
assert(0 && "already in subdir");
debug_warn("already in subdir");
SubDirIt it = res.first;
return &it->second;
return it->second;
}
VDir* subdir_find(const char* fn)
@ -339,40 +283,31 @@ struct VDir
SubDirIt it = subdirs.find(_fn);
if(it == subdirs.end())
return 0;
return &it->second;
return it->second;
}
void clear_tree()
{
SubDirIt it;
for(it = subdirs.begin(); it != subdirs.end(); ++it)
{
VDir& dir = it->second;
dir.clear_tree();
}
files.clear();
subdirs.clear();
}
friend void tree_clearR(VDir*);
SubDirs subdirs; // can't make private; needed for iterator
private:
Files files;
private:;
};
VDir vfs_root;
static VDir vfs_root;
enum LookupFlags
{
PF_DEFAULT,
LF_DEFAULT,
LF_CREATE_MISSING_COMPONENTS = 1
};
static int tree_lookup(const char* vfs_path, Loc** loc = 0, VDir** dir = 0, LookupFlags flags = PF_DEFAULT)
static int tree_lookup(const char* vfs_path, Loc** loc = 0, VDir** dir = 0, LookupFlags flags = LF_DEFAULT)
{
CHECK_PATH(vfs_path);
@ -419,10 +354,7 @@ static int tree_lookup(const char* vfs_path, Loc** loc = 0, VDir** dir = 0, Look
if(!subdir)
{
if(create_missing_components)
{
VDir _dir;
subdir = cur_dir->subdir_add(subdir_name, _dir);
}
subdir = cur_dir->subdir_add(subdir_name);
else
return ERR_PATH_NOT_FOUND;
}
@ -434,24 +366,24 @@ static int tree_lookup(const char* vfs_path, Loc** loc = 0, VDir** dir = 0, Look
}
static void tree_clearR(VDir* const dir)
{
SubDirIt it;
for(it = dir->subdirs.begin(); it != dir->subdirs.end(); ++it)
{
VDir* subdir = it->second;
tree_clearR(subdir);
}
dir->files.clear();
dir->subdirs.clear();
}
typedef std::vector<Handle> Archives;
typedef Archives::iterator ArchiveIt;
static inline void tree_clear()
{
tree_clearR(&vfs_root);
}
@ -464,13 +396,13 @@ struct FileCBParams
{
VDir* dir;
Loc* loc;
};
// somewhat of a hack. which archives are mounted into the VFS is stored
// in an Archives list in the Mount struct; they don't have anything to
// do with a VFS dir. we want to enumerate the archives in a dir via the
// normal populate(), though, so have to pass this to its callback.
Archives* archives;
};
// called for each OS dir ent.
@ -484,109 +416,62 @@ struct FileCBParams
// to try to open it as an archive - not good.
// this restriction also simplifies the code a bit, but if it's a problem,
// just generate a list of archives here and mount them from the caller.
static int file_cb(const char* fn, uint flags, ssize_t size, uintptr_t user)
static int add_dirent_cb(const char* fn, uint flags, ssize_t size, uintptr_t user)
{
FileCBParams* params = (FileCBParams*)user;
VDir* cur_dir = params->dir;
Loc* cur_loc = params->loc;
Archives* archives = params->archives;
// directory
if(flags & LOC_DIR)
{
VDir _dir;
cur_dir->subdir_add(fn, _dir);
}
cur_dir->subdir_add(fn);
// file
else
{
// only add to list; don't enumerate its files yet for easier debugging
// (we see which files are in a dir / archives)
// also somewhat faster, due to better locality.
//
// don't check filename extension - archives won't necessarily
// be called .zip (example: Quake III .pk3).
// just try to open the file.
if(archives)
{
const Handle ha = zip_archive_open(fn);
if(ha > 0)
archives->push_back(ha);
}
cur_dir->file_add(fn, cur_loc->pri, cur_loc);
}
return 0;
}
static int vdir_add_from_archive(VDir* dir, const Handle ha, const uint pri, Archives* archives)
{
// all files in the archive share this location
Loc* loc = loc_create(ha, 0, pri-1);
// add all files in archive to the VFS dir
FileCBParams params = { dir, loc, archives };
CHECK_ERR(zip_enum_files(ha, file_cb, (uintptr_t)&params));
return 0;
}
static int addR(VDir* vdir, const char* path, Loc* loc, const uint pri, Archives* archives)
static int tree_add_dirR(VDir* vdir, const char* dir, Loc* loc)
{
// add watch
if(!vdir->watch)
vdir->watch = 0;
// add files and subdirs to dir; gather list of all archives
FileCBParams params = { vdir, loc, archives };
file_enum_dirents(path, file_cb, (uintptr_t)&params);
// loc will now be used for files in Zip archives
loc->pri--;
// loc->path = 0;
// add files and subdirs to dir
FileCBParams params = { vdir, loc };
file_enum(dir, add_dirent_cb, (uintptr_t)&params);
for(SubDirIt it = vdir->subdirs.begin(); it != vdir->subdirs.end(); ++it)
{
VDir* subdir = &it->second;
VDir* subdir = it->second;
char v_subdir_path[PATH_MAX];
const char* v_subdir_name_c = subdir->v_name.c_str();
CHECK_ERR(path_append(v_subdir_path, path, v_subdir_name_c));
CHECK_ERR(path_append(v_subdir_path, dir, v_subdir_name_c));
addR(subdir, v_subdir_path, loc, pri, archives);
tree_add_dirR(subdir, v_subdir_path, loc);
}
// for each archive:
// (already sorted due to file_enum_dirents)
/*
{
for(ArchiveIt it = archives->begin(); it != archives->end(); ++it)
{
const Handle ha = *it;
CHECK_ERR(vdir_add_from_archive(vdir, ha, pri, archives));
}
}
*/
return 0;
}
// parent param not reference to allow passing 0 root node?
static int vdir_add_from_dir(VDir* vdir, const char* path, const uint pri, Archives* archives)
static int tree_add_loc(VDir* vdir, Loc* loc)
{
// all loose files in the new dir and its subdirs share this location
Loc* loc = loc_create(0, path, pri+1);
const char* dir = loc->dir.c_str();
return addR(vdir, path, loc, pri, archives);
FileCBParams params = { vdir, loc };
if(loc->archive > 0)
return zip_enum(loc->archive, add_dirent_cb, (uintptr_t)&params);
else
{
CHECK_PATH(dir);
return tree_add_dirR(vdir, dir, loc);
}
}
///////////////////////////////////////////////////////////////////////////////
@ -596,114 +481,144 @@ static int vdir_add_from_dir(VDir* vdir, const char* path, const uint pri, Archi
///////////////////////////////////////////////////////////////////////////////
// need a list of all mounted dirs or archives so we can vfs_reload at
// any time. it's also nice, but not necessary, to unmount at exit
// (so resources aren't reported as leaked).
typedef std::vector<Loc> Locs;
typedef Locs::iterator LocIt;
struct Mount
{
std::string vfs_path;
std::string name; // of OS dir or archive being mounted
std::string vfs_mount_point;
std::string name;
uint pri;
Archives archives;
Loc loc;
Locs archive_locs;
Mount(const char* _vfs_path, const char* _name, uint _pri)
: vfs_path(_vfs_path), name(_name), pri(_pri), archives() {}
Mount() {}
Mount(const char* _vfs_mount_point, const char* _name, uint _pri)
: vfs_mount_point(_vfs_mount_point), name(_name), pri(_pri) {}
};
typedef std::list<Mount> Mounts;
typedef std::vector<Mount> Mounts;
typedef Mounts::iterator MountIt;
static Mounts mounts;
// called for each OS dir ent.
// add each archive to list.
static int archive_cb(const char* fn, uint flags, ssize_t size, uintptr_t user)
{
Locs* archive_locs = (Locs*)user;
// only add to list; don't enumerate its files yet for easier debugging
// (we see which files are in a dir / archives)
// also somewhat faster, due to better locality.
//
// don't check filename extension - archives won't necessarily
// be called .zip (example: Quake III .pk3).
// just try to open the file.
const Handle archive = zip_archive_open(fn);
if(archive > 0)
archive_locs->push_back(Loc(archive, "", 0));
/// HACK HACK HACK pass along pri
// tree_add_loc them here?
return 0;
}
// actually mount the specified entry (either Zip archive or dir).
// split out of vfs_mount because we need to mount without changing the
// mount list, when invalidating (reloading) the VFS.
static int remount(Mount& m)
{
const char* vfs_path = m.vfs_path.c_str();
int err;
const char* vfs_mount_point = m.vfs_mount_point.c_str();
const char* name = m.name.c_str();
const uint pri = m.pri;
CHECK_PATH(name);
VDir* vdir;
CHECK_ERR(tree_lookup(vfs_path, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
CHECK_ERR(tree_lookup(vfs_mount_point, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
int err;
// check if target is a single Zip archive
// order doesn't matter; can't have both an archive and dir
// add files and subdirectories to the VFS dir
err = vdir_add_from_dir(vdir, name, pri, &m.archives);
// success
// if(err == 0)
return 0;
const Handle archive = zip_archive_open(name);
if(archive > 0)
{
m.archive_locs.push_back(Loc(archive, "", pri));
LocIt it = m.archive_locs.end();
Loc* loc = &*(--it);
return tree_add_loc(vdir, loc);
}
const Handle ha = zip_archive_open(name);
err = vdir_add_from_archive(vdir, ha, pri, &m.archives);
if(err == 0)
return 0;
m.loc.dir.assign(m.name);
err = tree_add_loc(vdir, &m.loc);
if(err < 0)
err = err;
return ERR_PATH_NOT_FOUND;
// enumerate all archives
return file_enum(name, archive_cb, (uintptr_t)&m.archive_locs);
}
static int unmount(Mount& m)
{
std::for_each(m.archives.begin(), m.archives.end(), zip_archive_close);
for(LocIt it = m.archive_locs.begin(); it != m.archive_locs.end(); ++it)
{
Loc& loc = *it;
zip_archive_close(loc.archive);
}
m.archive_locs.clear();
return 0;
}
static void unmount_all(void)
{
std::for_each(mounts.begin(), mounts.end(), unmount);
}
{ std::for_each(mounts.begin(), mounts.end(), unmount); }
static void remount_all()
{ std::for_each(mounts.begin(), mounts.end(), remount); }
int vfs_mount(const char* const vfs_path, const char* const name, const uint pri)
int vfs_mount(const char* const vfs_mount_point, const char* const name, const uint pri)
{
ONCE(atexit(unmount_all));
MountIt it;
// make sure it's not already mounted, i.e. in mounts
{
for(MountIt it = mounts.begin(); it != mounts.end(); ++it)
for(it = mounts.begin(); it != mounts.end(); ++it)
if(it->name == name)
{
assert(0 && "vfs_mount: already mounted");
debug_warn("vfs_mount: already mounted");
return -1;
}
}
mounts.push_back(Mount(vfs_path, name, pri));
mounts.push_back(Mount(vfs_mount_point, name, pri));
// actually mount the entry
MountIt it = mounts.end();
it = mounts.end();
Mount& m = *(--it);
return remount(m);
}
// eventually returns the first error that occurred; does not abort.
int vfs_rebuild()
{
int err = 0;
tree_clear();
vfs_root.clear_tree();
loc_free_all();
// need error return. manual loop is easier than functor + for_each.
for(MountIt it = mounts.begin(); it != mounts.end(); ++it)
{
int ret = remount(*it);
if(err == 0)
err = ret;
}
return err;
unmount_all();
remount_all();
return 0;
}
@ -713,19 +628,19 @@ int vfs_unmount(const char* name)
// found the corresponding entry
if(it->name == name)
{
int unmount_err = unmount(*it);
Mount& m = *it;
unmount(m);
mounts.erase(it);
int rebuild_err = vfs_rebuild();
return (unmount_err < 0)? unmount_err : rebuild_err;
return vfs_rebuild();
}
return ERR_PATH_NOT_FOUND;
}
///////////////////////////////////////////////////////////////////////////////
//
//
@ -746,17 +661,17 @@ int vfs_realpath(const char* fn, char* full_path)
Loc* loc;
CHECK_ERR(tree_lookup(fn, &loc));
if(loc->ha <= 0)
if(loc->archive > 0)
{
strncpy(full_path, loc->path.c_str(), PATH_MAX);
}
else
{
const char* archive_fn = h_filename(loc->ha);
const char* archive_fn = h_filename(loc->archive);
if(!archive_fn)
return -1;
strncpy(full_path, archive_fn, PATH_MAX);
}
else
{
strncpy(full_path, loc->dir.c_str(), PATH_MAX);
}
return 0;
}
@ -767,10 +682,13 @@ int vfs_stat(const char* fn, struct stat* s)
Loc* loc;
CHECK_ERR(tree_lookup(fn, &loc));
if(loc->ha <= 0)
return stat(loc->path.c_str(), s);
if(loc->archive > 0)
return zip_stat(loc->archive, fn, s);
else
return zip_stat(loc->ha, fn, s);
{
const char* dir = loc->dir.c_str();
return file_stat(dir, s);
}
}
@ -871,31 +789,22 @@ static int VFile_reload(VFile* vf, const char* fn)
Loc* loc;
CHECK_ERR(tree_lookup(fn, &loc));
if(loc->ha <= 0)
if(loc->archive <= 0)
{
const char* path;
char buf[PATH_MAX+1];
// (it's in the VFS root dir)
if(loc->path[0] == '\0')
path = fn;
else
{
const char* loc_path = loc->path.c_str();
CHECK_ERR(path_append(buf, loc_path, fn));
path = buf;
}
char path[PATH_MAX];
const char* dir = loc->dir.c_str();
CHECK_ERR(path_append(path, dir, fn));
CHECK_ERR(file_open(path, vf_flags(vf), &vf->f));
}
else
{
if(flags & VFS_WRITE)
{
assert(0 && "requesting write access to file in archive");
debug_warn("requesting write access to file in archive");
return -1;
}
CHECK_ERR(zip_open(loc->ha, fn, &vf->zf));
CHECK_ERR(zip_open(loc->archive, fn, &vf->zf));
flags |= VF_ZIP;
}
@ -907,7 +816,7 @@ static int VFile_reload(VFile* vf, const char* fn)
}
Handle vfs_open(const char* fn, int flags /* = 0 */)
Handle vfs_open(const char* fn, uint flags /* = 0 */)
{
Handle h = h_alloc(H_VFile, fn, 0, flags);
// pass file flags to init
@ -966,7 +875,7 @@ debug_out("vfs_load fn=%s\n", fn);
goto skip_read;
}
else
assert(0 && "vfs_load: invalid MEM attached to vfile (0 pointer)");
debug_warn("vfs_load: invalid MEM attached to vfile (0 pointer)");
// happens if someone frees the pointer. not an error!
}
@ -1003,7 +912,7 @@ int vfs_store(const char* fn, void* p, size_t size)
Handle vfs_map(const char* fn, int flags, void*& p, size_t& size)
Handle vfs_map(const char* fn, uint flags, void*& p, size_t& size)
{
Handle hf = vfs_open(fn, flags);
H_DEREF(hf, VFile, vf);

View File

@ -25,7 +25,7 @@
#define VFS_MAX_PATH 256 // includes trailing '\0'
extern int vfs_mount(const char* vfs_path, const char* name, uint pri);
extern int vfs_mount(const char* vfs_mount_point, const char* name, uint pri);
extern int vfs_umount(const char* name);
extern int vfs_stat(const char* fn, struct stat*);
@ -33,10 +33,10 @@ extern int vfs_realpath(const char* fn, char* realpath);
extern Handle vfs_load(const char* fn, void*& p, size_t& size);
extern Handle vfs_open(const char* fn, int flags = 0);
extern Handle vfs_open(const char* fn, uint flags = 0);
extern int vfs_close(Handle& h);
extern Handle vfs_map(Handle hf, int flags, void*& p, size_t& size);
extern Handle vfs_map(Handle hf, uint flags, void*& p, size_t& size);

View File

@ -16,9 +16,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cassert>
#include <cstring>
#include <cstdlib>
#include "precompiled.h"
#include "lib.h"
#include "res.h"
@ -68,7 +66,7 @@ static int zip_find_ecdr(const void* const file, const size_t size, const u8*& e
if(size < ECDR_SIZE)
{
assert(0 && "zip_find_ecdr: size is way too small");
debug_warn("zip_find_ecdr: size is way too small");
return -1;
}
const u8* ecdr = (const u8*)file + size - ECDR_SIZE;
@ -118,7 +116,7 @@ static int zip_verify_lfh(const void* const file, const size_t lfh_ofs, const si
if(*(u32*)lfh != *(u32*)lfh_id)
{
assert(0 && "LFH corrupt! (signature doesn't match)");
debug_warn("LFH corrupt! (signature doesn't match)");
return -1;
}
@ -129,7 +127,7 @@ static int zip_verify_lfh(const void* const file, const size_t lfh_ofs, const si
if(file_ofs != lfh_file_ofs)
{
assert(0 && "warning: CDFH and LFH data differ! normal builds will"\
debug_warn("warning: CDFH and LFH data differ! normal builds will"\
"return incorrect file offsets. check Zip file!");
return -1;
}
@ -149,7 +147,7 @@ static int zip_read_cdfh(const u8*& cdfh, const char*& fn, size_t& fn_len, ZFile
if(*(u32*)cdfh != *(u32*)cdfh_id)
{
assert(0 && "CDFH corrupt! (signature doesn't match)");
debug_warn("CDFH corrupt! (signature doesn't match)");
goto skip_file;
}
@ -167,7 +165,7 @@ static int zip_read_cdfh(const u8*& cdfh, const char*& fn, size_t& fn_len, ZFile
// compression method: neither deflated nor stored
if(method & ~8)
{
assert(0 && "warning: unknown compression method");
debug_warn("warning: unknown compression method");
goto skip_file;
}
@ -443,7 +441,7 @@ static int lookup_get_file_info(LookupInfo* const li, const i32 idx, const char*
{
if(idx < 0 || idx >= li->num_files-1)
{
assert(0 && "lookup_get_file_info: index out of bounds");
debug_warn("lookup_get_file_info: index out of bounds");
return -1;
}
@ -557,7 +555,7 @@ int zip_archive_close(Handle& ha)
// would be nice to pass along a key (allowing for O(1) lookup in archive),
// but then the callback is no longer compatible to file / vfs enum files.
int zip_enum_files(const Handle ha, const ZipFileCB cb, const uintptr_t user)
int zip_enum(const Handle ha, const ZipFileCB cb, const uintptr_t user)
{
H_DEREF(ha, ZArchive, za);
@ -592,7 +590,7 @@ int inf_start_read(uintptr_t ctx, void* out, size_t out_size)
if(stream->next_out || stream->avail_out)
{
assert(0 && "zip_start_read: ctx already in use!");
debug_warn("zip_start_read: ctx already in use!");
return -1;
}
stream->next_out = (Byte*)out;
@ -636,7 +634,7 @@ int inf_finish_read(uintptr_t ctx)
if(stream->avail_in || stream->avail_out)
{
assert("zip_finish_read: input or input buffer has space remaining");
debug_warn("zip_finish_read: input or input buffer has space remaining");
stream->avail_in = stream->avail_out = 0;
return -1;
}
@ -703,7 +701,7 @@ static int zfile_validate(uint line, ZFile* zf)
// failed somewhere - err is the error code,
// or -1 if not set specifically above.
debug_out("zfile_validate at line %d failed: %s\n", line, msg);
assert(0 && "zfile_validate failed");
debug_warn("zfile_validate failed");
return err;
}
@ -841,7 +839,7 @@ ssize_t zip_read(ZFile* zf, size_t raw_ofs, size_t size, void*& p)
// problem: partial reads
if(raw_ofs != zf->last_raw_ofs)
{
assert(0 && "zip_read: compressed read offset is non-continuous");
debug_warn("zip_read: compressed read offset is non-continuous");
return -1;
}
@ -893,7 +891,7 @@ int zip_map(ZFile* zf, void*& p, size_t& size)
// doesn't really make sense to map compressed files, so disallow it.
if(is_compressed(zf))
{
assert(0 && "mapping a compressed file from archive. why?");
debug_warn("mapping a compressed file from archive. why?");
return -1;
}

View File

@ -57,7 +57,7 @@ enum ZIP_CB_FLAGS
};
typedef int(*ZipFileCB)(const char* const fn, const uint flags, const ssize_t size, const uintptr_t user);
extern int zip_enum_files(const Handle ha, const ZipFileCB cb, const uintptr_t user);
extern int zip_enum(const Handle ha, const ZipFileCB cb, const uintptr_t user);
//
// file

View File

@ -15,17 +15,10 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "precompiled.h"
#ifdef _M_IX86
#include <cstring>
#include <cstdio> // sscanf
#include <cmath>
#include <cassert>
#include <time.h>
#include <vector>
#include <algorithm>
#include "ia32.h"
#include "lib.h"
#include "detect.h"

View File

@ -1,6 +1,4 @@
#include <stdio.h>
#include <stdarg.h>
#include <wchar.h>
#include "precompiled.h"
#include "sysdep.h"

View File

@ -15,11 +15,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cmath>
#include <cassert>
#include <cstdlib>
#include <numeric>
#include "precompiled.h"
#include "hrt.h"
#include "lib.h"
@ -171,7 +167,7 @@ static void choose_impl()
}
// no warning here - doesn't inspire confidence in VC dead code removal.
assert(0 && "hrt_choose_impl: no safe timer found!");
debug_warn("hrt_choose_impl: no safe timer found!");
hrt_impl = HRT_NONE;
hrt_nominal_freq = -1;
return;
@ -214,7 +210,7 @@ static i64 ticks_lk()
// add further timers here.
default:
assert(0 && "hrt_ticks: invalid impl");
debug_warn("hrt_ticks: invalid impl");
// fall through
case HRT_NONE:
@ -375,7 +371,7 @@ int hrt_override_impl(HRTOverride ovr, HRTImpl impl)
if((ovr != HRT_DISABLE && ovr != HRT_FORCE && ovr != HRT_DEFAULT) ||
(impl != HRT_TSC && impl != HRT_QPC && impl != HRT_TGT && impl != HRT_NONE))
{
assert(0 && "hrt_override: invalid ovr or impl param");
debug_warn("hrt_override: invalid ovr or impl param");
return -1;
}

View File

@ -16,9 +16,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cassert>
#include <cstdlib>
#include <cstdio>
#include "precompiled.h"
#include <io.h>
@ -128,12 +126,12 @@ int aio_h_set(int fd, HANDLE h)
{
if(aio_hs[fd] != INVALID_HANDLE_VALUE)
{
assert("AioHandles::set: handle already set!");
debug_warn("AioHandles::set: handle already set!");
goto fail;
}
if(!is_valid_file_handle(h))
{
assert("AioHandles::set: setting invalid handle");
debug_warn("AioHandles::set: setting invalid handle");
goto fail;
}
}
@ -145,7 +143,7 @@ int aio_h_set(int fd, HANDLE h)
fail:
win_unlock(WAIO_CS);
assert(0 && "aio_h_set failed");
debug_warn("aio_h_set failed");
return -1;
}
@ -307,14 +305,14 @@ int aio_assign_handle(uintptr_t handle)
HANDLE h = CreateEvent(0,0,0,0);
if(h == INVALID_HANDLE_VALUE)
{
assert(0 && "aio_assign_handle failed");
debug_warn("aio_assign_handle failed");
return -1;
}
int fd = _open_osfhandle((intptr_t)h, 0);
if(fd < 0)
{
assert(0 && "aio_assign_handle failed");
debug_warn("aio_assign_handle failed");
return fd;
}
@ -347,13 +345,13 @@ WIN_ONCE(init()); // TODO: need to do this elsewhere in case other routines call
HANDLE h = CreateFile(fn, access, share, 0, create, flags, 0);
if(h == INVALID_HANDLE_VALUE)
{
assert(0 && "aio_open failed");
debug_warn("aio_open failed");
return -1;
}
if(aio_h_set(fd, h) < 0)
{
assert(0 && "aio_open failed");
debug_warn("aio_open failed");
CloseHandle(h);
return -1;
}
@ -368,7 +366,7 @@ int aio_close(int fd)
HANDLE h = aio_h_get(fd);
if(h == INVALID_HANDLE_VALUE) // out of bounds or already closed
{
assert(0 && "aio_close failed");
debug_warn("aio_close failed");
return -1;
}
@ -407,21 +405,21 @@ debug_out("aio_rw cb=%p\n", cb);
HANDLE h = aio_h_get(cb->aio_fildes);
if(h == INVALID_HANDLE_VALUE)
{
assert(0 && "aio_rw: associated handle is invalid");
debug_warn("aio_rw: associated handle is invalid");
return -EINVAL;
}
if(cb->req_)
{
// SUSv3 says this has undefined results; we fail the attempt.
assert(0 && "aio_rw: aiocb is already in use");
debug_warn("aio_rw: aiocb is already in use");
return -1;
}
Req* r = req_alloc(cb);
if(!r)
{
assert(0 && "aio_rw: cannot allocate a Req (too many concurrent IOs)");
debug_warn("aio_rw: cannot allocate a Req (too many concurrent IOs)");
return -1;
}

View File

@ -16,8 +16,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <stdio.h>
#include <stdlib.h>
#include "precompiled.h"
#include "detect.h"
#include "lib.h"
@ -31,8 +30,8 @@
#endif
// EnumDisplayDevices (used in get_monitor_size and win_get_gfx_card)
// is not available on Win95 or NT. try to import it manually here.
// 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()
@ -68,113 +67,15 @@ int get_cur_resolution(int& xres, int& yres)
// useful for determining aspect ratio. not called by detect().
// if we fail, outputs are unchanged (assumed initialized to defaults)
int get_monitor_size(int& width_cm, int& height_cm)
int get_monitor_size(int& width_mm, int& height_mm)
{
DISPLAY_DEVICE adapter = { sizeof(DISPLAY_DEVICE) };
DISPLAY_DEVICE monitor = { sizeof(DISPLAY_DEVICE) };
// need to be distinct (EnumDisplayDevices requirement)
HDC dc = GetDC(0); // dc for entire screen
LONG err;
char key_name[256];
DWORD key_name_len;
DWORD key_type;
width_mm = GetDeviceCaps(dc, HORZSIZE);
height_mm = GetDeviceCaps(dc, VERTSIZE);
bool found = false;
// make sure EnumDisplayDevices is available (as pEnumDisplayDevicesA)
CHECK_ERR(import_EnumDisplayDevices());
HKEY hkDisplay;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\Display", 0, KEY_READ, &hkDisplay) != 0)
return -1;
// we only look at the first monitor of the first display adapter
// attached to the desktop, assumed to be the primary monitor.
// for each display adapter
for(int adapter_idx = 0; !found; adapter_idx++)
{
// get display adapter
if(!pEnumDisplayDevicesA(0, adapter_idx, &adapter, 0))
break;
if(!(adapter.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
continue;
// get its associated monitor;
// will search for its DeviceID in the registry
if(!pEnumDisplayDevicesA(adapter.DeviceName, 0, &monitor, 0))
continue;
// for each class in registry
for(int class_idx = 0; !found; class_idx++)
{
// open next key
HKEY hkClass;
key_name_len = sizeof(key_name);
if(RegEnumKeyEx(hkDisplay, class_idx, key_name, &key_name_len, 0, 0, 0, 0) != 0)
break;
if(RegOpenKeyEx(hkDisplay, key_name, 0, KEY_READ, &hkClass) != 0)
break;
// for each device in registry
for(int dev_idx = 0; !found; dev_idx++)
{
// open next key
HKEY hkDev;
key_name_len = sizeof(key_name);
if(RegEnumKeyEx(hkClass, dev_idx, key_name, &key_name_len, 0, 0, 0, 0) != 0)
break;
if(RegOpenKeyEx(hkClass, key_name, 0, KEY_READ, &hkDev) != 0)
break;
// build dev_id: (%s\\%s, HardwareID, Driver)
// example: "Monitor\NEC6604\{4D36E96E-E325-11CE-BFC1-08002BE10318}\0001"
// will compare this against monitor.DeviceID
char dev_id[256];
DWORD dev_id_len = sizeof(dev_id);
err = RegQueryValueEx(hkDev, "HardwareID", 0, &key_type, (BYTE*)dev_id, &dev_id_len);
if(err != 0 || (key_type != REG_MULTI_SZ && key_type != REG_SZ))
goto skip_dev;
char* p = (char*)dev_id + strlen((const char*)dev_id);
*p++ = '\\';
dev_id_len = sizeof(dev_id) - dev_id_len;
err = RegQueryValueEx(hkDev, "Driver", 0, &key_type, (BYTE*)p, &dev_id_len);
if(err != 0 || (key_type != REG_MULTI_SZ && key_type != REG_SZ))
goto skip_dev;
// this (hkDev) is not the monitor you're looking for..
if(strcmp(monitor.DeviceID, (const char*)dev_id) != 0)
goto skip_dev;
HKEY hkDevParams;
if(RegOpenKeyEx(hkDev, "Device Parameters", 0, KEY_READ, &hkDevParams) != 0)
goto skip_dev;
// read EDID
BYTE edid[256];
DWORD edid_len = sizeof(edid);
if(RegQueryValueEx(hkDevParams, "EDID", 0, &key_type, edid, &edid_len) == 0)
{
width_cm = edid[21];
height_cm = edid[22];
found = true;
// break out of all loops; all keys will be closed
}
RegCloseKey(hkDevParams);
skip_dev:
RegCloseKey(hkDev);
}
RegCloseKey(hkClass);
}
}
RegCloseKey(hkDisplay);
return found? 0 : -1;
ReleaseDC(0, dc);
return 0;
}
@ -184,8 +85,7 @@ int win_get_gfx_card()
if(import_EnumDisplayDevices() < 0)
return -1;
DISPLAY_DEVICEA dev;
dev.cb = sizeof(dev);
DISPLAY_DEVICEA dev = { sizeof(dev) };
if(!pEnumDisplayDevicesA(0, 0, &dev, 0))
return -1;
@ -199,9 +99,12 @@ int win_get_gfx_card()
int win_get_gfx_drv()
{
// get driver DLL name
static DEVMODE dm; // note: dmDriverVersion is something else
DEVMODEA dm;
// note: dmDriverVersion is not what we're looking for
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(dm);
if(!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &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);

View File

@ -15,13 +15,11 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "precompiled.h"
#include "lib.h"
#include "win_internal.h"
#include <stdlib.h> // __argc
#include <cstdio>
#include <cassert>
#include <crtdbg.h> // malloc debug
#include <malloc.h>
@ -133,6 +131,10 @@ static void at_exit(void)
{
for(int i = 0; i < NUM_CS; i++)
DeleteCriticalSection(&cs[i]);
// redirected to stdout.txt in pre_main_init;
// close to avoid BoundsChecker warning.
fclose(stdout);
}
@ -162,7 +164,7 @@ static inline void pre_main_init()
atexit(at_exit);
// SDL will do this as well. no matter.
// real SDL will do this as well. no matter.
// ignore BoundsChecker warning here.
freopen("stdout.txt", "wt", stdout);
}

View File

@ -18,10 +18,7 @@
// collection of hacks :P
#include <cassert>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include "precompiled.h"
#include <process.h>
@ -305,7 +302,11 @@ int pthread_create(pthread_t* /* thread */, const void* /* attr */, void*(*func)
pthread_mutex_t pthread_mutex_initializer()
{
return CreateMutex(0, 0, 0);
HANDLE h = CreateMutex(0, 0, 0);
if(h == INVALID_HANDLE_VALUE)
return 0;
atexit2(CloseHandle, (uintptr_t)h, CC_STDCALL_1);
return h;
}
int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t*)
@ -313,7 +314,7 @@ int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t*)
if(!m)
return -1;
*m = pthread_mutex_initializer();
return 0;
return *m? 0 : -1;
}
int pthread_mutex_lock(pthread_mutex_t* m)
@ -464,7 +465,7 @@ int clock_gettime(clockid_t clock, struct timespec* t)
#ifndef NDEBUG
if(clock != CLOCK_REALTIME || !t)
{
assert(0 && "clock_gettime: invalid clock or t param");
debug_warn("clock_gettime: invalid clock or t param");
return -1;
}
#endif
@ -481,7 +482,7 @@ int clock_getres(clockid_t clock, struct timespec* res)
#ifndef NDEBUG
if(clock != CLOCK_REALTIME || !res)
{
assert(0 && "clock_getres: invalid clock or res param");
debug_warn("clock_getres: invalid clock or res param");
return -1;
}
#endif
@ -510,7 +511,7 @@ int gettimeofday(struct timeval* tv, void* tzp)
#ifndef NDEBUG
if(!tv)
{
assert(0 && "gettimeofday: invalid t param");
debug_warn("gettimeofday: invalid t param");
return -1;
}
#endif
@ -625,14 +626,18 @@ long sysconf(int name)
if(!page_size)
sysconf(_SC_PAGESIZE); // sets page_size
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
{
MEMORYSTATUSEX ms = { sizeof(ms) };
GlobalMemoryStatusEx(&ms);
if(name == _SC_PHYS_PAGES)
return (long)(round_up(ms.dwTotalPhys, 2*MB) / page_size);
// this is 528 KB less than it should be on Win2k and WinXP.
// is it DOS low mem? mem command shows more free, though.
return (long)(round_up((uintptr_t)ms.ullTotalPhys, 2*MB) / page_size);
// Richter, "Programming Applications for Windows":
// reported value doesn't include non-paged pool reserved
// during boot; it's not considered available to kernel.
// it's 528 KB on my 512 MB machine (WinXP and Win2k).
else
return (long)(ms.dwAvailPhys / page_size);
return (long)(ms.ullAvailPhys / page_size);
}
default:
return -1;

View File

@ -18,9 +18,13 @@
* http://www.stud.uni-karlsruhe.de/~urkt/
*/
#include <cstdio>
#include <cstdlib>
#include <cassert>
// TODO: should use GetMessage when not active to reduce CPU load.
// where to do this?
// - force the app to check for SDL's activation messages, and call
// sdl-wait-message?
// - do it here, just make SDL_PollEvent block until message received?
#include "precompiled.h"
#include <process.h>
@ -28,6 +32,7 @@
#include "lib.h"
#include "win_internal.h"
#include "misc.h"
#include <SDL_vkeys.h>
#ifdef _MSC_VER
@ -70,12 +75,6 @@ static LRESULT CALLBACK wndproc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPA
case WM_ERASEBKGND:
return 0;
// prevent screensaver / monitor power off
case WM_SYSCOMMAND:
if(wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER)
return 0;
break;
case WM_ACTIVATE:
app_active = (wParam & 0xffff) != 0;
@ -90,6 +89,26 @@ static LRESULT CALLBACK wndproc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPA
case WM_CLOSE:
exit(0);
// prevent moving, sizing, screensaver, and power-off in fullscreen mode
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_MOVE:
case SC_SIZE:
case SC_MAXIMIZE:
case SC_MONITORPOWER:
if(fullscreen)
return 1;
}
break;
// prevent selecting menu in fullscreen mode
case WM_NCHITTEST:
if(fullscreen)
return HTCLIENT;
// else: fall through to DefWindowProc
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
@ -123,16 +142,8 @@ static void init_vkmap(SDLKey (&VK_keymap)[256])
VK_keymap[VK_OEM_MINUS] = SDLK_MINUS;
VK_keymap[VK_OEM_PERIOD] = SDLK_PERIOD;
VK_keymap[VK_OEM_2] = SDLK_SLASH;
VK_keymap[VK_0] = SDLK_0;
VK_keymap[VK_1] = SDLK_1;
VK_keymap[VK_2] = SDLK_2;
VK_keymap[VK_3] = SDLK_3;
VK_keymap[VK_4] = SDLK_4;
VK_keymap[VK_5] = SDLK_5;
VK_keymap[VK_6] = SDLK_6;
VK_keymap[VK_7] = SDLK_7;
VK_keymap[VK_8] = SDLK_8;
VK_keymap[VK_9] = SDLK_9;
for(i = 0; i < 10; i++)
VK_keymap[VK_0+i] = (SDLKey)(SDLK_0+i);
VK_keymap[VK_OEM_1] = SDLK_SEMICOLON;
VK_keymap[VK_OEM_PLUS] = SDLK_EQUALS;
VK_keymap[VK_OEM_4] = SDLK_LEFTBRACKET;
@ -140,44 +151,15 @@ static void init_vkmap(SDLKey (&VK_keymap)[256])
VK_keymap[VK_OEM_6] = SDLK_RIGHTBRACKET;
VK_keymap[VK_OEM_3] = SDLK_BACKQUOTE;
VK_keymap[VK_OEM_8] = SDLK_BACKQUOTE;
VK_keymap[VK_A] = SDLK_a;
VK_keymap[VK_B] = SDLK_b;
VK_keymap[VK_C] = SDLK_c;
VK_keymap[VK_D] = SDLK_d;
VK_keymap[VK_E] = SDLK_e;
VK_keymap[VK_F] = SDLK_f;
VK_keymap[VK_G] = SDLK_g;
VK_keymap[VK_H] = SDLK_h;
VK_keymap[VK_I] = SDLK_i;
VK_keymap[VK_J] = SDLK_j;
VK_keymap[VK_K] = SDLK_k;
VK_keymap[VK_L] = SDLK_l;
VK_keymap[VK_M] = SDLK_m;
VK_keymap[VK_N] = SDLK_n;
VK_keymap[VK_O] = SDLK_o;
VK_keymap[VK_P] = SDLK_p;
VK_keymap[VK_Q] = SDLK_q;
VK_keymap[VK_R] = SDLK_r;
VK_keymap[VK_S] = SDLK_s;
VK_keymap[VK_T] = SDLK_t;
VK_keymap[VK_U] = SDLK_u;
VK_keymap[VK_V] = SDLK_v;
VK_keymap[VK_W] = SDLK_w;
VK_keymap[VK_X] = SDLK_x;
VK_keymap[VK_Y] = SDLK_y;
VK_keymap[VK_Z] = SDLK_z;
for(i = 0; i < 26; i++)
VK_keymap[VK_A+i] = (SDLKey)(SDLK_a+i);
VK_keymap[VK_DELETE] = SDLK_DELETE;
VK_keymap[VK_NUMPAD0] = SDLK_KP0;
VK_keymap[VK_NUMPAD1] = SDLK_KP1;
VK_keymap[VK_NUMPAD2] = SDLK_KP2;
VK_keymap[VK_NUMPAD3] = SDLK_KP3;
VK_keymap[VK_NUMPAD4] = SDLK_KP4;
VK_keymap[VK_NUMPAD5] = SDLK_KP5;
VK_keymap[VK_NUMPAD6] = SDLK_KP6;
VK_keymap[VK_NUMPAD7] = SDLK_KP7;
VK_keymap[VK_NUMPAD8] = SDLK_KP8;
VK_keymap[VK_NUMPAD9] = SDLK_KP9;
for(i = 0; i < 10; i++)
VK_keymap[VK_NUMPAD0+i] = (SDLKey)(SDLK_KP0+i);
VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD;
VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE;
VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY;
@ -194,21 +176,8 @@ static void init_vkmap(SDLKey (&VK_keymap)[256])
VK_keymap[VK_PRIOR] = SDLK_PAGEUP;
VK_keymap[VK_NEXT] = SDLK_PAGEDOWN;
VK_keymap[VK_F1] = SDLK_F1;
VK_keymap[VK_F2] = SDLK_F2;
VK_keymap[VK_F3] = SDLK_F3;
VK_keymap[VK_F4] = SDLK_F4;
VK_keymap[VK_F5] = SDLK_F5;
VK_keymap[VK_F6] = SDLK_F6;
VK_keymap[VK_F7] = SDLK_F7;
VK_keymap[VK_F8] = SDLK_F8;
VK_keymap[VK_F9] = SDLK_F9;
VK_keymap[VK_F10] = SDLK_F10;
VK_keymap[VK_F11] = SDLK_F11;
VK_keymap[VK_F12] = SDLK_F12;
VK_keymap[VK_F13] = SDLK_F13;
VK_keymap[VK_F14] = SDLK_F14;
VK_keymap[VK_F15] = SDLK_F15;
for(i = 0; i < 12; i++)
VK_keymap[VK_F1+i] = (SDLKey)(SDLK_F1+i);
VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK;
VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK;
@ -275,7 +244,7 @@ return_char:
return 1;
}
else
assert(0 && "SDL_PollEvent: next_char_idx invalid");
debug_warn("SDL_PollEvent: next_char_idx invalid");
}

View File

@ -15,6 +15,8 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include "precompiled.h"
#ifdef HAVE_X
#include <Xlib.h>
@ -38,7 +40,7 @@ int get_cur_resolution(int& xres, int& yres)
// useful for determining aspect ratio. not called by detect().
// if we fail, outputs are unchanged (assumed initialized to defaults)
int get_monitor_size(int& width_cm, int& height_cm)
int get_monitor_size(int& width_mm, int& height_mm)
{
return -1;
}

View File

@ -15,7 +15,7 @@
// Jan.Wassenberg@stud.uni-karlsruhe.de
// http://www.stud.uni-karlsruhe.de/~urkt/
#include <cmath>
#include "precompiled.h"
#include "timer.h"
#include "types.h"