Remove NaCl code (#190)

* Remove the nacl dir

* Remove nacl from ifdef checks shared with other platforms

* Remove nacl from build bash scripts

* More removal of nacl from bash scripts

* Remove nacl-specific code from the engine

* More removal of nacl-specific code from the engine

* remove nacl-specific code from the Quake 3 plugin

* Remove nacl from readme (also seems to have force LF line endings)

* Remove nacl mention from browser.txt

* Remove nacl from Makefile

* Remove nacl from dotnet2005 solution file (lol)

* Correcting an endif, this did not end nacl

* Clarification for NaCL no longer needed

* Left small todo for myself

* Partially undo f44daef091bcc5917b0ddb2cbe41ebdd9738f770
the if preproc checking for `_DEBUG` was incorrectly removed
This commit is contained in:
fhomolka 2023-07-02 00:20:13 +02:00 committed by GitHub
parent 7f8b827cb8
commit 6d83a3218a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 115 additions and 2721 deletions

View File

@ -1,123 +1,105 @@
Yay, you found out the secrit location to download the sauce code from!
Right, urm, now what?
Yeah, good question.
Urm.
Quick start guide:
cd engine
make sv-rel -j4
make gl-rel -j4
cd ..
engine/release/fteqw.sv -nohome -basedir ~/quake
engine/release/fteqw.gl -nohome -basedir ~/quake
You do not need to configure. The makefile will automatically do that depending on the target build/system.
Yay, you found out the secrit location to download the sauce code from!
Right, urm, now what?
Yeah, good question.
Urm.
Quick start guide:
cd engine
make sv-rel -j4
make gl-rel -j4
cd ..
engine/release/fteqw.sv -nohome -basedir ~/quake
engine/release/fteqw.gl -nohome -basedir ~/quake
You do not need to configure. The makefile will automatically do that depending on the target build/system.
Easy Build Bot System:
If you want to set up a linux box that cross-compiles each target with your own private customisations, then you can run the build_setup.sh script to set up which targets you wish to support.
You can then just run the build_wip.sh script any time your code changes to have it rebuild every target you previously picked.
The script can also be run from cygwin, but does not support compiling for linux then.
(The setup script will install android+emscripten+nacl dependancies for you, so you're likely to find this an easier way to deal with those special targets).
(The setup script will install android+emscripten dependancies for you, so you're likely to find this an easier way to deal with those special targets).
(note that the android sdk can be a big download, while installing emscripten may require several hours to compile clang and about 40gb of disk space if emscripten doesn't provide prebuilt stuff for your distro).
To compile the FTEDroid port with cygwin:
make droid-rel PATH=C:\Cygwin\bin\ DROID_SDK_PATH=/cygdrive/c/Games/tools/android-sdk DROID_NDK_PATH=/cygdrive/c/Games/tools/android-ndk-r7 ANT=/cygdrive/c/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL="/cygdrive/c/Program\ Files/Java/jdk1.7.0_02/bin/" DROID_ARCH="armeabi x86" -j4 DROID_PACKSU=/cygdrive/c/games/quake/id1/pak0.pak
On linux you can omit the PATH, ANT, and JAVATOOL parts as they should already be in the path (yes I copied the above out of a batch file).
Then install the release/FTEDroid.apk file on your android device.
The DROID_PACKSU part is used to include the pak file within the android package. Ideally you would use a pk3 file instead. Also you would use something that will not violate iD software's copyright. THIS IS AN EXAMPLE ONLY. You can omit the setting entirely if you require the user to provide their own packages.
Note that there is no way to install the package with a different name at this time.
Browser versions of FTE:
The FTE browser plugin is available only in windows.
Compile with 'make npfte-rel FTE_TARGET=win32'.
This will yield an npfte.dll file.
You can 'register' this dll by running 'regsvr32 npfte.dll' at a command prompt (this is the standard way to register an activex control - any setup software should provide some mechanism to do this at install time). This will register both the netscape/firefox/chrome/opera version, and the activex/IE version of the plugin.
Note that the plugin will run the engine in a separate process and thus requires a valid fteqw.exe file in the same directory as the plugin.
If given an 'npfte.txt' file that contains the line 'relexe foo', the plugin will try to run foo.exe instead of fteqw, basedir "foo" can be used to invoke it with a different basedir. You can use this if you'd rather run the mingl or gl-only version, or if you'd like to retarget npfte to invoke a different quake engine intead. Note that different quake engines will need to support the -plugin argument and the stdin/stdout parsing for embedding - at the time of writing, no others do.
The following chunk of html can then be included on a web page to embed it. Yes. Two nested objects.
<object name="ieplug" type="text/x-quaketvident" classid="clsid:7d676c9f-fb84-40b6-b3ff-e10831557eeb" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''><object name="npplug" type="text/x-quaketvident" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''>Plugin failed to load</object></object>
Nacl version of FTE:
make gl-rel FTE_TARGET=nacl NACL_SDK_ROOT=SOMEVALIDPATHHERE BITS=32
make gl-rel FTE_TARGET=nacl NACL_SDK_ROOT=SOMEVALIDPATHHERE BITS=64
in windows compile with cygwin, not minsys.
This will give you two 'nexe' files.
You can then embed the 'fteqw.nmf' file (its entire contents can be found on the following line) with mime type 'application/x-nacl' on your page. Give it a sane width/height.
{
"program": {
"x86-64": {"url": "fteqw_x86_64.nexe"},
"x86-32": {"url": "fteqw_x86_32.nexe"}
}
}
You can object.postMessage("join foo") / qtvplay / map to tell it to switch server/map/stream.
You can read console prints via listener.addEventListener('message', handleMessage, true);
Your users will need to explicitly allow nacl use outside of google play (in about:config or whatever it is), or you will need to submit your port of fte to google play.
This stuff has separate directories
engine: FTEQW game engine itself. Both client and dedicated server.
engine/ftequake: location of old msvc6 project file. Might not work.
engine/dotnet2005: location of microsoft visual c 2005 project file. Most likely to be up to date, but also most likely to be specific to Spike's config.
engine/dotnet2010: location of microsoft visual c 2010 (express) project file. Might not work.
engine/release: the makefile writes its release-build binaries here. Intermediate files are contained within a sub-directory.
engine/debug: the makefile writes its debug-build binaries here. Intermediate files are contained within a sub-directory.
fteqtv: the qtv proxy server program.
plugins: several optional plugins that do various interesting things, though not so interesting
q3asm2: my quick hack at a qvm assembler which is not horribly slow. ignore it.
quakec: Various quakec mods. Some interesting, some not.
quakec/basemod: TimeServ's attempt to bugfix and modify vanilla quake
quakec/csaddon: ingame csqc-controlled editors. Currently contains the camquake featureset (thanks Jogi), rtlights editor, terrain editor ui, particle editor.
quakec/csqctest: my csqc sample mod. Originally created as a feature testbed for the csqc api. Useful as a reference/sample, but you perhaps don't want to use it as a base.
specs: modder/advanced documentation and samples.
Interesting commandline arguments:
-nohome disables the use of home directories. all file access will occur within the gamedir.
-basedir $FOO tells the engine where to find the game.
-game $FOO traditional NQ way to specify a mod.
-mem $FOO may still be needed on linux, at least for now. Not required on windows. Value is in MB.
+sv_public 0 stop the server from reporting to master servers.
-window override config files to force fte into windowed mode at startup. Can still be made fullscreen via the menus or console.
NQ compat cvars:
sv_port 26000 (fte listens on port 27500 by default, as its derived from quakeworld).
cl_defaultport 26000 (see above. you can always specify the port in the connect command).
sv_nomsec 1 (disables player prediction, giving authentic nq player physics).
sv_listen_nq 1 (if 0, disables NQ clients. if 1, allows qsmurfing. if 2(default), blocks qsmurfing but may have compat issues with some clients).
Limit breaking stuff:
pr_maxedicts 32767 (max ent limit)
sv_bigcoords 1 (expands coord sizes, but has compat issues)
Hexen2 / Quake2 / Quake3:
Copy the engine to your h2/q2/q3 dir, and run from there.
Alternatively, specify the h2/q2/q3 dir via -basedir.
The engine will autodetect the game from its basedir, and reconfigure as appropriate if appropriate.
Problems?
You can report problems on IRC.
Join irc.quakenet.org #fte
If you refuse to use IRC, you can instead report issues to Spike via the inside3d.com forums, or the quakeone.com forums, depending on where you're able to create an account.
Bug reports are (generally) always apreciated! :)
To compile the FTEDroid port with cygwin:
make droid-rel PATH=C:\Cygwin\bin\ DROID_SDK_PATH=/cygdrive/c/Games/tools/android-sdk DROID_NDK_PATH=/cygdrive/c/Games/tools/android-ndk-r7 ANT=/cygdrive/c/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL="/cygdrive/c/Program\ Files/Java/jdk1.7.0_02/bin/" DROID_ARCH="armeabi x86" -j4 DROID_PACKSU=/cygdrive/c/games/quake/id1/pak0.pak
On linux you can omit the PATH, ANT, and JAVATOOL parts as they should already be in the path (yes I copied the above out of a batch file).
Then install the release/FTEDroid.apk file on your android device.
The DROID_PACKSU part is used to include the pak file within the android package. Ideally you would use a pk3 file instead. Also you would use something that will not violate iD software's copyright. THIS IS AN EXAMPLE ONLY. You can omit the setting entirely if you require the user to provide their own packages.
Note that there is no way to install the package with a different name at this time.
Browser versions of FTE:
The FTE browser plugin is available only in windows.
Compile with 'make npfte-rel FTE_TARGET=win32'.
This will yield an npfte.dll file.
You can 'register' this dll by running 'regsvr32 npfte.dll' at a command prompt (this is the standard way to register an activex control - any setup software should provide some mechanism to do this at install time). This will register both the netscape/firefox/chrome/opera version, and the activex/IE version of the plugin.
Note that the plugin will run the engine in a separate process and thus requires a valid fteqw.exe file in the same directory as the plugin.
If given an 'npfte.txt' file that contains the line 'relexe foo', the plugin will try to run foo.exe instead of fteqw, basedir "foo" can be used to invoke it with a different basedir. You can use this if you'd rather run the mingl or gl-only version, or if you'd like to retarget npfte to invoke a different quake engine intead. Note that different quake engines will need to support the -plugin argument and the stdin/stdout parsing for embedding - at the time of writing, no others do.
The following chunk of html can then be included on a web page to embed it. Yes. Two nested objects.
<object name="ieplug" type="text/x-quaketvident" classid="clsid:7d676c9f-fb84-40b6-b3ff-e10831557eeb" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''><object name="npplug" type="text/x-quaketvident" width=100% height=100% ><param name="splash" value="http://127.0.0.1:27599/qtvsplash.jpg"><param name="game" value="q1"><param name="dataDownload" value=''>Plugin failed to load</object></object>
This stuff has separate directories
engine: FTEQW game engine itself. Both client and dedicated server.
engine/ftequake: location of old msvc6 project file. Might not work.
engine/dotnet2005: location of microsoft visual c 2005 project file. Most likely to be up to date, but also most likely to be specific to Spike's config.
engine/dotnet2010: location of microsoft visual c 2010 (express) project file. Might not work.
engine/release: the makefile writes its release-build binaries here. Intermediate files are contained within a sub-directory.
engine/debug: the makefile writes its debug-build binaries here. Intermediate files are contained within a sub-directory.
fteqtv: the qtv proxy server program.
plugins: several optional plugins that do various interesting things, though not so interesting
q3asm2: my quick hack at a qvm assembler which is not horribly slow. ignore it.
quakec: Various quakec mods. Some interesting, some not.
quakec/basemod: TimeServ's attempt to bugfix and modify vanilla quake
quakec/csaddon: ingame csqc-controlled editors. Currently contains the camquake featureset (thanks Jogi), rtlights editor, terrain editor ui, particle editor.
quakec/csqctest: my csqc sample mod. Originally created as a feature testbed for the csqc api. Useful as a reference/sample, but you perhaps don't want to use it as a base.
specs: modder/advanced documentation and samples.
Interesting commandline arguments:
-nohome disables the use of home directories. all file access will occur within the gamedir.
-basedir $FOO tells the engine where to find the game.
-game $FOO traditional NQ way to specify a mod.
-mem $FOO may still be needed on linux, at least for now. Not required on windows. Value is in MB.
+sv_public 0 stop the server from reporting to master servers.
-window override config files to force fte into windowed mode at startup. Can still be made fullscreen via the menus or console.
NQ compat cvars:
sv_port 26000 (fte listens on port 27500 by default, as its derived from quakeworld).
cl_defaultport 26000 (see above. you can always specify the port in the connect command).
sv_nomsec 1 (disables player prediction, giving authentic nq player physics).
sv_listen_nq 1 (if 0, disables NQ clients. if 1, allows qsmurfing. if 2(default), blocks qsmurfing but may have compat issues with some clients).
Limit breaking stuff:
pr_maxedicts 32767 (max ent limit)
sv_bigcoords 1 (expands coord sizes, but has compat issues)
Hexen2 / Quake2 / Quake3:
Copy the engine to your h2/q2/q3 dir, and run from there.
Alternatively, specify the h2/q2/q3 dir via -basedir.
The engine will autodetect the game from its basedir, and reconfigure as appropriate if appropriate.
Problems?
You can report problems on IRC.
Join irc.quakenet.org #fte
If you refuse to use IRC, you can instead report issues to Spike via the inside3d.com forums, or the quakeone.com forums, depending on where you're able to create an account.
Bug reports are (generally) always apreciated! :)

View File

@ -17,10 +17,6 @@ OSXCROSSROOT=$FTEROOT/osxcross
#emscripten defaults
EMSCRIPTENROOT=$FTEROOT/emsdk-portable
#nacl defaults
NACLROOT=$FTEROOT/nacl_sdk
NACLSDKVERSION=pepper_49
#android defaults
ANDROIDROOT=$FTEROOT/android
if [ ! -z "$(uname -o 2>&1 | grep Cygwin)" ]; then
@ -187,7 +183,6 @@ if [ "$REUSE_CONFIG" != "y" ]; then
else
echo "Skipping mac option."
fi
read -n 1 -p "Build for NaCL? [y/N] " BUILD_NACL && echo
fi
BUILD_CLEAN=${BUILD_CLEAN:-y}
@ -205,7 +200,6 @@ BUILD_SDL=${BUILD_SDL:-n}
BUILD_ANDROID=${BUILD_ANDROID:-n}
BUILD_WEB=${BUILD_WEB:-n}
BUILD_MAC=${BUILD_MAC:-n}
BUILD_NACL=${BUILD_NACL:-n}
if [ "$UID" != "0" ]; then
echo "#path config for fte build scripts" >$FTECONFIG
@ -218,9 +212,6 @@ if [ "$UID" != "0" ]; then
echo "export ANDROID_ZIPALIGN=\"$ANDROID_ZIPALIGN\"" >>$FTECONFIG
echo "EMSCRIPTENROOT=\"$EMSCRIPTENROOT\"" >>$FTECONFIG
echo "OSXCROSSROOT=\"$OSXCROSSROOT\"" >>$FTECONFIG
echo "NACLROOT=\"$NACLROOT\"" >>$FTECONFIG
echo "NACL_SDK_ROOT=\"$NACLROOT/nacl_sdk/$NACLSDKVERSION\"" >>$FTECONFIG
echo "NACLSDKVERSION=\"$NACLSDKVERSION\"" >>$FTECONFIG
echo "BUILD_CLEAN=\"$BUILD_CLEAN\"" >>$FTECONFIG
@ -238,7 +229,6 @@ if [ "$UID" != "0" ]; then
echo "BUILD_SDL=\"$BUILD_SDL\"" >>$FTECONFIG
echo "BUILD_WEB=\"$BUILD_WEB\"" >>$FTECONFIG
echo "BUILD_MAC=\"$BUILD_MAC\"" >>$FTECONFIG
echo "BUILD_NACL=\"$BUILD_NACL\"" >>$FTECONFIG
echo "TARGETS_WINDOWS=\"$TARGETS_WINDOWS\"" >>$FTECONFIG
echo "TARGETS_LINUX=\"$TARGETS_LINUX\"" >>$FTECONFIG
@ -441,16 +431,6 @@ if [ "$BUILD_MAC" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ] &
cd ~
fi
if [ "$BUILD_NACL" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up NaCL..."
mkdir -p $NACLROOT
cd $NACLROOT/..
wget -N https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip
unzip -qn nacl_sdk.zip
cd $NACLROOT
./naclsdk update $NACLSDKVERSION
fi
if [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
#initial checkout of fte's svn

View File

@ -31,8 +31,6 @@ TARGETS_LINUX="qcc-rel rel dbg vk-rel plugins-rel plugins-dbg"
TARGETS_WINDOWS="sv-rel m-rel qcc-rel qccgui-scintilla qccgui-dbg m-dbg sv-dbg plugins-dbg plugins-rel"
TARGETS_WEB="gl-rel"
########### NaCL stuff
NACL_SDK_ROOT=/opt/nacl_sdk/pepper_31/
if [ -e $FTECONFIG ]; then
. $FTECONFIG
@ -106,7 +104,6 @@ done
MAKEARGS="$THREADS $TARGET"
export NACL_SDK_ROOT
########### Emscripten / Web Stuff
export EMSDK=$EMSCRIPTENROOT
@ -264,13 +261,6 @@ fi
if [ "$BUILD_SDL_WIN64" == "y" ]; then
build "Windows 64-bit (SDL)" win64_sdl FTE_TARGET=win64_SDL $TARGETS_SDL
fi
if [ "$BUILD_NACL" != "n" ]; then
#non-pnacl is supported ONLY in chrome's store crap, but pnacl works anywhere.
# build "Native Client 64-bit" nacl_amd64 FTE_TARGET=nacl NARCH=x86_64 gl-rel
# build "Native Client 32-bit" nacl_x86 FTE_TARGET=nacl NARCH=x86_32 gl-rel
#internal compiler error build "Native Client ARM" nacl_arm FTE_TARGET=nacl NARCH=arm gl-rel
build "Native Client Portable" nacl_portable FTE_TARGET=nacl NARCH=pnacl gl-rel
fi
####build "MorphOS" morphos CFLAGS="-I$BASE/morphos/os-include/ -I$BASE/morphos/lib/ -L$BASE/morphos/lib/ -I$BASE/zlib/zlib-1.2.5 -L$BASE/zlib/zlib-1.2.5 -I./libs $WARNINGLEVEL" gl-rel mingl-rel sv-rel qcc-rel
if [ "$BUILD_MAC" != "n" ]; then
#build "MacOSX" macosx_tiger CFLAGS="-I$BASE/mac/x86/include/ -L$BASE/mac/x86/lib -I./libs" FTE_TARGET=macosx_x86 sv-rel gl-rel mingl-rel qcc-rel
@ -279,6 +269,7 @@ if [ "$BUILD_MAC" != "n" ]; then
build "MacOSX 64-bit" osx64 CC=o64-clang CXX=o64-clang++ FTE_TARGET=osx_x86_64 BITS=64 sv-rel gl-rel mingl-rel qcc-rel
fi
#third party stuff / misc crap
if [ "$BUILD_WEB" != "n" ]; then
cp $BASE/3rdparty/web/* $BUILDFOLDER/web/
@ -358,31 +349,6 @@ fi
#cp $BUILDFOLDER/macosx_tiger/fteqcc $QCCBUILDFOLDER/macosx_tiger-fteqcc
cp $BUILDFOLDER/version.txt $QCCBUILDFOLDER/version.txt
if [ "$BUILD_NACL" != "n" ]; then
mkdir -p $BUILDFOLDER/nacl
NACL=$BUILDFOLDER/nacl/fteqw.nmf
echo "{ \"program\":{" > $NACL
if [ -e "$BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe" ]; then
mv $BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe $BUILDFOLDER/nacl/fteqw-x86_64.nexe
echo " \"x86-64\":{\"url\":\"fteqw-x86_64.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe" ]; then
mv $BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe $BUILDFOLDER/nacl/fteqw-x86_32.nexe
echo " \"x86-32\":{\"url\":\"fteqw-x86_32.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_arm/fteqw-arm.nexe" ]; then
mv $BUILDFOLDER/nacl_arm/fteqw-arm.nexe $BUILDFOLDER/nacl/fteqw-arm.nexe
echo " \"arm\":{\"url\":\"fteqw-arm.nexe\"}" >> $NACL
fi
$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-finalize -o $BUILDFOLDER/nacl/fteqw.pexe $BUILDFOLDER/nacl_portable/fteqw.pexe
echo " \"portable\":{\"pnacl-translate\":{\"url\":\"fteqw.pexe\"}}" >> $NACL
echo "} }" >> $NACL
rm -rf "$BUILDFOLDER/nacl_amd64"
rm -rf "$BUILDFOLDER/nacl_x86"
rm -rf "$BUILDFOLDER/nacl_arm"
rm -rf "$BUILDFOLDER/nacl_portable"
fi
if [ "$BUILD_WIN32" != "n" ] && [ "$BUILD_WIN64" != "n" ]; then
echo Archiving output
SVNVER=$(svnversion $SVNROOT)

View File

@ -17,8 +17,6 @@
#linux->morphos (FTE_TARGET=morphos)
#linux->macosx (FTE_TARGET=macosx) or (FTE_TARGET=macosx_x86)
#linux->javascript (FTE_TARGET=web)
#linux->nacl (FTE_TARGET=nacl NARCH=x86_64) deprecated.
#win32->nacl
#linux->droid (make droid)
#win32->droid (make droid)
#if you are cross compiling, you'll need to use FTE_TARGET=mytarget
@ -574,7 +572,6 @@ HTTP_DIR=$(BASE_DIR)/http
#LIBS_DIR=$(BASE_DIR)/libs
LIBS_DIR?=.
PROGS_DIR=$(BASE_DIR)/qclib
NACL_DIR=$(BASE_DIR)/nacl
ifeq ($(NOCOMPAT),1)
NCCFLAGS=-DNOLEGACY -DOMIT_QCC
@ -717,7 +714,7 @@ ifeq ($(FTE_TARGET),SDL2)
BASE_CFLAGS+=-DLIBJPEG_STATIC -DLIBJPEG_STATIC -DLIBPNG_STATIC -DOPUS_STATIC -DSPEEX_STATIC -DFREETYPE_STATIC -DLIBVORBISFILE_STATIC
endif
VPATH := $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(SW_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(QUX_DIR) : $(PROGS_DIR) : $(NACL_DIR) : $(D3D_DIR) : $(VK_DIR) : $(BASE_DIR)/web
VPATH := $(BASE_DIR) : $(CLIENT_DIR) : $(GL_DIR) : $(SW_DIR) : $(COMMON_DIR) : $(SERVER_DIR) : $(HTTP_DIR) : $(QUX_DIR) : $(PROGS_DIR) : $(D3D_DIR) : $(VK_DIR) : $(BASE_DIR)/web
PROFILE_CFLAGS=-pg
DX7SDK=-I./libs/dxsdk7/include/
@ -1136,76 +1133,6 @@ endif
#specific targets override those defaults as needed.
#google native client
ifeq ($(FTE_TARGET),nacl)
CLIENTLDDEPS=
SERVERLDDEPS=
NARCH ?= x86_32
ifeq ($(shell uname -o 2>&1 | grep Cygwin),)
MYOS=linux
else
MYOS=win
endif
CC=
CXX=
STRIP=@echo SKIP: strip
NACLLIBC=glibc
ifeq ($(NARCH),x86_32)
CC=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-gcc -DNACL -m32
CXX=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-g++ -DNACL -m32
STRIP=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-strip
BITS=
NACLLIBS=$(NACLLIBC)_x86_32/Release
endif
ifeq ($(NARCH),x86_64)
CC=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-gcc -DNACL -m64
CXX=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-g++ -DNACL -m64
STRIP=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_x86_$(NACLLIBC)/bin/i686-nacl-strip
BITS=
NACLLIBS=$(NACLLIBC)_x86_64/Release
endif
ifeq ($(NARCH),arm)
CC=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_arm_$(NACLLIBC)/bin/arm-nacl-gcc -DNACL
CXX=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_arm_$(NACLLIBC)/bin/arm-nacl-g++ -DNACL
STRIP=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_arm_$(NACLLIBC)/bin/arm-nacl-strip
BITS=
NACLLIBS=$(NACLLIBC)_arm/Release
endif
ifeq ($(NARCH),pnacl)
CC=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_pnacl/bin/pnacl-clang -DNACL
CXX=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_pnacl/bin/pnacl-clang++ -DNACL
STRIP=$(NACL_SDK_ROOT)/toolchain/$(MYOS)_pnacl/bin/pnacl-strip
STRIPFLAGS=
BITS=
NACLLIBS=pnacl/Release
endif
BASELDFLAGS = -lm -lppapi_gles2 -lnosys -lppapi
IMAGELDFLAGS =
GL_CFLAGS=$(GLCFLAGS)
GL_CFLAGS+=-I$(realpath $(NACL_SDK_ROOT)/include)
BASELDFLAGS+=-L$(realpath $(NACL_SDK_ROOT)/lib/$(NACLLIBS))
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) sys_ppapi.o cd_null.o gl_vidppapi.o fs_ppapi.o snd_ppapi.o
GL_LDFLAGS=$(GLLDFLAGS)
M_LDFLAGS=$(GLLDFLAGS)
GLB_DIR=gl_nacl_$(NARCH)
MINGL_DIR=mingl_nacl_$(NARCH)
ifeq ($(NARCH),pnacl)
GL_EXE_NAME=../$(EXE_NAME).pexe
GLCL_EXE_NAME=../$(EXE_NAME)-cl.pexe
MINGL_EXE_NAME=../$(EXE_NAME)-mingl.pexe
else
GL_EXE_NAME=../$(EXE_NAME)-$(NARCH).nexe
GLCL_EXE_NAME=../$(EXE_NAME)-cl-$(NARCH).nexe
MINGL_EXE_NAME=../$(EXE_NAME)-mingl-$(NARCH).nexe
endif
endif
#FTE_TARGET=win32_SDL | FTE_TARGET=win64_SDL (MinGW32 + SDL | MinGW64 + SDL)
ifeq (win_SDL,$(findstring win,$(FTE_TARGET))$(findstring _SDL,$(FTE_TARGET)))
@ -2211,14 +2138,13 @@ help:
@-echo "'droid-???' (cross compiles Android package)"
@-echo "'web-???' (compiles javascript/emscripten page)"
@-echo "'npfte-???' (cross compiles QuakeTV Firefox/Netscape browser plugin)"
@-echo "'nacl-???' (cross compiles QuakeTV Firefox/Netscape browser plugin)"
@-echo ""
@-echo "Cross targets can be specified with FTE_TARGET=blah"
@-echo "linux32, linux64 specify specific x86 archs"
@-echo "SDL - Attempt to use sdl for the current target"
@-echo "win32 - Mingw compile for win32"
@-echo "vc - Attempts to use msvc8+ to compile. Note: uses profile guided optimisations. You must build+run the relevent profile target before a release target will compile properly. Debug doesn't care."
@-echo "android, npfte, nacl targets explicitly cross compile, and should generally not be given an FTE_TARGET."
@-echo "android, npfte, targets explicitly cross compile, and should generally not be given an FTE_TARGET."
clean:
-rm -f -r $(RELEASE_DIR)
@ -2266,20 +2192,6 @@ npfte-profile:
@$(MAKE) npfte-tmp TYPE=_npfte-profile OUT_DIR="$(PROFILE_DIR)/$(NPFTEB_DIR)"
#################################################
#nacl shortcut
nacl-rel:
@$(MAKE) gl-rel FTE_TARGET=nacl NARCH=x86_32
@$(MAKE) gl-rel FTE_TARGET=nacl NARCH=x86_64
@$(MAKE) gl-rel FTE_TARGET=nacl NARCH=arm
@$(MAKE) gl-rel FTE_TARGET=nacl NARCH=pnacl
nacl-dbg:
@$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=x86_32
@$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=x86_64
@$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=arm
@$(MAKE) gl-dbg FTE_TARGET=nacl NARCH=pnacl
#################################################
#webgl helpers

View File

@ -4375,7 +4375,7 @@ static void Mods_Draw(int x, int y, struct menucustom_s *c, struct emenu_s *m)
R_DrawTextField(0, y, vid.width, vid.height - y,
va(
"No games or mods known.\n"
#if defined(FTE_TARGET_WEB) || defined(NACL)
#if defined(FTE_TARGET_WEB)
"Connection issue or bad server config.\n"
#else
#ifndef ANDROID

View File

@ -1862,9 +1862,6 @@ sounddriver_t fte_weakstruct Droid_AudioOutput;
#if defined(__MORPHOS__)
sounddriver_t fte_weakstruct AHI_AudioOutput; //prefered on morphos
#endif
#ifdef NACL
extern sounddriver_t PPAPI_AudioOutput; //nacl
#endif
sounddriver_t fte_weakstruct SNDIO_AudioOutput; //bsd
//in order of preference
@ -1910,9 +1907,6 @@ static sounddriver_t *outputdrivers[] =
#endif
#if defined(__MORPHOS__)
&AHI_AudioOutput, //prefered on morphos
#endif
#ifdef NACL
&PPAPI_AudioOutput, //google's native client
#endif
&SNDIO_AudioOutput, //prefered on OpenBSD

View File

@ -52,13 +52,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define HAVE_PACKET
#endif
#ifdef NACL
#define NO_PNG
#define NO_JPEG
#define NO_OGG
#define NO_ZLIB
#endif
#ifndef MULTITHREAD
#if !defined(_WIN32) || defined(FTE_SDL) //win32 is annoying
#define NO_MULTITHREAD
@ -350,24 +343,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#define NO_OPENAL
#endif
#if defined(NACL)
//stuff is sandboxed.
#undef HAVE_TCP //websockets are not true tcp
#undef HAVE_PACKET //no udp support.
#undef SUPPORT_ICE
#undef CL_MASTER //no sockets support
#undef SV_MASTER //noone uses this anyway
#undef WEBSERVER //http server
#undef FTPSERVER //ftp server
#undef FTPCLIENT //ftp client.
#undef TCPCONNECT
#undef IRCCONNECT
#define GLSLONLY //pointless having the junk
#define GLESONLY //should reduce the conditions a little
#undef HEADLESSQUAKE
#define NO_FREETYPE
#endif
#if (defined(_MSC_VER) && (_MSC_VER < 1500)) || defined(FTE_SDL)
#undef AVAIL_WASAPI //wasapi is available in the vista sdk, while that's compatible with earlier versions, its not really expected until 2008
#endif
@ -505,7 +480,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef WEBSERVER //http server
#undef FTPSERVER //ftp server
#undef FTPCLIENT //ftp client.
#if !defined(FTE_TARGET_WEB) && !defined(NACL)
#if !defined(FTE_TARGET_WEB)
#undef WEBCLIENT
#endif
#endif
@ -612,8 +587,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PLATFORM "Web"
#define ARCH_CPU_POSTFIX "web"
#define ARCH_DL_POSTFIX ".wasm"
#elif defined(NACL)
#define PLATFORM "Nacl"
#elif defined(_WIN32_WCE)
#define PLATFORM "WinCE"
#define ARCH_DL_POSTFIX ".dll"

View File

@ -5422,7 +5422,7 @@ void COM_InitArgv (int argc, const char **argv) //not allowed to tprint
qboolean safe;
int i;
#if !defined(NACL) && !defined(FTE_TARGET_WEB)
#if !defined(FTE_TARGET_WEB)
FILE *f;
if (argv && argv[0])

View File

@ -529,7 +529,7 @@ extern char com_homepath[MAX_OSPATH];
//qofs_Make is used to 'construct' a variable of qofs_t type. this is so the code can merge two 32bit ints on old systems and use a long long type internally without generating warnings about bit shifts when qofs_t is only 32bit instead.
//#if defined(__amd64__) || defined(_AMD64_) || __WORDSIZE == 64
#if !defined(FTE_TARGET_WEB) && !defined(NACL)
#if !defined(FTE_TARGET_WEB)
#if !defined(_MSC_VER) || _MSC_VER > 1200
#define FS_64BIT
#endif

View File

@ -6303,7 +6303,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
confpath[i] = NULL;
}
#if defined(NACL) || defined(FTE_TARGET_WEB) || defined(ANDROID) || defined(WINRT)
#if defined(FTE_TARGET_WEB) || defined(ANDROID) || defined(WINRT)
//these targets are considered to be sandboxed already, and have their own app-based base directory which they will always use.
Q_strncpyz (newbasedir, host_parms.basedir, sizeof(newbasedir));
fixedbasedir = true;

View File

@ -5,7 +5,7 @@
#include <sys/stat.h>
#endif
#if !defined(NACL) && !defined(FTE_TARGET_WEB) && (!defined(_WIN32) || defined(FTE_SDL))
#if !defined(FTE_TARGET_WEB) && (!defined(_WIN32) || defined(FTE_SDL))
#ifdef WEBSVONLY
#define Z_Free free

View File

@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_ANY -1
#if defined(NACL) || defined(FTE_TARGET_WEB)
#if defined(FTE_TARGET_WEB)
#define HAVE_WEBSOCKCL
#endif

View File

@ -278,8 +278,6 @@ void Netchan_Init (void)
// pick a port value that should be nice and random
#ifdef _WIN32
port = (time(NULL)) & 0xffff;
#elif defined(NACL)
port = ((int)(getpid()) * time(NULL)) & 0xffff;
#else
port = ((int)(getpid()+getuid()*1000) * time(NULL)) & 0xffff;
#endif

View File

@ -4319,7 +4319,7 @@ typedef struct ftenet_tcp_stream_s {
//TCPC_QTV, //included for completeness. qtv handles the sockets itself, we just parse initial handshake and then pass it over (as either a tcp or tls vfsfile_t)
TCPC_QIZMO, //'qizmo\n' handshake, followed by packets prefixed with a 16bit packet length.
#ifdef HAVE_HTTPSV
TCPC_WEBSOCKETU, //utf-8 encoded data.
TCPC_WEBSOCKETU, //utf-8 encoded data. //TODO(fhomolka): Check if any targets use this, remove if not
TCPC_WEBSOCKETB, //binary encoded data (subprotocol = 'binary')
TCPC_WEBSOCKETNQ, //raw nq msg buffers with no encapsulation or handshake
TCPC_HTTPCLIENT, //we're sending a file to this victim.
@ -8062,300 +8062,6 @@ static ftenet_generic_connection_t *FTENET_WebRTC_EstablishConnection(ftenet_con
}
#endif
#ifdef NACL
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_resource.h>
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/ppb_websocket.h>
#include <ppapi/c/ppb_var.h>
#include <ppapi/c/ppb_var_array_buffer.h>
#include <ppapi/c/ppb_instance.h>
extern PPB_Core *ppb_core;
extern PPB_WebSocket *ppb_websocket_interface;
extern PPB_Var *ppb_var_interface;
extern PPB_VarArrayBuffer *ppb_vararraybuffer_interface;
extern PP_Instance pp_instance;
typedef struct
{
ftenet_generic_connection_t generic;
PP_Resource sock;
netadr_t remoteadr;
struct PP_Var incomingpacket;
qboolean havepacket;
qboolean failed;
int showerror;
} ftenet_websocket_connection_t;
static void websocketgot(void *user_data, int32_t result)
{
ftenet_websocket_connection_t *wsc = user_data;
if (result == PP_OK)
{
wsc->havepacket = true;
}
else
{
Sys_Printf("%s: %i\n", __func__, result);
wsc->failed = true;
wsc->showerror = result;
}
}
static void websocketconnected(void *user_data, int32_t result)
{
ftenet_websocket_connection_t *wsc = user_data;
if (result == PP_OK)
{
int res;
//we got a successful connection, enable reception.
struct PP_CompletionCallback ccb = {websocketgot, wsc, PP_COMPLETIONCALLBACK_FLAG_OPTIONAL};
res = ppb_websocket_interface->ReceiveMessage(wsc->sock, &wsc->incomingpacket, ccb);
if (res != PP_OK_COMPLETIONPENDING)
websocketgot(wsc, res);
}
else
{
Sys_Printf("%s: %i\n", __func__, result);
//some sort of error connecting, make it timeout now
wsc->failed = true;
wsc->showerror = result;
}
}
static void websocketclosed(void *user_data, int32_t result)
{
ftenet_websocket_connection_t *wsc = user_data;
if (wsc->havepacket)
{
wsc->havepacket = false;
ppb_var_interface->Release(wsc->incomingpacket);
}
ppb_core->ReleaseResource(wsc->sock);
// Z_Free(wsc);
}
static void FTENET_NaClWebSocket_Close(ftenet_generic_connection_t *gcon)
{
int res;
/*meant to free the memory too, in this case we get the callback to do it*/
ftenet_websocket_connection_t *wsc = (void*)gcon;
struct PP_CompletionCallback ccb = {websocketclosed, wsc, PP_COMPLETIONCALLBACK_FLAG_NONE};
ppb_websocket_interface->Close(wsc->sock, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, PP_MakeUndefined(), ccb);
}
static qboolean FTENET_NaClWebSocket_GetPacket(ftenet_generic_connection_t *gcon)
{
ftenet_websocket_connection_t *wsc = (void*)gcon;
int res;
int len = 0;
if (wsc->havepacket)
{
if (wsc->incomingpacket.type == PP_VARTYPE_ARRAY_BUFFER)
{
uint32_t length;
void *buf = ppb_vararraybuffer_interface->Map(wsc->incomingpacket);
if (buf && ppb_vararraybuffer_interface->ByteLength(wsc->incomingpacket, &length))
{
net_message.cursize = length;
memcpy(net_message_buffer, buf, length);
ppb_vararraybuffer_interface->Unmap(wsc->incomingpacket);
}
else
net_message.cursize = 0;
}
else
{
unsigned char *utf8 = (unsigned char *)ppb_var_interface->VarToUtf8(wsc->incomingpacket, &len);
unsigned char *out = (unsigned char *)net_message_buffer;
while(len && out < net_message_buffer + sizeof(net_message_buffer))
{
if ((*utf8 & 0xe0)==0xc0 && len > 1)
{
*out = ((utf8[0] & 0x1f)<<6) | ((utf8[1] & 0x3f)<<0);
utf8+=2;
len -= 2;
}
else if (*utf8 & 0x80)
{
*out = '?';
utf8++;
len -= 1;
}
else
{
*out = utf8[0];
utf8++;
len -= 1;
}
out++;
}
net_message.cursize = out - net_message_buffer;
}
memcpy(&net_from, &wsc->remoteadr, sizeof(net_from));
wsc->havepacket = false;
ppb_var_interface->Release(wsc->incomingpacket);
if (!wsc->failed)
{
//get the next one
struct PP_CompletionCallback ccb = {websocketgot, wsc, PP_COMPLETIONCALLBACK_FLAG_OPTIONAL};
res = ppb_websocket_interface->ReceiveMessage(wsc->sock, &wsc->incomingpacket, ccb);
if (res != PP_OK_COMPLETIONPENDING)
websocketgot(wsc, res);
}
if (len)
{
char adr[64];
Con_TPrintf ("Warning: Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from));
return false;
}
return true;
}
if (wsc->showerror != PP_OK)
{
switch(wsc->showerror)
{
case PP_ERROR_FAILED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_FAILED\n");
break;
case PP_ERROR_ABORTED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_ABORTED\n");
break;
case PP_ERROR_NOTSUPPORTED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_NOTSUPPORTED\n");
break;
case PP_ERROR_CONNECTION_CLOSED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_CLOSED\n");
break;
case PP_ERROR_CONNECTION_RESET:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_RESET\n");
break;
case PP_ERROR_CONNECTION_REFUSED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_REFUSED\n");
break;
case PP_ERROR_CONNECTION_ABORTED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_ABORTED\n");
break;
case PP_ERROR_CONNECTION_FAILED:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_FAILED\n");
break;
case PP_ERROR_CONNECTION_TIMEDOUT:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_CONNECTION_TIMEDOUT\n");
break;
case PP_ERROR_ADDRESS_INVALID:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_ADDRESS_INVALID\n");
break;
case PP_ERROR_ADDRESS_UNREACHABLE:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_ADDRESS_UNREACHABLE\n");
break;
case PP_ERROR_ADDRESS_IN_USE:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: PP_ERROR_ADDRESS_IN_USE\n");
break;
default:
Con_TPrintf ("FTENET_NaClWebSocket_GetPacket: error %i\n", wsc->showerror);
break;
}
wsc->showerror = PP_OK;
}
return false;
}
static neterr_t FTENET_NaClWebSocket_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t *to)
{
ftenet_websocket_connection_t *wsc = (void*)gcon;
int res;
if (wsc->failed)
return NETERR_DISCONNECTED;
#if 1
struct PP_Var str = ppb_vararraybuffer_interface->Create(length);
void *out = ppb_vararraybuffer_interface->Map(str);
if (!out)
return NETERR_MTU;
memcpy(out, data, length);
ppb_vararraybuffer_interface->Unmap(str);
#else
int outchars = 0;
unsigned char outdata[length*2+1];
unsigned char *out=outdata, *in=data;
while(length-->0)
{
if (!*in)
{
//sends 256 instead of 0
*out++ = 0xc0 | (0x100 >> 6);
*out++ = 0x80 | (0x100 & 0x3f);
}
else if (*in >= 0x80)
{
*out++ = 0xc0 | (*in >> 6);
*out++ = 0x80 | (*in & 0x3f);
}
else
*out++ = *in;
in++;
outchars++;
}
*out = 0;
struct PP_Var str = ppb_var_interface->VarFromUtf8(outdata, out - outdata);
#endif
res = ppb_websocket_interface->SendMessage(wsc->sock, str);
// Sys_Printf("FTENET_WebSocket_SendPacket: result %i\n", res);
ppb_var_interface->Release(str);
return NETERR_SENT;
}
/*nacl websockets implementation...*/
static ftenet_generic_connection_t *FTENET_WebSocket_EstablishConnection(ftenet_connections_t *col, const char *address, netadr_t adr)
{
qboolean isserver = col->islisten;
ftenet_websocket_connection_t *newcon;
PP_Resource newsocket;
if (isserver || !ppb_websocket_interface)
{
return NULL;
}
newcon = Z_Malloc(sizeof(*newcon));
if (newcon)
{
#define WEBSOCKETPROTOCOL "fteqw"
struct PP_CompletionCallback ccb = {websocketconnected, newcon, PP_COMPLETIONCALLBACK_FLAG_NONE};
newsocket = ppb_websocket_interface->Create(pp_instance);
struct PP_Var str = ppb_var_interface->VarFromUtf8(adr.address.websocketurl, strlen(adr.address.websocketurl));
struct PP_Var protocols[1] = {ppb_var_interface->VarFromUtf8(WEBSOCKETPROTOCOL, strlen(WEBSOCKETPROTOCOL))};
ppb_websocket_interface->Connect(newsocket, str, protocols, countof(protocols), ccb);
ppb_var_interface->Release(str);
ppb_var_interface->Release(protocols[0]);
Q_strncpyz(newcon->generic.name, "WebSocket", sizeof(newcon->generic.name));
newcon->generic.GetPacket = FTENET_NaClWebSocket_GetPacket;
newcon->generic.SendPacket = FTENET_NaClWebSocket_SendPacket;
newcon->generic.Close = FTENET_NaClWebSocket_Close;
newcon->generic.islisten = isserver;
newcon->generic.addrtype[0] = NA_WEBSOCKET;
newcon->generic.addrtype[1] = NA_INVALID;
newcon->generic.thesocket = INVALID_SOCKET;
newcon->sock = newsocket;
newcon->remoteadr = adr;
return &newcon->generic;
}
return NULL;
}
#endif
qboolean NET_GetRates(ftenet_connections_t *collection, float *pi, float *po, float *bi, float *bo)
{
int ctime;

View File

@ -24,8 +24,6 @@
#define AF_UNSPEC 0
// #define AF_INET 1
/*NaCl engines cannot host servers. Regular FTE servers can use the same listening tcpconnect socket to host a websocket connection*/
#define AF_WEBSOCK 342
struct sockaddr_websocket

View File

@ -6,8 +6,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fteqcc", "..\qclib\dotnet20
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtvprox", "..\..\fteqtv\dotnet2005\qtvprox.vcproj", "{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj", "{4735677B-6D5A-4BE6-A945-CB32A7282F56}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "berkplug", "..\..\plugins\berkelium\berkelium.vcproj", "{4877586B-E85B-4DF8-BCCE-59D31514D240}"

View File

@ -1588,7 +1588,7 @@ void GLR_SetupFog (void)
static void R_RenderMotionBlur(void)
{
#if !defined(ANDROID) && !defined(NACL)
#if !defined(ANDROID)
int vwidth = 1, vheight = 1;
float vs, vt, cs, ct;
shader_t *shader;

View File

@ -282,9 +282,7 @@ FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
#define GLchar char
#ifdef NACL
#undef DEBUG
#elif defined(_DEBUG) && !defined(DEBUG)
#if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG
#endif
#if defined(DEBUG)
@ -1191,7 +1189,6 @@ static qboolean GL_CheckExtensions (void *(*getglfunction) (char *name))
{ //gles has different TexImage2D arguments for specifying quality.
gl_config.arb_depth_texture = gl_config.glversion >= 3.0
|| GL_CheckExtension("GL_OES_depth_texture") //gles2
|| GL_CheckExtension("GL_CHROMIUM_depth_texture") //nacl
|| GL_CheckExtension("GL_WEBGL_depth_texture") //webgl. duh.
|| GL_CheckExtension("GL_ANGLE_depth_texture"); //gah. should just use wildcards huh (no uploads)
gl_config.arb_shadow = gl_config.glversion>=3.0;//||GL_CheckExtension("GL_EXT_shadow_samplers");

View File

@ -56,7 +56,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b); //data ===
#endif
#include <OpenGL/gl.h> //tuna says use this.
//apple really do suck.
#elif defined(NACL) || defined(FTE_TARGET_WEB)
#elif defined(FTE_TARGET_WEB)
#include <GLES2/gl2.h>
#define GLclampd GLclampf
#define GLdouble GLfloat
@ -1079,7 +1079,7 @@ void GL_SelectProgram(int program);
#ifdef _DEBUG
#if defined(__GNUC__) && !defined(NACL)
#if defined(__GNUC__)
#define checkglerror() do {int i=qglGetError(); if (i) Sys_Printf("GL Error %i detected at line %s:%i (caller %p)\n", i, __FILE__, __LINE__, __builtin_return_address(0));}while(0)
#else
#define checkglerror() do {int i=qglGetError(); if (i) Con_Printf("GL Error %i detected at line %s:%i\n", i, __FILE__, __LINE__);}while(0)

View File

@ -127,154 +127,6 @@ qboolean DL_Decide(struct dl_download *dl)
return true;
}
#elif defined(NACL)
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/pp_file_info.h>
#include <ppapi/c/ppb_file_system.h>
#include <ppapi/c/ppb_file_ref.h>
#include <ppapi/c/ppb_url_request_info.h>
#include <ppapi/c/ppb_url_response_info.h>
#include <ppapi/c/pp_var.h>
#include <ppapi/c/ppb_var.h>
#include <ppapi/c/ppb_file_io.h>
#include <ppapi/c/ppb_url_loader.h>
extern PPB_Core *ppb_core;
extern PPB_URLRequestInfo *urlrequestinfo;
extern PPB_URLLoader *urlloader;
extern PP_Instance pp_instance;
extern PPB_Var *ppb_var_interface;
struct nacl_dl {
char buffer[65536];
PP_Resource req;
};
static void readfinished(void* user_data, int32_t result)
{
struct dl_download *f = user_data;
struct nacl_dl *ctx = f->ctx;
struct PP_CompletionCallback ccb = {readfinished, f, PP_COMPLETIONCALLBACK_FLAG_NONE};
//trying to clean up
if (!ctx)
return;
// Sys_Printf("lastresult: %i\n", result);
if (result == PP_OK)
{
// Sys_Printf("%s completed\n", f->url);
ppb_core->ReleaseResource(ctx->req);
ctx->req = 0;
f->status = DL_FINISHED;
return;
}
for (; result > 0; result = urlloader->ReadResponseBody(ctx->req, ctx->buffer, sizeof(ctx->buffer), ccb))
{
//make sure the file is 'open'.
if (!f->file)
{
if (*f->localname)
{
FS_CreatePath(f->localname, dl->fsroot);
f->file = FS_OpenVFS(f->localname, "w+b", dl->fsroot);
}
else
f->file = FS_OpenTemp();
}
// Sys_Printf("write: %i\n", result);
VFS_WRITE(f->file, ctx->buffer, result);
f->completed += result;
}
// Sys_Printf("result: %i\n", result);
if (result != PP_OK_COMPLETIONPENDING)
{
Sys_Printf("file %s failed or something\n", f->url);
ppb_core->ReleaseResource(ctx->req);
ctx->req = 0;
f->status = DL_FAILED;
}
}
//urloader->open completed
static void dlstarted(void* user_data, int32_t result)
{
struct dl_download *f = user_data;
struct nacl_dl *ctx = f->ctx;
struct PP_CompletionCallback ccb = {readfinished, f, PP_COMPLETIONCALLBACK_FLAG_NONE};
readfinished(user_data, urlloader->ReadResponseBody(ctx->req, ctx->buffer, sizeof(ctx->buffer), ccb));
}
static void nadl_cleanup_cb(void* user_data, int32_t result)
{
struct nacl_dl *ctx = user_data;
if (ctx->req)
ppb_core->ReleaseResource(ctx->req);
free(ctx);
}
void NADL_Cleanup(struct dl_download *dl)
{
struct nacl_dl *ctx = dl->ctx;
//we can't free the ctx memory etc, in case the browser still has requests pending on it before it handles our close.
//so set up a callback to do it later
dl->ctx = NULL; //orphan
struct PP_CompletionCallback ccb = {nadl_cleanup_cb, ctx, PP_COMPLETIONCALLBACK_FLAG_NONE};
ppb_core->CallOnMainThread(1000, ccb, 0);
}
qboolean DL_Decide(struct dl_download *dl)
{
const char *url = dl->redir;
struct nacl_dl *ctx;
if (!*url)
url = dl->url;
if (dl->postdata)
{
NADL_Cleanup(dl);
return false; //safe to destroy it now
}
if (dl->ctx)
{
if (dl->status == DL_FAILED || dl->status == DL_FINISHED)
{
NADL_Cleanup(dl);
return false; //safe to destroy it now
}
}
else
{
PP_Resource dlri;
dl->status = DL_ACTIVE;
dl->abort = NADL_Cleanup;
dl->ctx = ctx = Z_Malloc(sizeof(*ctx));
/*everything goes via nacl, so we might as well just init that here*/
ctx->req = urlloader->Create(pp_instance);
dlri = urlrequestinfo->Create(pp_instance);
urlrequestinfo->SetProperty(dlri, PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS, ppb_var_interface->VarFromUtf8(url, strlen(url)));
urlrequestinfo->SetProperty(dlri, PP_URLREQUESTPROPERTY_URL, ppb_var_interface->VarFromUtf8(url, strlen(url)));
struct PP_CompletionCallback ccb = {dlstarted, dl, PP_COMPLETIONCALLBACK_FLAG_NONE};
urlloader->Open(ctx->req, dlri, ccb);
ppb_core->ReleaseResource(dlri);
}
return true;
}
#else
qboolean DL_Decide(struct dl_download *dl);
@ -1433,7 +1285,7 @@ qboolean DL_Decide(struct dl_download *dl)
}
return true;
}
#endif /*!defined(NACL)*/
#endif /*!defined(FTE_TARGET_WEB)*/
#ifdef MULTITHREAD
static unsigned int dlthreads = 0;

View File

@ -1,834 +0,0 @@
#include "quakedef.h"
#include "fs.h"
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/pp_file_info.h>
#include <ppapi/c/ppb_file_system.h>
#include <ppapi/c/ppb_file_ref.h>
#include <ppapi/c/ppb_url_request_info.h>
#include <ppapi/c/ppb_url_response_info.h>
#include <ppapi/c/pp_var.h>
#include <ppapi/c/ppb_var.h>
#include <ppapi/c/ppb_file_io.h>
#include <ppapi/c/ppb_url_loader.h>
extern PPB_FileIO *ppb_fileio;
extern PPB_FileRef *ppb_fileref;
extern PPB_FileSystem *ppb_filesystem;
extern PPB_Core *ppb_core;
extern PPB_URLLoader *urlloader;
extern PPB_URLRequestInfo *urlrequestinfo;
extern PPB_URLResponseInfo *urlresponseinfo;
extern PPB_Var *ppb_var_interface;
extern PP_Instance pp_instance;
#define GOOGLE_DONT_KNOW_HOW_TO_CREATE_USABLE_APIS
#ifdef GOOGLE_DONT_KNOW_HOW_TO_CREATE_USABLE_APIS
//the pepper api is flawed. deeply flawed.
//1: api calls (including various gl calls) may only be made on the main thread).
//2: the main thread may not use non-asyncronous calls.
//the recommendation to get around this is to run everything on a worker thread, but to make calls to the main thread to do the actual call, then signal the worker thread to wake up again in the main thread's callback.
//which is impractical when you have 80+ different sorts of performance-dependant gl calls.
//I can't easily put things requiring file access on another thread, if only because it would make alias/exec console commands non-synchronous
//to get around this, I instead make my own memory-only 'filesystem', populating it at startup with downloads. I *really* hope your browser/server are set to enable file caching.
//at some point I'll periodically write the data back to a persistant store/reload it at startup so saved games/configs can work
#define FSPPAPI_OpenTemp FS_OpenTemp
#define VFSPPAPI_Open VFSOS_Open
#define FSPPAPI_OpenPath VFSOS_OpenPath
typedef struct mfchunk_s
{
struct mfchunk_s *prev;
struct mfchunk_s *next;
unsigned long startpos;
unsigned int len;
char data[64];
} mfchunk_t;
typedef struct mfile_s
{
/*chunks can be trimmed only when there's no refs*/
char name[MAX_QPATH];
int refs;
int unlinked:1;
unsigned long length;
mfchunk_t *chunkhead;
mfchunk_t *chunktail;
struct mfile_s *prev;
struct mfile_s *next;
} mfile_t;
mfile_t *mfiles;
typedef struct
{
vfsfile_t funcs;
mfile_t *file;
unsigned long offset;
mfchunk_t *cchunk;
} vfsmfile_t;
typedef struct
{
searchpathfuncs_t pub;
int depth;
char rootpath[1];
} pppath_t;
qboolean FSPPAPI_Init(int *fileid)
{
return true; /*engine has all the content it needs*/
}
static int preparechunk(vfsmfile_t *f, int bytes, void **data)
{
int sz;
mfchunk_t *cnk;
if (!bytes)
{
*data = 0;
return 0;
}
if (!f->cchunk)
cnk = f->file->chunkhead;
else
{
cnk = f->cchunk;
//rewind through the chunks
while (cnk->startpos > f->offset)
cnk = cnk->prev;
}
//find the chunk that contains our start offset
while (!cnk || cnk->startpos+cnk->len <= f->offset)
{
if (!cnk)
{
sz = (bytes + sizeof(*cnk) - sizeof(cnk->data) + 4095) & ~4095;
if (sz < 65536)
sz = 65536;
cnk = malloc(sz);
memset(cnk, 0xcc, sz);
if (!cnk)
{
*data = 0;
return 0;
}
cnk->len = (sz + sizeof(cnk->data) - sizeof(*cnk));
cnk->next = NULL;
if (f->file->chunktail)
{
cnk->prev = f->file->chunktail;
cnk->prev->next = cnk;
cnk->startpos = cnk->prev->startpos + cnk->prev->len;
}
else
{
f->file->chunkhead = cnk;
cnk->prev = NULL;
cnk->startpos = 0;
}
// Sys_Printf("Allocated chunk %p: %u-%u\n", cnk, cnk->startpos, cnk->startpos + cnk->len);
f->file->chunktail = cnk;
}
else
cnk = cnk->next;
}
// Sys_Printf("Returning offset %p, %i\n", cnk, (f->offset - cnk->startpos));
// Sys_Printf("%u %u\n", f->offset, cnk->startpos);
*data = cnk->data + (f->offset - cnk->startpos);
f->cchunk = cnk;
sz = cnk->startpos + cnk->len - f->offset;
if (sz > bytes)
{
// Sys_Printf("Returning len %u\n", bytes);
return bytes;
}
// Sys_Printf("Returning len %u\n", sz);
return sz;
}
static int VFSMEM_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
{
int total = 0;
int chunklen;
void *chunkdat;
vfsmfile_t *f = (vfsmfile_t*)file;
if (bytestoread > f->file->length - f->offset)
bytestoread = f->file->length - f->offset;
while ((chunklen = preparechunk(f, bytestoread, &chunkdat)) > 0)
{
// Sys_Printf("Read %i at %u\n", chunklen, f->offset);
memcpy(buffer, chunkdat, chunklen);
buffer = (char*)buffer + chunklen;
bytestoread -= chunklen;
total += chunklen;
f->offset += chunklen;
}
// Sys_Printf("%s", (char*)buffer-total);
return total;
}
static int VFSMEM_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread)
{
int total = 0;
int chunklen;
void *chunkdat;
vfsmfile_t *f = (vfsmfile_t*)file;
while ((chunklen = preparechunk(f, bytestoread, &chunkdat)) > 0)
{
// Sys_Printf("Write %i at %u\n", chunklen, f->offset);
memcpy(chunkdat, buffer, chunklen);
buffer = (char*)buffer + chunklen;
bytestoread -= chunklen;
total += chunklen;
f->offset += chunklen;
}
if (f->file->length < f->offset)
f->file->length = f->offset;
// Sys_Printf("written: %i, file is now at %i\n", total, f->offset);
return total;
}
static qboolean VFSMEM_Seek (struct vfsfile_s *file, qofs_t pos)
{
vfsmfile_t *f = (vfsmfile_t*)file;
f->offset = pos;
return true;
}
static qofs_t VFSMEM_Tell (struct vfsfile_s *file)
{
vfsmfile_t *f = (vfsmfile_t*)file;
return f->offset;
}
static qofs_t VFSMEM_GetSize (struct vfsfile_s *file)
{
vfsmfile_t *f = (vfsmfile_t*)file;
return f->file->length;
}
static void FSPPAPI_DoUnlink(mfile_t *file)
{
mfchunk_t *cnk;
//must have no lingering references.
//free any file chunks.
while (file->chunkhead)
{
cnk = file->chunkhead->next;
free(file->chunkhead);
file->chunkhead = cnk;
}
//unlink the file so nothing else is harmed
if (file->prev)
file->prev->next = file->next;
else if (file == mfiles)
mfiles = file->next;
if (file->next)
file->next->prev = file->prev;
//and finally free the last bit of memory.
free(file);
}
static qboolean VFSMEM_Close(vfsfile_t *file)
{
vfsmfile_t *f = (vfsmfile_t*)file;
f->file->refs -= 1;
if (!f->file->refs)
if (f->file->unlinked)
FSPPAPI_DoUnlink(f->file);
free(f);
return true;
}
static void VFSMEM_Flush(struct vfsfile_s *file)
{
// vfsmfile_t *f = (vfsmfile_t*)file;
}
vfsfile_t *FSPPAPI_OpenTemp(void)
{
/*create a file which is already unlinked*/
mfile_t *f;
vfsmfile_t *r;
f = malloc(sizeof(*f));
if (!f)
return NULL;
strcpy(f->name, "some temp file");
f->refs = 0;
f->unlinked = true;
f->length = 0;
f->next = NULL;
f->prev = NULL;
f->chunkhead = NULL;
f->chunktail = NULL;
r = malloc(sizeof(*r));
if (!r)
return NULL;
r->file = f;
r->offset = 0;
r->cchunk = NULL;
f->refs++;
r->funcs.ReadBytes = VFSMEM_ReadBytes;
r->funcs.WriteBytes = VFSMEM_WriteBytes;
r->funcs.Seek = VFSMEM_Seek;
r->funcs.Tell = VFSMEM_Tell;
r->funcs.GetLen = VFSMEM_GetSize;
r->funcs.Close = VFSMEM_Close;
r->funcs.Flush = VFSMEM_Flush;
return &r->funcs;
}
qboolean Sys_remove (const char *path)
{
mfile_t *f;
for (f = mfiles; f; f = f->next)
{
if (!strcmp(f->name, path))
{
if (!f->refs)
FSPPAPI_DoUnlink(f);
else
f->unlinked = true; //can't delete it yet, but we can orphan it so we can kill it later.
return true;
}
}
return false;
}
qboolean Sys_Rename (const char *oldfname, const char *newfname)
{
mfile_t *f;
for (f = mfiles; f; f = f->next)
{
if (!strcmp(f->name, oldfname))
{
Q_strncpyz(f->name, newfname, sizeof(f->name));
return true;
}
}
return false;
}
//no concept of directories.
void Sys_mkdir (const char *path)
{
}
qboolean Sys_rmdir (const char *path)
{
return false;
}
vfsfile_t *VFSPPAPI_Open(const char *osname, const char *mode)
{
mfile_t *f;
vfsmfile_t *r;
if (strlen(osname) >= sizeof(f->name)) //yay strcpy!
return NULL;
for (f = mfiles; f; f = f->next)
{
if (!strcmp(f->name, osname))
break;
}
if (!f && (*mode == 'w' || *mode == 'a'))
{
f = malloc(sizeof(*f));
if (f)
{
strcpy(f->name, osname);
f->refs = 0;
f->unlinked = false;
f->length = 0;
f->next = mfiles;
f->prev = NULL;
if (mfiles)
mfiles->prev = f;
mfiles = f;
f->chunkhead = NULL;
f->chunktail = NULL;
}
}
if (!f)
return NULL;
r = malloc(sizeof(*r));
if (!r)
return NULL;
r->file = f;
r->offset = 0;
r->cchunk = NULL;
f->refs++;
r->funcs.ReadBytes = VFSMEM_ReadBytes;
r->funcs.WriteBytes = VFSMEM_WriteBytes;
r->funcs.Seek = VFSMEM_Seek;
r->funcs.Tell = VFSMEM_Tell;
r->funcs.GetLen = VFSMEM_GetSize;
r->funcs.Close = VFSMEM_Close;
r->funcs.Flush = VFSMEM_Flush;
return &r->funcs;
}
static vfsfile_t *FSPPAPI_OpenVFS(searchpathfuncs_t *handle, flocation_t *loc, const char *mode)
{
pppath_t *sp = (void*)handle;
char diskname[MAX_OSPATH];
//path is already cleaned, as anything that gets a valid loc needs cleaning up first.
snprintf(diskname, sizeof(diskname), "%s/%s", sp->rootpath, loc->rawname);
return VFSPPAPI_Open(diskname, mode);
}
static void FSPPAPI_ClosePath(searchpathfuncs_t *handle)
{
Z_Free(handle);
}
int Sys_EnumerateFiles (const char *rootpath, const char *match, int (*func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath)
{
int rootlen = strlen(rootpath);
char *sub;
mfile_t *f;
if (*match == '/')
match++;
for (f = mfiles; f; f = f->next)
{
sub = f->name;
if (strncmp(sub, rootpath, rootlen))
continue;
sub += rootlen;
if (*sub == '/')
sub++;
if (wildcmp(match, sub))
{
if (!func(sub, f->length, (time_t)0, parm, spath))
return false;
}
}
return true;
}
static int FSPPAPI_EnumerateFiles (searchpathfuncs_t *handle, const char *match, int (*func)(const char *, qofs_t, time_t, void *, searchpathfuncs_t *), void *parm)
{
pppath_t *sp = (void*)handle;
return Sys_EnumerateFiles(sp->rootpath, match, func, parm, handle);
}
static int FSPPAPI_RebuildFSHash(const char *filename, qofs_t filesize, time_t time, void *data, searchpathfuncs_t *handle)
{
pppath_t *sp = (void*)handle;
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, FSPPAPI_RebuildFSHash, data, handle);
return true;
}
AddFileHash(0, filename, NULL, handle);
return true;
}
static void FSPPAPI_BuildHash(searchpathfuncs_t *handle, int depth, void (QDECL *AddFileHash)(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle))
{
pppath_t *sp = (void*)handle;
Sys_EnumerateFiles(sp->rootpath, "*", FSPPAPI_RebuildFSHash, AddFileHash, handle);
}
static qboolean FSPPAPI_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
{
pppath_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 = VFSPPAPI_Open(netpath, "rb");
if (!f)
return false;
len = VFS_GETLEN(f);
VFS_CLOSE(f);
}
if (loc)
{
loc->len = len;
loc->offset = 0;
loc->fhandle = 0;
Q_strncpyz(loc->rawname, filename, sizeof(loc->rawname));
}
return true;
}
static void FSPPAPI_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, char *buffer)
{
vfsfile_t *f;
size_t result;
f = VFSPPAPI_Open(loc->rawname, "rb");
if (!f) //err...
return;
VFS_SEEK(f, loc->offset);
result = VFS_READ(f, buffer, loc->len);
if (result != loc->len)
Con_Printf("FSPPAPI_ReadFile() fread: Filename: %s, expected %i, result was %u\n",loc->rawname,(int)loc->len,(unsigned int)result);
VFS_CLOSE(f);
}
searchpathfuncs_t *QDECL FSPPAPI_OpenPath(vfsfile_t *mustbenull, const char *desc, const char *prefix)
{
pppath_t *np;
int dlen = strlen(desc);
if (mustbenull)
return NULL;
if (prefix && *prefix)
return NULL; //don't try to support this. too risky with absolute paths etc.
np = Z_Malloc(sizeof(*np) + dlen);
if (np)
{
np->depth = 0;
memcpy(np->rootpath, desc, dlen+1);
}
np->pub.fsver = FSVER;
np->pub.ClosePath = FSPPAPI_ClosePath;
np->pub.BuildHash = FSPPAPI_BuildHash;
np->pub.FindFile = FSPPAPI_FLocate;
np->pub.ReadFile = FSPPAPI_ReadFile;
np->pub.EnumerateFiles = FSPPAPI_EnumerateFiles;
np->pub.OpenVFS = FSPPAPI_OpenVFS;
//np->pub.PollChanges = FSPPAPI_PollChanges;
return &np->pub;
}
#else
//this code is old and won't work.
#define FSPPAPI_OpenTemp FS_OpenTemp
#define VFSPPAPI_Open VFSOS_Open
extern PPB_FileIO *ppb_fileio;
extern PPB_FileRef *ppb_fileref;
extern PPB_FileSystem *ppb_filesystem;
extern PPB_Core *ppb_core;
extern PP_Instance pp_instance;
static PP_Resource mainfilesystem;
struct PP_CompletionCallback nullccb;
void FSPPAPI_Init(void)
{
mainfilesystem = ppb_filesystem->Create(pp_instance, PP_FILESYSTEMTYPE_LOCALPERSISTENT);
ppb_filesystem->Open(mainfilesystem, 100*1024*1024, nullccb);
}
typedef struct {
vfsfile_t funcs;
PP_Resource handle;
int64_t offset;
} vfsppapifile_t;
static int VFSPPAPI_ReadBytes (struct vfsfile_s *file, void *buffer, int bytestoread)
{
int res;
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
res = ppb_fileio->Read(intfile->handle, intfile->offset, buffer, bytestoread, nullccb);
if (res > 0)
intfile->offset += res;
return res;
}
static int VFSPPAPI_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestoread)
{
int res;
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
res = ppb_fileio->Write(intfile->handle, intfile->offset, buffer, bytestoread, nullccb);
if (res > 0)
intfile->offset += res;
return res;
}
static qboolean VFSPPAPI_Seek (struct vfsfile_s *file, qofs_t pos)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
intfile->offset = pos;
return true;
}
static qofs_t VFSPPAPI_Tell (struct vfsfile_s *file)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
return intfile->offset;
}
static void VFSPPAPI_Flush(struct vfsfile_s *file)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
ppb_fileio->Flush(intfile->handle, nullccb);
}
static qofs_t VFSPPAPI_GetSize (struct vfsfile_s *file)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
struct PP_FileInfo fileinfo;
fileinfo.size = 0;
ppb_fileio->Query(intfile->handle, &fileinfo, nullccb);
return fileinfo.size;
}
static void VFSPPAPI_Close(vfsfile_t *file)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
ppb_fileio->Close(intfile->handle);
ppb_core->ReleaseResource(intfile->handle);
Z_Free(file);
}
#ifdef _WIN32
static void VFSPPAPI_CloseTemp(vfsfile_t *file)
{
vfsppapifile_t *intfile = (vfsppapifile_t*)file;
char *fname = (char*)(intfile+1);
ppb_fileio->Close(intfile->handle);
ppb_core->ReleaseResource(intfile->handle);
/*FIXME: add the remove somewhere*/
// _unlink(fname);
Z_Free(file);
}
#endif
vfsfile_t *FSPPAPI_OpenTemp(void)
{
return NULL;
#if 0
FILE *f;
vfsppapifile_t *file;
f = tmpfile();
if (!f)
return NULL;
file = Z_Malloc(sizeof(vfsppapifile_t));
file->funcs.Close = VFSPPAPI_Close;
file->funcs.ReadBytes = VFSPPAPI_ReadBytes;
file->funcs.WriteBytes = VFSPPAPI_WriteBytes;
file->funcs.Seek = VFSPPAPI_Seek;
file->funcs.Tell = VFSPPAPI_Tell;
file->funcs.GetLen = VFSPPAPI_GetSize;
file->funcs.Flush = VFSPPAPI_Flush;
file->handle = f;
return (vfsfile_t*)file;
#endif
}
vfsfile_t *VFSPPAPI_Open(const char *osname, const char *mode)
{
int e;
PP_Resource f;
PP_Resource fsf;
vfsppapifile_t *file;
qboolean read = !!strchr(mode, 'r');
qboolean write = !!strchr(mode, 'w');
qboolean append = !!strchr(mode, 'a');
int newmode = 0;
if (read)
newmode |= PP_FILEOPENFLAG_READ;
if (write)
newmode |= PP_FILEOPENFLAG_WRITE|PP_FILEOPENFLAG_TRUNCATE|PP_FILEOPENFLAG_CREATE;
if (append)
newmode |= PP_FILEOPENFLAG_WRITE|PP_FILEOPENFLAG_CREATE;
/*should we support w+ or r+ */
fsf = ppb_fileref->Create(mainfilesystem, osname);
f = ppb_fileio->Create(pp_instance);
e = ppb_fileio->Open(f, fsf, newmode, nullccb);
ppb_core->ReleaseResource(fsf);
if (e != PP_OK)
{
Con_Printf("unable to open %s. error %i\n", osname, e);
return NULL;
}
file = Z_Malloc(sizeof(vfsppapifile_t));
file->funcs.ReadBytes = strchr(mode, 'r')?VFSPPAPI_ReadBytes:NULL;
file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSPPAPI_WriteBytes:NULL;
file->funcs.Seek = VFSPPAPI_Seek;
file->funcs.Tell = VFSPPAPI_Tell;
file->funcs.GetLen = VFSPPAPI_GetSize;
file->funcs.Close = VFSPPAPI_Close;
file->funcs.Flush = VFSPPAPI_Flush;
file->handle = f;
if (append)
file->offset = VFSPPAPI_GetSize((vfsfile_t*)file);
else
file->offset = 0;
return (vfsfile_t*)file;
}
static vfsfile_t *FSPPAPI_OpenVFS(void *handle, flocation_t *loc, const char *mode)
{
char diskname[MAX_OSPATH];
//path is already cleaned, as anything that gets a valid loc needs cleaning up first.
snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname);
return VFSPPAPI_Open(diskname, mode);
}
static void FSPPAPI_PrintPath(searchpathfuncs_t *handle)
{
Con_Printf("%s\n", (char*)handle);
}
static void FSPPAPI_ClosePath(searchpathfuncs_t *handle)
{
Z_Free(handle);
}
static int FSPPAPI_RebuildFSHash(const char *filename, qofs_t filesize, void *data)
{
if (filename[strlen(filename)-1] == '/')
{ //this is actually a directory
char childpath[256];
Q_snprintfz(childpath, sizeof(childpath), "%s*", filename);
Sys_EnumerateFiles((char*)data, childpath, FSPPAPI_RebuildFSHash, data);
return true;
}
if (!Hash_GetInsensative(&filesystemhash, filename))
{
bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1);
strcpy((char *)(bucket+1), filename);
//#ifdef _WIN32
// Q_strlwr((char *)(bucket+1));
//#endif
Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket);
fs_hash_files++;
}
else
fs_hash_dups++;
return true;
}
static void FSPPAPI_BuildHash(searchpathfuncs_t *handle)
{
Sys_EnumerateFiles(handle, "*", FSPPAPI_RebuildFSHash, handle);
}
static qboolean FSPPAPI_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
{
int len;
char netpath[MAX_OSPATH];
Con_Printf("Locate %s\n", filename);
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",(char*)handle, filename);
{
vfsfile_t *f = VFSPPAPI_Open(netpath, "rb");
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, filename, sizeof(loc->rawname));
}
return true;
}
static void FSPPAPI_ReadFile(searchpathfuncs_t *handle, flocation_t *loc, char *buffer)
{
vfsfile_t *f;
size_t result;
f = VFSPPAPI_Open(loc->rawname, "rb");
if (!f) //err...
return;
VFS_SEEK(f, loc->offset);
result = VFS_READ(f, buffer, loc->len);
if (result != loc->len)
Con_Printf("FSPPAPI_ReadFile() fread: Filename: %s, expected %i, result was %u\n",loc->rawname,loc->len,(unsigned int)result);
VFS_CLOSE(f);
}
static int FSPPAPI_EnumerateFiles (searchpathfuncs_t *handle, const char *match, int (*func)(const char *, int, void *), void *parm)
{
return Sys_EnumerateFiles(handle, match, func, parm);
}
searchpathfuncs_t *QDECL FSPPAPI_OpenPath(vfsfile_t *mustbenull, const char *desc)
{
stdiopath_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 = FSPPAPI_ClosePath;
np->pub.BuildHash = FSPPAPI_BuildHash;
np->pub.FindFile = FSPPAPI_FLocate;
np->pub.ReadFile = FSPPAPI_ReadFile;
np->pub.EnumerateFiles = FSPPAPI_EnumerateFiles;
np->pub.OpenVFS = FSPPAPI_OpenVFS;
//np->pub.PollChanges = FSPPAPI_PollChanges;
return &np->pub;
}
#endif

