no message

This was SVN commit r10.
This commit is contained in:
janwas 2003-11-03 16:43:26 +00:00
parent 5cc814759f
commit d97b24d027
31 changed files with 0 additions and 5322 deletions

View File

@ -1,301 +0,0 @@
// system detect
//
// 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/
// things missing in POSIX and SDL :P
#include <cstdio>
#include <cstring>
#ifdef _WIN32
#include "win.h"
#endif
#include "detect.h"
#include "time.h"
#include "ogl.h"
#include "wsdl.h"
// useful for choosing a video mode. not called by detect().
// currently not implemented for non-Win32 systems (returns 800x600).
void get_cur_resolution(int& xres, int& yres)
{
// guess
xres = 800; yres = 600;
#ifdef _WIN32
static DEVMODE dm;
dm.dmSize = sizeof(dm);
EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm);
xres = dm.dmPelsWidth;
yres = dm.dmPelsHeight;
#endif
}
unsigned long tot_mem = 0;
unsigned long avl_mem = 0;
void get_mem_status()
{
// Win32
#ifdef _WIN32
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
tot_mem = round_up(ms.dwTotalPhys, 1*MB);
// fixes results for my machine - off by 528 KB. why?!
avl_mem = ms.dwAvailPhys;
// Sys V derived (GNU/Linux, Solaris)
#elif defined(_SC_PAGESIZE) && defined(_SC_AVPHYS_PAGES)
long page_size = sysconf(_SC_PAGESIZE);
tot_mem = sysconf(_SC_PHYS_PAGES ) * page_size;
avl_mem = sysconf(_SC_AVPHYS_PAGES) * page_size;
// BSD / Mac OS X
#elif HAVE_SYSCTL && defined(HW_PHYSMEM)
size_t len = sizeof(tot_mem);
int mib[2] = { CTL_HW, HW_PHYSMEM };
sysctl(mib, 2, &tot_mem, &len, 0, 0);
mib[1] = HW_USERMEM;
sysctl(mib, 2, &avl_mem, &len, 0, 0);
#endif
}
char gfx_card[512] = ""; // = D3D8 MAX_DEVICE_IDENTIFIER_STRING
#ifdef D3D8
#include <d3d8.h>
#ifdef _MSC_VER
#pragma comment(lib, "d3d8.lib")
#endif
#endif
// no-op on non-Win32 systems until OpenGL is initialized.
void get_gfx_card()
{
// already successfully detected
if(gfx_card[0] != 0)
return;
#ifdef D3D8
IDirect3D8* d3d = Direct3DCreate8(D3D_SDK_VERSION);
D3DADAPTER_IDENTIFIER8 id;
d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, D3DENUM_NO_WHQL_LEVEL, &id);
d3d->Release();
strcpy(gfx_card, id.Description);
#else
char* v = (char*)glGetString(GL_VENDOR);
if(!v) // OpenGL probably not initialized yet
return;
strncpy(gfx_card, v, sizeof(gfx_card));
if(!strcmp(gfx_card, "ATI Technologies Inc."))
gfx_card[3] = 0;
if(!strcmp(gfx_card, "NVIDIA Corporation"))
gfx_card[6] = 0;
strcat(gfx_card, (char*)glGetString(GL_RENDERER));
#endif
}
//
// CPU
//
char cpu_type[49] = "unknown CPU"; // processor brand string is 48 chars
double cpu_freq = 0.f;
long cpu_caps = 0;
long cpu_ext_caps = 0;
// -1 if detect not yet called, or cannot be determined
int cpus = -1;
int is_notebook = -1;
#ifdef _M_IX86
int has_tsc = -1;
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;
}
#endif
static void get_cpu_info()
{
#ifdef _M_IX86
static char cpu_vendor[13];
int family, model;
__asm
{
; make sure CPUID is supported (size opt.)
pushfd
or byte ptr [esp+2], 32
popfd
pushfd
pop eax
shr eax, 22 ; bit 21 toggled?
jnc no_cpuid
; get vendor string
xor eax, eax
cpuid
mov dword ptr [cpu_vendor], ebx
mov dword ptr [cpu_vendor+4], edx
mov dword ptr [cpu_vendor+8], ecx
; (already 0 terminated)
; get CPU signature and std feature bits
mov eax, 1
cpuid
mov [cpu_caps], edx
mov edx, eax
shr edx, 4
and edx, 0x0f
mov [model], edx
shr eax, 8
and eax, 0x0f
mov [family], eax
; make sure CPUID ext functions are supported
mov eax, 0x80000000
cpuid
cmp eax, 0x80000000
jbe no_brand_str
; get CPU brand string (>= Athlon XP, P4)
mov edi, offset cpu_type
mov esi, -2 ; loop counter: -2 to 0
$1: lea eax, [0x80000004+esi]
cpuid
stosd
xchg eax, ebx
stosd
xchg eax, ecx
stosd
xchg eax, edx
stosd
inc esi
jle $1
; already 0 terminated
; get extended feature flags
mov eax, 0x80000001
cpuid
mov [cpu_ext_caps], edx
}
// strip (tm) from Athlon string
if(!strncmp(cpu_type, "AMD Athlon(tm)", 14))
memmove(cpu_type+10, cpu_type+14, 34);
// fixup Intel's as well
int a, b; // not needed, but sscanf returns # fields actually stored
if(sscanf(cpu_type, "Intel ® Pentium 4 CPU %d.%d GHz", &a, &b) == 2)
strcpy(cpu_type, "Intel Pentium 4");
goto have_brand_str;
no_brand_str:
// AMD
if(!strcmp(cpu_vendor, "AuthenticAMD"))
{
if(family == 6)
strcpy(cpu_type, (model == 3)? "AMD Duron" : "AMD Athlon");
}
// Intel
else if(!strcmp(cpu_vendor, "GenuineIntel"))
{
if(family == 6 && model >= 7)
strcpy(cpu_type, "Intel Pentium III / Celeron");
}
have_brand_str:
// calc CPU freq (count clocks in 50 ms)
if(cpu_caps & TSC)
{
u64 clocks1 = rdtsc();
// .. wait at at least 50 ms
double t1 = get_time();
double t2;
do
t2 = get_time();
while(t2 < t1 + 50e-3);
u64 clocks2 = rdtsc();
// .. freq = (clocks / 50 [ms]) / 50 [ms] * 1000
// cpuid/rdtsc overhead is negligible
cpu_freq = (__int64)(clocks2-clocks1) / (t2-t1);
// VC6 can't convert u64 -> double, and we don't need full range
}
// don't bother with a WAG timing loop
no_cpuid:
#endif // #ifdef _M_IX86
#ifdef _WIN32
HW_PROFILE_INFO hi;
GetCurrentHwProfile(&hi);
is_notebook = !(hi.dwDockInfo & DOCKINFO_DOCKED) ^
!(hi.dwDockInfo & DOCKINFO_UNDOCKED);
// both flags set <==> this is a desktop machine.
// both clear is unspecified; we assume it's not a notebook.
SYSTEM_INFO si;
GetSystemInfo(&si);
cpus = si.dwNumberOfProcessors;
#endif
}
void detect()
{
get_mem_status();
get_gfx_card();
get_cpu_info();
}

View File

@ -1,88 +0,0 @@
// system detect
//
// 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 __DETECT_H__
#define __DETECT_H__
#include "misc.h"
#ifdef __cplusplus
extern "C" {
#endif
// useful for choosing a video mode. not called by detect().
// currently not implemented for non-Win32 systems (returns 800x600).
extern void get_cur_resolution(int& xres, int& yres);
extern char gfx_card[];
// no-op on non-Win32 systems until OpenGL is initialized.
extern void get_gfx_card();
//
// mem
//
extern unsigned long tot_mem;
extern unsigned long avl_mem;
// updates *_mem above
extern void get_mem_status();
//
// CPU
//
extern char cpu_type[];
extern double cpu_freq;
enum
{
TSC = BIT(4),
CMOV = BIT(15),
MMX = BIT(23),
SSE = BIT(25),
SSE2 = BIT(26)
};
extern long cpu_caps;
// define instead of enum to avoid stupid sign conversion warning
#define EXT_3DNOW_PRO BIT(30)
#define EXT_3DNOW BIT(31)
extern long cpu_ext_caps;
// -1 if detect not yet called, or cannot be determined
extern int cpus;
extern int is_notebook;
extern void detect();
#ifdef __cplusplus
}
#endif
#endif // #ifndef __DETECT_H__

