fix for vc7 (incomplete type in container). also some updates to vfs
This was SVN commit r221.
This commit is contained in:
parent
df282bb714
commit
f383cfd4a8
@ -1,6 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "adts.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
template<class T, int max_items> class DynArray
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
@ -18,8 +18,7 @@
|
||||
* http://www.stud.uni-karlsruhe.de/~urkt/
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "input.h"
|
||||
|
||||
|
@ -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++];
|
||||
|
@ -108,6 +108,9 @@ enum LibError
|
||||
|
||||
|
||||
|
||||
#define debug_warn(str) assert(0 && (str))
|
||||
|
||||
|
||||
|
||||
|
||||
// converts 4 character string to u32 for easy comparison
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "sdl.h"
|
||||
#include "ogl.h"
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
#include "precompiled.h"
|
@ -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);
|
||||
|
||||
@ -564,9 +566,18 @@ fail:
|
||||
t->fmt = fmt;
|
||||
t->bpp = bpp;
|
||||
t->ofs = ofs;
|
||||
t->hm = img_hm;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,111 +416,64 @@ 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)¶ms));
|
||||
|
||||
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)¶ms);
|
||||
|
||||
// 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)¶ms);
|
||||
|
||||
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)¶ms);
|
||||
else
|
||||
{
|
||||
CHECK_PATH(dir);
|
||||
return tree_add_dirR(vdir, dir, loc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mount archives and directories into the VFS
|
||||
@ -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();
|
||||
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));
|
||||
|
||||
int err;
|
||||
|
||||
// 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 char* vfs_mount_point = m.vfs_mount_point.c_str();
|
||||
const char* name = m.name.c_str();
|
||||
const uint pri = m.pri;
|
||||
|
||||
const Handle ha = zip_archive_open(name);
|
||||
err = vdir_add_from_archive(vdir, ha, pri, &m.archives);
|
||||
if(err == 0)
|
||||
return 0;
|
||||
VDir* vdir;
|
||||
CHECK_ERR(tree_lookup(vfs_mount_point, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
|
||||
|
||||
return ERR_PATH_NOT_FOUND;
|
||||
// check if target is a single Zip archive
|
||||
// order doesn't matter; can't have both an archive and dir
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
m.loc.dir.assign(m.name);
|
||||
err = tree_add_loc(vdir, &m.loc);
|
||||
if(err < 0)
|
||||
err = err;
|
||||
|
||||
// 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);
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
else
|
||||
return (long)(ms.dwAvailPhys / page_size);
|
||||
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.ullAvailPhys / page_size);
|
||||
}
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
@ -17,10 +17,14 @@
|
||||
* Jan.Wassenberg@stud.uni-karlsruhe.de
|
||||
* http://www.stud.uni-karlsruhe.de/~urkt/
|
||||
*/
|
||||
|
||||
// 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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user