View File

@ -1,297 +0,0 @@
#include "quakedef.h"
#include "glquake.h"
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/pp_completion_callback.h>
#include <ppapi/gles2/gl2ext_ppapi.h>
#include <ppapi/c/ppb_graphics_3d.h>
#include <ppapi/c/ppb_instance.h>
#include <ppapi/c/pp_errors.h>
extern PPB_Core *ppb_core;
extern PPB_GetInterface sys_gbi;
extern PPB_Graphics3D* graphics3d_interface;
extern PP_Instance pp_instance;
static PP_Resource glcontext;
extern PPB_Instance* instance_interface;
qboolean swappending;
extern cvar_t vid_vsync;
void FrameEvent(void* user_data, int32_t result);
qboolean NAGL_SwapPending(void)
{
return swappending;
}
void swap_callback(void* user_data, int32_t result)
{
if (swappending)
{
swappending = false;
FrameEvent(NULL, 0);
}
}
void GLVID_SwapBuffers(void)
{
qboolean vsync = vid_vsync.ival || !*vid_vsync.string;
struct PP_CompletionCallback ccb = { swap_callback, NULL, vsync?PP_COMPLETIONCALLBACK_FLAG_NONE:PP_COMPLETIONCALLBACK_FLAG_OPTIONAL};
glFlush();
switch(graphics3d_interface->SwapBuffers(glcontext, ccb))
{
case PP_OK_COMPLETIONPENDING:
swappending |= vsync;
break;
case PP_OK:
break;
case PP_ERROR_INPROGRESS:
Con_DPrintf("chrome still can't handle vid_wait 0. forcing vsync\n");
vid_vsync.ival = 1;
break;
default:
Con_DPrintf("unknown error on SwapBuffers call\n");
break;
}
}
qboolean GLVID_ApplyGammaRamps (unsigned int gammarampsize, unsigned short *ramps)
{
return false;
}
void *PPAPI_GetGLSymbol(char *symname)
{
int i;
static struct {char *name; void *ptr;} funcs[] =
{
#define f(n) {#n , n},
f(glActiveTexture)
f(glAttachShader)
f(glBindAttribLocation)
f(glBindBuffer)
f(glBindFramebuffer)
f(glBindRenderbuffer)
f(glBindTexture)
f(glBlendColor)
f(glBlendEquation)
f(glBlendEquationSeparate)
f(glBlendFunc)
f(glBlendFuncSeparate)
f(glBufferData)
f(glBufferSubData)
f(glCheckFramebufferStatus)
f(glClear)
f(glClearColor)
f(glClearDepthf)
f(glClearStencil)
f(glColorMask)
f(glCompileShader)
f(glCompressedTexImage2D)
f(glCompressedTexSubImage2D)
f(glCopyTexImage2D)
f(glCopyTexSubImage2D)
f(glCreateProgram)
f(glCreateShader)
f(glCullFace)
f(glDeleteBuffers)
f(glDeleteFramebuffers)
f(glDeleteProgram)
f(glDeleteRenderbuffers)
f(glDeleteShader)
f(glDeleteTextures)
f(glDepthFunc)
f(glDepthMask)
f(glDepthRangef)
f(glDetachShader)
f(glDisable)
f(glDisableVertexAttribArray)
f(glDrawArrays)
f(glDrawElements)
f(glEnable)
f(glEnableVertexAttribArray)
f(glFinish)
f(glFlush)
f(glFramebufferRenderbuffer)
f(glFramebufferTexture2D)
f(glFrontFace)
f(glGenBuffers)
f(glGenerateMipmap)
f(glGenFramebuffers)
f(glGenRenderbuffers)
f(glGenTextures)
f(glGetActiveAttrib)
f(glGetActiveUniform)
f(glGetAttachedShaders)
f(glGetAttribLocation)
f(glGetBooleanv)
f(glGetBufferParameteriv)
f(glGetError)
f(glGetFloatv)
f(glGetFramebufferAttachmentParameteriv)
f(glGetIntegerv)
f(glGetProgramiv)
f(glGetProgramInfoLog)
f(glGetRenderbufferParameteriv)
f(glGetShaderiv)
f(glGetShaderInfoLog)
f(glGetShaderPrecisionFormat)
f(glGetShaderSource)
f(glGetString)
f(glGetTexParameterfv)
f(glGetTexParameteriv)
f(glGetUniformfv)
f(glGetUniformiv)
f(glGetUniformLocation)
f(glGetVertexAttribfv)
f(glGetVertexAttribiv)
f(glGetVertexAttribPointerv)
f(glHint)
f(glIsBuffer)
f(glIsEnabled)
f(glIsFramebuffer)
f(glIsProgram)
f(glIsRenderbuffer)
f(glIsShader)
f(glIsTexture)
f(glLineWidth)
f(glLinkProgram)
f(glPixelStorei)
f(glPolygonOffset)
f(glReadPixels)
f(glReleaseShaderCompiler)
f(glRenderbufferStorage)
f(glSampleCoverage)
f(glScissor)
f(glShaderBinary)
f(glShaderSource)
f(glStencilFunc)
f(glStencilFuncSeparate)
f(glStencilMask)
f(glStencilMaskSeparate)
f(glStencilOp)
f(glStencilOpSeparate)
f(glTexImage2D)
f(glTexParameterf)
f(glTexParameterfv)
f(glTexParameteri)
f(glTexParameteriv)
f(glTexSubImage2D)
f(glUniform1f)
f(glUniform1fv)
f(glUniform1i)
f(glUniform1iv)
f(glUniform2f)
f(glUniform2fv)
f(glUniform2i)
f(glUniform2iv)
f(glUniform3f)
f(glUniform3fv)
f(glUniform3i)
f(glUniform3iv)
f(glUniform4f)
f(glUniform4fv)
f(glUniform4i)
f(glUniform4iv)
f(glUniformMatrix2fv)
f(glUniformMatrix3fv)
f(glUniformMatrix4fv)
f(glUseProgram)
f(glValidateProgram)
f(glVertexAttrib1f)
f(glVertexAttrib1fv)
f(glVertexAttrib2f)
f(glVertexAttrib2fv)
f(glVertexAttrib3f)
f(glVertexAttrib3fv)
f(glVertexAttrib4f)
f(glVertexAttrib4fv)
f(glVertexAttribPointer)
f(glViewport)
{NULL}
};
for (i = 0; funcs[i].name; i++)
{
if (!strcmp(funcs[i].name, symname))
return funcs[i].ptr;
}
return NULL;
}
void GL_Resized(int width, int height)
{
extern cvar_t vid_conautoscale, vid_conwidth;
vid.pixelwidth = width;
vid.pixelheight = height;
if (glcontext)
{
graphics3d_interface->ResizeBuffers(glcontext, width, height);
Cvar_ForceCallback(&vid_conautoscale);
Cvar_ForceCallback(&vid_conwidth);
}
}
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
{
if (!vid.pixelwidth)
vid.pixelwidth = info->width;
if (!vid.pixelheight)
vid.pixelheight = info->height;
if (vid.pixelwidth < 320)
vid.pixelwidth = 320;
if (vid.pixelheight < 200)
vid.pixelheight = 200;
int32_t attribs[] = {PP_GRAPHICS3DATTRIB_WIDTH, vid.pixelwidth,
PP_GRAPHICS3DATTRIB_HEIGHT, vid.pixelheight,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
PP_GRAPHICS3DATTRIB_SWAP_BEHAVIOR, PP_GRAPHICS3DATTRIB_BUFFER_DESTROYED,
PP_GRAPHICS3DATTRIB_NONE};
glcontext = graphics3d_interface->Create(pp_instance, 0, attribs);
glSetCurrentContextPPAPI(glcontext);
if (!instance_interface->BindGraphics(pp_instance, glcontext))
{
Con_Printf("failed to bind context\n");
return false;
}
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLVID_SwapBuffers();
// vid.pixelwidth = info->width;
// vid.pixelheight = info->height;
return GL_Init(PPAPI_GetGLSymbol);
}
void GLVID_Shutdown (void)
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLVID_SwapBuffers();
ppb_core->ReleaseResource(glcontext);
// glTerminatePPAPI();
GL_ForgetPointers();
}
void GLVID_DeInit (void)
{
GLVID_Shutdown();
}
void GLVID_Crashed(void);
void GLVID_Update (vrect_t *rects);
void GLVID_SetCaption(const char *caption)
{
}

View File

@ -1,122 +0,0 @@
#include "quakedef.h"
#include <ppapi/c/ppb_core.h>
#include <ppapi/c/ppb_audio.h>
#include <ppapi/c/ppb_audio_config.h>
extern PPB_Core *ppb_core;
extern PPB_Audio *audio_interface;
extern PPB_AudioConfig *audioconfig_interface;
extern PP_Instance pp_instance;
extern int S_GetMixerTime(soundcardinfo_t *sc);
static void PPAPI_audio_callback(void *sample_buffer, uint32_t len,
#ifdef PPB_AUDIO_INTERFACE_1_1
PP_TimeDelta latency,
#endif
void *user_data)
{
soundcardinfo_t *sc = user_data;
unsigned int framesz;
if (sc)
{
int curtime = S_GetMixerTime(sc);
framesz = sc->sn.numchannels * sc->sn.samplebytes;
//might as well dump it directly...
sc->sn.buffer = sample_buffer;
sc->sn.samples = len / sc->sn.samplebytes;
S_PaintChannels (sc, curtime + (len / framesz));
sc->sn.samples = 0;
sc->sn.buffer = NULL;
sc->snd_sent += len;
}
}
static void PPAPI_Shutdown(soundcardinfo_t *sc)
{
audio_interface->StopPlayback((PP_Resource)sc->handle);
ppb_core->ReleaseResource((PP_Resource)sc->handle);
}
static unsigned int PPAPI_GetDMAPos(soundcardinfo_t *sc)
{
sc->sn.samplepos = sc->snd_sent / sc->sn.samplebytes;
return sc->sn.samplepos;
}
static void PPAPI_UnlockBuffer(soundcardinfo_t *sc, void *buffer)
{
}
static void *PPAPI_LockBuffer(soundcardinfo_t *sc, unsigned int *sampidx)
{
*sampidx = 0;
return sc->sn.buffer;
}
static void PPAPI_Submit(soundcardinfo_t *sc, int start, int end)
{
}
static qboolean PPAPI_InitCard (soundcardinfo_t *sc, const char *cardname)
{
PP_Resource config;
int framecount;
/*I'm not aware of any limits on the number of 'devices' we can create, but virtual devices on the same physical device are utterly pointless, so don't load more than one*/
if (cardname && *cardname)
return false; //only use the default device
/*the docs say only two sample rates are allowed*/
if (sc->sn.speed <= 44100)
sc->sn.speed = 44100;
else
sc->sn.speed = 48000;
/*we can't choose these settings at all*/
sc->sn.samplebytes = 2;
sc->sn.sampleformat = QSF_S16;
sc->sn.numchannels = 2;
#ifdef PPB_AUDIO_CONFIG_INTERFACE_1_1
framecount = audioconfig_interface->RecommendSampleFrameCount(pp_instance, sc->sn.speed, 2048);
#else
framecount = audioconfig_interface->RecommendSampleFrameCount(sc->sn.speed, 2048);
#endif
/*the callback paints directly into the caller's buffer, so we don't need a separate 'dma' buffer*/
sc->selfpainting = true;
sc->sn.samples = 0; /*framecount*/
sc->sn.buffer = NULL;
sc->snd_sent = 0;
sc->sn.samplepos = 0;
sc->Submit = PPAPI_Submit;
sc->GetDMAPos = PPAPI_GetDMAPos;
sc->Lock = PPAPI_LockBuffer;
sc->Unlock = PPAPI_UnlockBuffer;
sc->Shutdown = PPAPI_Shutdown;
config = audioconfig_interface->CreateStereo16Bit(pp_instance, sc->sn.speed, framecount);
if (config)
{
sc->handle = (void*)audio_interface->Create(pp_instance, config, PPAPI_audio_callback, sc);
ppb_core->ReleaseResource(config);
if (sc->handle)
{
if (audio_interface->StartPlayback((PP_Resource)sc->handle))
return true;
}
}
return false;
}
sounddriver_t PPAPI_AudioOutput =
{
"Pepper",
PPAPI_InitCard,
NULL
};