View File

@ -1,226 +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 <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "font.h"
#include "res.h"
#include "tex.h"
#include "ogl.h"
#include "posix.h"
#include "misc.h"
typedef struct
{
Handle tex;
uint list_base;
}
FONT;
#if 0
#include <ft2build.h>
//#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(HDATA* hd)
{
FONT* font = (FONT*)hd->internal;
glDeleteLists(font->list_base, 96);
}
u32 font_load(const char* fn)
{
void* p;
size_t size;
HDATA* hd;
u32 h = res_load(fn, RES_FONT, font_dtor, p, size, hd);
if(!h || !hd || !p)
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;
}
}
// 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* font = (FONT*)hd->internal;
font->tex = tex;
font->list_base = list_base;
return h;
}
int font_bind(const u32 h)
{
HDATA* hd = h_data(h, RES_FONT);
if(!hd)
return -1;
FONT* font = (FONT*)hd->internal;
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(strlen(buf), GL_UNSIGNED_BYTE, buf);
}

View File

@ -1,79 +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"
// load and return a handle to the font defined in <fn>
extern u32 font_load(const char* fn);
// use the font referenced by h for all subsequent glprintf() calls
extern int font_bind(u32 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, xres, 0, 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
*/

View File

@ -1,25 +0,0 @@
/* GL 1.2 */
FUNC(void, glActiveTexture, (int))
/* EXT_swap_control */
FUNC(int, wglSwapIntervalEXT, (int))
/* NV_vertex_array */
FUNC(void, glVertexArrayRangeNV, (int, void*))
FUNC(void, glFlushVertexArrayRangeNV, ())
FUNC(void*, wglAllocateMemoryNV, (int, float, float, float))
FUNC(void, wglFreeMemoryNV, (void*))
/* NV_fence */
FUNC(void, glGenFencesNV, (int, unsigned int*))
FUNC(void, glDeleteFencesNV, (int, const unsigned int*))
FUNC(void, glSetFenceNV, (unsigned int, int))
FUNC(int, glTestFenceNV, (unsigned int))
FUNC(void, glFinishFenceNV, (unsigned int))
FUNC(int, glIsFenceNV, (unsigned int))
FUNC(void, glGetFenceivNV, (unsigned int, int, int*))
FUNC(void, glCompressedTexImage2DARB, (int, int, int, unsigned int, unsigned int, int, unsigned int, const void*))
FUNC(void, glCompressedTexSubImage2DARB, (int, int, int, int, unsigned int, int, int, unsigned int, const void*))

View File

@ -1,164 +0,0 @@
/*
* input layer (dispatch events to multiple handlers; record/playback events)
*
* 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 <stdio.h>
#include <stdlib.h>
#include "input.h"
#define MAX_HANDLERS 4
static IN_HANDLER handler_stack[MAX_HANDLERS];
static int handler_stack_top = 0;
int in_add_handler(IN_HANDLER handler)
{
if(handler_stack_top >= MAX_HANDLERS || !handler)
return -1;
handler_stack[handler_stack_top++] = handler;
return 0;
}
/* send event to each handler (newest first) until one returns true */
static void dispatch_event(const SDL_Event& event)
{
for(int i = handler_stack_top-1; i >= 0; i--)
if(handler_stack[i](event))
return;
}
static enum
{
INIT, /* first call to in_record() or in_playback(): register cleanup routine */
IDLE,
RECORD,
PLAYBACK
}
state = INIT;
static FILE* f;
extern u32 game_ticks;
static u32 time_adjust = 0;
static u32 next_event_time;
void in_stop()
{
if(f)
{
fclose(f);
f = 0;
}
state = IDLE;
}
int in_record(const char* fn)
{
if(state == INIT)
atexit(in_stop);
in_stop();
f = fopen(fn, "wb");
if(!f)
return -1;
fwrite(&game_ticks, sizeof(u32), 1, f);
state = RECORD;
return 0;
}
int in_playback(const char* fn)
{
if(state == INIT)
atexit(in_stop);
in_stop();
f = fopen(fn, "rb");
if(!f)
return -1;
u32 rec_start_time;
fread(&rec_start_time, sizeof(u32), 1, f);
time_adjust = game_ticks-rec_start_time;
fread(&next_event_time, sizeof(u32), 1, f);
next_event_time += time_adjust;
state = PLAYBACK;
return 0;
}
void in_get_events()
{
SDL_Event event;
while(state == PLAYBACK && next_event_time <= game_ticks)
{
fread(&event, sizeof(SDL_Event), 1, f);
/*
* do this before dispatch_event(),
* in case a handler calls in_stop() (setting f to 0)
*/
if(!fread(&next_event_time, sizeof(u32), 1, f))
{
in_stop();
exit(0x73c07d);
// TODO: 'disconnect'?
}
next_event_time += time_adjust;
dispatch_event(event);
}
/* get new events */
while(SDL_PollEvent(&event))
{
if(state == RECORD)
{
fwrite(&game_ticks, sizeof(u32), 1, f);
fwrite(&event, sizeof(SDL_Event), 1, f);
}
if(state == PLAYBACK)
if(event.type == SDL_KEYDOWN)
in_stop();
dispatch_event(event);
}
}

View File

@ -1,56 +0,0 @@
/*
* input layer (dispatch events to multiple handlers; record/playback events)
*
* 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/
*/
#ifndef __INPUT_H__
#define __INPUT_H__
#include "wsdl.h"
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
extern u32 game_ticks;
typedef bool (*IN_HANDLER)(const SDL_Event& event);
/*
* register an input handler, which will receive all subsequent events first.
* events are passed to other handlers if handler returns false.
*/
extern int in_add_handler(IN_HANDLER handler);
extern void in_get_events();
extern int in_record(const char* fn);
extern int in_playback(const char* fn);
extern void in_stop();
#ifdef __cplusplus
}
#endif
#endif /* #ifndef __INPUT_H__ */

View File

