misc fixes/tweaks/stuff intended to get the emscripten port working better.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4456 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
cf893a1921
commit
3b51dae2c9
21 changed files with 1303 additions and 135 deletions
|
@ -1118,20 +1118,24 @@ ifeq ($(FTE_TARGET),droid)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(FTE_TARGET),web)
|
ifeq ($(FTE_TARGET),web)
|
||||||
|
COMMON_OBJS+=sys_web.o fs_web.o
|
||||||
WEB_PREJS ?= --pre-js web/prejs.js
|
WEB_PREJS ?= --pre-js web/prejs.js
|
||||||
# WEB_MEMORY?=402653184 #384mb
|
# WEB_MEMORY?=402653184 #384mb
|
||||||
ASMJS_MEMORY?=536870912 #512mb (required for asm.js)
|
ASMJS_MEMORY?=536870912 #512mb (required for asm.js)
|
||||||
|
# ASMJS_MEMORY?=268435456 #256mb (required for asm.js)
|
||||||
WEB_MEMORY?=$(ASMJS_MEMORY)
|
WEB_MEMORY?=$(ASMJS_MEMORY)
|
||||||
|
JSLIBS=--js-library web/ftejslib.js --js-library web/library_sdl.js -s DISABLE_GL_EMULATION=1
|
||||||
|
EMCC_ARGS=$(JSLIBS) $(WEB_PREJS) --shell-file web/fteshell.html -s ERROR_ON_UNDEFINED_SYMBOLS=1
|
||||||
RELEASE_CFLAGS=-DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
RELEASE_CFLAGS=-DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
||||||
DEBUG_CFLAGS=-g --jcache -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
DEBUG_CFLAGS=-g --jcache -DOMIT_QCC -DGL_STATIC -DFTE_TARGET_WEB
|
||||||
# RELEASE_LDFLAGS=-s ASM_JS=1 -O2 $(WEB_PREJS) -s TOTAL_MEMORY=$(ASMJS_MEMORY) --js-library web/ftejslib.js --shell-file web/fteshell.html
|
RELEASE_LDFLAGS=-s ASM_JS=1 -O1 -s TOTAL_MEMORY=$(ASMJS_MEMORY) $(EMCC_ARGS)
|
||||||
RELEASE_LDFLAGS=-O1 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js --shell-file web/fteshell.html
|
# RELEASE_LDFLAGS=-s ASM_JS=0 -O1 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS)
|
||||||
DEBUG_LDLAGS=-O0 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js
|
DEBUG_LDLAGS=-O0 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS)
|
||||||
CC=emcc
|
CC=emcc
|
||||||
#BASELDFLAGS=
|
#BASELDFLAGS=
|
||||||
|
|
||||||
#mostly we inherit the sdl defaults. because we can, however emscripten does not support sdl cd code.
|
#mostly we inherit the sdl defaults. because we can, however emscripten does not support sdl cd code.
|
||||||
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) gl_vidsdl.o snd_sdl.o cd_null.o sys_sdl.o in_sdl.o
|
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) gl_vidweb.o cd_null.o
|
||||||
SDL_INCLUDES=
|
SDL_INCLUDES=
|
||||||
|
|
||||||
SV_DIR=sv_web
|
SV_DIR=sv_web
|
||||||
|
@ -1200,7 +1204,7 @@ ifneq ($(OUT_DIR),)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(BOTLIB_DIR) : $(BASE_DIR)/libs/speex/libspeex
|
VPATH = $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(BASE_DIR)/irc : $(BASE_DIR)/email : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(BOTLIB_DIR) : $(BASE_DIR)/libs/speex/libspeex : $(BASE_DIR)/web
|
||||||
|
|
||||||
ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),)
|
ifneq ($(findstring -DSPEEX_STATIC, $(CFLAGS)),)
|
||||||
#add these to statically link libspeex
|
#add these to statically link libspeex
|
||||||
|
|
|
@ -254,7 +254,7 @@ static texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
|
||||||
|
|
||||||
typedef struct wadfile_s {
|
typedef struct wadfile_s {
|
||||||
char name[64];
|
char name[64];
|
||||||
FILE *file;
|
vfsfile_t *file;
|
||||||
struct wadfile_s *next;
|
struct wadfile_s *next;
|
||||||
} wadfile_t;
|
} wadfile_t;
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ void Wads_Flush (void)
|
||||||
wadfile_t *wf;
|
wadfile_t *wf;
|
||||||
while(openwadfiles)
|
while(openwadfiles)
|
||||||
{
|
{
|
||||||
fclose(openwadfiles->file);
|
VFS_CLOSE(openwadfiles->file);
|
||||||
|
|
||||||
wf = openwadfiles->next;
|
wf = openwadfiles->next;
|
||||||
Z_Free(openwadfiles);
|
Z_Free(openwadfiles);
|
||||||
|
|
|
@ -3796,7 +3796,7 @@ void COM_InitArgv (int argc, const char **argv) //not allowed to tprint
|
||||||
int i;
|
int i;
|
||||||
size_t result;
|
size_t result;
|
||||||
|
|
||||||
#ifndef NACL
|
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (argv && argv[0])
|
if (argv && argv[0])
|
||||||
|
|
|
@ -479,6 +479,11 @@ void Cvar_Reset_f (void)
|
||||||
if (gsearch)
|
if (gsearch)
|
||||||
Q_strlwr(gsearch);
|
Q_strlwr(gsearch);
|
||||||
|
|
||||||
|
if (!strcmp(search, "*"))
|
||||||
|
search = NULL;
|
||||||
|
if (!strcmp(gsearch, "*"))
|
||||||
|
gsearch = NULL;
|
||||||
|
|
||||||
for (grp=cvar_groups ; grp ; grp=grp->next)
|
for (grp=cvar_groups ; grp ; grp=grp->next)
|
||||||
{
|
{
|
||||||
if (gsearch)
|
if (gsearch)
|
||||||
|
@ -519,7 +524,7 @@ void Cvar_Reset_f (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmd->flags & CVAR_NOSET) && !strcmp(search, "*"))
|
if ((cmd->flags & CVAR_NOSET) && !search)
|
||||||
continue;
|
continue;
|
||||||
// reset cvar to default
|
// reset cvar to default
|
||||||
Cvar_Set(cmd, cmd->defaultstr);
|
Cvar_Set(cmd, cmd->defaultstr);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
|
|
||||||
#ifndef NACL
|
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
|
||||||
|
|
||||||
#ifdef WEBSVONLY
|
#ifdef WEBSVONLY
|
||||||
#define Z_Free free
|
#define Z_Free free
|
||||||
|
|
|
@ -4066,11 +4066,7 @@ struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboole
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FTE_TARGET_WEB
|
#ifdef FTE_TARGET_WEB
|
||||||
int emscriptenfte_ws_connect(char *url);
|
#include "web/ftejslib.h"
|
||||||
int emscriptenfte_ws_close(int sock);
|
|
||||||
int emscriptenfte_ws_cansend(int sock, int extra, int maxpending);
|
|
||||||
int emscriptenfte_ws_send(int sock, void *data, int len);
|
|
||||||
int emscriptenfte_ws_recv(int sock, void *data, int len);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -563,6 +563,9 @@ void TL_ParseLanguage (char *name, char *data, int num) //this is one of the fir
|
||||||
|
|
||||||
void TL_LoadLanguage (char *name, char *shortname, int num) //this is one of the first functions to be called.
|
void TL_LoadLanguage (char *name, char *shortname, int num) //this is one of the first functions to be called.
|
||||||
{
|
{
|
||||||
|
#ifdef FTE_TARGET_WEB
|
||||||
|
return;
|
||||||
|
#else
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int size;
|
int size;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
@ -585,6 +588,7 @@ void TL_LoadLanguage (char *name, char *shortname, int num) //this is one of the
|
||||||
|
|
||||||
TL_ParseLanguage(name, buffer, num);
|
TL_ParseLanguage(name, buffer, num);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define CONVERTDEFAULT
|
#define CONVERTDEFAULT
|
||||||
|
|
|
@ -1271,6 +1271,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
|
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
|
||||||
|
if (scaled_width * scaled_height*4 > sizeofuploadmemorybufferintermediate)
|
||||||
|
{
|
||||||
|
sizeofuploadmemorybufferintermediate = scaled_width * scaled_height * 4;
|
||||||
|
uploadmemorybufferintermediate = BZ_Realloc(uploadmemorybufferintermediate, sizeofuploadmemorybufferintermediate);
|
||||||
|
}
|
||||||
|
|
||||||
if (scaled_width*scaled_height*4 > sizeofuploadmemorybufferintermediate)
|
if (scaled_width*scaled_height*4 > sizeofuploadmemorybufferintermediate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -158,6 +158,7 @@ void (APIENTRY *qglFogf) (GLenum pname, GLfloat param);
|
||||||
void (APIENTRY *qglFogi) (GLenum pname, GLint param);
|
void (APIENTRY *qglFogi) (GLenum pname, GLint param);
|
||||||
void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params);
|
void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params);
|
||||||
|
|
||||||
|
#ifndef GL_STATIC
|
||||||
void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids);
|
void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids);
|
||||||
void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids);
|
void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids);
|
||||||
void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id);
|
void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id);
|
||||||
|
@ -165,6 +166,7 @@ void (APIENTRY *qglBufferDataARB)(GLenum target, GLsizei size, const void* data,
|
||||||
void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data);
|
void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data);
|
||||||
void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access);
|
void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access);
|
||||||
GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
|
GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
|
||||||
|
#endif
|
||||||
|
|
||||||
void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
|
void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
|
||||||
void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
||||||
|
@ -172,11 +174,13 @@ void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
||||||
const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index);
|
const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index);
|
||||||
void (APIENTRY * qglGetPointerv) (GLenum pname, GLvoid **parms);
|
void (APIENTRY * qglGetPointerv) (GLenum pname, GLvoid **parms);
|
||||||
|
|
||||||
|
#ifndef GL_STATIC
|
||||||
void (APIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint* ids);
|
void (APIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint* ids);
|
||||||
void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id);
|
void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id);
|
||||||
void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
||||||
void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId);
|
void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId);
|
||||||
GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
|
GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
|
||||||
|
#endif
|
||||||
|
|
||||||
void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
|
void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
|
||||||
/*
|
/*
|
||||||
|
@ -191,7 +195,9 @@ FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT;
|
||||||
|
|
||||||
//extensions
|
//extensions
|
||||||
//arb multitexture
|
//arb multitexture
|
||||||
|
#ifndef qglActiveTextureARB
|
||||||
qlpSelTexFUNC qglActiveTextureARB;
|
qlpSelTexFUNC qglActiveTextureARB;
|
||||||
|
#endif
|
||||||
qlpSelTexFUNC qglClientActiveTextureARB;
|
qlpSelTexFUNC qglClientActiveTextureARB;
|
||||||
qlpMTex3FUNC qglMultiTexCoord3fARB;
|
qlpMTex3FUNC qglMultiTexCoord3fARB;
|
||||||
qlpMTex2FUNC qglMultiTexCoord2fARB;
|
qlpMTex2FUNC qglMultiTexCoord2fARB;
|
||||||
|
@ -521,7 +527,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
//multitexture
|
//multitexture
|
||||||
gl_mtexable = false;
|
gl_mtexable = false;
|
||||||
gl_mtexarbable = 0;
|
gl_mtexarbable = 0;
|
||||||
|
#ifndef qglActiveTextureARB
|
||||||
qglActiveTextureARB = NULL;
|
qglActiveTextureARB = NULL;
|
||||||
|
#endif
|
||||||
qglMultiTexCoord2fARB = NULL;
|
qglMultiTexCoord2fARB = NULL;
|
||||||
qglMultiTexCoord3fARB = NULL;
|
qglMultiTexCoord3fARB = NULL;
|
||||||
qglMTexCoord2fSGIS = NULL;
|
qglMTexCoord2fSGIS = NULL;
|
||||||
|
@ -587,7 +595,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
|
|
||||||
if (gl_config.gles)
|
if (gl_config.gles)
|
||||||
{
|
{
|
||||||
|
#ifndef qglActiveTextureARB
|
||||||
qglActiveTextureARB = (void *) getglext("glActiveTexture");
|
qglActiveTextureARB = (void *) getglext("glActiveTexture");
|
||||||
|
#endif
|
||||||
qglClientActiveTextureARB = (void *) getglext("glClientActiveTexture");
|
qglClientActiveTextureARB = (void *) getglext("glClientActiveTexture");
|
||||||
qglSelectTextureSGIS = qglActiveTextureARB;
|
qglSelectTextureSGIS = qglActiveTextureARB;
|
||||||
mtexid0 = GL_TEXTURE0_ARB;
|
mtexid0 = GL_TEXTURE0_ARB;
|
||||||
|
@ -598,7 +608,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
}
|
}
|
||||||
else if (GL_CheckExtension("GL_ARB_multitexture") && !COM_CheckParm("-noamtex"))
|
else if (GL_CheckExtension("GL_ARB_multitexture") && !COM_CheckParm("-noamtex"))
|
||||||
{ //ARB multitexture is the popular choice.
|
{ //ARB multitexture is the popular choice.
|
||||||
|
#ifndef qglActiveTextureARB
|
||||||
qglActiveTextureARB = (void *) getglext("glActiveTextureARB");
|
qglActiveTextureARB = (void *) getglext("glActiveTextureARB");
|
||||||
|
#endif
|
||||||
qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB");
|
qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB");
|
||||||
qglMultiTexCoord2fARB = (void *) getglext("glMultiTexCoord2fARB");
|
qglMultiTexCoord2fARB = (void *) getglext("glMultiTexCoord2fARB");
|
||||||
qglMultiTexCoord3fARB = (void *) getglext("glMultiTexCoord3fARB");
|
qglMultiTexCoord3fARB = (void *) getglext("glMultiTexCoord3fARB");
|
||||||
|
@ -611,6 +623,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
|
|
||||||
mtexid0 = GL_TEXTURE0_ARB;
|
mtexid0 = GL_TEXTURE0_ARB;
|
||||||
|
|
||||||
|
#ifndef qglActiveTextureARB
|
||||||
if (!qglActiveTextureARB || !qglClientActiveTextureARB || !qglMultiTexCoord2fARB)
|
if (!qglActiveTextureARB || !qglClientActiveTextureARB || !qglMultiTexCoord2fARB)
|
||||||
{
|
{
|
||||||
qglActiveTextureARB = NULL;
|
qglActiveTextureARB = NULL;
|
||||||
|
@ -625,7 +638,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
{
|
{
|
||||||
Con_DPrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n");
|
Con_DPrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
else if (GL_CheckExtension("GL_SGIS_multitexture") && !COM_CheckParm("-nomtex"))
|
else if (GL_CheckExtension("GL_SGIS_multitexture") && !COM_CheckParm("-nomtex"))
|
||||||
|
@ -712,6 +725,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
|
|
||||||
gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map");
|
gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map");
|
||||||
|
|
||||||
|
#if !defined(GL_STATIC)
|
||||||
/*vbos*/
|
/*vbos*/
|
||||||
if (gl_config.gles && gl_config.glversion >= 2)
|
if (gl_config.gles && gl_config.glversion >= 2)
|
||||||
{
|
{
|
||||||
|
@ -733,6 +747,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
||||||
qglMapBufferARB = (void *)getglext("glMapBufferARB");
|
qglMapBufferARB = (void *)getglext("glMapBufferARB");
|
||||||
qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB");
|
qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GL_STATIC
|
#ifdef GL_STATIC
|
||||||
gl_config.arb_shader_objects = true;
|
gl_config.arb_shader_objects = true;
|
||||||
|
@ -1608,11 +1623,13 @@ void GL_Init(void *(*getglfunction) (char *name))
|
||||||
qglEndList = (void*)getglcore("glEndList");
|
qglEndList = (void*)getglcore("glEndList");
|
||||||
qglCallList = (void*)getglcore("glCallList");
|
qglCallList = (void*)getglcore("glCallList");
|
||||||
|
|
||||||
|
#ifndef GL_STATIC
|
||||||
qglBindBufferARB = (void *)getglext("glBindBufferARB");
|
qglBindBufferARB = (void *)getglext("glBindBufferARB");
|
||||||
if (!qglBindBufferARB)
|
if (!qglBindBufferARB)
|
||||||
qglBindBufferARB = (void *)getglext("glBindBuffer");
|
qglBindBufferARB = (void *)getglext("glBindBuffer");
|
||||||
if (!qglBindBufferARB)
|
if (!qglBindBufferARB)
|
||||||
qglBindBufferARB = GL_BindBufferARBStub;
|
qglBindBufferARB = GL_BindBufferARBStub;
|
||||||
|
#endif
|
||||||
|
|
||||||
gl_vendor = qglGetString (GL_VENDOR);
|
gl_vendor = qglGetString (GL_VENDOR);
|
||||||
Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
|
Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
|
||||||
|
|
|
@ -440,12 +440,12 @@ void R_NetGraph (void);
|
||||||
#ifdef GL_STATIC
|
#ifdef GL_STATIC
|
||||||
//these are the functions that are valid in gles2.
|
//these are the functions that are valid in gles2.
|
||||||
//other functions should never actually be used.
|
//other functions should never actually be used.
|
||||||
#define qglActiveTexture glActiveTexture
|
#define qglActiveTextureARB glActiveTexture
|
||||||
#define qglAttachShader glAttachShader
|
#define qglAttachShader glAttachShader
|
||||||
#define qglBindAttribLocation glBindAttribLocation
|
#define qglBindAttribLocation glBindAttribLocation
|
||||||
#define qglBindBuffer glBindBuffer
|
#define qglBindBuffer glBindBuffer
|
||||||
#define qglBindFramebuffer glBindFramebuffer
|
#define qglBindFramebuffer glBindFramebuffer
|
||||||
#define qglBindRenderbuffer glBindRenderbuffer
|
#define qglBindRenderbufferEXT glBindRenderbuffer
|
||||||
#define qglBindTexture glBindTexture
|
#define qglBindTexture glBindTexture
|
||||||
#define qglBlendColor glBlendColor
|
#define qglBlendColor glBlendColor
|
||||||
#define qglBlendEquation glBlendEquation
|
#define qglBlendEquation glBlendEquation
|
||||||
|
@ -454,7 +454,7 @@ void R_NetGraph (void);
|
||||||
#define qglBlendFuncSeparate glBlendFuncSeparate
|
#define qglBlendFuncSeparate glBlendFuncSeparate
|
||||||
#define qglBufferData glBufferData
|
#define qglBufferData glBufferData
|
||||||
#define qglBufferSubData glBufferSubData
|
#define qglBufferSubData glBufferSubData
|
||||||
#define qglCheckFramebufferStatus glCheckFramebufferStatus
|
#define qglCheckFramebufferStatusEXT glCheckFramebufferStatus
|
||||||
#define qglClear glClear
|
#define qglClear glClear
|
||||||
#define qglClearColor glClearColor
|
#define qglClearColor glClearColor
|
||||||
#define qglClearDepthf glClearDepthf
|
#define qglClearDepthf glClearDepthf
|
||||||
|
@ -486,13 +486,13 @@ void R_NetGraph (void);
|
||||||
#define qglEnableVertexAttribArray glEnableVertexAttribArray
|
#define qglEnableVertexAttribArray glEnableVertexAttribArray
|
||||||
#define qglFinish glFinish
|
#define qglFinish glFinish
|
||||||
#define qglFlush glFlush
|
#define qglFlush glFlush
|
||||||
#define qglFramebufferRenderbuffer glFramebufferRenderbuffer
|
#define qglFramebufferRenderbufferEXT glFramebufferRenderbuffer
|
||||||
#define qglFramebufferTexture2D glFramebufferTexture2D
|
#define qglFramebufferTexture2D glFramebufferTexture2D
|
||||||
#define qglFrontFace glFrontFace
|
#define qglFrontFace glFrontFace
|
||||||
#define qglGenBuffers glGenBuffers
|
#define qglGenBuffers glGenBuffers
|
||||||
#define qglGenerateMipmap glGenerateMipmap
|
#define qglGenerateMipmap glGenerateMipmap
|
||||||
#define qglGenFramebuffers glGenFramebuffers
|
#define qglGenFramebuffers glGenFramebuffers
|
||||||
#define qglGenRenderbuffers glGenRenderbuffers
|
#define qglGenRenderbuffersEXT glGenRenderbuffers
|
||||||
#define qglGenTextures glGenTextures
|
#define qglGenTextures glGenTextures
|
||||||
#define qglGetActiveAttrib glGetActiveAttrib
|
#define qglGetActiveAttrib glGetActiveAttrib
|
||||||
#define qglGetActiveUniform glGetActiveUniform
|
#define qglGetActiveUniform glGetActiveUniform
|
||||||
|
@ -534,7 +534,7 @@ void R_NetGraph (void);
|
||||||
#define qglPolygonOffset glPolygonOffset
|
#define qglPolygonOffset glPolygonOffset
|
||||||
#define qglReadPixels glReadPixels
|
#define qglReadPixels glReadPixels
|
||||||
#define qglReleaseShaderCompiler glReleaseShaderCompiler
|
#define qglReleaseShaderCompiler glReleaseShaderCompiler
|
||||||
#define qglRenderbufferStorage glRenderbufferStorage
|
#define qglRenderbufferStorageEXT glRenderbufferStorage
|
||||||
#define qglSampleCoverage glSampleCoverage
|
#define qglSampleCoverage glSampleCoverage
|
||||||
#define qglScissor glScissor
|
#define qglScissor glScissor
|
||||||
#define qglShaderBinary glShaderBinary
|
#define qglShaderBinary glShaderBinary
|
||||||
|
@ -616,6 +616,14 @@ void R_NetGraph (void);
|
||||||
#define qglUniform1iARB glUniform1i
|
#define qglUniform1iARB glUniform1i
|
||||||
#define qglUniform1fARB glUniform1f
|
#define qglUniform1fARB glUniform1f
|
||||||
|
|
||||||
|
#define qglGenBuffersARB glGenBuffers
|
||||||
|
#define qglDeleteBuffersARB glDeleteBuffers
|
||||||
|
#define qglBindBufferARB glBindBuffer
|
||||||
|
#define qglBufferDataARB glBufferData
|
||||||
|
#define qglBufferSubDataARB glBufferSubData
|
||||||
|
#define qglMapBufferARB glMapBuffer
|
||||||
|
#define qglUnmapBufferARB glUnmapBuffer
|
||||||
|
|
||||||
#else
|
#else
|
||||||
extern void (APIENTRY *qglBindTexture) (GLenum target, GLuint texture);
|
extern void (APIENTRY *qglBindTexture) (GLenum target, GLuint texture);
|
||||||
extern void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
|
extern void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
|
||||||
|
@ -708,6 +716,14 @@ extern FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv;
|
||||||
extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
|
extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
|
||||||
extern FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray;
|
extern FTEPFNGLDISABLEVERTEXATTRIBARRAY qglDisableVertexAttribArray;
|
||||||
|
|
||||||
|
extern void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids);
|
||||||
|
extern void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids);
|
||||||
|
extern void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id);
|
||||||
|
extern void (APIENTRY *qglBufferDataARB)(GLenum target, GLsizei size, const void* data, GLenum usage);
|
||||||
|
extern void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data);
|
||||||
|
extern void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access);
|
||||||
|
extern GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//non-gles2 gl functions
|
//non-gles2 gl functions
|
||||||
|
@ -1045,14 +1061,6 @@ extern void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, G
|
||||||
extern void (APIENTRY *qglEnableClientState) (GLenum array);
|
extern void (APIENTRY *qglEnableClientState) (GLenum array);
|
||||||
extern void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
|
extern void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
|
||||||
|
|
||||||
extern void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids);
|
|
||||||
extern void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids);
|
|
||||||
extern void (APIENTRY *qglBindBufferARB)(GLenum target, GLuint id);
|
|
||||||
extern void (APIENTRY *qglBufferDataARB)(GLenum target, GLsizei size, const void* data, GLenum usage);
|
|
||||||
extern void (APIENTRY *qglBufferSubDataARB)(GLenum target, GLint offset, GLsizei size, void* data);
|
|
||||||
extern void *(APIENTRY *qglMapBufferARB)(GLenum target, GLenum access);
|
|
||||||
extern GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
|
|
||||||
|
|
||||||
extern void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
|
extern void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
|
||||||
extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
||||||
|
|
||||||
|
|
|
@ -17,72 +17,6 @@
|
||||||
#include <emscripten/emscripten.h>
|
#include <emscripten/emscripten.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
vfsfile_t funcs;
|
|
||||||
unsigned long offset;
|
|
||||||
unsigned long length;
|
|
||||||
char data[];
|
|
||||||
} mfile_t;
|
|
||||||
static int VFSMEM_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
|
|
||||||
{
|
|
||||||
mfile_t *f = (mfile_t*)file;
|
|
||||||
if (f->offset >= f->length)
|
|
||||||
return -1; //eof!
|
|
||||||
if (bytestoread > f->length - f->offset)
|
|
||||||
bytestoread = f->length - f->offset; //eof!
|
|
||||||
memcpy(buffer, &f->data[f->offset], bytestoread);
|
|
||||||
f->offset += bytestoread;
|
|
||||||
return bytestoread;
|
|
||||||
}
|
|
||||||
static int VFSMEM_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static qboolean VFSMEM_Seek (struct vfsfile_s *file, unsigned long pos)
|
|
||||||
{
|
|
||||||
mfile_t *f = (mfile_t*)file;
|
|
||||||
f->offset = pos;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
static unsigned long VFSMEM_Tell (struct vfsfile_s *file)
|
|
||||||
{
|
|
||||||
mfile_t *f = (mfile_t*)file;
|
|
||||||
return f->offset;
|
|
||||||
}
|
|
||||||
static unsigned long VFSMEM_GetSize (struct vfsfile_s *file)
|
|
||||||
{
|
|
||||||
mfile_t *f = (mfile_t*)file;
|
|
||||||
return f->length;
|
|
||||||
}
|
|
||||||
static void VFSMEM_Close(vfsfile_t *file)
|
|
||||||
{
|
|
||||||
free(file);
|
|
||||||
}
|
|
||||||
static void VFSMEM_Flush(struct vfsfile_s *file)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static vfsfile_t *VFSMEM_File(void *data, unsigned int datasize)
|
|
||||||
{
|
|
||||||
/*create a file which is already unlinked*/
|
|
||||||
mfile_t *f;
|
|
||||||
f = malloc(sizeof(*f) + datasize);
|
|
||||||
if (!f)
|
|
||||||
return NULL;
|
|
||||||
f->funcs.ReadBytes = VFSMEM_ReadBytes;
|
|
||||||
f->funcs.WriteBytes = VFSMEM_WriteBytes;
|
|
||||||
f->funcs.Seek = VFSMEM_Seek;
|
|
||||||
f->funcs.Tell = VFSMEM_Tell;
|
|
||||||
f->funcs.GetLen = VFSMEM_GetSize;
|
|
||||||
f->funcs.Close = VFSMEM_Close;
|
|
||||||
f->funcs.Flush = VFSMEM_Flush;
|
|
||||||
f->offset = 0;
|
|
||||||
f->length = datasize;
|
|
||||||
memcpy(f->data, data, datasize);
|
|
||||||
|
|
||||||
return &f->funcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DL_Abort(struct dl_download *dl)
|
static void DL_Abort(struct dl_download *dl)
|
||||||
{
|
{
|
||||||
dl->ctx = NULL;
|
dl->ctx = NULL;
|
||||||
|
@ -102,20 +36,23 @@ static void DL_OnLoad(void *c, void *data, int datasize)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//emscripten does not close the file. plus we seem to end up with infinite loops.
|
//emscripten does not close the file. plus we seem to end up with infinite loops.
|
||||||
dl->file = VFSMEM_File(data, datasize);
|
dl->file = FS_OpenTemp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dl->file)
|
if (dl->file)
|
||||||
{
|
{
|
||||||
VFS_WRITE(dl->file, data, datasize);
|
VFS_WRITE(dl->file, data, datasize);
|
||||||
|
VFS_SEEK(dl->file, 0);
|
||||||
|
dl->status = DL_FINISHED;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
dl->status = DL_FAILED;
|
||||||
|
|
||||||
dl->replycode = 200;
|
dl->replycode = 200;
|
||||||
#if !MYJS
|
#if !MYJS
|
||||||
dl->completed += datasize;
|
dl->completed += datasize;
|
||||||
#endif
|
#endif
|
||||||
dl->status = DL_FINISHED;
|
|
||||||
}
|
}
|
||||||
#if MYJS
|
#if MYJS
|
||||||
static void DL_OnError(void *c, int ecode)
|
static void DL_OnError(void *c, int ecode)
|
||||||
|
@ -124,13 +61,13 @@ static void DL_OnError(void *c)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct dl_download *dl = c;
|
struct dl_download *dl = c;
|
||||||
Con_Printf("download %p: error\n", dl);
|
|
||||||
|
|
||||||
#if MYJS
|
#if MYJS
|
||||||
dl->replycode = ecode;
|
dl->replycode = ecode;
|
||||||
#else
|
#else
|
||||||
dl->replycode = 404; //we don't actually know. should we not do this?
|
dl->replycode = 404; //we don't actually know. should we not do this?
|
||||||
#endif
|
#endif
|
||||||
|
Con_Printf("download %p: error %i\n", dl, dl->replycode);
|
||||||
dl->status = DL_FAILED;
|
dl->status = DL_FAILED;
|
||||||
}
|
}
|
||||||
static void DL_OnProgress(void *c, int position, int totalsize)
|
static void DL_OnProgress(void *c, int position, int totalsize)
|
||||||
|
|
|
@ -1106,6 +1106,9 @@ static int PDECL qclib_null_printf(const char *s, ...)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#ifdef FTE_TARGET_WEB
|
||||||
|
#define printf NULL //should be some null wrapper instead
|
||||||
|
#endif
|
||||||
|
|
||||||
//defs incase following structure is not passed.
|
//defs incase following structure is not passed.
|
||||||
struct edict_s *safesv_edicts;
|
struct edict_s *safesv_edicts;
|
||||||
|
|
|
@ -1686,11 +1686,13 @@ void SV_AcceptMessage(int protocol)
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
static void SV_CheckRecentCrashes(client_t *tellclient)
|
static void SV_CheckRecentCrashes(client_t *tellclient)
|
||||||
{
|
{
|
||||||
|
#ifndef FTE_TARGET_WEB
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (-1 != stat("crash.log", &sb))
|
if (-1 != stat("crash.log", &sb))
|
||||||
{
|
{
|
||||||
SV_ClientPrintf(tellclient, PRINT_HIGH, "\1WARNING: crash.log exists, dated %s\n", ctime(&sb.st_mtime));
|
SV_ClientPrintf(tellclient, PRINT_HIGH, "\1WARNING: crash.log exists, dated %s\n", ctime(&sb.st_mtime));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void SV_CheckRecentCrashes(client_t *tellclient)
|
static void SV_CheckRecentCrashes(client_t *tellclient)
|
||||||
|
|
|
@ -651,6 +651,9 @@ int Rank_Enumerate (unsigned int first, unsigned int last, void (*callback) (con
|
||||||
|
|
||||||
void Rank_RankingList_f (void)
|
void Rank_RankingList_f (void)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
Con_Printf("Fixme\n");
|
||||||
|
#else
|
||||||
rankinfo_t ri;
|
rankinfo_t ri;
|
||||||
int id;
|
int id;
|
||||||
int num;
|
int num;
|
||||||
|
@ -680,6 +683,7 @@ void Rank_RankingList_f (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rank_Remove_f (void)
|
void Rank_Remove_f (void)
|
||||||
|
|
272
engine/web/fs_web.c
Normal file
272
engine/web/fs_web.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#include "quakedef.h"
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
|
#if defined(FTE_TARGET_WEB)
|
||||||
|
#include "ftejslib.h"
|
||||||
|
|
||||||
|
#if !defined(_WIN32) || defined(_SDL)
|
||||||
|
#define FSWEB_OpenPath VFSOS_OpenPath
|
||||||
|
#endif
|
||||||
|
#define FSWEB_OpenTemp FS_OpenTemp
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
searchpathfuncs_t pub;
|
||||||
|
int depth;
|
||||||
|
void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle);
|
||||||
|
char rootpath[1];
|
||||||
|
} webpath_t;
|
||||||
|
typedef struct {
|
||||||
|
vfsfile_t funcs;
|
||||||
|
int offset;
|
||||||
|
int handle;
|
||||||
|
} vfswebfile_t;
|
||||||
|
static int QDECL VFSWEB_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
int len = emscriptenfte_buf_read(intfile->handle, intfile->offset, buffer, bytestoread);
|
||||||
|
intfile->offset += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
static int QDECL VFSWEB_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
int len = emscriptenfte_buf_write(intfile->handle, intfile->offset, buffer, bytestoread);
|
||||||
|
intfile->offset += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
static qboolean QDECL VFSWEB_Seek (struct vfsfile_s *file, unsigned long pos)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
if (pos < 0)
|
||||||
|
return 0;
|
||||||
|
intfile->offset = pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static unsigned long QDECL VFSWEB_Tell (struct vfsfile_s *file)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
return intfile->offset;
|
||||||
|
}
|
||||||
|
static void QDECL VFSWEB_Flush(struct vfsfile_s *file)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
}
|
||||||
|
static unsigned long QDECL VFSWEB_GetSize (struct vfsfile_s *file)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
unsigned long l;
|
||||||
|
l = emscriptenfte_buf_getsize(intfile->handle);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
static void QDECL VFSWEB_Close(vfsfile_t *file)
|
||||||
|
{
|
||||||
|
vfswebfile_t *intfile = (vfswebfile_t*)file;
|
||||||
|
emscriptenfte_buf_release(intfile->handle);
|
||||||
|
Z_Free(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfsfile_t *FSWEB_OpenTemp(void)
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
vfswebfile_t *file;
|
||||||
|
|
||||||
|
f = emscriptenfte_buf_create();
|
||||||
|
if (f == -1)
|
||||||
|
{
|
||||||
|
Con_Printf("FSWEB_OpenTemp failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = Z_Malloc(sizeof(vfswebfile_t));
|
||||||
|
file->funcs.Close = VFSWEB_Close;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
Q_strncpyz(file->funcs.dbgname, "FSWEB_OpenTemp", sizeof(file->funcs.dbgname));
|
||||||
|
#endif
|
||||||
|
file->funcs.ReadBytes = VFSWEB_ReadBytes;
|
||||||
|
file->funcs.WriteBytes = VFSWEB_WriteBytes;
|
||||||
|
file->funcs.Seek = VFSWEB_Seek;
|
||||||
|
file->funcs.Tell = VFSWEB_Tell;
|
||||||
|
file->funcs.GetLen = VFSWEB_GetSize;
|
||||||
|
file->funcs.Flush = VFSWEB_Flush;
|
||||||
|
file->handle = f;
|
||||||
|
|
||||||
|
return &file->funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfsfile_t *VFSWEB_Open(const char *osname, const char *mode, qboolean *needsflush)
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
vfswebfile_t *file;
|
||||||
|
//qboolean read = !!strchr(mode, 'r');
|
||||||
|
qboolean write = !!strchr(mode, 'w');
|
||||||
|
qboolean append = !!strchr(mode, 'a');
|
||||||
|
|
||||||
|
if (needsflush)
|
||||||
|
*needsflush = false;
|
||||||
|
f = emscriptenfte_buf_open(osname, write||append);
|
||||||
|
if (f == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (write || append)
|
||||||
|
{
|
||||||
|
if (needsflush)
|
||||||
|
*needsflush = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = Z_Malloc(sizeof(vfswebfile_t));
|
||||||
|
#ifdef _DEBUG
|
||||||
|
Q_strncpyz(file->funcs.dbgname, osname, sizeof(file->funcs.dbgname));
|
||||||
|
#endif
|
||||||
|
file->funcs.ReadBytes = VFSWEB_ReadBytes;
|
||||||
|
file->funcs.WriteBytes = VFSWEB_WriteBytes;
|
||||||
|
file->funcs.Seek = VFSWEB_Seek;
|
||||||
|
file->funcs.Tell = VFSWEB_Tell;
|
||||||
|
file->funcs.GetLen = VFSWEB_GetSize;
|
||||||
|
file->funcs.Close = VFSWEB_Close;
|
||||||
|
file->funcs.Flush = VFSWEB_Flush;
|
||||||
|
file->handle = f;
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
file->offset = VFSWEB_GetSize(&file->funcs);
|
||||||
|
|
||||||
|
return &file->funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
vfsfile_t *VFSOS_Open(const char *osname, const char *mode)
|
||||||
|
{
|
||||||
|
vfsfile_t *f;
|
||||||
|
qboolean needsflush;
|
||||||
|
f = VFSWEB_Open(osname, mode, &needsflush);
|
||||||
|
if (needsflush)
|
||||||
|
FS_FlushFSHashReally();
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vfsfile_t *QDECL FSWEB_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const char *mode)
|
||||||
|
{
|
||||||
|
vfsfile_t *f;
|
||||||
|
webpath_t *sp = (void*)handle;
|
||||||
|
qboolean needsflush;
|
||||||
|
|
||||||
|
f = VFSWEB_Open(loc->rawname, mode, &needsflush);
|
||||||
|
if (needsflush && sp->AddFileHash)
|
||||||
|
sp->AddFileHash(sp->depth, loc->rawname, NULL, sp);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void QDECL FSWEB_ClosePath(searchpathfuncs_t *handle)
|
||||||
|
{
|
||||||
|
Z_Free(handle);
|
||||||
|
}
|
||||||
|
static qboolean QDECL FSWEB_PollChanges(searchpathfuncs_t *handle)
|
||||||
|
{
|
||||||
|
// webpath_t *np = handle;
|
||||||
|
return true; //can't verify that or not, so we have to assume the worst
|
||||||
|
}
|
||||||
|
static int QDECL FSWEB_RebuildFSHash(const char *filename, int filesize, void *data, searchpathfuncs_t *spath)
|
||||||
|
{
|
||||||
|
webpath_t *sp = (void*)spath;
|
||||||
|
void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) = data;
|
||||||
|
if (filename[strlen(filename)-1] == '/')
|
||||||
|
{ //this is actually a directory
|
||||||
|
|
||||||
|
char childpath[256];
|
||||||
|
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
|
||||||
|
Sys_EnumerateFiles(sp->rootpath, childpath, FSWEB_RebuildFSHash, data, spath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AddFileHash(sp->depth, filename, NULL, sp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static void QDECL FSWEB_BuildHash(searchpathfuncs_t *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle))
|
||||||
|
{
|
||||||
|
webpath_t *sp = (void*)handle;
|
||||||
|
sp->depth = depth;
|
||||||
|
sp->AddFileHash = AddFileHash;
|
||||||
|
Sys_EnumerateFiles(sp->rootpath, "*", FSWEB_RebuildFSHash, AddFileHash, handle);
|
||||||
|
}
|
||||||
|
static qboolean QDECL FSWEB_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
|
||||||
|
{
|
||||||
|
webpath_t *sp = (void*)handle;
|
||||||
|
int len;
|
||||||
|
char netpath[MAX_OSPATH];
|
||||||
|
|
||||||
|
if (hashedresult && (void *)hashedresult != handle)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!static_registered)
|
||||||
|
{ // if not a registered version, don't ever go beyond base
|
||||||
|
if ( strchr (filename, '/') || strchr (filename,'\\'))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// check a file in the directory tree
|
||||||
|
snprintf (netpath, sizeof(netpath)-1, "%s/%s", sp->rootpath, filename);
|
||||||
|
|
||||||
|
{
|
||||||
|
vfsfile_t *f = VFSWEB_Open(netpath, "rb", NULL);
|
||||||
|
if (!f)
|
||||||
|
return false;
|
||||||
|
len = VFS_GETLEN(f);
|
||||||
|
VFS_CLOSE(f);
|
||||||
|
}
|
||||||
|
if (loc)
|
||||||
|
{
|
||||||
|
loc->len = len;
|
||||||
|
loc->offset = 0;
|
||||||
|
loc->index = 0;
|
||||||
|
Q_strncpyz(loc->rawname, netpath, sizeof(loc->rawname));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static void QDECL FSWEB_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, char *buffer)
|
||||||
|
{
|
||||||
|
vfsfile_t *f;
|
||||||
|
size_t result;
|
||||||
|
|
||||||
|
f = VFSWEB_Open(loc->rawname, "rb", NULL);
|
||||||
|
if (!f) //err...
|
||||||
|
return;
|
||||||
|
VFS_SEEK(f, loc->offset);
|
||||||
|
result = VFS_READ(f, buffer, loc->len); // do soemthing with result
|
||||||
|
|
||||||
|
if (result != loc->len)
|
||||||
|
Con_Printf("FSWEB_ReadFile() fread: Filename: %s, expected %i, result was %u \n",loc->rawname,loc->len,(unsigned int)result);
|
||||||
|
|
||||||
|
VFS_CLOSE(f);
|
||||||
|
}
|
||||||
|
static int QDECL FSWEB_EnumerateFiles (searchpathfuncs_t *handle, const char *match, int (QDECL *func)(const char *, int, void *, searchpathfuncs_t *spath), void *parm)
|
||||||
|
{
|
||||||
|
webpath_t *sp = (webpath_t*)handle;
|
||||||
|
return Sys_EnumerateFiles(sp->rootpath, match, func, parm, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
searchpathfuncs_t *QDECL FSWEB_OpenPath(vfsfile_t *mustbenull, const char *desc)
|
||||||
|
{
|
||||||
|
webpath_t *np;
|
||||||
|
int dlen = strlen(desc);
|
||||||
|
if (mustbenull)
|
||||||
|
return NULL;
|
||||||
|
np = Z_Malloc(sizeof(*np) + dlen);
|
||||||
|
if (np)
|
||||||
|
{
|
||||||
|
np->depth = 0;
|
||||||
|
memcpy(np->rootpath, desc, dlen+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
np->pub.fsver = FSVER;
|
||||||
|
np->pub.ClosePath = FSWEB_ClosePath;
|
||||||
|
np->pub.BuildHash = FSWEB_BuildHash;
|
||||||
|
np->pub.FindFile = FSWEB_FLocate;
|
||||||
|
np->pub.ReadFile = FSWEB_ReadFile;
|
||||||
|
np->pub.EnumerateFiles = FSWEB_EnumerateFiles;
|
||||||
|
np->pub.OpenVFS = FSWEB_OpenVFS;
|
||||||
|
np->pub.PollChanges = FSWEB_PollChanges;
|
||||||
|
return &np->pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,2 +1,32 @@
|
||||||
void emscriptenfte_async_wget_data2(const char *url, void *ctx, void (*onload)(void*ctx,void*buf,int sz), void (*onerror)(void*ctx,int code), void (*onprogress)(void*ctx,int prog,int total));
|
void emscriptenfte_async_wget_data2(const char *url, void *ctx, void (*onload)(void*ctx,void*buf,int sz), void (*onerror)(void*ctx,int code), void (*onprogress)(void*ctx,int prog,int total));
|
||||||
|
|
||||||
|
//filesystem buffers are implemented in javascript so that we are not bound by power-of-two heap limitations quite so much.
|
||||||
|
//also, we can't use emscripten because it reserves 16m file handles or something.
|
||||||
|
int emscriptenfte_buf_create(void);
|
||||||
|
int emscriptenfte_buf_open(const char *name, int createifneeded);
|
||||||
|
int emscriptenfte_buf_rename(const char *oldname, const char *newname);
|
||||||
|
int emscriptenfte_buf_delete(const char *fname);
|
||||||
|
void emscriptenfte_buf_release(int handle);
|
||||||
|
unsigned int emscriptenfte_buf_getsize(int handle);
|
||||||
|
int emscriptenfte_buf_read(int handle, int offset, void *data, int len);
|
||||||
|
int emscriptenfte_buf_write(int handle, int offset, const void *data, int len);
|
||||||
|
|
||||||
|
//websocket is implemented in javascript because there is no usable C api (emscripten's javascript implementation is shite).
|
||||||
|
int emscriptenfte_ws_connect(const char *url);
|
||||||
|
void emscriptenfte_ws_close(int sockid);
|
||||||
|
int emscriptenfte_ws_cansend(int sockid, int extra, int maxpending);
|
||||||
|
int emscriptenfte_ws_send(int sockid, const void *data, int len);
|
||||||
|
int emscriptenfte_ws_recv(int sockid, void *data, int len);
|
||||||
|
|
||||||
|
void Sys_Print(const char *msg);
|
||||||
|
unsigned long emscriptenfte_ticks_ms(void);
|
||||||
|
|
||||||
|
int emscriptenfte_setupcanvas(
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
void(*Resized)(int newwidth, int newheight),
|
||||||
|
void(*Mouse)(int devid,int abs,float x,float y,float z,float size),
|
||||||
|
void(*Button)(int devid, int down, int mbutton),
|
||||||
|
void(*Keyboard)(int devid, int down, int keycode, int unicode)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,57 +1,335 @@
|
||||||
|
|
||||||
mergeInto(LibraryManager.library,
|
mergeInto(LibraryManager.library,
|
||||||
{
|
{
|
||||||
$FTESockets__deps: [],
|
//generic handles array
|
||||||
$FTESockets: {
|
//yeah, I hope you don't use-after-free. hopefully that sort of thing will be detected on systems with easier non-mangled debuggers.
|
||||||
socks: []
|
$FTEH__deps: [],
|
||||||
|
$FTEH: {
|
||||||
|
h: [],
|
||||||
|
f: {}
|
||||||
},
|
},
|
||||||
emscriptenfte_ws_connect__deps: ['$FTESockets'],
|
|
||||||
|
$FTEC:
|
||||||
|
{
|
||||||
|
w: -1,
|
||||||
|
h: -1,
|
||||||
|
donecb:0,
|
||||||
|
evcb: {
|
||||||
|
resize:0,
|
||||||
|
mouse:0,
|
||||||
|
key:0,
|
||||||
|
},
|
||||||
|
|
||||||
|
handleevent : function(event)
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case 'resize':
|
||||||
|
if (FTEC.evcb.resize != 0)
|
||||||
|
Runtime.dynCall('vii', FTEC.evcb.resize, [Module['canvas'].width, Module['canvas'].height]);
|
||||||
|
break;
|
||||||
|
case 'mousemove':
|
||||||
|
if (FTEC.evcb.mouse != 0)
|
||||||
|
{
|
||||||
|
if (Browser.pointerLock)
|
||||||
|
{
|
||||||
|
if (typeof event.movementX === 'undefined')
|
||||||
|
{
|
||||||
|
event.movementX = event.mozMovementX;
|
||||||
|
event.movementY = event.mozMovementY;
|
||||||
|
}
|
||||||
|
if (typeof event.movementX === 'undefined')
|
||||||
|
{
|
||||||
|
event.movementX = event.webkitMovementX;
|
||||||
|
event.movementY = event.webkitMovementY;
|
||||||
|
}
|
||||||
|
Runtime.dynCall('viiffff', FTEC.evcb.mouse, [0, false, event.movementX, event.movementY, 0, 0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Runtime.dynCall('viiffff', FTEC.evcb.mouse, [0, true, event.pageX, event.pageY, 0, 0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'mousedown':
|
||||||
|
case 'mouseup':
|
||||||
|
Browser.requestFullScreen(true, true);
|
||||||
|
Module['canvas'].requestPointerLock();
|
||||||
|
if (FTEC.evcb.button != 0)
|
||||||
|
{
|
||||||
|
Runtime.dynCall('viii', FTEC.evcb.button, [0, event.type=='mousedown', event.button]);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'mousewheel':
|
||||||
|
case 'wheel':
|
||||||
|
if (FTEC.evcb.button != 0)
|
||||||
|
{
|
||||||
|
Runtime.dynCall('viii', FTEC.evcb.button, [0, 3, event.deltaY]);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'mouseout':
|
||||||
|
if (FTEC.evcb.button != 0)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
|
Runtime.dynCall('viii', FTEC.evcb.button, [0, false, i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'keypress':
|
||||||
|
if (FTEC.evcb.key != 0)
|
||||||
|
{
|
||||||
|
Runtime.dynCall('viiii', FTEC.evcb.key, [0, 1, 0, event.charCode]);
|
||||||
|
Runtime.dynCall('viiii', FTEC.evcb.key, [0, 0, 0, event.charCode]);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'keydown':
|
||||||
|
case 'keyup':
|
||||||
|
//122 is 'toggle fullscreen'.
|
||||||
|
//we don't steal that because its impossible to leave it again once used.
|
||||||
|
if (FTEC.evcb.key != 0 && event.keyCode != 122)
|
||||||
|
{
|
||||||
|
Runtime.dynCall('viiii', FTEC.evcb.key, [0, event.type=='keydown', event.keyCode, 0]);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'keydown':
|
||||||
|
default:
|
||||||
|
console.log(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emscriptenfte_setupcanvas__deps: ['$FTEC', '$Browser'],
|
||||||
|
emscriptenfte_setupcanvas : function(nw,nh,evresz,evm,evb,evk)
|
||||||
|
{
|
||||||
|
FTEC.evcb.resize = evresz;
|
||||||
|
FTEC.evcb.mouse = evm;
|
||||||
|
FTEC.evcb.button = evb;
|
||||||
|
FTEC.evcb.key = evk;
|
||||||
|
if (!FTEC.donecb)
|
||||||
|
{
|
||||||
|
FTEC.donecb = 1;
|
||||||
|
['mousedown', 'mouseup', 'mousemove', 'wheel', 'mousewheel', 'mouseout', 'keydown', 'keyup'].forEach(function(event)
|
||||||
|
{
|
||||||
|
Module['canvas'].addEventListener(event, FTEC.handleevent, true);
|
||||||
|
});
|
||||||
|
['keydown', 'keyup', 'keypress'].forEach(function(event)
|
||||||
|
{
|
||||||
|
document.addEventListener(event, FTEC.handleevent, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
Browser.resizeListeners.push(function(w, h) {
|
||||||
|
FTEC.handleevent({
|
||||||
|
type: 'resize',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var ctx = Browser.createContext(Module['canvas'], true, true);
|
||||||
|
if (!ctx)
|
||||||
|
return 0;
|
||||||
|
Browser.setCanvasSize(nw, nh, false);
|
||||||
|
|
||||||
|
window.onresize = function()
|
||||||
|
{
|
||||||
|
//emscripten's browser library will revert sizes wrongly or something when we're fullscreen, so make sure that doesn't happen.
|
||||||
|
if (Browser.isFullScreen)
|
||||||
|
{
|
||||||
|
Browser.windowedWidth = window.innerWidth;
|
||||||
|
Browser.windowedHeight = window.innerHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Browser.setCanvasSize(window.innerWidth, window.innerHeight, false);
|
||||||
|
};
|
||||||
|
window.onresize();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
Sys_Print : function(msg)
|
||||||
|
{
|
||||||
|
console.log(Pointer_stringify(msg));
|
||||||
|
},
|
||||||
|
emscriptenfte_ticks_ms : function()
|
||||||
|
{
|
||||||
|
return Date.now();
|
||||||
|
},
|
||||||
|
|
||||||
|
emscriptenfte_handle_alloc__deps : ['$FTEH'],
|
||||||
|
emscriptenfte_handle_alloc : function(h)
|
||||||
|
{
|
||||||
|
for (var i = 0; FTEH.h.length; i+=1)
|
||||||
|
{
|
||||||
|
if (FTEH.h[i] == null)
|
||||||
|
{
|
||||||
|
FTEH.h[i] = h;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = FTEH.h.length;
|
||||||
|
FTEH.h[i] = h;
|
||||||
|
return i;
|
||||||
|
},
|
||||||
|
|
||||||
|
//temp files
|
||||||
|
emscriptenfte_buf_create__deps : ['emscriptenfte_handle_alloc'],
|
||||||
|
emscriptenfte_buf_create : function()
|
||||||
|
{
|
||||||
|
var b = {h:-1, r:1, l:0,m:4096,d:new Uint8Array(4096), n:null};
|
||||||
|
b.h = _emscriptenfte_handle_alloc(b);
|
||||||
|
return b.h;
|
||||||
|
},
|
||||||
|
//temp files
|
||||||
|
emscriptenfte_buf_open__deps : ['emscriptenfte_buf_create'],
|
||||||
|
emscriptenfte_buf_open : function(name, createifneeded)
|
||||||
|
{
|
||||||
|
name = Pointer_stringify(name);
|
||||||
|
var f = FTEH.f[name];
|
||||||
|
var r = -1;
|
||||||
|
if (f == null)
|
||||||
|
{
|
||||||
|
if (createifneeded)
|
||||||
|
r = _emscriptenfte_buf_create();
|
||||||
|
if (r != -1)
|
||||||
|
{
|
||||||
|
f = FTEH.h[r];
|
||||||
|
f.r+=1;
|
||||||
|
f.n = name;
|
||||||
|
FTEH.f[name] = f;
|
||||||
|
if (FTEH.f[name] != f || f.n != name)
|
||||||
|
console.log('error creating file '+name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f.r+=1;
|
||||||
|
r = f.h;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_rename : function(oldname, newname)
|
||||||
|
{
|
||||||
|
oldname = Pointer_stringify(oldname);
|
||||||
|
newname = Pointer_stringify(newname);
|
||||||
|
var f = FTEH.f[oldname];
|
||||||
|
if (f == null)
|
||||||
|
return 0;
|
||||||
|
if (FTEH.f[newname] != null)
|
||||||
|
return 0;
|
||||||
|
FTEH.f[newname] = f;
|
||||||
|
delete FTEH.f[oldname];
|
||||||
|
f.n = newname;
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_delete : function(name)
|
||||||
|
{
|
||||||
|
name = Pointer_stringify(name);
|
||||||
|
var f = FTEH.f[name];
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
delete FTEH.f[name];
|
||||||
|
f.n = null;
|
||||||
|
emscriptenfte_buf_release(f.h);
|
||||||
|
console.log('deleted '+name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_release : function(handle)
|
||||||
|
{
|
||||||
|
var b = FTEH.h[handle];
|
||||||
|
if (b == null)
|
||||||
|
{
|
||||||
|
Module.printError('emscriptenfte_buf_release with invalid handle');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
b.r -= 1;
|
||||||
|
if (b.r == 0)
|
||||||
|
{
|
||||||
|
if (b.n != null)
|
||||||
|
delete FTEH.f[b.n];
|
||||||
|
delete FTEH.h[handle];
|
||||||
|
b.d = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_getsize : function(handle)
|
||||||
|
{
|
||||||
|
var b = FTEH.h[handle];
|
||||||
|
return b.l;
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_read : function(handle, offset, data, len)
|
||||||
|
{
|
||||||
|
var b = FTEH.h[handle];
|
||||||
|
if (offset+len > b.l) //clamp the read
|
||||||
|
len = b.l - offset;
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
if (offset+len >= b.l)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
HEAPU8.set(b.d.subarray(offset, offset+len), data);
|
||||||
|
return len;
|
||||||
|
},
|
||||||
|
emscriptenfte_buf_write : function(handle, offset, data, len)
|
||||||
|
{
|
||||||
|
var b = FTEH.h[handle];
|
||||||
|
if (offset+len > b.m)
|
||||||
|
{ //extend it if needed.
|
||||||
|
b.m = offset + len + 4095;
|
||||||
|
b.m = b.m & ~4095;
|
||||||
|
var nd = new Uint8Array(b.m);
|
||||||
|
nd.set(b.d, 0);
|
||||||
|
b.d = nd;
|
||||||
|
}
|
||||||
|
if (len < 0)
|
||||||
|
len = 0;
|
||||||
|
console.log('deleted '+name);
|
||||||
|
b.d.set(HEAPU8.subarray(data, data+len), offset);
|
||||||
|
if (offset + len > b.l)
|
||||||
|
b.l = offset + len;
|
||||||
|
return len;
|
||||||
|
},
|
||||||
|
|
||||||
|
emscriptenfte_ws_connect__deps: ['emscriptenfte_handle_alloc'],
|
||||||
emscriptenfte_ws_connect : function(url)
|
emscriptenfte_ws_connect : function(url)
|
||||||
{
|
{
|
||||||
var _url = Pointer_stringify(url);
|
var _url = Pointer_stringify(url);
|
||||||
var s = {ws:null, inq:[], err:0};
|
var s = {ws:null, inq:[], err:0};
|
||||||
for (var i = 0; ; i+=1)
|
s.ws = new WebSocket(_url, 'binary');
|
||||||
{
|
if (!s.ws)
|
||||||
if (!FTESockets.socks[i])
|
return -1;
|
||||||
|
s.ws.onerror = function(event) {s.err = 1;};
|
||||||
|
s.ws.onclose = function(event) {s.err = 1;};
|
||||||
|
// s.ws.onopen = function(event) {};
|
||||||
|
s.ws.onmessage = function(event)
|
||||||
{
|
{
|
||||||
s.ws = new WebSocket(_url, 'binary');
|
assert(typeof event.data !== 'string' && event.data.byteLength);
|
||||||
if (!s.ws)
|
s.inq.push(new Uint8Array(event.data));
|
||||||
return -1;
|
};
|
||||||
FTESockets.socks[i] = s;
|
|
||||||
s.ws.onerror = function(event) {s.err = 1;};
|
return _emscriptenfte_handle_alloc(s);
|
||||||
s.ws.onclose = function(event) {s.err = 1;};
|
|
||||||
// s.ws.onopen = function(event) {};
|
|
||||||
s.ws.onmessage = function(event)
|
|
||||||
{
|
|
||||||
assert(typeof event.data !== 'string' && event.data.byteLength);
|
|
||||||
s.inq.push(new Uint8Array(event.data));
|
|
||||||
};
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
},
|
||||||
emscriptenfte_ws_close : function(sockid)
|
emscriptenfte_ws_close : function(sockid)
|
||||||
{
|
{
|
||||||
var s = FTESockets.socks[sockid];
|
var s = FTEH.h[sockid];
|
||||||
if (!s)
|
if (!s)
|
||||||
return -1;
|
return -1;
|
||||||
s.ws.close();
|
s.ws.close();
|
||||||
s.ws = null; //make sure to avoid circular references
|
s.ws = null; //make sure to avoid circular references
|
||||||
FTESockets.socks[sockid] = null; //socked is no longer accessible.
|
delete FTEH.h[sockid]; //socked is no longer accessible.
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
//separate call allows for more sane flood control when fragmentation is involved.
|
//separate call allows for more sane flood control when fragmentation is involved.
|
||||||
emscriptenfte_ws_cansend : function(sockid, extra, maxpending)
|
emscriptenfte_ws_cansend : function(sockid, extra, maxpending)
|
||||||
{
|
{
|
||||||
var s = FTESockets.socks[sockid];
|
var s = FTEH.h[sockid];
|
||||||
if (!s)
|
if (!s)
|
||||||
return 1; //go on punk, make my day.
|
return 1; //go on punk, make my day.
|
||||||
return ((s.ws.bufferedAmount+extra) < maxpending);
|
return ((s.ws.bufferedAmount+extra) < maxpending);
|
||||||
},
|
},
|
||||||
emscriptenfte_ws_send : function(sockid, data, len)
|
emscriptenfte_ws_send : function(sockid, data, len)
|
||||||
{
|
{
|
||||||
var s = FTESockets.socks[sockid];
|
var s = FTEH.h[sockid];
|
||||||
if (!s)
|
if (!s)
|
||||||
return -1;
|
return -1;
|
||||||
s.s.send(HEAPU8.subarray(data, data+len).buffer);
|
s.s.send(HEAPU8.subarray(data, data+len).buffer);
|
||||||
|
@ -59,7 +337,7 @@ mergeInto(LibraryManager.library,
|
||||||
},
|
},
|
||||||
emscriptenfte_ws_recv : function(sockid, data, len)
|
emscriptenfte_ws_recv : function(sockid, data, len)
|
||||||
{
|
{
|
||||||
var s = FTESockets.socks[sockid];
|
var s = FTEH.h[sockid];
|
||||||
if (!s)
|
if (!s)
|
||||||
return -1;
|
return -1;
|
||||||
var inp = s.inq.shift();
|
var inp = s.inq.shift();
|
||||||
|
@ -80,13 +358,14 @@ mergeInto(LibraryManager.library,
|
||||||
emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress)
|
emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress)
|
||||||
{
|
{
|
||||||
var _url = Pointer_stringify(url);
|
var _url = Pointer_stringify(url);
|
||||||
|
console.log("Attempting download of " + _url);
|
||||||
var http = new XMLHttpRequest();
|
var http = new XMLHttpRequest();
|
||||||
http.open('GET', _url, true);
|
http.open('GET', _url, true);
|
||||||
http.responseType = 'arraybuffer';
|
http.responseType = 'arraybuffer';
|
||||||
|
|
||||||
http.onload = function(e)
|
http.onload = function(e)
|
||||||
{
|
{
|
||||||
|
console.log("onload: " + _url + " status " + http.status);
|
||||||
if (http.status == 200)
|
if (http.status == 200)
|
||||||
{
|
{
|
||||||
var bar = new Uint8Array(http.response);
|
var bar = new Uint8Array(http.response);
|
||||||
|
@ -104,6 +383,7 @@ mergeInto(LibraryManager.library,
|
||||||
|
|
||||||
http.onerror = function(e)
|
http.onerror = function(e)
|
||||||
{
|
{
|
||||||
|
console.log("onerror: " + _url + " status " + http.status);
|
||||||
if (onerror)
|
if (onerror)
|
||||||
Runtime.dynCall('vii', onerror, [ctx, http.status]);
|
Runtime.dynCall('vii', onerror, [ctx, http.status]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
<title>FTE QuakeWorld</title>
|
<title>FTE QuakeWorld</title>
|
||||||
<style>
|
<style>
|
||||||
body { background-color:#000000; color:#808080; }
|
body { background-color:#000000; color:#808080; height:100%;width:100%;margin:0;padding:0;}
|
||||||
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
|
||||||
div.emscripten { text-align: center; }
|
div.emscripten { text-align: center; padding:0; margin: 0;}
|
||||||
div.emscripten_border { border: 1px solid black; }
|
div.emscripten_border { padding:0; margin: 0; }
|
||||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||||
canvas.emscripten { border: 0px none; }
|
canvas.emscripten { border: 0px none; width:100%; height:100%; padding:0; margin: 0;}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -21,14 +21,14 @@
|
||||||
<div class="emscripten_border">
|
<div class="emscripten_border">
|
||||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<div class="emscripten">
|
<!-- <div class="emscripten">
|
||||||
<input type="checkbox" id="resize">Resize canvas
|
<input type="checkbox" id="resize">Resize canvas
|
||||||
<input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer
|
<input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer
|
||||||
|
|
||||||
<input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
|
<input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
|
||||||
document.getElementById('resize').checked)">
|
document.getElementById('resize').checked)">
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
// connect to canvas
|
// connect to canvas
|
||||||
var Module = {
|
var Module = {
|
||||||
|
|
214
engine/web/gl_vidweb.c
Normal file
214
engine/web/gl_vidweb.c
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
#include "quakedef.h"
|
||||||
|
#include "glquake.h"
|
||||||
|
#include "web/ftejslib.h"
|
||||||
|
|
||||||
|
extern cvar_t vid_hardwaregamma;
|
||||||
|
extern cvar_t gl_lateswap;
|
||||||
|
extern int gammaworks;
|
||||||
|
|
||||||
|
extern qboolean vid_isfullscreen;
|
||||||
|
|
||||||
|
qboolean ActiveApp;
|
||||||
|
qboolean mouseactive;
|
||||||
|
extern qboolean mouseusedforgui;
|
||||||
|
|
||||||
|
|
||||||
|
static void *GLVID_getsdlglfunction(char *functionname)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void VID_Resized(int width, int height)
|
||||||
|
{
|
||||||
|
extern cvar_t vid_conautoscale, vid_conwidth;
|
||||||
|
vid.pixelwidth = width;
|
||||||
|
vid.pixelheight = height;
|
||||||
|
Con_Printf("Resized: %i %i\n", vid.pixelwidth, vid.pixelheight);
|
||||||
|
|
||||||
|
Cvar_ForceCallback(&vid_conautoscale);
|
||||||
|
Cvar_ForceCallback(&vid_conwidth);
|
||||||
|
}
|
||||||
|
static unsigned int domkeytoquake(unsigned int code)
|
||||||
|
{
|
||||||
|
unsigned int tab[256] =
|
||||||
|
{
|
||||||
|
/* 0*/ 0,0,0,0,0,0,0,0, K_BACKSPACE,K_TAB,0,0,0,K_ENTER,0,0,
|
||||||
|
/* 16*/ K_SHIFT,K_CTRL,K_ALT,K_PAUSE,K_CAPSLOCK,0,0,0,0,0,0,K_ESCAPE,0,0,0,0,
|
||||||
|
/* 32*/ ' ',K_PGUP,K_PGDN,K_END,K_HOME,K_LEFTARROW,K_UPARROW,K_RIGHTARROW, K_DOWNARROW,0,0,0,K_PRINTSCREEN,K_INS,K_DEL,0,
|
||||||
|
/* 48*/ '0','1','2','3','4','5','6','7', '8','9',0,0,0,0,0,0,
|
||||||
|
|
||||||
|
/* 64*/ 0,'a','b','c','d','e','f','g', 'h','i','j','k','l','m','n','o',
|
||||||
|
/* 80*/ 'p','q','r','s','t','u','v','w', 'x','y','z',K_LWIN,K_RWIN,K_APP,0,0,
|
||||||
|
/* 96*/ K_KP_INS,K_KP_END,K_KP_DOWNARROW,K_KP_PGDN,K_KP_LEFTARROW,K_KP_5,K_KP_RIGHTARROW,K_KP_HOME, K_KP_UPARROW,K_KP_PGDN,K_KP_STAR,K_KP_PLUS,0,K_KP_MINUS,K_KP_DEL,K_KP_SLASH,
|
||||||
|
/*112*/ K_F1,K_F2,K_F3,K_F4,K_F5,K_F6,K_F7,K_F8,K_F9,K_F10,K_F11,K_F12,0,0,0,0,
|
||||||
|
/*128*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
/*144*/ K_KP_NUMLOCK,K_SCRLCK,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
/*160*/ 0,0,0,'#',0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
/*176*/ 0,0,0,0,0,0,0,0, 0,0,';','=',',','-','.','/',
|
||||||
|
/*192*/ '`',0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
/*208*/ 0,0,0,0,0,0,0,0, 0,0,0,'[','\\',']','\'','`',
|
||||||
|
/*224*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
/*240*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
|
||||||
|
};
|
||||||
|
if (!code)
|
||||||
|
return 0;
|
||||||
|
if (code >= sizeof(tab)/sizeof(tab[0]))
|
||||||
|
{
|
||||||
|
Con_DPrintf("You just pressed key %u, but I don't know what its meant to be\n", code);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!tab[code])
|
||||||
|
Con_DPrintf("You just pressed key %u, but I don't know what its meant to be\n", code);
|
||||||
|
|
||||||
|
Con_DPrintf("You just pressed dom key %u, which is quake key %u\n", code, tab[code]);
|
||||||
|
return tab[code];
|
||||||
|
}
|
||||||
|
static void DOM_KeyEvent(int devid, int down, int scan, int uni)
|
||||||
|
{
|
||||||
|
IN_KeyEvent(0, down, domkeytoquake(scan), uni);
|
||||||
|
}
|
||||||
|
static void DOM_ButtonEvent(int devid, int down, int button)
|
||||||
|
{
|
||||||
|
if (down == 2)
|
||||||
|
{
|
||||||
|
//fixme: the event is a float. we ignore that.
|
||||||
|
while(button < 0)
|
||||||
|
{
|
||||||
|
IN_KeyEvent(0, true, K_MWHEELUP, 0);
|
||||||
|
button += 1;
|
||||||
|
}
|
||||||
|
while(button > 0)
|
||||||
|
{
|
||||||
|
IN_KeyEvent(0, true, K_MWHEELDOWN, 0);
|
||||||
|
button -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//swap buttons 2 and 3, so rmb is still +forward by default and not +mlook.
|
||||||
|
if (button == 2)
|
||||||
|
button = 1;
|
||||||
|
else if (button == 1)
|
||||||
|
button = 2;
|
||||||
|
|
||||||
|
IN_KeyEvent(0, down, K_MOUSE1+button, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
vid_isfullscreen = true;
|
||||||
|
|
||||||
|
if (!emscriptenfte_setupcanvas(
|
||||||
|
info->width,
|
||||||
|
info->height,
|
||||||
|
VID_Resized,
|
||||||
|
IN_MouseMove,
|
||||||
|
DOM_ButtonEvent,
|
||||||
|
DOM_KeyEvent
|
||||||
|
))
|
||||||
|
{
|
||||||
|
Con_Printf("Couldn't set up canvas\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveApp = true;
|
||||||
|
|
||||||
|
GL_Init(GLVID_getsdlglfunction);
|
||||||
|
|
||||||
|
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
|
||||||
|
|
||||||
|
mouseactive = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVID_DeInit (void)
|
||||||
|
{
|
||||||
|
ActiveApp = false;
|
||||||
|
|
||||||
|
emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GL_BeginRendering (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean screenflush;
|
||||||
|
void GL_DoSwap (void)
|
||||||
|
{
|
||||||
|
if (!screenflush)
|
||||||
|
return;
|
||||||
|
screenflush = 0;
|
||||||
|
|
||||||
|
//webgl doesn't support swapbuffers.
|
||||||
|
//you can't use it for loading screens.
|
||||||
|
//such things must result in waiting until the following frame.
|
||||||
|
//although there IS a swapped-buffers event, which we should probably use in preference to requestanimationframe or whatever the call is.
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!vid_isfullscreen)
|
||||||
|
{
|
||||||
|
if (!_windowed_mouse.value)
|
||||||
|
{
|
||||||
|
if (mouseactive)
|
||||||
|
{
|
||||||
|
IN_DeactivateMouse ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((key_dest == key_game||mouseusedforgui) && ActiveApp)
|
||||||
|
IN_ActivateMouse ();
|
||||||
|
else if (!(key_dest == key_game || mouseusedforgui) || !ActiveApp)
|
||||||
|
IN_DeactivateMouse ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_EndRendering (void)
|
||||||
|
{
|
||||||
|
screenflush = true;
|
||||||
|
if (!gl_lateswap.value)
|
||||||
|
GL_DoSwap();
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean GLVID_ApplyGammaRamps (unsigned short *ramps)
|
||||||
|
{
|
||||||
|
gammaworks = false;
|
||||||
|
return gammaworks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVID_SetCaption(char *text)
|
||||||
|
{
|
||||||
|
// SDL_WM_SetCaption( text, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_SendKeyEvents(void)
|
||||||
|
{
|
||||||
|
/*callbacks happen outside our code, we don't need to poll for events*/
|
||||||
|
}
|
||||||
|
/*various stuff for joysticks, which we don't support in this port*/
|
||||||
|
void INS_Shutdown (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void INS_ReInit (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void INS_Move(float *movements, int pnum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void INS_Init (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void INS_Accumulate(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void INS_Commands (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Module['preRun'] = function()
|
Module['preRun'] = function()
|
||||||
{
|
{
|
||||||
FS.createPath('/', 'id1', true, true);
|
//FS.createPath('/', 'id1', true, true);
|
||||||
//FS.createPath('/', 'qw', true, true);
|
//FS.createPath('/', 'qw', true, true);
|
||||||
//FS.createPath('/', 'fte', true, true);
|
//FS.createPath('/', 'fte', true, true);
|
||||||
|
|
||||||
|
|
387
engine/web/sys_web.c
Normal file
387
engine/web/sys_web.c
Normal file
|
@ -0,0 +1,387 @@
|
||||||
|
#include "quakedef.h"
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#ifdef MULTITHREAD
|
||||||
|
#include <SDL_thread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <SDL_loadso.h>
|
||||||
|
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
#include "ftejslib.h"
|
||||||
|
|
||||||
|
#ifndef isDedicated
|
||||||
|
qboolean isDedicated;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Sys_Error (const char *error, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char string[1024];
|
||||||
|
|
||||||
|
va_start (argptr,error);
|
||||||
|
vsnprintf (string, sizeof (string), error, argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
Sys_Printf("Error: %s\n", string);
|
||||||
|
|
||||||
|
Con_Print ("Quake Error: ");
|
||||||
|
Con_Print (string);
|
||||||
|
Con_Print ("\n");
|
||||||
|
|
||||||
|
if (COM_CheckParm("-crashonerror"))
|
||||||
|
*(int*)-3 = 0;
|
||||||
|
|
||||||
|
Host_Shutdown ();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_RecentServer(char *command, char *target, char *title, char *desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_RandomBytes(qbyte *string, int len)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//print into stdout
|
||||||
|
void Sys_Printf (char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
va_start (argptr,fmt);
|
||||||
|
vsnprintf (buf, sizeof(buf), fmt, argptr);
|
||||||
|
Sys_Print(buf);
|
||||||
|
va_end (argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Sys_Milliseconds(void)
|
||||||
|
{
|
||||||
|
static int first = true;
|
||||||
|
static unsigned long oldtime = 0, curtime = 0;
|
||||||
|
unsigned long newtime;
|
||||||
|
|
||||||
|
newtime = emscriptenfte_ticks_ms(); //return Date.now()
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = false;
|
||||||
|
oldtime = newtime;
|
||||||
|
}
|
||||||
|
if (newtime < oldtime)
|
||||||
|
Con_Printf("Sys_Milliseconds stepped backwards!\n");
|
||||||
|
else
|
||||||
|
curtime += newtime - oldtime;
|
||||||
|
oldtime = newtime;
|
||||||
|
return curtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
//return the current time, in the form of a double
|
||||||
|
double Sys_DoubleTime (void)
|
||||||
|
{
|
||||||
|
return Sys_Milliseconds() / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create a directory
|
||||||
|
void Sys_mkdir (char *path)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//unlink a file
|
||||||
|
qboolean Sys_remove (char *path)
|
||||||
|
{
|
||||||
|
emscriptenfte_buf_delete(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_Rename (char *oldfname, char *newfname)
|
||||||
|
{
|
||||||
|
return emscriptenfte_buf_rename(oldfname, newfname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//someone used the 'quit' command
|
||||||
|
void Sys_Quit (void)
|
||||||
|
{
|
||||||
|
Host_Shutdown();
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath)
|
||||||
|
{
|
||||||
|
Con_DPrintf("Warning: Sys_EnumerateFiles not implemented\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//blink window if possible (it's not)
|
||||||
|
void Sys_ServerActivity(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_CloseLibrary(dllhandle_t *lib)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Sys_Init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void Sys_Shutdown(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int VARGS Sys_DebugLog(char *file, char *fmt, ...)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
qboolean Sys_InitTerminal(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
char *Sys_ConsoleInput(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void Sys_CloseTerminal (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_MainLoop(void)
|
||||||
|
{
|
||||||
|
static float oldtime;
|
||||||
|
float newtime, time;
|
||||||
|
newtime = Sys_DoubleTime ();
|
||||||
|
if (!oldtime)
|
||||||
|
oldtime = newtime;
|
||||||
|
time = newtime - oldtime;
|
||||||
|
Host_Frame (time);
|
||||||
|
oldtime = newtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QDECL main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
float time, newtime, oldtime;
|
||||||
|
quakeparms_t parms;
|
||||||
|
int t;
|
||||||
|
int delay = 1;
|
||||||
|
|
||||||
|
memset(&parms, 0, sizeof(parms));
|
||||||
|
|
||||||
|
|
||||||
|
parms.basedir = "";
|
||||||
|
|
||||||
|
parms.argc = argc;
|
||||||
|
parms.argv = (const char**)argv;
|
||||||
|
|
||||||
|
COM_InitArgv (parms.argc, parms.argv);
|
||||||
|
|
||||||
|
TL_InitLanguages();
|
||||||
|
|
||||||
|
Sys_Printf ("Host_Init\n");
|
||||||
|
Host_Init (&parms);
|
||||||
|
|
||||||
|
oldtime = Sys_DoubleTime ();
|
||||||
|
|
||||||
|
|
||||||
|
//-1 fps should give vsync
|
||||||
|
emscripten_set_main_loop(Sys_MainLoop, -1, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *clipboard_buffer;
|
||||||
|
char *Sys_GetClipboard(void)
|
||||||
|
{
|
||||||
|
return clipboard_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_CloseClipboard(char *bf)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_SaveClipboard(char *text)
|
||||||
|
{
|
||||||
|
free(clipboard_buffer);
|
||||||
|
clipboard_buffer = strdup(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MULTITHREAD
|
||||||
|
/* Thread creation calls */
|
||||||
|
void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize)
|
||||||
|
{
|
||||||
|
// SDL threads do not support setting thread stack size
|
||||||
|
return (void *)SDL_CreateThread(func, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_WaitOnThread(void *thread)
|
||||||
|
{
|
||||||
|
SDL_WaitThread((SDL_Thread *)thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Mutex calls */
|
||||||
|
// SDL mutexes don't have try-locks for mutexes in the spec so we stick with 1-value semaphores
|
||||||
|
void *Sys_CreateMutex(void)
|
||||||
|
{
|
||||||
|
return (void *)SDL_CreateSemaphore(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_TryLockMutex(void *mutex)
|
||||||
|
{
|
||||||
|
return !SDL_SemTryWait(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_LockMutex(void *mutex)
|
||||||
|
{
|
||||||
|
return !SDL_SemWait(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_UnlockMutex(void *mutex)
|
||||||
|
{
|
||||||
|
return !SDL_SemPost(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_DestroyMutex(void *mutex)
|
||||||
|
{
|
||||||
|
SDL_DestroySemaphore(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Conditional wait calls */
|
||||||
|
typedef struct condvar_s
|
||||||
|
{
|
||||||
|
SDL_mutex *mutex;
|
||||||
|
SDL_cond *cond;
|
||||||
|
} condvar_t;
|
||||||
|
|
||||||
|
void *Sys_CreateConditional(void)
|
||||||
|
{
|
||||||
|
condvar_t *condv;
|
||||||
|
SDL_mutex *mutex;
|
||||||
|
SDL_cond *cond;
|
||||||
|
|
||||||
|
condv = (condvar_t *)malloc(sizeof(condvar_t));
|
||||||
|
if (!condv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mutex = SDL_CreateMutex();
|
||||||
|
cond = SDL_CreateCond();
|
||||||
|
|
||||||
|
if (mutex)
|
||||||
|
{
|
||||||
|
if (cond)
|
||||||
|
{
|
||||||
|
condv->cond = cond;
|
||||||
|
condv->mutex = mutex;
|
||||||
|
|
||||||
|
return (void *)condv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SDL_DestroyMutex(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(condv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_LockConditional(void *condv)
|
||||||
|
{
|
||||||
|
return !SDL_mutexP(((condvar_t *)condv)->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_UnlockConditional(void *condv)
|
||||||
|
{
|
||||||
|
return !SDL_mutexV(((condvar_t *)condv)->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_ConditionWait(void *condv)
|
||||||
|
{
|
||||||
|
return !SDL_CondWait(((condvar_t *)condv)->cond, ((condvar_t *)condv)->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_ConditionSignal(void *condv)
|
||||||
|
{
|
||||||
|
return !SDL_CondSignal(((condvar_t *)condv)->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Sys_ConditionBroadcast(void *condv)
|
||||||
|
{
|
||||||
|
return !SDL_CondBroadcast(((condvar_t *)condv)->cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sys_DestroyConditional(void *condv)
|
||||||
|
{
|
||||||
|
condvar_t *cv = (condvar_t *)condv;
|
||||||
|
|
||||||
|
SDL_DestroyCond(cv->cond);
|
||||||
|
SDL_DestroyMutex(cv->mutex);
|
||||||
|
free(cv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Sys_Sleep (double seconds)
|
||||||
|
{
|
||||||
|
SDL_Delay(seconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//emscripten does not support the full set of sdl functions, so we stub the extras.
|
||||||
|
int SDL_GetGammaRamp(Uint16 *redtable, Uint16 *greentable, Uint16 *bluetable)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int SDL_SetGammaRamp(const Uint16 *redtable, const Uint16 *greentable, const Uint16 *bluetable)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//SDL_GL_GetAttribute
|
||||||
|
void SDL_UnloadObject(void *object)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void *SDL_LoadObject(const char *sofile)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *SDL_LoadFunction(void *handle, const char *name)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Uint8 SDL_GetAppState(void)
|
||||||
|
{
|
||||||
|
return SDL_APPACTIVE;
|
||||||
|
}
|
||||||
|
#define socklen_t int
|
||||||
|
int getsockname(int socket, struct sockaddr *address, socklen_t *address_len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int getpeername(int socket, struct sockaddr *address, socklen_t *address_len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ssize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue