1
0
Fork 0
forked from fte/fteqw
fteqw/engine/nacl/sys_ppapi.c
Spoike 9dbf5b5837 changed to not load gamecode from quake paths, to avoid issues with buggy quakeworld clients that will freely download stuff from anywhere (not sure what to do about ktx, but it can be reenabled with a cvar).
image_width is now only set by a single function.
tweaked scancode inputs slightly. added support for printscreen binds.
changed the way gamma works. glsl gamma now used when running windows, or hardware gamma is not available. removed gl_contrast+gl_brightness.
q2 gamecode support no longer has a system componant. this means that ports only need the generic stuff.
misc tweaks to the d3d11 renderer.
added brief descriptions to many builtins. need to add comments to constants, globals, and fields too, somehow.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4355 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-05-11 14:02:55 +00:00

686 lines
No EOL
18 KiB
C

#include "quakedef.h"
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/ppb.h>
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/ppb_graphics_3d.h>
#include <ppapi/c/ppb_instance.h>
#include <ppapi/c/ppp.h>
#include <ppapi/c/ppp_instance.h>
#include <ppapi/c/ppb_input_event.h>
#include <ppapi/c/ppp_input_event.h>
#include <ppapi/c/ppb_var.h>
#include <ppapi/c/ppb_messaging.h>
#include <ppapi/c/ppb_file_system.h>
#include <ppapi/c/ppb_file_ref.h>
#include <ppapi/c/ppb_file_io.h>
#include <ppapi/c/ppb_url_loader.h>
#include <ppapi/c/ppb_url_response_info.h>
#include <ppapi/c/ppb_url_request_info.h>
#include <ppapi/c/ppb_audio.h>
#include <ppapi/c/ppb_audio_config.h>
#include <ppapi/c/ppb_mouse_lock.h>
#include <ppapi/c/ppp_mouse_lock.h>
#include <ppapi/c/ppb_fullscreen.h>
#include <ppapi/c/ppb_websocket.h>
#include <ppapi/c/ppb_view.h>
#include <ppapi/c/ppp_messaging.h>
#include <ppapi/c/pp_input_event.h>
#include <ppapi/gles2/gl2ext_ppapi.h>
PPB_Core *ppb_core = NULL;
PPB_Graphics3D *graphics3d_interface = NULL;
PPB_Instance *instance_interface = NULL;
PPB_Messaging *ppb_messaging_interface = NULL;
PPB_Var *ppb_var_interface = NULL;
PPB_InputEvent *ppb_inputevent_interface = NULL;
PPB_KeyboardInputEvent *ppb_keyboardinputevent_interface = NULL;
PPB_MouseInputEvent *ppb_mouseinputevent_interface = NULL;
PPB_WheelInputEvent *ppb_wheelinputevent_interface = NULL;
PPB_FileIO *ppb_fileio = NULL;
PPB_FileRef *ppb_fileref = NULL;
PPB_FileSystem *ppb_filesystem = NULL;
PPB_URLLoader *urlloader = NULL;
PPB_URLRequestInfo *urlrequestinfo = NULL;
PPB_URLResponseInfo *urlresponseinfo = NULL;
PPB_Audio *audio_interface = NULL;
PPB_AudioConfig *audioconfig_interface = NULL;
PPB_MouseLock *ppb_mouselock_interface = NULL;
PPB_Fullscreen *ppb_fullscreen_interface = NULL;
PPB_WebSocket *ppb_websocket_interface = NULL;
PPB_View *ppb_view_instance = NULL;
PP_Instance pp_instance;
PPB_GetInterface sys_gbi;
static double lasttime;
static qboolean mouselocked;
static qboolean shuttingdown;
qboolean FSPPAPI_Init(int *filenocookie);
qboolean NAGL_SwapPending(void);
unsigned short htons(unsigned short a)
{
union
{
unsigned char c[2];
unsigned short s;
} u;
u.s = a;
return u.c[0] | (unsigned short)(u.c[1]<<8);
}
unsigned short ntohs(unsigned short a)
{
return htons(a);
}
unsigned int htonl(unsigned int a)
{
union
{
unsigned char c[4];
unsigned int s;
} u;
u.s = a;
return u.c[0] | (unsigned int)(u.c[1]<<8) | (unsigned int)(u.c[2]<<16) | (unsigned int)(u.c[3]<<24);
}
unsigned long ntohl(unsigned long a)
{
return htonl(a);
}
qboolean isDedicated = false;
dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
{
return NULL;
}
void Sys_CloseLibrary(dllhandle_t *lib)
{
}
void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
{
return NULL;
}
char *Sys_GetNameForAddress(dllhandle_t *module, void *address)
{
return NULL;
}
qboolean Sys_RandomBytes(qbyte *string, int len)
{
return false;
}
qboolean Sys_InitTerminal (void)
{
return false;
}
void Sys_CloseTerminal (void)
{
}
char *Sys_GetClipboard(void)
{
return NULL;
}
void Sys_CloseClipboard(char *buf)
{
}
void Sys_SaveClipboard(char *text)
{
}
void Sys_ServerActivity(void)
{
}
char *Sys_ConsoleInput (void)
{
return NULL;
}
void Sys_SendKeyEvents(void)
{
}
void Sys_Init (void)
{
}
void Sys_Shutdown(void)
{
}
//this is already done using the ppapi event callback. can't poll any of this stuff.
void INS_Move(float *movements, int pnum)
{
}
void INS_Commands(void)
{
}
void INS_Init(void)
{
}
void INS_ReInit(void)
{
}
void INS_Shutdown(void)
{
}
/*
//nacl supposedly has no way to implement this (other than us writing a listfile in each directory)
int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm)
{
return 0;
}
*/
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate)
{
*width = 1024;
*height = 768;
*bpp = 32;
*refreshrate = 60;
return true;
return false;
}
// an error will cause the entire program to exit
NORETURN void VARGS Sys_Error (const char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr, error);
vsnprintf (string, sizeof(string)-1, error, argptr);
va_end (argptr);
Sys_Printf("Sys_Error: %s", string);
exit(1);
}
static struct PP_Var CStrToVar(const char* str)
{
if (ppb_var_interface != NULL)
{
return ppb_var_interface->VarFromUtf8(str, strlen(str));
}
return PP_MakeUndefined();
}
void VARGS Sys_Printf (char *fmt, ...)
{
va_list argptr;
char string[1024];
va_start (argptr, fmt);
vsnprintf (string, sizeof(string)-1, fmt, argptr);
va_end (argptr);
//this stuff generally doesn't even get shown
printf("%s", string);
if (pp_instance)
ppb_messaging_interface->PostMessage(pp_instance, CStrToVar(string));
}
void ppp_handlemessage(PP_Instance instance, struct PP_Var message)
{
char *clean;
const char *msg;
unsigned int len;
msg = ppb_var_interface->VarToUtf8(message, &len);
clean = malloc(len+2);
clean[len+0] = '\n';
clean[len+1] = 0;
memcpy(clean, msg, len);
Cbuf_AddText(clean, RESTRICT_INSECURE);
free(clean);
}
void Sys_Quit (void)
{
Sys_Printf("Sys_Quit\n");
shuttingdown = true;
}
void Sys_RecentServer(char *command, char *target, char *title, char *desc)
{
}
void Sys_mkdir (char *path)
{
}
qboolean Sys_remove (char *path)
{
return false;
}
qboolean Sys_Rename (char *oldfname, char *newfname)
{
return false;
}
#include <sys/time.h>
static int secbase;
double Sys_DoubleTime(void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000000.0;
}
return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
}
unsigned int Sys_Milliseconds (void)
{
return Sys_DoubleTime()*1000;
}
void FrameEvent(void* user_data, int32_t result)
{
if (shuttingdown)
{
if (!mouselocked && ppb_mouselock_interface)
ppb_mouselock_interface->UnlockMouse(pp_instance);
if (ppb_fullscreen_interface)
ppb_fullscreen_interface->SetFullscreen(pp_instance, PP_FALSE);
Host_Shutdown ();
ppb_inputevent_interface->RequestInputEvents(pp_instance, 0);
shuttingdown = false;
return;
}
if (pp_instance)
{
if (!NAGL_SwapPending())
{
double newtime = Sys_DoubleTime();
// Sys_Printf("Frame %f\n", newtime);
Host_Frame(newtime - lasttime);
lasttime = newtime;
}
if (!NAGL_SwapPending())
{
struct PP_CompletionCallback ccb = {FrameEvent, user_data, PP_COMPLETIONCALLBACK_FLAG_NONE};
ppb_core->CallOnMainThread(0, ccb, 0);
}
}
}
void startquake(char *manif)
{
static char *args[16];
quakeparms_t parms;
memset(&parms, 0, sizeof(parms));
parms.basedir = ""; /*filled in later*/
parms.argc = 0;
parms.argv = args;
//FIXME: generate some sort of commandline properly.
args[parms.argc++] = "ftedroid";
if (manif)
{
args[parms.argc++] = "-manifest";
args[parms.argc++] = manif;
}
parms.memsize = 16*1024*1024;
parms.membase = malloc(parms.memsize);
if (!parms.membase)
{
Sys_Printf("Unable to alloc heap\n");
return;
}
Sys_Printf("Starting up\n");
COM_InitArgv(parms.argc, parms.argv);
TL_InitLanguages();
#ifdef SERVERONLY
SV_Init(&parms);
#else
Host_Init(&parms);
#endif
lasttime = Sys_DoubleTime();
FrameEvent(NULL, 0);
}
void trystartquake(void* user_data, int32_t result)
{
if (FSPPAPI_Init(&result))
startquake(user_data);
else
{
struct PP_CompletionCallback ccb = {trystartquake, user_data, PP_COMPLETIONCALLBACK_FLAG_NONE};
ppb_core->CallOnMainThread(100, ccb, result);
}
}
static PP_Bool Instance_DidCreate(PP_Instance instance,
uint32_t argc,
const char* argn[],
const char* argv[])
{
int i;
pp_instance = instance;
char *manif = NULL;
//FIXME: do something with the embed arguments
for (i = 0; i < argc; i++)
{
if (!strcasecmp(argn[i], "ftemanifest"))
manif = strdup(argv[i]);
}
ppb_inputevent_interface->RequestInputEvents(pp_instance, PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_KEYBOARD | PP_INPUTEVENT_CLASS_WHEEL);
trystartquake(manif, 0);
return PP_TRUE;
}
static void cb_mouselocked(void* user_data, int32_t result)
{
if (result == PP_OK)
{
mouselocked = true;
}
}
static void ppp_mouseunlocked(PP_Instance instance)
{
mouselocked = false;
}
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,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 >= 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 int QuakeButtonForNACLButton(int but)
{
switch(but)
{
case 1:
return K_MOUSE3;
case 2:
return K_MOUSE2;
default:
return K_MOUSE1 + but;
}
}
static PP_Bool InputEvent_HandleEvent(PP_Instance pp_instance, PP_Resource resource)
{
extern cvar_t vid_fullscreen;
if (!pp_instance || !host_initialized)
return PP_FALSE;
switch(ppb_inputevent_interface->GetType(resource))
{
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
if (vid_fullscreen.ival)
{
if (ppb_fullscreen_interface)
ppb_fullscreen_interface->SetFullscreen(pp_instance, PP_TRUE);
if (!mouselocked && ppb_mouselock_interface)
{
struct PP_CompletionCallback ccb = {cb_mouselocked, NULL, PP_COMPLETIONCALLBACK_FLAG_NONE};
int res = ppb_mouselock_interface->LockMouse(pp_instance, ccb);
if (res != PP_OK_COMPLETIONPENDING)
cb_mouselocked(NULL, res);
else
return PP_TRUE;
}
}
IN_KeyEvent(0, true, QuakeButtonForNACLButton(ppb_mouseinputevent_interface->GetButton(resource)), 0);
return PP_TRUE;
case PP_INPUTEVENT_TYPE_MOUSEUP:
IN_KeyEvent(0, false, QuakeButtonForNACLButton(ppb_mouseinputevent_interface->GetButton(resource)), 0);
return PP_TRUE;
case PP_INPUTEVENT_TYPE_MOUSEMOVE:
{
struct PP_Point p;
if (mouselocked)
{
p = ppb_mouseinputevent_interface->GetMovement(resource);
IN_MouseMove(0, false, p.x, p.y, 0, 0);
}
else
{
p = ppb_mouseinputevent_interface->GetPosition(resource);
IN_MouseMove(0, true, p.x, p.y, 0, 0);
}
}
return PP_TRUE;
case PP_INPUTEVENT_TYPE_MOUSEENTER:
//we don't really care too much if it leave the window
// Con_Printf("mouseenter\n");
return PP_TRUE;
case PP_INPUTEVENT_TYPE_MOUSELEAVE:
//we don't really care too much if it leave the window (should throttle framerates perhaps, but that's all)
// Con_Printf("mouseleave\n");
return PP_TRUE;
case PP_INPUTEVENT_TYPE_WHEEL:
{
static float wheelticks;
struct PP_FloatPoint p;
p = ppb_wheelinputevent_interface->GetTicks(resource);
//the value is fractional, so we need some persistant value to track it on high-precision mice.
wheelticks += p.y;
while (wheelticks > 1)
{
IN_KeyEvent(0, 1, K_MWHEELUP, 0);
IN_KeyEvent(0, 0, K_MWHEELUP, 0);
wheelticks--;
}
while (wheelticks < 0)
{
IN_KeyEvent(0, 1, K_MWHEELDOWN, 0);
IN_KeyEvent(0, 0, K_MWHEELDOWN, 0);
wheelticks++;
}
}
return PP_TRUE;
case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
// Con_Printf("rawkeydown\n");
return PP_FALSE;
case PP_INPUTEVENT_TYPE_KEYDOWN:
IN_KeyEvent(0, 1, domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource)), 0);
return PP_FALSE;
case PP_INPUTEVENT_TYPE_KEYUP:
IN_KeyEvent(0, 0, domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource)), 0);
return PP_TRUE;
case PP_INPUTEVENT_TYPE_CHAR:
{
const unsigned char *s;
unsigned int c;
unsigned int len;
len = 0;
s = ppb_var_interface->VarToUtf8(ppb_keyboardinputevent_interface->GetCharacterText(resource), &len);
while(len)
{
if (*s & 0x80)
{
if (!(*s & 0x40))
{
//illegal encoding
c = '?';
len -= 1;
}
else if (!(*s & 0x20) && (s[1] & 0xc0) == 0x80)
{
c = ((s[0] & 0x1f)<<6) | ((s[1] & 0x3f)<<0);
if (c < (1<<7))
c = '?';
len -= 2;
}
else if (!(*s & 0x10) && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80)
{
c = ((s[0] & 0x0f)<<12) | ((s[1] & 0x3f)<<6) | ((s[2] & 0x3f)<<0);
if (c < (1<<13))
c = '?';
len -= 3;
}
else if (!(*s & 0x08) && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80 && (s[3] & 0xc0) == 0x80)
{
c = ((s[0] & 0x07)<<18) | ((s[1] & 0x3f)<<12) | ((s[2] & 0x3f)<<6) | ((s[3] & 0x3f)<<0);
if (c < (1<<19))
c = '?';
len -= 4;
}
else
{
//too lazy to handle that encoding
c = '?';
len -= 1;
}
}
else
{
c = *s;
len--;
}
IN_KeyEvent(0, true, 0, c);
IN_KeyEvent(0, false, 0, c);
}
}
return PP_TRUE;
case PP_INPUTEVENT_TYPE_CONTEXTMENU:
//We don't care about the context menu, we just want to be able to right-click.
return PP_TRUE;
default:
Con_Printf("Unknown input event type\n");
break;
}
return PP_FALSE;
}
static void Instance_DidDestroy(PP_Instance instance)
{
}
void GL_Resized(int width, int height);
static void Instance_DidChangeView(PP_Instance instance, PP_Resource view_resource)
{
struct PP_Rect rect;
ppb_view_instance->GetRect(view_resource, &rect);
GL_Resized(rect.size.width, rect.size.height);
}
static void Instance_DidChangeFocus(PP_Instance instance, PP_Bool has_focus)
{
}
static PP_Bool Instance_HandleDocumentLoad(PP_Instance instance, PP_Resource url_loader)
{
return PP_FALSE;
}
PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser)
{
ppb_core = (PPB_Core*)(get_browser(PPB_CORE_INTERFACE));
sys_gbi = get_browser;
graphics3d_interface = (PPB_Graphics3D*)(get_browser(PPB_GRAPHICS_3D_INTERFACE));
ppb_messaging_interface = (PPB_Messaging*)(get_browser(PPB_MESSAGING_INTERFACE));
ppb_var_interface = (PPB_Var*)(get_browser(PPB_VAR_INTERFACE));
instance_interface = (PPB_Instance*)(get_browser(PPB_INSTANCE_INTERFACE));
ppb_inputevent_interface = (PPB_InputEvent*)(get_browser(PPB_INPUT_EVENT_INTERFACE));
ppb_keyboardinputevent_interface = (PPB_KeyboardInputEvent*)(get_browser(PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
ppb_mouseinputevent_interface = (PPB_MouseInputEvent*)(get_browser(PPB_MOUSE_INPUT_EVENT_INTERFACE));
ppb_wheelinputevent_interface = (PPB_WheelInputEvent*)(get_browser(PPB_WHEEL_INPUT_EVENT_INTERFACE));
ppb_fileio = (PPB_FileIO*)(get_browser(PPB_FILEIO_INTERFACE));
ppb_fileref = (PPB_FileRef*)(get_browser(PPB_FILEREF_INTERFACE));
ppb_filesystem = (PPB_FileSystem*)(get_browser(PPB_FILESYSTEM_INTERFACE));
urlloader = (PPB_URLLoader*)(get_browser(PPB_URLLOADER_INTERFACE ));
urlrequestinfo = (PPB_URLRequestInfo*)(get_browser(PPB_URLREQUESTINFO_INTERFACE));
urlresponseinfo = (PPB_URLResponseInfo*)(get_browser(PPB_URLRESPONSEINFO_INTERFACE));
audio_interface = (PPB_Audio*)(get_browser(PPB_AUDIO_INTERFACE));
audioconfig_interface = (PPB_AudioConfig*)(get_browser(PPB_AUDIO_CONFIG_INTERFACE));
ppb_mouselock_interface = (PPB_MouseLock*)(get_browser(PPB_MOUSELOCK_INTERFACE));
ppb_fullscreen_interface = (PPB_Fullscreen*)(get_browser(PPB_FULLSCREEN_INTERFACE));
ppb_websocket_interface = (PPB_WebSocket*)(get_browser(PPB_WEBSOCKET_INTERFACE));
ppb_view_instance = (PPB_View*)(get_browser(PPB_VIEW_INTERFACE));
glInitializePPAPI(sys_gbi);
return PP_OK;
}
PP_EXPORT const void* PPP_GetInterface(const char* interface_name)
{
if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0)
{
static PPP_Instance instance_interface =
{
&Instance_DidCreate,
&Instance_DidDestroy,
&Instance_DidChangeView,
&Instance_DidChangeFocus,
&Instance_HandleDocumentLoad,
};
return &instance_interface;
}
if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0)
{
static PPP_InputEvent input_event_interface =
{
&InputEvent_HandleEvent
};
return &input_event_interface;
}
if (strcmp(interface_name, PPP_MOUSELOCK_INTERFACE) == 0)
{
static PPP_MouseLock mouselock_interface =
{
&ppp_mouseunlocked
};
return &mouselock_interface;
}
if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0)
{
static PPP_Messaging messaging_interface =
{
ppp_handlemessage
};
return &messaging_interface;
}
return NULL;
}
PP_EXPORT void PPP_ShutdownModule()
{
}