@ -1,123 +0,0 @@
// malloc layer for less fragmentation, alignment, and automatic release
#include <cstdlib>
#include <map>
#include "types.h"
#include "mem.h"
#include "res.h"
#include "misc.h"
struct MEM
{
uint type;
void* org_p; // MEM_HEAP only
size_t size; // MEM_POOL only
};
static void heap_dtor(HDATA* hd)
{
MEM* mem = (MEM*)hd->internal;
free(mem->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((long)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_dtor(HDATA* hd)
{
MEM* mem = (MEM*)hd->internal;
long pool_ofs = (u8*)hd->p - (u8*)pool;
// not at end of pool
if(pool_ofs + mem->size == pool_pos)
pool_pos -= mem->size;
}
static void* pool_alloc(const size_t size, const uint align, MEM& mem)
{
if(!pool)
pool = (u8*)mem_alloc(size, MEM_HEAP, align);
if(!pool)
return 0;
size_t ofs = round_up((ulong)pool+pool_pos, align) - (ulong)pool;
if(ofs+size > POOL_CAP)
return 0;
void* p = (u8*)pool + ofs;
mem.size = size;
pool_pos = ofs+size;
return p;
}
static void mem_dtor(HDATA* hd)
{
MEM* mem = (MEM*)hd->internal;
if(mem->type == MEM_HEAP)
heap_dtor(hd);
else if(mem->type == MEM_POOL)
pool_dtor(hd);
}
void* mem_alloc(size_t size, const MemType type, const uint align)
{
if(size == 0)
size = 1;
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
return 0;
HDATA* hd;
Handle h = h_alloc((u32)p, RES_MEM, mem_dtor, hd);
if(!h || !hd)
return 0;
*(MEM*)hd->internal = mem;
return p;
}
int mem_free(void* p)
{
if(!p)
return 1;
HDATA* hd;
Handle h = h_find((u32)p, RES_MEM, hd);
if(!h)
return -1;
h_free(h, RES_MEM);
return 0;
}

View File

@ -1,13 +0,0 @@
#ifndef __MEM_H__
#define __MEM_H__
enum MemType
{
MEM_POOL,
MEM_HEAP
};
extern void* mem_alloc(size_t size, MemType type = MEM_HEAP, uint align = 1);
extern int mem_free(void* p);
#endif // #ifndef __MEM_H__

View File

@ -1,62 +0,0 @@
/*
* block prefetch memcpy for large, uncached arrays
*
* src and len must be multiples of CHUNK_SIZE.
*/
void memcpy_nt(void* dst, void* src, int len)
{
__asm
{
push esi
mov edx, [dst]
mov esi, [src]
mov ecx, [len]
shr ecx, 12 ; # chunks
; smaller than sub ecx, CHUNK_SIZE below
main_loop:
; prefetch: touch each cache line in chunk
; (backwards to prevent hardware prefetches)
; add esi, CHUNK_SIZE
prefetch_loop:
mov eax, [esi-64]
mov eax, [esi-128]
sub esi, 128
test esi, 4095 ; CHUNK_SIZE-1 (icc doesn't preprocess asm)
jnz prefetch_loop
; copy the chunk 64 bytes at a time
write_loop:
movq mm0, [esi]
movq mm1, [esi+8]
movq mm2, [esi+16]
movq mm3, [esi+24]
movq mm4, [esi+32]
movq mm5, [esi+40]
movq mm6, [esi+48]
movq mm7, [esi+56]
add esi, 64
test esi, 4095 ; CHUNK_SIZE-1
movntq [edx], mm0
movntq [edx+8], mm1
movntq [edx+16], mm2
movntq [edx+24], mm3
movntq [edx+32], mm4
movntq [edx+40], mm5
movntq [edx+48], mm6
movntq [edx+56], mm7
lea edx, [edx+64] ; leave flags intact
jnz write_loop
dec ecx
jnz main_loop
sfence
emms
pop esi
}
}

View File

@ -1,223 +0,0 @@
// miscellany
//
// 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 <cassert>
#include <cstdlib>
#include <cmath>
#include "time.h"
#include "misc.h"
#include <map>
// FNV1-A
u32 fnv_hash(const char* str, int len)
{
u32 h = 0;
while(len--)
{
h ^= *(const u8*)str++;
h *= 0x01000193;
}
return h;
}
#if defined(_M_IX86) && !defined(_WIN32)
// 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
}
return 0;
}
#endif
u16 bswap16(u16 x)
{
return (u16)(((x & 0xff) << 8) | (x >> 8));
}
u32 bswap32(u32 x)
{
#ifdef _M_IX86
__asm
{
mov eax, [x]
bswap eax
mov [x], eax
}
#else
u32 t = x;
for(int i = 0; i < 4; i++)
{
x <<= 8;
x |= t & 0xff;
}
#endif
return x;
}
void bswap32(const u8* data, int cnt)
{
__asm
{
mov edx, [data]
mov ecx, [cnt]
$loop: dec ecx
js $ret
mov eax, [edx+ecx*4]
bswap eax
mov [edx+ecx*4], eax
jmp $loop
$ret:
}
}
bool is_pow2(const int n)
{
return (n > 0) && !(n & (n-1));
}
// return -1 if not an integral power of 2,
// otherwise the base2 logarithm
int log2(const int n)
{
#ifdef _M_IX86
__asm
{
mov ecx, [n]
or eax, -1 // return value
lea edx, [ecx-1]
test ecx, edx // power of 2?
jnz $ret
bsf eax, ecx
$ret:
mov [n], eax
}
return n;
#else
if(n || n & (n-1))
return -1;
int i = 1, j = 0;
for(; i != n; i += i, j++)
;
return j;
#endif
}
static int log2(const float x)
{
u32 i = (u32&)x;
u32 exp = (i >> 23) & 0xff;
return (int)exp - 127;
}
long round_up(long val, int multiple)
{
val += multiple-1;
val -= val % multiple;
return val;
}
// replace pathetic libc implementation
#if defined(_M_IX86) && defined(_WIN32)
double ceil(double f)
{
double r;
const float _49 = 0.499999f;
__asm
{
fld [f]
fadd [_49]
frndint
fstp [r]
}
return r;
}
#endif
// big endian!
void base32(const int len, const u8* in, u8* out)
{
int bits = 0;
u32 pool = 0;
static u8 tbl[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
for(int i = 0; i < len; i++)
{
if(bits < 5)
{
pool <<= 8;
pool |= *in++;
bits += 8;
}
bits -= 5;
int c = (pool >> bits) & 31;
*out++ = tbl[c];
}
}

View File

@ -1,121 +0,0 @@
// miscellany
//
// 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 __MISC_H__
#define __MISC_H__
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define UNUSED(param) (void)param;
#define ONCE(code) { static bool done; if(!done) { code; }; done = true; }
const u32 KB = 1 << 10;
const u32 MB = 1 << 20;
#ifdef _WIN32
#define DIR_SEP '\\'
#else
#define DIR_SEP '/'
#endif
#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);
extern u32 fnv_hash(const char* str, int len);
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define BIT(n) (1ul << (n))
#ifndef min
inline int min(int a, int b)
{
return (a < b)? a : b;
}
inline int max(int a, int b)
{
return (a > b)? a : b;
}
#endif
extern u16 bswap16(u16);
extern u32 bswap32(u32);
static inline u16 read_le16(const void* p)
{
#ifdef BIG_ENDIAN
const u8* _p = p;
return (u16)_p[0] | (u16)_p[1] << 8;
#else
return *(u16*)p;
#endif
}
static inline u32 read_le32(const void* p)
{
#ifdef BIG_ENDIAN
u32 t = 0;
for(int i = 0; i < 32; i += 8)
t |= (*(const u8*)p++) << i;
return t;
#else
return *(u32*)p;
#endif
}
extern bool is_pow2(int n);
// return -1 if not an integral power of 2,
// otherwise the base2 logarithm
extern int log2(const int n);
extern long round_up(long val, int multiple);
extern double ceil(double f);
#ifdef __cplusplus
}
#endif
#endif // #ifndef __MISC_H__

View File

@ -1,103 +0,0 @@
#include <cassert>
#include <cstring>
#include <cstdio>
#include "wsdl.h"
#include "ogl.h"
#ifdef _MSC_VER
#pragma comment(lib, "opengl32.lib")
#endif
// define extension function pointers
extern "C"
{
#define FUNC(ret, name, params) ret (__stdcall *name) params;
#include "glext_funcs.h"
#undef FUNC
}
static const char* exts;
// check if the extension <ext> is supported by the OpenGL implementation
bool oglExtAvail(const char* ext)
{
assert(exts && "call oglInit before using this function");
const char *p = exts, *end;
// make sure ext is valid & doesn't contain spaces
if(!ext || ext == '\0' || strchr(ext, ' '))
return false;
for(;;)
{
p = strstr(p, ext);
if(!p)
return false; // <ext> string not found - extension not supported
end = p + strlen(ext); // end of current substring
// make sure the substring found is an entire extension string,
// i.e. it starts and ends with ' '
if(p == exts || *(p-1) == ' ') // valid start?
if(*end == ' ' || *end == '\0') // valid end?
return true;
p = end;
}
}
void oglPrintErrors()
{
#define E(e) case e: printf("%s\n", #e); break;
for(;;)
switch(glGetError())
{
case GL_NO_ERROR:
return;
E(GL_INVALID_ENUM)
E(GL_INVALID_VALUE)
E(GL_INVALID_OPERATION)
E(GL_STACK_OVERFLOW)
E(GL_STACK_UNDERFLOW)
E(GL_OUT_OF_MEMORY)
}
}
int max_tex_size; // [pixels]
int tex_units;
int max_VAR_elements = -1; // GF2: 64K; GF3: 1M
bool tex_compression_avail; // S3TC / DXT{1,3,5}
int video_mem; // [MB]; approximate
#include "time.h"
// call after each video mode change
void oglInit()
{
exts = (const char*)glGetString(GL_EXTENSIONS);
// import functions
#define FUNC(ret, name, params) *(void**)&name = SDL_GL_GetProcAddress(#name);
#include "glext_funcs.h"
#undef FUNC
// detect OpenGL / graphics card caps
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &tex_units);
// make sure value is -1 if not supported
if(oglExtAvail("GL_NV_vertex_array_range"))
glGetIntegerv(GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV, &max_VAR_elements);
tex_compression_avail = oglExtAvail("GL_ARB_texture_compression") &&
(oglExtAvail("GL_EXT_texture_compression_s3tc") || oglExtAvail("GL_S3_s3tc"));
video_mem = (SDL_GetVideoInfo()->video_mem) / 1048576; // [MB]
// TODO: add sizeof(FB)?
}

View File

@ -1,65 +0,0 @@
#ifndef __OGL_H__
#define __OGL_H__
#ifdef __cplusplus
extern "C" {
#endif
// function pointer declarations
#define FUNC(ret, name, params) extern ret (__stdcall *name) params;
#include "glext_funcs.h"
#undef FUNC
#ifdef _WIN32
#ifndef WINGDIAPI
#define WINGDIAPI __declspec(dllimport)
#endif
#ifndef CALLBACK
#define CALLBACK __stdcall
#endif
#ifndef APIENTRY
#define APIENTRY __stdcall
#endif
typedef unsigned short wchar_t; // for glu.h
#endif // #ifndef _WIN32
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
#define GL_TEXTURE_IMAGE_SIZE_ARB 0x86A0
extern int max_tex_size; // [pixels]
extern int tex_units;
extern int max_VAR_elements; // GF2: 64K; GF3: 1M
extern bool tex_compression_avail; // S3TC / DXT{1,3,5}
extern int video_mem; // [MB]; approximate
// check if the extension <ext> is supported by the OpenGL implementation
extern bool oglExtAvail(const char* ext);
// print all OpenGL errors
extern void oglPrintErrors();
// call before using any of the above, and after each mode change
extern void oglInit();
#ifdef __cplusplus
}
#endif
#endif // #ifndef __OGL_H__

View File

@ -1,494 +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 <cassert>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include <process.h>
#include "posix.h"
#include "win.h"
#include "time.h"
#include "misc.h"
// VC6 windows.h may not have defined these
#ifndef INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
#ifndef PROCESSOR_ARCHITECTURE_AMD64
#define PROCESSOR_ARCHITECTURE_AMD64 9
#endif
extern "C"
{
// both hooked to support aio
extern int _open(const char* fn, int mode, ...);
extern int _close(int);
extern int _get_osfhandle(int);
extern void mainCRTStartup();
}
//////////////////////////////////////////////////////////////////////////////
//
// 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)_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)3, (HANDLE)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)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);
}
//////////////////////////////////////////////////////////////////////////////
//
// 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)_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;
}
#ifndef NO_WINSOCK
#ifdef _MSC_VER
#pragma comment(lib, "wsock32.lib")
#endif
extern "C" {
IMP(int, WSAStartup, (WORD, char*))
}
#endif
extern void entry(void);
void entry(void)
{
// alloc __pio, __iob?
// replace CRT init?
// header also removed to prevent calling Winsock functions
#ifndef NO_WINSOCK
char d[1024];
WSAStartup(0x0101, d);
#endif
mainCRTStartup();
}

