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
|
||||
|
||||
ifeq ($(FTE_TARGET),web)
|
||||
COMMON_OBJS+=sys_web.o fs_web.o
|
||||
WEB_PREJS ?= --pre-js web/prejs.js
|
||||
# WEB_MEMORY?=402653184 #384mb
|
||||
ASMJS_MEMORY?=536870912 #512mb (required for asm.js)
|
||||
# ASMJS_MEMORY?=268435456 #256mb (required for asm.js)
|
||||
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
|
||||
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=-O1 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js --shell-file web/fteshell.html
|
||||
DEBUG_LDLAGS=-O0 $(WEB_PREJS) -s TOTAL_MEMORY=$(WEB_MEMORY) --js-library web/ftejslib.js
|
||||
RELEASE_LDFLAGS=-s ASM_JS=1 -O1 -s TOTAL_MEMORY=$(ASMJS_MEMORY) $(EMCC_ARGS)
|
||||
# RELEASE_LDFLAGS=-s ASM_JS=0 -O1 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS)
|
||||
DEBUG_LDLAGS=-O0 -s TOTAL_MEMORY=$(WEB_MEMORY) $(EMCC_ARGS)
|
||||
CC=emcc
|
||||
#BASELDFLAGS=
|
||||
|
||||
#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=
|
||||
|
||||
SV_DIR=sv_web
|
||||
|
@ -1200,7 +1204,7 @@ ifneq ($(OUT_DIR),)
|
|||
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)),)
|
||||
#add these to statically link libspeex
|
||||
|
|
|
@ -254,7 +254,7 @@ static texwadlump_t texwadlump[TEXWAD_MAXIMAGES];
|
|||
|
||||
typedef struct wadfile_s {
|
||||
char name[64];
|
||||
FILE *file;
|
||||
vfsfile_t *file;
|
||||
struct wadfile_s *next;
|
||||
} wadfile_t;
|
||||
|
||||
|
@ -265,7 +265,7 @@ void Wads_Flush (void)
|
|||
wadfile_t *wf;
|
||||
while(openwadfiles)
|
||||
{
|
||||
fclose(openwadfiles->file);
|
||||
VFS_CLOSE(openwadfiles->file);
|
||||
|
||||
wf = openwadfiles->next;
|
||||
Z_Free(openwadfiles);
|
||||
|
|
|
@ -3796,7 +3796,7 @@ void COM_InitArgv (int argc, const char **argv) //not allowed to tprint
|
|||
int i;
|
||||
size_t result;
|
||||
|
||||
#ifndef NACL
|
||||
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
|
||||
FILE *f;
|
||||
|
||||
if (argv && argv[0])
|
||||
|
|
|
@ -479,6 +479,11 @@ void Cvar_Reset_f (void)
|
|||
if (gsearch)
|
||||
Q_strlwr(gsearch);
|
||||
|
||||
if (!strcmp(search, "*"))
|
||||
search = NULL;
|
||||
if (!strcmp(gsearch, "*"))
|
||||
gsearch = NULL;
|
||||
|
||||
for (grp=cvar_groups ; grp ; grp=grp->next)
|
||||
{
|
||||
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;
|
||||
// reset cvar to default
|
||||
Cvar_Set(cmd, cmd->defaultstr);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "fs.h"
|
||||
#include "errno.h"
|
||||
|
||||
#ifndef NACL
|
||||
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
|
||||
|
||||
#ifdef WEBSVONLY
|
||||
#define Z_Free free
|
||||
|
|
|
@ -4066,11 +4066,7 @@ struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboole
|
|||
#endif
|
||||
|
||||
#ifdef FTE_TARGET_WEB
|
||||
int emscriptenfte_ws_connect(char *url);
|
||||
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);
|
||||
#include "web/ftejslib.h"
|
||||
|
||||
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.
|
||||
{
|
||||
#ifdef FTE_TARGET_WEB
|
||||
return;
|
||||
#else
|
||||
FILE *f;
|
||||
int size;
|
||||
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);
|
||||
free(buffer);
|
||||
#endif
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
#define CONVERTDEFAULT
|
||||
|
|
|
@ -1271,6 +1271,11 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne
|
|||
}
|
||||
else
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -158,6 +158,7 @@ void (APIENTRY *qglFogf) (GLenum pname, GLfloat param);
|
|||
void (APIENTRY *qglFogi) (GLenum pname, GLint param);
|
||||
void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params);
|
||||
|
||||
#ifndef GL_STATIC
|
||||
void (APIENTRY *qglGenBuffersARB)(GLsizei n, GLuint* ids);
|
||||
void (APIENTRY *qglDeleteBuffersARB)(GLsizei n, GLuint* ids);
|
||||
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 *qglMapBufferARB)(GLenum target, GLenum access);
|
||||
GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
|
||||
#endif
|
||||
|
||||
void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
|
||||
void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
||||
|
@ -172,11 +174,13 @@ void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
|
|||
const GLubyte * (APIENTRY * qglGetStringi) (GLenum name, GLuint index);
|
||||
void (APIENTRY * qglGetPointerv) (GLenum pname, GLvoid **parms);
|
||||
|
||||
#ifndef GL_STATIC
|
||||
void (APIENTRY *qglGenRenderbuffersEXT)(GLsizei n, GLuint* ids);
|
||||
void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id);
|
||||
void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height);
|
||||
void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId);
|
||||
GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target);
|
||||
#endif
|
||||
|
||||
void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax);
|
||||
/*
|
||||
|
@ -191,7 +195,9 @@ FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT;
|
|||
|
||||
//extensions
|
||||
//arb multitexture
|
||||
#ifndef qglActiveTextureARB
|
||||
qlpSelTexFUNC qglActiveTextureARB;
|
||||
#endif
|
||||
qlpSelTexFUNC qglClientActiveTextureARB;
|
||||
qlpMTex3FUNC qglMultiTexCoord3fARB;
|
||||
qlpMTex2FUNC qglMultiTexCoord2fARB;
|
||||
|
@ -521,7 +527,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
//multitexture
|
||||
gl_mtexable = false;
|
||||
gl_mtexarbable = 0;
|
||||
#ifndef qglActiveTextureARB
|
||||
qglActiveTextureARB = NULL;
|
||||
#endif
|
||||
qglMultiTexCoord2fARB = NULL;
|
||||
qglMultiTexCoord3fARB = NULL;
|
||||
qglMTexCoord2fSGIS = NULL;
|
||||
|
@ -587,7 +595,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
|
||||
if (gl_config.gles)
|
||||
{
|
||||
#ifndef qglActiveTextureARB
|
||||
qglActiveTextureARB = (void *) getglext("glActiveTexture");
|
||||
#endif
|
||||
qglClientActiveTextureARB = (void *) getglext("glClientActiveTexture");
|
||||
qglSelectTextureSGIS = qglActiveTextureARB;
|
||||
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"))
|
||||
{ //ARB multitexture is the popular choice.
|
||||
#ifndef qglActiveTextureARB
|
||||
qglActiveTextureARB = (void *) getglext("glActiveTextureARB");
|
||||
#endif
|
||||
qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB");
|
||||
qglMultiTexCoord2fARB = (void *) getglext("glMultiTexCoord2fARB");
|
||||
qglMultiTexCoord3fARB = (void *) getglext("glMultiTexCoord3fARB");
|
||||
|
@ -611,6 +623,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
|
||||
mtexid0 = GL_TEXTURE0_ARB;
|
||||
|
||||
#ifndef qglActiveTextureARB
|
||||
if (!qglActiveTextureARB || !qglClientActiveTextureARB || !qglMultiTexCoord2fARB)
|
||||
{
|
||||
qglActiveTextureARB = NULL;
|
||||
|
@ -625,7 +638,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
{
|
||||
Con_DPrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
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");
|
||||
|
||||
#if !defined(GL_STATIC)
|
||||
/*vbos*/
|
||||
if (gl_config.gles && gl_config.glversion >= 2)
|
||||
{
|
||||
|
@ -733,6 +747,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
qglMapBufferARB = (void *)getglext("glMapBufferARB");
|
||||
qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GL_STATIC
|
||||
gl_config.arb_shader_objects = true;
|
||||
|
@ -1608,11 +1623,13 @@ void GL_Init(void *(*getglfunction) (char *name))
|
|||
qglEndList = (void*)getglcore("glEndList");
|
||||
qglCallList = (void*)getglcore("glCallList");
|
||||
|
||||
#ifndef GL_STATIC
|
||||
qglBindBufferARB = (void *)getglext("glBindBufferARB");
|
||||
if (!qglBindBufferARB)
|
||||
qglBindBufferARB = (void *)getglext("glBindBuffer");
|
||||
if (!qglBindBufferARB)
|
||||
qglBindBufferARB = GL_BindBufferARBStub;
|
||||
#endif
|
||||
|
||||
gl_vendor = qglGetString (GL_VENDOR);
|
||||
Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
|
||||
|
|
|
@ -440,12 +440,12 @@ void R_NetGraph (void);
|
|||
#ifdef GL_STATIC
|
||||
//these are the functions that are valid in gles2.
|
||||
//other functions should never actually be used.
|
||||
#define qglActiveTexture glActiveTexture
|
||||
#define qglActiveTextureARB glActiveTexture
|
||||
#define qglAttachShader glAttachShader
|
||||
#define qglBindAttribLocation glBindAttribLocation
|
||||
#define qglBindBuffer glBindBuffer
|
||||
#define qglBindFramebuffer glBindFramebuffer
|
||||
#define qglBindRenderbuffer glBindRenderbuffer
|
||||
#define qglBindRenderbufferEXT glBindRenderbuffer
|
||||
#define qglBindTexture glBindTexture
|
||||
#define qglBlendColor glBlendColor
|
||||
#define qglBlendEquation glBlendEquation
|
||||
|
@ -454,7 +454,7 @@ void R_NetGraph (void);
|
|||
#define qglBlendFuncSeparate glBlendFuncSeparate
|
||||
#define qglBufferData glBufferData
|
||||
#define qglBufferSubData glBufferSubData
|
||||
#define qglCheckFramebufferStatus glCheckFramebufferStatus
|
||||
#define qglCheckFramebufferStatusEXT glCheckFramebufferStatus
|
||||
#define qglClear glClear
|
||||
#define qglClearColor glClearColor
|
||||
#define qglClearDepthf glClearDepthf
|
||||
|
@ -486,13 +486,13 @@ void R_NetGraph (void);
|
|||
#define qglEnableVertexAttribArray glEnableVertexAttribArray
|
||||
#define qglFinish glFinish
|
||||
#define qglFlush glFlush
|
||||
#define qglFramebufferRenderbuffer glFramebufferRenderbuffer
|
||||
#define qglFramebufferRenderbufferEXT glFramebufferRenderbuffer
|
||||
#define qglFramebufferTexture2D glFramebufferTexture2D
|
||||
#define qglFrontFace glFrontFace
|
||||
#define qglGenBuffers glGenBuffers
|
||||
#define qglGenerateMipmap glGenerateMipmap
|
||||
#define qglGenFramebuffers glGenFramebuffers
|
||||
#define qglGenRenderbuffers glGenRenderbuffers
|
||||
#define qglGenRenderbuffersEXT glGenRenderbuffers
|
||||
#define qglGenTextures glGenTextures
|
||||
#define qglGetActiveAttrib glGetActiveAttrib
|
||||
#define qglGetActiveUniform glGetActiveUniform
|
||||
|
@ -534,7 +534,7 @@ void R_NetGraph (void);
|
|||
#define qglPolygonOffset glPolygonOffset
|
||||
#define qglReadPixels glReadPixels
|
||||
#define qglReleaseShaderCompiler glReleaseShaderCompiler
|
||||
#define qglRenderbufferStorage glRenderbufferStorage
|
||||
#define qglRenderbufferStorageEXT glRenderbufferStorage
|
||||
#define qglSampleCoverage glSampleCoverage
|
||||
#define qglScissor glScissor
|
||||
#define qglShaderBinary glShaderBinary
|
||||
|
@ -616,6 +616,14 @@ void R_NetGraph (void);
|
|||
#define qglUniform1iARB glUniform1i
|
||||
#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
|
||||
extern void (APIENTRY *qglBindTexture) (GLenum target, GLuint texture);
|
||||
extern void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
|
||||
|
@ -708,6 +716,14 @@ extern FTEPFNGLGETVERTEXATTRIBIV qglGetVertexAttribiv;
|
|||
extern FTEPFNGLENABLEVERTEXATTRIBARRAY qglEnableVertexAttribArray;
|
||||
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
|
||||
|
||||
//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 *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 *qglBindVertexArray)(GLuint vaoarray);
|
||||
|
||||
|
|
|
@ -17,72 +17,6 @@
|
|||
#include <emscripten/emscripten.h>
|
||||
#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)
|
||||
{
|
||||
dl->ctx = NULL;
|
||||
|
@ -102,20 +36,23 @@ static void DL_OnLoad(void *c, void *data, int datasize)
|
|||
else
|
||||
{
|
||||
//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)
|
||||
{
|
||||
VFS_WRITE(dl->file, data, datasize);
|
||||
VFS_SEEK(dl->file, 0);
|
||||
dl->status = DL_FINISHED;
|
||||
}
|
||||
else
|
||||
dl->status = DL_FAILED;
|
||||
|
||||
dl->replycode = 200;
|
||||
#if !MYJS
|
||||
dl->completed += datasize;
|
||||
#endif
|
||||
dl->status = DL_FINISHED;
|
||||
}
|
||||
#if MYJS
|
||||
static void DL_OnError(void *c, int ecode)
|
||||
|
@ -124,13 +61,13 @@ static void DL_OnError(void *c)
|
|||
#endif
|
||||
{
|
||||
struct dl_download *dl = c;
|
||||
Con_Printf("download %p: error\n", dl);
|
||||
|
||||
#if MYJS
|
||||
dl->replycode = ecode;
|
||||
#else
|
||||
dl->replycode = 404; //we don't actually know. should we not do this?
|
||||
#endif
|
||||
Con_Printf("download %p: error %i\n", dl, dl->replycode);
|
||||
dl->status = DL_FAILED;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#ifdef FTE_TARGET_WEB
|
||||
#define printf NULL //should be some null wrapper instead
|
||||
#endif
|
||||
|
||||
//defs incase following structure is not passed.
|
||||
struct edict_s *safesv_edicts;
|
||||
|
|
|
@ -1686,11 +1686,13 @@ void SV_AcceptMessage(int protocol)
|
|||
#include <sys/stat.h>
|
||||
static void SV_CheckRecentCrashes(client_t *tellclient)
|
||||
{
|
||||
#ifndef FTE_TARGET_WEB
|
||||
struct stat sb;
|
||||
if (-1 != stat("crash.log", &sb))
|
||||
{
|
||||
SV_ClientPrintf(tellclient, PRINT_HIGH, "\1WARNING: crash.log exists, dated %s\n", ctime(&sb.st_mtime));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
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)
|
||||
{
|
||||
#if 1
|
||||
Con_Printf("Fixme\n");
|
||||
#else
|
||||
rankinfo_t ri;
|
||||
int id;
|
||||
int num;
|
||||
|
@ -680,6 +683,7 @@ void Rank_RankingList_f (void)
|
|||
}
|
||||
|
||||
fclose(outfile);
|
||||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
//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,
|
||||
{
|
||||
$FTESockets__deps: [],
|
||||
$FTESockets: {
|
||||
socks: []
|
||||
//generic handles array
|
||||
//yeah, I hope you don't use-after-free. hopefully that sort of thing will be detected on systems with easier non-mangled debuggers.
|
||||
$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)
|
||||
{
|
||||
var _url = Pointer_stringify(url);
|
||||
var s = {ws:null, inq:[], err:0};
|
||||
for (var i = 0; ; i+=1)
|
||||
{
|
||||
if (!FTESockets.socks[i])
|
||||
s.ws = new WebSocket(_url, 'binary');
|
||||
if (!s.ws)
|
||||
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');
|
||||
if (!s.ws)
|
||||
return -1;
|
||||
FTESockets.socks[i] = s;
|
||||
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)
|
||||
{
|
||||
assert(typeof event.data !== 'string' && event.data.byteLength);
|
||||
s.inq.push(new Uint8Array(event.data));
|
||||
};
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
assert(typeof event.data !== 'string' && event.data.byteLength);
|
||||
s.inq.push(new Uint8Array(event.data));
|
||||
};
|
||||
|
||||
return _emscriptenfte_handle_alloc(s);
|
||||
},
|
||||
emscriptenfte_ws_close : function(sockid)
|
||||
{
|
||||
var s = FTESockets.socks[sockid];
|
||||
var s = FTEH.h[sockid];
|
||||
if (!s)
|
||||
return -1;
|
||||
s.ws.close();
|
||||
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;
|
||||
},
|
||||
//separate call allows for more sane flood control when fragmentation is involved.
|
||||
emscriptenfte_ws_cansend : function(sockid, extra, maxpending)
|
||||
{
|
||||
var s = FTESockets.socks[sockid];
|
||||
var s = FTEH.h[sockid];
|
||||
if (!s)
|
||||
return 1; //go on punk, make my day.
|
||||
return ((s.ws.bufferedAmount+extra) < maxpending);
|
||||
},
|
||||
emscriptenfte_ws_send : function(sockid, data, len)
|
||||
{
|
||||
var s = FTESockets.socks[sockid];
|
||||
var s = FTEH.h[sockid];
|
||||
if (!s)
|
||||
return -1;
|
||||
s.s.send(HEAPU8.subarray(data, data+len).buffer);
|
||||
|
@ -59,7 +337,7 @@ mergeInto(LibraryManager.library,
|
|||
},
|
||||
emscriptenfte_ws_recv : function(sockid, data, len)
|
||||
{
|
||||
var s = FTESockets.socks[sockid];
|
||||
var s = FTEH.h[sockid];
|
||||
if (!s)
|
||||
return -1;
|
||||
var inp = s.inq.shift();
|
||||
|
@ -80,13 +358,14 @@ mergeInto(LibraryManager.library,
|
|||
emscriptenfte_async_wget_data2 : function(url, ctx, onload, onerror, onprogress)
|
||||
{
|
||||
var _url = Pointer_stringify(url);
|
||||
|
||||
console.log("Attempting download of " + _url);
|
||||
var http = new XMLHttpRequest();
|
||||
http.open('GET', _url, true);
|
||||
http.responseType = 'arraybuffer';
|
||||
|
||||
http.onload = function(e)
|
||||
{
|
||||
console.log("onload: " + _url + " status " + http.status);
|
||||
if (http.status == 200)
|
||||
{
|
||||
var bar = new Uint8Array(http.response);
|
||||
|
@ -104,6 +383,7 @@ mergeInto(LibraryManager.library,
|
|||
|
||||
http.onerror = function(e)
|
||||
{
|
||||
console.log("onerror: " + _url + " status " + http.status);
|
||||
if (onerror)
|
||||
Runtime.dynCall('vii', onerror, [ctx, http.status]);
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>FTE QuakeWorld</title>
|
||||
<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; }
|
||||
div.emscripten { text-align: center; }
|
||||
div.emscripten_border { border: 1px solid black; }
|
||||
div.emscripten { text-align: center; padding:0; margin: 0;}
|
||||
div.emscripten_border { padding:0; margin: 0; }
|
||||
/* 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>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -21,14 +21,14 @@
|
|||
<div class="emscripten_border">
|
||||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
</div>
|
||||
<div class="emscripten">
|
||||
<!-- <div class="emscripten">
|
||||
<input type="checkbox" id="resize">Resize canvas
|
||||
<input type="checkbox" id="pointerLock" checked>Lock/hide mouse pointer
|
||||
|
||||
<input type="button" value="Fullscreen" onclick="Module.requestFullScreen(document.getElementById('pointerLock').checked,
|
||||
document.getElementById('resize').checked)">
|
||||
</div>
|
||||
|
||||
-->
|
||||
<script type='text/javascript'>
|
||||
// connect to canvas
|
||||
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()
|
||||
{
|
||||
FS.createPath('/', 'id1', true, true);
|
||||
//FS.createPath('/', 'id1', true, true);
|
||||
//FS.createPath('/', 'qw', 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