diff --git a/source/lib/font.cpp b/source/lib/font.cpp deleted file mode 100755 index 95d0ab51b7..0000000000 --- a/source/lib/font.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * OpenGL texture font - * - * Copyright (c) 2002 Jan Wassenberg - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact info: - * Jan.Wassenberg@stud.uni-karlsruhe.de - * http://www.stud.uni-karlsruhe.de/~urkt/ - */ - -#include -#include -#include -#include - -#include "font.h" -#include "res.h" -#include "vfs.h" -#include "tex.h" -#include "ogl.h" -#include "posix.h" -#include "misc.h" - - -typedef struct -{ - Handle tex; - uint list_base; -} -FONT; - - -#if 0 - -#include -//#include FT_FREETYPE_H - - -static FT_Library lib; - - -static void cleanup(void) -{ - FT_Done_FreeType(lib); -} - - -int build_font(const char* in_ttf, const char* out_fnt, const char* out_raw, int height) -{ - if(!lib) - { - FT_Init_FreeType(&lib); - atexit(cleanup); - } - - FT_Face face; - if(FT_New_Face(lib, in_ttf, 0, &face)) - return -1; - - FT_Set_Pixel_Sizes(face, 0, height); - const int tex_dim = 256; - const int w = 24, h = 24; - - FILE* f = fopen(out_fnt, "w"); - if(!f) - return -1; - fprintf(f, "%s\n%d %d\n", out_raw, w, h); /* header */ - - u8* tex = (u8*)calloc(tex_dim*tex_dim, 2); /* GL_LUMINANCE_ALPHA fmt */ - - int x = 0, y = 0; - - for(int c = 32; c < 128; c++) /* for each (printable) char */ - { - FT_Load_Char(face, c, FT_LOAD_RENDER); - const u8* bmp = face->glyph->bitmap.buffer; - - /* copy glyph's bitmap into texture */ - for(int j = 0; j < face->glyph->bitmap.rows; j++) - { - u8* pos = &tex[(y+h-8-face->glyph->bitmap_top+j)*tex_dim*2 + (x+face->glyph->bitmap_left)*2]; - for(int i = 0; i < face->glyph->bitmap.width; i++) - { - *pos++ = *bmp; /* luminance */ - *pos++ = (*bmp)? 0xff : 0x00; /* alpha */ - bmp++; - } - } - - x += w; - if(x + w >= tex_dim) - x = 0, y += h; - - fprintf(f, "%d ", face->glyph->advance.x / 64); - } - - fclose(f); - - /* write texture */ - f = fopen(out_raw, "wb"); - fwrite(tex, 2, tex_dim*tex_dim, f); - fclose(f); - - free(tex); - - return 0; -} - - -#endif - - -static void font_dtor(void* p) -{ - FONT* font = (FONT*)p; - glDeleteLists(font->list_base, 96); -} - - -Handle font_load(const char* fn) -{ - const u32 fn_hash = fnv_hash(fn, strlen(fn)); - - FONT* font; - Handle h = h_alloc(fn_hash, H_FONT, font_dtor, (void**)&font); - if(!h) - return 0; - if(font->tex) - return h; - - void* p; - size_t size; - Handle hm = vfs_load(fn, p, size); - if(!hm) - return 0; - - int pos; // current position in the file - const char* file = (const char*)p; - - // read header - char tex_filename[PATH_MAX]; - int x_stride, y_stride; // glyph spacing in texture - if(sscanf(file, "%s\n%d %d\n%n", tex_filename, &x_stride, &y_stride, &pos) != 3) - { - printf("Problem loading \"%s\": header is invalid", fn); - return 0; - } - - // read glyph widths - int adv[128]; - for(int i = 32; i < 128; i++) - { - file += pos; - if(sscanf(file, "%d %n", &adv[i], &pos) != 1) - { - printf("Problem loading \"%s\": glyph width array is invalid", fn); - return 0; - } - } - - h_free(hm, H_MEM); - - // load glyph texture - const Handle tex = tex_load(tex_filename); - if(!tex) - return 0; - tex_upload(tex); - - const int tex_dim = 256; - const float du = (float)x_stride / (float)tex_dim; - float u = 0, v = 0; - - // create a display list for each glyph - const uint list_base = glGenLists(128); - for(int c = 32; c < 128; c++) - { - const float w = (float)adv[c], h = (float)y_stride; // glyph quad width/height - const float tw = w / tex_dim, th = h / tex_dim; // texture space width/height - - glNewList(list_base+c, GL_COMPILE); - glBegin(GL_QUADS); - glTexCoord2f(u, v+th); glVertex2f(0, 0); - glTexCoord2f(u+tw, v+th); glVertex2f(w, 0); - glTexCoord2f(u+tw, v); glVertex2f(w, h); - glTexCoord2f(u, v); glVertex2f(0, h); - glEnd(); - glTranslatef(w, 0, 0); - glEndList(); - - u += du; - if(u + du > 1.f) - u = 0.f, v += th; - } - - font->tex = tex; - font->list_base = list_base; - - return h; -} - - -int font_bind(const Handle h) -{ - FONT* font = (FONT*)h_user_data(h, H_FONT); - if(!font) - return -1; - - tex_bind(font->tex); - glListBase(font->list_base); - - return 0; -} - - -void glprintf(const char* fmt, ...) -{ - va_list args; - char buf[1024]; buf[1023] = 0; - - va_start(args, fmt); - vsnprintf(buf, sizeof(buf)-1, fmt, args); - va_end(args); - - glCallLists((GLsizei)strlen(buf), GL_UNSIGNED_BYTE, buf); -} diff --git a/source/lib/font.h b/source/lib/font.h deleted file mode 100755 index f489730a0f..0000000000 --- a/source/lib/font.h +++ /dev/null @@ -1,80 +0,0 @@ -// OpenGL texture font -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __FONT_H__ -#define __FONT_H__ - -#include "types.h" -#include "res.h" - -// load and return a handle to the font defined in -extern Handle font_load(const char* fn); - -// use the font referenced by h for all subsequent glprintf() calls -extern int font_bind(Handle h); - -// output text at current OpenGL modelview pos. -// assumes ortho projection with texturing, alpha test, and blending enabled. -// must bind a font before calling! -extern void glprintf(const char* fmt, ...); - - -#endif // #ifndef __FONT_H__ - - - - -/* -EXAMPLE: - -#include "font.h" - - -u32 h; - -void init() -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, g_xres, 0, g_yres, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.5); - - h = font_load("font.fnt"); - if(!h) - abort(); -} - - -void render() -{ - font_bind(h); - glprintf("string"); -} - -// FONT FILE FORMAT: -%s // texture file name -%d %d // width/height of glyphs in the texture -%d [...] %d // advance width for chars 32..127 - -*/ diff --git a/source/lib/ia32.cpp b/source/lib/ia32.cpp deleted file mode 100755 index d8e85d9b9c..0000000000 --- a/source/lib/ia32.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "ia32.h" -#include "types.h" -#include "misc.h" - - -#ifndef _M_IX86 -#error "#define _M_IX86 to enable IA-32 code" -#endif - - -inline u64 rdtsc() -{ - u64 c; -__asm -{ - cpuid - rdtsc - mov dword ptr [c], eax - mov dword ptr [c+4], edx -} - // 64 bit values are returned in edx:eax, but we do it the safe way - return c; -} - - -// change FPU control word (used to set precision) -uint _control87(uint new_cw, uint mask) -{ -__asm -{ - push eax - fnstcw [esp] - pop eax ; old_cw - mov ecx, [new_cw] - mov edx, [mask] - and ecx, edx ; new_cw & mask - not edx ; ~mask - and eax, edx ; old_cw & ~mask - or eax, ecx ; (old_cw & ~mask) | (new_cw & mask) - push eax - fldcw [esp] - pop eax -} - - UNUSED(new_cw) - UNUSED(mask) - - return 0; -} diff --git a/source/lib/ia32.h b/source/lib/ia32.h deleted file mode 100755 index 3008586959..0000000000 --- a/source/lib/ia32.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _M_IX86 -#define __IA32_H__ -#endif - - -#ifndef __IA32_H__ - -#include "types.h" - - -extern u64 rdtsc(); - - -#ifndef _MCW_PC -#define _MCW_PC 0x0300 // Precision Control -#endif -#ifndef _PC_24 -#define _PC_24 0x0000 // 24 bits -#endif - -extern uint _control87(uint new_cw, uint mask); - -#endif // #ifndef __IA32_H__ diff --git a/source/lib/mem.cpp b/source/lib/mem.cpp deleted file mode 100755 index 2637035f7c..0000000000 --- a/source/lib/mem.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// malloc layer for less fragmentation, alignment, and automatic release - -#include -#include - -#include - -#include "types.h" -#include "mem.h" -#include "res.h" -#include "misc.h" -#include "posix.h" - - -static void heap_free(MEM* m) -{ - free(m->org_p); -} - - -static void* heap_alloc(const size_t size, const int align, MEM* mem) -{ - u8* org_p = (u8*)malloc(size+align-1); - u8* p = (u8*)round_up((uintptr_t)org_p, align); - - mem->org_p = org_p; - return p; -} - - -////////////////////////////////////////////////////////////////////////////// - - -static u8* pool; -static size_t pool_pos; -static const size_t POOL_CAP = 64*MB; // TODO: user editable - - -static void pool_free(MEM* m) -{ - // at end of pool? if so, 'free' it - if(m->ofs + m->size == pool_pos) - pool_pos -= m->size; -} - - -static void* pool_alloc(const size_t size, const uint align, MEM* mem) -{ - if(!pool) - { - pool = (u8*)mem_alloc(size, align, MEM_HEAP); - if(!pool) - return 0; - } - - ptrdiff_t ofs = (u8*)round_up((uintptr_t)pool+pool_pos, align) - pool; - if(ofs+size > POOL_CAP) - return 0; - - void* p = (u8*)pool + ofs; - - mem->size = size; - mem->ofs = ofs; - - pool_pos = ofs+size; - return p; -} - - -////////////////////////////////////////////////////////////////////////////// - - -static void mmap_free(MEM* m) -{ - munmap(m->p, (uint)m->size); -} - - -static void* mmap_alloc(const size_t size, const int fd, MEM* mem) -{ - mem->p = mmap(0, (uint)size, PROT_READ, MAP_PRIVATE, fd, 0); - mem->size = size; - mem->fd = fd; - - return mem->p; -} - - -////////////////////////////////////////////////////////////////////////////// - - -static void mem_dtor(void* p) -{ - MEM* m = (MEM*)p; - if(m->type == MEM_HEAP) - heap_free(m); - else if(m->type == MEM_POOL) - pool_free(m); - else if(m->type == MEM_MAPPED) - mmap_free(m); - else - assert(0 && "mem_dtor: MEM.type invalid!"); -} - - -int mem_free(void* p) -{ - if(!p) - return 1; - - Handle h = h_find((uintptr_t)p, H_MEM, 0); - if(h) - return h_free(h, H_MEM); - return -1; -} - - -int mem_free(Handle hm) -{ - return h_free(hm, H_MEM); -} - - -void* mem_alloc(size_t size, const uint align, const MemType type, const int fd, Handle* ph) -{ - assert(size != 0 && "mem_alloc: why is size = 0?"); - - // bit of a hack: the allocators require space for bookkeeping, - // but we can't allocate a handle until we know the key - // (the pointer address), which is used to find the corresponding - // handle when freeing memory. - // we fill a temp MEM, and then copy it into the handle's user data space - MEM mem; - - void* p; - if(type == MEM_HEAP) - p = heap_alloc(size, align, &mem); - else if(type == MEM_POOL) - p = pool_alloc(size, align, &mem); - else if(type == MEM_MAPPED) - p = mmap_alloc(size, fd, &mem); - else - { - assert(0 && "mem_alloc: invalid type parameter"); - return 0; - } - - if(!p) - return 0; - - MEM* pmem; - Handle h = h_alloc((uintptr_t)p, H_MEM, mem_dtor, (void**)&pmem); - if(!h) // failed to allocate a handle - { - mem_dtor(&mem); - return 0; - } - *pmem = mem; // copy our memory info into the handle's user data space - - // caller is asking for the handle - // (freeing the memory via handle is faster than mem_free, because - // we wouldn't have to scan all handles looking for the pointer) - if(ph) - *ph = h; - - return p; -} \ No newline at end of file diff --git a/source/lib/mem.h b/source/lib/mem.h deleted file mode 100755 index 5dbccb43de..0000000000 --- a/source/lib/mem.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __MEM_H__ -#define __MEM_H__ - -#include "res.h" - -// include memory mappings because the VFS may return either a chunk of -// memory, or the mapped file, and a client doesn't know the difference. - -enum MemType -{ - MEM_POOL, - MEM_HEAP, - MEM_MAPPED -}; - - -struct MEM -{ - void* p; - size_t size; - - MemType type; - - union - { - size_t ofs; // MEM_POOL only - void* org_p; // MEM_HEAP only - int fd; // MEM_MAPPED only - }; -}; - -extern void* mem_alloc(size_t size, uint align = 1, MemType type = MEM_HEAP, int fd = -1, Handle* ph = 0); -extern int mem_free(void* p); - -// faster than mem_free(void*) - no scan of open handles for the pointer -extern int mem_free(Handle hm); - -#endif // #ifndef __MEM_H__ diff --git a/source/lib/posix.cpp b/source/lib/posix.cpp deleted file mode 100755 index a8c12a1528..0000000000 --- a/source/lib/posix.cpp +++ /dev/null @@ -1,523 +0,0 @@ -// POSIX emulation for Win32 -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -// collection of hacks :P - -#include -#include -#include -#include - -#include - -#include "posix.h" -#include "win.h" -#include "time.h" -#include "misc.h" - - -////////////////////////////////////////////////////////////////////////////// -// -// file -// -////////////////////////////////////////////////////////////////////////////// - -/* -extern int aio_open(const char*, int, int); -extern int aio_close(int); -*/ - -int open(const char* fn, int mode, ...) -{ - // /dev/tty? => COM? - if(!strncmp(fn, "/dev/tty", 8)) - { - static char port[] = "COM "; - port[3] = (char)(fn[8]+1); - fn = port; - } - - int fd = _open(fn, mode); - - // open it for async I/O as well (_open defaults to deny_none sharing) - if(fd > 2) - aio_open(fn, mode, fd); - - return fd; -} - - -int close(int fd) -{ - aio_close(fd); - return _close(fd); -} - - -int ioctl(int fd, int op, int* data) -{ - HANDLE h = (HANDLE)((char*)0 + _get_osfhandle(fd)); - - switch(op) - { - case TIOCMGET: - /* TIOCM_* mapped directly to MS_*_ON */ - GetCommModemStatus(h, (DWORD*)data); - break; - - case TIOCMBIS: - /* only RTS supported */ - if(*data & TIOCM_RTS) - EscapeCommFunction(h, SETRTS); - else - EscapeCommFunction(h, CLRRTS); - break; - - case TIOCMIWAIT: - static DWORD mask; - DWORD new_mask = 0; - if(*data & TIOCM_CD) - new_mask |= EV_RLSD; - if(*data & TIOCM_CTS) - new_mask |= EV_CTS; - if(new_mask != mask) - SetCommMask(h, mask = new_mask); - WaitCommEvent(h, &mask, 0); - break; - } - - return 0; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// dir -// -////////////////////////////////////////////////////////////////////////////// - - -char* realpath(const char* fn, char* path) -{ - if(!GetFullPathName(fn, PATH_MAX, path, 0)) - return 0; - return path; -} - - -int mkdir(const char* path, mode_t) -{ - return CreateDirectory(path, 0)? 0 : -1; -} - - -struct _DIR -{ - WIN32_FIND_DATA fd; - HANDLE handle; - struct dirent ent; // must not be overwritten by calls for different dirs - bool not_first; -}; - - -DIR* opendir(const char* name) -{ - DWORD fa = GetFileAttributes(name); - if(fa == INVALID_FILE_ATTRIBUTES || !(fa & FILE_ATTRIBUTE_DIRECTORY)) - return 0; - - _DIR* d = (_DIR*)calloc(sizeof(_DIR), 1); - - char path[MAX_PATH+1]; - strncpy(path, name, MAX_PATH-2); - strcat(path, "\\*"); - d->handle = FindFirstFile(path, &d->fd); - - return d; -} - - -struct dirent* readdir(DIR* dir) -{ - _DIR* d = (_DIR*)dir; - - if(d->not_first) - if(!FindNextFile(d->handle, &d->fd)) - return 0; - d->not_first = true; - - d->ent.d_ino = 0; - d->ent.d_name = &d->fd.cFileName[0]; - return &d->ent; -} - - -int closedir(DIR* dir) -{ - _DIR* d = (_DIR*)dir; - - FindClose(d->handle); - - free(dir); - return 0; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// terminal -// -////////////////////////////////////////////////////////////////////////////// - - -static HANDLE std_h[2] = { (HANDLE)(((char*)0) + 3), (HANDLE)(((char*)0) + 7) }; - - -__declspec(naked) void _get_console() -{ __asm jmp dword ptr [AllocConsole] } - -__declspec(naked) void _hide_console() -{ __asm jmp dword ptr [FreeConsole] } - - -int tcgetattr(int fd, struct termios* termios_p) -{ - if(fd > 2) - return -1; - HANDLE h = std_h[fd]; - - DWORD mode; - GetConsoleMode(h, &mode); - termios_p->c_lflag = mode & (ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT); - - return 0; -} - - -int tcsetattr(int fd, int /* optional_actions */, const struct termios* termios_p) -{ - if(fd > 2) - return -1; - HANDLE h = std_h[fd]; - SetConsoleMode(h, (DWORD)termios_p->c_lflag); - FlushConsoleInputBuffer(h); - - return 0; -} - - -int poll(struct pollfd /* fds */[], int /* nfds */, int /* timeout */) -{ - return -1; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// thread -// -////////////////////////////////////////////////////////////////////////////// - - -__declspec(naked) pthread_t pthread_self(void) -{ __asm jmp dword ptr [GetCurrentThread] } - - -int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param* param) -{ - if(policy == SCHED_FIFO) - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); - - HANDLE hThread = (HANDLE)((char*)0 + thread); - - SetThreadPriority(hThread, param->sched_priority); - return 0; -} - - -int pthread_create(pthread_t* /* thread */, const void* /* attr */, void*(* func)(void*), void* arg) -{ - /* can't use asm 'cause _beginthread might be a func ptr (with libc) */ - return (int)_beginthread((void(*)(void*))func, 0, arg); -} - - -pthread_mutex_t pthread_mutex_initializer() -{ - return CreateMutex(0, 0, 0); -} - -int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t*) -{ - if(!m) - return -1; - *m = pthread_mutex_initializer(); - return 0; -} - -int pthread_mutex_lock(pthread_mutex_t* m) -{ - return WaitForSingleObject(*m, INFINITE) == WAIT_OBJECT_0? 0 : -1; -} - -int pthread_mutex_trylock(pthread_mutex_t* m) -{ - return WaitForSingleObject(*m, 0) == WAIT_OBJECT_0? 0 : -1; -} - -int pthread_mutex_unlock(pthread_mutex_t* m) -{ - return ReleaseMutex(*m)? 0 : -1; -} - - - - - -////////////////////////////////////////////////////////////////////////////// -// -// time -// -////////////////////////////////////////////////////////////////////////////// - - -int clock_gettime(clockid_t clock_id, struct timespec* tp) -{ - static double start_t = -1.0; - static time_t start_s; - - if(start_t < 0.0) - { - start_s = time(0); - start_t = get_time(); - } - - if(clock_id != CLOCK_REALTIME) - { -// errno = EINVAL; - return -1; - } - - double t = get_time(); - double dt = t-start_t; - start_t = t; - - int ds = (int)floor(dt); - int dn = (int)floor((dt-ds) * 1.0e9); - - tp->tv_sec = start_s + ds; - tp->tv_nsec = 0 + dn; - - return 0; -} - - -int nanosleep(const struct timespec* rqtp, struct timespec* /* rmtp */) -{ - int ms = (int)rqtp->tv_sec * 1000 + rqtp->tv_nsec / 1000000; - if(ms > 0) - Sleep(ms); - else - { - struct timespec t1, t2; - clock_gettime(CLOCK_REALTIME, &t1); - int d_ns; - do - { - clock_gettime(CLOCK_REALTIME, &t2); - d_ns = (int)(t2.tv_sec-t1.tv_sec)*1000000000 + (t2.tv_nsec-t1.tv_nsec); - } - while(d_ns < rqtp->tv_nsec); - } - - return 0; -} - - -uint sleep(uint sec) -{ - Sleep(sec * 1000); - - return sec; -} - - -////////////////////////////////////////////////////////////////////////////// -// -// memory mapping -// -////////////////////////////////////////////////////////////////////////////// - - -void* mmap(void* start, unsigned int len, int prot, int flags, int fd, long offset) -{ - if(!(flags & MAP_FIXED)) - start = 0; - - /* interpret protection/mapping flags. */ - SECURITY_ATTRIBUTES sec = { sizeof(SECURITY_ATTRIBUTES), 0, 0 }; - DWORD flProtect = PAGE_READONLY; /* mapping object permission */ - DWORD dwAccess = FILE_MAP_READ; /* file map access permission */ - if(prot & PROT_WRITE) - { - flProtect = PAGE_READWRITE; - - /* changes are shared & written to file */ - if(flags & MAP_SHARED) - { - sec.bInheritHandle = 1; - dwAccess = FILE_MAP_ALL_ACCESS; - } - /* private copy on write mapping */ - else if(flags & MAP_PRIVATE) - { - flProtect = PAGE_WRITECOPY; - dwAccess = FILE_MAP_COPY; - } - } - - DWORD len_hi = (u32)((u64)len >> 32), len_lo = (u32)len & 0xffffffff; - - HANDLE hFile = (HANDLE)((char*)0 + _get_osfhandle(fd)); - HANDLE hMap = CreateFileMapping(hFile, &sec, flProtect, len_hi, len_lo, 0); - - void* ptr = MapViewOfFileEx(hMap, dwAccess, len_hi, offset, len_lo, start); - - /* file mapping object will be freed when ptr is unmapped */ - CloseHandle(hMap); - - if(!ptr || (flags & MAP_FIXED && ptr != start)) - return MAP_FAILED; - - return ptr; -} - - -int munmap(void* start, unsigned int /* len */) -{ - return UnmapViewOfFile(start) - 1; /* 0: success; -1: fail */ -} - - -int uname(struct utsname* un) -{ - if(!un) - return -1; - - static OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&vi); - - // OS implementation name - const char* family = "??"; - int ver = (vi.dwMajorVersion << 8) | vi.dwMinorVersion; - if(vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - family = (ver == 0x045a)? "ME" : "9x"; - if(vi.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - if(ver == 0x0500) - family = "2k"; - else if(ver == 0x0501) - family = "XP"; - else - family = "NT"; - } - sprintf(un->sysname, "Win%s", family); - - // release info - const char* vs = vi.szCSDVersion; - int sp; - if(sscanf(vs, "Service Pack %d", &sp) == 1) - sprintf(un->release, "SP %d", sp); - else - { - const char* release = ""; - if(vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - { - if(!strcmp(vs, " C")) - release = "OSR2"; - else if(!strcmp(vs, " A")) - release = "SE"; - } - strcpy(un->release, release); - } - - // version - sprintf(un->version, "%lu.%02lu.%lu", vi.dwMajorVersion, vi.dwMinorVersion, vi.dwBuildNumber & 0xffff); - - // node name - u32 buf_size = sizeof(un->nodename); - GetComputerName(un->nodename, &buf_size); - - // hardware type - static SYSTEM_INFO si; - GetSystemInfo(&si); - if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - strcpy(un->machine, "AMD64"); - else - strcpy(un->machine, "x86"); - - return 0; -} - - - -u16_t htons(u16_t s) -{ - return (s >> 8) | ((s & 0xff) << 8); -} - -/******************************************************************/ -/* socket dynamic functions */ -fp_getnameinfo_t getnameinfo; -fp_getaddrinfo_t getaddrinfo; -fp_freeaddrinfo_t freeaddrinfo; - -/* IPv6 globals -These are included in the linux C libraries, and in newer platform SDK's, so -should only be needed in VC++6 or earlier. -*/ -#if _MSC_VER <= 1200 /* VC++6 or earlier */ -const struct in6_addr in6addr_any=IN6ADDR_ANY_INIT; /* :: */ -const struct in6_addr in6addr_loopback=IN6ADDR_LOOPBACK_INIT; /* ::1 */ -#endif - -void entry(void) -{ -// note: winsock header is also removed by this define -#ifndef NO_WINSOCK - char d[1024]; - WSAStartup(0x0002, d); // want 2.0 -#endif - - HMODULE h=LoadLibrary("ws2_32.dll"); - if (h) - { - getaddrinfo=(fp_getaddrinfo_t)GetProcAddress(h, "getaddrinfo"); - getnameinfo=(fp_getnameinfo_t)GetProcAddress(h, "getnameinfo"); - freeaddrinfo=(fp_freeaddrinfo_t)GetProcAddress(h, "freeaddrinfo"); - } - else - { - getaddrinfo=NULL; - getnameinfo=NULL; - freeaddrinfo=NULL; - } - - mainCRTStartup(); -} diff --git a/source/lib/posix/aio.cpp b/source/lib/posix/aio.cpp deleted file mode 100755 index c60f0fb14e..0000000000 --- a/source/lib/posix/aio.cpp +++ /dev/null @@ -1,465 +0,0 @@ -// POSIX asynchronous I/O -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#include -#include -#include - -//#include -#include "posix.h" -#include "win.h" -#include "misc.h" -#include "types.h" - -// Win32 functions require sector aligned transfers. -// updated by aio_open; changes don't affect aio_return -static size_t sector_size = 4096; - -// async-capable handles to each lowio file -static HANDLE* aio_hs; -static uint hs_cap; - -// information about active transfers (reused) -struct Req -{ - // used to identify this request; != 0 <==> request valid - aiocb* cb; - - OVERLAPPED ovl; - // hEvent signals when transfer complete - - // read into a separate align buffer if necessary - // (note: unaligned writes aren't supported. see aio_rw) - size_t pad; // offset from starting sector - void* buf; // reused; resize if too small - size_t buf_size; -}; - -static const int MAX_REQS = 4; -static Req reqs[MAX_REQS]; - -// TODO: use pthread mutex -static HANDLE open_mutex = INVALID_HANDLE_VALUE; -static HANDLE reqs_mutex = INVALID_HANDLE_VALUE; -#define LOCK(what)\ -{\ -if(what##_mutex == INVALID_HANDLE_VALUE)\ - what##_mutex = CreateMutex(0,0,"aio_"#what);\ -WaitForSingleObject(what##_mutex, INFINITE);\ -} -#define UNLOCK(what) ReleaseMutex(what##_mutex); - - -// get async capable handle to file -// current implementation: open both versions of the file on open() -// wastes 1 handle/file, but we don't have to remember the filename/mode -static HANDLE aio_h(int fd) -{ - if((unsigned)fd >= hs_cap) - return INVALID_HANDLE_VALUE; - - return aio_hs[fd]; -} - - -// find request slot currently in use by cb -// cb = 0 => search for empty slot -static Req* find_req(const aiocb* cb) -{ - Req* r = reqs; - for(int i = 0; i < MAX_REQS; i++, r++) - if(r->cb == cb) - return r; - - return 0; -} - - -static void cleanup(void) -{ - int i; - - // close files - for(i = 0; i < (int)hs_cap; i++) - { - HANDLE h = aio_h(i); - if(h != INVALID_HANDLE_VALUE) - CloseHandle(h); - } - free(aio_hs); - aio_hs = 0; - hs_cap = 0; - - // free requests - Req* r = reqs; - for(i = 0; i < MAX_REQS; i++, r++) - { - r->cb = 0; - - CloseHandle(r->ovl.hEvent); - r->ovl.hEvent = INVALID_HANDLE_VALUE; - - free(r->buf); - r->buf = 0; - } - - CloseHandle(open_mutex); - open_mutex = INVALID_HANDLE_VALUE; - if(reqs_mutex != INVALID_HANDLE_VALUE) // happens if not initialized, i.e. aio_rw wasn't called - CloseHandle(reqs_mutex); - reqs_mutex = INVALID_HANDLE_VALUE; -} - -// called by aio_open and aio_open_winhandle -static void init() -{ - ONCE( - for(int i = 0; i < MAX_REQS; i++) - { - reqs[i].ovl.hEvent = CreateEvent(0,1,0,0); // manual reset - //printf("Req %p [%d]: hEvent %x\n", reqs+i, i, reqs[i].ovl.hEvent); - } - - atexit(cleanup); - ) -} - - -int aio_close(int fd) -{ - HANDLE h = aio_h(fd); - if(h == INVALID_HANDLE_VALUE) // out of bounds or already closed - return -1; - - CloseHandle(h); - aio_hs[fd] = INVALID_HANDLE_VALUE; - return 0; -} - -//NOTE: Requires that the "open" lock is held -int alloc_handle_entry(int fd) -{ - // alloc aio_hs entry - if((unsigned)fd >= hs_cap) - { - uint hs_cap2 = (uint)round_up(fd+8, 8); - HANDLE* aio_hs2 = (HANDLE*)realloc(aio_hs, hs_cap2*sizeof(HANDLE)); - if(!aio_hs2) - return -1; - - for(uint i = hs_cap; i < hs_cap2; i++) - aio_hs2[i] = INVALID_HANDLE_VALUE; - aio_hs = aio_hs2; - hs_cap = hs_cap2; - } - return 0; -} - -// fd is already opened in async/overlapped mode; add to required internal structures -int aio_open_winhandle(HANDLE fd) -{ - init(); - - LOCK(open) - - if (alloc_handle_entry(HANDLE2INT(fd)) == -1) - { - UNLOCK(open) - return -1; - } - - aio_hs[HANDLE2INT(fd)]=fd; - - UNLOCK(open) - return 0; -} - -// open fn in async mode; associate with fd (retrieve via aio_h(fd)) -int aio_open(const char* fn, int mode, int fd) -{ - init(); - -LOCK(open) - - if (alloc_handle_entry(fd) == -1) - return -1; - -UNLOCK(open) - - // interpret mode - u32 access = GENERIC_READ; // assume O_RDONLY - u32 share = 0; - if(mode & O_WRONLY) - access = GENERIC_WRITE; - else if(mode & O_RDWR) - access = GENERIC_READ|GENERIC_WRITE; - else - share = FILE_SHARE_READ; - u32 create = OPEN_EXISTING; - if(mode & O_CREAT) - create = (mode & O_EXCL)? CREATE_NEW : CREATE_ALWAYS; - u32 flags = FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN; - - // open file, store in aio_hs array - aio_hs[fd] = CreateFile(fn, access, share, 0, create, flags, 0); - if(aio_hs[fd] == INVALID_HANDLE_VALUE) - return -1; - - // check drive's sector size (Win32 requires alignment) - char path[PATH_MAX]; - realpath(fn, path); - path[3] = 0; // cut off after ?:\\ - u32 spc, nfc, tnc; // don't need these - u32 sector_size2; - GetDiskFreeSpace(path, &spc, §or_size2, &nfc, &tnc); - -LOCK(open) - - if(sector_size < sector_size2) - sector_size = sector_size2; - -UNLOCK(open) - - return 0; -} - - -// called by aio_read, aio_write, and lio_listio -// cb->aio_lio_opcode specifies desired operation -static int aio_rw(struct aiocb* cb) -{ - if(!cb) - return -1; - if(cb->aio_lio_opcode == LIO_NOP) - return 0; - - HANDLE h = aio_h(cb->aio_fildes); - if(h == INVALID_HANDLE_VALUE) - { - printf("Invalid handle\n"); - return -1; - } - -LOCK(reqs) - - // find free request slot - Req* r = find_req(0); - if(!r) - { - UNLOCK(reqs) - printf("No Req\n"); - return -1; - } - r->cb = cb; - -UNLOCK(reqs) - - size_t ofs = 0; - size_t size = cb->aio_nbytes; - void* buf = cb->aio_buf; - -#define SOL_SOCKET 0xffff -#define SO_TYPE 0x1008 - - unsigned long opt = 0; - socklen_t optlen = sizeof(opt); - if (getsockopt((int)h, SOL_SOCKET, SO_TYPE, &opt, &optlen) != -1) -// || (WSAGetLastError() != WSAENOTSOCK)) - cb->aio_offset = 0; - else - { - // align - r->pad = cb->aio_offset % sector_size; // offset to start of sector - ofs = cb->aio_offset - r->pad; - size += r->pad + sector_size-1; - size &= sector_size-1; // align (sector_size = 2**n) - - if(r->pad || (uintptr_t)buf % sector_size) - { - // current align buffer is too small - resize - if(r->buf_size < size) - { - void* buf2 = realloc(r->buf, size); - if(!buf2) - return -1; - r->buf = buf2; - r->buf_size = size; - } - - // unaligned writes are not supported - - // we'd have to read padding, then write our data. ugh. - if(cb->aio_lio_opcode == LIO_WRITE) - { - return -1; - } - - buf = r->buf; - } - } - -#if _MSC_VER >= 1300 - r->ovl.Pointer = (void*)ofs; -#else - r->ovl.Offset = ofs; -#endif - - DWORD size32 = (DWORD)(size & 0xffffffff); - u32 status = (cb->aio_lio_opcode == LIO_READ)? - ReadFile(h, buf, size32, 0, &r->ovl) : WriteFile(h, buf, size32, 0, &r->ovl); - - if(status || GetLastError() == ERROR_IO_PENDING) - return 0; - return -1; -} - - -int aio_read(struct aiocb* cb) -{ - cb->aio_lio_opcode = LIO_READ; - return aio_rw(cb); -} - - -int aio_write(struct aiocb* cb) -{ - cb->aio_lio_opcode = LIO_WRITE; - return aio_rw(cb); -} - - -int lio_listio(int mode, struct aiocb* const cbs[], int n, struct sigevent* se) -{ - UNUSED(se) - - for(int i = 0; i < n; i++) - aio_rw(cbs[i]); // aio_rw checks for 0 param - - if(mode == LIO_WAIT) - aio_suspend(cbs, n, 0); - - return 0; -} - - -// return status of transfer -int aio_error(const struct aiocb* cb) -{ - Req* const r = find_req(cb); - if(!r) - return -1; - - switch(r->ovl.Internal) // I/O status - { - case 0: - return 0; - case STATUS_PENDING: - return -EINPROGRESS; - - // TODO: errors - default: - return -1; - } -} - - -// get bytes transferred. call exactly once for each op. -ssize_t aio_return(struct aiocb* cb) -{ - Req* const r = find_req(cb); - if(!r) - return -1; - - assert(r->ovl.Internal == 0 && "aio_return with transfer in progress"); - - // read wasn't aligned - need to copy to user's buffer - const size_t _buf = (char*)cb->aio_buf - (char*)0; - if(r->pad || _buf % sector_size) - memcpy(cb->aio_buf, (u8*)r->buf + r->pad, cb->aio_nbytes); - - // free this request slot - r->cb = 0; - - return (ssize_t)cb->aio_nbytes; -} - - -int aio_cancel(int fd, struct aiocb* cb) -{ - UNUSED(cb) - - const HANDLE h = aio_h(fd); - if(h == INVALID_HANDLE_VALUE) - return -1; - - // Win32 limitation: can't cancel single transfers - CancelIo(h); - return AIO_CANCELED; -} - - -int aio_fsync(int, struct aiocb*) -{ - return -1; -} - - -int aio_suspend(const struct aiocb* const cbs[], int n, const struct timespec* ts) -{ - if(n <= 0 || n > MAXIMUM_WAIT_OBJECTS) - return -1; - - int cnt = 0; // actual number of valid cbs - HANDLE* hs = (HANDLE*)malloc(n*sizeof(HANDLE)); - if(!hs) - return -1; - for(int i = 0; i < n; i++) - { - // ignore NULL list entries - if(!cbs[i]) - continue; - - Req* r = find_req(cbs[i]); - if(r) - { - if(r->ovl.Internal == STATUS_PENDING) - hs[cnt++] = r->ovl.hEvent; - } - } - - // no valid, pending transfers - done - if(!cnt) - return 0; - - // timeout: convert timespec to ms (NULL ptr -> no timeout) - u32 timeout = INFINITE; - if(ts) - timeout = ts->tv_sec*1000 + ts->tv_nsec/1000000; - - u32 status = WaitForMultipleObjects(cnt, hs, 0, timeout); - - free(hs); - - if(status == WAIT_TIMEOUT) - { - //errno = -EAGAIN; - return -1; - } - else if(status == WAIT_FAILED) - return -1; - return 0; -} diff --git a/source/lib/posix/aio.h b/source/lib/posix/aio.h deleted file mode 100755 index 7de3a39c93..0000000000 --- a/source/lib/posix/aio.h +++ /dev/null @@ -1,63 +0,0 @@ -// POSIX asynchronous I/O -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -// included by posix.h - -// Note: for maximum efficiency, transfer buffers, offsets, and lengths -// should be sector aligned (otherwise, buffer is copied). - - -struct aiocb -{ - int aio_fildes; // File descriptor. - off_t aio_offset; // File offset. - void* aio_buf; // Location of buffer. - size_t aio_nbytes; // Length of transfer. - int aio_reqprio; // Request priority offset. - struct sigevent aio_sigevent; // Signal number and value. - int aio_lio_opcode; // Operation to be performed. -}; - -enum -{ - // aio_cancel return - AIO_ALLDONE, // None of the requested operations could be canceled since they are already complete. - AIO_CANCELED, // All requested operations have been canceled. - AIO_NOTCANCELED, // Some of the requested operations could not be canceled since they are in progress. - - // lio_listio mode - LIO_WAIT, // wait until all I/O is complete - LIO_NOWAIT, - - // lio_listio ops - LIO_NOP, - LIO_READ, - LIO_WRITE -}; - -extern int aio_cancel(int, struct aiocb*); -extern int aio_error(const struct aiocb*); -extern int aio_fsync(int, struct aiocb*); -extern int aio_read(struct aiocb*); -extern ssize_t aio_return(struct aiocb*); -extern int aio_suspend(const struct aiocb* const[], int, const struct timespec*); -extern int aio_write(struct aiocb*); -extern int lio_listio(int, struct aiocb* const[], int, struct sigevent*); - -extern int aio_close(int fd); -extern int aio_open(const char* fn, int mode, int fd); diff --git a/source/lib/res.cpp b/source/lib/res.cpp deleted file mode 100755 index 30ad8e6e8b..0000000000 --- a/source/lib/res.cpp +++ /dev/null @@ -1,326 +0,0 @@ -// handle-based resource manager -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#include -#include -#include -#include - -#include "types.h" -#include "zip.h" -#include "posix.h" -#include "misc.h" -#include "res.h" -#include "mem.h" -#include "vfs.h" - - -// handle (32 bits) -// .. make sure this is the same handle we opened -const uint HTAG_BITS = 16; -// .. index into array => = log2(max open handles) -const uint HIDX_BITS = 12; - -// together, <= 32-TAG_BITS bits -const uint HTYPE_BITS = 4; -const uint HREF_BITS = 8; - -const int HDATA_USER_SIZE = 20; - -// 32 bytes -struct HDATA -{ - uintptr_t key; - u32 tag : HTAG_BITS; - u32 type : HTYPE_BITS; // handle's type (e.g. texture, sound) - u32 refs : HREF_BITS; - - u32 unused; // TODO: type pointer? - - u8 user[HDATA_USER_SIZE]; -}; - -static const ulong hdata_cap = 1ul << HIDX_BITS; -static const uint type_cap = 1ul << HTYPE_BITS; - -// array of pages for better locality, less fragmentation -static const uint PAGE_SIZE = 4096; -static const uint hdata_per_page = PAGE_SIZE / sizeof(HDATA); -static const uint num_pages = hdata_cap / hdata_per_page; -static HDATA* pages[num_pages]; - -static int first_free = -1; // don't want to scan array every h_alloc -static int last_in_use = -1; // don't search unused entries - - -static void(*dtors[type_cap])(void*); - - -// get pointer to handle data (non-contiguous array) -static HDATA* h_data(const int idx) -{ - if(idx > hdata_cap) - return 0; - HDATA*& page = pages[idx / hdata_per_page]; - if(!page) - { - page = (HDATA*)calloc(PAGE_SIZE, 1); - if(!page) - return 0; - } - - return &page[idx % hdata_per_page]; -} - - -// get array index from handle -static int h_idx(const Handle h, const uint type) -{ - const int idx = h & ((1 << HIDX_BITS)-1); - if(idx > last_in_use) - return -1; - - const HDATA* hd = h_data(idx); - // cannot fail - all HDATA up to last_in_use are valid - - const u32 tag = h >> HIDX_BITS; - // note: tag = 0 marks unused entries => is invalid - if(!tag || hd->tag != tag || hd->type != type) - return -1; - - return idx; -} - - -static Handle handle(const int idx) -{ - const HDATA* hd = h_data(idx); - if(!hd) // out of memory - return 0; - return (hd->tag) << HIDX_BITS | (u32)idx; -} - - - -static int h_free(const int idx) -{ - HDATA* hd = h_data(idx); - if(!hd) - return -1; - - // not the last reference - if(--hd->refs) - return 0; - - // TODO: keep this handle open (cache) - - // call its type's destructor - if(dtors[hd->type]) - dtors[hd->type](hd); - - memset(hd, 0, sizeof(HDATA)); - - if(first_free == -1 || idx < first_free) - first_free = idx; - - return 0; -} - - -static void cleanup(void) -{ - int i; - - // close open handles - for(i = 0; i < last_in_use; i++) - h_free(i); - - // free hdata array - for(i = 0; i < (int)num_pages; i++) - { - free(pages[i]); - pages[i] = 0; - } -} - - -Handle h_find(const uintptr_t key, uint type, void** puser) -{ - int idx; - HDATA* hd; - - // already have first free entry cached - just search - if(first_free != -1) - { - for(idx = 0; idx <= last_in_use; idx++) - { - hd = h_data(idx); // guaranteed valid - if(hd->key == key && hd->type == type) - goto found; - } - } - // search and remember first free entry (slower) - else - { - for(idx = 0; idx <= last_in_use; idx++) - { - hd = h_data(idx); // guaranteed valid - if(!hd->tag && first_free == -1) - first_free = idx; - else if(hd->key == key && hd->type == type) - goto found; - } - } - - // not found - return 0; - -found: - Handle h = handle(idx); - if(puser) - *puser = hd->user; - return h; -} - - -Handle h_alloc(const uintptr_t key, const uint type, /*const size_t user_size,*/ H_DTOR dtor, void** puser) -{ - ONCE(atexit(cleanup)) -/* - if(user_size > HDATA_USER_SIZE) - { - assert(!"h_alloc: not enough space in entry for user data"); - return 0; - } -*/ - if(type >= type_cap) - { - assert(!"h_alloc: invalid type"); - return 0; - } - - if(dtor) - { - // registering a second dtor for type - if(dtors[type] && dtors[type] != dtor) - { - assert(!"h_alloc: registering a second, different dtor for type"); - return 0; - } - dtors[type] = dtor; - } - - int idx; - HDATA* hd; - - if(key) - { - // object already loaded? - Handle h = h_find(key, type, 0); - if(h) - { - hd = h_data(h_idx(h, type)); - - if(hd->refs == (1ul << HREF_BITS)) - { - assert(!"h_alloc: too many references to a handle - increase REF_BITS"); - return 0; - } - hd->refs++; - - if(puser) - *puser = hd; - - return h; - } - } - - // cached - if(first_free != -1) - { - idx = first_free; - hd = h_data(idx); - } - // search handle data for first free entry - else - for(idx = 0; idx < hdata_cap; idx++) - { - hd = h_data(idx); - // not enough memory - abort (don't leave a hole in the array) - if(!hd) - return 0; - // found an empty entry - done - if(!hd->tag) - break; - } - - if(idx >= hdata_cap) - { - assert(!"h_alloc: too many open handles (increase IDX_BITS)"); - return 0; - } - - // check if next entry is free - HDATA* hd2 = h_data(idx+1); - if(hd2 && hd2->tag == 0) - first_free = idx+1; - else - first_free = -1; - - if(idx > last_in_use) - last_in_use = idx; - - static u32 tag; - if(++tag >= (1 << HTAG_BITS)) - { - assert(!"h_alloc: tag overflow - may not notice stale handle reuse (increase TAG_BITS)"); - tag = 1; - } - - hd->key = key; - hd->tag = tag; - hd->type = type; - - if(puser) - *puser = hd->user; - return handle(idx); -} - - -int h_free(Handle& h, const uint type) -{ - int idx = h_idx(h, type); - h = 0; - if(idx >= 0) - return h_free(idx); - return -1; -} - - - -void* h_user_data(const Handle h, const uint type) -{ - int idx = h_idx(h, type); - if(idx >= 0) - return h_data(idx)->user; // pointer is always valid if index is in range - return 0; -} - - - - diff --git a/source/lib/res.h b/source/lib/res.h deleted file mode 100755 index b6b144b756..0000000000 --- a/source/lib/res.h +++ /dev/null @@ -1,79 +0,0 @@ -// handle based caching resource manager -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __RES_H__ -#define __RES_H__ - -#include "types.h" - - -// handle type (for 'type safety' - can't use a texture handle as a sound) -// -// rationale: we could use the destructor passed to h_alloc to identify -// the handle, but it's good to have a list of all types, and we avoid having -// to create empty destructors for handle types that wouldn't need them. -// finally, we save memory - this fits in a few bits, vs. needing a pointer. -enum HType -{ - H_TEX = 1, - H_FONT = 2, - H_SOUND = 3, - H_ZFILE = 4, - H_ZARCHIVE = 5, - H_VFILE = 6, - H_MEM = 7, - - NUM_HANDLE_TYPES -}; - - - - -// 0 = invalid handle value. -typedef u32 Handle; - - -// destructor, registered by h_alloc for a given handle type. -// receives the user data associated with the handle. -typedef void(*H_DTOR)(void*); - - -// all functions check the passed tag (part of the handle) and type against -// the internal values. if they differ, an error is returned. - - -// allocate a new handle. -// if key is 0, or a (key, type) handle doesn't exist, -// the first free entry is used. -// otherwise, a handle to the existing object is returned, -// and HDATA.size != 0. -//// user_size is checked to make sure the user data fits in the handle data space. -// dtor is associated with type and called when the object is freed. -// handle data is initialized to 0; optionally, a pointer to it is returned. -extern Handle h_alloc(uintptr_t key, uint type,/* size_t user_size,*/ H_DTOR dtor = 0, void** puser = 0); -extern int h_free(Handle& h, uint type); - -// find and return a handle by type and key (typically filename hash) -// currently O(n). -extern Handle h_find(uintptr_t key, uint type, void** puser = 0); - -// return a pointer to handle data -extern void* h_user_data(Handle h, uint type); - - -#endif // #ifndef __RES_H__ diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index 09ba60331c..3f8ccfe132 100755 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -80,14 +80,6 @@ static inline Handle handle(const i32 idx, const i32 tag) return _idx | _tag; } -inline __int64 __declspec(naked) GetCycleCount() -{ - __asm - { - RDTSC - } -} - // // internal per-resource-instance data diff --git a/source/lib/tex.cpp b/source/lib/tex.cpp deleted file mode 100755 index 240a507b29..0000000000 --- a/source/lib/tex.cpp +++ /dev/null @@ -1,795 +0,0 @@ -// OpenGL texturing -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -// supported formats: DDS, TGA, PNG, JP2, BMP, RAW - -#include -#include -#include -#include - -#include "vfs.h" -#include "tex.h" -#include "mem.h" -#include "ogl.h" -#include "res.h" -#include "misc.h" - -#define NO_JP2 -#define NO_PNG - -#ifndef NO_JP2 -#include -#endif - -#ifndef NO_PNG -#include -#pragma comment(lib, "libpng.lib") -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// DDS -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_DDS - -// converts 4 character string to u32 for easy comparison -// can't pass code as string, and use s[0]..s[3], because -// VC6/7 don't realize the macro is constant (and it's used in a switch{}) -#ifdef BIG_ENDIAN -#define FOURCC(a,b,c,d) ( ((u32)a << 24) | ((u32)b << 16) | \ - ((u32)c << 8 ) | ((u32)d << 0 ) ) -#else -#define FOURCC(a,b,c,d) ( ((u32)a << 0 ) | ((u32)b << 8 ) | \ - ((u32)c << 16) | ((u32)d << 24) ) -#endif - -// modified from ddraw header - -#pragma pack(push, 1) - -typedef struct { u32 lo, hi; } DDCOLORKEY; - -typedef struct -{ - u32 dwSize; // size of structure - u32 dwFlags; // pixel format flags - u32 dwFourCC; // (FOURCC code) - u32 dwRGBBitCount; // how many bits per pixel - u32 dwRBitMask; // mask for red bit - u32 dwGBitMask; // mask for green bits - u32 dwBBitMask; // mask for blue bits - u32 dwRGBAlphaBitMask; // mask for alpha channel -} -DDPIXELFORMAT; - -typedef struct -{ - u32 dwCaps; // capabilities of surface wanted - u32 dwCaps2; - u32 dwCaps3; - u32 dwCaps4; -} -DDSCAPS2; - -typedef struct -{ - u32 dwSize; // size of the DDSURFACEDESC structure - u32 dwFlags; // determines what fields are valid - u32 dwHeight; // height of surface to be created - u32 dwWidth; // width of input surface - u32 dwLinearSize; // surface size - u32 dwBackBufferCount; // number of back buffers requested - u32 dwMipMapCount; // number of mip-map levels requestde - u32 dwAlphaBitDepth; // depth of alpha buffer requested - u32 dwReserved; // reserved - void* lpSurface; // pointer to the associated surface memory - DDCOLORKEY unused[4]; // src/dst overlay, blt - DDPIXELFORMAT ddpfPixelFormat; // pixel format description of the surface - DDSCAPS2 ddsCaps; // direct draw surface capabilities - u32 dwTextureStage; // stage in multitexture cascade -} -DDSURFACEDESC2; - -#pragma pack(pop) - - -static inline bool dds_valid(const u8* ptr, size_t size) -{ - UNUSED(size) // only need first 4 chars - - return *(u32*)ptr == FOURCC('D','D','S',' '); -} - - -// TODO: DXT1a? -static int dds_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - const char* err = 0; - - const DDSURFACEDESC2* surf = (const DDSURFACEDESC2*)(ptr+4); - const u32 hdr_size = 4+sizeof(DDSURFACEDESC2); - if(size < hdr_size) - err = "header not completely read"; - else - { - const u32 w = read_le32(&surf->dwWidth); - const u32 h = read_le32(&surf->dwHeight); - const u32 ddsd_size = read_le32(&surf->dwSize); - const u32 img_size = read_le32(&surf->dwLinearSize); - const u32 mipmaps = read_le32(&surf->dwMipMapCount); - - uint fmt = 0; - switch(surf->ddpfPixelFormat.dwFourCC) // endian-independent - { - case FOURCC('D','X','T','1'): - fmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - break; - case FOURCC('D','X','T','3'): - fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - case FOURCC('D','X','T','5'): - fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - } - - tex->width = w; - tex->height = h; - tex->fmt = fmt; - tex->bpp = img_size / (w * h); - tex->ofs = hdr_size; - - if(sizeof(DDSURFACEDESC2) != ddsd_size) - err = "DDSURFACEDESC2 size mismatch"; - if(size < hdr_size + img_size) - err = "not completely loaded"; - if(mipmaps > 0) - err = "contains mipmaps"; - if(fmt == 0) - err = "invalid pixel format (not DXT{1,3,5})"; - } - - if(err) - { - printf("dds_load: %s: %s\n", fn, err); - return -1; - } - - return 0; -} - -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// TGA -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_TGA - -static inline bool tga_valid(const u8* ptr, size_t size) -{ - UNUSED(size) - - // no color map; uncompressed grayscale or true color - return (ptr[1] == 0 && (ptr[2] == 2 || ptr[2] == 3)); -} - - -// requirements: uncompressed, direct color, bottom up -static int tga_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - const char* err = ""; - - const u8 img_id_len = ptr[0]; - const uint hdr_size = 18+img_id_len; - if(size < hdr_size) - err = "header not completely read"; - else - { - const u8 type = ptr[2]; - const u16 w = read_le16(ptr+12); - const u16 h = read_le16(ptr+14); - const u8 bpp = ptr[16]; - const u8 desc = ptr[17]; - - const u8 alpha_bits = desc & 0x0f; - - const ulong img_size = (ulong)w * h * bpp / 8; - - // determine format - int fmt = -1; - // .. grayscale - if(type == 3) - { - if(bpp == 8) - fmt = 0; - else if(bpp == 16 && alpha_bits == 8) - fmt = GL_LUMINANCE_ALPHA; - } - // .. true color - else if(type == 2) - { - if(bpp == 24 && alpha_bits == 0) - fmt = GL_BGR; - else if(bpp == 32 && alpha_bits == 8) - fmt = GL_BGRA; - } - - tex->width = w; - tex->height = h; - tex->fmt = fmt; - tex->bpp = bpp; - tex->ofs = hdr_size; - - if(fmt == -1) - err = "invalid format or bpp"; - if(desc & 0x18) - err = "image is not bottom-up and left-to-right"; - if(size < hdr_size + img_size) - err = "size < image size"; - } - - if(err) - { - printf("tga_load: %s: %s\n", fn, err); - return -1; - } - - return 0; -} - -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// BMP -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_BMP - -#pragma pack(push, 1) - -struct BITMAPFILEHEADER -{ - u16 bfType; // "BM" - u32 bfSize; // of file - u32 reserved; - u32 bfOffBits; // offset to image data -}; - -// BITMAPCOREHEADER + compression field -struct BITMAPCOREHEADER2 -{ - u32 biSize; - long biWidth; - long biHeight; - u16 biPlanes; // = 1 - u16 biBitCount; // bpp - u32 biCompression; -}; - -#pragma pack(pop) - -#define BI_RGB 0 // bch->biCompression - - -static inline bool bmp_valid(const u8* ptr, size_t size) -{ - UNUSED(size) - - // bfType == BM? (check single bytes => endian safe) - return ptr[0] == 'B' && ptr[1] == 'M'; -} - - -// requirements: uncompressed, direct color, bottom up -static int bmp_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - const char* err = 0; - - BITMAPFILEHEADER* bfh = (BITMAPFILEHEADER*)ptr; - BITMAPCOREHEADER2* bch = (BITMAPCOREHEADER2*)(ptr+sizeof(BITMAPFILEHEADER)); - const int hdr_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPCOREHEADER2); - if(size < hdr_size) - err = "header not completely read"; - else - { - const long w = read_le32(&bch->biWidth); - const long h = read_le32(&bch->biHeight); - const u16 bpp = read_le16(&bch->biBitCount); - const u32 compress = read_le32(&bch->biCompression); - const u32 ofs = read_le32(&bfh->bfOffBits); - - const u32 img_size = w * h * bpp/8; - - tex->width = w; - tex->height = h; - tex->fmt = (bpp == 24)? GL_BGR : GL_BGRA; - tex->bpp = bpp; - tex->ofs = ofs; - - if(h < 0) - err = "top-down"; - if(compress != BI_RGB) - err = "compressed"; - if(bpp < 24) - err = "not direct color"; - if(size < ofs+img_size) - err = "image not completely read"; - } - - if(err) - { - printf("bmp_load: %s: %s\n", fn, err); - return -1; - } - - return 0; -} -// TODO: no extra buffer needed here; dealloc? - -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// RAW -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_RAW - -static inline bool raw_valid(const u8* p, size_t size) -{ - UNUSED(p) - UNUSED(size) - - return true; -} - - -static int raw_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - static GLenum fmts[5] = { 0, 0, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; - for(int i = 1; i <= 4; i++) - { - u32 dim = (u32)sqrtf((float)size/i); - // TODO: differentiate 8/32 bpp - if(dim*dim*i != size) - continue; - - tex->width = dim; - tex->height = dim; - tex->fmt = fmts[i]; - tex->bpp = i * 8; - tex->ofs = 0; - - return 0; - } - - printf("raw_load: %s: %s\n", fn, "no matching format found"); - return -1; -} - -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// PNG -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_PNG - -struct MemRange -{ - const u8* p; - size_t size; -}; - - -static void png_read_fn(png_struct* png_ptr, u8* data, png_size_t length) -{ - MemRange* const mr = (MemRange*)png_ptr->io_ptr; - mr->size -= length; - if(mr->size < 0) - png_error(png_ptr, "png_read_fn: no data remaining"); - - memcpy(data, mr->ptr, length); - mr->ptr += length; -} - - -static inline bool png_valid(const u8* ptr, size_t size) -{ - return png_sig_cmp((u8*)ptr, 0, min(size, 8)) == 0; -} - - -// requirement: direct color -static int png_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - const char* err = 0; - - // allocate PNG structures - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - if(!png_ptr) - return -1; - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) - { - png_destroy_read_struct(&png_ptr, 0, 0); - return -1; - } - - // setup error handling - if(setjmp(png_jmpbuf(png_ptr))) - { -fail: - printf("png_load: %s: %s\n", fn, err? err : ""); - png_destroy_read_struct(&png_ptr, &info_ptr, 0); - return -1; - } - - MemRange mr = { ptr, size }; - png_set_read_fn(png_ptr, &mr, png_read_fn); - - png_read_info(png_ptr, info_ptr); - unsigned long width, height; - int prec, color_type; - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); - - // can only handle 8 bits per channel - if(prec != 8) - { - err = "channel precision != 8"; - goto fail; - } - - // allocate mem for image - rows point into buffer (sequential) - int pitch = png_get_rowbytes(png_ptr, info_ptr); - u8* img = (u8*)malloc(pitch * (height+1)); - u8** rows = (u8**)png_malloc(png_ptr, (height+1)*sizeof(void*)); - for(u32 i = 0; i < height+1; i++) - rows[i] = img + i*pitch; - - png_read_image(png_ptr, rows); - - png_read_end(png_ptr, 0); - png_destroy_read_struct(&png_ptr, &info_ptr, 0); - - // store info in ti - tex->width = width; tex->height = height; - - int fmts[8] = { 0, -1, GL_RGB, -1, GL_LUMINANCE_ALPHA, -1, GL_RGBA, -1 }; - if(color_type >= 8) - return -1; - tex->fmt = fmts[color_type]; - if(tex->fmt == -1) // <==> palette image - { - printf("png_load: %s: %s\n", fn, "not direct color"); - return -1; - } - - tex->ptr = img; - tex->bpp = pitch / width * 8; - - return 0; -} - -#endif - - -////////////////////////////////////////////////////////////////////////////// -// -// JP2 -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_JP2 - -static inline bool jp2_valid(const u8* p, size_t size) -{ - static bool initialized; - if(!initialized) - { - jas_init(); - initialized = true; - } - - jas_stream_t* stream = jas_stream_memopen((char*)ptr, size); - return jp2_validate(stream) >= 0; -} - - -static int jp2_load(const char* fn, const u8* ptr, size_t size, TEX* tex) -{ - const char* err = 0; - - jas_stream_t* stream = jas_stream_memopen((char*)ptr, size); - jas_image_t* image = jas_image_decode(stream, -1, 0); - if(!image) - return -1; - - int num_cmpts = jas_image_numcmpts(image); - jas_matrix_t* matr[4] = {0}; - jas_seqent_t* rows[4] = {0}; - int width = jas_image_cmptwidth (image, 0); - int height = jas_image_cmptheight(image, 0); - int prec = jas_image_cmptprec (image, 0); - - if(depth != 8) - { - err = "channel precision != 8"; - printf("jp2_load: %s: %s\n", fn, err); -// TODO: destroy image - return -1; - } - - u8* img = (u8*)malloc(width*height*num_cmpts); - u8* out = img; - - int cmpt; - for(cmpt = 0; cmpt < num_cmpts; cmpt++) - matr[cmpt] = jas_matrix_create(1, width); - - for(int y = 0; y < height; y++) - { - for(cmpt = 0; cmpt < num_cmpts; cmpt++) - { - jas_image_readcmpt(image, cmpt, 0, y, width, 1, matr[cmpt]); - rows[cmpt] = jas_matrix_getref(matr[cmpt], 0, 0); - } - - for(int x = 0; x < width; x++) - for(cmpt = 0; cmpt < num_cmpts; cmpt++) - *out++ = *rows[cmpt]++; - } - - for(cmpt = 0; cmpt < num_cmpts; cmpt++) - jas_matrix_destroy(matr[cmpt]); - - tex->width = width; - tex->height = height; - tex->fmt = GL_RGB; - tex->bpp = num_cmpts * 8; - tex->ptr = img; - - return 0; -} - -#endif - - - - -static void tex_dtor(void* p) -{ - TEX* tex = (TEX*)p; - - mem_free(tex->hm); - - glDeleteTextures(1, &tex->id); -} - - -// TEX output param is invalid if function fails -Handle tex_load(const char* fn, TEX* ptex) -{ - const u32 fn_hash = fnv_hash(fn, strlen(fn)); - - TEX* tex; - Handle ht = h_alloc(fn_hash, H_TEX, tex_dtor, (void**)&tex); - if(!ht) - return 0; - if(tex->id != 0) - goto already_loaded; - -{ - // load file - const u8* p; - size_t size; - Handle hm = vfs_load(fn, (void*&)p, size); - // .. note: xxx_valid routines assume 4 header bytes are available - if(!hm || !p || size < 4) - { - h_free(ht, H_TEX); - return 0; - } - tex->hm = hm; - - int err = -1; - -#ifndef NO_DDS - if(dds_valid(p, size)) - err = dds_load(fn, p, size, tex); else -#endif -#ifndef NO_PNG - if(png_valid(p, size)) - err = png_load(fn, p, size, tex); else -#endif -#ifndef NO_JP2 - if(jp2_valid(p, size)) - err = jp2_load(fn, p, size, tex); else -#endif -#ifndef NO_BMP - if(bmp_valid(p, size)) - err = bmp_load(fn, p, size, tex); else -#endif -#ifndef NO_TGA - if(tga_valid(p, size)) - err = tga_load(fn, p, size, tex); else -#endif -#ifndef NO_RAW - if(raw_valid(p, size)) - err = raw_load(fn, p, size, tex); else -#endif - ; // make sure else chain is ended - - if(err < 0) - return err; - - // loaders weren't able to determine type - if(tex->fmt == 0) - { - assert(tex->bpp == 8); - tex->fmt = GL_ALPHA; - // TODO: check file name, go to 32 bit if wrong - } - - uint id; - glGenTextures(1, &id); - tex->id = id; - // this can't realistically fail, just note that the already_loaded - // check above assumes (id > 0) <==> texture is loaded and valid -} - -already_loaded: - if(ptex) - *ptex = *tex; - - return ht; -} - - -int tex_bind(const Handle h) -{ - TEX* tex = (TEX*)h_user_data(h, H_TEX); - if(!tex) - { - glBindTexture(GL_TEXTURE_2D, 0); - return -1; - } - else - { - glBindTexture(GL_TEXTURE_2D, tex->id); - return 0; - } -} - - -int tex_filter = GL_LINEAR; -uint tex_bpp = 32; // 16 or 32 - -int tex_upload(const Handle ht, int filter, int int_fmt) -{ - TEX* tex = (TEX*)h_user_data(ht, H_TEX); - if(!tex) - return -1; - - // greater than max supported tex dimension? - // no-op if oglInit not yet called - if(tex->width > (uint)max_tex_size || tex->height > (uint)max_tex_size) - { - assert(!"tex_upload: image dimensions exceed OpenGL implementation limit"); - return 0; - } - - // both NV_texture_rectangle and subtexture require work for the client - // (changing tex coords) => we'll just disallow non-power of 2 textures. - // TODO: ARB_texture_non_power_of_two - if(!is_pow2(tex->width) || !is_pow2(tex->height)) - { - assert(!"tex_upload: image is not power-of-2"); - return 0; - } - - tex_bind(ht); - - // get pointer to image data - MEM* mem = (MEM*)h_user_data(tex->hm, H_MEM); - if(!mem) - return 0; - void* p = mem->p; - if(!p) - { - assert(0 && "tex_upload: mem object is a NULL pointer"); - return 0; - } - - // set filter - if(!filter) - filter = tex_filter; - const int mag = (filter == GL_NEAREST)? GL_NEAREST : GL_LINEAR; - const bool mipmap = (filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_LINEAR_MIPMAP_NEAREST || - filter == GL_NEAREST_MIPMAP_LINEAR || filter == GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag); - - - const bool has_alpha = tex->fmt == GL_RGBA || tex->fmt == GL_BGRA || tex->fmt == GL_LUMINANCE_ALPHA || tex->fmt == GL_ALPHA; - - // S3TC compressed - if(tex->fmt >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT && - tex->fmt <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) - { - const int img_size = tex->width * tex->height * tex->bpp; - assert(4+sizeof(DDSURFACEDESC2)+img_size == mem->size && "tex_upload: dds file size mismatch"); - glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, tex->fmt, tex->width, tex->height, 0, img_size, p); - } - // normal - else - { - // calc internal fmt from format and global bpp, if not passed as a param - if(!int_fmt) - { - if(tex->bpp == 32) - int_fmt = (tex_bpp == 32)? GL_RGBA8 : GL_RGBA4; - else if(tex->bpp == 24) - int_fmt = (tex_bpp == 32)? GL_RGB8 : GL_RGB5; - else if(tex->bpp == 16) - int_fmt = (tex_bpp == 32)? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE4_ALPHA4; - else if(tex->fmt == GL_ALPHA) - int_fmt = (tex_bpp == 32)? GL_ALPHA8 : GL_ALPHA4; - else if(tex->fmt == GL_LUMINANCE) - int_fmt = (tex_bpp == 32)? GL_LUMINANCE8 : GL_LUMINANCE4; - else - return -1; - } - - // check if SGIS_generate_mipmap is available (once) - static int sgm_avl = -1; - if(sgm_avl == -1) - sgm_avl = oglExtAvail("GL_SGIS_generate_mipmap"); - - // manual mipmap gen via GLU (box filter) - if(mipmap && !sgm_avl) - gluBuild2DMipmaps(GL_TEXTURE_2D, int_fmt, tex->width, tex->height, tex->fmt, GL_UNSIGNED_BYTE, p); - // auto mipmap gen, or no mipmap - else - { - if(mipmap) - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); - - glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, tex->width, tex->height, 0, tex->fmt, GL_UNSIGNED_BYTE, p); - } - } - - mem_free(tex->hm); - - return 0; -} diff --git a/source/lib/tex.h b/source/lib/tex.h deleted file mode 100755 index 00b3bcbd30..0000000000 --- a/source/lib/tex.h +++ /dev/null @@ -1,55 +0,0 @@ -// OpenGL texturing -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __TEX_H__ -#define __TEX_H__ - -#include "types.h" -#include "res.h" -#include "misc.h" - -struct TEX -{ - u32 width : 16; - u32 height : 16; - u32 fmt : 16; - u32 bpp : 16; - Handle hm; // H_MEM handle to loaded file - size_t ofs; // WRT image data in file - uint id; -}; - - - - -// load and return a handle to the texture given in . -// supports RAW, BMP, JP2, PNG, TGA, DDS -// optionally returns a copy of information about the texture. -extern Handle tex_load(const char* fn, TEX* tex_info = 0); - -extern int tex_bind(Handle h); - - -extern int tex_filter; // GL values; default: GL_LINEAR -extern uint tex_bpp; // 16 or 32; default: 32 - -// upload the specified texture to OpenGL. Texture filter and internal format -// may be specified to override the global defaults. -extern int tex_upload(Handle h, int filter_override = 0, int internal_fmt_override = 0); - -#endif // __TEX_H__ diff --git a/source/lib/time.cpp b/source/lib/time.cpp deleted file mode 100755 index 4c9edcd624..0000000000 --- a/source/lib/time.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// platform indepentend high resolution timer -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#include -#include - -#include "win.h" - -#include "ia32.h" -#include "posix.h" -#include "detect.h" -#include "time.h" -#include "types.h" -#include "misc.h" - - - -// high resolution (> 1 µs) timestamp [s], starting at or near 0 s. -// -// uses TSC on single processor x86 desktop systems unless NO_TSC is defined, -// otherwise platform specific timers (QueryPerformanceCounter, gettimeofday). -double get_time() -{ - static double to_s; - double t; - -#if defined(_M_IX86) && !defined(NO_TSC) - static int use_tsc = -1; - static u64 tsc_start; - - // spaghetti code for minimum timing overhead -first_tsc: - if(use_tsc == 1) - return (__int64)(rdtsc() - tsc_start) * to_s; - // VC6 can't convert u64 -> double; we don't need full range anyway - // don't know yet - if(use_tsc == -1) - // don't use yet - need a time reference for CPU freq calculation. - if(cpu_freq != 0.0f) - // use only on single processor desktop systems - // (otherwise CPU freq may change, clocks may get out of sync) - if(cpus == 1 && !is_notebook && (cpu_caps & TSC)) - { - use_tsc = 1; - to_s = 1.0 / cpu_freq; - tsc_start = rdtsc(); - goto first_tsc; // using the other timers now would trash to_s - } - else - use_tsc = 0; -#endif - -#ifdef _WIN32 - - static LARGE_INTEGER start; - LARGE_INTEGER i; - - if(!to_s) - { - QueryPerformanceFrequency(&i); - to_s = 1.0 / i.QuadPart; - - QueryPerformanceCounter(&start); - } - - QueryPerformanceCounter(&i); - t = (i.QuadPart - start.QuadPart) * to_s; - -#else - - static struct timeval start; - struct timeval tv; - - if(!start.tv_sec) - gettimeofday(&start, 0); - - gettimeofday(&tv, 0); - t = (tv.tv_sec - start.tv_sec) + (tv.tv_usec - start.tv_usec)*1e-6; - -#endif - - return t; -} - - - - -// calculate fps (call once per frame) -// several smooth filters: -// - throw out single spikes / dips -// - average via small history buffer -// - update final value iff the difference (% or absolute) is too great, -// or if the change is consistent with the trend over the last few frames. -// -// => less fluctuation, but rapid tracking. -// filter values are tuned for 100 FPS. - -int fps = 0; - -void calc_fps() -{ - // history buffer - smooth out slight variations -#define H 10 // # buffer entries - static float fps_sum = 0; // sum of last H frames' cur_fps - static float fps_hist[H]; // last H frames' cur_fps - // => don't need to re-average every time - static uint head = 0; // oldest entry in fps_hist - // must be unsigned, b/c we do (head-1)%H - - // get elapsed time [s] since last frame; approximate current fps - static double last_t; - double t = get_time(); - float cur_fps = 30.0f; // start value => history converges faster - if(last_t != 0.0) - cur_fps = 1.0f / (float)(t-last_t); // = 1 / elapsed time - last_t = t; - - // calculate fps activity over 3 frames (used below to prevent fluctuation) - // -1: decreasing, +1: increasing, 0: neither or fluctuating - float h1 = fps_hist[(head-1)%H]; // last frame's cur_fps - float h2 = fps_hist[(head-2)%H]; // 2nd most recent frame's cur_fps - - int trend = 0; - if(h2 > h1 && h1 > cur_fps) // decreasing - trend = -1; - else if(cur_fps < h1 && h1 < h2) // increasing - trend = 1; - - // ignore onetime skips in fps (probably page faults or similar) - static int bad = 0; // bad > 0 <==> last value was skipped - if(fabs(h1-cur_fps) > .05f*h1) // > 5% difference - { - // first 'bad' value: don't update fps_hist/fps; otherwise, reset bad - if(!bad++) - return; - } - else - bad = 0; - - // remove oldest cur_fps value in fps_hist from the sum - // and add cur_fps; also insert cur_fps in fps_hist - fps_sum -= fps_hist[head]; - fps_sum += (fps_hist[head] = cur_fps); - head = (head+1)%H; - - // update fps counter if update threshold is exceeded - const float avg_fps = fps_sum / H; - const float d_avg = avg_fps-fps; - const float max_diff = fminf(5.f, 0.05f*fps); - - if((trend > 0 && (avg_fps > fps || d_avg < -4.f)) || // going up, or large drop - (trend < 0 && (avg_fps < fps || d_avg > 4.f)) || // going down, or large raise - (fabs(d_avg) > max_diff)) // significant difference - fps = (int)avg_fps; -} diff --git a/source/lib/time.h b/source/lib/time.h deleted file mode 100755 index 591fe7e654..0000000000 --- a/source/lib/time.h +++ /dev/null @@ -1,44 +0,0 @@ -// platform indepentend high resolution timer -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __TIME_H__ -#define __TIME_H__ - -#ifdef __cplusplus -extern "C" { -#endif - - -// high resolution (> 1 µs) timestamp [s], starting at or near 0 s. -extern double get_time(); - - -// calculate fps (call once per frame) -// several smooth filters (tuned for ~100 FPS) -// => less fluctuation, but rapid tracking - -extern int fps; - -extern void calc_fps(); - - -#ifdef __cplusplus -} -#endif - -#endif // #ifndef __TIME_H__ diff --git a/source/lib/vfs.cpp b/source/lib/vfs.cpp deleted file mode 100755 index 4f665059d9..0000000000 --- a/source/lib/vfs.cpp +++ /dev/null @@ -1,567 +0,0 @@ -// virtual file system - transparent access to files in archives; -// allows multiple search paths -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#include -#include -#include -#include - -#include -#include -#include - -#include "posix.h" -#include "zip.h" -#include "misc.h" -#include "vfs.h" -#include "mem.h" - - -// H_VFILE handle -struct VFILE -{ - int fd; - - size_t size; // compressed size, if a Zip file - - // Zip only: - size_t ucsize; - size_t ofs; - - Handle hm; // memory handle to the file or archive, if a Zip file -}; - - -// rationale for n-archives per PATH entry: -// We need to be able to unmount specific paths (e.g. when switching mods). -// Don't want to remount everything (slow), or specify a mod tag when mounting -// (not this module's job). Instead, we include all archives in one path entry; -// the game keeps track of what path(s) it mounted for a mod, -// and unmounts those when needed. - -struct PATH -{ - struct PATH* next; // linked list - - char* dir; // relative to root dir; - // points to space at end of this struct - - size_t num_archives; - Handle archives[1]; - - // space allocated here for archive Handles + dir string -}; -static PATH* path_list; - - -static void vfile_dtor(void* p) -{ - VFILE* vf = (VFILE*)p; - - if(vf->fd > 0) - { - close(vf->fd); - vf->fd = -1; - } - - mem_free(vf->hm); -} - - -int vfs_set_root(const char* argv0, const char* root) -{ - if(access(argv0, X_OK) != 0) - return -1; - - char path[PATH_MAX+1]; - path[PATH_MAX] = 0; - if(!realpath(argv0, path)) - return -1; - - // remove executable name - char* fn = strrchr(path, DIR_SEP); - if(!fn) - return -1; - *fn = 0; - - chdir(path); - chdir(root); - - return vfs_mount("."); -} - - -int vfs_mount(const char* path) -{ - const size_t path_len = strlen(path); - if(path_len > VFS_MAX_PATH) - { - assert(!"vfs_mount_dir: path name is longer than VFS_MAX_PATH"); - return -1; - } - - // enumerate all archives in - std::vector archives; - DIR* dir = opendir(path); - struct dirent* ent; - while((ent = readdir(dir))) - { - struct stat s; - if(stat(ent->d_name, &s) < 0) - continue; - if(s.st_mode == S_IFREG) // regular file - archives.push_back(ent->d_name); - } - closedir(dir); - const size_t num_archives = archives.size(); - - // alloc search path entry (add to front) - const size_t archives_size = num_archives*sizeof(Handle); - const size_t entry_size = round_up((long)(sizeof(PATH)+archives_size+path_len+1), 32); - PATH* entry = (PATH*)mem_alloc(entry_size, 32, MEM_HEAP); - if(!entry) - return -1; - entry->next = path_list; - path_list = entry; - - entry->dir = (char*)&entry->archives[0] + archives_size; - strcpy(entry->dir, path); - - // add archives in alphabetical order - std::sort(archives.begin(), archives.end()); - entry->num_archives = num_archives; - for(size_t i = 0; i < num_archives; i++) - entry->archives[i] = zip_open(archives[i].c_str()); - - return 0; -} - - -int vfs_umount(const char* path) -{ - PATH** prev = &path_list; - PATH* entry = path_list; - while(entry) - { - // found - if(!strcmp(entry->dir, path)) - { - // close all archives - for(size_t i = 0; i < entry->num_archives; i++) - h_free(entry->archives[i], H_ZARCHIVE); - - // remove from list - *prev = entry->next; - mem_free(entry); - - return 0; - } - - prev = &entry->next; - entry = entry->next; - } - - // not found - return -1; -} - - -// call func, passing the data argument, for each mounted path -// fail if its return value is < 0, stop if it returns 0 -static int vfs_foreach_path(int (*func)(const char* path, Handle ha, void* data), const char* fn, void* data) -{ - char buf[PATH_MAX+1]; buf[PATH_MAX] = 0; - - for(PATH* entry = path_list; entry; entry = entry->next) - { - // dir - const char* path = fn; - if(entry->dir[0] != '.' || entry->dir[1] != '\0') - { - // only prepend dir if not "." (root) - "./" isn't portable - snprintf(buf, PATH_MAX, "%s/%s", entry->dir, fn); - path = buf; - } - - int err = func(path, 0, data); - if(err <= 0) - return err; - - // archive - for(size_t i = 0; i < entry->num_archives; i++) - { - err = func(path, entry->archives[i], data); - if(err <= 0) - return err; - } - } - - return -1; // func never returned 0 -} - - - -static int realpath_cb(const char* path, Handle ha, void* data) -{ - char* full_path = (char*)data; - struct stat s; - - if(!path && !ha) - { - assert(0 && "realpath_cb: called with invalid path and archive handle"); - return 1; - } - - if(path) - { - if(!stat(path, &s)) - { - strncpy(full_path, path, PATH_MAX); - return 0; - } - } - else if(ha) - { - if(!zip_stat(ha, path, &s)) - { - zip_archive_info(ha, full_path, 0); - return 0; - } - } - - return 1; -} - -int vfs_realpath(const char* fn, char* full_path) -{ - return vfs_foreach_path(realpath_cb, fn, full_path); -} - - -static int stat_cb(const char* path, Handle ha, void* data) -{ - struct stat* s = (struct stat*)data; - - if(path) - return stat(path, s)? 1 : 0; - else if(ha) - return zip_stat(ha, path, s)? 1 : 0; - - assert(0 && "stat_cb: called with invalid path and archive handle"); - return 1; -} - -int vfs_stat(const char* fn, struct stat* s) -{ - return vfs_foreach_path(stat_cb, fn, s); -} - - - -static int open_cb(const char* path, Handle ha, void* data) -{ - struct stat s; - VFILE* vf = (VFILE*)data; - - // normal file - if(path) - { - if(stat(path, &s) < 0) - return 1; - - int fd = open(path, O_RDONLY); - if(fd < 0) - return 1; - - vf->fd = fd; - vf->size = s.st_size; - } - // from archive - else if(ha) - { - ZFILE* zf = zip_lookup(ha, path); - if(!zf) - return 1; - - Handle hm; - if(zip_archive_info(ha, 0, &hm) < 0) - return 1; - - vf->ofs = zf->ofs; - vf->size = zf->csize; - vf->ucsize = zf->ucsize; - vf->fd = -1; - vf->hm = hm; - } - else - { - assert(0 && "open_cb: called with invalid path and archive handle"); - return 1; - } - - return 0; -} - -Handle vfs_open(const char* fn) -{ - u32 fn_hash = fnv_hash(fn, strlen(fn)); - - VFILE* vf; - Handle hv = h_alloc(fn_hash, H_VFILE, vfile_dtor, (void**)&vf); - if(!hv) - return 0; - - // already open - if(vf->size) - return hv; - - if(vfs_foreach_path(open_cb, fn, vf) < 0) - { - h_free(hv, H_VFILE); - return 0; - } - - return hv; -} - - - -const uint IDX_BITS = 4; -const uint NUM_SLOTS = 1ul << IDX_BITS; -const uint TAG_BITS = 32 - IDX_BITS; -static struct Slot -{ - u32 tag; // = 0 <==> slot available - struct aiocb cb; -} -slots[NUM_SLOTS]; - -u32 vfs_start_read(const Handle hf, size_t& ofs, void** buf) -{ - VFILE* vf = (VFILE*)h_user_data(hf, H_VFILE); - if(!vf) - return 0; - - if(ofs >= vf->size) - return 0; - size_t bytes_left = vf->size - ofs; - -// TODO: thread safety - - // find a free slot - int i = 0; - Slot* s = slots; - for(; i < NUM_SLOTS; i++, s++) - if(!s->tag) - break; - if(i == NUM_SLOTS) - { - assert(!"vfs_start_read: too many active reads; increase NUM_SLOTS"); - return 0; - } - - // mark it in use - static u32 tag; - if(++tag == 1ul << TAG_BITS) - { - assert(!"vfs_start_read: tag overflow!"); - tag = 1; - } - s->tag = tag; - - struct aiocb* cb = &s->cb; - - // use the buffer given (e.g. read directly into output buffer) - if(buf) - cb->aio_buf = *buf; - // allocate our own (reused for subsequent requests) - else - if(!cb->aio_buf) - { - cb->aio_buf = mem_alloc(64*KB, 64*KB, MEM_HEAP); - if(!cb->aio_buf) - return 0; - } - - // align to 64 KB for speed - size_t rsize = 64*KB - (ofs & 0xffff); // min(~, bytes_left) - avoid warning - if(rsize > bytes_left) - rsize = bytes_left; - - cb->aio_offset = (off_t)ofs; - cb->aio_nbytes = rsize; - aio_read(cb); - - ofs += rsize; - if(buf) - (size_t&)*buf += rsize; - - return 0; -} - - -int vfs_finish_read(const u32 slot, void*& p, size_t& size) -{ - p = 0; - size = 0; - - const uint idx = slot & (NUM_SLOTS-1); - const u32 tag = slot >> IDX_BITS; - Slot* const s = &slots[idx]; - if(s->tag != tag) - { - assert(!"vfs_finish_read: invalid slot"); - return -1; - } - - struct aiocb* cb = &s->cb; - - // wait for read to complete - while(aio_error(cb) == -EINPROGRESS) - aio_suspend(&cb, 1, 0); - - ssize_t bytes_read = aio_return(cb); - - s->tag = 0; // free this slot - - p = (void *)cb->aio_buf; - size = bytes_read; - - return (bytes_read > 0)? 0 : -1; -} - - - -Handle vfs_load(const char* fn, void*& _p, size_t& _size, bool dont_map) -{ - _p = 0; - _size = 0; - - Handle hf = vfs_open(fn); - if(!hf) - return 0; - - VFILE* vf = (VFILE*)h_user_data(hf, H_VFILE); - - const bool deflated = vf->fd == -1 && vf->size != vf->ucsize; - const size_t in_size = vf->size; - const size_t out_size = deflated? vf->ucsize : vf->size; - - // already mapped or read - if(vf->hm) - { - MEM* m = (MEM*)h_user_data(vf->hm, H_MEM); - if(m) - { - assert(out_size == m->size && "vfs_load: mismatch between VFILE and MEM size"); - - _p = m->p; - _size = m->size; - return vf->hm; - } - else - assert(0 && "vfs_load: invalid MEM attached to VFILE"); - } - - // decide whether to map the file, or read it - MemType mt = MEM_MAPPED; - if(deflated || dont_map) - mt = MEM_POOL; - - // allocate memory / map the file - Handle hm; - void* out = mem_alloc(out_size, 64*KB, mt, vf->fd, &hm); - if(!out) - { - vfs_close(hf); - return 0; - } - - if(mt == MEM_MAPPED) - { - _p = out; - _size = out_size; - return vf->hm = hm; - } - - // now we read the file in 64 KB chunks (double buffered); - // if in an archive, we inflate while waiting for the next chunk to finish - u32 slots[2]; - int active_read = 0; - - void* pos = out; // if not inflating, read directly into output buffer - size_t ofs = vf->ofs; - - void* ctx; - if(deflated) - { - pos = 0; // read into separate buffer - ctx = zip_inflate_start(out, out_size); - } - - bool first = true; - bool done = false; - - for(;;) - { - // start reading next block - if(!done) - slots[active_read] = vfs_start_read(hf, ofs, &pos); - - active_read ^= 1; - - // process block read in previous iteration - if(!first) - { - void* p; - size_t bytes_read; - vfs_finish_read(slots[active_read], p, bytes_read); - - // inflate what we read - if(deflated) - zip_inflate_process(ctx, p, bytes_read); - } - - first = false; - if(done) - break; - // one more iteration to process the last pending block - if(ofs >= in_size) - done = true; - } - - if(deflated) - { - if(zip_inflate_end(ctx) < 0) - { - mem_free(out); - return 0; - } - } - - _p = out; - _size = out_size; - return vf->hm = hm; -} - - -int vfs_close(Handle h) -{ - return h_free(h, H_VFILE); -} diff --git a/source/lib/vfs.h b/source/lib/vfs.h deleted file mode 100755 index 5ab74e2378..0000000000 --- a/source/lib/vfs.h +++ /dev/null @@ -1,41 +0,0 @@ -// virtual file system - transparent access to files in archives; -// allows multiple search paths -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __VFS_H__ -#define __VFS_H__ - -#include "res.h" - -#define VFS_MAX_PATH 40 - -extern int vfs_set_root(const char* argv0, const char* root); -extern int vfs_mount(const char* path); -extern int vfs_umount(const char* path); - -extern int vfs_stat(const char* fn, struct stat *buffer); -extern int vfs_realpath(const char* fn, char* realpath); - -extern Handle vfs_load(const char* fn, void*& p, size_t& size, bool dont_map = false); - -extern Handle vfs_open(const char* fn); -extern int vfs_close(Handle h); -extern u32 vfs_start_read(Handle hf, size_t& ofs, void** buf = 0); -extern int vfs_finish_read(u32 slot, void*& p, size_t& size); - -#endif // #ifndef __VFS_H__ \ No newline at end of file diff --git a/source/lib/win.h b/source/lib/win.h deleted file mode 100755 index 52f0adee6e..0000000000 --- a/source/lib/win.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifdef _WIN32 - -#ifndef __WIN_H__ -#define __WIN_H__ - -// Win32 socket decls aren't portable (e.g. problems with socklen_t) -// => skip winsock.h; posix.h should be used instead - -#define _WINSOCKAPI_ - -#define WIN32_LEAN_AND_MEAN -#define VC_EXTRALEAN - -// set version; needed for EnumDisplayDevices -#define _WIN32_WINNT 0x0500 - - -#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ -//#define NOVIRTUALKEYCODES // VK_* -//#define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* -//#define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* -#define NOSYSMETRICS // SM_* -#define NOMENUS // MF_* -#define NOICONS // IDI_* -#define NOKEYSTATES // MK_* -//#define NOSYSCOMMANDS // SC_* -#define NORASTEROPS // Binary and Tertiary raster ops -//#define NOSHOWWINDOW // SW_* -#define OEMRESOURCE // OEM Resource values -#define NOATOM // Atom Manager routines -//#define NOCLIPBOARD // Clipboard routines -#define NOCOLOR // Screen colors -#define NOCTLMGR // Control and Dialog routines -#define NODRAWTEXT // DrawText() and DT_* -//#define NOGDI // All GDI defines and routines -//#define NOKERNEL // All KERNEL defines and routines -//#define NOUSER // All USER defines and routines -#define NONLS // All NLS defines and routines -//#define NOMB // MB_* and MessageBox() -#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines -#define NOMETAFILE // typedef METAFILEPICT -#define NOMINMAX // Macros min(a,b) and max(a,b) -//#define NOMSG // typedef MSG and associated routines -#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* -#define NOSCROLL // SB_* and scrolling routines -#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. -//#define NOSOUND // Sound driver routines -#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines -//#define NOWH // SetWindowsHook and WH_* -#define NOWINOFFSETS // GWL_*, GCL_*, associated routines -//#define NOCOMM // COMM driver routines -#define NOKANJI // Kanji support stuff. -#define NOHELP // Help engine interface. -#define NOPROFILER // Profiler interface. -#define NODEFERWINDOWPOS // DeferWindowPos routines -#define NOMCX // Modem Configuration Extensions - -#include - -// VC6 windows.h doesn't define these -#ifndef INVALID_FILE_ATTRIBUTES -#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) -#endif - -#ifndef PROCESSOR_ARCHITECTURE_AMD64 -#define PROCESSOR_ARCHITECTURE_AMD64 9 -#endif - -// end VC6 fixes - - -// HACK: warning-free definition for ICC (value is -1) -#undef INVALID_HANDLE_VALUE -const HANDLE INVALID_HANDLE_VALUE = (HANDLE)(((char*)0) + ~0); - -#define HANDLE2INT(_h) ((char *)_h - (char *)0) - -extern "C" { -extern int _get_osfhandle(int); -extern int _open(const char* fn, int mode, ...); -extern int _close(int); -extern int aio_open_winhandle(HANDLE); - -#ifndef NO_WINSOCK -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") -#endif - -extern __declspec(dllimport) int __stdcall WSAAsyncSelect(int s, HANDLE hWnd, unsigned int wMsg, long lEvent); - -#define FD_READ_BIT 0 -#define FD_READ (1 << FD_READ_BIT) - -#define FD_WRITE_BIT 1 -#define FD_WRITE (1 << FD_WRITE_BIT) - -#define FD_ACCEPT_BIT 3 -#define FD_ACCEPT (1 << FD_ACCEPT_BIT) - -#define FD_CONNECT_BIT 4 -#define FD_CONNECT (1 << FD_CONNECT_BIT) - -#define FD_CLOSE_BIT 5 -#define FD_CLOSE (1 << FD_CLOSE_BIT) - -extern __declspec(dllimport) int __stdcall WSAStartup(WORD, void*); -extern __declspec(dllimport) int __stdcall WSAGetLastError(); -#endif -} - -#endif // #ifndef __WIN_H__ -#endif // #ifdef _WIN32 \ No newline at end of file diff --git a/source/lib/wsdl.cpp b/source/lib/wsdl.cpp deleted file mode 100755 index 7611fbe1d5..0000000000 --- a/source/lib/wsdl.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/* - * emulation of a subset of SDL and GLUT for Win32 - * - * Copyright (c) 2003 Jan Wassenberg - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Contact info: - * Jan.Wassenberg@stud.uni-karlsruhe.de - * http://www.stud.uni-karlsruhe.de/~urkt/ - */ - -#include -#include - -#include - -#include "wsdl.h" -#include "win.h" -#include "misc.h" - -#ifdef _MSC_VER -#pragma comment(lib, "user32.lib") -#pragma comment(lib, "gdi32.lib") -#endif - - - -/* state */ -static bool app_active; /* is window active & on top? - if not, msg loop should yield */ -static bool fullscreen; /* in fullscreen mode? - if so, restore mode when app is deactivated */ - -HWND hWnd = 0; /* available to the app for ShowWindow calls, etc. */ - -static DEVMODE dm; /* current video mode */ -static HDC hDC; -static HGLRC hGLRC; - -static int z_depth = 24; /* depth buffer size; set via SDL_GL_SetAttribute */ - -static u16 mouse_x, mouse_y; - - - -/* - * shared msg handler - * SDL and GLUT have separate pumps; messages are handled there - */ -static LRESULT CALLBACK wndproc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) -{ - switch(uMsg) - { - case WM_PAINT: - PAINTSTRUCT ps; - BeginPaint(hWnd, &ps); - EndPaint(hWnd, &ps); - return 0; - - 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; - - if(fullscreen) - { - if(app_active) - ChangeDisplaySettings(&dm, CDS_FULLSCREEN); - else - ChangeDisplaySettings(0, 0); - } - break; - - case WM_CLOSE: - exit(0); - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - - -int SDL_PollEvent(SDL_Event* ev) -{ - if(!ev) - return -1; - - // events that trigger messages (mouse done below) - MSG msg; - while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - - int sdl_btn = -1; - - switch(msg.message) - { - // - case WM_KEYUP: - case WM_KEYDOWN: - ev->type = (u8)((msg.message == WM_KEYUP)? SDL_KEYUP : SDL_KEYDOWN); - ev->key.keysym.sym = (SDLKey)msg.wParam; - return 1; - - // - case WM_ACTIVATE: - ev->type = SDL_ACTIVE; - ev->active.gain = app_active; - ev->active.state = 0; - return 1; - - // - case WM_MOUSEWHEEL: - sdl_btn = (msg.wParam & BIT(31))? SDL_BUTTON_WHEELUP : SDL_BUTTON_WHEELDOWN; - break; // event filled in mouse code below - } - - // mouse button - // map Win L(up,down,double),R(),M() to L,R,M with up flag - uint btn = msg.message-0x201; // 0..8 if it's a valid button; - if(btn < 9 && btn%3 != 2) // every third msg is dblclick - sdl_btn = SDL_BUTTON_LEFT + btn/3; // assumes L,R,M - if(sdl_btn != -1) - { - ev->type = SDL_MOUSEBUTTONDOWN + btn%3; - ev->button.button = (u8)sdl_btn; - ev->button.x = (u16)(msg.lParam & 0xffff); - ev->button.y = (u16)((msg.lParam >> 16) & 0xffff); - return 1; - } - } - - // mouse motion - // - // don't use DirectInput, because we want to respect the user's mouse - // sensitivity settings. Windows messages are laggy, so poll instead. - POINT p; - GetCursorPos(&p); - if(mouse_x != p.x || mouse_y != p.y) - { - ev->type = SDL_MOUSEMOTION; - ev->motion.x = mouse_x = (u16)p.x; - ev->motion.y = mouse_y = (u16)p.y; - return 1; - } - - return 0; -} - - - -int SDL_GL_SetAttribute(SDL_GLattr attr, int value) -{ - if(attr == SDL_GL_DEPTH_SIZE) - z_depth = value; - - return 0; -} - - -/* - * set video mode wxh:bpp if necessary. - * w = h = bpp = 0 => no change. - */ -int SDL_SetVideoMode(int w, int h, int bpp, u32 flags) -{ - fullscreen = (flags & SDL_FULLSCREEN); - - /* get current mode settings */ - dm.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm); - int cur_w = dm.dmPelsWidth, cur_h = dm.dmPelsHeight; - - dm.dmBitsPerPel = bpp; - dm.dmFields = DM_BITSPERPEL; - - /* - * check if mode needs to be changed - * (could split this out, but depends on fullscreen and dm) - */ - if(w != 0 && h != 0 && bpp != 0) - if(/* higher res mode needed */ - (w > cur_w || h > cur_h) || - /* fullscreen, and not exact mode */ - (fullscreen && (w != cur_w || h != cur_h))) - { - dm.dmPelsWidth = w; - dm.dmPelsHeight = h; - dm.dmFields |= DM_PELSWIDTH|DM_PELSHEIGHT; - } - // mode set at first WM_ACTIVATE - - /* - * window init - * create new window every time (instead of once at startup), 'cause - * pixel format isn't supposed to be changed more than once - */ - - HINSTANCE hInst = GetModuleHandle(0); - - /* register window class */ - static WNDCLASS wc; - wc.style = CS_OWNDC; - wc.lpfnWndProc = wndproc; - wc.lpszClassName = "ogl"; - wc.hInstance = hInst; - RegisterClass(&wc); - - hWnd = CreateWindowEx(0, "ogl", APP_NAME, WS_POPUP|WS_VISIBLE, 0, 0, w, h, 0, 0, hInst, 0); - if(!hWnd) - return 0; - - hDC = GetDC(hWnd); - - /* set pixel format */ - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_SUPPORT_OPENGL|PFD_DRAW_TO_WINDOW|PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, - (BYTE)bpp, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - (BYTE)z_depth, - 0, 0, - PFD_MAIN_PLANE, - 0, 0, 0, 0 - }; - - int pf = ChoosePixelFormat(hDC, &pfd); - if(!SetPixelFormat(hDC, pf, &pfd)) - return 0; - - hGLRC = wglCreateContext(hDC); - if(!hGLRC) - return 0; - - if(!wglMakeCurrent(hDC, hGLRC)) - return 0; - - return 1; -} - - -inline void SDL_GL_SwapBuffers() -{ - SwapBuffers(hDC); -} - - - - - -void SDL_Quit() -{ - DestroyWindow(hWnd); - - wglMakeCurrent(0, 0); - wglDeleteContext(hGLRC); - ChangeDisplaySettings(0, 0); -} - - - - -#define DDRAW - - -#ifdef DDRAW -#include -#ifdef _MSC_VER -#pragma comment(lib, "ddraw.lib") - // for DirectDrawCreate. don't bother with dynamic linking - - // DirectX is present in all Windows versions since Win95. -#endif -#endif - - -SDL_VideoInfo* SDL_GetVideoInfo() -{ - static SDL_VideoInfo video_info; - -#ifdef DDRAW - - static bool init; - if(!init) - { - IDirectDraw* dd = 0; - HRESULT hr = DirectDrawCreate(0, &dd, 0); - if(SUCCEEDED(hr) && dd != 0) - { - static DDCAPS caps; - caps.dwSize = sizeof(caps); - hr = dd->GetCaps(&caps, 0); - if(SUCCEEDED(hr)) - video_info.video_mem = caps.dwVidMemTotal; - dd->Release(); - } - - init = true; - } - -#endif - - return &video_info; -} - - -SDL_Surface* SDL_GetVideoSurface() -{ - return 0; -} - -__declspec(naked) u32 SDL_GetTicks() -{ -__asm jmp dword ptr [GetTickCount] -} - - -void* SDL_GL_GetProcAddress(const char* name) -{ - return wglGetProcAddress(name); -} - - -SDL_sem* SDL_CreateSemaphore(int cnt) -{ - return (SDL_sem*)CreateSemaphore(0, cnt, 0x7fffffff, 0); -} - -void __stdcall SDL_DestroySemaphore(SDL_sem*) -{ -__asm jmp dword ptr [CloseHandle] -} - -int SDL_SemPost(SDL_sem* sem) -{ - return ReleaseSemaphore(sem, 1, 0); -} - -int SDL_SemWait(SDL_sem* sem) -{ - return WaitForSingleObject(sem, INFINITE); -} - -SDL_Thread* SDL_CreateThread(int(*func)(void*), void* param) -{ - return (SDL_Thread*)_beginthread((void(*)(void*))func, 0, param); -} - - -int SDL_KillThread(SDL_Thread* thread) -{ - return TerminateThread(thread, 0); -} - - -__declspec(naked) int __stdcall SDL_WarpMouse(int, int) -{ -__asm jmp dword ptr [SetCursorPos] -} - - - - - - - - - - - - - - - - - - - - - - -static bool need_redisplay; /* display callback should be called in next main loop iteration */ - - - -/* glut callbacks */ -static void (*idle)(); -static void (*display)(); -static void (*key)(int, int, int); -static void (*special)(int, int, int); -static void (*mouse)(int, int, int, int); - -void glutIdleFunc(void (*func)()) -{ idle = func; } - -void glutDisplayFunc(void (*func)()) -{ display = func; } - -void glutKeyboardFunc(void (*func)(int, int, int)) -{ key = func; } - -void glutSpecialFunc(void (*func)(int, int, int)) -{ special = func; } - -void glutMouseFunc(void (*func)(int, int, int, int)) -{ mouse = func; } - - - - - - - - - -void glutInit(int* argc, char* argv[]) -{ - UNUSED(argc) - UNUSED(argv) - - SDL_Init(0); - atexit(SDL_Quit); -} - - -int glutGet(int arg) -{ - if(arg == GLUT_ELAPSED_TIME) - return GetTickCount(); - - dm.dmSize = sizeof(DEVMODE); - EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm); - - if(arg == GLUT_SCREEN_WIDTH) - return dm.dmPelsWidth; - if(arg == GLUT_SCREEN_HEIGHT) - return dm.dmPelsHeight; - - return 0; -} - - -static int w, h, bpp, refresh; - -int glutGameModeString(const char* str) -{ - /* default = "don't care", in case string doesn't specify all values */ - w = 0, h = 0, bpp = 0, refresh = 0; - - sscanf(str, "%dx%d:%d@%d", &w, &h, &bpp, &refresh); - - return 1; -} - - -/* - */ -int glutEnterGameMode() -{ - return SDL_SetVideoMode(w, h, bpp, SDL_OPENGL|SDL_FULLSCREEN); -} - - - -inline void glutPostRedisplay() -{ - need_redisplay = true; -} - - -void glutSetCursor(int cursor) -{ - SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(cursor))); -} - - - -/* - * GLUT message handler - * message also goes to the shared wndproc - * - * not done in wndproc to separate GLUT and SDL; - * split out of glutMainLoop for clarity. - */ -static void glut_process_msg(MSG* msg) -{ - switch(msg->message) - { - case WM_PAINT: - need_redisplay = true; - break; - - case WM_CHAR: - if(key) - key((int)msg->wParam, mouse_x, mouse_y); - break; - - case WM_KEYDOWN: - if(special) - special((int)msg->wParam, mouse_x, mouse_y); - break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: /* FIXME: only left/right clicks, assume GLUT_LEFT|RIGHT_BUTTON == 0, 1 */ - if(mouse) - mouse(msg->message == WM_RBUTTONDOWN, GLUT_DOWN, (int)(msg->lParam & 0xffff), (int)(msg->lParam >> 16)); - break; - - case WM_MOUSEWHEEL: - if(mouse) - mouse(GLUT_MIDDLE_BUTTON, ((short)(msg->wParam >> 16) > 0)? GLUT_UP : GLUT_DOWN, 0, 0); - break; - } -} - - -void glutMainLoop() -{ - for(;;) - { - if(!app_active) - WaitMessage(); - - MSG msg; - if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - glut_process_msg(&msg); - - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - if(idle) - idle(); - - if(need_redisplay) - { - need_redisplay = false; - display(); - } - } -} diff --git a/source/lib/wsdl.h b/source/lib/wsdl.h deleted file mode 100755 index 414408d80d..0000000000 --- a/source/lib/wsdl.h +++ /dev/null @@ -1,309 +0,0 @@ -#ifndef _WIN32 -#include -#include -#define __WSDL_H__ // => rest of header ignored -#endif - - -#ifndef __WSDL_H__ -#define __WSDL_H__ - - -#include "types.h" - -/* allow apps to override window name */ -#ifndef APP_NAME -#define APP_NAME "ogl" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* SDL_Init flags */ -#define SDL_INIT_VIDEO 0 -#define SDL_INIT_AUDIO 0 -#define SDL_INIT_TIMER 0 -#define SDL_INIT_NOPARACHUTE 0 - -extern void SDL_Quit(); - - -typedef enum -{ - SDL_GL_DEPTH_SIZE, - SDL_GL_DOUBLEBUFFER /* ignored - always double buffered */ -} -SDL_GLattr; - -extern int SDL_GL_SetAttribute(SDL_GLattr attr, int value); - - -/* SDL_SetVideoMode() flags */ -#define SDL_OPENGL 0 -#define SDL_FULLSCREEN 1 - -extern int SDL_SetVideoMode(int w, int h, int bpp, u32 flags); - - -typedef struct -{ - int w, h; -} -SDL_Surface; - -extern SDL_Surface* SDL_GetVideoSurface(); - - -typedef struct -{ - int video_mem; -} -SDL_VideoInfo; - -extern SDL_VideoInfo* SDL_GetVideoInfo(); - - -/* - * threads / sync - */ - -typedef void SDL_sem; -typedef void SDL_Thread; - -extern void* SDL_GL_GetProcAddress(const char*); - -extern void SDL_GL_SwapBuffers(); - -extern u32 SDL_GetTicks(); - -extern SDL_sem* SDL_CreateSemaphore(int cnt); -extern void __stdcall SDL_DestroySemaphore(SDL_sem*); -extern int SDL_SemPost(SDL_sem*); -extern int SDL_SemWait(SDL_sem* sem); - -extern SDL_Thread* SDL_CreateThread(int(*)(void*), void*); -extern int SDL_KillThread(SDL_Thread*); - -extern int __stdcall SDL_WarpMouse(int, int); - - - - -/* macros */ - -#define SDL_Init - -#define SDL_GRAB_ON 0 -#define SDL_WM_GrabInput(a) -#define SDL_GetError() "" - - - - -/************************************************************************************************ - * events - ************************************************************************************************/ - -/* SDLKey (mapped to VK_* codes) */ -typedef enum -{ - SDLK_ESCAPE = 0x1b, - SDLK_8 = '8', - SDLK_9 = '9', - SDLK_0 = '0', - SDLK_p = 'P', - SDLK_r = 'R', - SDLK_s = 'S', - - SDLK_KP_PLUS = 0x6b, - SDLK_KP_MINUS = 0x6d, - SDLK_LEFT = 0x25, - SDLK_UP = 0x26, - SDLK_RIGHT = 0x27, - SDLK_DOWN = 0x28, - - SDLK_KP0 = 0x60, - SDLK_KP1 = 0x61, - SDLK_KP2 = 0x62, - SDLK_KP3 = 0x63, - SDLK_KP4 = 0x64, - SDLK_KP5 = 0x65, - SDLK_KP6 = 0x66, - SDLK_KP7 = 0x67, - SDLK_KP8 = 0x68, - SDLK_KP9 = 0x69, - -__SDLK // hack to allow trailing comma -} -SDLKey; - -typedef struct -{ - SDLKey sym; -} -SDL_keysym; - -typedef struct -{ - SDL_keysym keysym; -} -SDL_KeyboardEvent; - -typedef struct -{ - u16 x, y; -} -SDL_MouseMotionEvent; - -/* SDL_MouseButtonEvent.button */ -enum -{ - // do not change order - SDL_BUTTON_LEFT, - SDL_BUTTON_RIGHT, - SDL_BUTTON_MIDDLE, - - SDL_BUTTON_WHEELUP, - SDL_BUTTON_WHEELDOWN -}; - -typedef struct -{ - u8 button; - u8 state; - u16 x, y; -} -SDL_MouseButtonEvent; - -typedef struct -{ - u8 gain; - u8 state; -} -SDL_ActiveEvent; - -/* SDL_Event.type */ -enum -{ - SDL_KEYDOWN, - SDL_KEYUP, - SDL_MOUSEMOTION, - SDL_MOUSEBUTTONDOWN, - SDL_MOUSEBUTTONUP, - SDL_ACTIVE -}; - -typedef struct -{ - u8 type; - union - { - SDL_KeyboardEvent key; - SDL_MouseMotionEvent motion; - SDL_MouseButtonEvent button; - SDL_ActiveEvent active; - }; -} -SDL_Event; - -extern int SDL_PollEvent(SDL_Event* ev); - - - - - - - - - - - - - - - -/* glutInitDisplayMode */ -#define GLUT_RGB 0 -#define GLUT_DOUBLE 0 -#define GLUT_DEPTH 0 - -/* mouse buttons */ -enum -{ - GLUT_LEFT_BUTTON, - GLUT_RIGHT_BUTTON, - GLUT_MIDDLE_BUTTON /* also wheel, if avail */ -}; - -/* mouse button state */ -enum -{ - GLUT_DOWN, - GLUT_UP -}; - -/* keys */ -enum -{ - GLUT_KEY_LEFT = 0x25, /* VK_* */ - GLUT_KEY_RIGHT = 0x27, - GLUT_KEY_UP = 0x26, - GLUT_KEY_DOWN = 0x28 -}; - - -/* glutSetCursor */ -#define GLUT_CURSOR_INHERIT 32512 /* IDC_* */ -#define GLUT_CURSOR_WAIT 32514 -#define GLUT_CURSOR_DESTROY 32648 -#define GLUT_CURSOR_NONE 0 - -/* glutGet */ -enum -{ -GLUT_ELAPSED_TIME, -GLUT_SCREEN_WIDTH, -GLUT_SCREEN_HEIGHT, - -GLUT_GAME_MODE_WIDTH, -GLUT_GAME_MODE_HEIGHT, -GLUT_GAME_MODE_PIXEL_DEPTH, -GLUT_GAME_MODE_REFRESH_RATE -}; - - - -extern void glutIdleFunc(void(*)()); -extern void glutDisplayFunc(void(*)()); -extern void glutKeyboardFunc(void(*)(int, int, int)); -extern void glutSpecialFunc(void(*)(int, int, int)); -extern void glutMouseFunc(void(*)(int, int, int, int)); - - -#define glutInitDisplayMode(a) /* pixel format is hardwired */ - -extern int glutGameModeString(const char* str); - - - -extern void glutInit(int* argc, char* argv[]); -extern int glutGet(int arg); -extern int glutEnterGameMode(); -extern void glutMainLoop(); - -extern void glutPostRedisplay(); - -extern void glutSetCursor(int); - - - -#define glutSwapBuffers SDL_GL_SwapBuffers - - - -#ifdef __cplusplus -} -#endif - -#endif // #ifndef __WSDL_H__ diff --git a/source/lib/zip.cpp b/source/lib/zip.cpp deleted file mode 100755 index 5d0d66a1f3..0000000000 --- a/source/lib/zip.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// ZIP archiving (on top of ZLib) -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#include -#include -#include - -#include "zip.h" -#include "posix.h" -#include "misc.h" -#include "res.h" -#include "mem.h" -#include "vfs.h" - -// don't include windows.h from zconf! -// not necessary, causes many conflicts. -#define _WINDOWS_ -#define WINAPI __stdcall -#define WINAPIV __cdecl - -#include -#ifdef _MSC_VER -#pragma comment(lib, "zlib.lib") -#endif - - -// H_ZARCHIVE -// information about a Zip archive -struct ZARCHIVE -{ - Handle hm; // archive in memory (usually mapped) - - const char* fn; // archive filename - - // file lookup - u16 num_files; - u16 last_file; // index of last file we found (speed up lookups of sequential files) - u32* fn_hashs; // split for more efficient search - ZFILE* files; -}; - - -static const char ecdr_id[] = "PK\5\6"; // End of Central Directory Header identifier -static const char cdfh_id[] = "PK\1\2"; // Central File Header identifier -static const char lfh_id[] = "PK\3\4"; // Local File Header identifier - - - -static void zarchive_dtor(void* p) -{ - ZARCHIVE* za = (ZARCHIVE*)p; - - mem_free(za->hm); - mem_free((void*)za->fn); - mem_free(za->fn_hashs); // both fn_hashs[] and files[] -} - - -// open and return a handle to the zip archive indicated by -Handle zip_open(const char* const fn) -{ - const u8* ecdr; // declared here to avoid goto scope problems - - const u32 fn_hash = fnv_hash(fn, strlen(fn)); - - // allocate a handle - ZARCHIVE* za; - Handle ha = h_alloc(fn_hash, H_ZARCHIVE, zarchive_dtor, (void**)&za); - // .. failed - if(!ha) - return 0; - // .. archive already loaded - if(za->hm) - return ha; - - // map the Zip file - const u8* zfile; - size_t size; - Handle hm = vfs_load(fn, (void*&)zfile, size); - if(!hm) - goto fail; - -{ - // find end of central dir record - // by scanning last 66000 bytes of file for ecdr_id magic - // (zip comment <= 65535 bytes, sizeof(ECDR) = 22, add some for safety) - // if the zip file is < 66000 bytes, scan the whole file - - size_t bytes_left = 66000; // min(66k, size) - avoid stupid warning - if(bytes_left > size) - bytes_left = size; - ecdr = zfile + size - bytes_left; - - while(bytes_left-3 > 0) - { - if(*(u32*)ecdr == *(u32*)&ecdr_id) - goto found_ecdr; - - // check next 4 bytes (non aligned!!) - ecdr++; - bytes_left--; - } - - // reached EOF and still haven't found the ECDR identifier -} - -fail: - h_free(ha, H_ZARCHIVE); - mem_free(hm); - return 0; - -found_ecdr: -{ - // read ECDR - const u16 num_files = read_le16(ecdr+10); - const u32 cd_ofs = read_le32(ecdr+16); - - // memory for fn_hash and File arrays - void* mem = mem_alloc(num_files * (sizeof(u32) + sizeof(ZFILE)), 4*KB, MEM_HEAP); - if(!mem) - goto fail; - - za->hm = hm; - za->fn_hashs = (u32*)mem; - za->files = (ZFILE*)((u8*)mem + sizeof(u32)*num_files); - za->last_file = 0; - - za->fn = (const char*)mem_alloc(strlen(fn)+1); - strcpy((char*)za->fn, fn); - - // cache file list for faster lookups - // currently linear search, comparing filename hash. - // TODO: if too slow, use hash table. - const u8* cdfh = zfile+cd_ofs; - u32* hs = za->fn_hashs; - ZFILE* f = za->files; - u16 i; - for(i = 0; i < num_files; i++) - { - // read CDFH - if(*(u32*)cdfh != *(u32*)cdfh_id) - continue; - const u32 csize = read_le32(cdfh+20); - const u32 ucsize = read_le32(cdfh+24); - const u16 fn_len = read_le16(cdfh+28); - const u16 e_len = read_le16(cdfh+30); - const u16 c_len = read_le16(cdfh+32); - const u32 lfh_ofs = read_le32(cdfh+42); - const u8 method = cdfh[10]; - - if(method & ~8) // neither deflated nor stored - continue; - - // read LFH - const u8* const lfh = zfile + lfh_ofs; - if(*(u32*)lfh != *(u32*)lfh_id) - continue; - const u16 lfh_fn_len = read_le16(lfh+26); - const u16 lfh_e_len = read_le16(lfh+28); - const char* lfh_fn = (const char*)lfh+30; - - *hs++ = fnv_hash(lfh_fn, lfh_fn_len); - f->ofs = lfh_ofs + 30 + lfh_fn_len + lfh_e_len; - f->csize = csize; - f->ucsize = ucsize; - f++; - - (uintptr_t&)cdfh += 46 + fn_len + e_len + c_len; - } - - za->num_files = i; -} - - return ha; -} - - -int zip_close(Handle ha) -{ - return h_free(ha, H_ZARCHIVE); -} - - -ZFILE* zip_lookup(Handle ha, const char* fn) -{ - ZARCHIVE* za = (ZARCHIVE*)h_user_data(ha, H_ZARCHIVE); - if(!za) - return 0; - - // find its File descriptor - const u32 fn_hash = fnv_hash(fn, strlen(fn)); - u16 i = za->last_file+1; - if(i >= za->num_files || za->fn_hashs[i] != fn_hash) - { - for(i = 0; i < za->num_files; i++) - if(za->fn_hashs[i] == fn_hash) - break; - if(i == za->num_files) - return 0; - - za->last_file = i; - } - - return &za->files[i]; -} - - -int zip_stat(Handle ha, const char* fn, struct stat* s) -{ - ZFILE* zf = zip_lookup(ha, fn); - if(!zf) - return -1; - - s->st_size = (off_t)zf->ucsize; - return 0; -} - - -int zip_archive_info(Handle ha, char* fn, Handle* hm) -{ - ZARCHIVE* za = (ZARCHIVE*)h_user_data(ha, H_ZARCHIVE); - if(!za) - return -1; - - if(fn) - strcpy(fn, za->fn); - - if(hm) - *hm = za->hm; - return 0; -} - - -void* zip_inflate_start(void* out, size_t out_size) -{ - z_stream* stream = (z_stream*)mem_alloc(sizeof(z_stream), 4, MEM_POOL); - memset(stream, 0, sizeof(stream)); - - if(inflateInit2(stream, -MAX_WBITS) != Z_OK) - return 0; - // -MAX_WBITS indicates no zlib header present - - stream->next_out = (Bytef*)out; - stream->avail_out = (uInt)out_size; - - return stream; -} - - -int zip_inflate_process(void* ctx, void* p, size_t size) -{ - z_stream* stream = (z_stream*)ctx; - - stream->next_in = (Bytef*)p; - stream->avail_in = (uInt)size; - return inflate(stream, 0); -} - - -int zip_inflate_end(void* ctx) -{ - z_stream* stream = (z_stream*)ctx; - inflateEnd(stream); - - // didn't read everything - if(stream->avail_out || stream->avail_in) - return -1; - return 0; -} - diff --git a/source/lib/zip.h b/source/lib/zip.h deleted file mode 100755 index 2c92a8e2eb..0000000000 --- a/source/lib/zip.h +++ /dev/null @@ -1,48 +0,0 @@ -// ZIP archiving (on top of ZLib) -// -// Copyright (c) 2003 Jan Wassenberg -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License as -// published by the Free Software Foundation; either version 2 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// Contact info: -// Jan.Wassenberg@stud.uni-karlsruhe.de -// http://www.stud.uni-karlsruhe.de/~urkt/ - -#ifndef __ZIP_H__ -#define __ZIP_H__ - -#include "res.h" - -// open and return a handle to the zip archive indicated by -extern Handle zip_open(const char* fn); -extern int zip_close(Handle ha); - -extern int zip_archive_info(Handle ha, char* fn, Handle* hm); - -extern int zip_stat(Handle ha, const char* fn, struct stat* s); - - -struct ZFILE -{ - size_t ofs; - size_t csize; - size_t ucsize; -}; - -// return information about file in archive (i.e. 'open' it) -extern ZFILE* zip_lookup(Handle ha, const char* fn); - -extern void* zip_inflate_start(void* out, size_t out_size); -extern int zip_inflate_process(void* ctx, void* p, size_t size); -extern int zip_inflate_end(void* ctx); - - -#endif // #ifndef __ZIP_H__ \ No newline at end of file