View File

@ -1,437 +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/
#ifndef __POSIX_H__
#define __POSIX_H__
#include <sys/stat.h>
#ifdef __cplusplus
extern "C" {
#endif
#define IMP(ret, name, param) extern __declspec(dllimport) ret __stdcall name param;
//
// <inttypes.h>
//
typedef unsigned short u16_t;
//
// <sys/types.h>
//
typedef int ssize_t;
typedef unsigned int size_t;
//
// <limits.h>
//
#define PATH_MAX 260
//
// <errno.h>
//
enum
{
EINPROGRESS = 1000, // Operation in progress.
ENOMEM // Not enough space.
/*
EACCES, // Permission denied.
EADDRINUSE, // Address in use.
EADDRNOTAVAIL, // Address not available.
EAGAIN, // Resource unavailable, try again (may be the same value as EWOULDBLOCK]).
EALREADY, // Connection already in progress.
EBADF, // Bad file descriptor.
ECANCELED, // Operation canceled.
ECONNABORTED, // Connection aborted.
ECONNREFUSED, // Connection refused.
ECONNRESET, // Connection reset.
EDOM, // Mathematics argument out of domain of IMPtion.
EEXIST, // File exists.
EFAULT, // Bad address.
EHOSTUNREACH, // Host is unreachable.
EINTR, // Interrupted IMPtion.
EINVAL, // Invalid argument.
EISCONN, // Socket is connected.
EISDIR, // Is a directory.
ENAMETOOLONG, // Filename too long.
ENETDOWN, // Network is down.
ENETRESET, // Connection aborted by network.
ENETUNREACH, // Network unreachable.
ENOENT, // No such file or directory.
ENOEXEC, // Executable file format error.
ENOSPC, // No space left on device.
ENOSYS, // IMPtion not supported.
ENOTCONN, // The socket is not connected.
ENOTDIR, // Not a directory.
ENOTEMPTY, // Directory not empty.
ENOTSOCK, // Not a socket.
ENOTSUP, // Not supported.
EOVERFLOW, // Value too large to be stored in data type.
EPERM, // Operation not permitted.
EPIPE, // Broken pipe.
EPROTO, // Protocol error.
ERANGE, // Result too large.
ETIMEDOUT, // Connection timed out.
EWOULDBLOCK // Operation would block (may be the same value as EAGAIN]).
*/
};
//
// <time.h>
//
typedef long time_t;
typedef enum
{
CLOCK_REALTIME
}
clockid_t;
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
extern time_t time(time_t*);
extern int clock_gettime(clockid_t clock_id, struct timespec* tp);
extern int nanosleep(const struct timespec* rqtp, struct timespec* rmtp);
//
// sys/stat.h
//
typedef unsigned short ino_t;
typedef unsigned int mode_t;
typedef long off_t;
typedef unsigned int dev_t;
// struct stat defined in VC sys/stat.h
#define stat _stat
extern int mkdir(const char*, mode_t);
//
// dirent.h
//
typedef void DIR;
struct dirent
{
ino_t d_ino;
char* d_name;
};
extern DIR* opendir(const char* name);
extern struct dirent* readdir(DIR*);
extern int closedir(DIR*);
//
// <sys/mman.h>
//
#define PROT_READ 0x01 // page can be read
#define PROT_WRITE 0x02 // page can be written
#define MAP_SHARED 0x01 // share changes across processes
#define MAP_PRIVATE 0x02 // private copy on write mapping
#define MAP_FIXED 0x04
#define MAP_FAILED 0
extern void* mmap(void* start, unsigned int len, int prot, int flags, int fd, long offset);
extern int munmap(void* start, unsigned int len);
//
// <fcntl.h>
//
// values from MS _open - do not change!
#define O_RDONLY 0x0000 // open for reading only
#define O_WRONLY 0x0001 // open for writing only
#define O_RDWR 0x0002 // open for reading and writing
#define O_APPEND 0x0008 // writes done at eof
#define O_CREAT 0x0100 // create and open file
#define O_TRUNC 0x0200 // open and truncate
#define O_EXCL 0x0400 // open only if file doesn't already exist
#define O_BINARY 0x8000 // file mode is binary (untranslated)
#define O_NONBLOCK 0x1000000
extern int open(const char* fn, int mode, ...);
//
// <unistd.h>
//
#define F_OK 0
#define R_OK 1
#define W_OK 2
#define X_OK 4
#define read _read
#define write _write
extern int close(int);
extern int access(const char*, int);
extern int chdir(const char*);
extern unsigned int sleep(unsigned int sec);
IMP(int, gethostname, (char* name, size_t namelen))
//
// <stdlib.h>
//
extern char* realpath(const char*, char*);
//
// <signal.h>
//
union sigval
{
int sival_int; // Integer signal value.
void* sival_ptr; // Pointer signal value.
};
struct sigevent
{
int sigev_notify; // notification mode
int sigev_signo; // signal number
union sigval sigev_value; // signal value
};
//
// <termios.h>
//
#define TCSANOW 0
struct termios
{
long c_lflag;
};
#define ICANON 2 // do not change - correspond to ENABLE_LINE_INPUT / ENABLE_ECHO_INPUT
#define ECHO 4
extern int tcgetattr(int fd, struct termios* termios_p);
extern int tcsetattr(int fd, int optional_actions, const struct termios* termios_p);
//
// <sched.h>
//
struct sched_param
{
int sched_priority;
};
enum
{
SCHED_RR,
SCHED_FIFO,
SCHED_OTHER
};
#define sched_get_priority_max(policy) 15 // TIME_CRITICAL
#define sched_get_priority_min(policy) -15 // IDLE
//
// <pthread.h>
//
typedef unsigned int pthread_t;
extern pthread_t pthread_self();
extern int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param* param);
extern int pthread_create(pthread_t* thread, const void* attr, void*(*IMP)(void*), void* arg);
//
// <sys/socket.h>
//
typedef unsigned long socklen_t;
typedef unsigned short sa_family_t;
// Win32 values - do not change
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define AF_INET 2
struct sockaddr;
//
// <netinet/in.h>
//
typedef unsigned long in_addr_t;
typedef unsigned short in_port_t;
struct in_addr
{
in_addr_t s_addr;
};
struct sockaddr_in
{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
#define INADDR_ANY 0
//
// <netdb.h>
//
struct hostent
{
char* h_name; // Official name of the host.
char** h_aliases; // A pointer to an array of pointers to
// alternative host names, terminated by a
// null pointer.
short h_addrtype; // Address type.
short h_length; // The length, in bytes, of the address.
char** h_addr_list; // A pointer to an array of pointers to network
// addresses (in network byte order) for the host,
// terminated by a null pointer.
};
IMP(struct hostent*, gethostbyname, (const char *name))
//
// <arpa/inet.h>
//
extern u16_t htons(u16_t hostshort);
#define ntohs htons
IMP(in_addr_t, inet_addr, (const char*))
IMP(char*, inet_ntoa, (in_addr))
IMP(int, accept, (int, struct sockaddr*, socklen_t*))
IMP(int, bind, (int, const struct sockaddr*, socklen_t))
IMP(int, connect, (int, const struct sockaddr*, socklen_t))
IMP(int, listen, (int, int))
IMP(ssize_t, recv, (int, void*, size_t, int))
IMP(ssize_t, send, (int, const void*, size_t, int))
IMP(int, socket, (int, int, int))
//
// <poll.h>
//
struct pollfd
{
int fd;
short int events, revents;
};
#define POLLIN 1
extern int poll(struct pollfd[], int, int);
//
// <sys/utsname.h>
//
struct utsname
{
char sysname[9]; // Name of this implementation of the operating system.
char nodename[16]; // Name of this node within an implementation-defined
// communications network.
// Win9x requires this minimum buffer size.
char release[9]; // Current release level of this implementation.
char version[16]; // Current version level of this release.
char machine[9]; // Name of the hardware type on which the system is running.
};
extern int uname(struct utsname*);
//
// serial port IOCTL
//
// use with TIOCMBIS
#define TIOCM_RTS 1
// use with TIOCMGET or TIOCMIWAIT
#define TIOCM_CD 0x80 // MS_RLSD_ON
#define TIOCM_CTS 0x10 // MS_CTS_ON
enum
{
TIOCMBIS, // set control line
TIOCMGET, // get line state
TIOCMIWAIT // wait for status change
};
extern int ioctl(int fd, int op, int* data);
extern void _get_console();
extern void _hide_console();
#include "posix/aio.h"
#ifdef __cplusplus
}
#endif
#endif // #ifndef __POSIX_H__