View File

@ -1,697 +0,0 @@
#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_var_array_buffer.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_VarArrayBuffer *ppb_vararraybuffer_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)
{
}
#define SYS_CLIPBOARD_SIZE 256
static char clipboard_buffer[SYS_CLIPBOARD_SIZE] = {0};
void Sys_Clipboard_PasteText(clipboardtype_t cbt, void (*callback)(void *cb, char *utf8), void *ctx)
{
callback(ctx, clipboard_buffer);
}
void Sys_SaveClipboard(clipboardtype_t cbt, char *text)
{
Q_strncpyz(clipboard_buffer, text, SYS_CLIPBOARD_SIZE);
}
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(void)
{
}
void INS_Commands(void)
{
}
void INS_Init(void)
{
}
void INS_ReInit(void)
{
}
void INS_Shutdown(void)
{
}
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
/*
//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 *, qofs_t, 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;
}
void Sys_Sleep (double seconds)
{
struct timespec ts;
ts.tv_sec = (time_t)seconds;
seconds -= ts.tv_sec;
ts.tv_nsec = seconds * 1000000000.0;
nanosleep(&ts, NULL);
}
// 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);
COM_WorkerAbort(string);
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)
{
}
#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 const 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;
}
Sys_Printf("Starting up (Built "__DATE__ ", " __TIME__")\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:
{
int k = domkeytoquake(ppb_keyboardinputevent_interface->GetKeyCode(resource));
int u = 0;
if (k == K_TAB)
u = '\t';
if (k == K_ENTER)
u = '\r';
IN_KeyEvent(0, 1, k, u);
}
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--;
}
//these keys are handled by actual proper keys
if (c == '\t' || c == '\r')
continue;
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)
{
// ActiveApp = 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));
ppb_vararraybuffer_interface = (PPB_VarArrayBuffer*)(get_browser(PPB_VAR_ARRAY_BUFFER_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()
{
}

View File

@ -1830,7 +1830,7 @@ void PDECL PR_ExecuteProgram (pubprogfuncs_t *ppf, func_t fnum)
{
// if (pr_global_struct->self)
// ED_Print (PROG_TO_EDICT(pr_global_struct->self));
#if defined(__GNUC__) && !defined(FTE_TARGET_WEB) && !defined(NACL)
#if defined(__GNUC__) && !defined(FTE_TARGET_WEB)
externs->Printf("PR_ExecuteProgram: NULL function from exe (address %p)\n", __builtin_return_address(0));
#else
externs->Printf("PR_ExecuteProgram: NULL function from exe\n");

View File

@ -1,7 +1,7 @@
#include "progsint.h"
#include "qcc.h"
#if !defined(FTE_TARGET_WEB) && !defined(NACL) && !defined(_XBOX)
#if !defined(FTE_TARGET_WEB) && !defined(_XBOX)
#ifndef AVAIL_ZLIB
#define AVAIL_ZLIB
#endif

View File

@ -363,18 +363,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define DLL_EXT ".so"
#endif
#ifdef NACL
#define OS_STRING "nacl"
#define ID_INLINE static inline
#define PATH_SEP '/'
#define ARCH_STRING "web"
#define Q3_LITTLE_ENDIAN
#define DLL_EXT ".so"
#endif
//================================================================== Q3VM ===
#ifdef Q3_VM

View File

@ -1,4 +1,4 @@
There are multiple ways to embed a program into a browser. The 'web'/emscripten port, the nacl port, the npapi port, and the activex port.
There are multiple ways to embed a program into a browser. The 'web'/emscripten port, the npapi port, and the activex port.
Quick start with browser-servers:
(this uses webrtc, which should give low latency but is incompatible with native servers at this time.)