View File

@ -1,289 +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 <cassert>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include "types.h"
#include "unzip.h"
#include "posix.h"
#include "misc.h"
#include "res.h"
#include "vfs.h"
// handle (32 bits)
// .. detect use of already freed handles
static const uint TAG_BITS = 18;
// .. index into array => = log2(max open handles)
static const uint IDX_BITS = 14;
static const uint TYPE_BITS = 5;
static const uint REF_BITS = 9;
struct Res
{
u32 key;
u32 tag : TAG_BITS;
u32 type : TYPE_BITS;
u32 refs : REF_BITS;
};
static const ulong res_array_cap = 1ul << IDX_BITS;
static const uint max_types = 1ul << TYPE_BITS;
// static allocation for simplicity; mem usage isn't significant
static Res res_array[res_array_cap];
static int first_free = -1;
static int max_idx = -1; // index of last in-use entry
// 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 = res_array_cap / hdata_per_page;
static HDATA* pages[num_pages];
static void(*dtors[max_types])(HDATA*);
static Handle handle(const uint idx)
{
if(idx >= (1 << IDX_BITS))
{
assert(!"invalid index passed to handle()");
return 0;
}
return (res_array[idx].tag << IDX_BITS) | idx;
}
static int h_idx(Handle h, uint type)
{
int idx = h & ((1 << IDX_BITS)-1);
const Res& r = res_array[idx];
u32 tag = h >> IDX_BITS;
if(!tag || r.tag != tag || r.type != type)
return -1;
return idx;
}
static void cleanup(void)
{
int i;
// close open handles
for(i = 0; i < max_idx; i++)
h_free(handle(i));
// free internal data space
for(i = 0; i < (int)num_pages; i++)
{
free(pages[i]);
pages[i] = 0;
}
}
Handle h_alloc(const u32 key, const uint type, DTOR dtor, HDATA*& hd)
{
ONCE(atexit(cleanup))
if(type >= max_types)
return 0;
if(dtor)
{
// registering a second dtor for type
if(dtors[type] && dtors[type] != dtor)
return 0;
dtors[type] = dtor;
}
Handle h;
int idx;
Res* r = res_array;
h = h_find(key, type, hd);
if(h)
{
idx = h_idx(h, type);
r = &res_array[idx];
if(r->refs == 1ul << REF_BITS)
{
assert(!"too many references to a handle - increase REF_BITS");
return 0;
}
r->refs++;
return h;
}
// cached
if(first_free != -1)
{
idx = first_free;
r = &res_array[idx];
}
// search res_array for first entry
else
for(idx = 0; idx < res_array_cap; idx++, r++)
if(!r->tag)
break;
// check if next entry is free
if(idx+1 < res_array_cap && !r[1].key)
first_free = idx+1;
else
first_free = -1;
if(idx >= res_array_cap)
{
assert(!"too many open handles (increase IDX_BITS)");
return 0;
}
if(idx > max_idx)
max_idx = idx;
static u32 tag;
if(++tag >= (1 << TAG_BITS))
{
assert(!"tag overflow - may not notice stale handle reuse (increase TAG_BITS)");
tag = 1;
}
r->key = key;
r->tag = tag;
r->type = type;
h = handle(idx);
hd = h_data(h, type);
return h;
}
Handle h_find(const u32 key, uint type, HDATA*& hd)
{
int idx;
const Res* r = res_array;
// already have first free entry cached - just search
if(first_free != -1)
{
for(idx = 0; idx <= max_idx; idx++, r++)
if(r->key == key && r->type == type)
goto found;
}
// search and remember first free entry (slower)
else
{
for(idx = 0; idx <= max_idx; idx++, r++)
if(!r->tag && first_free == -1)
first_free = idx;
else if(r->key == key && r->type == type)
goto found;
}
// not found
return 0;
found:
Handle h = handle(idx);
hd = h_data(h, type);
return h;
}
int h_free(const Handle h, const uint type)
{
int idx = h_idx(h, type);
if(idx == -1)
return -1;
Res& r = res_array[idx];
if(--r.refs)
return 0;
HDATA* hd = h_data(h, type);
if(hd && dtors[type])
dtors[type](hd);
r.key = 0;
r.tag = 0;
if(first_free == -1 || idx < first_free)
first_free = idx;
return 0;
}
HDATA* h_data(const Handle h, const uint type)
{
int idx = h_idx(h, type);
if(idx == -1)
return 0;
HDATA*& page = pages[idx / hdata_per_page];
if(!page)
page = (HDATA*)malloc(PAGE_SIZE);
if(!page)
return 0;
return &page[idx % hdata_per_page];
}
Handle res_load(const char* fn, uint type, DTOR dtor, void*& p, size_t& size, HDATA*& hd)
{
p = 0;
size = 0;
hd = 0;
u32 fn_hash = fnv_hash(fn, strlen(fn));
// TODO: fn is usually a constant; pass fn len if too slow
Handle h = h_alloc(fn_hash, type, dtor, hd);
if(!h || !hd)
return 0;
Handle hf = vfs_open(fn);
int err = vfs_read(hf, p, size, 0);
vfs_close(hf);
if(err < 0)
return 0;
hd->p = p;
hd->size = size;
return h;
}

View File

@ -1,60 +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"
enum
{
RES_MEM = 1,
RES_BIN = 2,
RES_TEX = 3,
RES_FONT = 4,
RES_ZIP = 5,
RES_VFILE = 6,
NUM_RES_TYPES
};
typedef unsigned long Handle;
const int HDATA_INTERNAL_SIZE = 24;
struct HDATA
{
void* p;
size_t size;
u8 internal[HDATA_INTERNAL_SIZE];
};
typedef void(*DTOR)(HDATA*);
extern Handle h_alloc(u32 key, uint type, DTOR dtor, HDATA*& hd);
extern int h_free(Handle h, uint type = 0);
extern Handle h_find(u32 key, uint type, HDATA*& hd);
extern HDATA* h_data(Handle h, uint type);
extern Handle res_load(const char* fn, uint type, DTOR dtor, void*& p, size_t& size, HDATA*& hd);
#endif // #ifndef __RES_H__

View File

@ -1,22 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by assert_dlg.rc
//
#define IDD_DIALOG1 101
#define IDC_EDIT1 1001
#define IDC_COPY 1002
#define IDC_CONTINUE 2000
#define IDC_SUPPRESS 2001
#define IDC_BREAK 2002
#define IDC_EXIT 2003
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1,694 +0,0 @@
// 2d texture format decoders
//
// 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 <cassert>
#include <cmath>
#include <cstdio>
#include "tex.h"
#include "ogl.h"
#include "res.h"
#include "misc.h"
#define NO_JP2
#define NO_PNG
#ifndef NO_JP2
#include <jasper/jasper.h>
#endif
#ifndef NO_PNG
#include <png.h>
#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);
const u8* img = ptr + hdr_size;
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->ptr = img;
tex->img_size = img_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("load_dds: %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));
}
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 u8* img = ptr + hdr_size;
const ulong img_size = (ulong)w * h * bpp / 8;
// determine format
u32 fmt = 0;
// .. grayscale
if(type == 3)
{
if(bpp == 8)
fmt = GL_LUMINANCE;
else if(bpp == 16 && alpha_bits == 8)
fmt = GL_LUMINANCE_ALPHA;
}
// .. true color
else if(type == 2)
{
if(bpp == 16 || bpp == 24)
fmt = GL_BGR;
else if(bpp == 32 && alpha_bits == 8)
fmt = GL_BGRA;
}
tex->width = w;
tex->height = h;
tex->fmt = fmt;
tex->ptr = img;
if(!fmt)
err = "unknown format / invalid 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("load_tga: %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: bpp = 24, uncompressed, 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 u8* img = ptr + ofs;
const u32 img_size = w * h * bpp/8;
tex->width = w;
tex->height = h;
tex->ptr = img;
tex->fmt = GL_BGR;
if(h < 0)
err = "top-down";
if(compress != BI_RGB)
err = "compressed";
if(bpp != 24)
err = "not 24 bpp";
if(size < ofs+img_size)
err = "image not completely read";
}
if(err)
{
printf("load_bmp: %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;
}
// requirements: width = height = 2^n, bpp = {16|24|32}
static int raw_load(const char* fn, const u8* ptr, size_t size, TEX* tex)
{
// 8bpp textures aren't supported,
// b/c it's impossible to differentiate 8bpp 2n*2n and 32bpp n*n
static GLenum fmts[5] = { 0, 0, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
for(int i = 2; i <= 4; i++)
{
u32 dim = (u32)sqrt(size/i);
if(size % i || // size is not a multiple of i components
!is_pow2(dim) || dim*dim*i != size)
continue;
tex->width = tex->height = dim;
tex->fmt = fmts[i];
tex->ptr = ptr;
return 0;
}
printf("load_raw: %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;
}
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("load_png: %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 bit_depth, 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(bit_depth != 8)
{
err = "bit depth != 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;
tex->ptr = img;
uint fmts[8] = { GL_LUMINANCE, 0, GL_RGB, 0, GL_LUMINANCE_ALPHA, 0, GL_RGBA, 0 };
assert(color_type < 8);
tex->fmt = fmts[color_type];
if(!tex->fmt) // <==> palette image
{
printf("load_png: %s: %s\n", fn, "palettes not supported");
return -1;
}
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)
{
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 depth = jas_image_cmptprec (image, 0);
if(depth != 8)
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->ptr = img;
return 0;
}
#endif
static void tex_dtor(HDATA* hd)
{
TEX* tex = (TEX*)hd->internal;
glDeleteTextures(1, &tex->id);
}
u32 tex_load(const char* fn, TEX* ptex)
{
// load file
const u8* p;
size_t size;
HDATA* hd;
u32 h = res_load(fn, RES_TEX, tex_dtor, (void*&)p, size, hd);
if(h != 0 && !p) // already loaded
return h;
if(!p || size < 4) // is_* require a valid pointer, and >= 4 bytes
return 0;
TEX* tex = (TEX*)hd->internal;
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;
uint id;
glGenTextures(1, &id);
tex->id = id;
if(ptex)
*ptex = *tex;
return h;
}
int tex_bind(u32 h)
{
HDATA* hd = h_data(h, RES_TEX);
if(!hd)
{
glBindTexture(GL_TEXTURE_2D, 0);
return -1;
}
TEX* tex = (TEX*)hd->internal;
glBindTexture(GL_TEXTURE_2D, tex->id);
return 0;
}
uint tex_filter_quality = BILINEAR; // 1..6
uint tex_bpp = 32; // 16 or 32
int tex_upload(const u32 h, const uint q_ovr, uint int_fmt)
{
HDATA* hd = h_data(h, RES_TEX);
if(!hd)
return -1;
TEX* tex = (TEX*)hd->internal;
// TODO: texture_rectangle or subtexture
if(!is_pow2(tex->width) || !is_pow2(tex->height))
return 0;
tex_bind(h);
// filter quality
uint q = q_ovr? q_ovr : tex_filter_quality;
if(q > 6)
return 0;
const uint filters[7] = { 0, GL_NEAREST, GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR };
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filters[q]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filters[min(q, 2)]);
// internal format
if(!int_fmt)
{
if(tex->fmt == GL_RGBA || tex->fmt == GL_BGRA)
int_fmt = (tex_bpp == 32)? 4 : GL_RGBA4;
else
int_fmt = (tex_bpp == 32)? 3 : GL_RGB5;
}
if(tex->fmt >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
tex->fmt <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, tex->fmt, tex->width, tex->height, 0, tex->img_size, tex->ptr);
else
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, tex->width, tex->height, 0, tex->fmt, GL_UNSIGNED_BYTE, tex->ptr);
return 0;
}

View File

@ -1,48 +0,0 @@
//
// 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/
#ifndef __TEX_H__
#define __TEX_H__
#include "types.h"
struct TEX
{
uint width;
uint height;
uint fmt;
const u8* ptr;
uint id;
uint img_size; // currently only used for S3TC
};
extern u32 tex_load(const char* fn, TEX* ti = 0);
extern int tex_bind(u32 h);
const int BILINEAR = 2;
const int TRINILEAR = 6;
extern uint tex_filter_quality; // 1..6; default: BILINEAR
extern uint tex_bpp; // 16 or 32; default: 32
extern int tex_upload(u32 h, uint filter_quality = 0, uint internal_fmt = 0);
#endif // __TEX_H__

View File

@ -1,167 +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 <time.h>
#include <cmath>
#include "detect.h"
#include "time.h"
#include "types.h"
#ifdef _WIN32
#include "win.h"
#endif
// 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)
extern u64 rdtsc();
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) // \
trend = -1;
else if(cur_fps < h1 && h1 < h2) // /
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
float avg_fps = fps_sum / H;
if((trend > 0 && (avg_fps > fps || avg_fps-fps < -4.f)) || // going up, or large drop
(trend < 0 && (avg_fps < fps || avg_fps-fps > 4.f)) || // going down, or large raise
(fabs(fps-avg_fps) > min(5.f, 0.05f*fps))) // significant difference
fps = (int)avg_fps;
}

View File

@ -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__

View File

@ -1,18 +0,0 @@
#ifndef __TYPES_H__
#define __TYPES_H__
// defines instead of typedefs so we can #undef conflicting decls
#define uint unsigned int
#define ulong unsigned long
#define int8 signed char
#define int16 short
#define int32 long
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned long // compatibility with Win32 DWORD
#define u64 unsigned __int64
#endif // #ifndef __TYPES_H__

View File

@ -1,351 +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 <cassert>
#include <cstring>
#include <cstdlib>
#include <zlib.h>
#include "unzip.h"
#include "posix.h"
#include "misc.h"
#include "res.h"
#include "mem.h"
#ifdef _MSC_VER
#pragma comment(lib, "zlib.lib")
#endif
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
// Location and size of an archived file
struct File
{
u32 ofs;
u32 csize; // bit 31 = compression method (1: deflate; 0: stored)
u32 ucsize;
};
struct ZIP
{
int fd;
// file lookup
u32 num_files;
u32* fn_hashs; // split for more efficient search
File* files;
u32 last_file; // index of last file we found (speed up lookups of sequential files)
};
static void zip_dtor(HDATA* hd)
{
ZIP* const z = (ZIP*)hd->internal;
close(z->fd);
z->fd = -1;
}
// open and return a handle to the zip archive indicated by <fn>
Handle zopen(const char* const fn)
{
const u32 fn_hash = fnv_hash(fn, strlen(fn));
// already loaded?
HDATA* hd;
Handle h = h_find(fn_hash, RES_ZIP, hd);
if(h)
return h;
// file size
struct stat stat_buf;
if(stat(fn, &stat_buf))
return 0;
const size_t size = stat_buf.st_size;
if(size < 4) // ECDR scan below would overrun
return 0;
// map zip file (easy access while getting list of files)
const int fd = open(fn, O_RDONLY);
if(fd < 0)
return 0;
u8* zfile = (u8*)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
if(zfile == MAP_FAILED)
return 0;
// 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
u32 bytes_left = min(size, 66000);
u8* ecdr = zfile + size - bytes_left;
while(bytes_left)
{
if(*(u32*)ecdr == *(u32*)&ecdr_id)
break;
// check next 4 bytes (non aligned!!)
ecdr++;
bytes_left--;
}
{
// reached EOF and still haven't found the ECDR identifier
if(bytes_left == 0)
goto fail;
// read ECDR
u16 num_files = read_le16(ecdr+10);
u32 cd_ofs = read_le32(ecdr+16);
h = h_alloc(fn_hash, RES_ZIP, zip_dtor, hd);
if(!h || !hd)
goto fail;
ZIP* const zip = (ZIP*)hd->internal;
zip->fd = fd;
zip->fn_hashs = ( u32*)mem_alloc(num_files * sizeof(u32 ), MEM_HEAP, 64);
zip->files = (File*)mem_alloc(num_files * sizeof(File), MEM_HEAP, 64);
if(!zip->fn_hashs || !zip->files)
{
h_free(h, RES_ZIP);
mem_free(zip->fn_hashs);
mem_free(zip->files);
goto fail;
}
zip->num_files = num_files;
zip->last_file = 0;
// cache file list for faster lookups
// currently linear search, comparing filename hash.
// if too slow, use hash table
const u8* cdfh = zfile+cd_ofs;
u32* hs = zip->fn_hashs;
File* f = zip->files;
for(uint i = 0; i < zip->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];
// 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 | ((method == 8)? BIT(31) : 0);
f->ucsize = ucsize;
f++;
(int&)cdfh += 46 + fn_len + e_len + c_len;
}
}
// unmap file and return 0
fail:
munmap(zfile, size);
// actual reading is done with aio
return h;
}
// close the zip file zd
void zclose(const Handle h)
{
h_free(h, RES_ZIP);
}
// make file <fn> in zip <zd> available
// returns a pointer to the data, and optionally its size (0 on error)
//
// returns 0 on error.
int zread(Handle h, const char* fn, void*& p, size_t& size, size_t ofs)
{
// size = 0 if we fail
size = 0;
HDATA* hd = h_data(h, RES_ZIP);
if(!hd)
return 0;
ZIP* zip = (ZIP*)hd->internal;
// find its File descriptor
u32 fn_hash = fnv_hash(fn, strlen(fn));
uint i = zip->last_file+1;
if(i >= zip->num_files || zip->fn_hashs[i] != fn_hash)
{
for(i = 0; i < zip->num_files; i++)
if(zip->fn_hashs[i] == fn_hash)
break;
if(i == zip->num_files)
return 0;
zip->last_file = i;
}
const File* const f = &zip->files[i];
const bool deflated = (f->csize & BIT(31)) != 0;
ofs += f->ofs;
const u32 csize = f->csize & ~BIT(31);
const u32 ucsize = f->ucsize;
aiocb cbs[2];
memset(cbs, 0, sizeof(cbs));
cbs[0].aio_fildes = cbs[1].aio_fildes = zip->fd;
// decompress only:
void* read_bufs = 0;
const int BLOCK_SIZE = 64*KB;
int active_read = 0;
z_stream stream;
if(deflated)
{
memset(&stream, 0, sizeof(stream));
if(inflateInit2(&stream, -MAX_WBITS) != Z_OK)
return -1;
// -MAX_WBITS indicates no zlib header present
read_bufs = mem_alloc(BLOCK_SIZE*2, MEM_HEAP, 64*KB);
if(!read_bufs)
return -1;
cbs[0].aio_buf = read_bufs;
cbs[1].aio_buf = (u8*)read_bufs + BLOCK_SIZE;
}
void* out_mem = mem_alloc(ucsize, MEM_HEAP, 64*KB);
// pos in output buffer when reading uncompressed data
u8* out_pos = (u8*)out_mem;
stream.next_out = (u8*)out_mem;
stream.avail_out = ucsize;
long cbytes_left = csize;
bool first = true;
bool done = false;
for(;;)
{
aiocb* cb = &cbs[active_read];
// start reading next block
if(cbytes_left)
{
// align to 64 KB for speed
u32 rsize = min(64*KB - (ofs & 0xffff), cbytes_left);
// if uncompressed, read directly into output buffer
if(!deflated)
{
cb->aio_buf = out_pos;
out_pos += rsize;
}
cb->aio_offset = ofs;
cb->aio_nbytes = rsize;
aio_read(cb);
ofs += rsize;
cbytes_left -= rsize;
assert(cbytes_left >= 0); // read size clamped => never negative
}
active_read ^= 1;
// process block read in previous iteration
if(first)
first = false;
else
{
// wait for read to complete
cb = &cbs[active_read];
while(aio_error(cb) == -EINPROGRESS)
aio_suspend(&cb, 1, 0);
ssize_t bytes_read = aio_return(cb);
// inflate
if(deflated)
{
stream.next_in = (u8*)cb->aio_buf;
stream.avail_in = bytes_read;
inflate(&stream, 0);
}
}
// one more iteration to process the last pending block
if(done)
break;
if(!cbytes_left)
done = true;
}
if(deflated)
{
inflateEnd(&stream);
mem_free(read_bufs);
if(stream.total_in != csize || stream.total_out != ucsize)
{
// read_bufs is not yet allocated, or already freed
mem_free(out_mem);
return 0;
}
}
p = out_mem;
size = ucsize;
return 0;
}
//1 cache per zip - res layer doesnt know our internals (cache entry=ofs, csize,ucsize)
//cache=array (allow finding next file quickly; need some mechanism for faster random access?)
//sync is not a problem - zip file won't be updated during gameplay because it's still open

View File

@ -1,33 +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 __UNZIP_H__
#define __UNZIP_H__
#include "res.h"
// open and return a handle to the zip archive indicated by <fn>
extern Handle zopen(const char* fn);
extern void zclose(Handle h);
extern int zread(Handle h, const char* fn, void*& p, size_t& size, size_t ofs);
#endif // #ifndef __UNZIP_H__

View File

@ -1,169 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "posix.h"
#include "unzip.h"
#include "misc.h"
#include "vfs.h"
#include "mem.h"
struct PATH
{
Handle zip;
const char* path;
struct PATH* next;
};
static PATH* path_list;
int vfs_goto_app_dir(char* argv0)
{
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;
return chdir(path);
}
// TODO: check CD drives?
int vfs_add_search_path(const char* p)
{
// copy path string - need to append .zip / save a copy if dir
const size_t path_len = strlen(p);
char* path = (char*)mem_alloc(path_len+4+1);
if(!p)
return -1;
strcpy(path, p);
// ZIP file?
strcpy(path+path_len, ".zip"); // append zip extension
Handle zip = zopen(path);
// dir?
path[path_len] = 0; // remove .zip extension
DIR* dir = opendir(path);
if(dir)
closedir(dir);
else
mem_free(path);
// neither
if(!zip && !dir)
return -1;
PATH* entry = (PATH*)mem_alloc(sizeof(PATH));
if(!entry)
return -1;
entry->next = path_list;
path_list = entry;
entry->zip = zip;
entry->path = dir? path : 0;
return 0;
}
int vfs_remove_first_path()
{
PATH* const p = path_list;
if(!p)
return -1;
mem_free((void*)p->path);
path_list = p->next;
zclose(p->zip);
mem_free(p);
return 0;
}
static void vfile_dtor(HDATA* hd)
{
}
Handle vfs_open(const char* fn)
{
char path[PATH_MAX+1]; path[PATH_MAX] = 0;
// for each search path:
for(PATH* entry = path_list; entry; entry = entry->next)
{
// dir - memory map the file
{
if(!entry->path)
goto not_dir;
struct stat stat_buf;
snprintf(path, PATH_MAX, "%s%c%s", entry->path, DIR_SEP, fn);
if(stat(path, &stat_buf) != 0)
goto not_dir;
int fd = open(path, O_RDONLY);
if(fd < 0)
goto not_dir;
size_t size = stat_buf.st_size;
void* p = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if(p != MAP_FAILED)
{
HDATA* hd;
Handle h = h_alloc(0, RES_VFILE, vfile_dtor, hd);
if(h && hd)
{
hd->p = p;
hd->size = size;
return h;
}
}
}
not_dir:
// archive
if(entry->zip)
return entry->zip;
}
// not found
return 0;
}
int vfs_read(Handle h, void*& p, size_t& size, size_t ofs)
{
p = 0;
size = 0;
HDATA* hd = h_data(h, RES_VFILE);
if(hd)
{
p = (u8*)hd->p + ofs;
if(!size || size > hd->size)
size = hd->size;
return 0;
}
// else
// return zread(h, fn, p, size, ofs);
return -1;
}
int vfs_close(Handle h)
{
h_free(h, RES_ZIP);
h_free(h, RES_VFILE);
return 0;
}

View File

@ -1,8 +0,0 @@
extern int vfs_add_search_path(const char* path);
extern int vfs_remove_first_path();
extern Handle vfs_open(const char* fn);
extern int vfs_close(Handle h);
extern int vfs_read(Handle h, void*& p, size_t& size, size_t ofs = 0);

View File

@ -1,5 +0,0 @@
#define _WINSOCKAPI_ // sockets already defined by posix.h
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define _WIN32_WINNT 0x0400 // needed for e.g. mousewheel support
#include <windows.h>

View File

@ -1,547 +0,0 @@
/*
* emulation of a subset of SDL and GLUT for Win32
*
* 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 <stdio.h>
#include <stdlib.h>
#include <process.h>
#include "wsdl.h"
#include "win.h"
#include "misc.h"
/* 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) /* ev must be valid */
{
/* windows messages */
MSG msg;
while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
/* key */
if(msg.message == WM_KEYUP || msg.message == WM_KEYDOWN)
{
ev->type = (u8)((msg.message == WM_KEYUP)? SDL_KEYUP : SDL_KEYDOWN);
ev->key.keysym.sym = (SDLKey)msg.wParam;
return 1;
}
if(msg.message == WM_SYSCOMMAND)
ev->type = 0;
/* mouse click */
uint button;
for(button = 0; button < 3; button++)
{
if(msg.message == button+WM_LBUTTONDOWN)
ev->type = SDL_MOUSEBUTTONDOWN;
else if(msg.message == button+WM_LBUTTONUP)
ev->type = SDL_MOUSEBUTTONUP;
}
if(button < 3)
{
ev->button.button = (u8)button;
ev->button.x = (u16)(msg.lParam & 0xffff);
ev->button.y = (u16)((msg.lParam >> 16) & 0xffff);
return 1;
}
/* active */
if(msg.message == WM_ACTIVATE)
{
ev->type = SDL_ACTIVE;
ev->active.gain = app_active;
ev->active.state = 0;
return 1;
}
}
/*
* mouse motion
*
* don't use DirectInput, because we want to respect the user's mouse sensitivity
* 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;
int cur_bpp = dm.dmBitsPerPel;
/*
* 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(/* wrong bit depth */
(bpp != cur_bpp) ||
/* 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.dmBitsPerPel = bpp;
dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
}
// 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, dm.dmPelsWidth, dm.dmPelsHeight, 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);
}
static SDL_VideoInfo video_info;
#ifdef DDRAW7
#include <ddraw.h>
#ifdef _MSC_VER
#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")
#endif
#endif
int SDL_Init(u32 flags)
{
UNUSED(flags)
#ifdef DDRAW7
LPDIRECTDRAW7 dd;
DirectDrawCreateEx(0, (void**)&dd, IID_IDirectDraw7, 0);
static DDSCAPS2 caps;
caps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
dd->GetAvailableVidMem(&caps, (DWORD*)&video_info.video_mem, 0);
dd->Release();
#endif
dm.dmSize = sizeof(DEVMODE);
EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm);
return 0;
}
void SDL_Quit()
{
DestroyWindow(hWnd);
wglMakeCurrent(0, 0);
wglDeleteContext(hGLRC);
ChangeDisplaySettings(0, 0);
}
SDL_VideoInfo* SDL_GetVideoInfo()
{
return &video_info;
}
SDL_Surface* SDL_GetVideoSurface()
{
static SDL_Surface surf;
surf.w = dm.dmPelsWidth;
surf.h = dm.dmPelsHeight;
return &surf;
}
__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, (const char*)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();
}
}
}

View File

@ -1,287 +0,0 @@
#ifndef __WSDL_H__
#define __WSDL_H__
#ifndef _WIN32
#include <SDL/sdl.h>
#else
#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 int SDL_Init(u32);
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_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'
}
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
{
SDL_BUTTON_LEFT,
SDL_BUTTON_MIDDLE,
SDL_BUTTON_RIGHT
};
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 /* #else / #ifndef WIN32 */
#endif /* #ifndef __WSDL_H__ */