Initial Commit of Source

This commit is contained in:
Simon 2016-01-29 22:43:55 +00:00
parent d5460eaba0
commit 90d0c76d59
242 changed files with 208887 additions and 0 deletions

17
.gitattributes vendored Normal file
View file

@ -0,0 +1,17 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

61
.gitignore vendored Normal file
View file

@ -0,0 +1,61 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# build files
*.o
*.d
#binaries
*.so
#files created by build
*.apk
*.ap_
*.class
*.log
bin/*
gen/*
.idea/*
.gradle/*

19
QVR.iml Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="QVR" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

92
app/app.iml Normal file
View file

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="QVR" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":app" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
</content>
<orderEntry type="jdk" jdkName="Android API 16 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="cardboard" level="project" />
</component>
</module>

25
app/build.gradle Normal file
View file

@ -0,0 +1,25 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 16
buildToolsVersion '19.1.0'
defaultConfig {
applicationId "com.drbeef.qvr"
minSdkVersion 16
targetSdkVersion 19
versionCode 1
versionName '1.0.0'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
}

117
app/jni/Android.mk Normal file
View file

@ -0,0 +1,117 @@
LOCAL_PATH:= $(call my-dir)
#--------------------------------------------------------
# libquakecardboard.so
#--------------------------------------------------------
include $(CLEAR_VARS)
LOCAL_MODULE := qvr
LOCAL_CFLAGS := -std=c99
LOCAL_SRC_FILES := QVR.c
LOCAL_LDLIBS := -llog -landroid -lGLESv2 -lEGL # include default libraries
# CD objects
SRC_NOCD=cd_null.c
SRC_SND_COMMON=snd_main.c snd_mem.c snd_mix.c snd_ogg.c snd_wav.c snd_modplug.c
###### Common objects and flags #####
# Common objects
SRC_COMMON= \
bih.c \
cap_avi.c \
cap_ogg.c \
cd_shared.c \
crypto.c \
cl_collision.c \
cl_demo.c \
cl_dyntexture.c \
cl_input.c \
cl_main.c \
cl_parse.c \
cl_particles.c \
cl_screen.c \
cl_video.c \
clvm_cmds.c \
cmd.c \
collision.c \
common.c \
console.c \
csprogs.c \
curves.c \
cvar.c \
dpsoftrast.c \
dpvsimpledecode.c \
filematch.c \
fractalnoise.c \
fs.c \
ft2.c \
utf8lib.c \
gl_backend.c \
gl_draw.c \
gl_rmain.c \
gl_rsurf.c \
gl_textures.c \
hmac.c \
host.c \
host_cmd.c \
image.c \
image_png.c \
jpeg.c \
keys.c \
lhnet.c \
libcurl.c \
mathlib.c \
matrixlib.c \
mdfour.c \
menu.c \
meshqueue.c \
mod_skeletal_animatevertices_sse.c \
mod_skeletal_animatevertices_generic.c \
model_alias.c \
model_brush.c \
model_shared.c \
model_sprite.c \
mvm_cmds.c \
netconn.c \
palette.c \
polygon.c \
portals.c \
protocol.c \
prvm_cmds.c \
prvm_edict.c \
prvm_exec.c \
r_explosion.c \
r_lerpanim.c \
r_lightning.c \
r_modules.c \
r_shadow.c \
r_sky.c \
r_sprites.c \
sbar.c \
snprintf.c \
sv_demo.c \
sv_main.c \
sv_move.c \
sv_phys.c \
sv_user.c \
svbsp.c \
svvm_cmds.c \
sys_shared.c \
vid_shared.c \
view.c \
wad.c \
world.c \
zone.c
SRC_ANDROID= builddate.c sys_linux.c vid_android.c thread_pthread.c snd_android.c $(SRC_SND_COMMON) $(SRC_NOCD) $(SRC_COMMON)
LOCAL_SRC_FILES += $(SRC_ANDROID)
include $(BUILD_SHARED_LIBRARY)

22
app/jni/Application.mk Normal file
View file

@ -0,0 +1,22 @@
# Common build settings for all VR apps
# This needs to be defined to get the right header directories for egl / etc
APP_PLATFORM := android-16
APP_ABI := armeabi-v7a
# Statically link the GNU STL. This may not be safe for multi-so libraries but
# we don't know of any problems yet.
APP_STL := gnustl_static
# Make sure every shared lib includes a .note.gnu.build-id header, for crash reporting
APP_LDFLAGS := -Wl,--build-id
# Explicitly use GCC 4.8 as our toolchain. This is the 32-bit default as of
# r10d but versions as far back as r9d have 4.8. The previous default, 4.6, is
# deprecated as of r10c.
NDK_TOOLCHAIN_VERSION := 4.8
# Define the directories for $(import-module, ...) to look in
ROOT_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
NDK_MODULE_PATH :=

340
app/jni/COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

449
app/jni/QVR.c Normal file
View file

@ -0,0 +1,449 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <android/log.h>
#include <android/native_window_jni.h> // for native window JNI
#include <android/input.h>
#include <qtypes.h>
#include <quakedef.h>
#include <menu.h>
#include <cvar.h>
//All the functionality we link to in the DarkPlaces Engine implementation
extern void QC_BeginFrame();
extern void QC_DrawFrame(int eye, int x, int y);
extern void QC_EndFrame();
extern void QC_GetAudio();
extern void QC_KeyEvent(int state,int key,int character);
extern void QC_MoveEvent(float yaw, float pitch, float roll);
extern void QC_SetCallbacks(void *init_audio, void *write_audio);
extern void QC_SetResolution(int width, int height);
extern void QC_Analog(int enable,float x,float y);
extern void QC_MotionEvent(float delta, float dx, float dy);
extern int main (int argc, char **argv);
extern qboolean vrMode;
extern int bigScreen;
extern int gameAssetsDownloadStatus;
extern cvar_t cl_autocentreoffset;
extern cvar_t v_eyebufferresolution;
static JavaVM *jVM;
static jobject audioBuffer=0;
static jobject audioCallbackObj=0;
jmethodID android_initAudio;
jmethodID android_writeAudio;
jmethodID android_pauseAudio;
jmethodID android_resumeAudio;
jmethodID android_terminateAudio;
static jobject quakeCallbackObj=0;
jmethodID android_BigScreenMode;
jmethodID android_SwitchVRMode;
jmethodID android_SwitchStereoMode;
jmethodID android_Exit;
void jni_initAudio(void *buffer, int size)
{
JNIEnv *env;
jobject tmp;
(*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4);
tmp = (*env)->NewDirectByteBuffer(env, buffer, size);
audioBuffer = (jobject)(*env)->NewGlobalRef(env, tmp);
return (*env)->CallVoidMethod(env, audioCallbackObj, android_initAudio, size);
}
void jni_writeAudio(int offset, int length)
{
if (audioBuffer==0) return;
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, audioCallbackObj, android_writeAudio, audioBuffer, offset, length);
}
void jni_pauseAudio()
{
if (audioBuffer==0) return;
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, audioCallbackObj, android_pauseAudio);
}
void jni_resumeAudio()
{
if (audioBuffer==0) return;
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, audioCallbackObj, android_resumeAudio);
}
void jni_terminateAudio()
{
if (audioBuffer==0) return;
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, audioCallbackObj, android_terminateAudio);
}
void jni_BigScreenMode(int mode)
{
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, quakeCallbackObj, android_BigScreenMode, mode);
}
void jni_SwitchStereoMode(int mode)
{
JNIEnv *env;
if (((*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4))<0)
{
(*jVM)->AttachCurrentThread(jVM,&env, NULL);
}
(*env)->CallVoidMethod(env, quakeCallbackObj, android_SwitchStereoMode, mode);
}
void jni_SwitchVRMode(int mode)
{
//Force headtracking on / off depending on whether we are using VR mode
//user must then change to their preference
headtracking = vrMode > 0;
JNIEnv *env;
jobject tmp;
(*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4);
(*env)->CallVoidMethod(env, quakeCallbackObj, android_SwitchVRMode, mode);
}
void jni_Exit()
{
JNIEnv *env;
jobject tmp;
(*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4);
(*env)->CallVoidMethod(env, quakeCallbackObj, android_Exit);
}
//Retain the folder we are using
char *strGameFolder = NULL;
//Timing stuff for joypad control
static long oldtime=0;
long delta=0;
float last_joystick_x=0;
float last_joystick_y=0;
int curtime;
int Sys_Milliseconds (void)
{
struct timeval tp;
struct timezone tzp;
static int secbase;
gettimeofday(&tp, &tzp);
if (!secbase)
{
secbase = tp.tv_sec;
return tp.tv_usec/1000;
}
curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000;
return curtime;
}
int returnvalue = -1;
void QC_exit(int exitCode)
{
returnvalue = exitCode;
Host_Shutdown();
jni_Exit();
}
vec3_t hmdorientation;
int JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env;
jVM = vm;
if((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
return -1;
}
return JNI_VERSION_1_4;
}
static void UnEscapeQuotes( char *arg )
{
char *last = NULL;
while( *arg ) {
if( *arg == '"' && *last == '\\' ) {
char *c_curr = arg;
char *c_last = last;
while( *c_curr ) {
*c_last = *c_curr;
c_last = c_curr;
c_curr++;
}
*c_last = '\0';
}
last = arg;
arg++;
}
}
static int ParseCommandLine(char *cmdline, char **argv)
{
char *bufp;
char *lastp = NULL;
int argc, last_argc;
argc = last_argc = 0;
for ( bufp = cmdline; *bufp; ) {
while ( isspace(*bufp) ) {
++bufp;
}
if ( *bufp == '"' ) {
++bufp;
if ( *bufp ) {
if ( argv ) {
argv[argc] = bufp;
}
++argc;
}
while ( *bufp && ( *bufp != '"' || *lastp == '\\' ) ) {
lastp = bufp;
++bufp;
}
} else {
if ( *bufp ) {
if ( argv ) {
argv[argc] = bufp;
}
++argc;
}
while ( *bufp && ! isspace(*bufp) ) {
++bufp;
}
}
if ( *bufp ) {
if ( argv ) {
*bufp = '\0';
}
++bufp;
}
if( argv && last_argc != argc ) {
UnEscapeQuotes( argv[last_argc] );
}
last_argc = argc;
}
if ( argv ) {
argv[argc] = NULL;
}
return(argc);
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_setResolution( JNIEnv * env, jobject obj, int width, int height )
{
QC_SetResolution(width, height);
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_initialise( JNIEnv * env, jobject obj, jstring gameFolder, jstring commandLineParams )
{
static qboolean quake_initialised = false;
if (!quake_initialised)
{
jboolean iscopy;
const char * folder = (*env)->GetStringUTFChars(env, gameFolder, &iscopy);
chdir(folder);
strGameFolder = strdup(folder);
(*env)->ReleaseStringUTFChars(env, gameFolder, folder);
const char *arg = (*env)->GetStringUTFChars(env, commandLineParams, &iscopy);
char *cmdLine = NULL;
if (arg && strlen(arg))
{
cmdLine = strdup(arg);
}
(*env)->ReleaseStringUTFChars(env, commandLineParams, arg);
if (cmdLine)
{
char **argv;
int argc=0;
argv = malloc(sizeof(char*) * 255);
argc = ParseCommandLine(strdup(cmdLine), argv);
main(argc, argv);
}
else
{
int argc =1; char *argv[] = { "quake" };
main(argc, argv);
}
//Start game with credits active
MR_ToggleMenu(1);
quake_initialised = true;
}
}
#define YAW 1
#define PITCH 0
#define ROLL 2
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onNewFrame( JNIEnv * env, jobject obj, float pitch, float yaw, float roll )
{
long t=Sys_Milliseconds();
delta=t-oldtime;
oldtime=t;
if (delta>1000)
delta=1000;
QC_MotionEvent(delta, last_joystick_x, last_joystick_y);
//Save orientation
if (headtracking)
{
hmdorientation[YAW] = yaw;
hmdorientation[PITCH] = pitch;
hmdorientation[ROLL] = roll;
}
else
{
hmdorientation[YAW] = 0;
hmdorientation[PITCH] = 0;
hmdorientation[ROLL] = 0;
}
//Set move information
QC_MoveEvent(hmdorientation[YAW], hmdorientation[PITCH], hmdorientation[ROLL]);
//Set everything up
QC_BeginFrame();
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onDrawEye( JNIEnv * env, jobject obj, int eye, int x, int y )
{
QC_DrawFrame(eye, x, y);
//const GLenum depthAttachment[1] = { GL_DEPTH_ATTACHMENT };
//glInvalidateFramebuffer( GL_FRAMEBUFFER, 1, depthAttachment );
//glFlush();
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onFinishFrame( JNIEnv * env, jobject obj )
{
QC_EndFrame();
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onSwitchVRMode( JNIEnv * env, jobject obj, int mode )
{
vrMode = mode;
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onBigScreenMode( JNIEnv * env, jobject obj, int mode )
{
bigScreen = mode;
}
JNIEXPORT int JNICALL Java_com_drbeef_qvr_QVRJNILib_getCentreOffset( JNIEnv * env, jobject obj )
{
return cl_autocentreoffset.integer;
}
JNIEXPORT int JNICALL Java_com_drbeef_qvr_QVRJNILib_getEyeBufferResolution( JNIEnv * env, jobject obj )
{
return v_eyebufferresolution.integer;
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_setCentreOffset( JNIEnv * env, jobject obj, int offset )
{
//This is called only by the calculator, so only set it if it is not already set (i.e. by user or a previous run)
if (cl_autocentreoffset.integer == 0)
Cvar_SetValueQuick (&cl_autocentreoffset, offset);
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onKeyEvent( JNIEnv * env, jobject obj, int keyCode, int action, int character )
{
//Dispatch to quake
QC_KeyEvent(action == AKEY_EVENT_ACTION_DOWN ? 1 : 0, keyCode, character);
}
#define SOURCE_GAMEPAD 0x00000401
#define SOURCE_JOYSTICK 0x01000010
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onTouchEvent( JNIEnv * env, jobject obj, int source, int action, float x, float y )
{
if (source == SOURCE_JOYSTICK || source == SOURCE_GAMEPAD)
QC_Analog(true, x, y);
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_onMotionEvent( JNIEnv * env, jobject obj, int source, int action, float x, float y )
{
if (source == SOURCE_JOYSTICK || source == SOURCE_GAMEPAD)
{
last_joystick_x=x;
last_joystick_y=y;
}
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_setCallbackObjects(JNIEnv *env, jclass c, jobject obj1, jobject obj2)
{
jclass audioCallbackClass;
(*jVM)->GetEnv(jVM, (void**) &env, JNI_VERSION_1_4);
audioCallbackObj = (jobject)(*env)->NewGlobalRef(env, obj1);
audioCallbackClass = (*env)->GetObjectClass(env, audioCallbackObj);
android_initAudio = (*env)->GetMethodID(env,audioCallbackClass,"initAudio","(I)V");
android_writeAudio = (*env)->GetMethodID(env,audioCallbackClass,"writeAudio","(Ljava/nio/ByteBuffer;II)V");
android_pauseAudio = (*env)->GetMethodID(env,audioCallbackClass,"pauseAudio","()V");
android_resumeAudio = (*env)->GetMethodID(env,audioCallbackClass,"resumeAudio","()V");
android_terminateAudio = (*env)->GetMethodID(env,audioCallbackClass,"terminateAudio","()V");
jclass quakeCallbackClass;
quakeCallbackObj = (jobject)(*env)->NewGlobalRef(env, obj2);
quakeCallbackClass = (*env)->GetObjectClass(env, quakeCallbackObj);
android_BigScreenMode = (*env)->GetMethodID(env,quakeCallbackClass,"BigScreenMode","(I)V");
android_SwitchVRMode = (*env)->GetMethodID(env,quakeCallbackClass,"SwitchVRMode","(I)V");
android_SwitchStereoMode = (*env)->GetMethodID(env,quakeCallbackClass,"SwitchStereoMode","(I)V");
android_Exit = (*env)->GetMethodID(env,quakeCallbackClass,"Exit","()V");
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_requestAudioData(JNIEnv *env, jclass c, jlong handle)
{
QC_GetAudio();
}
JNIEXPORT void JNICALL Java_com_drbeef_qvr_QVRJNILib_setDownloadStatus( JNIEnv * env, jobject obj, int status )
{
gameAssetsDownloadStatus = status;
}

11
app/jni/SDLMain.h Normal file
View file

@ -0,0 +1,11 @@
/* SDLMain.m - main entry point for our Cocoa-ized SDL app
Initial Version: Darrell Walisser <dwaliss1@purdue.edu>
Non-NIB-Code & other changes: Max Horn <max@quendi.de>
Feel free to customize this file to suit your needs
*/
#import <Cocoa/Cocoa.h>
@interface SDLMain : NSObject
@end

216
app/jni/bih.c Normal file
View file

@ -0,0 +1,216 @@
// This code written in 2010 by Forest Hale (lordhavoc ghdigital com), and placed into public domain.
#include <stdlib.h>
#include <string.h>
#include "bih.h"
static int BIH_BuildNode(bih_t *bih, int numchildren, int *leaflist, float *totalmins, float *totalmaxs)
{
int i;
int j;
int longestaxis;
int axis = 0;
int nodenum;
int front = 0;
int back = 0;
bih_node_t *node;
bih_leaf_t *child;
float splitdist;
float d;
float mins[3];
float maxs[3];
float size[3];
float frontmins[3];
float frontmaxs[3];
float backmins[3];
float backmaxs[3];
// calculate bounds of children
child = bih->leafs + leaflist[0];
mins[0] = child->mins[0];
mins[1] = child->mins[1];
mins[2] = child->mins[2];
maxs[0] = child->maxs[0];
maxs[1] = child->maxs[1];
maxs[2] = child->maxs[2];
for (i = 1;i < numchildren;i++)
{
child = bih->leafs + leaflist[i];
if (mins[0] > child->mins[0]) mins[0] = child->mins[0];
if (mins[1] > child->mins[1]) mins[1] = child->mins[1];
if (mins[2] > child->mins[2]) mins[2] = child->mins[2];
if (maxs[0] < child->maxs[0]) maxs[0] = child->maxs[0];
if (maxs[1] < child->maxs[1]) maxs[1] = child->maxs[1];
if (maxs[2] < child->maxs[2]) maxs[2] = child->maxs[2];
}
size[0] = maxs[0] - mins[0];
size[1] = maxs[1] - mins[1];
size[2] = maxs[2] - mins[2];
// provide bounds to caller
totalmins[0] = mins[0];
totalmins[1] = mins[1];
totalmins[2] = mins[2];
totalmaxs[0] = maxs[0];
totalmaxs[1] = maxs[1];
totalmaxs[2] = maxs[2];
// if we run out of nodes it's the caller's fault, but don't crash
if (bih->numnodes == bih->maxnodes)
{
if (!bih->error)
bih->error = BIHERROR_OUT_OF_NODES;
return 0;
}
nodenum = bih->numnodes++;
node = bih->nodes + nodenum;
// store bounds for node
node->mins[0] = mins[0];
node->mins[1] = mins[1];
node->mins[2] = mins[2];
node->maxs[0] = maxs[0];
node->maxs[1] = maxs[1];
node->maxs[2] = maxs[2];
node->front = 0;
node->back = 0;
node->frontmin = 0;
node->backmax = 0;
memset(node->children, -1, sizeof(node->children));
// check if there are few enough children to store an unordered node
if (numchildren <= BIH_MAXUNORDEREDCHILDREN)
{
node->type = BIH_UNORDERED;
for (j = 0;j < numchildren;j++)
node->children[j] = leaflist[j];
return nodenum;
}
// pick longest axis
longestaxis = 0;
if (size[0] < size[1]) longestaxis = 1;
if (size[longestaxis] < size[2]) longestaxis = 2;
// iterate possible split axis choices, starting with the longest axis, if
// all fail it means all children have the same bounds and we simply split
// the list in half because each node can only have two children.
for (j = 0;j < 3;j++)
{
// pick an axis
axis = (longestaxis + j) % 3;
// sort children into front and back lists
splitdist = (node->mins[axis] + node->maxs[axis]) * 0.5f;
front = 0;
back = 0;
for (i = 0;i < numchildren;i++)
{
child = bih->leafs + leaflist[i];
d = (child->mins[axis] + child->maxs[axis]) * 0.5f;
if (d < splitdist)
bih->leafsortscratch[back++] = leaflist[i];
else
leaflist[front++] = leaflist[i];
}
// now copy the back ones into the space made in the leaflist for them
if (back)
memcpy(leaflist + front, bih->leafsortscratch, back*sizeof(leaflist[0]));
// if both sides have some children, it's good enough for us.
if (front && back)
break;
}
if (j == 3)
{
// somewhat common case: no good choice, divide children arbitrarily
axis = 0;
back = numchildren >> 1;
front = numchildren - back;
}
// we now have front and back children divided in leaflist...
node->type = (bih_nodetype_t)((int)BIH_SPLITX + axis);
node->front = BIH_BuildNode(bih, front, leaflist, frontmins, frontmaxs);
node->frontmin = frontmins[axis];
node->back = BIH_BuildNode(bih, back, leaflist + front, backmins, backmaxs);
node->backmax = backmaxs[axis];
return nodenum;
}
int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_node_t *nodes, int *temp_leafsort, int *temp_leafsortscratch)
{
int i;
memset(bih, 0, sizeof(*bih));
bih->numleafs = numleafs;
bih->leafs = leafs;
bih->leafsort = temp_leafsort;
bih->leafsortscratch = temp_leafsortscratch;
bih->numnodes = 0;
bih->maxnodes = maxnodes;
bih->nodes = nodes;
// clear things we intend to rebuild
memset(bih->nodes, 0, sizeof(bih->nodes[0]) * bih->maxnodes);
for (i = 0;i < bih->numleafs;i++)
bih->leafsort[i] = i;
bih->rootnode = BIH_BuildNode(bih, bih->numleafs, bih->leafsort, bih->mins, bih->maxs);
return bih->error;
}
static void BIH_GetTriangleListForBox_Node(const bih_t *bih, int nodenum, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, int *numtrianglespointer, const float *mins, const float *maxs)
{
int axis;
bih_node_t *node;
bih_leaf_t *leaf;
for(;;)
{
node = bih->nodes + nodenum;
// check if this is an unordered node (which holds an array of leaf numbers)
if (node->type == BIH_UNORDERED)
{
for (axis = 0;axis < BIH_MAXUNORDEREDCHILDREN && node->children[axis] >= 0;axis++)
{
leaf = bih->leafs + node->children[axis];
if (mins[0] > leaf->maxs[0] || maxs[0] < leaf->mins[0]
|| mins[1] > leaf->maxs[1] || maxs[1] < leaf->mins[1]
|| mins[2] > leaf->maxs[2] || maxs[2] < leaf->mins[2])
continue;
switch(leaf->type)
{
case BIH_RENDERTRIANGLE:
if (*numtrianglespointer >= maxtriangles)
{
++*numtrianglespointer; // so the caller can detect overflow
break;
}
if(trianglelist_surf)
trianglelist_surf[*numtrianglespointer] = leaf->surfaceindex;
trianglelist_idx[*numtrianglespointer] = leaf->itemindex;
++*numtrianglespointer;
break;
default:
break;
}
}
return;
}
// splitting node
axis = node->type - BIH_SPLITX;
if (mins[axis] < node->backmax)
{
if (maxs[axis] > node->frontmin)
BIH_GetTriangleListForBox_Node(bih, node->front, maxtriangles, trianglelist_idx, trianglelist_surf, numtrianglespointer, mins, maxs);
nodenum = node->back;
continue;
}
if (maxs[axis] > node->frontmin)
{
nodenum = node->front;
continue;
}
// fell between the child groups, nothing here
return;
}
}
int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, const float *mins, const float *maxs)
{
int numtriangles = 0;
BIH_GetTriangleListForBox_Node(bih, bih->rootnode, maxtriangles, trianglelist_idx, trianglelist_surf, &numtriangles, mins, maxs);
return numtriangles;
}

91
app/jni/bih.h Normal file
View file

@ -0,0 +1,91 @@
// This code written in 2010 by Forest Hale (lordhavoc ghdigital com), and placed into public domain.
// Based on information in http://zach.in.tu-clausthal.de/papers/vrst02.html (in particular vrst02_boxtree.pdf)
#ifndef BIH_H
#define BIH_H
#define BIH_MAXUNORDEREDCHILDREN 8
typedef enum biherror_e
{
BIHERROR_OK, // no error, be happy
BIHERROR_OUT_OF_NODES // could not produce complete hierarchy, maxnodes too low (should be roughly half of numleafs)
}
biherror_t;
typedef enum bih_nodetype_e
{
BIH_SPLITX = 0,
BIH_SPLITY = 1,
BIH_SPLITZ = 2,
BIH_UNORDERED = 3,
}
bih_nodetype_t;
typedef enum bih_leaftype_e
{
BIH_BRUSH = 4,
BIH_COLLISIONTRIANGLE = 5,
BIH_RENDERTRIANGLE = 6
}
bih_leaftype_t;
typedef struct bih_node_s
{
bih_nodetype_t type; // = BIH_SPLITX and similar values
// TODO: store just one float for distance, and have BIH_SPLITMINX and BIH_SPLITMAXX distinctions, to reduce memory footprint and traversal time, as described in the paper (vrst02_boxtree.pdf)
// TODO: move bounds data to parent node and remove it from leafs?
float mins[3];
float maxs[3];
// node indexes of children (always > this node's index)
int front;
int back;
// interval of children
float frontmin; // children[0]
float backmax; // children[1]
// BIH_UNORDERED uses this for a list of leafindex (all >= 0), -1 = end of list
int children[BIH_MAXUNORDEREDCHILDREN];
}
bih_node_t;
typedef struct bih_leaf_s
{
bih_leaftype_t type; // = BIH_BRUSH And similar values
float mins[3];
float maxs[3];
// data past this point is generic and entirely up to the caller...
int textureindex;
int surfaceindex;
int itemindex; // triangle or brush index
}
bih_leaf_t;
typedef struct bih_s
{
// permanent fields
// leafs are constructed by caller before calling BIH_Build
int numleafs;
bih_leaf_t *leafs;
// nodes are constructed by BIH_Build
int numnodes;
bih_node_t *nodes;
int rootnode; // 0 if numnodes > 0, -1 otherwise
// bounds calculated by BIH_Build
float mins[3];
float maxs[3];
// fields used only during BIH_Build:
int maxnodes;
int error; // set to a value if an error occurs in building (such as numnodes == maxnodes)
int *leafsort;
int *leafsortscratch;
}
bih_t;
int BIH_Build(bih_t *bih, int numleafs, bih_leaf_t *leafs, int maxnodes, bih_node_t *nodes, int *temp_leafsort, int *temp_leafsortscratch);
int BIH_GetTriangleListForBox(const bih_t *bih, int maxtriangles, int *trianglelist_idx, int *trianglelist_surf, const float *mins, const float *maxs);
#endif

321
app/jni/bspfile.h Normal file
View file

@ -0,0 +1,321 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define MAX_MAP_HULLS 16 // Q1BSP has 4, Hexen2 Q1BSP has 8, MCBSP has 16
//=============================================================================
#define BSPVERSION 29
typedef struct lump_s
{
int fileofs, filelen;
} lump_t;
#define LUMP_ENTITIES 0
#define LUMP_PLANES 1
#define LUMP_TEXTURES 2
#define LUMP_VERTEXES 3
#define LUMP_VISIBILITY 4
#define LUMP_NODES 5
#define LUMP_TEXINFO 6
#define LUMP_FACES 7
#define LUMP_LIGHTING 8
#define LUMP_CLIPNODES 9
#define LUMP_LEAFS 10
#define LUMP_MARKSURFACES 11
#define LUMP_EDGES 12
#define LUMP_SURFEDGES 13
#define LUMP_MODELS 14
#define HEADER_LUMPS 15
typedef struct hullinfo_s
{
int filehulls;
float hullsizes[MAX_MAP_HULLS][2][3];
} hullinfo_t;
typedef struct mmodel_s
{
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} mmodel_t;
/*
// WARNING: this struct does NOT match q1bsp's disk format because MAX_MAP_HULLS has been changed by Sajt's MCBSP code, this struct is only being used in memory as a result
typedef struct dmodel_s
{
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLS];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
} dmodel_t;
typedef struct dheader_s
{
int version;
lump_t lumps[HEADER_LUMPS];
} dheader_t;
typedef struct dmiptexlump_s
{
int nummiptex;
int dataofs[4]; // [nummiptex]
} dmiptexlump_t;
*/
#define MIPLEVELS 4
/*
typedef struct miptex_s
{
char name[16];
unsigned width, height;
unsigned offsets[MIPLEVELS]; // four mip maps stored
} miptex_t;
typedef struct dvertex_s
{
float point[3];
} dvertex_t;
*/
// 0-2 are axial planes
#define PLANE_X 0
#define PLANE_Y 1
#define PLANE_Z 2
// 3-5 are non-axial planes snapped to the nearest
#define PLANE_ANYX 3
#define PLANE_ANYY 4
#define PLANE_ANYZ 5
/*
typedef struct dplane_s
{
float normal[3];
float dist;
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
} dplane_t;
*/
// contents values in Q1 maps
#define CONTENTS_EMPTY -1
#define CONTENTS_SOLID -2
#define CONTENTS_WATER -3
#define CONTENTS_SLIME -4
#define CONTENTS_LAVA -5
#define CONTENTS_SKY -6
// these were #ifdef QUAKE2 in the quake source
#define CONTENTS_ORIGIN -7 // removed at csg time
#define CONTENTS_CLIP -8 // changed to contents_solid
#define CONTENTS_CURRENT_0 -9
#define CONTENTS_CURRENT_90 -10
#define CONTENTS_CURRENT_180 -11
#define CONTENTS_CURRENT_270 -12
#define CONTENTS_CURRENT_UP -13
#define CONTENTS_CURRENT_DOWN -14
//contents flags in Q2 maps
#define CONTENTSQ2_SOLID 0x00000001 // an eye is never valid in a solid
#define CONTENTSQ2_WINDOW 0x00000002 // translucent, but not watery
#define CONTENTSQ2_AUX 0x00000004
#define CONTENTSQ2_LAVA 0x00000008
#define CONTENTSQ2_SLIME 0x00000010
#define CONTENTSQ2_WATER 0x00000020
#define CONTENTSQ2_MIST 0x00000040
#define CONTENTSQ2_AREAPORTAL 0x00008000
#define CONTENTSQ2_PLAYERCLIP 0x00010000
#define CONTENTSQ2_MONSTERCLIP 0x00020000
#define CONTENTSQ2_CURRENT_0 0x00040000
#define CONTENTSQ2_CURRENT_90 0x00080000
#define CONTENTSQ2_CURRENT_180 0x00100000
#define CONTENTSQ2_CURRENT_270 0x00200000
#define CONTENTSQ2_CURRENT_UP 0x00400000
#define CONTENTSQ2_CURRENT_DOWN 0x00800000
#define CONTENTSQ2_ORIGIN 0x01000000 // removed before bsping an entity
#define CONTENTSQ2_MONSTER 0x02000000 // should never be on a brush, only in game
#define CONTENTSQ2_DEADMONSTER 0x04000000
#define CONTENTSQ2_DETAIL 0x08000000 // brushes to be added after vis leafs
#define CONTENTSQ2_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTSQ2_LADDER 0x20000000
//contents flags in Q3 maps
#define CONTENTSQ3_SOLID 0x00000001 // solid (opaque and transparent)
#define CONTENTSQ3_LAVA 0x00000008 // lava
#define CONTENTSQ3_SLIME 0x00000010 // slime
#define CONTENTSQ3_WATER 0x00000020 // water
#define CONTENTSQ3_FOG 0x00000040 // unused?
#define CONTENTSQ3_AREAPORTAL 0x00008000 // areaportal (separates areas)
#define CONTENTSQ3_PLAYERCLIP 0x00010000 // block players
#define CONTENTSQ3_MONSTERCLIP 0x00020000 // block monsters
#define CONTENTSQ3_TELEPORTER 0x00040000 // hint for Q3's bots
#define CONTENTSQ3_JUMPPAD 0x00080000 // hint for Q3's bots
#define CONTENTSQ3_CLUSTERPORTAL 0x00100000 // hint for Q3's bots
#define CONTENTSQ3_DONOTENTER 0x00200000 // hint for Q3's bots
#define CONTENTSQ3_BOTCLIP 0x00400000 // hint for Q3's bots
#define CONTENTSQ3_ORIGIN 0x01000000 // used by origin brushes to indicate origin of bmodel (removed by map compiler)
#define CONTENTSQ3_BODY 0x02000000 // used by bbox entities (should never be on a brush)
#define CONTENTSQ3_CORPSE 0x04000000 // used by dead bodies (SOLID_CORPSE in darkplaces)
#define CONTENTSQ3_DETAIL 0x08000000 // brushes that do not split the bsp tree (decorations)
#define CONTENTSQ3_STRUCTURAL 0x10000000 // brushes that split the bsp tree
#define CONTENTSQ3_TRANSLUCENT 0x20000000 // leaves surfaces that are inside for rendering
#define CONTENTSQ3_TRIGGER 0x40000000 // used by trigger entities
#define CONTENTSQ3_NODROP 0x80000000 // remove items that fall into this brush
#define SUPERCONTENTS_SOLID 0x00000001
#define SUPERCONTENTS_WATER 0x00000002
#define SUPERCONTENTS_SLIME 0x00000004
#define SUPERCONTENTS_LAVA 0x00000008
#define SUPERCONTENTS_SKY 0x00000010
#define SUPERCONTENTS_BODY 0x00000020
#define SUPERCONTENTS_CORPSE 0x00000040
#define SUPERCONTENTS_NODROP 0x00000080
#define SUPERCONTENTS_PLAYERCLIP 0x00000100
#define SUPERCONTENTS_MONSTERCLIP 0x00000200
#define SUPERCONTENTS_DONOTENTER 0x00000400
#define SUPERCONTENTS_BOTCLIP 0x00000800
#define SUPERCONTENTS_OPAQUE 0x00001000
// TODO: is there any reason to define:
// fog?
// areaportal?
// teleporter?
// jumppad?
// clusterportal?
// detail? (div0) no, game code should not be allowed to differentiate between structural and detail
// structural? (div0) no, game code should not be allowed to differentiate between structural and detail
// trigger? (div0) no, as these are always solid anyway, and that's all that matters for trigger brushes
#define SUPERCONTENTS_LIQUIDSMASK (SUPERCONTENTS_LAVA | SUPERCONTENTS_SLIME | SUPERCONTENTS_WATER)
#define SUPERCONTENTS_VISBLOCKERMASK SUPERCONTENTS_OPAQUE
/*
#define SUPERCONTENTS_DEADMONSTER 0x00000000
#define SUPERCONTENTS_CURRENT_0 0x00000000
#define SUPERCONTENTS_CURRENT_90 0x00000000
#define SUPERCONTENTS_CURRENT_180 0x00000000
#define SUPERCONTENTS_CURRENT_270 0x00000000
#define SUPERCONTENTS_CURRENT_DOWN 0x00000000
#define SUPERCONTENTS_CURRENT_UP 0x00000000
#define SUPERCONTENTS_AREAPORTAL 0x00000000
#define SUPERCONTENTS_AUX 0x00000000
#define SUPERCONTENTS_CLUSTERPORTAL 0x00000000
#define SUPERCONTENTS_DETAIL 0x00000000
#define SUPERCONTENTS_STRUCTURAL 0x00000000
#define SUPERCONTENTS_DONOTENTER 0x00000000
#define SUPERCONTENTS_JUMPPAD 0x00000000
#define SUPERCONTENTS_LADDER 0x00000000
#define SUPERCONTENTS_MONSTER 0x00000000
#define SUPERCONTENTS_MONSTERCLIP 0x00000000
#define SUPERCONTENTS_PLAYERCLIP 0x00000000
#define SUPERCONTENTS_TELEPORTER 0x00000000
#define SUPERCONTENTS_TRANSLUCENT 0x00000000
#define SUPERCONTENTS_TRIGGER 0x00000000
#define SUPERCONTENTS_WINDOW 0x00000000
*/
/*
typedef struct dnode_s
{
int planenum;
short children[2]; // negative numbers are -(leafs+1), not nodes
short mins[3]; // for sphere culling
short maxs[3];
unsigned short firstface;
unsigned short numfaces; // counting both sides
} dnode_t;
typedef struct dclipnode_s
{
int planenum;
short children[2]; // negative numbers are contents
} dclipnode_t;
typedef struct texinfo_s
{
float vecs[2][4]; // [s/t][xyz offset]
int miptex;
int flags;
} texinfo_t;
*/
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
// note that edge 0 is never used, because negative edge nums are used for
// counterclockwise use of the edge in a face
/*
typedef struct dedge_s
{
unsigned short v[2]; // vertex numbers
} dedge_t;
*/
#define MAXLIGHTMAPS 4
/*
typedef struct dface_s
{
// LordHavoc: changed from short to unsigned short for q2 support
unsigned short planenum;
short side;
int firstedge; // we must support > 64k edges
short numedges;
short texinfo;
// lighting info
unsigned char styles[MAXLIGHTMAPS];
int lightofs; // start of [numstyles*surfsize] samples
} dface_t;
*/
#define AMBIENT_WATER 0
#define AMBIENT_SKY 1
#define AMBIENT_SLIME 2
#define AMBIENT_LAVA 3
#define NUM_AMBIENTS 4 // automatic ambient sounds
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
// all other leafs need visibility info
/*
typedef struct dleaf_s
{
int contents;
int visofs; // -1 = no visibility info
short mins[3]; // for frustum culling
short maxs[3];
unsigned short firstmarksurface;
unsigned short nummarksurfaces;
unsigned char ambient_level[NUM_AMBIENTS];
} dleaf_t;
*/

19
app/jni/build.bat Normal file
View file

@ -0,0 +1,19 @@
call ndk-build V=0 -j10 NDK_DEBUG=0 %1
cd ..\libs
del libs.jar
mkdir lib
mkdir lib\armeabi-v7a
copy .\armeabi-v7a\ lib\armeabi-v7a\*
7z a -x!*.jar libs.zip .\lib*
rename libs.zip libs.jar
REM Create an archive of the source
cd ..\src\main\assets\source
del QVRSource.zip
REM exclude unnecessary files from build
7z a -r -x!.git* -x!*.o -x!*.d -x!obj -x!*.bin -x!app\build -x!app\libs -x!*.jar -x!*.so -x!*.log -x!*.jks -x!*.apk QVRSource.zip ..\..\..\..\..\*
cd ..\..\..\..\jni

12
app/jni/builddate.c Normal file
View file

@ -0,0 +1,12 @@
#define STRINGIFY2(arg) #arg
#define STRINGIFY(arg) STRINGIFY2(arg)
extern const char *buildstring;
const char *buildstring = __TIME__ " " __DATE__
#ifdef SVNREVISION
" " STRINGIFY(SVNREVISION)
#endif
#ifdef BUILDTYPE
" " STRINGIFY(BUILDTYPE)
#endif
;

720
app/jni/cap_avi.c Normal file
View file

@ -0,0 +1,720 @@
#include "quakedef.h"
#include "cap_avi.h"
#define AVI_MASTER_INDEX_SIZE 640 // GB ought to be enough for anyone
typedef struct capturevideostate_avi_formatspecific_s
{
// AVI stuff
fs_offset_t videofile_firstchunkframes_offset;
fs_offset_t videofile_totalframes_offset1;
fs_offset_t videofile_totalframes_offset2;
fs_offset_t videofile_totalsampleframes_offset;
int videofile_ix_master_audio_inuse;
fs_offset_t videofile_ix_master_audio_inuse_offset;
fs_offset_t videofile_ix_master_audio_start_offset;
int videofile_ix_master_video_inuse;
fs_offset_t videofile_ix_master_video_inuse_offset;
fs_offset_t videofile_ix_master_video_start_offset;
fs_offset_t videofile_ix_movistart;
fs_offset_t position;
qboolean canseek;
sizebuf_t riffbuffer;
unsigned char riffbufferdata[128];
sizebuf_t riffindexbuffer;
int riffstacklevel;
fs_offset_t riffstackstartoffset[4];
fs_offset_t riffstacksizehint[4];
const char *riffstackfourcc[4];
}
capturevideostate_avi_formatspecific_t;
#define LOAD_FORMATSPECIFIC_AVI() capturevideostate_avi_formatspecific_t *format = (capturevideostate_avi_formatspecific_t *) cls.capturevideo.formatspecific
static void SCR_CaptureVideo_RIFF_Start(void)
{
LOAD_FORMATSPECIFIC_AVI();
memset(&format->riffbuffer, 0, sizeof(sizebuf_t));
format->riffbuffer.maxsize = sizeof(format->riffbufferdata);
format->riffbuffer.data = format->riffbufferdata;
format->position = 0;
}
static void SCR_CaptureVideo_RIFF_Flush(void)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize > 0)
{
if (!FS_Write(cls.capturevideo.videofile, format->riffbuffer.data, format->riffbuffer.cursize))
cls.capturevideo.error = true;
format->position += format->riffbuffer.cursize;
format->riffbuffer.cursize = 0;
format->riffbuffer.overflowed = false;
}
}
static void SCR_CaptureVideo_RIFF_FlushNoIncrease(void)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize > 0)
{
if (!FS_Write(cls.capturevideo.videofile, format->riffbuffer.data, format->riffbuffer.cursize))
cls.capturevideo.error = true;
format->riffbuffer.cursize = 0;
format->riffbuffer.overflowed = false;
}
}
static void SCR_CaptureVideo_RIFF_WriteBytes(const unsigned char *data, size_t size)
{
LOAD_FORMATSPECIFIC_AVI();
SCR_CaptureVideo_RIFF_Flush();
if (!FS_Write(cls.capturevideo.videofile, data, size))
cls.capturevideo.error = true;
format->position += size;
}
static void SCR_CaptureVideo_RIFF_Write32(int n)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize + 4 > format->riffbuffer.maxsize)
SCR_CaptureVideo_RIFF_Flush();
MSG_WriteLong(&format->riffbuffer, n);
}
static void SCR_CaptureVideo_RIFF_Write16(int n)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize + 2 > format->riffbuffer.maxsize)
SCR_CaptureVideo_RIFF_Flush();
MSG_WriteShort(&format->riffbuffer, n);
}
static void SCR_CaptureVideo_RIFF_WriteFourCC(const char *chunkfourcc)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize + (int)strlen(chunkfourcc) > format->riffbuffer.maxsize)
SCR_CaptureVideo_RIFF_Flush();
MSG_WriteUnterminatedString(&format->riffbuffer, chunkfourcc);
}
static void SCR_CaptureVideo_RIFF_WriteTerminatedString(const char *string)
{
LOAD_FORMATSPECIFIC_AVI();
if (format->riffbuffer.cursize + (int)strlen(string) > format->riffbuffer.maxsize)
SCR_CaptureVideo_RIFF_Flush();
MSG_WriteString(&format->riffbuffer, string);
}
static fs_offset_t SCR_CaptureVideo_RIFF_GetPosition(void)
{
LOAD_FORMATSPECIFIC_AVI();
SCR_CaptureVideo_RIFF_Flush();
//return FS_Tell(cls.capturevideo.videofile);
return format->position;
}
static void SCR_CaptureVideo_RIFF_Push(const char *chunkfourcc, const char *listtypefourcc, fs_offset_t sizeHint)
{
LOAD_FORMATSPECIFIC_AVI();
if (listtypefourcc && sizeHint >= 0)
sizeHint += 4; // size hint is for INNER size
SCR_CaptureVideo_RIFF_WriteFourCC(chunkfourcc);
SCR_CaptureVideo_RIFF_Write32(sizeHint);
SCR_CaptureVideo_RIFF_Flush();
format->riffstacksizehint[format->riffstacklevel] = sizeHint;
format->riffstackstartoffset[format->riffstacklevel] = SCR_CaptureVideo_RIFF_GetPosition();
format->riffstackfourcc[format->riffstacklevel] = chunkfourcc;
++format->riffstacklevel;
if (listtypefourcc)
SCR_CaptureVideo_RIFF_WriteFourCC(listtypefourcc);
}
static void SCR_CaptureVideo_RIFF_Pop(void)
{
LOAD_FORMATSPECIFIC_AVI();
fs_offset_t offset, sizehint;
int x;
unsigned char sizebytes[4];
// write out the chunk size and then return to the current file position
format->riffstacklevel--;
offset = SCR_CaptureVideo_RIFF_GetPosition();
sizehint = format->riffstacksizehint[format->riffstacklevel];
x = (int)(offset - (format->riffstackstartoffset[format->riffstacklevel]));
if(x != sizehint)
{
if(sizehint != -1)
{
int i;
Con_Printf("WARNING: invalid size hint %d when writing video data (actual size: %d)\n", (int) sizehint, x);
for(i = 0; i <= format->riffstacklevel; ++i)
{
Con_Printf(" RIFF level %d = %s\n", i, format->riffstackfourcc[i]);
}
}
sizebytes[0] = (x) & 0xff;sizebytes[1] = (x >> 8) & 0xff;sizebytes[2] = (x >> 16) & 0xff;sizebytes[3] = (x >> 24) & 0xff;
if(FS_Seek(cls.capturevideo.videofile, -(x + 4), SEEK_END) >= 0)
{
FS_Write(cls.capturevideo.videofile, sizebytes, 4);
}
FS_Seek(cls.capturevideo.videofile, 0, SEEK_END);
}
if (offset & 1)
{
SCR_CaptureVideo_RIFF_WriteBytes((unsigned char *) "\0", 1);
}
}
static void GrowBuf(sizebuf_t *buf, int extralen)
{
if(buf->cursize + extralen > buf->maxsize)
{
int oldsize = buf->maxsize;
unsigned char *olddata;
olddata = buf->data;
buf->maxsize = max(buf->maxsize * 2, 4096);
buf->data = (unsigned char *) Mem_Alloc(tempmempool, buf->maxsize);
if(olddata)
{
memcpy(buf->data, olddata, oldsize);
Mem_Free(olddata);
}
}
}
static void SCR_CaptureVideo_RIFF_IndexEntry(const char *chunkfourcc, int chunksize, int flags)
{
LOAD_FORMATSPECIFIC_AVI();
if(!format->canseek)
Sys_Error("SCR_CaptureVideo_RIFF_IndexEntry called on non-seekable AVI");
if (format->riffstacklevel != 2)
Sys_Error("SCR_Capturevideo_RIFF_IndexEntry: RIFF stack level is %i (should be 2)\n", format->riffstacklevel);
GrowBuf(&format->riffindexbuffer, 16);
SCR_CaptureVideo_RIFF_Flush();
MSG_WriteUnterminatedString(&format->riffindexbuffer, chunkfourcc);
MSG_WriteLong(&format->riffindexbuffer, flags);
MSG_WriteLong(&format->riffindexbuffer, (int)FS_Tell(cls.capturevideo.videofile) - format->riffstackstartoffset[1]);
MSG_WriteLong(&format->riffindexbuffer, chunksize);
}
static void SCR_CaptureVideo_RIFF_MakeIxChunk(const char *fcc, const char *dwChunkId, fs_offset_t masteridx_counter, int *masteridx_count, fs_offset_t masteridx_start)
{
LOAD_FORMATSPECIFIC_AVI();
int nMatching;
int i;
fs_offset_t ix = SCR_CaptureVideo_RIFF_GetPosition();
fs_offset_t pos, sz;
if(!format->canseek)
Sys_Error("SCR_CaptureVideo_RIFF_MakeIxChunk called on non-seekable AVI");
if(*masteridx_count >= AVI_MASTER_INDEX_SIZE)
return;
nMatching = 0; // go through index and enumerate them
for(i = 0; i < format->riffindexbuffer.cursize; i += 16)
if(!memcmp(format->riffindexbuffer.data + i, dwChunkId, 4))
++nMatching;
sz = 2+2+4+4+4+4+4;
for(i = 0; i < format->riffindexbuffer.cursize; i += 16)
if(!memcmp(format->riffindexbuffer.data + i, dwChunkId, 4))
sz += 8;
SCR_CaptureVideo_RIFF_Push(fcc, NULL, sz);
SCR_CaptureVideo_RIFF_Write16(2); // wLongsPerEntry
SCR_CaptureVideo_RIFF_Write16(0x0100); // bIndexType=1, bIndexSubType=0
SCR_CaptureVideo_RIFF_Write32(nMatching); // nEntriesInUse
SCR_CaptureVideo_RIFF_WriteFourCC(dwChunkId); // dwChunkId
SCR_CaptureVideo_RIFF_Write32(format->videofile_ix_movistart & (fs_offset_t) 0xFFFFFFFFu);
SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) format->videofile_ix_movistart) >> 32);
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved
for(i = 0; i < format->riffindexbuffer.cursize; i += 16)
if(!memcmp(format->riffindexbuffer.data + i, dwChunkId, 4))
{
unsigned int *p = (unsigned int *) (format->riffindexbuffer.data + i);
unsigned int flags = p[1];
unsigned int rpos = p[2];
unsigned int size = p[3];
size &= ~0x80000000;
if(!(flags & 0x10)) // no keyframe?
size |= 0x80000000;
SCR_CaptureVideo_RIFF_Write32(rpos + 8);
SCR_CaptureVideo_RIFF_Write32(size);
}
SCR_CaptureVideo_RIFF_Flush();
SCR_CaptureVideo_RIFF_Pop();
pos = SCR_CaptureVideo_RIFF_GetPosition();
if(FS_Seek(cls.capturevideo.videofile, masteridx_start + 16 * *masteridx_count, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(ix & (fs_offset_t) 0xFFFFFFFFu);
SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) ix) >> 32);
SCR_CaptureVideo_RIFF_Write32(pos - ix);
SCR_CaptureVideo_RIFF_Write32(nMatching);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
if(FS_Seek(cls.capturevideo.videofile, masteridx_counter, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(++*masteridx_count);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
FS_Seek(cls.capturevideo.videofile, 0, SEEK_END); // return value doesn't matter here
}
static void SCR_CaptureVideo_RIFF_Finish(qboolean final)
{
LOAD_FORMATSPECIFIC_AVI();
// close the "movi" list
SCR_CaptureVideo_RIFF_Pop();
if(format->videofile_ix_master_video_inuse_offset)
SCR_CaptureVideo_RIFF_MakeIxChunk("ix00", "00dc", format->videofile_ix_master_video_inuse_offset, &format->videofile_ix_master_video_inuse, format->videofile_ix_master_video_start_offset);
if(format->videofile_ix_master_audio_inuse_offset)
SCR_CaptureVideo_RIFF_MakeIxChunk("ix01", "01wb", format->videofile_ix_master_audio_inuse_offset, &format->videofile_ix_master_audio_inuse, format->videofile_ix_master_audio_start_offset);
// write the idx1 chunk that we've been building while saving the frames (for old style players)
if(final && format->videofile_firstchunkframes_offset)
// TODO replace index creating by OpenDML ix##/##ix/indx chunk so it works for more than one AVI part too
{
SCR_CaptureVideo_RIFF_Push("idx1", NULL, format->riffindexbuffer.cursize);
SCR_CaptureVideo_RIFF_WriteBytes(format->riffindexbuffer.data, format->riffindexbuffer.cursize);
SCR_CaptureVideo_RIFF_Pop();
}
format->riffindexbuffer.cursize = 0;
// pop the RIFF chunk itself
while (format->riffstacklevel > 0)
SCR_CaptureVideo_RIFF_Pop();
SCR_CaptureVideo_RIFF_Flush();
if(format->videofile_firstchunkframes_offset)
{
Con_DPrintf("Finishing first chunk (%d frames)\n", cls.capturevideo.frame);
if(FS_Seek(cls.capturevideo.videofile, format->videofile_firstchunkframes_offset, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
FS_Seek(cls.capturevideo.videofile, 0, SEEK_END);
format->videofile_firstchunkframes_offset = 0;
}
else
Con_DPrintf("Finishing another chunk (%d frames)\n", cls.capturevideo.frame);
}
static void SCR_CaptureVideo_RIFF_OverflowCheck(int framesize)
{
LOAD_FORMATSPECIFIC_AVI();
fs_offset_t cursize;
//fs_offset_t curfilesize;
if (format->riffstacklevel != 2)
Sys_Error("SCR_CaptureVideo_RIFF_OverflowCheck: chunk stack leakage!\n");
if(!format->canseek)
return;
// check where we are in the file
SCR_CaptureVideo_RIFF_Flush();
cursize = SCR_CaptureVideo_RIFF_GetPosition() - format->riffstackstartoffset[0];
//curfilesize = SCR_CaptureVideo_RIFF_GetPosition();
// if this would overflow the windows limit of 1GB per RIFF chunk, we need
// to close the current RIFF chunk and open another for future frames
if (8 + cursize + framesize + format->riffindexbuffer.cursize + 8 + format->riffindexbuffer.cursize + 64 > 1<<30) // note that the Ix buffer takes less space... I just don't dare to / 2 here now... sorry, maybe later
{
SCR_CaptureVideo_RIFF_Finish(false);
// begin a new 1GB extended section of the AVI
SCR_CaptureVideo_RIFF_Push("RIFF", "AVIX", -1);
SCR_CaptureVideo_RIFF_Push("LIST", "movi", -1);
format->videofile_ix_movistart = format->riffstackstartoffset[1];
}
}
// converts from BGRA32 to I420 colorspace (identical to YV12 except chroma plane order is reversed), this colorspace is handled by the Intel(r) 4:2:0 codec on Windows
static void SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(int width, int height, unsigned char *instart, unsigned char *outstart)
{
int x, y;
int blockr, blockg, blockb;
int outoffset = (width/2)*(height/2);
unsigned char *b, *out;
// process one line at a time, and CbCr every other line at 2 pixel intervals
for (y = 0;y < height;y++)
{
// 1x1 Y
for (b = instart + (height-1-y)*width*4, out = outstart + y*width, x = 0;x < width;x++, b += 4, out++)
{
blockr = b[2];
blockg = b[1];
blockb = b[0];
*out = cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
}
if ((y & 1) == 0 && y/2 < height/2) // if h is odd, this skips the last row
{
// 2x2 Cr and Cb planes
int inpitch = width*4;
for (b = instart + (height-2-y)*width*4, out = outstart + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 8, out++)
{
blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
// Cr
out[0 ] = cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
// Cb
out[outoffset] = cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
}
}
}
}
static void SCR_CaptureVideo_Avi_VideoFrames(int num)
{
LOAD_FORMATSPECIFIC_AVI();
int x = 0, width = cls.capturevideo.width, height = cls.capturevideo.height;
unsigned char *in, *out;
// FIXME: width/height must be multiple of 2, enforce this?
in = cls.capturevideo.outbuffer;
out = cls.capturevideo.outbuffer + width*height*4;
SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(width, height, in, out);
x = width*height+(width/2)*(height/2)*2;
while(num-- > 0)
{
if(format->canseek)
{
SCR_CaptureVideo_RIFF_OverflowCheck(8 + x);
SCR_CaptureVideo_RIFF_IndexEntry("00dc", x, 0x10); // AVIIF_KEYFRAME
}
if(!format->canseek)
{
SCR_CaptureVideo_RIFF_Push("RIFF", "AVIX", 12+8+x);
SCR_CaptureVideo_RIFF_Push("LIST", "movi", 8+x);
}
SCR_CaptureVideo_RIFF_Push("00dc", NULL, x);
SCR_CaptureVideo_RIFF_WriteBytes(out, x);
SCR_CaptureVideo_RIFF_Pop();
if(!format->canseek)
{
SCR_CaptureVideo_RIFF_Pop();
SCR_CaptureVideo_RIFF_Pop();
}
}
}
static void SCR_CaptureVideo_Avi_EndVideo(void)
{
LOAD_FORMATSPECIFIC_AVI();
if(format->canseek)
{
// close any open chunks
SCR_CaptureVideo_RIFF_Finish(true);
// go back and fix the video frames and audio samples fields
if(format->videofile_totalframes_offset1)
if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalframes_offset1, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
if(format->videofile_totalframes_offset2)
if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalframes_offset2, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.frame);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
if (cls.capturevideo.soundrate)
{
if(format->videofile_totalsampleframes_offset)
if(FS_Seek(cls.capturevideo.videofile, format->videofile_totalsampleframes_offset, SEEK_SET) >= 0)
{
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundsampleframe);
SCR_CaptureVideo_RIFF_FlushNoIncrease();
}
}
}
if (format->riffindexbuffer.data)
{
Mem_Free(format->riffindexbuffer.data);
format->riffindexbuffer.data = NULL;
}
FS_Close(cls.capturevideo.videofile);
cls.capturevideo.videofile = NULL;
Mem_Free(format);
}
static void SCR_CaptureVideo_Avi_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length)
{
LOAD_FORMATSPECIFIC_AVI();
int x;
unsigned char bufstereo16le[PAINTBUFFER_SIZE * 4];
unsigned char* out_ptr;
size_t i;
// write the sound buffer as little endian 16bit interleaved stereo
for(i = 0, out_ptr = bufstereo16le; i < length; i++, out_ptr += 4)
{
int n0, n1;
n0 = paintbuffer[i].sample[0] * 32768.0f;
n0 = bound(-32768, n0, 32767);
out_ptr[0] = (unsigned char)n0;
out_ptr[1] = (unsigned char)(n0 >> 8);
n1 = paintbuffer[i].sample[1] * 32768.0f;
n1 = bound(-32768, n1, 32767);
out_ptr[2] = (unsigned char)n1;
out_ptr[3] = (unsigned char)(n1 >> 8);
}
x = length*4;
if(format->canseek)
{
SCR_CaptureVideo_RIFF_OverflowCheck(8 + x);
SCR_CaptureVideo_RIFF_IndexEntry("01wb", x, 0x10); // AVIIF_KEYFRAME
}
if(!format->canseek)
{
SCR_CaptureVideo_RIFF_Push("RIFF", "AVIX", 12+8+x);
SCR_CaptureVideo_RIFF_Push("LIST", "movi", 8+x);
}
SCR_CaptureVideo_RIFF_Push("01wb", NULL, x);
SCR_CaptureVideo_RIFF_WriteBytes(bufstereo16le, x);
SCR_CaptureVideo_RIFF_Pop();
if(!format->canseek)
{
SCR_CaptureVideo_RIFF_Pop();
SCR_CaptureVideo_RIFF_Pop();
}
}
void SCR_CaptureVideo_Avi_BeginVideo(void)
{
int width = cls.capturevideo.width;
int height = cls.capturevideo.height;
int n, d;
unsigned int i;
double aspect;
char vabuf[1024];
aspect = vid.width / (vid.height * vid_pixelheight.value);
cls.capturevideo.format = CAPTUREVIDEOFORMAT_AVI_I420;
cls.capturevideo.formatextension = "avi";
cls.capturevideo.videofile = FS_OpenRealFile(va(vabuf, sizeof(vabuf), "%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
cls.capturevideo.endvideo = SCR_CaptureVideo_Avi_EndVideo;
cls.capturevideo.videoframes = SCR_CaptureVideo_Avi_VideoFrames;
cls.capturevideo.soundframe = SCR_CaptureVideo_Avi_SoundFrame;
cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_avi_formatspecific_t));
{
LOAD_FORMATSPECIFIC_AVI();
format->canseek = (FS_Seek(cls.capturevideo.videofile, 0, SEEK_SET) == 0);
SCR_CaptureVideo_RIFF_Start();
// enclosing RIFF chunk (there can be multiple of these in >1GB files, the later ones are "AVIX" instead of "AVI " and have no header/stream info)
SCR_CaptureVideo_RIFF_Push("RIFF", "AVI ", format->canseek ? -1 : 12+(8+56+12+(12+52+8+40+8+68)+(cls.capturevideo.soundrate?(12+12+52+8+18):0)+12+(8+4))+12+(8+(((int) strlen(engineversion) | 1) + 1))+12);
// AVI main header
SCR_CaptureVideo_RIFF_Push("LIST", "hdrl", format->canseek ? -1 : 8+56+12+(12+52+8+40+8+68)+(cls.capturevideo.soundrate?(12+12+52+8+18):0)+12+(8+4));
SCR_CaptureVideo_RIFF_Push("avih", NULL, 56);
SCR_CaptureVideo_RIFF_Write32((int)(1000000.0 / (cls.capturevideo.framerate / cls.capturevideo.framestep))); // microseconds per frame
SCR_CaptureVideo_RIFF_Write32(0); // max bytes per second
SCR_CaptureVideo_RIFF_Write32(0); // padding granularity
SCR_CaptureVideo_RIFF_Write32(0x910); // flags (AVIF_HASINDEX | AVIF_ISINTERLEAVED | AVIF_TRUSTCKTYPE)
format->videofile_firstchunkframes_offset = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0); // total frames
SCR_CaptureVideo_RIFF_Write32(0); // initial frames
if (cls.capturevideo.soundrate)
SCR_CaptureVideo_RIFF_Write32(2); // number of streams
else
SCR_CaptureVideo_RIFF_Write32(1); // number of streams
SCR_CaptureVideo_RIFF_Write32(0); // suggested buffer size
SCR_CaptureVideo_RIFF_Write32(width); // width
SCR_CaptureVideo_RIFF_Write32(height); // height
SCR_CaptureVideo_RIFF_Write32(0); // reserved[0]
SCR_CaptureVideo_RIFF_Write32(0); // reserved[1]
SCR_CaptureVideo_RIFF_Write32(0); // reserved[2]
SCR_CaptureVideo_RIFF_Write32(0); // reserved[3]
SCR_CaptureVideo_RIFF_Pop();
// video stream info
SCR_CaptureVideo_RIFF_Push("LIST", "strl", format->canseek ? -1 : 12+52+8+40+8+68);
SCR_CaptureVideo_RIFF_Push("strh", "vids", 52);
SCR_CaptureVideo_RIFF_WriteFourCC("I420"); // stream fourcc (I420 colorspace, uncompressed)
SCR_CaptureVideo_RIFF_Write32(0); // flags
SCR_CaptureVideo_RIFF_Write16(0); // priority
SCR_CaptureVideo_RIFF_Write16(0); // language
SCR_CaptureVideo_RIFF_Write32(0); // initial frames
// find an ideal divisor for the framerate
FindFraction(cls.capturevideo.framerate / cls.capturevideo.framestep, &n, &d, 1000);
SCR_CaptureVideo_RIFF_Write32(d); // samples/second divisor
SCR_CaptureVideo_RIFF_Write32(n); // samples/second multiplied by divisor
SCR_CaptureVideo_RIFF_Write32(0); // start
format->videofile_totalframes_offset1 = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0xFFFFFFFF); // length
SCR_CaptureVideo_RIFF_Write32(width*height+(width/2)*(height/2)*2); // suggested buffer size
SCR_CaptureVideo_RIFF_Write32(0); // quality
SCR_CaptureVideo_RIFF_Write32(0); // sample size
SCR_CaptureVideo_RIFF_Write16(0); // frame left
SCR_CaptureVideo_RIFF_Write16(0); // frame top
SCR_CaptureVideo_RIFF_Write16(width); // frame right
SCR_CaptureVideo_RIFF_Write16(height); // frame bottom
SCR_CaptureVideo_RIFF_Pop();
// video stream format
SCR_CaptureVideo_RIFF_Push("strf", NULL, 40);
SCR_CaptureVideo_RIFF_Write32(40); // BITMAPINFO struct size
SCR_CaptureVideo_RIFF_Write32(width); // width
SCR_CaptureVideo_RIFF_Write32(height); // height
SCR_CaptureVideo_RIFF_Write16(3); // planes
SCR_CaptureVideo_RIFF_Write16(12); // bitcount
SCR_CaptureVideo_RIFF_WriteFourCC("I420"); // compression
SCR_CaptureVideo_RIFF_Write32(width*height+(width/2)*(height/2)*2); // size of image
SCR_CaptureVideo_RIFF_Write32(0); // x pixels per meter
SCR_CaptureVideo_RIFF_Write32(0); // y pixels per meter
SCR_CaptureVideo_RIFF_Write32(0); // color used
SCR_CaptureVideo_RIFF_Write32(0); // color important
SCR_CaptureVideo_RIFF_Pop();
// master index
if(format->canseek)
{
SCR_CaptureVideo_RIFF_Push("indx", NULL, -1);
SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry
SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0
format->videofile_ix_master_video_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse
SCR_CaptureVideo_RIFF_WriteFourCC("00dc"); // dwChunkId
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3
format->videofile_ix_master_video_start_offset = SCR_CaptureVideo_RIFF_GetPosition();
for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i)
SCR_CaptureVideo_RIFF_Write32(0); // fill up later
SCR_CaptureVideo_RIFF_Pop();
}
// extended format (aspect!)
SCR_CaptureVideo_RIFF_Push("vprp", NULL, 68);
SCR_CaptureVideo_RIFF_Write32(0); // VideoFormatToken
SCR_CaptureVideo_RIFF_Write32(0); // VideoStandard
SCR_CaptureVideo_RIFF_Write32((int)(cls.capturevideo.framerate / cls.capturevideo.framestep)); // dwVerticalRefreshRate (bogus)
SCR_CaptureVideo_RIFF_Write32(width); // dwHTotalInT
SCR_CaptureVideo_RIFF_Write32(height); // dwVTotalInLines
FindFraction(aspect, &n, &d, 1000);
SCR_CaptureVideo_RIFF_Write32((n << 16) | d); // dwFrameAspectRatio // TODO a word
SCR_CaptureVideo_RIFF_Write32(width); // dwFrameWidthInPixels
SCR_CaptureVideo_RIFF_Write32(height); // dwFrameHeightInLines
SCR_CaptureVideo_RIFF_Write32(1); // nFieldPerFrame
SCR_CaptureVideo_RIFF_Write32(width); // CompressedBMWidth
SCR_CaptureVideo_RIFF_Write32(height); // CompressedBMHeight
SCR_CaptureVideo_RIFF_Write32(width); // ValidBMHeight
SCR_CaptureVideo_RIFF_Write32(height); // ValidBMWidth
SCR_CaptureVideo_RIFF_Write32(0); // ValidBMXOffset
SCR_CaptureVideo_RIFF_Write32(0); // ValidBMYOffset
SCR_CaptureVideo_RIFF_Write32(0); // ValidBMXOffsetInT
SCR_CaptureVideo_RIFF_Write32(0); // ValidBMYValidStartLine
SCR_CaptureVideo_RIFF_Pop();
SCR_CaptureVideo_RIFF_Pop();
if (cls.capturevideo.soundrate)
{
// audio stream info
SCR_CaptureVideo_RIFF_Push("LIST", "strl", format->canseek ? -1 : 12+52+8+18);
SCR_CaptureVideo_RIFF_Push("strh", "auds", 52);
SCR_CaptureVideo_RIFF_Write32(1); // stream fourcc (PCM audio, uncompressed)
SCR_CaptureVideo_RIFF_Write32(0); // flags
SCR_CaptureVideo_RIFF_Write16(0); // priority
SCR_CaptureVideo_RIFF_Write16(0); // language
SCR_CaptureVideo_RIFF_Write32(0); // initial frames
SCR_CaptureVideo_RIFF_Write32(1); // samples/second divisor
SCR_CaptureVideo_RIFF_Write32((int)(cls.capturevideo.soundrate)); // samples/second multiplied by divisor
SCR_CaptureVideo_RIFF_Write32(0); // start
format->videofile_totalsampleframes_offset = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0xFFFFFFFF); // length
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate * 2); // suggested buffer size (this is a half second)
SCR_CaptureVideo_RIFF_Write32(0); // quality
SCR_CaptureVideo_RIFF_Write32(4); // sample size
SCR_CaptureVideo_RIFF_Write16(0); // frame left
SCR_CaptureVideo_RIFF_Write16(0); // frame top
SCR_CaptureVideo_RIFF_Write16(0); // frame right
SCR_CaptureVideo_RIFF_Write16(0); // frame bottom
SCR_CaptureVideo_RIFF_Pop();
// audio stream format
SCR_CaptureVideo_RIFF_Push("strf", NULL, 18);
SCR_CaptureVideo_RIFF_Write16(1); // format (uncompressed PCM?)
SCR_CaptureVideo_RIFF_Write16(2); // channels (stereo)
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate); // sampleframes per second
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.soundrate * 4); // average bytes per second
SCR_CaptureVideo_RIFF_Write16(4); // block align
SCR_CaptureVideo_RIFF_Write16(16); // bits per sample
SCR_CaptureVideo_RIFF_Write16(0); // size
SCR_CaptureVideo_RIFF_Pop();
// master index
if(format->canseek)
{
SCR_CaptureVideo_RIFF_Push("indx", NULL, -1);
SCR_CaptureVideo_RIFF_Write16(4); // wLongsPerEntry
SCR_CaptureVideo_RIFF_Write16(0); // bIndexSubType=0, bIndexType=0
format->videofile_ix_master_audio_inuse_offset = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0); // nEntriesInUse
SCR_CaptureVideo_RIFF_WriteFourCC("01wb"); // dwChunkId
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved1
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved2
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved3
format->videofile_ix_master_audio_start_offset = SCR_CaptureVideo_RIFF_GetPosition();
for(i = 0; i < AVI_MASTER_INDEX_SIZE * 4; ++i)
SCR_CaptureVideo_RIFF_Write32(0); // fill up later
SCR_CaptureVideo_RIFF_Pop();
}
SCR_CaptureVideo_RIFF_Pop();
}
format->videofile_ix_master_audio_inuse = format->videofile_ix_master_video_inuse = 0;
// extended header (for total #frames)
SCR_CaptureVideo_RIFF_Push("LIST", "odml", 8+4);
SCR_CaptureVideo_RIFF_Push("dmlh", NULL, 4);
format->videofile_totalframes_offset2 = SCR_CaptureVideo_RIFF_GetPosition();
SCR_CaptureVideo_RIFF_Write32(0xFFFFFFFF);
SCR_CaptureVideo_RIFF_Pop();
SCR_CaptureVideo_RIFF_Pop();
// close the AVI header list
SCR_CaptureVideo_RIFF_Pop();
// software that produced this AVI video file
SCR_CaptureVideo_RIFF_Push("LIST", "INFO", 8+((strlen(engineversion) | 1) + 1));
SCR_CaptureVideo_RIFF_Push("ISFT", NULL, strlen(engineversion) + 1);
SCR_CaptureVideo_RIFF_WriteTerminatedString(engineversion);
SCR_CaptureVideo_RIFF_Pop();
// enable this junk filler if you like the LIST movi to always begin at 4KB in the file (why?)
#if 0
SCR_CaptureVideo_RIFF_Push("JUNK", NULL);
x = 4096 - SCR_CaptureVideo_RIFF_GetPosition();
while (x > 0)
{
const char *junkfiller = "[ DarkPlaces junk data ]";
int i = min(x, (int)strlen(junkfiller));
SCR_CaptureVideo_RIFF_WriteBytes((const unsigned char *)junkfiller, i);
x -= i;
}
SCR_CaptureVideo_RIFF_Pop();
#endif
SCR_CaptureVideo_RIFF_Pop();
// begin the actual video section now
SCR_CaptureVideo_RIFF_Push("LIST", "movi", format->canseek ? -1 : 0);
format->videofile_ix_movistart = format->riffstackstartoffset[1];
// we're done with the headers now...
SCR_CaptureVideo_RIFF_Flush();
if (format->riffstacklevel != 2)
Sys_Error("SCR_CaptureVideo_BeginVideo: broken AVI writing code (stack level is %i (should be 2) at end of headers)\n", format->riffstacklevel);
if(!format->canseek)
{
// close the movi immediately
SCR_CaptureVideo_RIFF_Pop();
// close the AVI immediately (we'll put all frames into AVIX)
SCR_CaptureVideo_RIFF_Pop();
}
}
}

1
app/jni/cap_avi.h Normal file
View file

@ -0,0 +1 @@
void SCR_CaptureVideo_Avi_BeginVideo(void);

1121
app/jni/cap_ogg.c Normal file

File diff suppressed because it is too large Load diff

4
app/jni/cap_ogg.h Normal file
View file

@ -0,0 +1,4 @@
void SCR_CaptureVideo_Ogg_Init(void);
qboolean SCR_CaptureVideo_Ogg_Available(void);
void SCR_CaptureVideo_Ogg_BeginVideo(void);
void SCR_CaptureVideo_Ogg_CloseDLL(void);

91
app/jni/cd_null.c Normal file
View file

@ -0,0 +1,91 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "cdaudio.h"
void CDAudio_SysEject (void)
{
}
void CDAudio_SysCloseDoor (void)
{
}
int CDAudio_SysGetAudioDiskInfo (void)
{
return -1;
}
float CDAudio_SysGetVolume (void)
{
return -1.0f;
}
void CDAudio_SysSetVolume (float volume)
{
}
int CDAudio_SysPlay (int track)
{
return -1;
}
int CDAudio_SysStop (void)
{
return -1;
}
int CDAudio_SysPause (void)
{
return -1;
}
int CDAudio_SysResume (void)
{
return -1;
}
int CDAudio_SysUpdate (void)
{
return -1;
}
void CDAudio_SysInit (void)
{
}
int CDAudio_SysStartup (void)
{
return -1;
}
void CDAudio_SysShutdown (void)
{
}

783
app/jni/cd_shared.c Normal file
View file

@ -0,0 +1,783 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include "quakedef.h"
#include "cdaudio.h"
#include "sound.h"
// used by menu to ghost CD audio slider
cvar_t cdaudioinitialized = {CVAR_READONLY,"cdaudioinitialized","0","indicates if CD Audio system is active"};
cvar_t cdaudio = {CVAR_SAVE,"cdaudio","1","CD playing mode (0 = never access CD drive, 1 = play CD tracks if no replacement available, 2 = play fake tracks if no CD track available, 3 = play only real CD tracks, 4 = play real CD tracks even instead of named fake tracks)"};
#define MAX_PLAYLISTS 10
int music_playlist_active = -1;
int music_playlist_playing = 0; // 0 = not playing, 1 = playing, -1 = tried and failed
cvar_t music_playlist_index = {0, "music_playlist_index", "-1", "selects which of the music_playlist_ variables is the active one, -1 disables playlists"};
cvar_t music_playlist_list[MAX_PLAYLISTS] =
{
{0, "music_playlist_list0", "", "list of tracks to play"},
{0, "music_playlist_list1", "", "list of tracks to play"},
{0, "music_playlist_list2", "", "list of tracks to play"},
{0, "music_playlist_list3", "", "list of tracks to play"},
{0, "music_playlist_list4", "", "list of tracks to play"},
{0, "music_playlist_list5", "", "list of tracks to play"},
{0, "music_playlist_list6", "", "list of tracks to play"},
{0, "music_playlist_list7", "", "list of tracks to play"},
{0, "music_playlist_list8", "", "list of tracks to play"},
{0, "music_playlist_list9", "", "list of tracks to play"}
};
cvar_t music_playlist_current[MAX_PLAYLISTS] =
{
{0, "music_playlist_current0", "0", "current track index to play in list"},
{0, "music_playlist_current1", "0", "current track index to play in list"},
{0, "music_playlist_current2", "0", "current track index to play in list"},
{0, "music_playlist_current3", "0", "current track index to play in list"},
{0, "music_playlist_current4", "0", "current track index to play in list"},
{0, "music_playlist_current5", "0", "current track index to play in list"},
{0, "music_playlist_current6", "0", "current track index to play in list"},
{0, "music_playlist_current7", "0", "current track index to play in list"},
{0, "music_playlist_current8", "0", "current track index to play in list"},
{0, "music_playlist_current9", "0", "current track index to play in list"},
};
cvar_t music_playlist_random[MAX_PLAYLISTS] =
{
{0, "music_playlist_random0", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random1", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random2", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random3", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random4", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random5", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random6", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random7", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random8", "0", "enables random play order if 1, 0 is sequential play"},
{0, "music_playlist_random9", "0", "enables random play order if 1, 0 is sequential play"},
};
cvar_t music_playlist_sampleposition[MAX_PLAYLISTS] =
{
{0, "music_playlist_sampleposition0", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition1", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition2", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition3", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition4", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition5", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition6", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition7", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition8", "-1", "resume position for track, -1 restarts every time"},
{0, "music_playlist_sampleposition9", "-1", "resume position for track, -1 restarts every time"},
};
static qboolean wasPlaying = false;
static qboolean initialized = false;
static qboolean enabled = false;
static float cdvolume;
typedef char filename_t[MAX_QPATH];
#ifdef MAXTRACKS
static filename_t remap[MAXTRACKS];
#endif
static unsigned char maxTrack;
static int faketrack = -1;
static float saved_vol = 1.0f;
// exported variables
qboolean cdValid = false;
qboolean cdPlaying = false;
qboolean cdPlayLooping = false;
unsigned char cdPlayTrack;
cl_cdstate_t cd;
static void CDAudio_Eject (void)
{
if (!enabled)
return;
if(cdaudio.integer == 0)
return;
CDAudio_SysEject();
}
static void CDAudio_CloseDoor (void)
{
if (!enabled)
return;
if(cdaudio.integer == 0)
return;
CDAudio_SysCloseDoor();
}
static int CDAudio_GetAudioDiskInfo (void)
{
int ret;
cdValid = false;
if(cdaudio.integer == 0)
return -1;
ret = CDAudio_SysGetAudioDiskInfo();
if (ret < 1)
return -1;
cdValid = true;
maxTrack = ret;
return 0;
}
static qboolean CDAudio_Play_real (int track, qboolean looping, qboolean complain)
{
if(track < 1)
{
if(complain)
Con_Print("Could not load BGM track.\n");
return false;
}
if (!cdValid)
{
CDAudio_GetAudioDiskInfo();
if (!cdValid)
{
if(complain)
Con_DPrint ("No CD in player.\n");
return false;
}
}
if (track > maxTrack)
{
if(complain)
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return false;
}
if (CDAudio_SysPlay(track) == -1)
return false;
if(cdaudio.integer != 3)
Con_DPrintf ("CD track %u playing...\n", track);
return true;
}
void CDAudio_Play_byName (const char *trackname, qboolean looping, qboolean tryreal, float startposition)
{
unsigned int track;
sfx_t* sfx;
char filename[MAX_QPATH];
Host_StartVideo();
if (!enabled)
return;
if(tryreal && strspn(trackname, "0123456789") == strlen(trackname))
{
track = (unsigned char) atoi(trackname);
#ifdef MAXTRACKS
if(track > 0 && track < MAXTRACKS)
if(*remap[track])
{
if(strspn(remap[track], "0123456789") == strlen(remap[track]))
{
trackname = remap[track];
}
else
{
// ignore remappings to fake tracks if we're going to play a real track
switch(cdaudio.integer)
{
case 0: // we never access CD
case 1: // we have a replacement
trackname = remap[track];
break;
case 2: // we only use fake track replacement if CD track is invalid
CDAudio_GetAudioDiskInfo();
if(!cdValid || track > maxTrack)
trackname = remap[track];
break;
case 3: // we always play from CD - ignore this remapping then
case 4: // we randomize anyway
break;
}
}
}
#endif
}
if(tryreal && strspn(trackname, "0123456789") == strlen(trackname))
{
track = (unsigned char) atoi(trackname);
if (track < 1)
{
Con_DPrintf("CDAudio: Bad track number %u.\n", track);
return;
}
}
else
track = 0;
// div0: I assume this code was intentionally there. Maybe turn it into a cvar?
if (cdPlaying && cdPlayTrack == track && faketrack == -1)
return;
CDAudio_Stop ();
if(track >= 1)
{
if(cdaudio.integer == 3) // only play real CD tracks at all
{
if(CDAudio_Play_real(track, looping, true))
goto success;
return;
}
if(cdaudio.integer == 2) // prefer real CD track over fake
{
if(CDAudio_Play_real(track, looping, false))
goto success;
}
}
if(cdaudio.integer == 4) // only play real CD tracks, EVEN instead of fake tracks!
{
if(CDAudio_Play_real(track, looping, false))
goto success;
if(cdValid && maxTrack > 0)
{
track = 1 + (rand() % maxTrack);
if(CDAudio_Play_real(track, looping, true))
goto success;
}
else
{
Con_DPrint ("No CD in player.\n");
}
return;
}
// Try playing a fake track (sound file) first
if(track >= 1)
{
dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%03u.wav", track);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%03u.ogg", track);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/track%03u.ogg", track);// added by motorsep
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/track%03u.ogg", track);// added by motorsep
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%02u.wav", track);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%02u.ogg", track);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/track%02u.ogg", track);// added by motorsep
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/track%02u.ogg", track);// added by motorsep
}
else
{
dpsnprintf(filename, sizeof(filename), "%s", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "%s.wav", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "%s.ogg", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s.wav", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s.ogg", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s.wav", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s.ogg", trackname);
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/%s.ogg", trackname); // added by motorsep
if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/%s.ogg", trackname); // added by motorsep
}
if (FS_FileExists(filename) && (sfx = S_PrecacheSound (filename, false, false)))
{
faketrack = S_StartSound_StartPosition_Flags (-1, 0, sfx, vec3_origin, cdvolume, 0, startposition, (looping ? CHANNELFLAG_FORCELOOP : 0) | CHANNELFLAG_FULLVOLUME | CHANNELFLAG_LOCALSOUND, 1.0f);
if (faketrack != -1)
{
if(track >= 1)
{
if(cdaudio.integer != 0) // we don't need these messages if only fake tracks can be played anyway
Con_DPrintf ("Fake CD track %u playing...\n", track);
}
else
Con_DPrintf ("BGM track %s playing...\n", trackname);
}
}
// If we can't play a fake CD track, try the real one
if (faketrack == -1)
{
if(cdaudio.integer == 0 || track < 1)
{
Con_Print("Could not load BGM track.\n");
return;
}
else
{
if(!CDAudio_Play_real(track, looping, true))
return;
}
}
success:
cdPlayLooping = looping;
cdPlayTrack = track;
cdPlaying = true;
if (cdvolume == 0.0 || bgmvolume.value == 0)
CDAudio_Pause ();
}
void CDAudio_Play (int track, qboolean looping)
{
char buf[20];
if (music_playlist_index.integer >= 0)
return;
dpsnprintf(buf, sizeof(buf), "%d", (int) track);
CDAudio_Play_byName(buf, looping, true, 0);
}
float CDAudio_GetPosition (void)
{
if(faketrack != -1)
return S_GetChannelPosition(faketrack);
return -1;
}
static void CDAudio_StopPlaylistTrack(void);
void CDAudio_Stop (void)
{
if (!enabled)
return;
// save the playlist position
CDAudio_StopPlaylistTrack();
if (faketrack != -1)
{
S_StopChannel (faketrack, true, true);
faketrack = -1;
}
else if (cdPlaying && (CDAudio_SysStop() == -1))
return;
else if(wasPlaying)
{
CDAudio_Resume(); // needed by SDL - can't stop while paused there (causing pause/stop to fail after play, pause, stop, play otherwise)
if (cdPlaying && (CDAudio_SysStop() == -1))
return;
}
wasPlaying = false;
cdPlaying = false;
}
void CDAudio_Pause (void)
{
if (!enabled || !cdPlaying)
return;
if (faketrack != -1)
S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, true);
else if (CDAudio_SysPause() == -1)
return;
wasPlaying = cdPlaying;
cdPlaying = false;
}
void CDAudio_Resume (void)
{
if (!enabled || cdPlaying || !wasPlaying)
return;
if (faketrack != -1)
S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, false);
else if (CDAudio_SysResume() == -1)
return;
cdPlaying = true;
}
static void CD_f (void)
{
const char *command;
#ifdef MAXTRACKS
int ret;
int n;
#endif
command = Cmd_Argv (1);
if (strcasecmp(command, "remap") != 0)
Host_StartVideo();
if (strcasecmp(command, "on") == 0)
{
enabled = true;
return;
}
if (strcasecmp(command, "off") == 0)
{
CDAudio_Stop();
enabled = false;
return;
}
if (strcasecmp(command, "reset") == 0)
{
enabled = true;
CDAudio_Stop();
#ifdef MAXTRACKS
for (n = 0; n < MAXTRACKS; n++)
*remap[n] = 0; // empty string, that is, unremapped
#endif
CDAudio_GetAudioDiskInfo();
return;
}
if (strcasecmp(command, "rescan") == 0)
{
CDAudio_Shutdown();
CDAudio_Startup();
return;
}
if (strcasecmp(command, "remap") == 0)
{
#ifdef MAXTRACKS
ret = Cmd_Argc() - 2;
if (ret <= 0)
{
for (n = 1; n < MAXTRACKS; n++)
if (*remap[n])
Con_Printf(" %u -> %s\n", n, remap[n]);
return;
}
for (n = 1; n <= ret; n++)
strlcpy(remap[n], Cmd_Argv (n+1), sizeof(*remap));
#endif
return;
}
if (strcasecmp(command, "close") == 0)
{
CDAudio_CloseDoor();
return;
}
if (strcasecmp(command, "play") == 0)
{
if (music_playlist_index.integer >= 0)
return;
CDAudio_Play_byName(Cmd_Argv (2), false, true, (Cmd_Argc() > 3) ? atof( Cmd_Argv(3) ) : 0);
return;
}
if (strcasecmp(command, "loop") == 0)
{
if (music_playlist_index.integer >= 0)
return;
CDAudio_Play_byName(Cmd_Argv (2), true, true, (Cmd_Argc() > 3) ? atof( Cmd_Argv(3) ) : 0);
return;
}
if (strcasecmp(command, "stop") == 0)
{
if (music_playlist_index.integer >= 0)
return;
CDAudio_Stop();
return;
}
if (strcasecmp(command, "pause") == 0)
{
if (music_playlist_index.integer >= 0)
return;
CDAudio_Pause();
return;
}
if (strcasecmp(command, "resume") == 0)
{
if (music_playlist_index.integer >= 0)
return;
CDAudio_Resume();
return;
}
if (strcasecmp(command, "eject") == 0)
{
if (faketrack == -1)
CDAudio_Stop();
CDAudio_Eject();
cdValid = false;
return;
}
if (strcasecmp(command, "info") == 0)
{
CDAudio_GetAudioDiskInfo ();
if (cdValid)
Con_Printf("%u tracks on CD.\n", maxTrack);
else
Con_Print ("No CD in player.\n");
if (cdPlaying)
Con_Printf("Currently %s track %u\n", cdPlayLooping ? "looping" : "playing", cdPlayTrack);
else if (wasPlaying)
Con_Printf("Paused %s track %u\n", cdPlayLooping ? "looping" : "playing", cdPlayTrack);
if (cdvolume >= 0)
Con_Printf("Volume is %f\n", cdvolume);
else
Con_Printf("Can't get CD volume\n");
return;
}
Con_Printf("CD commands:\n");
Con_Printf("cd on - enables CD audio system\n");
Con_Printf("cd off - stops and disables CD audio system\n");
Con_Printf("cd reset - resets CD audio system (clears track remapping and re-reads disc information)\n");
Con_Printf("cd rescan - rescans disks in drives (to use another disc)\n");
Con_Printf("cd remap <remap1> [remap2] [remap3] [...] - chooses (possibly emulated) CD tracks to play when a map asks for a particular track, this has many uses\n");
Con_Printf("cd close - closes CD tray\n");
Con_Printf("cd eject - stops playing music and opens CD tray to allow you to change disc\n");
Con_Printf("cd play <tracknumber> <startposition> - plays selected track in remapping table\n");
Con_Printf("cd loop <tracknumber> <startposition> - plays and repeats selected track in remapping table\n");
Con_Printf("cd stop - stops playing current CD track\n");
Con_Printf("cd pause - pauses CD playback\n");
Con_Printf("cd resume - unpauses CD playback\n");
Con_Printf("cd info - prints basic disc information (number of tracks, currently playing track, volume level)\n");
}
static void CDAudio_SetVolume (float newvol)
{
// If the volume hasn't changed
if (newvol == cdvolume)
return;
// If the CD has been muted
if (newvol == 0.0f)
CDAudio_Pause ();
else
{
// If the CD has been unmuted
if (cdvolume == 0.0f)
CDAudio_Resume ();
if (faketrack != -1)
S_SetChannelVolume (faketrack, newvol);
else
CDAudio_SysSetVolume (newvol * mastervolume.value);
}
cdvolume = newvol;
}
static void CDAudio_StopPlaylistTrack(void)
{
if (music_playlist_active >= 0 && music_playlist_active < MAX_PLAYLISTS && music_playlist_sampleposition[music_playlist_active].value >= 0)
{
// save position for resume
float position = CDAudio_GetPosition();
Cvar_SetValueQuick(&music_playlist_sampleposition[music_playlist_active], position >= 0 ? position : 0);
}
music_playlist_active = -1;
music_playlist_playing = 0; // not playing
}
void CDAudio_StartPlaylist(qboolean resume)
{
const char *list;
const char *t;
int index;
int current;
int randomplay;
int count;
int listindex;
float position;
char trackname[MAX_QPATH];
CDAudio_Stop();
index = music_playlist_index.integer;
if (index >= 0 && index < MAX_PLAYLISTS && bgmvolume.value > 0)
{
list = music_playlist_list[index].string;
current = music_playlist_current[index].integer;
randomplay = music_playlist_random[index].integer;
position = music_playlist_sampleposition[index].value;
count = 0;
trackname[0] = 0;
if (list && list[0])
{
for (t = list;;count++)
{
if (!COM_ParseToken_Console(&t))
break;
// if we don't find the desired track, use the first one
if (count == 0)
strlcpy(trackname, com_token, sizeof(trackname));
}
}
if (count > 0)
{
// position < 0 means never resume track
if (position < 0)
position = 0;
// advance to next track in playlist if the last one ended
if (!resume)
{
position = 0;
current++;
if (randomplay)
current = (int)lhrandom(0, count);
}
// wrap playlist position if needed
if (current >= count)
current = 0;
// set current
Cvar_SetValueQuick(&music_playlist_current[index], current);
// get the Nth trackname
if (current >= 0 && current < count)
{
for (listindex = 0, t = list;;listindex++)
{
if (!COM_ParseToken_Console(&t))
break;
if (listindex == current)
{
strlcpy(trackname, com_token, sizeof(trackname));
break;
}
}
}
if (trackname[0])
{
CDAudio_Play_byName(trackname, false, false, position);
if (faketrack != -1)
music_playlist_active = index;
}
}
}
music_playlist_playing = music_playlist_active >= 0 ? 1 : -1;
}
void CDAudio_Update (void)
{
static int lastplaylist = -1;
if (!enabled)
return;
CDAudio_SetVolume (bgmvolume.value);
if (music_playlist_playing > 0 && CDAudio_GetPosition() < 0)
{
// this track ended, start a new track from the beginning
CDAudio_StartPlaylist(false);
lastplaylist = music_playlist_index.integer;
}
else if (lastplaylist != music_playlist_index.integer
|| (bgmvolume.value > 0 && !music_playlist_playing && music_playlist_index.integer >= 0))
{
// active playlist changed, save position and switch track
CDAudio_StartPlaylist(true);
lastplaylist = music_playlist_index.integer;
}
if (faketrack == -1 && cdaudio.integer != 0 && bgmvolume.value != 0)
CDAudio_SysUpdate();
}
int CDAudio_Init (void)
{
int i;
if (cls.state == ca_dedicated)
return -1;
// COMMANDLINEOPTION: Sound: -nocdaudio disables CD audio support
if (COM_CheckParm("-nocdaudio"))
return -1;
CDAudio_SysInit();
#ifdef MAXTRACKS
for (i = 0; i < MAXTRACKS; i++)
*remap[i] = 0;
#endif
Cvar_RegisterVariable(&cdaudio);
Cvar_RegisterVariable(&cdaudioinitialized);
Cvar_SetValueQuick(&cdaudioinitialized, true);
enabled = true;
Cvar_RegisterVariable(&music_playlist_index);
for (i = 0;i < MAX_PLAYLISTS;i++)
{
Cvar_RegisterVariable(&music_playlist_list[i]);
Cvar_RegisterVariable(&music_playlist_current[i]);
Cvar_RegisterVariable(&music_playlist_random[i]);
Cvar_RegisterVariable(&music_playlist_sampleposition[i]);
}
Cmd_AddCommand("cd", CD_f, "execute a CD drive command (cd on/off/reset/remap/close/play/loop/stop/pause/resume/eject/info) - use cd by itself for usage");
return 0;
}
int CDAudio_Startup (void)
{
if (COM_CheckParm("-nocdaudio"))
return -1;
CDAudio_SysStartup ();
if (CDAudio_GetAudioDiskInfo())
{
Con_Print("CDAudio_Init: No CD in player.\n");
cdValid = false;
}
saved_vol = CDAudio_SysGetVolume ();
if (saved_vol < 0.0f)
{
Con_Print ("Can't get initial CD volume\n");
saved_vol = 1.0f;
}
else
Con_Printf ("Initial CD volume: %g\n", saved_vol);
initialized = true;
Con_Print("CD Audio Initialized\n");
return 0;
}
void CDAudio_Shutdown (void)
{
if (!initialized)
return;
CDAudio_SysSetVolume (saved_vol);
CDAudio_Stop();
CDAudio_SysShutdown();
initialized = false;
}

66
app/jni/cdaudio.h Normal file
View file

@ -0,0 +1,66 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
typedef struct cl_cdstate_s
{
qboolean Valid;
qboolean Playing;
qboolean PlayLooping;
unsigned char PlayTrack;
}
cl_cdstate_t;
//extern cl_cdstate_t cd;
extern qboolean cdValid;
extern qboolean cdPlaying;
extern qboolean cdPlayLooping;
extern unsigned char cdPlayTrack;
extern cvar_t cdaudioinitialized;
int CDAudio_Init(void);
void CDAudio_Open(void);
void CDAudio_Close(void);
void CDAudio_Play(int track, qboolean looping);
void CDAudio_Play_byName (const char *trackname, qboolean looping, qboolean tryreal, float startposition);
void CDAudio_Stop(void);
void CDAudio_Pause(void);
void CDAudio_Resume(void);
int CDAudio_Startup(void);
void CDAudio_Shutdown(void);
void CDAudio_Update(void);
float CDAudio_GetPosition(void);
void CDAudio_StartPlaylist(qboolean resume);
// Prototypes of the system dependent functions
void CDAudio_SysEject (void);
void CDAudio_SysCloseDoor (void);
int CDAudio_SysGetAudioDiskInfo (void);
float CDAudio_SysGetVolume (void);
void CDAudio_SysSetVolume (float volume);
int CDAudio_SysPlay (int track);
int CDAudio_SysStop (void);
int CDAudio_SysPause (void);
int CDAudio_SysResume (void);
int CDAudio_SysUpdate (void);
void CDAudio_SysInit (void);
int CDAudio_SysStartup (void);
void CDAudio_SysShutdown (void);

30
app/jni/cflags.mk Normal file
View file

@ -0,0 +1,30 @@
# This file is included in all .mk files to ensure their compilation flags are in sync
# across debug and release builds.
# NOTE: this is not part of import_vrlib.mk because VRLib itself needs to have these flags
# set, but VRLib's make file cannot include import_vrlib.mk or it would be importing itself.
LOCAL_CFLAGS := -DANDROID_NDK
LOCAL_CFLAGS += -Werror # error on warnings
LOCAL_CFLAGS += -Wall
LOCAL_CFLAGS += -Wextra
#LOCAL_CFLAGS += -Wlogical-op # not part of -Wall or -Wextra
#LOCAL_CFLAGS += -Weffc++ # too many issues to fix for now
LOCAL_CFLAGS += -Wno-strict-aliasing # TODO: need to rewrite some code
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wno-missing-field-initializers # warns on this: SwipeAction ret = {}
LOCAL_CFLAGS += -Wno-multichar # used in internal Android headers: DISPLAY_EVENT_VSYNC = 'vsyn',
LOCAL_CPPFLAGS := -Wno-type-limits
LOCAL_CPPFLAGS += -Wno-invalid-offsetof
# disable deprecation errors, but keep the warnings
LOCAL_CFLAGS += -Wno-error=deprecated-declarations
ifeq ($(OVR_DEBUG),1)
LOCAL_CFLAGS += -DOVR_BUILD_DEBUG=1 -O0 -g
else
LOCAL_CFLAGS += -O3
endif
# Explicitly compile for the ARM and not the Thumb instruction set.
LOCAL_ARM_MODE := arm

1079
app/jni/cl_collision.c Normal file

File diff suppressed because it is too large Load diff

19
app/jni/cl_collision.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef CL_COLLISION_H
#define CL_COLLISION_H
float CL_SelectTraceLine(const vec3_t start, const vec3_t end, vec3_t impact, vec3_t normal, int *hitent, entity_render_t *ignoreent);
void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius);
dp_model_t *CL_GetModelByIndex(int modelindex);
dp_model_t *CL_GetModelFromEdict(prvm_edict_t *ed);
void CL_LinkEdict(prvm_edict_t *ent);
int CL_GenericHitSuperContentsMask(const prvm_edict_t *edict);
trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities, qboolean hitsurfaces);
trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask, qboolean hitnetworkbrushmodels, qboolean hitnetworkplayers, int *hitnetworkentity, qboolean hitcsqcentities);
trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int type, int hitsupercontentsmask);
#define CL_PointSuperContents(point) (CL_TracePoint((point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0, true, false, NULL, false).startsupercontents)
#endif

617
app/jni/cl_demo.c Normal file
View file

@ -0,0 +1,617 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
extern cvar_t cl_capturevideo;
extern cvar_t cl_capturevideo_demo_stop;
int old_vsync = 0;
static void CL_FinishTimeDemo (void);
/*
==============================================================================
DEMO CODE
When a demo is playing back, all outgoing network messages are skipped, and
incoming messages are read from the demo file.
Whenever cl.time gets past the last received message, another message is
read from the demo file.
==============================================================================
*/
/*
=====================
CL_NextDemo
Called to play the next demo in the demo loop
=====================
*/
void CL_NextDemo (void)
{
char str[MAX_INPUTLINE];
if (cls.demonum == -1)
return; // don't play demos
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
{
cls.demonum = 0;
if (!cls.demos[cls.demonum][0])
{
Con_Print("No demos listed with startdemos\n");
cls.demonum = -1;
return;
}
}
dpsnprintf (str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]);
Cbuf_InsertText (str);
cls.demonum++;
}
/*
==============
CL_StopPlayback
Called when a demo file runs out, or the user starts a game
==============
*/
// LordHavoc: now called only by CL_Disconnect
void CL_StopPlayback (void)
{
if (cl_capturevideo_demo_stop.integer)
Cvar_Set("cl_capturevideo", "0");
if (!cls.demoplayback)
return;
FS_Close (cls.demofile);
cls.demoplayback = false;
cls.demofile = NULL;
if (cls.timedemo)
CL_FinishTimeDemo ();
if (!cls.demostarting) // only quit if not starting another demo
if (COM_CheckParm("-demo") || COM_CheckParm("-capturedemo"))
Host_Quit_f();
}
/*
====================
CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
#====================
*/
void CL_WriteDemoMessage (sizebuf_t *message)
{
int len;
int i;
float f;
if (cls.demopaused) // LordHavoc: pausedemo
return;
len = LittleLong (message->cursize);
FS_Write (cls.demofile, &len, 4);
for (i=0 ; i<3 ; i++)
{
f = LittleFloat (cl.viewangles[i]);
FS_Write (cls.demofile, &f, 4);
}
FS_Write (cls.demofile, message->data, message->cursize);
}
/*
====================
CL_CutDemo
Dumps the current demo to a buffer, and resets the demo to its starting point.
Used to insert csprogs.dat files as a download to the beginning of a demo file.
====================
*/
void CL_CutDemo (unsigned char **buf, fs_offset_t *filesize)
{
*buf = NULL;
*filesize = 0;
FS_Close(cls.demofile);
*buf = FS_LoadFile(cls.demoname, tempmempool, false, filesize);
// restart the demo recording
cls.demofile = FS_OpenRealFile(cls.demoname, "wb", false);
if(!cls.demofile)
Sys_Error("failed to reopen the demo file");
FS_Printf(cls.demofile, "%i\n", cls.forcetrack);
}
/*
====================
CL_PasteDemo
Adds the cut stuff back to the demo. Also frees the buffer.
Used to insert csprogs.dat files as a download to the beginning of a demo file.
====================
*/
void CL_PasteDemo (unsigned char **buf, fs_offset_t *filesize)
{
fs_offset_t startoffset = 0;
if(!*buf)
return;
// skip cdtrack
while(startoffset < *filesize && ((char *)(*buf))[startoffset] != '\n')
++startoffset;
if(startoffset < *filesize)
++startoffset;
FS_Write(cls.demofile, *buf + startoffset, *filesize - startoffset);
Mem_Free(*buf);
*buf = NULL;
*filesize = 0;
}
/*
====================
CL_ReadDemoMessage
Handles playback of demos
====================
*/
void CL_ReadDemoMessage(void)
{
int i;
float f;
if (!cls.demoplayback)
return;
// LordHavoc: pausedemo
if (cls.demopaused)
return;
for (;;)
{
// decide if it is time to grab the next message
// always grab until fully connected
if (cls.signon == SIGNONS)
{
if (cls.timedemo)
{
cls.td_frames++;
cls.td_onesecondframes++;
// if this is the first official frame we can now grab the real
// td_starttime so the bogus time on the first frame doesn't
// count against the final report
if (cls.td_frames == 0)
{
cls.td_starttime = realtime;
cls.td_onesecondnexttime = cl.time + 1;
cls.td_onesecondrealtime = realtime;
cls.td_onesecondframes = 0;
cls.td_onesecondminfps = 0;
cls.td_onesecondmaxfps = 0;
cls.td_onesecondavgfps = 0;
cls.td_onesecondavgcount = 0;
}
if (cl.time >= cls.td_onesecondnexttime)
{
double fps = cls.td_onesecondframes / (realtime - cls.td_onesecondrealtime);
if (cls.td_onesecondavgcount == 0)
{
cls.td_onesecondminfps = fps;
cls.td_onesecondmaxfps = fps;
}
cls.td_onesecondrealtime = realtime;
cls.td_onesecondminfps = min(cls.td_onesecondminfps, fps);
cls.td_onesecondmaxfps = max(cls.td_onesecondmaxfps, fps);
cls.td_onesecondavgfps += fps;
cls.td_onesecondavgcount++;
cls.td_onesecondframes = 0;
cls.td_onesecondnexttime++;
}
}
else if (cl.time <= cl.mtime[0])
{
// don't need another message yet
return;
}
}
// get the next message
FS_Read(cls.demofile, &cl_message.cursize, 4);
cl_message.cursize = LittleLong(cl_message.cursize);
if(cl_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now!
{
// skip over demo packet
FS_Seek(cls.demofile, 12 + (cl_message.cursize & (~DEMOMSG_CLIENT_TO_SERVER)), SEEK_CUR);
continue;
}
if (cl_message.cursize > cl_message.maxsize)
{
Con_Printf("Demo message (%i) > cl_message.maxsize (%i)", cl_message.cursize, cl_message.maxsize);
cl_message.cursize = 0;
CL_Disconnect();
return;
}
VectorCopy(cl.mviewangles[0], cl.mviewangles[1]);
for (i = 0;i < 3;i++)
{
FS_Read(cls.demofile, &f, 4);
cl.mviewangles[0][i] = LittleFloat(f);
}
if (FS_Read(cls.demofile, cl_message.data, cl_message.cursize) == cl_message.cursize)
{
MSG_BeginReading(&cl_message);
CL_ParseServerMessage();
if (cls.signon != SIGNONS)
Cbuf_Execute(); // immediately execute svc_stufftext if in the demo before connect!
// In case the demo contains a "svc_disconnect" message
if (!cls.demoplayback)
return;
if (cls.timedemo)
return;
}
else
{
CL_Disconnect();
return;
}
}
}
/*
====================
CL_Stop_f
stop recording a demo
====================
*/
void CL_Stop_f (void)
{
sizebuf_t buf;
unsigned char bufdata[64];
if (!cls.demorecording)
{
Con_Print("Not recording a demo.\n");
return;
}
// write a disconnect message to the demo file
// LordHavoc: don't replace the cl_message when doing this
buf.data = bufdata;
buf.maxsize = sizeof(bufdata);
SZ_Clear(&buf);
MSG_WriteByte(&buf, svc_disconnect);
CL_WriteDemoMessage(&buf);
// finish up
if(cl_autodemo.integer && (cl_autodemo_delete.integer & 1))
{
FS_RemoveOnClose(cls.demofile);
Con_Print("Completed and deleted demo\n");
}
else
Con_Print("Completed demo\n");
FS_Close (cls.demofile);
cls.demofile = NULL;
cls.demorecording = false;
}
/*
====================
CL_Record_f
record <demoname> <map> [cd track]
====================
*/
void CL_Record_f (void)
{
int c, track;
char name[MAX_OSPATH];
char vabuf[1024];
c = Cmd_Argc();
if (c != 2 && c != 3 && c != 4)
{
Con_Print("record <demoname> [<map> [cd track]]\n");
return;
}
if (strstr(Cmd_Argv(1), ".."))
{
Con_Print("Relative pathnames are not allowed.\n");
return;
}
if (c == 2 && cls.state == ca_connected)
{
Con_Print("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
return;
}
if (cls.state == ca_connected)
CL_Disconnect();
// write the forced cd track number, or -1
if (c == 4)
{
track = atoi(Cmd_Argv(3));
Con_Printf("Forcing CD track to %i\n", cls.forcetrack);
}
else
track = -1;
// get the demo name
strlcpy (name, Cmd_Argv(1), sizeof (name));
FS_DefaultExtension (name, ".dem", sizeof (name));
// start the map up
if (c > 2)
Cmd_ExecuteString ( va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(2)), src_command, false);
// open the demo file
Con_Printf("recording to %s.\n", name);
cls.demofile = FS_OpenRealFile(name, "wb", false);
if (!cls.demofile)
{
Con_Print("ERROR: couldn't open.\n");
return;
}
strlcpy(cls.demoname, name, sizeof(cls.demoname));
cls.forcetrack = track;
FS_Printf(cls.demofile, "%i\n", cls.forcetrack);
cls.demorecording = true;
cls.demo_lastcsprogssize = -1;
cls.demo_lastcsprogscrc = -1;
}
/*
====================
CL_PlayDemo_f
play [demoname]
====================
*/
void CL_PlayDemo_f (void)
{
char name[MAX_QPATH];
int c;
qboolean neg = false;
qfile_t *f;
if (Cmd_Argc() != 2)
{
Con_Print("play <demoname> : plays a demo\n");
return;
}
// open the demo file
strlcpy (name, Cmd_Argv(1), sizeof (name));
FS_DefaultExtension (name, ".dem", sizeof (name));
f = FS_OpenVirtualFile(name, false);
if (!f)
{
Con_Printf("ERROR: couldn't open %s.\n", name);
cls.demonum = -1; // stop demo loop
return;
}
cls.demostarting = true;
// disconnect from server
CL_Disconnect ();
Host_ShutdownServer ();
// update networking ports (this is mainly just needed at startup)
NetConn_UpdateSockets();
cls.protocol = PROTOCOL_QUAKE;
Con_Printf("Playing demo %s.\n", name);
cls.demofile = f;
strlcpy(cls.demoname, name, sizeof(cls.demoname));
cls.demoplayback = true;
cls.state = ca_connected;
cls.forcetrack = 0;
while ((c = FS_Getc (cls.demofile)) != '\n')
if (c == '-')
neg = true;
else
cls.forcetrack = cls.forcetrack * 10 + (c - '0');
if (neg)
cls.forcetrack = -cls.forcetrack;
cls.demostarting = false;
}
typedef struct
{
int frames;
double time, totalfpsavg;
double fpsmin, fpsavg, fpsmax;
}
benchmarkhistory_t;
static size_t doublecmp_offset;
static int doublecmp_withoffset(const void *a_, const void *b_)
{
const double *a = (const double *) ((const char *) a_ + doublecmp_offset);
const double *b = (const double *) ((const char *) b_ + doublecmp_offset);
if(*a > *b)
return +1;
if(*a < *b)
return -1;
return 0;
}
/*
====================
CL_FinishTimeDemo
====================
*/
static void CL_FinishTimeDemo (void)
{
int frames;
int i;
double time, totalfpsavg;
double fpsmin, fpsavg, fpsmax; // report min/avg/max fps
static int benchmark_runs = 0;
char vabuf[1024];
cls.timedemo = false;
frames = cls.td_frames;
time = realtime - cls.td_starttime;
totalfpsavg = time > 0 ? frames / time : 0;
fpsmin = cls.td_onesecondminfps;
fpsavg = cls.td_onesecondavgcount ? cls.td_onesecondavgfps / cls.td_onesecondavgcount : 0;
fpsmax = cls.td_onesecondmaxfps;
// LordHavoc: timedemo now prints out 7 digits of fraction, and min/avg/max
Con_Printf("%i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
Log_Printf("benchmark.log", "date %s | enginedate %s | demo %s | commandline %s | run %d | result %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", Sys_TimeString("%Y-%m-%d %H:%M:%S"), buildstring, cls.demoname, cmdline.string, benchmark_runs + 1, frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
if (COM_CheckParm("-benchmark"))
{
++benchmark_runs;
i = COM_CheckParm("-benchmarkruns");
if(i && i + 1 < com_argc)
{
static benchmarkhistory_t *history = NULL;
if(!history)
history = (benchmarkhistory_t *)Z_Malloc(sizeof(*history) * atoi(com_argv[i + 1]));
history[benchmark_runs - 1].frames = frames;
history[benchmark_runs - 1].time = time;
history[benchmark_runs - 1].totalfpsavg = totalfpsavg;
history[benchmark_runs - 1].fpsmin = fpsmin;
history[benchmark_runs - 1].fpsavg = fpsavg;
history[benchmark_runs - 1].fpsmax = fpsmax;
if(atoi(com_argv[i + 1]) > benchmark_runs)
{
// restart the benchmark
Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", cls.demoname));
// cannot execute here
}
else
{
// print statistics
int first = COM_CheckParm("-benchmarkruns_skipfirst") ? 1 : 0;
if(benchmark_runs > first)
{
#define DO_MIN(f) \
for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f < f)) f = history[i].f
#define DO_MAX(f) \
for(i = first; i < benchmark_runs; ++i) if((i == first) || (history[i].f > f)) f = history[i].f
#define DO_MED(f) \
doublecmp_offset = (char *)&history->f - (char *)history; \
qsort(history + first, benchmark_runs - first, sizeof(*history), doublecmp_withoffset); \
if((first + benchmark_runs) & 1) \
f = history[(first + benchmark_runs - 1) / 2].f; \
else \
f = (history[(first + benchmark_runs - 2) / 2].f + history[(first + benchmark_runs) / 2].f) / 2
DO_MIN(frames);
DO_MAX(time);
DO_MIN(totalfpsavg);
DO_MIN(fpsmin);
DO_MIN(fpsavg);
DO_MIN(fpsmax);
Con_Printf("MIN: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
DO_MED(frames);
DO_MED(time);
DO_MED(totalfpsavg);
DO_MED(fpsmin);
DO_MED(fpsavg);
DO_MED(fpsmax);
Con_Printf("MED: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
DO_MAX(frames);
DO_MIN(time);
DO_MAX(totalfpsavg);
DO_MAX(fpsmin);
DO_MAX(fpsavg);
DO_MAX(fpsmax);
Con_Printf("MAX: %i frames %5.7f seconds %5.7f fps, one-second fps min/avg/max: %.0f %.0f %.0f (%i seconds)\n", frames, time, totalfpsavg, fpsmin, fpsavg, fpsmax, cls.td_onesecondavgcount);
}
Z_Free(history);
history = NULL;
Host_Quit_f();
}
}
else
Host_Quit_f();
}
}
/*
====================
CL_TimeDemo_f
timedemo [demoname]
====================
*/
void CL_TimeDemo_f (void)
{
if (Cmd_Argc() != 2)
{
Con_Print("timedemo <demoname> : gets demo speeds\n");
return;
}
srand(0); // predictable random sequence for benchmarking
CL_PlayDemo_f ();
// cls.td_starttime will be grabbed at the second frame of the demo, so
// all the loading time doesn't get counted
// instantly hide console and deactivate it
key_dest = key_game;
key_consoleactive = 0;
scr_con_current = 0;
cls.timedemo = true;
cls.td_frames = -2; // skip the first frame
cls.demonum = -1; // stop demo loop
}

93
app/jni/cl_dyntexture.c Normal file
View file

@ -0,0 +1,93 @@
// Andreas Kirsch 07
#include "quakedef.h"
#include "cl_dyntexture.h"
typedef struct dyntexture_s {
// everything after DYNAMIC_TEXTURE_PATH_PREFIX
char name[ MAX_QPATH + 32 ];
// texture pointer (points to r_texture_white at first)
rtexture_t *texture;
} dyntexture_t;
static dyntexture_t dyntextures[ MAX_DYNAMIC_TEXTURE_COUNT ];
static unsigned dyntexturecount;
#define DEFAULT_DYNTEXTURE r_texture_grey128
static dyntexture_t * cl_finddyntexture( const char *name, qboolean warnonfailure ) {
unsigned i;
dyntexture_t *dyntexture = NULL;
// sanity checks - make sure its actually a dynamic texture path
if( !name || !*name || strncmp( name, CLDYNTEXTUREPREFIX, sizeof( CLDYNTEXTUREPREFIX ) - 1 ) != 0 ) {
// TODO: print a warning or something
if (warnonfailure)
Con_Printf( "cl_finddyntexture: Bad dynamic texture name '%s'\n", name );
return NULL;
}
for( i = 0 ; i < dyntexturecount ; i++ ) {
dyntexture = &dyntextures[ i ];
if( dyntexture->name && strcmp( dyntexture->name, name ) == 0 ) {
return dyntexture;
}
}
if( dyntexturecount == MAX_DYNAMIC_TEXTURE_COUNT ) {
// TODO: warn or expand the array, etc.
return NULL;
}
dyntexture = &dyntextures[ dyntexturecount++ ];
strlcpy( dyntexture->name, name, sizeof( dyntexture->name ) );
dyntexture->texture = DEFAULT_DYNTEXTURE;
return dyntexture;
}
rtexture_t * CL_GetDynTexture( const char *name ) {
dyntexture_t *dyntexture = cl_finddyntexture( name, false );
if( dyntexture ) {
return dyntexture->texture;
} else {
return NULL;
}
}
void CL_LinkDynTexture( const char *name, rtexture_t *texture ) {
dyntexture_t *dyntexture;
cachepic_t *cachepic;
skinframe_t *skinframe;
dyntexture = cl_finddyntexture( name, true );
if( !dyntexture ) {
Con_Printf( "CL_LinkDynTexture: internal error in cl_finddyntexture!\n" );
return;
}
// TODO: assert dyntexture != NULL!
if( dyntexture->texture != texture ) {
dyntexture->texture = texture;
cachepic = Draw_CachePic_Flags( name, CACHEPICFLAG_NOTPERSISTENT );
// TODO: assert cachepic and skinframe should be valid pointers...
// TODO: assert cachepic->tex = dyntexture->texture
cachepic->tex = texture;
// update cachepic's size, too
cachepic->width = R_TextureWidth( texture );
cachepic->height = R_TextureHeight( texture );
// update skinframes
skinframe = NULL;
while( (skinframe = R_SkinFrame_FindNextByName( skinframe, name )) != NULL ) {
skinframe->base = texture;
// simply reset the compare* attributes of skinframe
skinframe->comparecrc = 0;
skinframe->comparewidth = skinframe->compareheight = 0;
// this is kind of hacky
}
}
}
void CL_UnlinkDynTexture( const char *name ) {
CL_LinkDynTexture( name, DEFAULT_DYNTEXTURE );
}

20
app/jni/cl_dyntexture.h Normal file
View file

@ -0,0 +1,20 @@
// Andreas 'Black' Kirsch 07
#ifndef CL_DYNTEXTURE_H
#define CL_DYNTEXTURE_H
#define CLDYNTEXTUREPREFIX "_dynamic/"
// always path fully specified names to the dynamic texture functions! (ie. with the _dynamic/ prefix, etc.!)
// return a valid texture handle for a dynamic texture (might be filler texture if it hasnt been initialized yet)
// or NULL if its not a valid dynamic texture name
rtexture_t * CL_GetDynTexture( const char *name );
// link a texture handle as dynamic texture and update texture handles in the renderer and draw_* accordingly
void CL_LinkDynTexture( const char *name, rtexture_t *texture );
// unlink a texture handle from its name
void CL_UnlinkDynTexture( const char *name );
#endif

2297
app/jni/cl_input.c Normal file

File diff suppressed because it is too large Load diff

2499
app/jni/cl_main.c Normal file

File diff suppressed because it is too large Load diff

4278
app/jni/cl_parse.c Normal file

File diff suppressed because it is too large Load diff

3101
app/jni/cl_particles.c Normal file

File diff suppressed because it is too large Load diff

2788
app/jni/cl_screen.c Normal file

File diff suppressed because it is too large Load diff

30
app/jni/cl_screen.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef CL_SCREEN_H
#define CL_SCREEN_H
void SHOWLMP_decodehide(void);
void SHOWLMP_decodeshow(void);
void SHOWLMP_drawall(void);
extern cvar_t vid_conwidth;
extern cvar_t vid_conheight;
extern cvar_t vid_pixelheight;
extern cvar_t scr_screenshot_jpeg;
extern cvar_t scr_screenshot_jpeg_quality;
extern cvar_t scr_screenshot_png;
extern cvar_t scr_screenshot_gammaboost;
extern cvar_t scr_screenshot_name;
void CL_Screen_NewMap(void);
void CL_Screen_Init(void);
void CL_Screen_Shutdown(void);
void CL_BeginUpdateScreen();
void CL_EndUpdateScreen();
void SCR_DrawScreen ();
qboolean R_Stereo_Active(void);
qboolean R_Stereo_ColorMasking(void);
#endif

743
app/jni/cl_video.c Normal file
View file

@ -0,0 +1,743 @@
#include "quakedef.h"
#include "cl_dyntexture.h"
#include "cl_video.h"
// cvars
cvar_t cl_video_subtitles = {CVAR_SAVE, "cl_video_subtitles", "0", "show subtitles for videos (if they are present)"};
cvar_t cl_video_subtitles_lines = {CVAR_SAVE, "cl_video_subtitles_lines", "4", "how many lines to occupy for subtitles"};
cvar_t cl_video_subtitles_textsize = {CVAR_SAVE, "cl_video_subtitles_textsize", "16", "textsize for subtitles"};
cvar_t cl_video_scale = {CVAR_SAVE, "cl_video_scale", "1", "scale of video, 1 = fullscreen, 0.75 - 3/4 of screen etc."};
cvar_t cl_video_scale_vpos = {CVAR_SAVE, "cl_video_scale_vpos", "0", "vertical align of scaled video, -1 is top, 1 is bottom"};
cvar_t cl_video_stipple = {CVAR_SAVE, "cl_video_stipple", "0", "draw interlacing-like effect on videos, similar to scr_stipple but static and used only with video playing."};
cvar_t cl_video_brightness = {CVAR_SAVE, "cl_video_brightness", "1", "brightness of video, 1 = fullbright, 0.75 - 3/4 etc."};
cvar_t cl_video_keepaspectratio = {CVAR_SAVE, "cl_video_keepaspectratio", "0", "keeps aspect ratio of fullscreen videos, leaving black color on unfilled areas, a value of 2 let video to be stretched horizontally with top & bottom being sliced out"};
cvar_t cl_video_fadein = {CVAR_SAVE, "cl_video_fadein", "0", "fading-from-black effect once video is started, in seconds"};
cvar_t cl_video_fadeout = {CVAR_SAVE, "cl_video_fadeout", "0", "fading-to-black effect once video is ended, in seconds"};
cvar_t v_glslgamma_video = {CVAR_SAVE, "v_glslgamma_video", "1", "applies GLSL gamma to played video, could be a fraction, requires r_glslgamma_2d 1."};
// DPV stream decoder
#include "dpvsimpledecode.h"
// VorteX: libavcodec implementation
#include "cl_video_libavw.c"
// JAM video decoder used by Blood Omnicide
#ifdef JAMVIDEO
#include "cl_video_jamdecode.c"
#endif
// constants (and semi-constants)
static int cl_videormask;
static int cl_videobmask;
static int cl_videogmask;
static int cl_videobytesperpixel;
static int cl_num_videos;
static clvideo_t cl_videos[ MAXCLVIDEOS ];
static rtexturepool_t *cl_videotexturepool;
static clvideo_t *FindUnusedVid( void )
{
int i;
for( i = 1 ; i < MAXCLVIDEOS ; i++ )
if( cl_videos[ i ].state == CLVIDEO_UNUSED )
return &cl_videos[ i ];
return NULL;
}
static qboolean OpenStream( clvideo_t * video )
{
const char *errorstring;
video->stream = dpvsimpledecode_open( video, video->filename, &errorstring);
if (video->stream)
return true;
#ifdef JAMVIDEO
video->stream = jam_open( video, video->filename, &errorstring);
if (video->stream)
return true;
#endif
video->stream = LibAvW_OpenVideo( video, video->filename, &errorstring);
if (video->stream)
return true;
Con_Printf("unable to open \"%s\", error: %s\n", video->filename, errorstring);
return false;
}
static void VideoUpdateCallback(rtexture_t *rt, void *data)
{
clvideo_t *video = (clvideo_t *) data;
R_UpdateTexture( video->cpif.tex, (unsigned char *)video->imagedata, 0, 0, 0, video->cpif.width, video->cpif.height, 1 );
}
static void LinkVideoTexture( clvideo_t *video )
{
video->cpif.tex = R_LoadTexture2D( cl_videotexturepool, video->cpif.name, video->cpif.width, video->cpif.height, NULL, TEXTYPE_BGRA, TEXF_PERSISTENT | TEXF_CLAMP, -1, NULL );
R_MakeTextureDynamic( video->cpif.tex, VideoUpdateCallback, video );
CL_LinkDynTexture( video->cpif.name, video->cpif.tex );
}
static void UnlinkVideoTexture( clvideo_t *video )
{
CL_UnlinkDynTexture( video->cpif.name );
// free the texture
R_FreeTexture( video->cpif.tex );
video->cpif.tex = NULL;
// free the image data
Mem_Free( video->imagedata );
}
static void SuspendVideo( clvideo_t * video )
{
if (video->suspended)
return;
video->suspended = true;
UnlinkVideoTexture(video);
// if we are in firstframe mode, also close the stream
if (video->state == CLVIDEO_FIRSTFRAME)
{
if (video->stream)
video->close(video->stream);
video->stream = NULL;
}
}
static qboolean WakeVideo( clvideo_t * video )
{
if( !video->suspended )
return true;
video->suspended = false;
if( video->state == CLVIDEO_FIRSTFRAME )
if( !OpenStream( video ) ) {
video->state = CLVIDEO_UNUSED;
return false;
}
video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
LinkVideoTexture( video );
// update starttime
video->starttime += realtime - video->lasttime;
return true;
}
static void LoadSubtitles( clvideo_t *video, const char *subtitlesfile )
{
char *subtitle_text;
const char *data;
float subtime, sublen;
int numsubs = 0;
if (gamemode == GAME_BLOODOMNICIDE)
{
char overridename[MAX_QPATH];
cvar_t *langcvar;
langcvar = Cvar_FindVar("language");
subtitle_text = NULL;
if (langcvar)
{
dpsnprintf(overridename, sizeof(overridename), "locale/%s/%s", langcvar->string, subtitlesfile);
subtitle_text = (char *)FS_LoadFile(overridename, cls.permanentmempool, false, NULL);
}
if (!subtitle_text)
subtitle_text = (char *)FS_LoadFile(subtitlesfile, cls.permanentmempool, false, NULL);
}
else
{
subtitle_text = (char *)FS_LoadFile(subtitlesfile, cls.permanentmempool, false, NULL);
}
if (!subtitle_text)
{
Con_DPrintf( "LoadSubtitles: can't open subtitle file '%s'!\n", subtitlesfile );
return;
}
// parse subtitle_text
// line is: x y "text" where
// x - start time
// y - seconds last (if 0 - last thru next sub, if negative - last to next sub - this amount of seconds)
data = subtitle_text;
for (;;)
{
if (!COM_ParseToken_QuakeC(&data, false))
break;
subtime = atof( com_token );
if (!COM_ParseToken_QuakeC(&data, false))
break;
sublen = atof( com_token );
if (!COM_ParseToken_QuakeC(&data, false))
break;
if (!com_token[0])
continue;
// check limits
if (video->subtitles == CLVIDEO_MAX_SUBTITLES)
{
Con_Printf("WARNING: CLVIDEO_MAX_SUBTITLES = %i reached when reading subtitles from '%s'\n", CLVIDEO_MAX_SUBTITLES, subtitlesfile);
break;
}
// add a sub
video->subtitle_text[numsubs] = (char *) Mem_Alloc(cls.permanentmempool, strlen(com_token) + 1);
memcpy(video->subtitle_text[numsubs], com_token, strlen(com_token) + 1);
video->subtitle_start[numsubs] = subtime;
video->subtitle_end[numsubs] = sublen;
if (numsubs > 0) // make true len for prev sub, autofix overlapping subtitles
{
if (video->subtitle_end[numsubs-1] <= 0)
video->subtitle_end[numsubs-1] = max(video->subtitle_start[numsubs-1], video->subtitle_start[numsubs] + video->subtitle_end[numsubs-1]);
else
video->subtitle_end[numsubs-1] = min(video->subtitle_start[numsubs-1] + video->subtitle_end[numsubs-1], video->subtitle_start[numsubs]);
}
numsubs++;
// todo: check timing for consistency?
}
if (numsubs > 0) // make true len for prev sub, autofix overlapping subtitles
{
if (video->subtitle_end[numsubs-1] <= 0)
video->subtitle_end[numsubs-1] = 99999999; // fixme: make it end when video ends?
else
video->subtitle_end[numsubs-1] = video->subtitle_start[numsubs-1] + video->subtitle_end[numsubs-1];
}
Z_Free( subtitle_text );
video->subtitles = numsubs;
/*
Con_Printf( "video->subtitles: %i\n", video->subtitles );
for (numsubs = 0; numsubs < video->subtitles; numsubs++)
Con_Printf( " %03.2f %03.2f : %s\n", video->subtitle_start[numsubs], video->subtitle_end[numsubs], video->subtitle_text[numsubs] );
*/
}
static clvideo_t* OpenVideo( clvideo_t *video, const char *filename, const char *name, int owner, const char *subtitlesfile )
{
strlcpy( video->filename, filename, sizeof(video->filename) );
video->ownertag = owner;
if( strncmp( name, CLVIDEOPREFIX, sizeof( CLVIDEOPREFIX ) - 1 ) )
return NULL;
strlcpy( video->cpif.name, name, sizeof(video->cpif.name) );
if( !OpenStream( video ) )
return NULL;
video->state = CLVIDEO_FIRSTFRAME;
video->framenum = -1;
video->framerate = video->getframerate( video->stream );
video->lasttime = realtime;
video->subtitles = 0;
video->cpif.width = video->getwidth( video->stream );
video->cpif.height = video->getheight( video->stream );
video->imagedata = Mem_Alloc( cls.permanentmempool, video->cpif.width * video->cpif.height * cl_videobytesperpixel );
LinkVideoTexture( video );
// VorteX: load simple subtitle_text file
if (subtitlesfile[0])
LoadSubtitles( video, subtitlesfile );
return video;
}
clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner, const char *subtitlesfile )
{
clvideo_t *video;
// sanity check
if( !name || !*name || strncmp( name, CLVIDEOPREFIX, sizeof( CLVIDEOPREFIX ) - 1 ) != 0 ) {
Con_DPrintf( "CL_OpenVideo: Bad video texture name '%s'!\n", name );
return NULL;
}
video = FindUnusedVid();
if( !video ) {
Con_Printf( "CL_OpenVideo: unable to open video \"%s\" - video limit reached\n", filename );
return NULL;
}
video = OpenVideo( video, filename, name, owner, subtitlesfile );
// expand the active range to include the new entry
if (video) {
cl_num_videos = max(cl_num_videos, (int)(video - cl_videos) + 1);
}
return video;
}
static clvideo_t* CL_GetVideoBySlot( int slot )
{
clvideo_t *video = &cl_videos[ slot ];
if( video->suspended )
{
if( !WakeVideo( video ) )
return NULL;
else if( video->state == CLVIDEO_RESETONWAKEUP )
video->framenum = -1;
}
video->lasttime = realtime;
return video;
}
clvideo_t *CL_GetVideoByName( const char *name )
{
int i;
for( i = 0 ; i < cl_num_videos ; i++ )
if( cl_videos[ i ].state != CLVIDEO_UNUSED
&& !strcmp( cl_videos[ i ].cpif.name , name ) )
break;
if( i != cl_num_videos )
return CL_GetVideoBySlot( i );
else
return NULL;
}
void CL_SetVideoState(clvideo_t *video, clvideostate_t state)
{
if (!video)
return;
video->lasttime = realtime;
video->state = state;
if (state == CLVIDEO_FIRSTFRAME)
CL_RestartVideo(video);
}
void CL_RestartVideo(clvideo_t *video)
{
if (!video)
return;
// reset time
video->starttime = video->lasttime = realtime;
video->framenum = -1;
// reopen stream
if (video->stream)
video->close(video->stream);
video->stream = NULL;
if (!OpenStream(video))
video->state = CLVIDEO_UNUSED;
}
// close video
void CL_CloseVideo(clvideo_t * video)
{
int i;
if (!video || video->state == CLVIDEO_UNUSED)
return;
// close stream
if (!video->suspended || video->state != CLVIDEO_FIRSTFRAME)
{
if (video->stream)
video->close(video->stream);
video->stream = NULL;
}
// unlink texture
if (!video->suspended)
UnlinkVideoTexture(video);
// purge subtitles
if (video->subtitles)
{
for (i = 0; i < video->subtitles; i++)
Z_Free( video->subtitle_text[i] );
video->subtitles = 0;
}
video->state = CLVIDEO_UNUSED;
}
// update all videos
void CL_Video_Frame(void)
{
clvideo_t *video;
int destframe;
int i;
if (!cl_num_videos)
return;
for (video = cl_videos, i = 0 ; i < cl_num_videos ; video++, i++)
{
if (video->state != CLVIDEO_UNUSED && !video->suspended)
{
if (realtime - video->lasttime > CLTHRESHOLD)
{
SuspendVideo(video);
continue;
}
if (video->state == CLVIDEO_PAUSE)
{
video->starttime = realtime - video->framenum * video->framerate;
continue;
}
// read video frame from stream if time has come
if (video->state == CLVIDEO_FIRSTFRAME )
destframe = 0;
else
destframe = (int)((realtime - video->starttime) * video->framerate);
if (destframe < 0)
destframe = 0;
if (video->framenum < destframe)
{
do {
video->framenum++;
if (video->decodeframe(video->stream, video->imagedata, cl_videormask, cl_videogmask, cl_videobmask, cl_videobytesperpixel, cl_videobytesperpixel * video->cpif.width))
{
// finished?
CL_RestartVideo(video);
if (video->state == CLVIDEO_PLAY)
video->state = CLVIDEO_FIRSTFRAME;
return;
}
} while(video->framenum < destframe);
R_MarkDirtyTexture(video->cpif.tex);
}
}
}
// stop main video
if (cl_videos->state == CLVIDEO_FIRSTFRAME)
CL_VideoStop();
// reduce range to exclude unnecessary entries
while(cl_num_videos > 0 && cl_videos[cl_num_videos-1].state == CLVIDEO_UNUSED)
cl_num_videos--;
}
void CL_PurgeOwner( int owner )
{
int i;
for (i = 0 ; i < cl_num_videos ; i++)
if (cl_videos[i].ownertag == owner)
CL_CloseVideo(&cl_videos[i]);
}
typedef struct
{
dp_font_t *font;
float x;
float y;
float width;
float height;
float alignment; // 0 = left, 0.5 = center, 1 = right
float fontsize;
float textalpha;
}
cl_video_subtitle_info_t;
static float CL_DrawVideo_WordWidthFunc(void *passthrough, const char *w, size_t *length, float maxWidth)
{
cl_video_subtitle_info_t *si = (cl_video_subtitle_info_t *) passthrough;
if(w == NULL)
return si->fontsize * si->font->maxwidth;
if(maxWidth >= 0)
return DrawQ_TextWidth_UntilWidth(w, length, si->fontsize, si->fontsize, false, si->font, -maxWidth); // -maxWidth: we want at least one char
else if(maxWidth == -1)
return DrawQ_TextWidth(w, *length, si->fontsize, si->fontsize, false, si->font);
else
return 0;
}
static int CL_DrawVideo_DisplaySubtitleLine(void *passthrough, const char *line, size_t length, float width, qboolean isContinuation)
{
cl_video_subtitle_info_t *si = (cl_video_subtitle_info_t *) passthrough;
int x = (int) (si->x + (si->width - width) * si->alignment);
if (length > 0)
DrawQ_String(x, si->y, line, length, si->fontsize, si->fontsize, 1.0, 1.0, 1.0, si->textalpha, 0, NULL, false, si->font);
si->y += si->fontsize;
return 1;
}
int cl_videoplaying = false; // old, but still supported
void CL_DrawVideo(void)
{
clvideo_t *video;
float videotime, px, py, sx, sy, st[8], b;
cl_video_subtitle_info_t si;
int i;
if (!cl_videoplaying)
return;
video = CL_GetVideoBySlot( 0 );
// fix cvars
if (cl_video_scale.value <= 0 || cl_video_scale.value > 1)
Cvar_SetValueQuick( &cl_video_scale, 1);
if (cl_video_brightness.value <= 0 || cl_video_brightness.value > 10)
Cvar_SetValueQuick( &cl_video_brightness, 1);
// calc video proportions
px = 0;
py = 0;
sx = vid_conwidth.integer;
sy = vid_conheight.integer;
st[0] = 0.0; st[1] = 0.0;
st[2] = 1.0; st[3] = 0.0;
st[4] = 0.0; st[5] = 1.0;
st[6] = 1.0; st[7] = 1.0;
if (cl_video_keepaspectratio.integer)
{
float a = video->getaspectratio(video->stream) / ((float)vid.width / (float)vid.height);
if (cl_video_keepaspectratio.integer >= 2)
{
// clip instead of scale
if (a < 1.0) // clip horizontally
{
st[1] = st[3] = (1 - a)*0.5;
st[5] = st[7] = 1 - (1 - a)*0.5;
}
else if (a > 1.0) // clip vertically
{
st[0] = st[4] = (1 - 1/a)*0.5;
st[2] = st[6] = (1/a)*0.5;
}
}
else if (a < 1.0) // scale horizontally
{
px += sx * (1 - a) * 0.5;
sx *= a;
}
else if (a > 1.0) // scale vertically
{
a = 1 / a;
py += sy * (1 - a);
sy *= a;
}
}
if (cl_video_scale.value != 1)
{
px += sx * (1 - cl_video_scale.value) * 0.5;
py += sy * (1 - cl_video_scale.value) * ((bound(-1, cl_video_scale_vpos.value, 1) + 1) / 2);
sx *= cl_video_scale.value;
sy *= cl_video_scale.value;
}
// calc brightness for fadein and fadeout effects
b = cl_video_brightness.value;
if (cl_video_fadein.value && (realtime - video->starttime) < cl_video_fadein.value)
b = pow((realtime - video->starttime)/cl_video_fadein.value, 2);
else if (cl_video_fadeout.value && ((video->starttime + video->framenum * video->framerate) - realtime) < cl_video_fadeout.value)
b = pow(((video->starttime + video->framenum * video->framerate) - realtime)/cl_video_fadeout.value, 2);
// draw black bg in case stipple is active or video is scaled
if (cl_video_stipple.integer || px != 0 || py != 0 || sx != vid_conwidth.integer || sy != vid_conheight.integer)
DrawQ_Fill(0, 0, vid_conwidth.integer, vid_conheight.integer, 0, 0, 0, 1, 0);
#ifndef USE_GLES2
// enable video-only polygon stipple (of global stipple is not active)
if (qglPolygonStipple && !scr_stipple.integer && cl_video_stipple.integer)
{
GLubyte stipple[128];
int i, s, width, parts;
s = cl_video_stipple.integer;
parts = (s & 007);
width = (s & 070) >> 3;
qglEnable(GL_POLYGON_STIPPLE);CHECKGLERROR // 0x0B42
for(i = 0; i < 128; ++i)
{
int line = i/4;
stipple[i] = ((line >> width) & ((1 << parts) - 1)) ? 0x00 : 0xFF;
}
qglPolygonStipple(stipple);CHECKGLERROR
}
#endif
// draw video
if (v_glslgamma_video.value >= 1)
DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, 0);
else
{
DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, 1, st[2], st[3], b, b, b, 1, st[4], st[5], b, b, b, 1, st[6], st[7], b, b, b, 1, DRAWFLAG_NOGAMMA);
if (v_glslgamma_video.value > 0.0)
DrawQ_SuperPic(px, py, &video->cpif, sx, sy, st[0], st[1], b, b, b, v_glslgamma_video.value, st[2], st[3], b, b, b, v_glslgamma_video.value, st[4], st[5], b, b, b, v_glslgamma_video.value, st[6], st[7], b, b, b, v_glslgamma_video.value, 0);
}
#ifndef USE_GLES2
// disable video-only stipple
if (qglPolygonStipple && !scr_stipple.integer && cl_video_stipple.integer)
qglDisable(GL_POLYGON_STIPPLE);CHECKGLERROR
#endif
// VorteX: draw subtitle_text
if (!video->subtitles || !cl_video_subtitles.integer)
return;
// find current subtitle
videotime = realtime - video->starttime;
for (i = 0; i < video->subtitles; i++)
{
if (videotime >= video->subtitle_start[i] && videotime <= video->subtitle_end[i])
{
// found, draw it
si.font = FONT_NOTIFY;
si.x = vid_conwidth.integer * 0.1;
si.y = vid_conheight.integer - (max(1, cl_video_subtitles_lines.value) * cl_video_subtitles_textsize.value);
si.width = vid_conwidth.integer * 0.8;
si.height = max(1, cl_video_subtitles_lines.integer) * cl_video_subtitles_textsize.value;
si.alignment = 0.5;
si.fontsize = cl_video_subtitles_textsize.value;
si.textalpha = min(1, (videotime - video->subtitle_start[i])/0.5) * min(1, ((video->subtitle_end[i] - videotime)/0.3)); // fade in and fade out
COM_Wordwrap(video->subtitle_text[i], strlen(video->subtitle_text[i]), 0, si.width, CL_DrawVideo_WordWidthFunc, &si, CL_DrawVideo_DisplaySubtitleLine, &si);
break;
}
}
}
void CL_VideoStart(char *filename, const char *subtitlesfile)
{
char vabuf[1024];
Host_StartVideo();
if( cl_videos->state != CLVIDEO_UNUSED )
CL_CloseVideo( cl_videos );
// already contains video/
if( !OpenVideo( cl_videos, filename, va(vabuf, sizeof(vabuf), CLDYNTEXTUREPREFIX "%s", filename ), 0, subtitlesfile ) )
return;
// expand the active range to include the new entry
cl_num_videos = max(cl_num_videos, 1);
cl_videoplaying = true;
CL_SetVideoState( cl_videos, CLVIDEO_PLAY );
CL_RestartVideo( cl_videos );
}
void CL_Video_KeyEvent( int key, int ascii, qboolean down )
{
// only react to up events, to allow the user to delay the abortion point if it suddenly becomes interesting..
if( !down ) {
if( key == K_ESCAPE || key == K_ENTER || key == K_MOUSE1 || key == K_SPACE ) {
CL_VideoStop();
}
}
}
void CL_VideoStop(void)
{
cl_videoplaying = false;
CL_CloseVideo( cl_videos );
}
static void CL_PlayVideo_f(void)
{
char name[MAX_QPATH], subtitlesfile[MAX_QPATH];
const char *extension;
Host_StartVideo();
if (COM_CheckParm("-benchmark"))
return;
if (Cmd_Argc() < 2)
{
Con_Print("usage: playvideo <videoname> [custom_subtitles_file]\nplays video named video/<videoname>.dpv\nif custom subtitles file is not presented\nit tries video/<videoname>.sub");
return;
}
extension = FS_FileExtension(Cmd_Argv(1));
if (extension[0])
dpsnprintf(name, sizeof(name), "video/%s", Cmd_Argv(1));
else
dpsnprintf(name, sizeof(name), "video/%s.dpv", Cmd_Argv(1));
if ( Cmd_Argc() > 2)
CL_VideoStart(name, Cmd_Argv(2));
else
{
dpsnprintf(subtitlesfile, sizeof(subtitlesfile), "video/%s.dpsubs", Cmd_Argv(1));
CL_VideoStart(name, subtitlesfile);
}
}
static void CL_StopVideo_f(void)
{
CL_VideoStop();
}
static void cl_video_start( void )
{
int i;
clvideo_t *video;
cl_videotexturepool = R_AllocTexturePool();
for( video = cl_videos, i = 0 ; i < cl_num_videos ; i++, video++ )
if( video->state != CLVIDEO_UNUSED && !video->suspended )
LinkVideoTexture( video );
}
static void cl_video_shutdown( void )
{
int i;
clvideo_t *video;
for( video = cl_videos, i = 0 ; i < cl_num_videos ; i++, video++ )
if( video->state != CLVIDEO_UNUSED && !video->suspended )
SuspendVideo( video );
R_FreeTexturePool( &cl_videotexturepool );
}
static void cl_video_newmap( void )
{
}
void CL_Video_Init( void )
{
union
{
unsigned char b[4];
unsigned int i;
}
bgra;
cl_num_videos = 0;
cl_videobytesperpixel = 4;
// set masks in an endian-independent way (as they really represent bytes)
bgra.i = 0;bgra.b[0] = 0xFF;cl_videobmask = bgra.i;
bgra.i = 0;bgra.b[1] = 0xFF;cl_videogmask = bgra.i;
bgra.i = 0;bgra.b[2] = 0xFF;cl_videormask = bgra.i;
Cmd_AddCommand( "playvideo", CL_PlayVideo_f, "play a .dpv video file" );
Cmd_AddCommand( "stopvideo", CL_StopVideo_f, "stop playing a .dpv video file" );
Cvar_RegisterVariable(&cl_video_subtitles);
Cvar_RegisterVariable(&cl_video_subtitles_lines);
Cvar_RegisterVariable(&cl_video_subtitles_textsize);
Cvar_RegisterVariable(&cl_video_scale);
Cvar_RegisterVariable(&cl_video_scale_vpos);
Cvar_RegisterVariable(&cl_video_brightness);
Cvar_RegisterVariable(&cl_video_stipple);
Cvar_RegisterVariable(&cl_video_keepaspectratio);
Cvar_RegisterVariable(&cl_video_fadein);
Cvar_RegisterVariable(&cl_video_fadeout);
Cvar_RegisterVariable(&v_glslgamma_video);
R_RegisterModule( "CL_Video", cl_video_start, cl_video_shutdown, cl_video_newmap, NULL, NULL );
LibAvW_OpenLibrary();
}
void CL_Video_Shutdown( void )
{
int i;
for (i = 0 ; i < cl_num_videos ; i++)
CL_CloseVideo(&cl_videos[ i ]);
LibAvW_CloseLibrary();
}

97
app/jni/cl_video.h Normal file
View file

@ -0,0 +1,97 @@
#ifndef CL_VIDEO_H
#define CL_VIDEO_H
#include "cl_dyntexture.h"
// yields DYNAMIC_TEXTURE_PATH_PREFIX CLVIDEOPREFIX video name for a path
#define CLVIDEOPREFIX CLDYNTEXTUREPREFIX "video/"
#define CLTHRESHOLD 2.0
#define MENUOWNER 1
typedef enum clvideostate_e
{
CLVIDEO_UNUSED,
CLVIDEO_PLAY,
CLVIDEO_LOOP,
CLVIDEO_PAUSE,
CLVIDEO_FIRSTFRAME,
CLVIDEO_RESETONWAKEUP,
CLVIDEO_STATECOUNT
} clvideostate_t;
#define CLVIDEO_MAX_SUBTITLES 512
extern cvar_t cl_video_subtitles;
extern cvar_t cl_video_subtitles_lines;
extern cvar_t cl_video_subtitles_textsize;
extern cvar_t cl_video_scale;
extern cvar_t cl_video_scale_vpos;
extern cvar_t cl_video_stipple;
extern cvar_t cl_video_brightness;
extern cvar_t cl_video_keepaspectratio;
typedef struct clvideo_s
{
int ownertag;
clvideostate_t state;
// private stuff
void *stream;
double starttime;
int framenum;
double framerate;
void *imagedata;
cachepic_t cpif;
// VorteX: subtitles array
int subtitles;
char *subtitle_text[CLVIDEO_MAX_SUBTITLES];
float subtitle_start[CLVIDEO_MAX_SUBTITLES];
float subtitle_end[CLVIDEO_MAX_SUBTITLES];
// this functions gets filled by video format module
void (*close) (void *stream);
unsigned int (*getwidth) (void *stream);
unsigned int (*getheight) (void *stream);
double (*getframerate) (void *stream);
double (*getaspectratio) (void *stream);
int (*decodeframe) (void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
// if a video is suspended, it is automatically paused (else we'd still have to process the frames)
// used to determine whether the video's resources should be freed or not
double lasttime;
// when lasttime - realtime > THRESHOLD, all but the stream is freed
qboolean suspended;
char filename[MAX_QPATH];
} clvideo_t;
clvideo_t* CL_OpenVideo( const char *filename, const char *name, int owner, const char *subtitlesfile );
clvideo_t* CL_GetVideoByName( const char *name );
void CL_SetVideoState( clvideo_t *video, clvideostate_t state );
void CL_RestartVideo( clvideo_t *video );
void CL_CloseVideo( clvideo_t * video );
void CL_PurgeOwner( int owner );
void CL_Video_Frame( void ); // update all videos
void CL_Video_Init( void );
void CL_Video_Shutdown( void );
// old interface
extern int cl_videoplaying;
void CL_DrawVideo( void );
void CL_VideoStart( char *filename, const char *subtitlesfile );
void CL_VideoStop( void );
// new function used for fullscreen videos
// TODO: Andreas Kirsch: move this subsystem somewhere else (preferably host) since the cl_video system shouldnt do such work like managing key events..
void CL_Video_KeyEvent( int key, int ascii, qboolean down );
#endif

386
app/jni/cl_video_libavw.c Normal file
View file

@ -0,0 +1,386 @@
/*
Libavcodec integration for Darkplaces by Timofeyev Pavel
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
// LordHavoc: for some reason this is being #include'd rather than treated as its own file...
// LordHavoc: adapted to not require stdint.h as this is not available on MSVC++, using unsigned char instead of uint8_t and fs_offset_t instead of int64_t.
// scaler type
#define LIBAVW_SCALER_BILINEAR 0
#define LIBAVW_SCALER_BICUBIC 1
#define LIBAVW_SCALER_X 2
#define LIBAVW_SCALER_POINT 3
#define LIBAVW_SCALER_AREA 4
#define LIBAVW_SCALER_BICUBLIN 5
#define LIBAVW_SCALER_GAUSS 6
#define LIBAVW_SCALER_SINC 7
#define LIBAVW_SCALER_LANCZOS 8
#define LIBAVW_SCALER_SPLINE 9
// output format
#define LIBAVW_PIXEL_FORMAT_BGR 0
#define LIBAVW_PIXEL_FORMAT_BGRA 1
// print levels
#define LIBAVW_PRINT_WARNING 1
#define LIBAVW_PRINT_ERROR 2
#define LIBAVW_PRINT_FATAL 3
#define LIBAVW_PRINT_PANIC 4
// exported callback functions:
typedef void avwCallbackPrint(int, const char *);
typedef int avwCallbackIoRead(void *, unsigned char *, int);
typedef fs_offset_t avwCallbackIoSeek(void *, fs_offset_t, int);
typedef fs_offset_t avwCallbackIoSeekSize(void *);
// exported functions:
int (*qLibAvW_Init)(avwCallbackPrint *printfunction); // init library, returns error code
const char *(*qLibAvW_ErrorString)(int errorcode); // get string for error code
const char *(*qLibAvW_AvcVersion)(void); // get a string containing libavcodec version wrapper was built for
float (*qLibAvW_Version)(void); // get wrapper version
int (*qLibAvW_CreateStream)(void **stream); // create stream, returns error code
void (*qLibAvW_RemoveStream)(void *stream); // flush and remove stream
int (*qLibAvW_StreamGetVideoWidth)(void *stream); // get video parameters of stream
int (*qLibAvW_StreamGetVideoHeight)(void *stream);
double (*qLibAvW_StreamGetFramerate)(void *stream);
int (*qLibAvW_StreamGetError)(void *stream); // get last function errorcode from stream
// simple API to play video
int (*qLibAvW_PlayVideo)(void *stream, void *file, avwCallbackIoRead *IoRead, avwCallbackIoSeek *IoSeek, avwCallbackIoSeekSize *IoSeekSize);
int (*qLibAvW_PlaySeekNextFrame)(void *stream);
int (*qLibAvW_PlayGetFrameImage)(void *stream, int pixel_format, void *imagedata, int imagewidth, int imageheight, int scaler);
static dllfunction_t libavwfuncs[] =
{
{"LibAvW_Init", (void **) &qLibAvW_Init },
{"LibAvW_ErrorString", (void **) &qLibAvW_ErrorString },
{"LibAvW_AvcVersion", (void **) &qLibAvW_AvcVersion },
{"LibAvW_Version", (void **) &qLibAvW_Version },
{"LibAvW_CreateStream", (void **) &qLibAvW_CreateStream },
{"LibAvW_RemoveStream", (void **) &qLibAvW_RemoveStream },
{"LibAvW_StreamGetVideoWidth", (void **) &qLibAvW_StreamGetVideoWidth },
{"LibAvW_StreamGetVideoHeight",(void **) &qLibAvW_StreamGetVideoHeight },
{"LibAvW_StreamGetFramerate", (void **) &qLibAvW_StreamGetFramerate },
{"LibAvW_StreamGetError", (void **) &qLibAvW_StreamGetError },
{"LibAvW_PlayVideo", (void **) &qLibAvW_PlayVideo },
{"LibAvW_PlaySeekNextFrame", (void **) &qLibAvW_PlaySeekNextFrame },
{"LibAvW_PlayGetFrameImage", (void **) &qLibAvW_PlayGetFrameImage },
{NULL, NULL}
};
const char* dllnames_libavw[] =
{
#if defined(WIN32)
"libavw.dll",
#elif defined(MACOSX)
"libavw.dylib",
#else
"libavw.so.1",
"libavw.so",
#endif
NULL
};
static dllhandle_t libavw_dll = NULL;
// DP videostream
typedef struct libavwstream_s
{
qfile_t *file;
double info_framerate;
unsigned int info_imagewidth;
unsigned int info_imageheight;
double info_aspectratio;
void *stream;
// channel the sound file is being played on
sfx_t *sfx;
int sndchan;
int sndstarted;
}
libavwstream_t;
cvar_t cl_video_libavw_minwidth = {CVAR_SAVE, "cl_video_libavw_minwidth", "0", "if videos width is lesser than minimal, thay will be upscaled"};
cvar_t cl_video_libavw_minheight = {CVAR_SAVE, "cl_video_libavw_minheight", "0", "if videos height is lesser than minimal, thay will be upscaled"};
cvar_t cl_video_libavw_scaler = {CVAR_SAVE, "cl_video_libavw_scaler", "1", "selects a scaler for libavcode played videos. Scalers are: 0 - bilinear, 1 - bicubic, 2 - x, 3 - point, 4 - area, 5 - bicublin, 6 - gauss, 7 - sinc, 8 - lanczos, 9 - spline."};
// video extensions
const char* libavw_extensions[] =
{
"ogv",
"avi",
"mpg",
"mp4",
"mkv",
"webm",
"bik",
"roq",
"flv",
"wmv",
"mpeg",
"mjpeg",
"mpeg4",
NULL
};
/*
=================================================================
Video decoding
a features that is not supported yet and likely to be done
- streaming audio from videofiles
- streaming subtitles
=================================================================
*/
unsigned int libavw_getwidth(void *stream);
unsigned int libavw_getheight(void *stream);
double libavw_getframerate(void *stream);
double libavw_getaspectratio(void *stream);
void libavw_close(void *stream);
static int libavw_decodeframe(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
{
int pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
int errorcode;
libavwstream_t *s = (libavwstream_t *)stream;
// start sound
if (!s->sndstarted)
{
if (s->sfx != NULL)
s->sndchan = S_StartSound(-1, 0, s->sfx, vec3_origin, 1.0f, 0);
s->sndstarted = 1;
}
// read frame
if (!qLibAvW_PlaySeekNextFrame(s->stream))
{
// got error or file end
errorcode = qLibAvW_StreamGetError(s->stream);
if (errorcode)
Con_Printf("LibAvW: %s\n", qLibAvW_ErrorString(errorcode));
return 1;
}
// decode into bgr texture
if (bytesperpixel == 4)
pixel_format = LIBAVW_PIXEL_FORMAT_BGRA;
else if (bytesperpixel == 3)
pixel_format = LIBAVW_PIXEL_FORMAT_BGR;
else
{
Con_Printf("LibAvW: cannot determine pixel format for bpp %i\n", bytesperpixel);
return 1;
}
if (!qLibAvW_PlayGetFrameImage(s->stream, pixel_format, imagedata, s->info_imagewidth, s->info_imageheight, min(9, max(0, cl_video_libavw_scaler.integer))))
Con_Printf("LibAvW: %s\n", qLibAvW_ErrorString(qLibAvW_StreamGetError(s->stream)));
return 0;
}
// get stream info
unsigned int libavw_getwidth(void *stream)
{
return ((libavwstream_t *)stream)->info_imagewidth;
}
unsigned int libavw_getheight(void *stream)
{
return ((libavwstream_t *)stream)->info_imageheight;
}
double libavw_getframerate(void *stream)
{
return ((libavwstream_t *)stream)->info_framerate;
}
double libavw_getaspectratio(void *stream)
{
return ((libavwstream_t *)stream)->info_aspectratio;
}
// close stream
void libavw_close(void *stream)
{
libavwstream_t *s = (libavwstream_t *)stream;
if (s->stream)
qLibAvW_RemoveStream(s->stream);
s->stream = NULL;
if (s->file)
FS_Close(s->file);
s->file = NULL;
if (s->sndchan >= 0)
S_StopChannel(s->sndchan, true, true);
s->sndchan = -1;
}
// IO wrapper
static int LibAvW_FS_Read(void *opaque, unsigned char *buf, int buf_size)
{
return FS_Read((qfile_t *)opaque, buf, buf_size);
}
static fs_offset_t LibAvW_FS_Seek(void *opaque, fs_offset_t pos, int whence)
{
return (fs_offset_t)FS_Seek((qfile_t *)opaque, pos, whence);
}
static fs_offset_t LibAvW_FS_SeekSize(void *opaque)
{
return (fs_offset_t)FS_FileSize((qfile_t *)opaque);
}
// open as DP video stream
static void *LibAvW_OpenVideo(clvideo_t *video, char *filename, const char **errorstring)
{
libavwstream_t *s;
char filebase[MAX_OSPATH], check[MAX_OSPATH];
unsigned int i;
int errorcode;
char *wavename;
size_t len;
if (!libavw_dll)
return NULL;
// allocate stream
s = (libavwstream_t *)Z_Malloc(sizeof(libavwstream_t));
if (s == NULL)
{
*errorstring = "unable to allocate memory for stream info structure";
return NULL;
}
memset(s, 0, sizeof(libavwstream_t));
s->sndchan = -1;
// open file
s->file = FS_OpenVirtualFile(filename, true);
if (!s->file)
{
FS_StripExtension(filename, filebase, sizeof(filebase));
// we tried .dpv, try another extensions
for (i = 0; libavw_extensions[i] != NULL; i++)
{
dpsnprintf(check, sizeof(check), "%s.%s", filebase, libavw_extensions[i]);
s->file = FS_OpenVirtualFile(check, true);
if (s->file)
break;
}
if (!s->file)
{
*errorstring = "unable to open videofile";
libavw_close(s);
Z_Free(s);
return NULL;
}
}
// allocate libavw stream
if ((errorcode = qLibAvW_CreateStream(&s->stream)))
{
*errorstring = qLibAvW_ErrorString(errorcode);
libavw_close(s);
Z_Free(s);
return NULL;
}
// open video for playing
if (!qLibAvW_PlayVideo(s->stream, s->file, &LibAvW_FS_Read, &LibAvW_FS_Seek, &LibAvW_FS_SeekSize))
{
*errorstring = qLibAvW_ErrorString(qLibAvW_StreamGetError(s->stream));
libavw_close(s);
Z_Free(s);
return NULL;
}
// all right, start codec
s->info_imagewidth = qLibAvW_StreamGetVideoWidth(s->stream);
s->info_imageheight = qLibAvW_StreamGetVideoHeight(s->stream);
s->info_framerate = qLibAvW_StreamGetFramerate(s->stream);
s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
video->close = libavw_close;
video->getwidth = libavw_getwidth;
video->getheight = libavw_getheight;
video->getframerate = libavw_getframerate;
video->decodeframe = libavw_decodeframe;
video->getaspectratio = libavw_getaspectratio;
// apply min-width, min-height, keep aspect rate
if (cl_video_libavw_minwidth.integer > 0)
s->info_imagewidth = max(s->info_imagewidth, (unsigned int)cl_video_libavw_minwidth.integer);
if (cl_video_libavw_minheight.integer > 0)
s->info_imageheight = max(s->info_imageheight, (unsigned int)cl_video_libavw_minheight.integer);
// provide sound in separate .wav
len = strlen(filename) + 10;
wavename = (char *)Z_Malloc(len);
if (wavename)
{
FS_StripExtension(filename, wavename, len-1);
strlcat(wavename, ".wav", len);
s->sfx = S_PrecacheSound(wavename, false, false);
s->sndchan = -1;
Z_Free(wavename);
}
return s;
}
static void libavw_message(int level, const char *message)
{
if (level == LIBAVW_PRINT_WARNING)
Con_Printf("LibAvcodec warning: %s\n", message);
else if (level == LIBAVW_PRINT_ERROR)
Con_Printf("LibAvcodec error: %s\n", message);
else if (level == LIBAVW_PRINT_FATAL)
Con_Printf("LibAvcodec fatal error: %s\n", message);
else
Con_Printf("LibAvcodec panic: %s\n", message);
}
static qboolean LibAvW_OpenLibrary(void)
{
int errorcode;
// COMMANDLINEOPTION: Video: -nolibavw disables libavcodec wrapper support
if (COM_CheckParm("-nolibavw"))
return false;
// load DLL's
Sys_LoadLibrary(dllnames_libavw, &libavw_dll, libavwfuncs);
if (!libavw_dll)
return false;
// initialize libav wrapper
if ((errorcode = qLibAvW_Init(&libavw_message)))
{
Con_Printf("LibAvW failed to initialize: %s\n", qLibAvW_ErrorString(errorcode));
Sys_UnloadLibrary(&libavw_dll);
}
Cvar_RegisterVariable(&cl_video_libavw_minwidth);
Cvar_RegisterVariable(&cl_video_libavw_minheight);
Cvar_RegisterVariable(&cl_video_libavw_scaler);
return true;
}
static void LibAvW_CloseLibrary(void)
{
Sys_UnloadLibrary(&libavw_dll);
}

2052
app/jni/client.h Normal file

File diff suppressed because it is too large Load diff

98
app/jni/clprogdefs.h Normal file
View file

@ -0,0 +1,98 @@
/* file generated by qcc, do not modify */
#ifndef CLPROGDEFS_H
#define CLPROGDEFS_H
/*
typedef struct cl_globalvars_s
{
int pad[28];
int self;
int other;
int world;
float time;
float frametime;
float player_localentnum;
float player_localnum;
float maxclients;
float clientcommandframe;
float servercommandframe;
string_t mapname;
vec3_t v_forward;
vec3_t v_up;
vec3_t v_right;
float trace_allsolid;
float trace_startsolid;
float trace_fraction;
vec3_t trace_endpos;
vec3_t trace_plane_normal;
float trace_plane_dist;
int trace_ent;
float trace_inopen;
float trace_inwater;
func_t CSQC_Init;
func_t CSQC_Shutdown;
func_t CSQC_InputEvent;
func_t CSQC_UpdateView;
func_t CSQC_ConsoleCommand;
vec3_t pmove_org;
vec3_t pmove_vel;
vec3_t pmove_mins;
vec3_t pmove_maxs;
float input_timelength;
vec3_t input_angles;
vec3_t input_movevalues;
float input_buttons;
float movevar_gravity;
float movevar_stopspeed;
float movevar_maxspeed;
float movevar_spectatormaxspeed;
float movevar_accelerate;
float movevar_airaccelerate;
float movevar_wateraccelerate;
float movevar_friction;
float movevar_waterfriction;
float movevar_entgravity;
} cl_globalvars_t;
typedef struct cl_entvars_s
{
float modelindex;
vec3_t absmin;
vec3_t absmax;
float entnum;
float drawmask;
func_t predraw;
float movetype;
float solid;
vec3_t origin;
vec3_t oldorigin;
vec3_t velocity;
vec3_t angles;
vec3_t avelocity;
string_t classname;
string_t model;
float frame;
float skin;
float effects;
vec3_t mins;
vec3_t maxs;
vec3_t size;
func_t touch;
func_t use;
func_t think;
func_t blocked;
float nextthink;
int chain;
string_t netname;
int enemy;
float flags;
float colormap;
int owner;
} cl_entvars_t;
#define CL_PROGHEADER_CRC 52195
*/
#endif

5007
app/jni/clvm_cmds.c Normal file

File diff suppressed because it is too large Load diff

27
app/jni/clvm_cmds.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef __CLVM_CMDS_H__
#define __CLVM_CMDS_H__
/* These are VM built-ins that originate in the client-side programs support
but are reused by the other programs (usually the menu). */
void VM_CL_setmodel (void);
void VM_CL_precache_model (void);
void VM_CL_setorigin (void);
void VM_CL_R_AddDynamicLight (void);
void VM_CL_R_ClearScene (void);
void VM_CL_R_AddEntities (void);
void VM_CL_R_AddEntity (void);
void VM_CL_R_SetView (void);
void VM_CL_R_RenderScene (void);
void VM_CL_R_LoadWorldModel (void);
void VM_CL_R_PolygonBegin (void);
void VM_CL_R_PolygonVertex (void);
void VM_CL_R_PolygonEnd (void);
void VM_CL_setattachment(void);
void VM_CL_gettagindex(void);
void VM_CL_gettaginfo(void);
#endif /* __CLVM_CMDS_H__ */

2233
app/jni/cmd.c Normal file

File diff suppressed because it is too large Load diff

173
app/jni/cmd.h Normal file
View file

@ -0,0 +1,173 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cmd.h -- Command buffer and command execution
//===========================================================================
/*
Any number of commands can be added in a frame, from several different sources.
Most commands come from either keybindings or console line input, but remote
servers can also send across commands and entire text files can be execed.
The + command line options are also added to the command buffer.
The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
*/
#ifndef CMD_H
#define CMD_H
/// allocates an initial text buffer that will grow as needed
void Cbuf_Init (void);
void Cmd_Init_Commands (void);
void Cbuf_Shutdown (void);
/*! as new commands are generated from the console or keybindings,
* the text is added to the end of the command buffer.
*/
void Cbuf_AddText (const char *text);
/*! when a command wants to issue other commands immediately, the text is
* inserted at the beginning of the buffer, before any remaining unexecuted
* commands.
*/
void Cbuf_InsertText (const char *text);
/*! Pulls off terminated lines of text from the command buffer and sends
* them through Cmd_ExecuteString. Stops when the buffer is empty.
* Normally called once per frame, but may be explicitly invoked.
* \note Do not call inside a command function!
*/
void Cbuf_Execute (void);
/*! Performs deferred commands and runs Cbuf_Execute, called by Host_Main */
void Cbuf_Frame (void);
//===========================================================================
/*
Command execution takes a null terminated string, breaks it into tokens,
then searches for a command or variable that matches the first token.
Commands can come from three sources, but the handler functions may choose
to dissallow the action or forward it to a remote server if the source is
not apropriate.
*/
typedef void (*xcommand_t) (void);
typedef enum
{
src_client, ///< came in over a net connection as a clc_stringcmd
///< host_client will be valid during this state.
src_command ///< from the command buffer
} cmd_source_t;
extern cmd_source_t cmd_source;
void Cmd_Init (void);
void Cmd_Shutdown (void);
// called by Host_Init, this marks cvars, commands and aliases with their init values
void Cmd_SaveInitState (void);
// called by FS_GameDir_f, this restores cvars, commands and aliases to init values
void Cmd_RestoreInitState (void);
void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolefunction, xcommand_t clientfunction, const char *description);
void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description);
// called by the init functions of other parts of the program to
// register commands and functions to call for them.
// The cmd_name is referenced later, so it should not be in temp memory
/// used by the cvar code to check for cvar / command name overlap
qboolean Cmd_Exists (const char *cmd_name);
/// attempts to match a partial command for automatic command line completion
/// returns NULL if nothing fits
const char *Cmd_CompleteCommand (const char *partial);
int Cmd_CompleteAliasCountPossible (const char *partial);
const char **Cmd_CompleteAliasBuildList (const char *partial);
int Cmd_CompleteCountPossible (const char *partial);
const char **Cmd_CompleteBuildList (const char *partial);
void Cmd_CompleteCommandPrint (const char *partial);
const char *Cmd_CompleteAlias (const char *partial);
void Cmd_CompleteAliasPrint (const char *partial);
// Enhanced console completion by Fett erich@heintz.com
// Added by EvilTypeGuy eviltypeguy@qeradiant.com
int Cmd_Argc (void);
const char *Cmd_Argv (int arg);
const char *Cmd_Args (void);
// The functions that execute commands get their parameters with these
// functions. Cmd_Argv () will return an empty string, not a NULL
// if arg > argc, so string operations are always safe.
/// Returns the position (1 to argc-1) in the command's argument list
/// where the given parameter apears, or 0 if not present
int Cmd_CheckParm (const char *parm);
//void Cmd_TokenizeString (char *text);
// Takes a null terminated string. Does not need to be /n terminated.
// breaks the string up into arg tokens.
/// Parses a single line of text into arguments and tries to execute it.
/// The text can come from the command buffer, a remote client, or stdin.
void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex);
/// adds the string as a clc_stringcmd to the client message.
/// (used when there is no reason to generate a local command to do it)
void Cmd_ForwardStringToServer (const char *s);
/// adds the current command line as a clc_stringcmd to the client message.
/// things like godmode, noclip, etc, are commands directed to the server,
/// so when they are typed in at the console, they will need to be forwarded.
void Cmd_ForwardToServer (void);
/// used by command functions to send output to either the graphics console or
/// passed as a print message to the client
void Cmd_Print(const char *text);
/// quotes a string so that it can be used as a command argument again;
/// quoteset is a string that contains one or more of ", \, $ and specifies
/// the characters to be quoted (you usually want to either pass "\"\\" or
/// "\"\\$"). Returns true on success, and false on overrun (in which case out
/// will contain a part of the quoted string). If putquotes is set, the
/// enclosing quote marks are also put.
qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes);
void Cmd_ClearCsqcFuncs (void);
#endif

1988
app/jni/collision.c Normal file

File diff suppressed because it is too large Load diff

191
app/jni/collision.h Normal file
View file

@ -0,0 +1,191 @@
#ifndef COLLISION_H
#define COLLISION_H
typedef struct plane_s
{
vec3_t normal;
float dist;
}
plane_t;
struct texture_s;
typedef struct trace_s
{
// if true, the entire trace was in solid (see hitsupercontentsmask)
int allsolid;
// if true, the initial point was in solid (see hitsupercontentsmask)
int startsolid;
// this is set to true in world.c if startsolid was set in a trace against world
int worldstartsolid;
// this is set to true in world.c if startsolid was set in a trace against a SOLID_BSP entity, in other words this is true if the entity is stuck in a door or wall, but not if stuck in another normal entity
int bmodelstartsolid;
// if true, the trace passed through empty somewhere
// (set only by Q1BSP tracing)
int inopen;
// if true, the trace passed through water/slime/lava somewhere
// (set only by Q1BSP tracing)
int inwater;
// fraction of the total distance that was traveled before impact
// (1.0 = did not hit anything)
double fraction;
// like fraction but is not nudged away from the surface (better for
// comparisons between two trace structs, as only one nudge for the final
// result is ever needed)
double realfraction;
// final position of the trace (simply a point between start and end)
double endpos[3];
// surface normal at impact (not really correct for edge collisions)
plane_t plane;
// entity the surface is on
// (not set by trace functions, only by physics)
void *ent;
// which SUPERCONTENTS bits to collide with, I.E. to consider solid
// (this also affects startsolid/allsolid)
int hitsupercontentsmask;
// the supercontents mask at the start point
int startsupercontents;
// the supercontents of the impacted surface
int hitsupercontents;
// the q3 surfaceflags of the impacted surface
int hitq3surfaceflags;
// the texture of the impacted surface
const struct texture_s *hittexture;
// initially false, set when the start leaf is found
// (set only by Q1BSP tracing and entity box tracing)
int startfound;
// if startsolid, contains the minimum penetration depth found in the
// trace, and the normal needed to push it out of that solid
double startdepth;
double startdepthnormal[3];
}
trace_t;
void Collision_Init(void);
void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture);
void Collision_ClipTrace_Point(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, int hitsupercontentsmask, int boxsupercontents, int boxq3surfaceflags, const texture_t *boxtexture);
void Collision_Cache_Reset(qboolean resetlimits);
void Collision_Cache_Init(mempool_t *mempool);
void Collision_Cache_NewFrame(void);
typedef struct colpointf_s
{
vec3_t v;
}
colpointf_t;
typedef struct colplanef_s
{
const struct texture_s *texture;
int q3surfaceflags;
vec3_t normal;
vec_t dist;
}
colplanef_t;
typedef struct colbrushf_s
{
// culling box
vec3_t mins;
vec3_t maxs;
// used to avoid tracing against the same brush more than once per sweep
int markframe;
// the content flags of this brush
int supercontents;
// bounding planes (face planes) of this brush
int numplanes;
colplanef_t *planes;
// edge directions (normals) of this brush
int numedgedirs;
colpointf_t *edgedirs;
// points (corners) of this brush
int numpoints;
colpointf_t *points;
// renderable triangles representing this brush, using the points
int numtriangles;
int *elements;
// texture data for cases where an edgedir is used
const struct texture_s *texture;
int q3surfaceflags;
// optimized collisions for common cases
int isaabb; // indicates this is an axis aligned box
int hasaabbplanes; // indicates this has precomputed planes for AABB collisions
}
colbrushf_t;
typedef struct colboxbrushf_s
{
colpointf_t points[8];
colpointf_t edgedirs[6];
colplanef_t planes[6];
colbrushf_t brush;
}
colboxbrushf_t;
void Collision_CalcPlanesForTriangleBrushFloat(colbrushf_t *brush);
colbrushf_t *Collision_AllocBrushFromPermanentPolygonFloat(mempool_t *mempool, int numpoints, float *points, int supercontents, int q3surfaceflags, const texture_t *texture);
colbrushf_t *Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalplanes, const colplanef_t *originalplanes, int supercontents, int q3surfaceflags, const texture_t *texture, int hasaabbplanes);
void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const colbrushf_t *thatbrush_start, const colbrushf_t *thatbrush_end);
void Collision_TraceBrushTriangleMeshFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int numtriangles, const int *element3i, const float *vertex3f, int stride, float *bbox6f, int supercontents, int q3surfaceflags, const texture_t *texture, const vec3_t segmentmins, const vec3_t segmentmaxs);
void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const colbrushf_t *thatbrush_start, const colbrushf_t *thatbrush_end);
void Collision_TraceLineTriangleMeshFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, int numtriangles, const int *element3i, const float *vertex3f, int stride, float *bbox6f, int supercontents, int q3surfaceflags, const texture_t *texture, const vec3_t segmentmins, const vec3_t segmentmaxs);
void Collision_TracePointBrushFloat(trace_t *trace, const vec3_t point, const colbrushf_t *thatbrush);
qboolean Collision_PointInsideBrushFloat(const vec3_t point, const colbrushf_t *brush);
void Collision_BrushForBox(colboxbrushf_t *boxbrush, const vec3_t mins, const vec3_t maxs, int supercontents, int q3surfaceflags, const texture_t *texture);
void Collision_BoundingBoxOfBrushTraceSegment(const colbrushf_t *start, const colbrushf_t *end, vec3_t mins, vec3_t maxs, float startfrac, float endfrac);
float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double *sphereorigin, double sphereradius, double *impactpoint, double *impactnormal);
void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const float *point0, const float *point1, const float *point2, int supercontents, int q3surfaceflags, const texture_t *texture);
void Collision_TraceBrushTriangleFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const float *v0, const float *v1, const float *v2, int supercontents, int q3surfaceflags, const texture_t *texture);
// traces a box move against a single entity
// mins and maxs are relative
//
// if the entire move stays in a single solid brush, trace.allsolid will be set
//
// if the starting point is in a solid, it will be allowed to move out to an
// open area, and trace.startsolid will be set
//
// type is one of the MOVE_ values such as MOVE_NOMONSTERS which skips box
// entities, only colliding with SOLID_BSP entities (doors, lifts)
//
// passedict is excluded from clipping checks
struct frameblend_s;
struct skeleton_s;
void Collision_ClipToGenericEntity(trace_t *trace, dp_model_t *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontentsmask);
void Collision_ClipLineToGenericEntity(trace_t *trace, dp_model_t *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask, qboolean hitsurfaces);
void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, const struct frameblend_s *frameblend, const struct skeleton_s *skeleton, const vec3_t bodymins, const vec3_t bodymaxs, int bodysupercontents, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, int hitsupercontentsmask);
// like above but does not do a transform and does nothing if model is NULL
void Collision_ClipToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int hitsupercontents);
void Collision_ClipLineToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents, qboolean hitsurfaces);
void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents);
// caching surface trace for renderer (NOT THREAD SAFE)
void Collision_Cache_ClipLineToGenericEntitySurfaces(trace_t *trace, dp_model_t *model, matrix4x4_t *matrix, matrix4x4_t *inversematrix, const vec3_t start, const vec3_t end, int hitsupercontentsmask);
void Collision_Cache_ClipLineToWorldSurfaces(trace_t *trace, dp_model_t *model, const vec3_t start, const vec3_t end, int hitsupercontents);
// combines data from two traces:
// merges contents flags, startsolid, allsolid, inwater
// updates fraction, endpos, plane and surface info if new fraction is shorter
void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *touch, qboolean isbmodel);
// shorten a trace by the given factor
void Collision_ShortenTrace(trace_t *trace, float shorten_factor, const vec3_t end);
// this enables rather large debugging spew!
// settings:
// 0 = no spew
// 1 = spew trace calls if something odd is happening
// 2 = spew trace calls always
// 3 = spew detailed trace flow (bsp tree recursion info)
#define COLLISIONPARANOID 0
// make every trace <collision_endposnudge>qu longer, and shorten the result, to work around a stupid bug somewhere
#define COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
#ifdef COLLISION_STUPID_TRACE_ENDPOS_IN_SOLID_WORKAROUND
extern cvar_t collision_endposnudge;
#endif
#endif

2276
app/jni/common.c Normal file

File diff suppressed because it is too large Load diff

380
app/jni/common.h Normal file
View file

@ -0,0 +1,380 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef COMMON_H
#define COMMON_H
/// MSVC has a different name for several standard functions
#ifdef WIN32
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
#endif
// Create our own define for Mac OS X
#if defined(__APPLE__) && defined(__MACH__)
# define MACOSX
#endif
#ifdef SUNOS
#include <sys/file.h> ///< Needed for FNDELAY
#endif
//============================================================================
typedef struct sizebuf_s
{
qboolean allowoverflow; ///< if false, do a Sys_Error
qboolean overflowed; ///< set to true if the buffer size failed
unsigned char *data;
int maxsize;
int cursize;
int readcount;
qboolean badread; // set if a read goes beyond end of message
} sizebuf_t;
void SZ_Clear (sizebuf_t *buf);
unsigned char *SZ_GetSpace (sizebuf_t *buf, int length);
void SZ_Write (sizebuf_t *buf, const unsigned char *data, int length);
void SZ_HexDumpToConsole(const sizebuf_t *buf);
void Com_HexDumpToConsole(const unsigned char *data, int size);
unsigned short CRC_Block(const unsigned char *data, size_t size);
unsigned short CRC_Block_CaseInsensitive(const unsigned char *data, size_t size); // for hash lookup functions that use strcasecmp for comparison
unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence);
// these are actually md4sum (mdfour.c)
unsigned Com_BlockChecksum (void *buffer, int length);
void Com_BlockFullChecksum (void *buffer, int len, unsigned char *outbuf);
void COM_Init_Commands(void);
//============================================================================
// Endianess handling
//============================================================================
// check mem_bigendian if you need to know the system byte order
/*! \name Byte order functions.
* @{
*/
// unaligned memory access crashes on some platform, so always read bytes...
#define BigShort(l) BuffBigShort((unsigned char *)&(l))
#define LittleShort(l) BuffLittleShort((unsigned char *)&(l))
#define BigLong(l) BuffBigLong((unsigned char *)&(l))
#define LittleLong(l) BuffLittleLong((unsigned char *)&(l))
#define BigFloat(l) BuffBigFloat((unsigned char *)&(l))
#define LittleFloat(l) BuffLittleFloat((unsigned char *)&(l))
/// Extract a big endian 32bit float from the given \p buffer.
float BuffBigFloat (const unsigned char *buffer);
/// Extract a big endian 32bit int from the given \p buffer.
int BuffBigLong (const unsigned char *buffer);
/// Extract a big endian 16bit short from the given \p buffer.
short BuffBigShort (const unsigned char *buffer);
/// Extract a little endian 32bit float from the given \p buffer.
float BuffLittleFloat (const unsigned char *buffer);
/// Extract a little endian 32bit int from the given \p buffer.
int BuffLittleLong (const unsigned char *buffer);
/// Extract a little endian 16bit short from the given \p buffer.
short BuffLittleShort (const unsigned char *buffer);
/// Encode a big endian 32bit int to the given \p buffer
void StoreBigLong (unsigned char *buffer, unsigned int i);
/// Encode a big endian 16bit int to the given \p buffer
void StoreBigShort (unsigned char *buffer, unsigned short i);
/// Encode a little endian 32bit int to the given \p buffer
void StoreLittleLong (unsigned char *buffer, unsigned int i);
/// Encode a little endian 16bit int to the given \p buffer
void StoreLittleShort (unsigned char *buffer, unsigned short i);
//@}
//============================================================================
// these versions are purely for internal use, never sent in network protocol
// (use Protocol_EnumForNumber and Protocol_NumberToEnum to convert)
typedef enum protocolversion_e
{
PROTOCOL_UNKNOWN,
PROTOCOL_DARKPLACES7, ///< added QuakeWorld-style movement protocol to allow more consistent prediction
PROTOCOL_DARKPLACES6, ///< various changes
PROTOCOL_DARKPLACES5, ///< uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at http://www.garagegames.com/articles/networking1/
PROTOCOL_DARKPLACES4, ///< various changes
PROTOCOL_DARKPLACES3, ///< uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snapshot updates on a QuakeWorld-like protocol, but it is broken and impossible to fix
PROTOCOL_DARKPLACES2, ///< various changes
PROTOCOL_DARKPLACES1, ///< uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta compression method
PROTOCOL_QUAKEDP, ///< darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as no extended features are used
PROTOCOL_NEHAHRAMOVIE, ///< Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but only ever used by neh_gl.exe), this is potentially backwards compatible with quake protocol as long as no extended features are used (but in actuality the neh_gl.exe which wrote this protocol ALWAYS wrote the extended information)
PROTOCOL_QUAKE, ///< quake (aka netquake/normalquake/nq) protocol
PROTOCOL_QUAKEWORLD, ///< quakeworld protocol
PROTOCOL_NEHAHRABJP, ///< same as QUAKEDP but with 16bit modelindex
PROTOCOL_NEHAHRABJP2, ///< same as NEHAHRABJP but with 16bit soundindex
PROTOCOL_NEHAHRABJP3 ///< same as NEHAHRABJP2 but with some changes
}
protocolversion_t;
/*! \name Message IO functions.
* Handles byte ordering and avoids alignment errors
* @{
*/
void MSG_InitReadBuffer (sizebuf_t *buf, unsigned char *data, int size);
void MSG_WriteChar (sizebuf_t *sb, int c);
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteLong (sizebuf_t *sb, int c);
void MSG_WriteFloat (sizebuf_t *sb, vec_t f);
void MSG_WriteString (sizebuf_t *sb, const char *s);
void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s);
void MSG_WriteAngle8i (sizebuf_t *sb, vec_t f);
void MSG_WriteAngle16i (sizebuf_t *sb, vec_t f);
void MSG_WriteAngle32f (sizebuf_t *sb, vec_t f);
void MSG_WriteCoord13i (sizebuf_t *sb, vec_t f);
void MSG_WriteCoord16i (sizebuf_t *sb, vec_t f);
void MSG_WriteCoord32f (sizebuf_t *sb, vec_t f);
void MSG_WriteCoord (sizebuf_t *sb, vec_t f, protocolversion_t protocol);
void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol);
void MSG_WriteAngle (sizebuf_t *sb, vec_t f, protocolversion_t protocol);
void MSG_BeginReading (sizebuf_t *sb);
int MSG_ReadLittleShort (sizebuf_t *sb);
int MSG_ReadBigShort (sizebuf_t *sb);
int MSG_ReadLittleLong (sizebuf_t *sb);
int MSG_ReadBigLong (sizebuf_t *sb);
float MSG_ReadLittleFloat (sizebuf_t *sb);
float MSG_ReadBigFloat (sizebuf_t *sb);
char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring);
int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out);
#define MSG_ReadChar(sb) ((sb)->readcount >= (sb)->cursize ? ((sb)->badread = true, -1) : (signed char)(sb)->data[(sb)->readcount++])
#define MSG_ReadByte(sb) ((sb)->readcount >= (sb)->cursize ? ((sb)->badread = true, -1) : (unsigned char)(sb)->data[(sb)->readcount++])
#define MSG_ReadShort MSG_ReadLittleShort
#define MSG_ReadLong MSG_ReadLittleLong
#define MSG_ReadFloat MSG_ReadLittleFloat
float MSG_ReadAngle8i (sizebuf_t *sb);
float MSG_ReadAngle16i (sizebuf_t *sb);
float MSG_ReadAngle32f (sizebuf_t *sb);
float MSG_ReadCoord13i (sizebuf_t *sb);
float MSG_ReadCoord16i (sizebuf_t *sb);
float MSG_ReadCoord32f (sizebuf_t *sb);
float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol);
void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol);
float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol);
//@}
//============================================================================
typedef float (*COM_WordWidthFunc_t) (void *passthrough, const char *w, size_t *length, float maxWidth); // length is updated to the longest fitting string into maxWidth; if maxWidth < 0, all characters are used and length is used as is
typedef int (*COM_LineProcessorFunc) (void *passthrough, const char *line, size_t length, float width, qboolean isContination);
int COM_Wordwrap(const char *string, size_t length, float continuationSize, float maxWidth, COM_WordWidthFunc_t wordWidth, void *passthroughCW, COM_LineProcessorFunc processLine, void *passthroughPL);
extern char com_token[MAX_INPUTLINE];
int COM_ParseToken_Simple(const char **datapointer, qboolean returnnewline, qboolean parsebackslash, qboolean parsecomments);
int COM_ParseToken_QuakeC(const char **datapointer, qboolean returnnewline);
int COM_ParseToken_VM_Tokenize(const char **datapointer, qboolean returnnewline);
int COM_ParseToken_Console(const char **datapointer);
extern int com_argc;
extern const char **com_argv;
extern int com_selffd;
int COM_CheckParm (const char *parm);
void COM_Init (void);
void COM_Shutdown (void);
void COM_InitGameType (void);
char *va(char *buf, size_t buflen, const char *format, ...) DP_FUNC_PRINTF(3);
char *portable_va(char *buf, size_t buflen, const char *format, ...) DP_FUNC_PRINTF(3);
// does a varargs printf into provided buffer, returns buffer (so it can be called in-line unlike dpsnprintf)
// snprintf and vsnprintf are NOT portable. Use their DP counterparts instead
#ifdef snprintf
# undef snprintf
#endif
#define snprintf DO_NOT_USE_SNPRINTF__USE_DPSNPRINTF
#ifdef vsnprintf
# undef vsnprintf
#endif
//#define vsnprintf DO_NOT_USE_VSNPRINTF__USE_DPVSNPRINTF
// dpsnprintf and dpvsnprintf
// return the number of printed characters, excluding the final '\0'
// or return -1 if the buffer isn't big enough to contain the entire string.
// buffer is ALWAYS null-terminated
extern int dpsnprintf (char *buffer, size_t buffersize, const char *format, ...) DP_FUNC_PRINTF(3);
extern int dpvsnprintf (char *buffer, size_t buffersize, const char *format, va_list args);
// A bunch of functions are forbidden for security reasons (and also to please MSVS 2005, for some of them)
// LordHavoc: added #undef lines here to avoid warnings in Linux
#undef strcat
#define strcat DO_NOT_USE_STRCAT__USE_STRLCAT_OR_MEMCPY
#undef strncat
#define strncat DO_NOT_USE_STRNCAT__USE_STRLCAT_OR_MEMCPY
#undef strcpy
#define strcpy DO_NOT_USE_STRCPY__USE_STRLCPY_OR_MEMCPY
#undef strncpy
#define strncpy DO_NOT_USE_STRNCPY__USE_STRLCPY_OR_MEMCPY
//#undef sprintf
//#define sprintf DO_NOT_USE_SPRINTF__USE_DPSNPRINTF
//============================================================================
extern struct cvar_s registered;
extern struct cvar_s cmdline;
typedef enum userdirmode_e
{
USERDIRMODE_NOHOME, // basedir only
USERDIRMODE_HOME, // Windows basedir, general POSIX (~/.)
USERDIRMODE_MYGAMES, // pre-Vista (My Documents/My Games/), general POSIX (~/.)
USERDIRMODE_SAVEDGAMES, // Vista (%USERPROFILE%/Saved Games/), OSX (~/Library/Application Support/), Linux (~/.config)
USERDIRMODE_COUNT
}
userdirmode_t;
typedef enum gamemode_e
{
GAME_NORMAL,
GAME_HIPNOTIC,
GAME_ROGUE,
GAME_QUOTH,
GAME_NEHAHRA,
GAME_NEXUIZ,
GAME_XONOTIC,
GAME_TRANSFUSION,
GAME_GOODVSBAD2,
GAME_TEU,
GAME_BATTLEMECH,
GAME_ZYMOTIC,
GAME_SETHERAL,
GAME_TENEBRAE, // full of evil hackery
GAME_NEOTERIC,
GAME_OPENQUARTZ, //this game sucks
GAME_PRYDON,
GAME_DELUXEQUAKE,
GAME_THEHUNTED,
GAME_DEFEATINDETAIL2,
GAME_DARSANA,
GAME_CONTAGIONTHEORY,
GAME_EDU2P,
GAME_PROPHECY,
GAME_BLOODOMNICIDE,
GAME_STEELSTORM, // added by motorsep
GAME_STEELSTORM2, // added by motorsep
GAME_TOMESOFMEPHISTOPHELES, // added by motorsep
GAME_STRAPBOMB, // added by motorsep for Urre
GAME_MOONHELM,
GAME_COUNT
}
gamemode_t;
extern gamemode_t gamemode;
extern const char *gamename;
extern const char *gamedirname1;
extern const char *gamedirname2;
extern const char *gamescreenshotname;
extern const char *gameuserdirname;
extern char com_modname[MAX_OSPATH];
void COM_ChangeGameTypeForGameDirs(void);
void COM_ToLowerString (const char *in, char *out, size_t size_out);
void COM_ToUpperString (const char *in, char *out, size_t size_out);
int COM_StringBeginsWith(const char *s, const char *match);
int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *tokenbuf, int tokenbufsize, const char *commentprefix);
size_t COM_StringLengthNoColors(const char *s, size_t size_s, qboolean *valid);
qboolean COM_StringDecolorize(const char *in, size_t size_in, char *out, size_t size_out, qboolean escape_carets);
void COM_ToLowerString (const char *in, char *out, size_t size_out);
void COM_ToUpperString (const char *in, char *out, size_t size_out);
typedef struct stringlist_s
{
/// maxstrings changes as needed, causing reallocation of strings[] array
int maxstrings;
int numstrings;
char **strings;
} stringlist_t;
int matchpattern(const char *in, const char *pattern, int caseinsensitive);
int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one);
void stringlistinit(stringlist_t *list);
void stringlistfreecontents(stringlist_t *list);
void stringlistappend(stringlist_t *list, const char *text);
void stringlistsort(stringlist_t *list, qboolean uniq);
void listdirectory(stringlist_t *list, const char *basepath, const char *path);
char *InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength);
void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value);
void InfoString_Print(char *buffer);
// strlcat and strlcpy, from OpenBSD
// Most (all?) BSDs already have them
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(MACOSX)
# define HAVE_STRLCAT 1
# define HAVE_STRLCPY 1
#endif
#ifndef HAVE_STRLCAT
/*!
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
size_t strlcat(char *dst, const char *src, size_t siz);
#endif // #ifndef HAVE_STRLCAT
#ifndef HAVE_STRLCPY
/*!
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif // #ifndef HAVE_STRLCPY
void FindFraction(double val, int *num, int *denom, int denomMax);
// decodes XPM file to XPM array (as if #include'd)
char **XPM_DecodeString(const char *in);
size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen);
#endif

365
app/jni/conproc.c Normal file
View file

@ -0,0 +1,365 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// conproc.c
#include "quakedef.h"
#include <windows.h>
#include <wchar.h>
#include "conproc.h"
HANDLE heventDone;
HANDLE hfileBuffer;
HANDLE heventChildSend;
HANDLE heventParentSend;
HANDLE hStdout;
HANDLE hStdin;
DWORD RequestProc (DWORD dwNichts);
LPVOID GetMappedBuffer (HANDLE hfileBuffer);
void ReleaseMappedBuffer (LPVOID pBuffer);
BOOL GetScreenBufferLines (int *piLines);
BOOL SetScreenBufferLines (int iLines);
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
BOOL WriteText (LPCTSTR szText);
int CharToCode (int c);
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild)
{
DWORD dwID;
// ignore if we don't have all the events.
if (!hFile || !heventParent || !heventChild)
return;
hfileBuffer = hFile;
heventParentSend = heventParent;
heventChildSend = heventChild;
// so we'll know when to go away.
heventDone = CreateEvent (NULL, false, false, NULL);
if (!heventDone)
{
Con_Print("Couldn't create heventDone\n");
return;
}
if (!CreateThread (NULL,
0,
(LPTHREAD_START_ROUTINE) RequestProc,
0,
0,
&dwID))
{
CloseHandle (heventDone);
Con_Print("Couldn't create QHOST thread\n");
return;
}
// save off the input/output handles.
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
hStdin = GetStdHandle (STD_INPUT_HANDLE);
// force 80 character width, at least 25 character height
SetConsoleCXCY (hStdout, 80, 25);
}
void DeinitConProc (void)
{
if (heventDone)
SetEvent (heventDone);
}
DWORD RequestProc (DWORD dwNichts)
{
int *pBuffer;
DWORD dwRet;
HANDLE heventWait[2];
int iBeginLine, iEndLine;
heventWait[0] = heventParentSend;
heventWait[1] = heventDone;
while (1)
{
dwRet = WaitForMultipleObjects (2, heventWait, false, INFINITE);
// heventDone fired, so we're exiting.
if (dwRet == WAIT_OBJECT_0 + 1)
break;
pBuffer = (int *) GetMappedBuffer (hfileBuffer);
// hfileBuffer is invalid. Just leave.
if (!pBuffer)
{
Con_Print("Invalid hfileBuffer\n");
break;
}
switch (pBuffer[0])
{
case CCOM_WRITE_TEXT:
// Param1 : Text
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
break;
case CCOM_GET_TEXT:
// Param1 : Begin line
// Param2 : End line
iBeginLine = pBuffer[1];
iEndLine = pBuffer[2];
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
iEndLine);
break;
case CCOM_GET_SCR_LINES:
// No params
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
break;
case CCOM_SET_SCR_LINES:
// Param1 : Number of lines
pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
break;
}
ReleaseMappedBuffer (pBuffer);
SetEvent (heventChildSend);
}
return 0;
}
LPVOID GetMappedBuffer (HANDLE hfileBuffer)
{
LPVOID pBuffer;
pBuffer = MapViewOfFile (hfileBuffer,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
return pBuffer;
}
void ReleaseMappedBuffer (LPVOID pBuffer)
{
UnmapViewOfFile (pBuffer);
}
BOOL GetScreenBufferLines (int *piLines)
{
CONSOLE_SCREEN_BUFFER_INFO info;
BOOL bRet;
bRet = GetConsoleScreenBufferInfo (hStdout, &info);
if (bRet)
*piLines = info.dwSize.Y;
return bRet;
}
BOOL SetScreenBufferLines (int iLines)
{
return SetConsoleCXCY (hStdout, 80, iLines);
}
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
{
COORD coord;
DWORD dwRead;
BOOL bRet;
coord.X = 0;
coord.Y = iBeginLine;
bRet = ReadConsoleOutputCharacter(
hStdout,
pszText,
80 * (iEndLine - iBeginLine + 1),
coord,
&dwRead);
// Make sure it's null terminated.
if (bRet)
pszText[dwRead] = '\0';
return bRet;
}
BOOL WriteText (LPCTSTR szText)
{
DWORD dwWritten;
INPUT_RECORD rec;
char upper, *sz;
sz = (LPTSTR) szText;
while (*sz)
{
// 13 is the code for a carriage return (\n) instead of 10.
if (*sz == 10)
*sz = 13;
upper = toupper(*sz);
rec.EventType = KEY_EVENT;
rec.Event.KeyEvent.bKeyDown = true;
rec.Event.KeyEvent.wRepeatCount = 1;
rec.Event.KeyEvent.wVirtualKeyCode = upper;
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
WriteConsoleInput(
hStdin,
&rec,
1,
&dwWritten);
rec.Event.KeyEvent.bKeyDown = false;
WriteConsoleInput(
hStdin,
&rec,
1,
&dwWritten);
sz++;
}
return true;
}
int CharToCode (int c)
{
char upper;
upper = toupper(c);
switch (c)
{
case 13:
return 28;
default:
break;
}
if (isalpha(c))
return (30 + upper - 65);
if (isdigit(c))
return (1 + upper - 47);
return c;
}
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
{
CONSOLE_SCREEN_BUFFER_INFO info;
COORD coordMax;
coordMax = GetLargestConsoleWindowSize(hStdout);
if (cy > coordMax.Y)
cy = coordMax.Y;
if (cx > coordMax.X)
cx = coordMax.X;
if (!GetConsoleScreenBufferInfo(hStdout, &info))
return false;
// height
info.srWindow.Left = 0;
info.srWindow.Right = info.dwSize.X - 1;
info.srWindow.Top = 0;
info.srWindow.Bottom = cy - 1;
if (cy < info.dwSize.Y)
{
if (!SetConsoleWindowInfo(hStdout, true, &info.srWindow))
return false;
info.dwSize.Y = cy;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return false;
}
else if (cy > info.dwSize.Y)
{
info.dwSize.Y = cy;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return false;
if (!SetConsoleWindowInfo(hStdout, true, &info.srWindow))
return false;
}
if (!GetConsoleScreenBufferInfo(hStdout, &info))
return false;
// width
info.srWindow.Left = 0;
info.srWindow.Right = cx - 1;
info.srWindow.Top = 0;
info.srWindow.Bottom = info.dwSize.Y - 1;
if (cx < info.dwSize.X)
{
if (!SetConsoleWindowInfo(hStdout, true, &info.srWindow))
return false;
info.dwSize.X = cx;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return false;
}
else if (cx > info.dwSize.X)
{
info.dwSize.X = cx;
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
return false;
if (!SetConsoleWindowInfo(hStdout, true, &info.srWindow))
return false;
}
return true;
}

42
app/jni/conproc.h Normal file
View file

@ -0,0 +1,42 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// conproc.h
#ifndef CONPROC_H
#define CONPROC_H
#define CCOM_WRITE_TEXT 0x2
// Param1 : Text
#define CCOM_GET_TEXT 0x3
// Param1 : Begin line
// Param2 : End line
#define CCOM_GET_SCR_LINES 0x4
// No params
#define CCOM_SET_SCR_LINES 0x5
// Param1 : Number of lines
void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild);
void DeinitConProc (void);
#endif

3014
app/jni/console.c Normal file

File diff suppressed because it is too large Load diff

151
app/jni/console.h Normal file
View file

@ -0,0 +1,151 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef CONSOLE_H
#define CONSOLE_H
//
// console
//
extern int con_totallines;
extern int con_backscroll;
extern qboolean con_initialized;
void Con_Rcon_Redirect_Init(lhnetsocket_t *sock, lhnetaddress_t *dest, qboolean proquakeprotocol);
void Con_Rcon_Redirect_End(void);
void Con_Rcon_Redirect_Abort(void);
/// If the line width has changed, reformat the buffer.
void Con_CheckResize (void);
void Con_Init (void);
void Con_Init_Commands (void);
void Con_Shutdown (void);
void Con_DrawConsole (int lines);
/// Prints to a chosen console target
void Con_MaskPrint(int mask, const char *msg);
// Prints to a chosen console target
void Con_MaskPrintf(int mask, const char *fmt, ...) DP_FUNC_PRINTF(2);
/// Prints to all appropriate console targets, and adds timestamps
void Con_Print(const char *txt);
/// Prints to all appropriate console targets.
void Con_Printf(const char *fmt, ...) DP_FUNC_PRINTF(1);
/// A Con_Print that only shows up if the "developer" cvar is set.
void Con_DPrint(const char *msg);
/// A Con_Printf that only shows up if the "developer" cvar is set
void Con_DPrintf(const char *fmt, ...) DP_FUNC_PRINTF(1);
void Con_Clear_f (void);
void Con_DrawNotify (void);
/// Clear all notify lines.
void Con_ClearNotify (void);
void Con_ToggleConsole_f (void);
int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos);
qboolean GetMapList (const char *s, char *completedname, int completednamebufferlength);
/// wrapper function to attempt to either complete the command line
/// or to list possible matches grouped by type
/// (i.e. will display possible variables, aliases, commands
/// that match what they've typed so far)
void Con_CompleteCommandLine(void);
/// Generic libs/util/console.c function to display a list
/// formatted in columns on the console
void Con_DisplayList(const char **list);
/*! \name log
* @{
*/
void Log_Init (void);
void Log_Close (void);
void Log_Start (void);
void Log_DestBuffer_Flush (void); ///< call this once per frame to send out replies to rcon streaming clients
void Log_Printf(const char *logfilename, const char *fmt, ...) DP_FUNC_PRINTF(2);
//@}
// CON_MASK_PRINT is the default (Con_Print/Con_Printf)
// CON_MASK_DEVELOPER is used by Con_DPrint/Con_DPrintf
#define CON_MASK_HIDENOTIFY 128
#define CON_MASK_CHAT 1
#define CON_MASK_INPUT 2
#define CON_MASK_DEVELOPER 4
#define CON_MASK_PRINT 8
typedef struct con_lineinfo_s
{
char *start;
size_t len;
int mask;
/// used only by console.c
double addtime;
int height; ///< recalculated line height when needed (-1 to unset)
}
con_lineinfo_t;
typedef struct conbuffer_s
{
qboolean active;
int textsize;
char *text;
int maxlines;
con_lineinfo_t *lines;
int lines_first;
int lines_count; ///< cyclic buffer
}
conbuffer_t;
#define CONBUFFER_LINES(buf, i) (buf)->lines[((buf)->lines_first + (i)) % (buf)->maxlines]
#define CONBUFFER_LINES_COUNT(buf) ((buf)->lines_count)
#define CONBUFFER_LINES_LAST(buf) CONBUFFER_LINES(buf, CONBUFFER_LINES_COUNT(buf) - 1)
void ConBuffer_Init(conbuffer_t *buf, int textsize, int maxlines, mempool_t *mempool);
void ConBuffer_Clear (conbuffer_t *buf);
void ConBuffer_Shutdown(conbuffer_t *buf);
/*! Notifies the console code about the current time
* (and shifts back times of other entries when the time
* went backwards)
*/
void ConBuffer_FixTimes(conbuffer_t *buf);
/// Deletes the first line from the console history.
void ConBuffer_DeleteLine(conbuffer_t *buf);
/// Deletes the last line from the console history.
void ConBuffer_DeleteLastLine(conbuffer_t *buf);
/// Appends a given string as a new line to the console.
void ConBuffer_AddLine(conbuffer_t *buf, const char *line, int len, int mask);
int ConBuffer_FindPrevLine(conbuffer_t *buf, int mask_must, int mask_mustnot, int start);
int ConBuffer_FindNextLine(conbuffer_t *buf, int mask_must, int mask_mustnot, int start);
const char *ConBuffer_GetLine(conbuffer_t *buf, int i);
#endif

2588
app/jni/crypto.c Normal file

File diff suppressed because it is too large Load diff

158
app/jni/crypto.h Normal file
View file

@ -0,0 +1,158 @@
#ifndef CRYPTO_H
#define CRYPTO_H
extern cvar_t crypto_developer;
extern cvar_t crypto_aeslevel;
#define ENCRYPTION_REQUIRED (crypto_aeslevel.integer >= 3)
extern int crypto_keyfp_recommended_length; // applies to LOCAL IDs, and to ALL keys
#define CRYPTO_HEADERSIZE 31
// AES case causes 16 to 31 bytes overhead
// SHA256 case causes 16 bytes overhead as we truncate to 128bit
#include "lhnet.h"
#define FP64_SIZE 44
#define DHKEY_SIZE 16
typedef struct
{
unsigned char dhkey[DHKEY_SIZE]; // shared key, not NUL terminated
char client_idfp[FP64_SIZE+1];
char client_keyfp[FP64_SIZE+1]; // NULL if signature fail
char server_idfp[FP64_SIZE+1];
char server_keyfp[FP64_SIZE+1]; // NULL if signature fail
qboolean authenticated;
qboolean use_aes;
void *data;
}
crypto_t;
void Crypto_Init(void);
void Crypto_Init_Commands(void);
void Crypto_LoadKeys(void); // NOTE: when this is called, the SV_LockThreadMutex MUST be active
void Crypto_Shutdown(void);
qboolean Crypto_Available(void);
void sha256(unsigned char *out, const unsigned char *in, int n); // may ONLY be called if Crypto_Available()
const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
#define CRYPTO_NOMATCH 0 // process as usual (packet was not used)
#define CRYPTO_MATCH 1 // process as usual (packet was used)
#define CRYPTO_DISCARD 2 // discard this packet
#define CRYPTO_REPLACE 3 // make the buffer the current packet
int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress);
int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress);
// if len_out is nonzero, the packet is to be sent to the client
qboolean Crypto_ServerAppendToChallenge(const char *data_in, size_t len_in, char *data_out, size_t *len_out, size_t maxlen);
crypto_t *Crypto_ServerGetInstance(lhnetaddress_t *peeraddress);
qboolean Crypto_ServerFinishInstance(crypto_t *out, crypto_t *in); // also clears allocated memory
const char *Crypto_GetInfoResponseDataString(void);
// retrieves a host key for an address (can be exposed to menuqc, or used by the engine to look up stored keys e.g. for server bookmarking)
// pointers may be NULL
qboolean Crypto_RetrieveHostKey(lhnetaddress_t *peeraddress, int *keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, int *aeslevel);
int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, qboolean *issigned); // return value: -1 if more to come, +1 if valid, 0 if end of list
size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size);
size_t Crypto_SignDataDetached(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size);
// netconn protocol:
// non-crypto:
// getchallenge >
// < challenge
// connect >
// < accept (or: reject)
// crypto:
// getchallenge >
// < challenge SP <challenge> NUL vlen <size> d0pk <fingerprints I can auth to> NUL NUL <other fingerprints I accept>
//
// IF serverfp:
// d0pk\cnt\0\challenge\<challenge>\aeslevel\<level> NUL <serverfp> NUL <clientfp>
// >
// check if client would get accepted; if not, do "reject" now
// require non-control packets to be encrypted require non-control packets to be encrypted
// do not send anything yet do not send anything yet
// RESET to serverfp RESET to serverfp
// d0_blind_id_authenticate_with_private_id_start() = 1
// < d0pk\cnt\1\aes\<aesenabled> NUL *startdata*
// d0_blind_id_authenticate_with_private_id_challenge() = 1
// d0pk\cnt\2 NUL *challengedata* >
// d0_blind_id_authenticate_with_private_id_response() = 0
// < d0pk\cnt\3 NUL *responsedata*
// d0_blind_id_authenticate_with_private_id_verify() = 1
// store server's fingerprint NOW
// d0_blind_id_sessionkey_public_id() = 1 d0_blind_id_sessionkey_public_id() = 1
//
// IF clientfp AND NOT serverfp:
// RESET to clientfp RESET to clientfp
// d0_blind_id_authenticate_with_private_id_start() = 1
// d0pk\cnt\0\challenge\<challenge>\aeslevel\<level> NUL NUL <clientfp> NUL *startdata*
// >
// check if client would get accepted; if not, do "reject" now
// require non-control packets to be encrypted require non-control packets to be encrypted
// d0_blind_id_authenticate_with_private_id_challenge() = 1
// < d0pk\cnt\5\aes\<aesenabled> NUL *challengedata*
//
// IF clientfp AND serverfp:
// RESET to clientfp RESET to clientfp
// d0_blind_id_authenticate_with_private_id_start() = 1
// d0pk\cnt\4 NUL *startdata* >
// d0_blind_id_authenticate_with_private_id_challenge() = 1
// < d0pk\cnt\5 NUL *challengedata*
//
// IF clientfp:
// d0_blind_id_authenticate_with_private_id_response() = 0
// d0pk\cnt\6 NUL *responsedata* >
// d0_blind_id_authenticate_with_private_id_verify() = 1
// store client's fingerprint NOW
// d0_blind_id_sessionkey_public_id() = 1 d0_blind_id_sessionkey_public_id() = 1
// note: the ... is the "connect" message, except without the challenge. Reinterpret as regular connect message on server side
//
// enforce encrypted transmission (key is XOR of the two DH keys)
//
// IF clientfp:
// < challenge (mere sync message)
//
// connect\... >
// < accept (ALWAYS accept if connection is encrypted, ignore challenge as it had been checked before)
//
// commence with ingame protocol
// in short:
// server:
// getchallenge NUL d0_blind_id: reply with challenge with added fingerprints
// cnt=0: IF server will auth, cnt=1, ELSE cnt=5
// cnt=2: cnt=3
// cnt=4: cnt=5
// cnt=6: send "challenge"
// client:
// challenge with added fingerprints: cnt=0; if client will auth but not server, append client auth start
// cnt=1: cnt=2
// cnt=3: IF client will auth, cnt=4, ELSE rewrite as "challenge"
// cnt=5: cnt=6, server will continue by sending "challenge" (let's avoid sending two packets as response to one)
// other change:
// accept empty "challenge", and challenge-less connect in case crypto protocol has executed and finished
// statusResponse and infoResponse get an added d0_blind_id key that lists
// the keys the server can auth with and to in key@ca SPACE key@ca notation
// any d0pk\ message has an appended "id" parameter; messages with an unexpected "id" are ignored to prevent errors from multiple concurrent auth runs
// comparison to OTR:
// - encryption: yes
// - authentication: yes
// - deniability: no (attacker requires the temporary session key to prove you
// have sent a specific message, the private key itself does not suffice), no
// measures are taken to provide forgeability to even provide deniability
// against an attacker who knows the temporary session key, as using CTR mode
// for the encryption - which, together with deriving the MAC key from the
// encryption key, and MACing the ciphertexts instead of the plaintexts,
// would provide forgeability and thus deniability - requires longer
// encrypted packets and deniability was not a goal of this, as we may e.g.
// reserve the right to capture packet dumps + extra state info to prove a
// client/server has sent specific packets to prove cheating)
// - perfect forward secrecy: yes (session key is derived via DH key exchange)
#endif

1252
app/jni/csprogs.c Normal file

File diff suppressed because it is too large Load diff

121
app/jni/csprogs.h Normal file
View file

@ -0,0 +1,121 @@
#ifndef CSPROGS_H
#define CSPROGS_H
// LordHavoc: changed to match MAX_EDICTS
#define CL_MAX_EDICTS MAX_EDICTS
#define ENTMASK_ENGINE 1
#define ENTMASK_ENGINEVIEWMODELS 2
#define ENTMASK_NORMAL 4
#define VF_MIN 1 //(vector)
#define VF_MIN_X 2 //(float)
#define VF_MIN_Y 3 //(float)
#define VF_SIZE 4 //(vector) (viewport size)
#define VF_SIZE_X 5 //(float)
#define VF_SIZE_Y 6 //(float)
#define VF_VIEWPORT 7 //(vector, vector)
#define VF_FOV 8 //(vector)
#define VF_FOVX 9 //(float)
#define VF_FOVY 10 //(float)
#define VF_ORIGIN 11 //(vector)
#define VF_ORIGIN_X 12 //(float)
#define VF_ORIGIN_Y 13 //(float)
#define VF_ORIGIN_Z 14 //(float)
#define VF_ANGLES 15 //(vector)
#define VF_ANGLES_X 16 //(float)
#define VF_ANGLES_Y 17 //(float)
#define VF_ANGLES_Z 18 //(float)
#define VF_DRAWWORLD 19 //(float) //actually world model and sky
#define VF_DRAWENGINESBAR 20 //(float)
#define VF_DRAWCROSSHAIR 21 //(float)
#define VF_CL_VIEWANGLES 33 //(vector) //sweet thing for RPGs/...
#define VF_CL_VIEWANGLES_X 34 //(float)
#define VF_CL_VIEWANGLES_Y 35 //(float)
#define VF_CL_VIEWANGLES_Z 36 //(float)
// FTEQW's extension range
#define VF_PERSPECTIVE 200 //(float)
// what is this doing here? This is a DP extension introduced by Black, should be in 4xx range
#define VF_CLEARSCREEN 201 //(float)
// what is this doing here? This is a DP extension introduced by VorteX, should be in 4xx range
#define VF_FOG_DENSITY 202 //(float)
#define VF_FOG_COLOR 203 //(vector)
#define VF_FOG_COLOR_R 204 //(float)
#define VF_FOG_COLOR_G 205 //(float)
#define VF_FOG_COLOR_B 206 //(float)
#define VF_FOG_ALPHA 207 //(float)
#define VF_FOG_START 208 //(float)
#define VF_FOG_END 209 //(float)
#define VF_FOG_HEIGHT 210 //(float)
#define VF_FOG_FADEDEPTH 211 //(float)
// DP's extension range
#define VF_MAINVIEW 400 //(float)
#define VF_MINFPS_QUALITY 401 //(float)
#define RF_VIEWMODEL 1 // The entity is never drawn in mirrors. In engines with realtime lighting, it casts no shadows.
#define RF_EXTERNALMODEL 2 // The entity is appears in mirrors but not in the normal view. It does still cast shadows in engines with realtime lighting.
#define RF_DEPTHHACK 4 // The entity appears closer to the view than normal, either by scaling it wierdly or by just using a depthrange. This will usually be found in conjunction with RF_VIEWMODEL
#define RF_ADDITIVE 8 // Add the entity acording to it's alpha values instead of the normal blend
#define RF_USEAXIS 16 // When set, the entity will use the v_forward, v_right and v_up globals instead of it's angles field for orientation. Angles will be ignored compleatly.
// Note that to use this properly, you'll NEED to use the predraw function to set the globals.
//#define RF_DOUBLESIDED 32
#define RF_USETRANSPARENTOFFSET 64 // Allows QC to customize origin used for transparent sorting via transparent_origin global, helps to fix transparent sorting bugs on a very large entities
#define RF_WORLDOBJECT 128 // for large outdoor entities that should not be culled
#define RF_MODELLIGHT 4096 // CSQC-set model light
#define RF_DYNAMICMODELLIGHT 8192 // origin-dependent model light
#define RF_FULLBRIGHT 256
#define RF_NOSHADOW 512
extern cvar_t csqc_progname; //[515]: csqc crc check and right csprogs name according to progs.dat
extern cvar_t csqc_progcrc;
extern cvar_t csqc_progsize;
void CL_VM_PreventInformationLeaks(void);
qboolean MakeDownloadPacket(const char *filename, unsigned char *data, size_t len, int crc, int cnt, sizebuf_t *buf, int protocol);
qboolean CL_VM_GetEntitySoundOrigin(int entnum, vec3_t out);
qboolean CL_VM_TransformView(int entnum, matrix4x4_t *viewmatrix, mplane_t *clipplane, vec3_t visorigin);
void CL_VM_Init(void);
void CL_VM_ShutDown(void);
void CL_VM_UpdateIntermissionState(int intermission);
void CL_VM_UpdateShowingScoresState(int showingscores);
qboolean CL_VM_InputEvent(int eventtype, int x, int y);
qboolean CL_VM_ConsoleCommand(const char *cmd);
void CL_VM_UpdateDmgGlobals(int dmg_take, int dmg_save, vec3_t dmg_origin);
void CL_VM_UpdateIntermissionState(int intermission);
qboolean CL_VM_Event_Sound(int sound_num, float volume, int channel, float attenuation, int ent, vec3_t pos, int flags, float speed);
qboolean CL_VM_Parse_TempEntity(void);
void CL_VM_Parse_StuffCmd(const char *msg);
void CL_VM_Parse_CenterPrint(const char *msg);
int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent);
int CL_GetTagMatrix(prvm_prog_t *prog, matrix4x4_t *out, prvm_edict_t *ent, int tagindex);
void CL_GetEntityMatrix(prvm_prog_t *prog, prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix);
/* VMs exposing the polygon calls must call this on Init/Reset */
void VM_Polygons_Reset(prvm_prog_t *prog);
void QW_CL_StartUpload(unsigned char *data, int size);
void CSQC_UpdateNetworkTimes(double newtime, double oldtime);
void CSQC_AddPrintText(const char *msg);
void CSQC_ReadEntities(void);
void CSQC_RelinkAllEntities(int drawmask);
void CSQC_RelinkCSQCEntities(void);
void CSQC_Predraw(prvm_edict_t *ed);
void CSQC_Think(prvm_edict_t *ed);
qboolean CSQC_AddRenderEdict(prvm_edict_t *ed, int edictnum);//csprogs.c
void CSQC_R_RecalcView(void);
dp_model_t *CL_GetModelByIndex(int modelindex);
int CL_VM_GetViewEntity(void);
#endif

440
app/jni/curves.c Normal file
View file

@ -0,0 +1,440 @@
/*
this code written by Forest Hale, on 2004-10-17, and placed into public domain
this implements Quadratic BSpline surfaces as seen in Quake3 by id Software
a small rant on misuse of the name 'bezier': many people seem to think that
bezier is a generic term for splines, but it is not, it is a term for a
specific type of bspline (4 control points, cubic bspline), bsplines are the
generalization of the bezier spline to support dimensions other than cubic.
example equations for 1-5 control point bsplines being sampled as t=0...1
1: flat (0th dimension)
o = a
2: linear (1st dimension)
o = a * (1 - t) + b * t
3: quadratic bspline (2nd dimension)
o = a * (1 - t) * (1 - t) + 2 * b * (1 - t) * t + c * t * t
4: cubic (bezier) bspline (3rd dimension)
o = a * (1 - t) * (1 - t) * (1 - t) + 3 * b * (1 - t) * (1 - t) * t + 3 * c * (1 - t) * t * t + d * t * t * t
5: quartic bspline (4th dimension)
o = a * (1 - t) * (1 - t) * (1 - t) * (1 - t) + 4 * b * (1 - t) * (1 - t) * (1 - t) * t + 6 * c * (1 - t) * (1 - t) * t * t + 4 * d * (1 - t) * t * t * t + e * t * t * t * t
arbitrary dimension bspline
double factorial(int n)
{
int i;
double f;
f = 1;
for (i = 1;i < n;i++)
f = f * i;
return f;
}
double bsplinesample(int dimensions, double t, double *param)
{
double o = 0;
for (i = 0;i < dimensions + 1;i++)
o += param[i] * factorial(dimensions)/(factorial(i)*factorial(dimensions-i)) * pow(t, i) * pow(1 - t, dimensions - i);
return o;
}
*/
#include "quakedef.h"
#include "mathlib.h"
#include <math.h>
#include "curves.h"
// Calculate number of resulting vertex rows/columns by given patch size and tesselation factor
// tess=0 means that we reduce detalization of base 3x3 patches by removing middle row and column of vertices
// "DimForTess" is "DIMension FOR TESSelation factor"
// NB: tess=0 actually means that tess must be 0.5, but obviously it can't because it is of int type. (so "a*tess"-like code is replaced by "a/2" if tess=0)
int Q3PatchDimForTess(int size, int tess)
{
if (tess > 0)
return (size - 1) * tess + 1;
else if (tess == 0)
return (size - 1) / 2 + 1;
else
return 0; // Maybe warn about wrong tess here?
}
// usage:
// to expand a 5x5 patch to 21x21 vertices (4x4 tesselation), one might use this call:
// Q3PatchSubdivideFloat(3, sizeof(float[3]), outvertices, 5, 5, sizeof(float[3]), patchvertices, 4, 4);
void Q3PatchTesselateFloat(int numcomponents, int outputstride, float *outputvertices, int patchwidth, int patchheight, int inputstride, float *patchvertices, int tesselationwidth, int tesselationheight)
{
int k, l, x, y, component, outputwidth = Q3PatchDimForTess(patchwidth, tesselationwidth);
float px, py, *v, a, b, c, *cp[3][3], temp[3][64];
int xmax = max(1, 2*tesselationwidth);
int ymax = max(1, 2*tesselationheight);
// iterate over the individual 3x3 quadratic spline surfaces one at a time
// expanding them to fill the output array (with some overlap to ensure
// the edges are filled)
for (k = 0;k < patchheight-1;k += 2)
{
for (l = 0;l < patchwidth-1;l += 2)
{
// set up control point pointers for quicker lookup later
for (y = 0;y < 3;y++)
for (x = 0;x < 3;x++)
cp[y][x] = (float *)((unsigned char *)patchvertices + ((k+y)*patchwidth+(l+x)) * inputstride);
// for each row...
for (y = 0;y <= ymax;y++)
{
// calculate control points for this row by collapsing the 3
// rows of control points to one row using py
py = (float)y / (float)ymax;
// calculate quadratic spline weights for py
a = ((1.0f - py) * (1.0f - py));
b = ((1.0f - py) * (2.0f * py));
c = (( py) * ( py));
for (component = 0;component < numcomponents;component++)
{
temp[0][component] = cp[0][0][component] * a + cp[1][0][component] * b + cp[2][0][component] * c;
temp[1][component] = cp[0][1][component] * a + cp[1][1][component] * b + cp[2][1][component] * c;
temp[2][component] = cp[0][2][component] * a + cp[1][2][component] * b + cp[2][2][component] * c;
}
// fetch a pointer to the beginning of the output vertex row
v = (float *)((unsigned char *)outputvertices + ((k * ymax / 2 + y) * outputwidth + l * xmax / 2) * outputstride);
// for each column of the row...
for (x = 0;x <= xmax;x++)
{
// calculate point based on the row control points
px = (float)x / (float)xmax;
// calculate quadratic spline weights for px
// (could be precalculated)
a = ((1.0f - px) * (1.0f - px));
b = ((1.0f - px) * (2.0f * px));
c = (( px) * ( px));
for (component = 0;component < numcomponents;component++)
v[component] = temp[0][component] * a + temp[1][component] * b + temp[2][component] * c;
// advance to next output vertex using outputstride
// (the next vertex may not be directly following this
// one, as this may be part of a larger structure)
v = (float *)((unsigned char *)v + outputstride);
}
}
}
}
#if 0
// enable this if you want results printed out
printf("vertices[%i][%i] =\n{\n", (patchheight-1)*tesselationheight+1, (patchwidth-1)*tesselationwidth+1);
for (y = 0;y < (patchheight-1)*tesselationheight+1;y++)
{
for (x = 0;x < (patchwidth-1)*tesselationwidth+1;x++)
{
printf("(");
for (component = 0;component < numcomponents;component++)
printf("%f ", outputvertices[(y*((patchwidth-1)*tesselationwidth+1)+x)*numcomponents+component]);
printf(") ");
}
printf("\n");
}
printf("}\n");
#endif
}
static int Q3PatchTesselation(float largestsquared3xcurvearea, float tolerance)
{
float f;
// f is actually a squared 2x curve area... so the formula had to be adjusted to give roughly the same subdivisions
f = pow(largestsquared3xcurvearea / 64.0f, 0.25f) / tolerance;
//if(f < 0.25) // VERY flat patches
if(f < 0.0001) // TOTALLY flat patches
return 0;
else if(f < 2)
return 1;
else
return (int) floor(log(f) / log(2.0f)) + 1;
// this is always at least 2
// maps [0.25..0.5[ to -1 (actually, 1 is returned)
// maps [0.5..1[ to 0 (actually, 1 is returned)
// maps [1..2[ to 1
// maps [2..4[ to 2
// maps [4..8[ to 4
}
static float Squared3xCurveArea(const float *a, const float *control, const float *b, int components)
{
#if 0
// mimicing the old behaviour with the new code...
float deviation;
float quartercurvearea = 0;
int c;
for (c = 0;c < components;c++)
{
deviation = control[c] * 0.5f - a[c] * 0.25f - b[c] * 0.25f;
quartercurvearea += deviation*deviation;
}
// But as the new code now works on the squared 2x curve area, let's scale the value
return quartercurvearea * quartercurvearea * 64.0;
#else
// ideally, we'd like the area between the spline a->control->b and the line a->b.
// but as this is hard to calculate, let's calculate an upper bound of it:
// the area of the triangle a->control->b->a.
//
// one can prove that the area of a quadratic spline = 2/3 * the area of
// the triangle of its control points!
// to do it, first prove it for the spline through (0,0), (1,1), (2,0)
// (which is a parabola) and then note that moving the control point
// left/right is just shearing and keeps the area of both the spline and
// the triangle invariant.
//
// why are we going for the spline area anyway?
// we know that:
//
// the area between the spline and the line a->b is a measure of the
// error of approximation of the spline by the line.
//
// also, on circle-like or parabola-like curves, you easily get that the
// double amount of line approximation segments reduces the error to its quarter
// (also, easy to prove for splines by doing it for one specific one, and using
// affine transforms to get all other splines)
//
// so...
//
// let's calculate the area! but we have to avoid the cross product, as
// components is not necessarily 3
//
// the area of a triangle spanned by vectors a and b is
//
// 0.5 * |a| |b| sin gamma
//
// now, cos gamma is
//
// a.b / (|a| |b|)
//
// so the area is
//
// 0.5 * sqrt(|a|^2 |b|^2 - (a.b)^2)
int c;
float aa = 0, bb = 0, ab = 0;
for (c = 0;c < components;c++)
{
float xa = a[c] - control[c];
float xb = b[c] - control[c];
aa += xa * xa;
ab += xa * xb;
bb += xb * xb;
}
// area is 0.5 * sqrt(aa*bb - ab*ab)
// 2x TRIANGLE area is sqrt(aa*bb - ab*ab)
// 3x CURVE area is sqrt(aa*bb - ab*ab)
return aa * bb - ab * ab;
#endif
}
// returns how much tesselation of each segment is needed to remain under tolerance
int Q3PatchTesselationOnX(int patchwidth, int patchheight, int components, const float *in, float tolerance)
{
int x, y;
const float *patch;
float squared3xcurvearea, largestsquared3xcurvearea;
largestsquared3xcurvearea = 0;
for (y = 0;y < patchheight;y++)
{
for (x = 0;x < patchwidth-1;x += 2)
{
patch = in + ((y * patchwidth) + x) * components;
squared3xcurvearea = Squared3xCurveArea(&patch[0], &patch[components], &patch[2*components], components);
if (largestsquared3xcurvearea < squared3xcurvearea)
largestsquared3xcurvearea = squared3xcurvearea;
}
}
return Q3PatchTesselation(largestsquared3xcurvearea, tolerance);
}
// returns how much tesselation of each segment is needed to remain under tolerance
int Q3PatchTesselationOnY(int patchwidth, int patchheight, int components, const float *in, float tolerance)
{
int x, y;
const float *patch;
float squared3xcurvearea, largestsquared3xcurvearea;
largestsquared3xcurvearea = 0;
for (y = 0;y < patchheight-1;y += 2)
{
for (x = 0;x < patchwidth;x++)
{
patch = in + ((y * patchwidth) + x) * components;
squared3xcurvearea = Squared3xCurveArea(&patch[0], &patch[patchwidth*components], &patch[2*patchwidth*components], components);
if (largestsquared3xcurvearea < squared3xcurvearea)
largestsquared3xcurvearea = squared3xcurvearea;
}
}
return Q3PatchTesselation(largestsquared3xcurvearea, tolerance);
}
// Find an equal vertex in array. Check only vertices with odd X and Y
static int FindEqualOddVertexInArray(int numcomponents, float *vertex, float *vertices, int width, int height)
{
int x, y, j;
for (y=0; y<height; y+=2)
{
for (x=0; x<width; x+=2)
{
qboolean found = true;
for (j=0; j<numcomponents; j++)
if (fabs(*(vertex+j) - *(vertices+j)) > 0.05)
// div0: this is notably smaller than the smallest radiant grid
// but large enough so we don't need to get scared of roundoff
// errors
{
found = false;
break;
}
if(found)
return y*width+x;
vertices += numcomponents*2;
}
vertices += numcomponents*(width-1);
}
return -1;
}
#define SIDE_INVALID -1
#define SIDE_X 0
#define SIDE_Y 1
static int GetSide(int p1, int p2, int width, int height, int *pointdist)
{
int x1 = p1 % width, y1 = p1 / width;
int x2 = p2 % width, y2 = p2 / width;
if (p1 < 0 || p2 < 0)
return SIDE_INVALID;
if (x1 == x2)
{
if (y1 != y2)
{
*pointdist = abs(y2 - y1);
return SIDE_Y;
}
else
return SIDE_INVALID;
}
else if (y1 == y2)
{
*pointdist = abs(x2 - x1);
return SIDE_X;
}
else
return SIDE_INVALID;
}
// Increase tesselation of one of two touching patches to make a seamless connection between them
// Returns 0 in case if patches were not modified, otherwise 1
int Q3PatchAdjustTesselation(int numcomponents, patchinfo_t *patch1, float *patchvertices1, patchinfo_t *patch2, float *patchvertices2)
{
// what we are doing here is:
// we take for each corner of one patch
// and check if the other patch contains that corner
// once we have a pair of such matches
struct {int id1,id2;} commonverts[8];
int i, j, k, side1, side2, *tess1, *tess2;
int dist1 = 0, dist2 = 0;
qboolean modified = false;
// Potential paired vertices (corners of the first patch)
commonverts[0].id1 = 0;
commonverts[1].id1 = patch1->xsize-1;
commonverts[2].id1 = patch1->xsize*(patch1->ysize-1);
commonverts[3].id1 = patch1->xsize*patch1->ysize-1;
for (i=0;i<4;++i)
commonverts[i].id2 = FindEqualOddVertexInArray(numcomponents, patchvertices1+numcomponents*commonverts[i].id1, patchvertices2, patch2->xsize, patch2->ysize);
// Corners of the second patch
commonverts[4].id2 = 0;
commonverts[5].id2 = patch2->xsize-1;
commonverts[6].id2 = patch2->xsize*(patch2->ysize-1);
commonverts[7].id2 = patch2->xsize*patch2->ysize-1;
for (i=4;i<8;++i)
commonverts[i].id1 = FindEqualOddVertexInArray(numcomponents, patchvertices2+numcomponents*commonverts[i].id2, patchvertices1, patch1->xsize, patch1->ysize);
for (i=0;i<8;++i)
for (j=i+1;j<8;++j)
{
side1 = GetSide(commonverts[i].id1,commonverts[j].id1,patch1->xsize,patch1->ysize,&dist1);
side2 = GetSide(commonverts[i].id2,commonverts[j].id2,patch2->xsize,patch2->ysize,&dist2);
if (side1 == SIDE_INVALID || side2 == SIDE_INVALID)
continue;
if(dist1 != dist2)
{
// no patch welding if the resolutions mismatch
continue;
}
// Update every lod level
for (k=0;k<PATCH_LODS_NUM;++k)
{
tess1 = side1 == SIDE_X ? &patch1->lods[k].xtess : &patch1->lods[k].ytess;
tess2 = side2 == SIDE_X ? &patch2->lods[k].xtess : &patch2->lods[k].ytess;
if (*tess1 != *tess2)
{
if (*tess1 < *tess2)
*tess1 = *tess2;
else
*tess2 = *tess1;
modified = true;
}
}
}
return modified;
}
#undef SIDE_INVALID
#undef SIDE_X
#undef SIDE_Y
// calculates elements for a grid of vertices
// (such as those produced by Q3PatchTesselate)
// (note: width and height are the actual vertex size, this produces
// (width-1)*(height-1)*2 triangles, 3 elements each)
void Q3PatchTriangleElements(int *elements, int width, int height, int firstvertex)
{
int x, y, row0, row1;
for (y = 0;y < height - 1;y++)
{
if(y % 2)
{
// swap the triangle order in odd rows as optimization for collision stride
row0 = firstvertex + (y + 0) * width + width - 2;
row1 = firstvertex + (y + 1) * width + width - 2;
for (x = 0;x < width - 1;x++)
{
*elements++ = row1;
*elements++ = row1 + 1;
*elements++ = row0 + 1;
*elements++ = row0;
*elements++ = row1;
*elements++ = row0 + 1;
row0--;
row1--;
}
}
else
{
row0 = firstvertex + (y + 0) * width;
row1 = firstvertex + (y + 1) * width;
for (x = 0;x < width - 1;x++)
{
*elements++ = row0;
*elements++ = row1;
*elements++ = row0 + 1;
*elements++ = row1;
*elements++ = row1 + 1;
*elements++ = row0 + 1;
row0++;
row1++;
}
}
}
}

39
app/jni/curves.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef CURVES_H
#define CURVES_H
#define PATCH_LODS_NUM 2
#define PATCH_LOD_COLLISION 0
#define PATCH_LOD_VISUAL 1
typedef struct patchinfo_s
{
int xsize, ysize;
struct {
int xtess, ytess;
} lods[PATCH_LODS_NUM];
} patchinfo_t;
// Calculate number of resulting vertex rows/columns by given patch size and tesselation factor
// When tess=0 it means that we reduce detalization of base 3x3 patches by removing middle row and column
// "DimForTess" is "DIMension FOR TESSelation factor"
int Q3PatchDimForTess(int size, int tess);
// usage:
// to expand a 5x5 patch to 21x21 vertices (4x4 tesselation), one might use this call:
// Q3PatchSubdivideFloat(3, sizeof(float[3]), outvertices, 5, 5, sizeof(float[3]), patchvertices, 4, 4);
void Q3PatchTesselateFloat(int numcomponents, int outputstride, float *outputvertices, int patchwidth, int patchheight, int inputstride, float *patchvertices, int tesselationwidth, int tesselationheight);
// returns how much tesselation of each segment is needed to remain under tolerance
int Q3PatchTesselationOnX(int patchwidth, int patchheight, int components, const float *in, float tolerance);
// returns how much tesselation of each segment is needed to remain under tolerance
int Q3PatchTesselationOnY(int patchwidth, int patchheight, int components, const float *in, float tolerance);
// calculates elements for a grid of vertices
// (such as those produced by Q3PatchTesselate)
// (note: width and height are the actual vertex size, this produces
// (width-1)*(height-1)*2 triangles, 3 elements each)
void Q3PatchTriangleElements(int *elements, int width, int height, int firstvertex);
int Q3PatchAdjustTesselation(int numcomponents, patchinfo_t *patch1, float *patchvertices1, patchinfo_t *patch2, float *patchvertices2);
#endif

1027
app/jni/cvar.c Normal file

File diff suppressed because it is too large Load diff

245
app/jni/cvar.h Normal file
View file

@ -0,0 +1,245 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cvar.h
/*
cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
in C code.
it is sufficient to initialize a cvar_t with just the first two fields, or
you can add a ,true flag for variables that you want saved to the configuration
file when the game is quit:
cvar_t r_draworder = {"r_draworder","1"};
cvar_t scr_screensize = {"screensize","1",true};
Cvars must be registered before use, or they will have a 0 value instead of the float interpretation of the string. Generally, all cvar_t declarations should be registered in the apropriate init function before any console commands are executed:
Cvar_RegisterVariable (&host_framerate);
C code usually just references a cvar in place:
if ( r_draworder.value )
It could optionally ask for the value to be looked up for a string name:
if (Cvar_VariableValue ("r_draworder"))
Interpreted prog code can access cvars with the cvar(name) or
cvar_set (name, value) internal functions:
teamplay = cvar("teamplay");
cvar_set ("registered", "1");
The user can access cvars from the console in two ways:
r_draworder prints the current value
r_draworder 0 sets the current value to 0
Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
*/
#ifndef CVAR_H
#define CVAR_H
// cvar flags
#define CVAR_SAVE 1
#define CVAR_NOTIFY 2
#define CVAR_READONLY 4
#define CVAR_SERVERINFO 8
#define CVAR_USERINFO 16
// CVAR_PRIVATE means do not $ expand or sendcvar this cvar under any circumstances (rcon_password uses this)
#define CVAR_PRIVATE 32
// this means that this cvar should update a userinfo key but the name does not correspond directly to the userinfo key to update, and may require additional conversion ("_cl_color" for example should update "topcolor" and "bottomcolor")
#define CVAR_NQUSERINFOHACK 64
// used to determine if flags is valid
#define CVAR_NORESETTODEFAULTS 128
// for engine-owned cvars that must not be reset on gametype switch (e.g. scr_screenshot_name, which otherwise isn't set to the mod name properly)
#define CVAR_MAXFLAGSVAL 255
// for internal use only!
#define CVAR_DEFAULTSET (1<<30)
#define CVAR_ALLOCATED (1<<31)
/*
// type of a cvar for menu purposes
#define CVARMENUTYPE_FLOAT 1
#define CVARMENUTYPE_INTEGER 2
#define CVARMENUTYPE_SLIDER 3
#define CVARMENUTYPE_BOOL 4
#define CVARMENUTYPE_STRING 5
#define CVARMENUTYPE_OPTION 6
// which menu to put a cvar in
#define CVARMENU_GRAPHICS 1
#define CVARMENU_SOUND 2
#define CVARMENU_INPUT 3
#define CVARMENU_NETWORK 4
#define CVARMENU_SERVER 5
#define MAX_CVAROPTIONS 16
typedef struct cvaroption_s
{
int value;
const char *name;
}
cvaroption_t;
typedef struct menucvar_s
{
int type;
float valuemin, valuemax, valuestep;
int numoptions;
cvaroption_t optionlist[MAX_CVAROPTIONS];
}
menucvar_t;
*/
typedef struct cvar_s
{
int flags;
const char *name;
const char *string;
const char *description;
int integer;
float value;
float vector[3];
const char *defstring;
// values at init (for Cvar_RestoreInitState)
qboolean initstate; // indicates this existed at init
int initflags;
const char *initstring;
const char *initdescription;
int initinteger;
float initvalue;
float initvector[3];
const char *initdefstring;
unsigned int globaldefindex_progid[3];
int globaldefindex[3];
int globaldefindex_stringno[3];
//menucvar_t menuinfo;
struct cvar_s *next;
struct cvar_s *nextonhashchain;
} cvar_t;
/*
void Cvar_MenuSlider(cvar_t *variable, int menu, float slider_min, float slider_max, float slider_step);
void Cvar_MenuBool(cvar_t *variable, int menu, const char *name_false, const char *name_true);
void Cvar_MenuFloat(cvar_t *variable, int menu, float range_min, float range_max);
void Cvar_MenuInteger(cvar_t *variable, int menu, int range_min, int range_max);
void Cvar_MenuString(cvar_t *variable, int menu);
void Cvar_MenuOption(cvar_t *variable, int menu, int value[16], const char *name[16]);
*/
/// registers a cvar that already has the name, string, and optionally the
/// archive elements set.
void Cvar_RegisterVariable (cvar_t *variable);
/// equivelant to "<name> <variable>" typed at the console
void Cvar_Set (const char *var_name, const char *value);
/// expands value to a string and calls Cvar_Set
void Cvar_SetValue (const char *var_name, float value);
void Cvar_SetQuick (cvar_t *var, const char *value);
void Cvar_SetValueQuick (cvar_t *var, float value);
float Cvar_VariableValueOr (const char *var_name, float def);
// returns def if not defined
float Cvar_VariableValue (const char *var_name);
// returns 0 if not defined or non numeric
const char *Cvar_VariableStringOr (const char *var_name, const char *def);
// returns def if not defined
const char *Cvar_VariableString (const char *var_name);
// returns an empty string if not defined
const char *Cvar_VariableDefString (const char *var_name);
// returns an empty string if not defined
const char *Cvar_VariableDescription (const char *var_name);
// returns an empty string if not defined
const char *Cvar_CompleteVariable (const char *partial);
// attempts to match a partial variable name for command line completion
// returns NULL if nothing fits
void Cvar_CompleteCvarPrint (const char *partial);
qboolean Cvar_Command (void);
// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
// command. Returns true if the command was a variable reference that
// was handled. (print or change)
void Cvar_SaveInitState(void);
void Cvar_RestoreInitState(void);
void Cvar_UnlockDefaults (void);
void Cvar_LockDefaults_f (void);
void Cvar_ResetToDefaults_All_f (void);
void Cvar_ResetToDefaults_NoSaveOnly_f (void);
void Cvar_ResetToDefaults_SaveOnly_f (void);
void Cvar_WriteVariables (qfile_t *f);
// Writes lines containing "set variable value" for all variables
// with the archive flag set to true.
cvar_t *Cvar_FindVar (const char *var_name);
cvar_t *Cvar_FindVarAfter (const char *prev_var_name, int neededflags);
int Cvar_CompleteCountPossible (const char *partial);
const char **Cvar_CompleteBuildList (const char *partial);
// Added by EvilTypeGuy - functions for tab completion system
// Thanks to Fett erich@heintz.com
// Thanks to taniwha
/// Prints a list of Cvars including a count of them to the user console
/// Referenced in cmd.c in Cmd_Init hence it's inclusion here.
/// Added by EvilTypeGuy eviltypeguy@qeradiant.com
/// Thanks to Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
void Cvar_List_f (void);
void Cvar_Set_f (void);
void Cvar_SetA_f (void);
void Cvar_Del_f (void);
// commands to create new cvars (or set existing ones)
// seta creates an archived cvar (saved to config)
/// allocates a cvar by name and returns its address,
/// or merely sets its value if it already exists.
cvar_t *Cvar_Get (const char *name, const char *value, int flags, const char *newdescription);
extern const char *cvar_dummy_description; // ALWAYS the same pointer
extern cvar_t *cvar_vars; // used to list all cvars
void Cvar_UpdateAllAutoCvars(void); // updates ALL autocvars of the active prog to the cvar values (savegame loading)
#ifdef FILLALLCVARSWITHRUBBISH
void Cvar_FillAll_f();
#endif /* FILLALLCVARSWITHRUBBISH */
#endif

5690
app/jni/dpsoftrast.c Normal file

File diff suppressed because it is too large Load diff

327
app/jni/dpsoftrast.h Normal file
View file

@ -0,0 +1,327 @@
#ifndef DPSOFTRAST_H
#define DPSOFTRAST_H
#include <stdlib.h>
#define DPSOFTRAST_MAXMIPMAPS 16
#define DPSOFTRAST_TEXTURE_MAXSIZE (1<<(DPSOFTRAST_MAXMIPMAPS - 1))
#define DPSOFTRAST_MAXTEXTUREUNITS 16
#define DPSOFTRAST_MAXTEXCOORDARRAYS 8
// type of pixels in texture (some of these are converted to BGRA8 on update)
#define DPSOFTRAST_TEXTURE_FORMAT_BGRA8 0
#define DPSOFTRAST_TEXTURE_FORMAT_DEPTH 1
#define DPSOFTRAST_TEXTURE_FORMAT_RGBA8 2
#define DPSOFTRAST_TEXTURE_FORMAT_ALPHA8 3
#define DPSOFTRAST_TEXTURE_FORMAT_RGBA16F 4
#define DPSOFTRAST_TEXTURE_FORMAT_RGBA32F 5
#define DPSOFTRAST_TEXTURE_FORMAT_COMPAREMASK 0x0F
// modifier flags for texture (can not be changed after creation)
#define DPSOFTRAST_TEXTURE_FLAG_MIPMAP 0x10
#define DPSOFTRAST_TEXTURE_FLAG_CUBEMAP 0x20
#define DPSOFTRAST_TEXTURE_FLAG_USEALPHA 0x40
#define DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE 0x80
typedef enum DPSOFTRAST_TEXTURE_FILTER_e
{
DPSOFTRAST_TEXTURE_FILTER_NEAREST = 0,
DPSOFTRAST_TEXTURE_FILTER_LINEAR = 1,
DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE = 2,
DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE = 3,
}
DPSOFTRAST_TEXTURE_FILTER;
int DPSOFTRAST_Init(int width, int height, int numthreads, int interlace, unsigned int *colorpixels, unsigned int *depthpixels);
void DPSOFTRAST_Shutdown(void);
void DPSOFTRAST_Flush(void);
void DPSOFTRAST_Finish(void);
int DPSOFTRAST_Texture_New(int flags, int width, int height, int depth);
void DPSOFTRAST_Texture_Free(int index);
void DPSOFTRAST_Texture_UpdatePartial(int index, int mip, const unsigned char *pixels, int blockx, int blocky, int blockwidth, int blockheight);
void DPSOFTRAST_Texture_UpdateFull(int index, const unsigned char *pixels);
int DPSOFTRAST_Texture_GetWidth(int index, int mip);
int DPSOFTRAST_Texture_GetHeight(int index, int mip);
int DPSOFTRAST_Texture_GetDepth(int index, int mip);
unsigned char *DPSOFTRAST_Texture_GetPixelPointer(int index, int mip);
void DPSOFTRAST_Texture_Filter(int index, DPSOFTRAST_TEXTURE_FILTER filter);
void DPSOFTRAST_SetRenderTargets(int width, int height, unsigned int *depthpixels, unsigned int *colorpixels0, unsigned int *colorpixels1, unsigned int *colorpixels2, unsigned int *colorpixels3);
void DPSOFTRAST_Viewport(int x, int y, int width, int height);
void DPSOFTRAST_ClearColor(float r, float g, float b, float a);
void DPSOFTRAST_ClearDepth(float d);
void DPSOFTRAST_ColorMask(int r, int g, int b, int a);
void DPSOFTRAST_DepthTest(int enable);
void DPSOFTRAST_ScissorTest(int enable);
void DPSOFTRAST_Scissor(float x, float y, float width, float height);
void DPSOFTRAST_ClipPlane(float x, float y, float z, float w);
void DPSOFTRAST_BlendFunc(int smodulate, int dmodulate);
void DPSOFTRAST_BlendSubtract(int enable);
void DPSOFTRAST_DepthMask(int enable);
void DPSOFTRAST_DepthFunc(int comparemode);
void DPSOFTRAST_DepthRange(float range0, float range1);
void DPSOFTRAST_PolygonOffset(float alongnormal, float intoview);
void DPSOFTRAST_CullFace(int mode);
void DPSOFTRAST_Color4f(float r, float g, float b, float a);
void DPSOFTRAST_GetPixelsBGRA(int blockx, int blocky, int blockwidth, int blockheight, unsigned char *outpixels);
void DPSOFTRAST_CopyRectangleToTexture(int index, int mip, int tx, int ty, int sx, int sy, int width, int height);
void DPSOFTRAST_SetTexture(int unitnum, int index);
void DPSOFTRAST_SetVertexPointer(const float *vertex3f, size_t stride);
void DPSOFTRAST_SetColorPointer(const float *color4f, size_t stride);
void DPSOFTRAST_SetColorPointer4ub(const unsigned char *color4ub, size_t stride);
void DPSOFTRAST_SetTexCoordPointer(int unitnum, int numcomponents, size_t stride, const float *texcoordf);
typedef enum gl20_texunit_e
{
// postprocess shaders, and generic shaders:
GL20TU_FIRST = 0,
GL20TU_SECOND = 1,
GL20TU_GAMMARAMPS = 2,
// standard material properties
GL20TU_NORMAL = 0,
GL20TU_COLOR = 1,
GL20TU_GLOSS = 2,
GL20TU_GLOW = 3,
// material properties for a second material
GL20TU_SECONDARY_NORMAL = 4,
GL20TU_SECONDARY_COLOR = 5,
GL20TU_SECONDARY_GLOSS = 6,
GL20TU_SECONDARY_GLOW = 7,
// material properties for a colormapped material
// conflicts with secondary material
GL20TU_PANTS = 4,
GL20TU_SHIRT = 7,
// fog fade in the distance
GL20TU_FOGMASK = 8,
// compiled ambient lightmap and deluxemap
GL20TU_LIGHTMAP = 9,
GL20TU_DELUXEMAP = 10,
// refraction, used by water shaders
GL20TU_REFRACTION = 3,
// reflection, used by water shaders, also with normal material rendering
// conflicts with secondary material
GL20TU_REFLECTION = 7,
// rtlight attenuation (distance fade) and cubemap filter (projection texturing)
// conflicts with lightmap/deluxemap
GL20TU_ATTENUATION = 9,
GL20TU_CUBE = 10,
GL20TU_SHADOWMAP2D = 15,
GL20TU_CUBEPROJECTION = 12,
// rtlight prepass data (screenspace depth and normalmap)
// GL20TU_UNUSED1 = 13,
GL20TU_SCREENNORMALMAP = 14,
// lightmap prepass data (screenspace diffuse and specular from lights)
GL20TU_SCREENDIFFUSE = 11,
GL20TU_SCREENSPECULAR = 12,
// fake reflections
GL20TU_REFLECTMASK = 5,
GL20TU_REFLECTCUBE = 6,
GL20TU_FOGHEIGHTTEXTURE = 14
}
gl20_texunit;
typedef enum glsl_attrib_e
{
GLSLATTRIB_POSITION = 0,
GLSLATTRIB_COLOR = 1,
GLSLATTRIB_TEXCOORD0 = 2,
GLSLATTRIB_TEXCOORD1 = 3,
GLSLATTRIB_TEXCOORD2 = 4,
GLSLATTRIB_TEXCOORD3 = 5,
GLSLATTRIB_TEXCOORD4 = 6,
GLSLATTRIB_TEXCOORD5 = 7,
GLSLATTRIB_TEXCOORD6 = 8,
GLSLATTRIB_TEXCOORD7 = 9,
}
glsl_attrib;
// this enum selects which of the glslshadermodeinfo entries should be used
typedef enum shadermode_e
{
SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP, // forced deluxemapping for lightmapped surfaces
SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR, // forced deluxemapping for vertexlit surfaces
SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
SHADERMODE_COUNT
}
shadermode_t;
typedef enum shaderpermutation_e
{
SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
SHADERPERMUTATION_FOGALPHAHACK = 1<<8, ///< fog color and density determined by texture mapped on vertical axis
SHADERPERMUTATION_GAMMARAMPS = 1<<9, ///< gamma (postprocessing only)
SHADERPERMUTATION_CUBEFILTER = 1<<10, ///< (lightsource) use cubemap light filter
SHADERPERMUTATION_GLOW = 1<<11, ///< (lightmap) blend in an additive glow texture
SHADERPERMUTATION_BLOOM = 1<<12, ///< bloom (postprocessing only)
SHADERPERMUTATION_SPECULAR = 1<<13, ///< (lightsource or deluxemapping) render specular effects
SHADERPERMUTATION_POSTPROCESSING = 1<<14, ///< user defined postprocessing (postprocessing only)
SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<19, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
SHADERPERMUTATION_SHADOWMAPORTHO = 1<<20, ///< (lightsource) use orthographic shadowmap projection
SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<21, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
SHADERPERMUTATION_ALPHAKILL = 1<<22, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5, (generic) apply global alpha
SHADERPERMUTATION_REFLECTCUBE = 1<<23, ///< fake reflections using global cubemap (not HDRI light probe)
SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<24, ///< (water) counter-direction normalmaps scrolling
SHADERPERMUTATION_BOUNCEGRID = 1<<25, ///< (lightmap) use Texture_BounceGrid as an additional source of ambient light
SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL = 1<<26, ///< (lightmap) use 16-component pixels in bouncegrid texture for directional lighting rather than standard 4-component
SHADERPERMUTATION_TRIPPY = 1<<27, ///< use trippy vertex shader effect
SHADERPERMUTATION_DEPTHRGB = 1<<28, ///< read/write depth values in RGB color coded format for older hardware without depth samplers
SHADERPERMUTATION_ALPHAGEN_VERTEX = 1<<29, ///< alphaGen vertex
SHADERPERMUTATION_SKELETAL = 1<<30, ///< (skeletal models) use skeletal matrices to deform vertices (gpu-skinning)
SHADERPERMUTATION_COUNT = 31 ///< size of shaderpermutationinfo array
}
shaderpermutation_t;
typedef enum DPSOFTRAST_UNIFORM_e
{
DPSOFTRAST_UNIFORM_Texture_First,
DPSOFTRAST_UNIFORM_Texture_Second,
DPSOFTRAST_UNIFORM_Texture_GammaRamps,
DPSOFTRAST_UNIFORM_Texture_Normal,
DPSOFTRAST_UNIFORM_Texture_Color,
DPSOFTRAST_UNIFORM_Texture_Gloss,
DPSOFTRAST_UNIFORM_Texture_Glow,
DPSOFTRAST_UNIFORM_Texture_SecondaryNormal,
DPSOFTRAST_UNIFORM_Texture_SecondaryColor,
DPSOFTRAST_UNIFORM_Texture_SecondaryGloss,
DPSOFTRAST_UNIFORM_Texture_SecondaryGlow,
DPSOFTRAST_UNIFORM_Texture_Pants,
DPSOFTRAST_UNIFORM_Texture_Shirt,
DPSOFTRAST_UNIFORM_Texture_FogHeightTexture,
DPSOFTRAST_UNIFORM_Texture_FogMask,
DPSOFTRAST_UNIFORM_Texture_Lightmap,
DPSOFTRAST_UNIFORM_Texture_Deluxemap,
DPSOFTRAST_UNIFORM_Texture_Attenuation,
DPSOFTRAST_UNIFORM_Texture_Cube,
DPSOFTRAST_UNIFORM_Texture_Refraction,
DPSOFTRAST_UNIFORM_Texture_Reflection,
DPSOFTRAST_UNIFORM_Texture_ShadowMap2D,
DPSOFTRAST_UNIFORM_Texture_CubeProjection,
DPSOFTRAST_UNIFORM_Texture_ScreenNormalMap,
DPSOFTRAST_UNIFORM_Texture_ScreenDiffuse,
DPSOFTRAST_UNIFORM_Texture_ScreenSpecular,
DPSOFTRAST_UNIFORM_Texture_ReflectMask,
DPSOFTRAST_UNIFORM_Texture_ReflectCube,
DPSOFTRAST_UNIFORM_Alpha,
DPSOFTRAST_UNIFORM_BloomBlur_Parameters,
DPSOFTRAST_UNIFORM_ClientTime,
DPSOFTRAST_UNIFORM_Color_Ambient,
DPSOFTRAST_UNIFORM_Color_Diffuse,
DPSOFTRAST_UNIFORM_Color_Specular,
DPSOFTRAST_UNIFORM_Color_Glow,
DPSOFTRAST_UNIFORM_Color_Pants,
DPSOFTRAST_UNIFORM_Color_Shirt,
DPSOFTRAST_UNIFORM_DeferredColor_Ambient,
DPSOFTRAST_UNIFORM_DeferredColor_Diffuse,
DPSOFTRAST_UNIFORM_DeferredColor_Specular,
DPSOFTRAST_UNIFORM_DeferredMod_Diffuse,
DPSOFTRAST_UNIFORM_DeferredMod_Specular,
DPSOFTRAST_UNIFORM_DistortScaleRefractReflect,
DPSOFTRAST_UNIFORM_EyePosition,
DPSOFTRAST_UNIFORM_FogColor,
DPSOFTRAST_UNIFORM_FogHeightFade,
DPSOFTRAST_UNIFORM_FogPlane,
DPSOFTRAST_UNIFORM_FogPlaneViewDist,
DPSOFTRAST_UNIFORM_FogRangeRecip,
DPSOFTRAST_UNIFORM_LightColor,
DPSOFTRAST_UNIFORM_LightDir,
DPSOFTRAST_UNIFORM_LightPosition,
DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
DPSOFTRAST_UNIFORM_PixelSize,
DPSOFTRAST_UNIFORM_ReflectColor,
DPSOFTRAST_UNIFORM_ReflectFactor,
DPSOFTRAST_UNIFORM_ReflectOffset,
DPSOFTRAST_UNIFORM_RefractColor,
DPSOFTRAST_UNIFORM_Saturation,
DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect,
DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect,
DPSOFTRAST_UNIFORM_ScreenToDepth,
DPSOFTRAST_UNIFORM_ShadowMap_Parameters,
DPSOFTRAST_UNIFORM_ShadowMap_TextureScale,
DPSOFTRAST_UNIFORM_SpecularPower,
DPSOFTRAST_UNIFORM_UserVec1,
DPSOFTRAST_UNIFORM_UserVec2,
DPSOFTRAST_UNIFORM_UserVec3,
DPSOFTRAST_UNIFORM_UserVec4,
DPSOFTRAST_UNIFORM_ViewTintColor,
DPSOFTRAST_UNIFORM_ViewToLightM1,
DPSOFTRAST_UNIFORM_ViewToLightM2,
DPSOFTRAST_UNIFORM_ViewToLightM3,
DPSOFTRAST_UNIFORM_ViewToLightM4,
DPSOFTRAST_UNIFORM_ModelToLightM1,
DPSOFTRAST_UNIFORM_ModelToLightM2,
DPSOFTRAST_UNIFORM_ModelToLightM3,
DPSOFTRAST_UNIFORM_ModelToLightM4,
DPSOFTRAST_UNIFORM_TexMatrixM1,
DPSOFTRAST_UNIFORM_TexMatrixM2,
DPSOFTRAST_UNIFORM_TexMatrixM3,
DPSOFTRAST_UNIFORM_TexMatrixM4,
DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1,
DPSOFTRAST_UNIFORM_BackgroundTexMatrixM2,
DPSOFTRAST_UNIFORM_BackgroundTexMatrixM3,
DPSOFTRAST_UNIFORM_BackgroundTexMatrixM4,
DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1,
DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM2,
DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM3,
DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM4,
DPSOFTRAST_UNIFORM_ModelViewMatrixM1,
DPSOFTRAST_UNIFORM_ModelViewMatrixM2,
DPSOFTRAST_UNIFORM_ModelViewMatrixM3,
DPSOFTRAST_UNIFORM_ModelViewMatrixM4,
DPSOFTRAST_UNIFORM_PixelToScreenTexCoord,
DPSOFTRAST_UNIFORM_ModelToReflectCubeM1,
DPSOFTRAST_UNIFORM_ModelToReflectCubeM2,
DPSOFTRAST_UNIFORM_ModelToReflectCubeM3,
DPSOFTRAST_UNIFORM_ModelToReflectCubeM4,
DPSOFTRAST_UNIFORM_ShadowMapMatrixM1,
DPSOFTRAST_UNIFORM_ShadowMapMatrixM2,
DPSOFTRAST_UNIFORM_ShadowMapMatrixM3,
DPSOFTRAST_UNIFORM_ShadowMapMatrixM4,
DPSOFTRAST_UNIFORM_BloomColorSubtract,
DPSOFTRAST_UNIFORM_NormalmapScrollBlend,
DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance,
DPSOFTRAST_UNIFORM_OffsetMapping_Bias,
DPSOFTRAST_UNIFORM_TOTAL
}
DPSOFTRAST_UNIFORM;
void DPSOFTRAST_SetShader(int mode, int permutation, int exactspecularmath);
#define DPSOFTRAST_Uniform1f(index, v0) DPSOFTRAST_Uniform4f(index, v0, 0, 0, 0)
#define DPSOFTRAST_Uniform2f(index, v0, v1) DPSOFTRAST_Uniform4f(index, v0, v1, 0, 0)
#define DPSOFTRAST_Uniform3f(index, v0, v1, v2) DPSOFTRAST_Uniform4f(index, v0, v1, v2, 0)
void DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM index, float v0, float v1, float v2, float v3);
void DPSOFTRAST_Uniform4fv(DPSOFTRAST_UNIFORM index, const float *v);
void DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM index, int arraysize, int transpose, const float *v);
void DPSOFTRAST_Uniform1i(DPSOFTRAST_UNIFORM index, int i0);
void DPSOFTRAST_DrawTriangles(int firstvertex, int numvertices, int numtriangles, const int *element3i, const unsigned short *element3s);
#endif // DPSOFTRAST_H

656
app/jni/dpvsimpledecode.c Normal file
View file

@ -0,0 +1,656 @@
#include "quakedef.h"
#include "dpvsimpledecode.h"
#define HZREADERROR_OK 0
#define HZREADERROR_EOF 1
#define HZREADERROR_MALLOCFAILED 2
//#define HZREADBLOCKSIZE 16000
#define HZREADBLOCKSIZE 1048576
typedef struct hz_bitstream_read_s
{
qfile_t *file;
int endoffile;
}
hz_bitstream_read_t;
typedef struct hz_bitstream_readblock_s
{
struct hz_bitstream_readblock_s *next;
unsigned int size;
unsigned char data[HZREADBLOCKSIZE];
}
hz_bitstream_readblock_t;
typedef struct hz_bitstream_readblocks_s
{
hz_bitstream_readblock_t *blocks;
hz_bitstream_readblock_t *current;
unsigned int position;
unsigned int store;
int count;
}
hz_bitstream_readblocks_t;
static hz_bitstream_read_t *hz_bitstream_read_open(char *filename)
{
qfile_t *file;
hz_bitstream_read_t *stream;
if ((file = FS_OpenVirtualFile(filename, false)))
{
stream = (hz_bitstream_read_t *)Z_Malloc(sizeof(hz_bitstream_read_t));
memset(stream, 0, sizeof(*stream));
stream->file = file;
return stream;
}
else
return NULL;
}
static void hz_bitstream_read_close(hz_bitstream_read_t *stream)
{
if (stream)
{
FS_Close(stream->file);
Z_Free(stream);
}
}
static hz_bitstream_readblocks_t *hz_bitstream_read_blocks_new(void)
{
hz_bitstream_readblocks_t *blocks;
blocks = (hz_bitstream_readblocks_t *)Z_Malloc(sizeof(hz_bitstream_readblocks_t));
if (blocks == NULL)
return NULL;
memset(blocks, 0, sizeof(hz_bitstream_readblocks_t));
return blocks;
}
static void hz_bitstream_read_blocks_free(hz_bitstream_readblocks_t *blocks)
{
hz_bitstream_readblock_t *b, *n;
if (blocks == NULL)
return;
for (b = blocks->blocks;b;b = n)
{
n = b->next;
Z_Free(b);
}
Z_Free(blocks);
}
static void hz_bitstream_read_flushbits(hz_bitstream_readblocks_t *blocks)
{
blocks->store = 0;
blocks->count = 0;
}
static int hz_bitstream_read_blocks_read(hz_bitstream_readblocks_t *blocks, hz_bitstream_read_t *stream, unsigned int size)
{
int s;
hz_bitstream_readblock_t *b, *p;
s = size;
p = NULL;
b = blocks->blocks;
while (s > 0)
{
if (b == NULL)
{
b = (hz_bitstream_readblock_t *)Z_Malloc(sizeof(hz_bitstream_readblock_t));
if (b == NULL)
return HZREADERROR_MALLOCFAILED;
b->next = NULL;
b->size = 0;
if (p != NULL)
p->next = b;
else
blocks->blocks = b;
}
if (s > HZREADBLOCKSIZE)
b->size = HZREADBLOCKSIZE;
else
b->size = s;
s -= b->size;
if (FS_Read(stream->file, b->data, b->size) != (fs_offset_t)b->size)
{
stream->endoffile = 1;
break;
}
p = b;
b = b->next;
}
while (b)
{
b->size = 0;
b = b->next;
}
blocks->current = blocks->blocks;
blocks->position = 0;
hz_bitstream_read_flushbits(blocks);
if (stream->endoffile)
return HZREADERROR_EOF;
return HZREADERROR_OK;
}
static unsigned int hz_bitstream_read_blocks_getbyte(hz_bitstream_readblocks_t *blocks)
{
while (blocks->current != NULL && blocks->position >= blocks->current->size)
{
blocks->position = 0;
blocks->current = blocks->current->next;
}
if (blocks->current == NULL)
return 0;
return blocks->current->data[blocks->position++];
}
static int hz_bitstream_read_bit(hz_bitstream_readblocks_t *blocks)
{
if (!blocks->count)
{
blocks->count += 8;
blocks->store <<= 8;
blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
}
blocks->count--;
return (blocks->store >> blocks->count) & 1;
}
static unsigned int hz_bitstream_read_bits(hz_bitstream_readblocks_t *blocks, int size)
{
unsigned int num = 0;
// we can only handle about 24 bits at a time safely
// (there might be up to 7 bits more than we need in the bit store)
if (size > 24)
{
size -= 8;
num |= hz_bitstream_read_bits(blocks, 8) << size;
}
while (blocks->count < size)
{
blocks->count += 8;
blocks->store <<= 8;
blocks->store |= hz_bitstream_read_blocks_getbyte(blocks) & 0xFF;
}
blocks->count -= size;
num |= (blocks->store >> blocks->count) & ((1 << size) - 1);
return num;
}
static unsigned int hz_bitstream_read_byte(hz_bitstream_readblocks_t *blocks)
{
return hz_bitstream_read_blocks_getbyte(blocks);
}
static unsigned int hz_bitstream_read_short(hz_bitstream_readblocks_t *blocks)
{
return (hz_bitstream_read_byte(blocks) << 8)
| (hz_bitstream_read_byte(blocks));
}
static unsigned int hz_bitstream_read_int(hz_bitstream_readblocks_t *blocks)
{
return (hz_bitstream_read_byte(blocks) << 24)
| (hz_bitstream_read_byte(blocks) << 16)
| (hz_bitstream_read_byte(blocks) << 8)
| (hz_bitstream_read_byte(blocks));
}
static void hz_bitstream_read_bytes(hz_bitstream_readblocks_t *blocks, void *outdata, unsigned int size)
{
unsigned char *out;
out = (unsigned char *)outdata;
while (size--)
*out++ = hz_bitstream_read_byte(blocks);
}
#define BLOCKSIZE 8
typedef struct dpvsimpledecodestream_s
{
hz_bitstream_read_t *bitstream;
hz_bitstream_readblocks_t *framedatablocks;
int error;
double info_framerate;
unsigned int info_frames;
unsigned int info_imagewidth;
unsigned int info_imageheight;
unsigned int info_imagebpp;
unsigned int info_imageRloss;
unsigned int info_imageRmask;
unsigned int info_imageRshift;
unsigned int info_imageGloss;
unsigned int info_imageGmask;
unsigned int info_imageGshift;
unsigned int info_imageBloss;
unsigned int info_imageBmask;
unsigned int info_imageBshift;
unsigned int info_imagesize;
double info_aspectratio;
// current video frame (needed because of delta compression)
int videoframenum;
// current video frame data (needed because of delta compression)
unsigned int *videopixels;
// channel the sound file is being played on
int sndchan;
}
dpvsimpledecodestream_t;
static int dpvsimpledecode_setpixelformat(dpvsimpledecodestream_t *s, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel)
{
int Rshift, Rbits, Gshift, Gbits, Bshift, Bbits;
if (!Rmask)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
return s->error;
}
if (!Gmask)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
return s->error;
}
if (!Bmask)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
return s->error;
}
if (Rmask & Gmask || Rmask & Bmask || Gmask & Bmask)
{
s->error = DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP;
return s->error;
}
switch (bytesperpixel)
{
case 2:
if ((Rmask | Gmask | Bmask) > 65536)
{
s->error = DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP;
return s->error;
}
break;
case 4:
break;
default:
s->error = DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP;
return s->error;
}
for (Rshift = 0;!(Rmask & 1);Rshift++, Rmask >>= 1);
for (Gshift = 0;!(Gmask & 1);Gshift++, Gmask >>= 1);
for (Bshift = 0;!(Bmask & 1);Bshift++, Bmask >>= 1);
if (((Rmask + 1) & Rmask) != 0)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDRMASK;
return s->error;
}
if (((Gmask + 1) & Gmask) != 0)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDGMASK;
return s->error;
}
if (((Bmask + 1) & Bmask) != 0)
{
s->error = DPVSIMPLEDECODEERROR_INVALIDBMASK;
return s->error;
}
for (Rbits = 0;Rmask & 1;Rbits++, Rmask >>= 1);
for (Gbits = 0;Gmask & 1;Gbits++, Gmask >>= 1);
for (Bbits = 0;Bmask & 1;Bbits++, Bmask >>= 1);
if (Rbits > 8)
{
Rshift += (Rbits - 8);
Rbits = 8;
}
if (Gbits > 8)
{
Gshift += (Gbits - 8);
Gbits = 8;
}
if (Bbits > 8)
{
Bshift += (Bbits - 8);
Bbits = 8;
}
s->info_imagebpp = bytesperpixel;
s->info_imageRloss = 16 + (8 - Rbits);
s->info_imageGloss = 8 + (8 - Gbits);
s->info_imageBloss = 0 + (8 - Bbits);
s->info_imageRmask = (1 << Rbits) - 1;
s->info_imageGmask = (1 << Gbits) - 1;
s->info_imageBmask = (1 << Bbits) - 1;
s->info_imageRshift = Rshift;
s->info_imageGshift = Gshift;
s->info_imageBshift = Bshift;
s->info_imagesize = s->info_imagewidth * s->info_imageheight * s->info_imagebpp;
return s->error;
}
// opening and closing streams
// opens a stream
void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring)
{
dpvsimpledecodestream_t *s;
char t[8], *wavename;
if (errorstring != NULL)
*errorstring = NULL;
s = (dpvsimpledecodestream_t *)Z_Malloc(sizeof(dpvsimpledecodestream_t));
if (s != NULL)
{
s->bitstream = hz_bitstream_read_open(filename);
if (s->bitstream != NULL)
{
// check file identification
s->framedatablocks = hz_bitstream_read_blocks_new();
if (s->framedatablocks != NULL)
{
hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
hz_bitstream_read_bytes(s->framedatablocks, t, 8);
if (!memcmp(t, "DPVideo", 8))
{
// check version number
hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 2);
if (hz_bitstream_read_short(s->framedatablocks) == 1)
{
hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 12);
s->info_imagewidth = hz_bitstream_read_short(s->framedatablocks);
s->info_imageheight = hz_bitstream_read_short(s->framedatablocks);
s->info_framerate = (double) hz_bitstream_read_int(s->framedatablocks) * (1.0 / 65536.0);
s->info_aspectratio = (double)s->info_imagewidth / (double)s->info_imageheight;
if (s->info_framerate > 0.0)
{
s->videopixels = (unsigned int *)Z_Malloc(s->info_imagewidth * s->info_imageheight * sizeof(*s->videopixels));
if (s->videopixels != NULL)
{
size_t namelen;
namelen = strlen(filename) + 10;
wavename = (char *)Z_Malloc(namelen);
if (wavename)
{
sfx_t* sfx;
FS_StripExtension(filename, wavename, namelen);
strlcat(wavename, ".wav", namelen);
sfx = S_PrecacheSound (wavename, false, false);
if (sfx != NULL)
s->sndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0);
else
s->sndchan = -1;
Z_Free(wavename);
}
// all is well...
// set the module functions
s->videoframenum = -10000;
video->close = dpvsimpledecode_close;
video->getwidth = dpvsimpledecode_getwidth;
video->getheight = dpvsimpledecode_getheight;
video->getframerate = dpvsimpledecode_getframerate;
video->decodeframe = dpvsimpledecode_video;
video->getaspectratio = dpvsimpledecode_getaspectratio;
return s;
}
else if (errorstring != NULL)
*errorstring = "unable to allocate video image buffer";
}
else if (errorstring != NULL)
*errorstring = "error in video info chunk";
}
else if (errorstring != NULL)
*errorstring = "read error";
}
else if (errorstring != NULL)
*errorstring = "not a dpvideo file";
hz_bitstream_read_blocks_free(s->framedatablocks);
}
else if (errorstring != NULL)
*errorstring = "unable to allocate memory for reading buffer";
hz_bitstream_read_close(s->bitstream);
}
else if (errorstring != NULL)
*errorstring = "unable to open file";
Z_Free(s);
}
else if (errorstring != NULL)
*errorstring = "unable to allocate memory for stream info structure";
return NULL;
}
// closes a stream
void dpvsimpledecode_close(void *stream)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
if (s == NULL)
return;
if (s->videopixels)
Z_Free(s->videopixels);
if (s->sndchan != -1)
S_StopChannel (s->sndchan, true, true);
if (s->framedatablocks)
hz_bitstream_read_blocks_free(s->framedatablocks);
if (s->bitstream)
hz_bitstream_read_close(s->bitstream);
Z_Free(s);
}
// utilitarian functions
// returns the current error number for the stream, and resets the error
// number to DPVSIMPLEDECODEERROR_NONE
// if the supplied string pointer variable is not NULL, it will be set to the
// error message
int dpvsimpledecode_error(void *stream, const char **errorstring)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
int e;
e = s->error;
s->error = 0;
if (errorstring)
{
switch (e)
{
case DPVSIMPLEDECODEERROR_NONE:
*errorstring = "no error";
break;
case DPVSIMPLEDECODEERROR_EOF:
*errorstring = "end of file reached (this is not an error)";
break;
case DPVSIMPLEDECODEERROR_READERROR:
*errorstring = "read error (corrupt or incomplete file)";
break;
case DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL:
*errorstring = "sound buffer is too small for decoding frame (please allocate it as large as dpvsimpledecode_getneededsoundbufferlength suggests)";
break;
case DPVSIMPLEDECODEERROR_INVALIDRMASK:
*errorstring = "invalid red bits mask";
break;
case DPVSIMPLEDECODEERROR_INVALIDGMASK:
*errorstring = "invalid green bits mask";
break;
case DPVSIMPLEDECODEERROR_INVALIDBMASK:
*errorstring = "invalid blue bits mask";
break;
case DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP:
*errorstring = "color bit masks overlap";
break;
case DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP:
*errorstring = "color masks too big for specified bytes per pixel";
break;
case DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP:
*errorstring = "unsupported bytes per pixel (must be 2 for 16bit, or 4 for 32bit)";
break;
default:
*errorstring = "unknown error";
break;
}
}
return e;
}
// returns the width of the image data
unsigned int dpvsimpledecode_getwidth(void *stream)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
return s->info_imagewidth;
}
// returns the height of the image data
unsigned int dpvsimpledecode_getheight(void *stream)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
return s->info_imageheight;
}
// returns the framerate of the stream
double dpvsimpledecode_getframerate(void *stream)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
return s->info_framerate;
}
// return aspect ratio of the stream
double dpvsimpledecode_getaspectratio(void *stream)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
return s->info_aspectratio;
}
static int dpvsimpledecode_convertpixels(dpvsimpledecodestream_t *s, void *imagedata, int imagebytesperrow)
{
unsigned int a, x, y, width, height;
unsigned int Rloss, Rmask, Rshift, Gloss, Gmask, Gshift, Bloss, Bmask, Bshift;
unsigned int *in;
width = s->info_imagewidth;
height = s->info_imageheight;
Rloss = s->info_imageRloss;
Rmask = s->info_imageRmask;
Rshift = s->info_imageRshift;
Gloss = s->info_imageGloss;
Gmask = s->info_imageGmask;
Gshift = s->info_imageGshift;
Bloss = s->info_imageBloss;
Bmask = s->info_imageBmask;
Bshift = s->info_imageBshift;
in = s->videopixels;
if (s->info_imagebpp == 4)
{
unsigned int *outrow;
for (y = 0;y < height;y++)
{
outrow = (unsigned int *)((unsigned char *)imagedata + y * imagebytesperrow);
for (x = 0;x < width;x++)
{
a = *in++;
outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
}
}
}
else
{
unsigned short *outrow;
for (y = 0;y < height;y++)
{
outrow = (unsigned short *)((unsigned char *)imagedata + y * imagebytesperrow);
if (Rloss == 19 && Gloss == 10 && Bloss == 3 && Rshift == 11 && Gshift == 5 && Bshift == 0)
{
// optimized
for (x = 0;x < width;x++)
{
a = *in++;
outrow[x] = ((a >> 8) & 0xF800) | ((a >> 5) & 0x07E0) | ((a >> 3) & 0x001F);
}
}
else
{
for (x = 0;x < width;x++)
{
a = *in++;
outrow[x] = (((a >> Rloss) & Rmask) << Rshift) | (((a >> Gloss) & Gmask) << Gshift) | (((a >> Bloss) & Bmask) << Bshift);
}
}
}
}
return s->error;
}
static int dpvsimpledecode_decompressimage(dpvsimpledecodestream_t *s)
{
int i, a, b, colors, g, x1, y1, bw, bh, width, height, palettebits;
unsigned int palette[256], *outrow, *out;
g = BLOCKSIZE;
width = s->info_imagewidth;
height = s->info_imageheight;
for (y1 = 0;y1 < height;y1 += g)
{
outrow = s->videopixels + y1 * width;
bh = g;
if (y1 + bh > height)
bh = height - y1;
for (x1 = 0;x1 < width;x1 += g)
{
out = outrow + x1;
bw = g;
if (x1 + bw > width)
bw = width - x1;
if (hz_bitstream_read_bit(s->framedatablocks))
{
// updated block
palettebits = hz_bitstream_read_bits(s->framedatablocks, 3);
colors = 1 << palettebits;
for (i = 0;i < colors;i++)
palette[i] = hz_bitstream_read_bits(s->framedatablocks, 24);
if (palettebits)
{
for (b = 0;b < bh;b++, out += width)
for (a = 0;a < bw;a++)
out[a] = palette[hz_bitstream_read_bits(s->framedatablocks, palettebits)];
}
else
{
for (b = 0;b < bh;b++, out += width)
for (a = 0;a < bw;a++)
out[a] = palette[0];
}
}
}
}
return s->error;
}
// decodes a video frame to the supplied output pixels
int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow)
{
dpvsimpledecodestream_t *s = (dpvsimpledecodestream_t *)stream;
unsigned int framedatasize;
char t[4];
s->error = DPVSIMPLEDECODEERROR_NONE;
if (dpvsimpledecode_setpixelformat(s, Rmask, Gmask, Bmask, bytesperpixel))
return s->error;
hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, 8);
hz_bitstream_read_bytes(s->framedatablocks, t, 4);
if (memcmp(t, "VID0", 4))
{
if (t[0] == 0)
return (s->error = DPVSIMPLEDECODEERROR_EOF);
else
return (s->error = DPVSIMPLEDECODEERROR_READERROR);
}
framedatasize = hz_bitstream_read_int(s->framedatablocks);
hz_bitstream_read_blocks_read(s->framedatablocks, s->bitstream, framedatasize);
if (dpvsimpledecode_decompressimage(s))
return s->error;
dpvsimpledecode_convertpixels(s, imagedata, imagebytesperrow);
return s->error;
}

49
app/jni/dpvsimpledecode.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef DPVSIMPLEDECODE_H
#define DPVSIMPLEDECODE_H
#include "cl_video.h"
#define DPVSIMPLEDECODEERROR_NONE 0
#define DPVSIMPLEDECODEERROR_EOF 1
#define DPVSIMPLEDECODEERROR_READERROR 2
#define DPVSIMPLEDECODEERROR_SOUNDBUFFERTOOSMALL 3
#define DPVSIMPLEDECODEERROR_INVALIDRMASK 4
#define DPVSIMPLEDECODEERROR_INVALIDGMASK 5
#define DPVSIMPLEDECODEERROR_INVALIDBMASK 6
#define DPVSIMPLEDECODEERROR_COLORMASKSOVERLAP 7
#define DPVSIMPLEDECODEERROR_COLORMASKSEXCEEDBPP 8
#define DPVSIMPLEDECODEERROR_UNSUPPORTEDBPP 9
// opening and closing streams
// opens a stream
void *dpvsimpledecode_open(clvideo_t *video, char *filename, const char **errorstring);
// closes a stream
void dpvsimpledecode_close(void *stream);
// utilitarian functions
// returns the current error number for the stream, and resets the error
// number to DPVDECODEERROR_NONE
// if the supplied string pointer variable is not NULL, it will be set to the
// error message
int dpvsimpledecode_error(void *stream, const char **errorstring);
// returns the width of the image data
unsigned int dpvsimpledecode_getwidth(void *stream);
// returns the height of the image data
unsigned int dpvsimpledecode_getheight(void *stream);
// returns the framerate of the stream
double dpvsimpledecode_getframerate(void *stream);
// returns aspect ratio of the stream
double dpvsimpledecode_getaspectratio(void *stream);
// decodes a video frame to the supplied output pixels
int dpvsimpledecode_video(void *stream, void *imagedata, unsigned int Rmask, unsigned int Gmask, unsigned int Bmask, unsigned int bytesperpixel, int imagebytesperrow);
#endif

207
app/jni/draw.h Normal file
View file

@ -0,0 +1,207 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// draw.h -- these are the only functions outside the refresh allowed
// to touch the vid buffer
#ifndef DRAW_H
#define DRAW_H
// FIXME: move this stuff to cl_screen
typedef struct cachepic_s
{
// size of pic
int width, height;
// this flag indicates that it should be loaded and unloaded on demand
int autoload;
// texture flags to upload with
int texflags;
// texture may be freed after a while
int lastusedframe;
// renderer texture to use
rtexture_t *tex;
// used for hash lookups
struct cachepic_s *chain;
// flags - CACHEPICFLAG_NEWPIC for example
unsigned int flags;
// has alpha?
qboolean hasalpha;
// name of pic
char name[MAX_QPATH];
// allow to override/free the texture
qboolean allow_free_tex;
}
cachepic_t;
typedef enum cachepicflags_e
{
CACHEPICFLAG_NOTPERSISTENT = 1,
CACHEPICFLAG_QUIET = 2,
CACHEPICFLAG_NOCOMPRESSION = 4,
CACHEPICFLAG_NOCLAMP = 8,
CACHEPICFLAG_NEWPIC = 16, // disables matching texflags check, because a pic created with Draw_NewPic should not be subject to that
CACHEPICFLAG_MIPMAP = 32,
CACHEPICFLAG_NEAREST = 64 // force nearest filtering instead of linear
}
cachepicflags_t;
void Draw_Init (void);
void Draw_Frame (void);
cachepic_t *Draw_CachePic_Flags (const char *path, unsigned int cachepicflags);
cachepic_t *Draw_CachePic (const char *path); // standard function with no options, used throughout engine
// create or update a pic's image
cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, unsigned char *pixels);
// free the texture memory used by a pic
void Draw_FreePic(const char *picname);
// a triangle mesh..
// each vertex is 3 floats
// each texcoord is 2 floats
// each color is 4 floats
typedef struct drawqueuemesh_s
{
rtexture_t *texture;
int num_triangles;
int num_vertices;
int *data_element3i;
unsigned short *data_element3s;
float *data_vertex3f;
float *data_texcoord2f;
float *data_color4f;
}
drawqueuemesh_t;
enum drawqueue_drawflag_e {
DRAWFLAG_NORMAL,
DRAWFLAG_ADDITIVE,
DRAWFLAG_MODULATE,
DRAWFLAG_2XMODULATE,
DRAWFLAG_SCREEN,
DRAWFLAG_NUMFLAGS,
DRAWFLAG_MASK = 0xFF, // ONLY R_BeginPolygon()
DRAWFLAG_MIPMAP = 0x100, // ONLY R_BeginPolygon()
DRAWFLAG_NOGAMMA = 0x200 // ONLY R_DrawQSuperPic()
};
#define DRAWFLAGS_BLEND 0xFF /* this matches all blending flags */
typedef struct ft2_settings_s
{
float scale, voffset;
// cvar parameters (only read on loadfont command)
int antialias, hinting;
float outline, blur, shadowx, shadowy, shadowz;
} ft2_settings_t;
#define MAX_FONT_SIZES 16
#define MAX_FONT_FALLBACKS 3
typedef struct dp_font_s
{
rtexture_t *tex;
float width_of[256]; // width_of[0] == max width of any char; 1.0f is base width (1/16 of texture width); therefore, all widths have to be <= 1 (does not include scale)
float maxwidth; // precalculated max width of the font (includes scale)
char texpath[MAX_QPATH];
char title[MAX_QPATH];
int req_face; // requested face index, usually 0
float req_sizes[MAX_FONT_SIZES]; // sizes to render the font with, 0 still defaults to 16 (backward compatibility when loadfont doesn't get a size parameter) and -1 = disabled
char fallbacks[MAX_FONT_FALLBACKS][MAX_QPATH];
int fallback_faces[MAX_FONT_FALLBACKS];
struct ft2_font_s *ft2;
ft2_settings_t settings;
}
dp_font_t;
typedef struct dp_fonts_s
{
dp_font_t *f;
int maxsize;
}
dp_fonts_t;
extern dp_fonts_t dp_fonts;
#define MAX_FONTS 16 // fonts at the start
#define FONTS_EXPAND 8 // fonts grow when no free slots
#define FONT_DEFAULT (&dp_fonts.f[0]) // should be fixed width
#define FONT_CONSOLE (&dp_fonts.f[1]) // REALLY should be fixed width (ls!)
#define FONT_SBAR (&dp_fonts.f[2]) // must be fixed width
#define FONT_NOTIFY (&dp_fonts.f[3]) // free
#define FONT_CHAT (&dp_fonts.f[4]) // free
#define FONT_CENTERPRINT (&dp_fonts.f[5]) // free
#define FONT_INFOBAR (&dp_fonts.f[6]) // free
#define FONT_MENU (&dp_fonts.f[7]) // should be fixed width
#define FONT_USER(i) (&dp_fonts.f[8+i]) // userdefined fonts
#define MAX_USERFONTS (dp_fonts.maxsize - 8)
// shared color tag printing constants
#define STRING_COLOR_TAG '^'
#define STRING_COLOR_DEFAULT 7
#define STRING_COLOR_DEFAULT_STR "^7"
#define STRING_COLOR_RGB_TAG_CHAR 'x'
#define STRING_COLOR_RGB_TAG "^x"
// all of these functions will set r_defdef.draw2dstage if not in 2D rendering mode (and of course prepare for 2D rendering in that case)
// draw an image (or a filled rectangle if pic == NULL)
void DrawQ_Pic(float x, float y, cachepic_t *pic, float width, float height, float red, float green, float blue, float alpha, int flags);
// draw a rotated image
void DrawQ_RotPic(float x, float y, cachepic_t *pic, float width, float height, float org_x, float org_y, float angle, float red, float green, float blue, float alpha, int flags);
// draw a filled rectangle (slightly faster than DrawQ_Pic with pic = NULL)
void DrawQ_Fill(float x, float y, float width, float height, float red, float green, float blue, float alpha, int flags);
// draw a text string,
// with optional color tag support,
// returns final unclipped x coordinate
// if outcolor is provided the initial color is read from it, and it is updated at the end with the new value at the end of the text (not at the end of the clipped part)
// the color is tinted by the provided base color
// if r_textshadow is not zero, an additional instance of the text is drawn first at an offset with an inverted shade of gray (black text produces a white shadow, brightly colored text produces a black shadow)
extern float DrawQ_Color[4];
float DrawQ_String(float x, float y, const char *text, size_t maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt);
float DrawQ_String_Scale(float x, float y, const char *text, size_t maxlen, float sizex, float sizey, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt);
float DrawQ_TextWidth(const char *text, size_t maxlen, float w, float h, qboolean ignorecolorcodes, const dp_font_t *fnt);
float DrawQ_TextWidth_UntilWidth(const char *text, size_t *maxlen, float w, float h, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxWidth);
float DrawQ_TextWidth_UntilWidth_TrackColors(const char *text, size_t *maxlen, float w, float h, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxwidth);
float DrawQ_TextWidth_UntilWidth_TrackColors_Scale(const char *text, size_t *maxlen, float w, float h, float sw, float sh, int *outcolor, qboolean ignorecolorcodes, const dp_font_t *fnt, float maxwidth);
// draw a very fancy pic (per corner texcoord/color control), the order is tl, tr, bl, br
void DrawQ_SuperPic(float x, float y, cachepic_t *pic, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags);
// draw a triangle mesh
void DrawQ_Mesh(drawqueuemesh_t *mesh, int flags, qboolean hasalpha);
// set the clipping area
void DrawQ_SetClipArea(float x, float y, float width, float height);
// reset the clipping area
void DrawQ_ResetClipArea(void);
// draw a line
void DrawQ_Line(float width, float x1, float y1, float x2, float y2, float r, float g, float b, float alpha, int flags);
// draw a lot of lines (call R_Mesh_PrepareVertices_Generic first)
void DrawQ_Lines(float width, int numlines, int flags, qboolean hasalpha);
// draw a line loop
void DrawQ_LineLoop(drawqueuemesh_t *mesh, int flags);
// resets r_refdef.draw2dstage
void DrawQ_Finish(void);
void DrawQ_ProcessDrawFlag(int flags, qboolean alpha); // sets GL_DepthMask and GL_BlendFunc
void DrawQ_RecalcView(void); // use this when changing r_refdef.view.* from e.g. csqc
rtexture_t *Draw_GetPicTexture(cachepic_t *pic);
void R_DrawGamma(void);
extern rtexturepool_t *drawtexturepool; // used by ft2.c
#endif

204
app/jni/filematch.c Normal file
View file

@ -0,0 +1,204 @@
#ifdef WIN32
#include <windows.h>
#else
#include <dirent.h>
#endif
#include "quakedef.h"
// LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such...
int matchpattern(const char *in, const char *pattern, int caseinsensitive)
{
return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false);
}
// wildcard_least_one: if true * matches 1 or more characters
// if false * matches 0 or more characters
int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one)
{
int c1, c2;
while (*pattern)
{
switch (*pattern)
{
case 0:
return 1; // end of pattern
case '?': // match any single character
if (*in == 0 || strchr(separators, *in))
return 0; // no match
in++;
pattern++;
break;
case '*': // match anything until following string
if(wildcard_least_one)
{
if (*in == 0 || strchr(separators, *in))
return 0; // no match
in++;
}
pattern++;
while (*in)
{
if (strchr(separators, *in))
break;
// see if pattern matches at this offset
if (matchpattern_with_separator(in, pattern, caseinsensitive, separators, wildcard_least_one))
return 1;
// nope, advance to next offset
in++;
}
break;
default:
if (*in != *pattern)
{
if (!caseinsensitive)
return 0; // no match
c1 = *in;
if (c1 >= 'A' && c1 <= 'Z')
c1 += 'a' - 'A';
c2 = *pattern;
if (c2 >= 'A' && c2 <= 'Z')
c2 += 'a' - 'A';
if (c1 != c2)
return 0; // no match
}
in++;
pattern++;
break;
}
}
if (*in)
return 0; // reached end of pattern but not end of input
return 1; // success
}
// a little strings system
void stringlistinit(stringlist_t *list)
{
memset(list, 0, sizeof(*list));
}
void stringlistfreecontents(stringlist_t *list)
{
int i;
for (i = 0;i < list->numstrings;i++)
{
if (list->strings[i])
Z_Free(list->strings[i]);
list->strings[i] = NULL;
}
list->numstrings = 0;
list->maxstrings = 0;
if (list->strings)
Z_Free(list->strings);
list->strings = NULL;
}
void stringlistappend(stringlist_t *list, const char *text)
{
size_t textlen;
char **oldstrings;
if (list->numstrings >= list->maxstrings)
{
oldstrings = list->strings;
list->maxstrings += 4096;
list->strings = (char **) Z_Malloc(list->maxstrings * sizeof(*list->strings));
if (list->numstrings)
memcpy(list->strings, oldstrings, list->numstrings * sizeof(*list->strings));
if (oldstrings)
Z_Free(oldstrings);
}
textlen = strlen(text) + 1;
list->strings[list->numstrings] = (char *) Z_Malloc(textlen);
memcpy(list->strings[list->numstrings], text, textlen);
list->numstrings++;
}
static int stringlistsort_cmp(const void *a, const void *b)
{
return strcasecmp(*(const char **)a, *(const char **)b);
}
void stringlistsort(stringlist_t *list, qboolean uniq)
{
int i, j;
if(list->numstrings < 1)
return;
qsort(&list->strings[0], list->numstrings, sizeof(list->strings[0]), stringlistsort_cmp);
if(uniq)
{
// i: the item to read
// j: the item last written
for (i = 1, j = 0; i < list->numstrings; ++i)
{
char *save;
if(!strcasecmp(list->strings[i], list->strings[j]))
continue;
++j;
save = list->strings[j];
list->strings[j] = list->strings[i];
list->strings[i] = save;
}
for(i = j+1; i < list->numstrings; ++i)
{
if (list->strings[i])
Z_Free(list->strings[i]);
}
list->numstrings = j+1;
}
}
// operating system specific code
static void adddirentry(stringlist_t *list, const char *path, const char *name)
{
if (strcmp(name, ".") && strcmp(name, ".."))
{
char temp[MAX_OSPATH];
dpsnprintf( temp, sizeof( temp ), "%s%s", path, name );
stringlistappend(list, temp);
}
}
#ifdef WIN32
void listdirectory(stringlist_t *list, const char *basepath, const char *path)
{
int i;
char pattern[4096], *c;
WIN32_FIND_DATA n_file;
HANDLE hFile;
strlcpy (pattern, basepath, sizeof(pattern));
strlcat (pattern, path, sizeof (pattern));
strlcat (pattern, "*", sizeof (pattern));
// ask for the directory listing handle
hFile = FindFirstFile(pattern, &n_file);
if(hFile == INVALID_HANDLE_VALUE)
return;
do {
adddirentry(list, path, n_file.cFileName);
} while (FindNextFile(hFile, &n_file) != 0);
FindClose(hFile);
// convert names to lowercase because windows does not care, but pattern matching code often does
for (i = 0;i < list->numstrings;i++)
for (c = list->strings[i];*c;c++)
if (*c >= 'A' && *c <= 'Z')
*c += 'a' - 'A';
}
#else
void listdirectory(stringlist_t *list, const char *basepath, const char *path)
{
char fullpath[MAX_OSPATH];
DIR *dir;
struct dirent *ent;
dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./");
dir = opendir(fullpath);
if (!dir)
return;
while ((ent = readdir(dir)))
adddirentry(list, path, ent->d_name);
closedir(dir);
}
#endif

226
app/jni/fractalnoise.c Normal file
View file

@ -0,0 +1,226 @@
#include "quakedef.h"
void fractalnoise(unsigned char *noise, int size, int startgrid)
{
int x, y, g, g2, amplitude, min, max, size1 = size - 1, sizepower, gridpower;
int *noisebuf;
#define n(x,y) noisebuf[((y)&size1)*size+((x)&size1)]
for (sizepower = 0;(1 << sizepower) < size;sizepower++);
if (size != (1 << sizepower))
{
Con_Printf("fractalnoise: size must be power of 2\n");
return;
}
for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
if (startgrid != (1 << gridpower))
{
Con_Printf("fractalnoise: grid must be power of 2\n");
return;
}
startgrid = bound(0, startgrid, size);
amplitude = 0xFFFF; // this gets halved before use
noisebuf = (int *)Mem_Alloc(tempmempool, size*size*sizeof(int));
memset(noisebuf, 0, size*size*sizeof(int));
for (g2 = startgrid;g2;g2 >>= 1)
{
// brownian motion (at every smaller level there is random behavior)
amplitude >>= 1;
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
n(x,y) += (rand()&amplitude);
g = g2 >> 1;
if (g)
{
// subdivide, diamond-square algorithm (really this has little to do with squares)
// diamond
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
// square
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
{
n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
}
}
}
// find range of noise values
min = max = 0;
for (y = 0;y < size;y++)
for (x = 0;x < size;x++)
{
if (n(x,y) < min) min = n(x,y);
if (n(x,y) > max) max = n(x,y);
}
max -= min;
max++;
// normalize noise and copy to output
for (y = 0;y < size;y++)
for (x = 0;x < size;x++)
*noise++ = (unsigned char) (((n(x,y) - min) * 256) / max);
Mem_Free(noisebuf);
#undef n
}
// unnormalized, used for explosions mainly, does not allocate/free memory (hence the name quick)
void fractalnoisequick(unsigned char *noise, int size, int startgrid)
{
int x, y, g, g2, amplitude, size1 = size - 1, sizepower, gridpower;
#define n(x,y) noise[((y)&size1)*size+((x)&size1)]
for (sizepower = 0;(1 << sizepower) < size;sizepower++);
if (size != (1 << sizepower))
{
Con_Printf("fractalnoise: size must be power of 2\n");
return;
}
for (gridpower = 0;(1 << gridpower) < startgrid;gridpower++);
if (startgrid != (1 << gridpower))
{
Con_Printf("fractalnoise: grid must be power of 2\n");
return;
}
startgrid = bound(0, startgrid, size);
amplitude = 255; // this gets halved before use
memset(noise, 0, size*size);
for (g2 = startgrid;g2;g2 >>= 1)
{
// brownian motion (at every smaller level there is random behavior)
amplitude >>= 1;
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
n(x,y) += (rand()&amplitude);
g = g2 >> 1;
if (g)
{
// subdivide, diamond-square algorithm (really this has little to do with squares)
// diamond
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
n(x+g,y+g) = (unsigned char) (((int) n(x,y) + (int) n(x+g2,y) + (int) n(x,y+g2) + (int) n(x+g2,y+g2)) >> 2);
// square
for (y = 0;y < size;y += g2)
for (x = 0;x < size;x += g2)
{
n(x+g,y) = (unsigned char) (((int) n(x,y) + (int) n(x+g2,y) + (int) n(x+g,y-g) + (int) n(x+g,y+g)) >> 2);
n(x,y+g) = (unsigned char) (((int) n(x,y) + (int) n(x,y+g2) + (int) n(x-g,y+g) + (int) n(x+g,y+g)) >> 2);
}
}
}
#undef n
}
#define NOISE_SIZE 256
#define NOISE_MASK 255
float noise4f(float x, float y, float z, float w)
{
int i;
int index[4][2];
float frac[4][2];
float v[4];
static float noisetable[NOISE_SIZE];
static int r[NOISE_SIZE];
// LordHavoc: this is inspired by code I saw in Quake3, however I think my
// version is much cleaner and substantially faster as well
//
// the following changes were made:
// 1. for the permutation indexing (r[] array in this code) I substituted
// the ^ operator (which never overflows) for the original addition and
// masking code, this should not have any effect on quality.
// 2. removed the outermost randomization array lookup.
// (it really wasn't necessary, it's fine if X indexes the array
// directly without permutation indexing)
// 3. reimplemented the blending using frac[] arrays rather than a macro.
// (the original macro read one parameter twice - not good)
// 4. cleaned up the code by using 4 nested loops to make it read nicer
// (but then I unrolled it completely for speed, it still looks nicer).
if (!noisetable[0])
{
// noisetable is a random-ish series of float values in +/- 1 range
for (i = 0;i < NOISE_SIZE;i++)
noisetable[i] = (rand() / (double)RAND_MAX) * 2 - 1;
// r is a remapping table to make each dimension of the index have different indexing behavior
for (i = 0;i < NOISE_SIZE;i++)
r[i] = (int)(rand() * (double)NOISE_SIZE / ((double)RAND_MAX + 1)) & NOISE_MASK;
// that & is only needed if RAND_MAX is > the range of double, which isn't the case on most platforms
}
frac[0][1] = x - floor(x);index[0][0] = ((int)floor(x)) & NOISE_MASK;
frac[1][1] = y - floor(y);index[1][0] = ((int)floor(y)) & NOISE_MASK;
frac[2][1] = z - floor(z);index[2][0] = ((int)floor(z)) & NOISE_MASK;
frac[3][1] = w - floor(w);index[3][0] = ((int)floor(w)) & NOISE_MASK;
for (i = 0;i < 4;i++)
frac[i][0] = 1 - frac[i][1];
for (i = 0;i < 4;i++)
index[i][1] = (index[i][0] < NOISE_SIZE - 1) ? (index[i][0] + 1) : 0;
#if 1
// short version
v[0] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]]);
v[1] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]]);
v[2] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]]);
v[3] = frac[1][0] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]]) + frac[1][1] * (frac[0][0] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]] + frac[0][1] * noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]]);
return frac[3][0] * (frac[2][0] * v[0] + frac[2][1] * v[1]) + frac[3][1] * (frac[2][0] * v[2] + frac[2][1] * v[3]);
#elif 1
// longer version
v[ 0] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]];
v[ 1] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]];
v[ 2] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]];
v[ 3] = noisetable[r[r[r[index[3][0]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]];
v[ 4] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]];
v[ 5] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]];
v[ 6] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]];
v[ 7] = noisetable[r[r[r[index[3][0]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]];
v[ 8] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][0]];
v[ 9] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][0]] ^ index[0][1]];
v[10] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][0]];
v[11] = noisetable[r[r[r[index[3][1]] ^ index[2][0]] ^ index[1][1]] ^ index[0][1]];
v[12] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][0]];
v[13] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][0]] ^ index[0][1]];
v[14] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][0]];
v[15] = noisetable[r[r[r[index[3][1]] ^ index[2][1]] ^ index[1][1]] ^ index[0][1]];
v[16] = frac[0][0] * v[ 0] + frac[0][1] * v[ 1];
v[17] = frac[0][0] * v[ 2] + frac[0][1] * v[ 3];
v[18] = frac[0][0] * v[ 4] + frac[0][1] * v[ 5];
v[19] = frac[0][0] * v[ 6] + frac[0][1] * v[ 7];
v[20] = frac[0][0] * v[ 8] + frac[0][1] * v[ 9];
v[21] = frac[0][0] * v[10] + frac[0][1] * v[11];
v[22] = frac[0][0] * v[12] + frac[0][1] * v[13];
v[23] = frac[0][0] * v[14] + frac[0][1] * v[15];
v[24] = frac[1][0] * v[16] + frac[1][1] * v[17];
v[25] = frac[1][0] * v[18] + frac[1][1] * v[19];
v[26] = frac[1][0] * v[20] + frac[1][1] * v[21];
v[27] = frac[1][0] * v[22] + frac[1][1] * v[23];
v[28] = frac[2][0] * v[24] + frac[2][1] * v[25];
v[29] = frac[2][0] * v[26] + frac[2][1] * v[27];
return frac[3][0] * v[28] + frac[3][1] * v[29];
#else
// the algorithm...
for (l = 0;l < 2;l++)
{
for (k = 0;k < 2;k++)
{
for (j = 0;j < 2;j++)
{
for (i = 0;i < 2;i++)
v[l][k][j][i] = noisetable[r[r[r[index[l][3]] ^ index[k][2]] ^ index[j][1]] ^ index[i][0]];
v[l][k][j][2] = frac[0][0] * v[l][k][j][0] + frac[0][1] * v[l][k][j][1];
}
v[l][k][2][2] = frac[1][0] * v[l][k][0][2] + frac[1][1] * v[l][k][1][2];
}
v[l][2][2][2] = frac[2][0] * v[l][0][2][2] + frac[2][1] * v[l][1][2][2];
}
v[2][2][2][2] = frac[3][0] * v[0][2][2][2] + frac[3][1] * v[1][2][2][2];
#endif
}

3995
app/jni/fs.c Normal file

File diff suppressed because it is too large Load diff

144
app/jni/fs.h Normal file
View file

@ -0,0 +1,144 @@
/*
DarkPlaces file system
Copyright (C) 2003-2005 Mathieu Olivier
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef FS_H
#define FS_H
// ------ Types ------ //
typedef struct qfile_s qfile_t;
#ifdef WIN32
//typedef long fs_offset_t; // 32bit
typedef __int64 fs_offset_t; ///< 64bit (lots of warnings, and read/write still don't take 64bit on win64)
#else
typedef long long fs_offset_t;
#endif
// ------ Variables ------ //
extern char fs_gamedir [MAX_OSPATH];
extern char fs_basedir [MAX_OSPATH];
extern char fs_userdir [MAX_OSPATH];
// list of active game directories (empty if not running a mod)
#define MAX_GAMEDIRS 16
extern int fs_numgamedirs;
extern char fs_gamedirs[MAX_GAMEDIRS][MAX_QPATH];
// ------ Main functions ------ //
// IMPORTANT: the file path is automatically prefixed by the current game directory for
// each file created by FS_WriteFile, or opened in "write" or "append" mode by FS_OpenRealFile
qboolean FS_AddPack(const char *pakfile, qboolean *already_loaded, qboolean keep_plain_dirs); // already_loaded may be NULL if caller does not care
const char *FS_WhichPack(const char *filename);
void FS_CreatePath (char *path);
int FS_SysOpenFD(const char *filepath, const char *mode, qboolean nonblocking); // uses absolute path
qfile_t* FS_SysOpen (const char* filepath, const char* mode, qboolean nonblocking); // uses absolute path
qfile_t* FS_OpenRealFile (const char* filepath, const char* mode, qboolean quiet);
qfile_t* FS_OpenVirtualFile (const char* filepath, qboolean quiet);
qfile_t* FS_FileFromData (const unsigned char *data, const size_t size, qboolean quiet);
int FS_Close (qfile_t* file);
void FS_RemoveOnClose(qfile_t* file);
fs_offset_t FS_Write (qfile_t* file, const void* data, size_t datasize);
fs_offset_t FS_Read (qfile_t* file, void* buffer, size_t buffersize);
int FS_Print(qfile_t* file, const char *msg);
int FS_Printf(qfile_t* file, const char* format, ...) DP_FUNC_PRINTF(2);
int FS_VPrintf(qfile_t* file, const char* format, va_list ap);
int FS_Getc (qfile_t* file);
int FS_UnGetc (qfile_t* file, unsigned char c);
int FS_Seek (qfile_t* file, fs_offset_t offset, int whence);
fs_offset_t FS_Tell (qfile_t* file);
fs_offset_t FS_FileSize (qfile_t* file);
void FS_Purge (qfile_t* file);
const char *FS_FileWithoutPath (const char *in);
const char *FS_FileExtension (const char *in);
int FS_CheckNastyPath (const char *path, qboolean isgamedir);
extern const char *const fs_checkgamedir_missing; // "(missing)"
const char *FS_CheckGameDir(const char *gamedir); // returns NULL if nasty, fs_checkgamedir_missing (exact pointer) if missing
typedef struct
{
char name[MAX_OSPATH];
char description[8192];
}
gamedir_t;
extern gamedir_t *fs_all_gamedirs; // terminated by entry with empty name
extern int fs_all_gamedirs_count;
qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean complain, qboolean failmissing);
qboolean FS_IsRegisteredQuakePack(const char *name);
int FS_CRCFile(const char *filename, size_t *filesizepointer);
void FS_Rescan(void);
typedef struct fssearch_s
{
int numfilenames;
char **filenames;
// array of filenames
char *filenamesbuffer;
}
fssearch_t;
fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet);
void FS_FreeSearch(fssearch_t *search);
unsigned char *FS_LoadFile (const char *path, mempool_t *pool, qboolean quiet, fs_offset_t *filesizepointer);
qboolean FS_WriteFileInBlocks (const char *filename, const void *const *data, const fs_offset_t *len, size_t count);
qboolean FS_WriteFile (const char *filename, const void *data, fs_offset_t len);
// ------ Other functions ------ //
void FS_StripExtension (const char *in, char *out, size_t size_out);
void FS_DefaultExtension (char *path, const char *extension, size_t size_path);
#define FS_FILETYPE_NONE 0
#define FS_FILETYPE_FILE 1
#define FS_FILETYPE_DIRECTORY 2
int FS_FileType (const char *filename); // the file can be into a package
int FS_SysFileType (const char *filename); // only look for files outside of packages
qboolean FS_FileExists (const char *filename); // the file can be into a package
qboolean FS_SysFileExists (const char *filename); // only look for files outside of packages
void FS_mkdir (const char *path);
unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflated_size, int level, mempool_t *mempool);
unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflated_size, mempool_t *mempool);
qboolean FS_HasZlib(void);
void FS_Init_SelfPack(void);
void FS_Init(void);
void FS_Shutdown(void);
void FS_Init_Commands(void);
#endif

1593
app/jni/ft2.c Normal file

File diff suppressed because it is too large Load diff

81
app/jni/ft2.h Normal file
View file

@ -0,0 +1,81 @@
/* Header for FreeType 2 and UTF-8 encoding support for
* DarkPlaces
*/
#ifndef DP_FREETYPE2_H__
#define DP_FREETYPE2_H__
//#include <sys/types.h>
#include "utf8lib.h"
/*
* From http://www.unicode.org/Public/UNIDATA/Blocks.txt
*
* E000..F8FF; Private Use Area
* F0000..FFFFF; Supplementary Private Use Area-A
*
* We use:
* Range E000 - E0FF
* Contains the non-FreeType2 version of characters.
*/
typedef struct ft2_font_map_s ft2_font_map_t;
typedef struct ft2_attachment_s ft2_attachment_t;
#define ft2_oldstyle_map ((ft2_font_map_t*)-1)
typedef float ft2_kernvec[2];
typedef struct ft2_kerning_s
{
ft2_kernvec kerning[256][256]; /* kerning[left char][right char] */
} ft2_kerning_t;
typedef struct ft2_font_s
{
char name[64];
qboolean has_kerning;
// last requested size loaded using Font_SetSize
float currentw;
float currenth;
float ascend;
float descend;
qboolean image_font; // only fallbacks are freetype fonts
// TODO: clean this up and do not expose everything.
const unsigned char *data; // FT2 needs it to stay
//fs_offset_t datasize;
void *face;
// an unordered array of ordered linked lists of glyph maps for a specific size
ft2_font_map_t *font_maps[MAX_FONT_SIZES];
int num_sizes;
// attachments
size_t attachmentcount;
ft2_attachment_t *attachments;
ft2_settings_t *settings;
// fallback mechanism
struct ft2_font_s *next;
} ft2_font_t;
void Font_CloseLibrary(void);
void Font_Init(void);
qboolean Font_OpenLibrary(void);
ft2_font_t* Font_Alloc(void);
void Font_UnloadFont(ft2_font_t *font);
// IndexForSize suggests to change the width and height if a font size is in a reasonable range
// for example, you render at a size of 12.4, and a font of size 12 has been loaded
// in such a case, *outw and *outh are set to 12, which is often a good alternative size
int Font_IndexForSize(ft2_font_t *font, float size, float *outw, float *outh);
ft2_font_map_t *Font_MapForIndex(ft2_font_t *font, int index);
qboolean Font_LoadFont(const char *name, dp_font_t *dpfnt);
qboolean Font_GetKerningForSize(ft2_font_t *font, float w, float h, Uchar left, Uchar right, float *outx, float *outy);
qboolean Font_GetKerningForMap(ft2_font_t *font, int map_index, float w, float h, Uchar left, Uchar right, float *outx, float *outy);
float Font_VirtualToRealSize(float sz);
float Font_SnapTo(float val, float snapwidth);
// since this is used on a font_map_t, let's name it FontMap_*
ft2_font_map_t *FontMap_FindForChar(ft2_font_map_t *start, Uchar ch);
#endif // DP_FREETYPE2_H__

500
app/jni/ft2_defs.h Normal file
View file

@ -0,0 +1,500 @@
/* FreeType 2 definitions from the freetype header mostly.
*/
#ifndef FT2_DEFS_H_H__
#define FT2_DEFS_H_H__
#ifdef _MSC_VER
typedef __int32 FT_Int32;
typedef unsigned __int32 FT_UInt32;
#else
# include <stdint.h>
typedef int32_t FT_Int32;
typedef uint32_t FT_UInt32;
#endif
typedef int FT_Error;
typedef signed char FT_Char;
typedef unsigned char FT_Byte;
typedef const FT_Byte *FT_Bytes;
typedef char FT_String;
typedef signed short FT_Short;
typedef unsigned short FT_UShort;
typedef signed int FT_Int;
typedef unsigned int FT_UInt;
typedef signed long FT_Long;
typedef signed long FT_Fixed;
typedef unsigned long FT_ULong;
typedef void *FT_Pointer;
typedef size_t FT_Offset;
typedef signed long FT_F26Dot6;
typedef void *FT_Stream;
typedef void *FT_Module;
typedef void *FT_Library;
typedef struct FT_FaceRec_ *FT_Face;
typedef struct FT_CharMapRec_* FT_CharMap;
typedef struct FT_SizeRec_* FT_Size;
typedef struct FT_Size_InternalRec_* FT_Size_Internal;
typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
typedef struct FT_SubGlyphRec_* FT_SubGlyph;
typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;
// Taken from the freetype headers:
typedef signed long FT_Pos;
typedef struct FT_Vector_
{
FT_Pos x;
FT_Pos y;
} FT_Vector;
typedef struct FT_BBox_
{
FT_Pos xMin, yMin;
FT_Pos xMax, yMax;
} FT_BBox;
typedef enum FT_Pixel_Mode_
{
FT_PIXEL_MODE_NONE = 0,
FT_PIXEL_MODE_MONO,
FT_PIXEL_MODE_GRAY,
FT_PIXEL_MODE_GRAY2,
FT_PIXEL_MODE_GRAY4,
FT_PIXEL_MODE_LCD,
FT_PIXEL_MODE_LCD_V,
FT_PIXEL_MODE_MAX /* do not remove */
} FT_Pixel_Mode;
typedef enum FT_Render_Mode_
{
FT_RENDER_MODE_NORMAL = 0,
FT_RENDER_MODE_LIGHT,
FT_RENDER_MODE_MONO,
FT_RENDER_MODE_LCD,
FT_RENDER_MODE_LCD_V,
FT_RENDER_MODE_MAX
} FT_Render_Mode;
#define ft_pixel_mode_none FT_PIXEL_MODE_NONE
#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO
#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY
#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2
#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4
typedef struct FT_Bitmap_
{
int rows;
int width;
int pitch;
unsigned char* buffer;
short num_grays;
char pixel_mode;
char palette_mode;
void* palette;
} FT_Bitmap;
typedef struct FT_Outline_
{
short n_contours; /* number of contours in glyph */
short n_points; /* number of points in the glyph */
FT_Vector* points; /* the outline's points */
char* tags; /* the points flags */
short* contours; /* the contour end points */
int flags; /* outline masks */
} FT_Outline;
#define FT_OUTLINE_NONE 0x0
#define FT_OUTLINE_OWNER 0x1
#define FT_OUTLINE_EVEN_ODD_FILL 0x2
#define FT_OUTLINE_REVERSE_FILL 0x4
#define FT_OUTLINE_IGNORE_DROPOUTS 0x8
#define FT_OUTLINE_SMART_DROPOUTS 0x10
#define FT_OUTLINE_INCLUDE_STUBS 0x20
#define FT_OUTLINE_HIGH_PRECISION 0x100
#define FT_OUTLINE_SINGLE_PASS 0x200
#define ft_outline_none FT_OUTLINE_NONE
#define ft_outline_owner FT_OUTLINE_OWNER
#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL
#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL
#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS
#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION
#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS
#define FT_CURVE_TAG( flag ) ( flag & 3 )
#define FT_CURVE_TAG_ON 1
#define FT_CURVE_TAG_CONIC 0
#define FT_CURVE_TAG_CUBIC 2
#define FT_CURVE_TAG_TOUCH_X 8 /* reserved for the TrueType hinter */
#define FT_CURVE_TAG_TOUCH_Y 16 /* reserved for the TrueType hinter */
#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \
FT_CURVE_TAG_TOUCH_Y )
#define FT_Curve_Tag_On FT_CURVE_TAG_ON
#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC
#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC
#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X
#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y
typedef int
(*FT_Outline_MoveToFunc)( const FT_Vector* to,
void* user );
#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc
typedef int
(*FT_Outline_LineToFunc)( const FT_Vector* to,
void* user );
#define FT_Outline_LineTo_Func FT_Outline_LineToFunc
typedef int
(*FT_Outline_ConicToFunc)( const FT_Vector* control,
const FT_Vector* to,
void* user );
#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc
typedef int
(*FT_Outline_CubicToFunc)( const FT_Vector* control1,
const FT_Vector* control2,
const FT_Vector* to,
void* user );
#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc
typedef struct FT_Outline_Funcs_
{
FT_Outline_MoveToFunc move_to;
FT_Outline_LineToFunc line_to;
FT_Outline_ConicToFunc conic_to;
FT_Outline_CubicToFunc cubic_to;
int shift;
FT_Pos delta;
} FT_Outline_Funcs;
#ifndef FT_IMAGE_TAG
#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \
value = ( ( (unsigned long)_x1 << 24 ) | \
( (unsigned long)_x2 << 16 ) | \
( (unsigned long)_x3 << 8 ) | \
(unsigned long)_x4 )
#endif /* FT_IMAGE_TAG */
typedef enum FT_Glyph_Format_
{
FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' )
} FT_Glyph_Format;
#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE
#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE
#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE
#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER
typedef struct FT_Glyph_Metrics_
{
FT_Pos width;
FT_Pos height;
FT_Pos horiBearingX;
FT_Pos horiBearingY;
FT_Pos horiAdvance;
FT_Pos vertBearingX;
FT_Pos vertBearingY;
FT_Pos vertAdvance;
} FT_Glyph_Metrics;
#define FT_EXPORT( x ) x
#define FT_OPEN_MEMORY 0x1
#define FT_OPEN_STREAM 0x2
#define FT_OPEN_PATHNAME 0x4
#define FT_OPEN_DRIVER 0x8
#define FT_OPEN_PARAMS 0x10
typedef struct FT_Parameter_
{
FT_ULong tag;
FT_Pointer data;
} FT_Parameter;
typedef struct FT_Open_Args_
{
FT_UInt flags;
const FT_Byte* memory_base;
FT_Long memory_size;
FT_String* pathname;
FT_Stream stream;
FT_Module driver;
FT_Int num_params;
FT_Parameter* params;
} FT_Open_Args;
typedef enum FT_Size_Request_Type_
{
FT_SIZE_REQUEST_TYPE_NOMINAL,
FT_SIZE_REQUEST_TYPE_REAL_DIM,
FT_SIZE_REQUEST_TYPE_BBOX,
FT_SIZE_REQUEST_TYPE_CELL,
FT_SIZE_REQUEST_TYPE_SCALES,
FT_SIZE_REQUEST_TYPE_MAX
} FT_Size_Request_Type;
typedef struct FT_Size_RequestRec_
{
FT_Size_Request_Type type;
FT_Long width;
FT_Long height;
FT_UInt horiResolution;
FT_UInt vertResolution;
} FT_Size_RequestRec;
typedef struct FT_Size_RequestRec_ *FT_Size_Request;
#define FT_LOAD_DEFAULT 0x0
#define FT_LOAD_NO_SCALE 0x1
#define FT_LOAD_NO_HINTING 0x2
#define FT_LOAD_RENDER 0x4
#define FT_LOAD_NO_BITMAP 0x8
#define FT_LOAD_VERTICAL_LAYOUT 0x10
#define FT_LOAD_FORCE_AUTOHINT 0x20
#define FT_LOAD_CROP_BITMAP 0x40
#define FT_LOAD_PEDANTIC 0x80
#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 0x200
#define FT_LOAD_NO_RECURSE 0x400
#define FT_LOAD_IGNORE_TRANSFORM 0x800
#define FT_LOAD_MONOCHROME 0x1000
#define FT_LOAD_LINEAR_DESIGN 0x2000
#define FT_LOAD_NO_AUTOHINT 0x8000U
#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 )
#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT )
#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO )
#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD )
#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V )
#define FT_ENC_TAG( value, a, b, c, d ) \
value = ( ( (FT_UInt32)(a) << 24 ) | \
( (FT_UInt32)(b) << 16 ) | \
( (FT_UInt32)(c) << 8 ) | \
(FT_UInt32)(d) )
typedef enum FT_Encoding_
{
FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),
FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ),
FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ),
FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ),
FT_ENC_TAG( FT_ENCODING_GB2312, 'g', 'b', ' ', ' ' ),
FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ),
FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ),
FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ),
/* for backwards compatibility */
FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS,
FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312,
FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5,
FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG,
FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB,
FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ),
FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ),
FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ),
FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ),
FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ),
FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' )
} FT_Encoding;
#define ft_encoding_none FT_ENCODING_NONE
#define ft_encoding_unicode FT_ENCODING_UNICODE
#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL
#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1
#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2
#define ft_encoding_sjis FT_ENCODING_SJIS
#define ft_encoding_gb2312 FT_ENCODING_GB2312
#define ft_encoding_big5 FT_ENCODING_BIG5
#define ft_encoding_wansung FT_ENCODING_WANSUNG
#define ft_encoding_johab FT_ENCODING_JOHAB
#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD
#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT
#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM
#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN
typedef struct FT_Bitmap_Size_
{
FT_Short height;
FT_Short width;
FT_Pos size;
FT_Pos x_ppem;
FT_Pos y_ppem;
} FT_Bitmap_Size;
typedef struct FT_CharMapRec_
{
FT_Face face;
FT_Encoding encoding;
FT_UShort platform_id;
FT_UShort encoding_id;
} FT_CharMapRec;
typedef void (*FT_Generic_Finalizer)(void* object);
typedef struct FT_Generic_
{
void* data;
FT_Generic_Finalizer finalizer;
} FT_Generic;
typedef struct FT_Size_Metrics_
{
FT_UShort x_ppem; /* horizontal pixels per EM */
FT_UShort y_ppem; /* vertical pixels per EM */
FT_Fixed x_scale; /* scaling values used to convert font */
FT_Fixed y_scale; /* units to 26.6 fractional pixels */
FT_Pos ascender; /* ascender in 26.6 frac. pixels */
FT_Pos descender; /* descender in 26.6 frac. pixels */
FT_Pos height; /* text height in 26.6 frac. pixels */
FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */
} FT_Size_Metrics;
typedef struct FT_SizeRec_
{
FT_Face face; /* parent face object */
FT_Generic generic; /* generic pointer for client uses */
FT_Size_Metrics metrics; /* size metrics */
FT_Size_Internal internal;
} FT_SizeRec;
typedef struct FT_FaceRec_
{
FT_Long num_faces;
FT_Long face_index;
FT_Long face_flags;
FT_Long style_flags;
FT_Long num_glyphs;
FT_String* family_name;
FT_String* style_name;
FT_Int num_fixed_sizes;
FT_Bitmap_Size* available_sizes;
FT_Int num_charmaps;
FT_CharMap* charmaps;
FT_Generic generic;
/*# The following member variables (down to `underline_thickness') */
/*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
/*# for bitmap fonts. */
FT_BBox bbox;
FT_UShort units_per_EM;
FT_Short ascender;
FT_Short descender;
FT_Short height;
FT_Short max_advance_width;
FT_Short max_advance_height;
FT_Short underline_position;
FT_Short underline_thickness;
FT_GlyphSlot glyph;
FT_Size size;
FT_CharMap charmap;
/* ft2 private
FT_Driver driver;
FT_Memory memory;
FT_Stream stream;
FT_ListRec sizes_list;
FT_Generic autohint;
void* extensions;
FT_Face_Internal internal;
*/
} FT_FaceRec;
typedef struct FT_GlyphSlotRec_
{
FT_Library library;
FT_Face face;
FT_GlyphSlot next;
FT_UInt reserved; /* retained for binary compatibility */
FT_Generic generic;
FT_Glyph_Metrics metrics;
FT_Fixed linearHoriAdvance;
FT_Fixed linearVertAdvance;
FT_Vector advance;
FT_Glyph_Format format;
FT_Bitmap bitmap;
FT_Int bitmap_left;
FT_Int bitmap_top;
FT_Outline outline;
FT_UInt num_subglyphs;
FT_SubGlyph subglyphs;
void* control_data;
long control_len;
FT_Pos lsb_delta;
FT_Pos rsb_delta;
void* other;
FT_Slot_Internal internal;
} FT_GlyphSlotRec;
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
#define FT_FACE_FLAG_SFNT ( 1L << 3 )
#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 )
#define FT_FACE_FLAG_VERTICAL ( 1L << 5 )
#define FT_FACE_FLAG_KERNING ( 1L << 6 )
#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 )
#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 )
#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 )
#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 )
#define FT_FACE_FLAG_HINTER ( 1L << 11 )
#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )
#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
typedef enum FT_Kerning_Mode_
{
FT_KERNING_DEFAULT = 0,
FT_KERNING_UNFITTED,
FT_KERNING_UNSCALED
} FT_Kerning_Mode;
#endif // FT2_DEFS_H_H__

64
app/jni/ft2_fontdefs.h Normal file
View file

@ -0,0 +1,64 @@
#ifndef FT2_PRIVATE_H__
#define FT2_PRIVATE_H__
// anything should work, but I recommend multiples of 8
// since the texture size should be a power of 2
#define FONT_CHARS_PER_LINE 16
#define FONT_CHAR_LINES 16
#define FONT_CHARS_PER_MAP (FONT_CHARS_PER_LINE * FONT_CHAR_LINES)
typedef struct glyph_slot_s
{
qboolean image;
// we keep the quad coords here only currently
// if you need other info, make Font_LoadMapForIndex fill it into this slot
float txmin; // texture coordinate in [0,1]
float txmax;
float tymin;
float tymax;
float vxmin;
float vxmax;
float vymin;
float vymax;
float advance_x;
float advance_y;
} glyph_slot_t;
struct ft2_font_map_s
{
Uchar start;
struct ft2_font_map_s *next;
float size;
// the actual size used in the freetype code
// by convention, the requested size is the height of the font's bounding box.
float intSize;
int glyphSize;
cachepic_t *pic;
qboolean static_tex;
glyph_slot_t glyphs[FONT_CHARS_PER_MAP];
// contains the kerning information for the first 256 characters
// for the other characters, we will lookup the kerning information
ft2_kerning_t kerning;
// safes us the trouble of calculating these over and over again
double sfx, sfy;
// the width_of for the image-font, pixel-snapped for this size
float width_of[256];
};
struct ft2_attachment_s
{
const unsigned char *data;
fs_offset_t size;
};
//qboolean Font_LoadMapForIndex(ft2_font_t *font, Uchar _ch, ft2_font_map_t **outmap);
qboolean Font_LoadMapForIndex(ft2_font_t *font, int map_index, Uchar _ch, ft2_font_map_t **outmap);
void font_start(void);
void font_shutdown(void);
void font_newmap(void);
#endif // FT2_PRIVATE_H__

4867
app/jni/gl_backend.c Normal file

File diff suppressed because it is too large Load diff

127
app/jni/gl_backend.h Normal file
View file

@ -0,0 +1,127 @@
#ifndef GL_BACKEND_H
#define GL_BACKEND_H
extern r_viewport_t gl_viewport;
extern matrix4x4_t gl_modelmatrix;
extern matrix4x4_t gl_viewmatrix;
extern matrix4x4_t gl_modelviewmatrix;
extern matrix4x4_t gl_projectionmatrix;
extern matrix4x4_t gl_modelviewprojectionmatrix;
extern float gl_modelview16f[16];
extern float gl_modelviewprojection16f[16];
extern qboolean gl_modelmatrixchanged;
extern cvar_t gl_vbo_dynamicvertex;
extern cvar_t gl_vbo_dynamicindex;
#define POLYGONELEMENTS_MAXPOINTS 258
extern int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
extern unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
#define QUADELEMENTS_MAXQUADS 128
extern int quadelement3i[QUADELEMENTS_MAXQUADS*6];
extern unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out);
qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor);
void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float zNear, float zFar, const float *nearplane);
void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, float zFar, const float *nearplane);
void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float zNear, const float *nearplane);
void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane);
void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane);
void R_SetViewport(const r_viewport_t *v);
void R_GetViewport(r_viewport_t *v);
void GL_Finish(void);
void GL_BlendFunc(int blendfunc1, int blendfunc2);
void GL_BlendEquationSubtract(qboolean negated);
void GL_DepthMask(int state);
void GL_DepthTest(int state);
void GL_DepthFunc(int state);
void GL_DepthRange(float nearfrac, float farfrac);
void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int frontzfail, int frontzpass, int backfail, int backzfail, int backzpass, int frontcompare, int backcompare, int comparereference, int comparemask);
void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask);
void GL_PolygonOffset(float planeoffset, float depthoffset);
void GL_CullFace(int state);
void GL_AlphaTest(int state);
void GL_AlphaToCoverage(qboolean state);
void GL_ColorMask(int r, int g, int b, int a);
void GL_Color(float cr, float cg, float cb, float ca);
void GL_ActiveTexture(unsigned int num);
void GL_ClientActiveTexture(unsigned int num);
void GL_Scissor(int x, int y, int width, int height);
void GL_ScissorTest(int state);
void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue);
void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels);
int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4);
void R_Mesh_DestroyFramebufferObject(int fbo);
void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4);
unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list);
void GL_Backend_FreeProgram(unsigned int prog);
extern cvar_t gl_paranoid;
extern cvar_t gl_printcheckerror;
// adds console variables and registers the render module (only call from GL_Init)
void gl_backend_init(void);
// starts mesh rendering for the frame
void R_Mesh_Start(void);
// ends mesh rendering for the frame
// (only valid after R_Mesh_Start)
void R_Mesh_Finish(void);
// vertex buffer and index buffer creation/updating/freeing
r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isuniformbuffer, qboolean isdynamic, qboolean isindex16);
void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qboolean subdata, size_t offset);
void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer);
void GL_Mesh_ListVBOs(qboolean printeach);
void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *buffer, int bufferoffset);
r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices);
qboolean R_Mesh_PrepareVertices_Generic_Unlock(void);
void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f);
void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset);
r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices);
qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void); // if this returns false, you need to prepare the mesh again!
void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *color4f, const float *texcoordtexture2f, const float *texcoordlightmap2f);
void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *buffer, int bufferoffset);
// sets up the requested vertex transform matrix
void R_EntityMatrix(const matrix4x4_t *matrix);
// sets the vertex array pointer
void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
// sets the color array pointer (GL_Color only works when this is NULL)
void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
// sets the texcoord array pointer for an array unit, if GL_UNSIGNED_BYTE | 0x80000000 is specified it will be an unnormalized type (integer values)
void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset);
// returns current texture bound to this identifier
int R_Mesh_TexBound(unsigned int unitnum, int id);
// copies a section of the framebuffer to a 2D texture
void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height);
// bind a given texture to a given image unit
void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex);
// sets the texcoord matrix for a texenv unit, can be NULL or blank (will use identity)
void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix);
// sets the combine state for a texenv unit
void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale);
// set up a blank texture state (unbinds all textures, texcoord pointers, and resets combine settings)
void R_Mesh_ResetTextureState(void);
// before a texture is freed, make sure there are no references to it
void R_Mesh_ClearBindingsForTexture(int texnum);
// renders a mesh
void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset);
// saves a section of the rendered frame to a .tga or .jpg file
qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *buffer2, int x, int y, int width, int height, qboolean flipx, qboolean flipy, qboolean flipdiagonal, qboolean jpeg, qboolean png, qboolean gammacorrect, qboolean keep_alpha);
// used by R_Envmap_f and internally in backend, clears the frame
void R_ClearScreen(qboolean fogcolor);
#endif

2268
app/jni/gl_draw.c Normal file

File diff suppressed because it is too large Load diff

12691
app/jni/gl_rmain.c Normal file

File diff suppressed because it is too large Load diff

1645
app/jni/gl_rsurf.c Normal file

File diff suppressed because it is too large Load diff

2983
app/jni/gl_textures.c Normal file

File diff suppressed because it is too large Load diff

1347
app/jni/glquake.h Normal file

File diff suppressed because it is too large Load diff

61
app/jni/hmac.c Normal file
View file

@ -0,0 +1,61 @@
#include "quakedef.h"
#include "hmac.h"
qboolean hmac(
hashfunc_t hfunc, int hlen, int hblock,
unsigned char *out,
const unsigned char *in, int n,
const unsigned char *key, int k
)
{
unsigned char hashbuf[32];
unsigned char k_xor_ipad[128];
unsigned char k_xor_opad[128];
unsigned char *catbuf;
int i;
if(sizeof(hashbuf) < (size_t) hlen)
return false;
if(sizeof(k_xor_ipad) < (size_t) hblock)
return false;
if(sizeof(k_xor_ipad) < (size_t) hlen)
return false;
catbuf = (unsigned char *)Mem_Alloc(tempmempool, (size_t) hblock + max((size_t) hlen, (size_t) n));
if(k > hblock)
{
// hash the key if it is too long
hfunc(k_xor_opad, key, k);
key = k_xor_opad;
k = hlen;
}
if(k < hblock)
{
// zero pad the key if it is too short
if(key != k_xor_opad)
memcpy(k_xor_opad, key, k);
for(i = k; i < hblock; ++i)
k_xor_opad[i] = 0;
key = k_xor_opad;
k = hblock;
}
for(i = 0; i < hblock; ++i)
{
k_xor_ipad[i] = key[i] ^ 0x36;
k_xor_opad[i] = key[i] ^ 0x5c;
}
memcpy(catbuf, k_xor_ipad, hblock);
memcpy(catbuf + hblock, in, n);
hfunc(hashbuf, catbuf, hblock + n);
memcpy(catbuf, k_xor_opad, hblock);
memcpy(catbuf + hblock, hashbuf, hlen);
hfunc(out, catbuf, hblock + hlen);
Mem_Free(catbuf);
return true;
}

15
app/jni/hmac.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef HMAC_H
#define HMAC_H
typedef void (*hashfunc_t) (unsigned char *out, const unsigned char *in, int n);
qboolean hmac(
hashfunc_t hfunc, int hlen, int hblock,
unsigned char *out,
const unsigned char *in, int n,
const unsigned char *key, int k
);
#define HMAC_MDFOUR_16BYTES(out, in, n, key, k) hmac(mdfour, 16, 64, out, in, n, key, k)
#define HMAC_SHA256_32BYTES(out, in, n, key, k) hmac(sha256, 32, 64, out, in, n, key, k)
#endif

1460
app/jni/host.c Normal file

File diff suppressed because it is too large Load diff

3051
app/jni/host_cmd.c Normal file

File diff suppressed because it is too large Load diff

1588
app/jni/image.c Normal file

File diff suppressed because it is too large Load diff

62
app/jni/image.h Normal file
View file

@ -0,0 +1,62 @@
#ifndef IMAGE_H
#define IMAGE_H
extern int image_width, image_height;
// swizzle components (even converting number of components) and flip images
// (warning: input must be different than output due to non-linear read/write)
// (tip: component indices can contain values | 0x80000000 to tell it to
// store them directly into output, so 255 | 0x80000000 would write 255)
void Image_CopyMux(unsigned char *outpixels, const unsigned char *inpixels, int inputwidth, int inputheight, qboolean inputflipx, qboolean inputflipy, qboolean inputflipdiagonal, int numoutputcomponents, int numinputcomponents, int *outputinputcomponentindices);
// applies gamma correction to RGB pixels, in can be the same as out
void Image_GammaRemapRGB(const unsigned char *in, unsigned char *out, int pixels, const unsigned char *gammar, const unsigned char *gammag, const unsigned char *gammab);
// converts 8bit image data to BGRA, in can not be the same as out
void Image_Copy8bitBGRA(const unsigned char *in, unsigned char *out, int pixels, const unsigned int *pal);
void Image_StripImageExtension (const char *in, char *out, size_t size_out);
// called by conchars.tga loader in gl_draw.c, otherwise private
unsigned char *LoadTGA_BGRA (const unsigned char *f, int filesize, int *miplevel);
// loads a texture, as pixel data
unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qboolean allowFixtrans, qboolean convertsRGB, int *miplevel);
// loads an 8bit pcx image into a 296x194x8bit buffer, with cropping as needed
qboolean LoadPCX_QWSkin(const unsigned char *f, int filesize, unsigned char *pixels, int outwidth, int outheight);
// loads a texture, as a texture
rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qboolean complain, int flags, qboolean allowFixtrans, qboolean sRGB);
// writes an upside down BGR image into a TGA
qboolean Image_WriteTGABGR_preflipped (const char *filename, int width, int height, const unsigned char *data);
// writes a BGRA image into a TGA file
qboolean Image_WriteTGABGRA (const char *filename, int width, int height, const unsigned char *data);
// resizes the image (in can not be the same as out)
void Image_Resample32(const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int quality);
// scales the image down by a power of 2 (in can be the same as out)
void Image_MipReduce32(const unsigned char *in, unsigned char *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth);
void Image_HeightmapToNormalmap_BGRA(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale);
// console command to fix the colors of transparent pixels (to prevent weird borders)
void Image_FixTransparentPixels_f(void);
extern cvar_t r_fixtrans_auto;
#define Image_LinearFloatFromsRGBFloat(c) (((c) <= 0.04045f) ? (c) * (1.0f / 12.92f) : (float)pow(((c) + 0.055f)*(1.0f/1.055f), 2.4f))
#define Image_sRGBFloatFromLinearFloat(c) (((c) < 0.0031308f) ? (c) * 12.92f : 1.055f * (float)pow((c), 1.0f/2.4f) - 0.055f)
#define Image_LinearFloatFromsRGB(c) Image_LinearFloatFromsRGBFloat((c) * (1.0f / 255.0f))
#define Image_sRGBFloatFromLinear(c) Image_sRGBFloatFromLinearFloat((c) * (1.0f / 255.0f))
#define Image_sRGBFloatFromLinear_Lightmap(c) Image_sRGBFloatFromLinearFloat((c) * (2.0f / 255.0f)) * 0.5f
void Image_MakeLinearColorsFromsRGB(unsigned char *pout, const unsigned char *pin, int numpixels);
void Image_MakesRGBColorsFromLinear_Lightmap(unsigned char *pout, const unsigned char *pin, int numpixels);
#endif

559
app/jni/image_png.c Normal file
View file

@ -0,0 +1,559 @@
/*
Copyright (C) 2006 Serge "(515)" Ziryukin, Forest "LordHavoc" Hale
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
//[515]: png implemented into DP ONLY FOR TESTING 2d stuff with csqc
// so delete this bullshit :D
//
//LordHavoc: rewrote most of this.
#include "quakedef.h"
#include "image.h"
#include "image_png.h"
static void (*qpng_set_sig_bytes) (void*, int);
static int (*qpng_sig_cmp) (const unsigned char*, size_t, size_t);
static void* (*qpng_create_read_struct) (const char*, void*, void(*)(void *png, const char *message), void(*)(void *png, const char *message));
static void* (*qpng_create_write_struct) (const char*, void*, void(*)(void *png, const char *message), void(*)(void *png, const char *message));
static void* (*qpng_create_info_struct) (void*);
static void (*qpng_read_info) (void*, void*);
static void (*qpng_set_compression_level) (void*, int);
static void (*qpng_set_filter) (void*, int, int);
static void (*qpng_set_expand) (void*);
static void (*qpng_set_palette_to_rgb) (void*);
static void (*qpng_set_tRNS_to_alpha) (void*);
static void (*qpng_set_gray_to_rgb) (void*);
static void (*qpng_set_filler) (void*, unsigned int, int);
static void (*qpng_set_IHDR) (void*, void*, unsigned long, unsigned long, int, int, int, int, int);
static void (*qpng_set_packing) (void*);
static void (*qpng_set_bgr) (void*);
static int (*qpng_set_interlace_handling) (void*);
static void (*qpng_read_update_info) (void*, void*);
static void (*qpng_read_image) (void*, unsigned char**);
static void (*qpng_read_end) (void*, void*);
static void (*qpng_destroy_read_struct) (void**, void**, void**);
static void (*qpng_destroy_write_struct) (void**, void**);
static void (*qpng_set_read_fn) (void*, void*, void(*)(void *png, unsigned char *data, size_t length));
static void (*qpng_set_write_fn) (void*, void*, void(*)(void *png, unsigned char *data, size_t length), void(*)(void *png));
static unsigned int (*qpng_get_valid) (void*, void*, unsigned int);
static unsigned int (*qpng_get_rowbytes) (void*, void*);
static unsigned char (*qpng_get_channels) (void*, void*);
static unsigned char (*qpng_get_bit_depth) (void*, void*);
static unsigned int (*qpng_get_IHDR) (void*, void*, unsigned long*, unsigned long*, int *, int *, int *, int *, int *);
static unsigned int (*qpng_access_version_number) (void); // FIXME is this return type right? It is a png_uint_32 in libpng
static void (*qpng_write_info) (void*, void*);
static void (*qpng_write_row) (void*, unsigned char*);
static void (*qpng_write_end) (void*, void*);
// libpng 1.4+ longjmp hack
typedef void (*qpng_longjmp_ptr) (jmp_buf, int);
static jmp_buf* (*qpng_set_longjmp_fn) (void *, qpng_longjmp_ptr, size_t);
#define qpng_jmpbuf_14(png_ptr) (*qpng_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf)))
// libpng 1.2 longjmp hack
#define qpng_jmpbuf_12(png_ptr) (*((jmp_buf *) png_ptr))
// all version support
#define qpng_jmpbuf(png_ptr) \
(qpng_set_longjmp_fn ? qpng_jmpbuf_14(png_ptr) : qpng_jmpbuf_12(png_ptr))
static dllfunction_t pngfuncs[] =
{
{"png_set_sig_bytes", (void **) &qpng_set_sig_bytes},
{"png_sig_cmp", (void **) &qpng_sig_cmp},
{"png_create_read_struct", (void **) &qpng_create_read_struct},
{"png_create_write_struct", (void **) &qpng_create_write_struct},
{"png_create_info_struct", (void **) &qpng_create_info_struct},
{"png_read_info", (void **) &qpng_read_info},
{"png_set_compression_level", (void **) &qpng_set_compression_level},
{"png_set_filter", (void **) &qpng_set_filter},
{"png_set_expand", (void **) &qpng_set_expand},
{"png_set_palette_to_rgb", (void **) &qpng_set_palette_to_rgb},
{"png_set_tRNS_to_alpha", (void **) &qpng_set_tRNS_to_alpha},
{"png_set_gray_to_rgb", (void **) &qpng_set_gray_to_rgb},
{"png_set_filler", (void **) &qpng_set_filler},
{"png_set_IHDR", (void **) &qpng_set_IHDR},
{"png_set_packing", (void **) &qpng_set_packing},
{"png_set_bgr", (void **) &qpng_set_bgr},
{"png_set_interlace_handling", (void **) &qpng_set_interlace_handling},
{"png_read_update_info", (void **) &qpng_read_update_info},
{"png_read_image", (void **) &qpng_read_image},
{"png_read_end", (void **) &qpng_read_end},
{"png_destroy_read_struct", (void **) &qpng_destroy_read_struct},
{"png_destroy_write_struct", (void **) &qpng_destroy_write_struct},
{"png_set_read_fn", (void **) &qpng_set_read_fn},
{"png_set_write_fn", (void **) &qpng_set_write_fn},
{"png_get_valid", (void **) &qpng_get_valid},
{"png_get_rowbytes", (void **) &qpng_get_rowbytes},
{"png_get_channels", (void **) &qpng_get_channels},
{"png_get_bit_depth", (void **) &qpng_get_bit_depth},
{"png_get_IHDR", (void **) &qpng_get_IHDR},
{"png_access_version_number", (void **) &qpng_access_version_number},
{"png_write_info", (void **) &qpng_write_info},
{"png_write_row", (void **) &qpng_write_row},
{"png_write_end", (void **) &qpng_write_end},
{NULL, NULL}
};
static dllfunction_t png14funcs[] =
{
{"png_set_longjmp_fn", (void **) &qpng_set_longjmp_fn},
{NULL, NULL}
};
// Handle for PNG DLL
dllhandle_t png_dll = NULL;
dllhandle_t png14_dll = NULL;
/*
=================================================================
DLL load & unload
=================================================================
*/
/*
====================
PNG_OpenLibrary
Try to load the PNG DLL
====================
*/
qboolean PNG_OpenLibrary (void)
{
const char* dllnames [] =
{
#if WIN32
"libpng16.dll",
"libpng16-16.dll",
"libpng15-15.dll",
"libpng15.dll",
"libpng14-14.dll",
"libpng14.dll",
"libpng12.dll",
#elif defined(MACOSX)
"libpng16.16.dylib",
"libpng15.15.dylib",
"libpng14.14.dylib",
"libpng12.0.dylib",
#else
"libpng16.so.16",
"libpng15.so.15", // WTF libtool guidelines anyone?
"libpng14.so.14", // WTF libtool guidelines anyone?
"libpng12.so.0",
"libpng.so", // FreeBSD
#endif
NULL
};
// Already loaded?
if (png_dll)
return true;
// Load the DLL
if(!Sys_LoadLibrary (dllnames, &png_dll, pngfuncs))
return false;
if(qpng_access_version_number() / 100 >= 104)
if(!Sys_LoadLibrary (dllnames, &png14_dll, png14funcs))
{
Sys_UnloadLibrary (&png_dll);
return false;
}
return true;
}
/*
====================
PNG_CloseLibrary
Unload the PNG DLL
====================
*/
void PNG_CloseLibrary (void)
{
Sys_UnloadLibrary (&png14_dll);
Sys_UnloadLibrary (&png_dll);
}
/*
=================================================================
PNG decompression
=================================================================
*/
#define PNG_LIBPNG_VER_STRING_12 "1.2.4"
#define PNG_LIBPNG_VER_STRING_14 "1.4.0"
#define PNG_LIBPNG_VER_STRING_15 "1.5.0"
#define PNG_LIBPNG_VER_STRING_16 "1.6.0"
#define PNG_COLOR_MASK_PALETTE 1
#define PNG_COLOR_MASK_COLOR 2
#define PNG_COLOR_MASK_ALPHA 4
#define PNG_COLOR_TYPE_GRAY 0
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA
#define PNG_INFO_tRNS 0x0010
// this struct is only used for status information during loading
static struct
{
const unsigned char *tmpBuf;
int tmpBuflength;
int tmpi;
//int FBgColor;
//int FTransparent;
unsigned int FRowBytes;
//double FGamma;
//double FScreenGamma;
unsigned char **FRowPtrs;
unsigned char *Data;
//char *Title;
//char *Author;
//char *Description;
int BitDepth;
int BytesPerPixel;
int ColorType;
unsigned long Height; // retarded libpng 1.2 pngconf.h uses long (64bit/32bit depending on arch)
unsigned long Width; // retarded libpng 1.2 pngconf.h uses long (64bit/32bit depending on arch)
int Interlace;
int Compression;
int Filter;
//double LastModified;
//int Transparent;
qfile_t *outfile;
} my_png;
//LordHavoc: removed __cdecl prefix, added overrun protection, and rewrote this to be more efficient
static void PNG_fReadData(void *png, unsigned char *data, size_t length)
{
size_t l;
l = my_png.tmpBuflength - my_png.tmpi;
if (l < length)
{
Con_Printf("PNG_fReadData: overrun by %i bytes\n", (int)(length - l));
// a read going past the end of the file, fill in the remaining bytes
// with 0 just to be consistent
memset(data + l, 0, length - l);
length = l;
}
memcpy(data, my_png.tmpBuf + my_png.tmpi, length);
my_png.tmpi += (int)length;
//Com_HexDumpToConsole(data, (int)length);
}
static void PNG_fWriteData(void *png, unsigned char *data, size_t length)
{
FS_Write(my_png.outfile, data, length);
}
static void PNG_fFlushData(void *png)
{
}
static void PNG_error_fn(void *png, const char *message)
{
Con_Printf("PNG_LoadImage: error: %s\n", message);
}
static void PNG_warning_fn(void *png, const char *message)
{
Con_Printf("PNG_LoadImage: warning: %s\n", message);
}
unsigned char *PNG_LoadImage_BGRA (const unsigned char *raw, int filesize, int *miplevel)
{
unsigned int c;
unsigned int y;
void *png, *pnginfo;
unsigned char *imagedata = NULL;
unsigned char ioBuffer[8192];
// FIXME: register an error handler so that abort() won't be called on error
// No DLL = no PNGs
if (!png_dll)
return NULL;
if(qpng_sig_cmp(raw, 0, filesize))
return NULL;
png = (void *)qpng_create_read_struct(
(qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 :
(qpng_access_version_number() / 100 == 104) ? PNG_LIBPNG_VER_STRING_14 :
(qpng_access_version_number() / 100 == 105) ? PNG_LIBPNG_VER_STRING_15 :
PNG_LIBPNG_VER_STRING_16, // nasty hack... whatever
0, PNG_error_fn, PNG_warning_fn
);
if(!png)
return NULL;
// this must be memset before the setjmp error handler, because it relies
// on the fields in this struct for cleanup
memset(&my_png, 0, sizeof(my_png));
// NOTE: this relies on jmp_buf being the first thing in the png structure
// created by libpng! (this is correct for libpng 1.2.x)
if (setjmp(qpng_jmpbuf(png)))
{
if (my_png.Data)
Mem_Free(my_png.Data);
my_png.Data = NULL;
if (my_png.FRowPtrs)
Mem_Free(my_png.FRowPtrs);
my_png.FRowPtrs = NULL;
qpng_destroy_read_struct(&png, &pnginfo, 0);
return NULL;
}
//
pnginfo = qpng_create_info_struct(png);
if(!pnginfo)
{
qpng_destroy_read_struct(&png, &pnginfo, 0);
return NULL;
}
qpng_set_sig_bytes(png, 0);
my_png.tmpBuf = raw;
my_png.tmpBuflength = filesize;
my_png.tmpi = 0;
//my_png.Data = NULL;
//my_png.FRowPtrs = NULL;
//my_png.Height = 0;
//my_png.Width = 0;
my_png.ColorType = PNG_COLOR_TYPE_RGB;
//my_png.Interlace = 0;
//my_png.Compression = 0;
//my_png.Filter = 0;
qpng_set_read_fn(png, ioBuffer, PNG_fReadData);
qpng_read_info(png, pnginfo);
qpng_get_IHDR(png, pnginfo, &my_png.Width, &my_png.Height,&my_png.BitDepth, &my_png.ColorType, &my_png.Interlace, &my_png.Compression, &my_png.Filter);
// this check guards against pngconf.h with unsigned int *width/height parameters on big endian systems by detecting the strange values and shifting them down 32bits
// (if it's little endian the unwritten bytes are the most significant
// ones and we don't worry about that)
//
// this is only necessary because of retarded 64bit png_uint_32 types in libpng 1.2, which can (conceivably) vary by platform
#if LONG_MAX > 4000000000
if (my_png.Width > LONG_MAX || my_png.Height > LONG_MAX)
{
my_png.Width >>= 32;
my_png.Height >>= 32;
}
#endif
if (my_png.ColorType == PNG_COLOR_TYPE_PALETTE)
qpng_set_palette_to_rgb(png);
if (my_png.ColorType == PNG_COLOR_TYPE_GRAY || my_png.ColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
qpng_set_gray_to_rgb(png);
if (qpng_get_valid(png, pnginfo, PNG_INFO_tRNS))
qpng_set_tRNS_to_alpha(png);
if (my_png.BitDepth == 8 && !(my_png.ColorType & PNG_COLOR_MASK_ALPHA))
qpng_set_filler(png, 255, 1);
if (( my_png.ColorType == PNG_COLOR_TYPE_GRAY) || (my_png.ColorType == PNG_COLOR_TYPE_GRAY_ALPHA ))
qpng_set_gray_to_rgb(png);
if (my_png.BitDepth < 8)
qpng_set_expand(png);
qpng_read_update_info(png, pnginfo);
my_png.FRowBytes = qpng_get_rowbytes(png, pnginfo);
my_png.BytesPerPixel = qpng_get_channels(png, pnginfo);
my_png.FRowPtrs = (unsigned char **)Mem_Alloc(tempmempool, my_png.Height * sizeof(*my_png.FRowPtrs));
if (my_png.FRowPtrs)
{
imagedata = (unsigned char *)Mem_Alloc(tempmempool, my_png.Height * my_png.FRowBytes);
if(imagedata)
{
my_png.Data = imagedata;
for(y = 0;y < my_png.Height;y++)
my_png.FRowPtrs[y] = my_png.Data + y * my_png.FRowBytes;
qpng_read_image(png, my_png.FRowPtrs);
}
else
{
Con_Printf("PNG_LoadImage : not enough memory\n");
qpng_destroy_read_struct(&png, &pnginfo, 0);
Mem_Free(my_png.FRowPtrs);
return NULL;
}
Mem_Free(my_png.FRowPtrs);
my_png.FRowPtrs = NULL;
}
else
{
Con_Printf("PNG_LoadImage : not enough memory\n");
qpng_destroy_read_struct(&png, &pnginfo, 0);
return NULL;
}
qpng_read_end(png, pnginfo);
qpng_destroy_read_struct(&png, &pnginfo, 0);
image_width = (int)my_png.Width;
image_height = (int)my_png.Height;
if (my_png.BitDepth != 8)
{
Con_Printf ("PNG_LoadImage : bad color depth\n");
Mem_Free(imagedata);
return NULL;
}
// swizzle RGBA to BGRA
for (y = 0;y < (unsigned int)(image_width*image_height*4);y += 4)
{
c = imagedata[y+0];
imagedata[y+0] = imagedata[y+2];
imagedata[y+2] = c;
}
return imagedata;
}
/*
=================================================================
PNG compression
=================================================================
*/
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define PNG_INTERLACE_NONE 0
#define PNG_INTERLACE_ADAM7 1
#define PNG_FILTER_TYPE_BASE 0
#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE
#define PNG_COMPRESSION_TYPE_BASE 0
#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
#define PNG_NO_FILTERS 0x00
#define PNG_FILTER_NONE 0x08
#define PNG_FILTER_SUB 0x10
#define PNG_FILTER_UP 0x20
#define PNG_FILTER_AVG 0x40
#define PNG_FILTER_PAETH 0x80
#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
PNG_FILTER_AVG | PNG_FILTER_PAETH)
/*
====================
PNG_SaveImage_preflipped
Save a preflipped PNG image to a file
====================
*/
qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, qboolean has_alpha, unsigned char *data)
{
unsigned int offset, linesize;
qfile_t* file = NULL;
void *png, *pnginfo;
unsigned char ioBuffer[8192];
int passes, i, j;
// No DLL = no JPEGs
if (!png_dll)
{
Con_Print("You need the libpng library to save PNG images\n");
return false;
}
png = (void *)qpng_create_write_struct(
(qpng_access_version_number() / 100 == 102) ? PNG_LIBPNG_VER_STRING_12 :
(qpng_access_version_number() / 100 == 104) ? PNG_LIBPNG_VER_STRING_14 :
(qpng_access_version_number() / 100 == 105) ? PNG_LIBPNG_VER_STRING_15 :
PNG_LIBPNG_VER_STRING_16, // nasty hack... whatever
0, PNG_error_fn, PNG_warning_fn
);
if(!png)
return false;
pnginfo = (void *)qpng_create_info_struct(png);
if(!pnginfo)
{
qpng_destroy_write_struct(&png, NULL);
return false;
}
// this must be memset before the setjmp error handler, because it relies
// on the fields in this struct for cleanup
memset(&my_png, 0, sizeof(my_png));
// NOTE: this relies on jmp_buf being the first thing in the png structure
// created by libpng! (this is correct for libpng 1.2.x)
#ifdef __cplusplus
#ifdef WIN64
if (setjmp((_JBTYPE *)png))
#elif defined(MACOSX) || defined(WIN32)
if (setjmp((int *)png))
#else
if (setjmp((__jmp_buf_tag *)png))
#endif
#else
if (setjmp(png))
#endif
{
qpng_destroy_write_struct(&png, &pnginfo);
return false;
}
// Open the file
file = FS_OpenRealFile(filename, "wb", true);
if (!file)
return false;
my_png.outfile = file;
qpng_set_write_fn(png, ioBuffer, PNG_fWriteData, PNG_fFlushData);
//qpng_set_compression_level(png, Z_BEST_COMPRESSION);
qpng_set_compression_level(png, Z_BEST_SPEED);
qpng_set_IHDR(png, pnginfo, width, height, 8, has_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
qpng_set_filter(png, 0, PNG_NO_FILTERS);
qpng_write_info(png, pnginfo);
qpng_set_packing(png);
qpng_set_bgr(png);
passes = qpng_set_interlace_handling(png);
linesize = width * (has_alpha ? 4 : 3);
offset = linesize * (height - 1);
for(i = 0; i < passes; ++i)
for(j = 0; j < height; ++j)
qpng_write_row(png, &data[offset - j * linesize]);
qpng_write_end(png, NULL);
qpng_destroy_write_struct(&png, &pnginfo);
FS_Close (file);
return true;
}

33
app/jni/image_png.h Normal file
View file

@ -0,0 +1,33 @@
/*
Copyright (C) 2006 Serge "(515)" Ziryukin
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef PNG_H
#define PNG_H
qboolean PNG_OpenLibrary (void);
void PNG_CloseLibrary (void);
unsigned char* PNG_LoadImage_BGRA (const unsigned char *f, int filesize, int *miplevel);
qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, qboolean has_alpha, unsigned char *data);
#endif

53
app/jni/input.h Normal file
View file

@ -0,0 +1,53 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/// \file input.h -- external (non-keyboard) input devices
#ifndef INPUT_H
#define INPUT_H
extern cvar_t in_pitch_min;
extern cvar_t in_pitch_max;
extern qboolean in_client_mouse;
extern float in_windowmouse_x, in_windowmouse_y;
extern float in_mouse_x, in_mouse_y;
//enum input_dest_e {input_game,input_message,input_menu} input_dest;
void IN_Move (void);
// add additional movement on top of the keyboard move cmd
#define IN_BESTWEAPON_MAX 32
typedef struct
{
char name[32];
int impulse;
int activeweaponcode;
int weaponbit;
int ammostat;
int ammomin;
/// \TODO add a parameter for the picture to be used by the sbar, and use it there
}
in_bestweapon_info_t;
extern in_bestweapon_info_t in_bestweapon_info[IN_BESTWEAPON_MAX];
void IN_BestWeapon_ResetData(void); ///< call before each map so QC can start from a clean state
#endif

22
app/jni/intoverflow.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef INTOVERFLOW_H
#define INTOVERFLOW_H
// simple safe library to handle integer overflows when doing buffer size calculations
// Usage:
// - calculate data size using INTOVERFLOW_??? macros
// - compare: calculated-size <= INTOVERFLOW_NORMALIZE(buffersize)
// Functionality:
// - all overflows (values > INTOVERFLOW_MAX) and errors are mapped to INTOVERFLOW_MAX
// - if any input of an operation is INTOVERFLOW_MAX, INTOVERFLOW_MAX will be returned
// - otherwise, regular arithmetics apply
#define INTOVERFLOW_MAX 2147483647
#define INTOVERFLOW_ADD(a,b) (((a) < INTOVERFLOW_MAX && (b) < INTOVERFLOW_MAX && (a) < INTOVERFLOW_MAX - (b)) ? ((a) + (b)) : INTOVERFLOW_MAX)
#define INTOVERFLOW_SUB(a,b) (((a) < INTOVERFLOW_MAX && (b) < INTOVERFLOW_MAX && (b) <= (a)) ? ((a) - (b)) : INTOVERFLOW_MAX)
#define INTOVERFLOW_MUL(a,b) (((a) < INTOVERFLOW_MAX && (b) < INTOVERFLOW_MAX && (a) < INTOVERFLOW_MAX / (b)) ? ((a) * (b)) : INTOVERFLOW_MAX)
#define INTOVERFLOW_DIV(a,b) (((a) < INTOVERFLOW_MAX && (b) < INTOVERFLOW_MAX && (b) > 0) ? ((a) / (b)) : INTOVERFLOW_MAX)
#define INTOVERFLOW_NORMALIZE(a) (((a) < INTOVERFLOW_MAX) ? (a) : (INTOVERFLOW_MAX - 1))
#endif

1108
app/jni/jpeg.c Normal file

File diff suppressed because it is too large Load diff

39
app/jni/jpeg.h Normal file
View file

@ -0,0 +1,39 @@
/*
Copyright (C) 2002 Mathieu Olivier
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef JPEG_H
#define JPEG_H
qboolean JPEG_OpenLibrary (void);
void JPEG_CloseLibrary (void);
unsigned char* JPEG_LoadImage_BGRA (const unsigned char *f, int filesize, int *miplevel);
qboolean JPEG_SaveImage_preflipped (const char *filename, int width, int height, unsigned char *data);
/*! \returns 0 if failed, or the size actually used.
*/
size_t JPEG_SaveImage_to_Buffer (char *jpegbuf, size_t jpegsize, int width, int height, unsigned char *data);
qboolean Image_Compress(const char *imagename, size_t maxsize, void **buf, size_t *size);
#endif

2003
app/jni/keys.c Normal file

File diff suppressed because it is too large Load diff

392
app/jni/keys.h Normal file
View file

@ -0,0 +1,392 @@
/*
$RCSfile$
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id: keys.h 11463 2011-10-22 23:52:58Z havoc $
*/
#ifndef __KEYS_H
#define __KEYS_H
#include "qtypes.h"
//
// these are the key numbers that should be passed to Key_Event
//
typedef enum keynum_e
{
K_TEXT = 1, // used only for unicode character input
K_TAB = 9,
K_ENTER = 13,
K_ESCAPE = 27,
K_SPACE = 32,
// normal keys should be passed as lowercased ascii
K_BACKSPACE = 127,
K_UPARROW,
K_DOWNARROW,
K_LEFTARROW,
K_RIGHTARROW,
K_ALT,
K_CTRL,
K_SHIFT,
K_F1,
K_F2,
K_F3,
K_F4,
K_F5,
K_F6,
K_F7,
K_F8,
K_F9,
K_F10,
K_F11,
K_F12,
K_INS,
K_DEL,
K_PGDN,
K_PGUP,
K_HOME,
K_END,
K_PAUSE,
K_NUMLOCK,
K_CAPSLOCK,
K_SCROLLOCK,
K_KP_0,
K_KP_INS = K_KP_0,
K_KP_1,
K_KP_END = K_KP_1,
K_KP_2,
K_KP_DOWNARROW = K_KP_2,
K_KP_3,
K_KP_PGDN = K_KP_3,
K_KP_4,
K_KP_LEFTARROW = K_KP_4,
K_KP_5,
K_KP_6,
K_KP_RIGHTARROW = K_KP_6,
K_KP_7,
K_KP_HOME = K_KP_7,
K_KP_8,
K_KP_UPARROW = K_KP_8,
K_KP_9,
K_KP_PGUP = K_KP_9,
K_KP_PERIOD,
K_KP_DEL = K_KP_PERIOD,
K_KP_DIVIDE,
K_KP_SLASH = K_KP_DIVIDE,
K_KP_MULTIPLY,
K_KP_MINUS,
K_KP_PLUS,
K_KP_ENTER,
K_KP_EQUALS,
K_PRINTSCREEN,
// mouse buttons generate virtual keys
K_MOUSE1 = 512,
K_OTHERDEVICESBEGIN = K_MOUSE1,
K_MOUSE2,
K_MOUSE3,
K_MWHEELUP,
K_MWHEELDOWN,
K_MOUSE4,
K_MOUSE5,
K_MOUSE6,
K_MOUSE7,
K_MOUSE8,
K_MOUSE9,
K_MOUSE10,
K_MOUSE11,
K_MOUSE12,
K_MOUSE13,
K_MOUSE14,
K_MOUSE15,
K_MOUSE16,
//
// joystick buttons
//
K_JOY1 = 768,
K_JOY2,
K_JOY3,
K_JOY4,
K_JOY5,
K_JOY6,
K_JOY7,
K_JOY8,
K_JOY9,
K_JOY10,
K_JOY11,
K_JOY12,
K_JOY13,
K_JOY14,
K_JOY15,
K_JOY16,
//
// aux keys are for multi-buttoned joysticks to generate so they can use
// the normal binding process
//
K_AUX1,
K_AUX2,
K_AUX3,
K_AUX4,
K_AUX5,
K_AUX6,
K_AUX7,
K_AUX8,
K_AUX9,
K_AUX10,
K_AUX11,
K_AUX12,
K_AUX13,
K_AUX14,
K_AUX15,
K_AUX16,
K_AUX17,
K_AUX18,
K_AUX19,
K_AUX20,
K_AUX21,
K_AUX22,
K_AUX23,
K_AUX24,
K_AUX25,
K_AUX26,
K_AUX27,
K_AUX28,
K_AUX29,
K_AUX30,
K_AUX31,
K_AUX32,
// Microsoft Xbox 360 Controller For Windows
K_X360_DPAD_UP,
K_X360_DPAD_DOWN,
K_X360_DPAD_LEFT,
K_X360_DPAD_RIGHT,
K_X360_START,
K_X360_BACK,
K_X360_LEFT_THUMB,
K_X360_RIGHT_THUMB,
K_X360_LEFT_SHOULDER,
K_X360_RIGHT_SHOULDER,
K_X360_A,
K_X360_B,
K_X360_X,
K_X360_Y,
K_X360_LEFT_TRIGGER,
K_X360_RIGHT_TRIGGER,
K_X360_LEFT_THUMB_UP,
K_X360_LEFT_THUMB_DOWN,
K_X360_LEFT_THUMB_LEFT,
K_X360_LEFT_THUMB_RIGHT,
K_X360_RIGHT_THUMB_UP,
K_X360_RIGHT_THUMB_DOWN,
K_X360_RIGHT_THUMB_LEFT,
K_X360_RIGHT_THUMB_RIGHT,
// generic joystick emulation for menu
K_JOY_UP,
K_JOY_DOWN,
K_JOY_LEFT,
K_JOY_RIGHT,
K_MIDINOTE0 = 896, // to this, the note number is added
K_MIDINOTE1,
K_MIDINOTE2,
K_MIDINOTE3,
K_MIDINOTE4,
K_MIDINOTE5,
K_MIDINOTE6,
K_MIDINOTE7,
K_MIDINOTE8,
K_MIDINOTE9,
K_MIDINOTE10,
K_MIDINOTE11,
K_MIDINOTE12,
K_MIDINOTE13,
K_MIDINOTE14,
K_MIDINOTE15,
K_MIDINOTE16,
K_MIDINOTE17,
K_MIDINOTE18,
K_MIDINOTE19,
K_MIDINOTE20,
K_MIDINOTE21,
K_MIDINOTE22,
K_MIDINOTE23,
K_MIDINOTE24,
K_MIDINOTE25,
K_MIDINOTE26,
K_MIDINOTE27,
K_MIDINOTE28,
K_MIDINOTE29,
K_MIDINOTE30,
K_MIDINOTE31,
K_MIDINOTE32,
K_MIDINOTE33,
K_MIDINOTE34,
K_MIDINOTE35,
K_MIDINOTE36,
K_MIDINOTE37,
K_MIDINOTE38,
K_MIDINOTE39,
K_MIDINOTE40,
K_MIDINOTE41,
K_MIDINOTE42,
K_MIDINOTE43,
K_MIDINOTE44,
K_MIDINOTE45,
K_MIDINOTE46,
K_MIDINOTE47,
K_MIDINOTE48,
K_MIDINOTE49,
K_MIDINOTE50,
K_MIDINOTE51,
K_MIDINOTE52,
K_MIDINOTE53,
K_MIDINOTE54,
K_MIDINOTE55,
K_MIDINOTE56,
K_MIDINOTE57,
K_MIDINOTE58,
K_MIDINOTE59,
K_MIDINOTE60,
K_MIDINOTE61,
K_MIDINOTE62,
K_MIDINOTE63,
K_MIDINOTE64,
K_MIDINOTE65,
K_MIDINOTE66,
K_MIDINOTE67,
K_MIDINOTE68,
K_MIDINOTE69,
K_MIDINOTE70,
K_MIDINOTE71,
K_MIDINOTE72,
K_MIDINOTE73,
K_MIDINOTE74,
K_MIDINOTE75,
K_MIDINOTE76,
K_MIDINOTE77,
K_MIDINOTE78,
K_MIDINOTE79,
K_MIDINOTE80,
K_MIDINOTE81,
K_MIDINOTE82,
K_MIDINOTE83,
K_MIDINOTE84,
K_MIDINOTE85,
K_MIDINOTE86,
K_MIDINOTE87,
K_MIDINOTE88,
K_MIDINOTE89,
K_MIDINOTE90,
K_MIDINOTE91,
K_MIDINOTE92,
K_MIDINOTE93,
K_MIDINOTE94,
K_MIDINOTE95,
K_MIDINOTE96,
K_MIDINOTE97,
K_MIDINOTE98,
K_MIDINOTE99,
K_MIDINOTE100,
K_MIDINOTE101,
K_MIDINOTE102,
K_MIDINOTE103,
K_MIDINOTE104,
K_MIDINOTE105,
K_MIDINOTE106,
K_MIDINOTE107,
K_MIDINOTE108,
K_MIDINOTE109,
K_MIDINOTE110,
K_MIDINOTE111,
K_MIDINOTE112,
K_MIDINOTE113,
K_MIDINOTE114,
K_MIDINOTE115,
K_MIDINOTE116,
K_MIDINOTE117,
K_MIDINOTE118,
K_MIDINOTE119,
K_MIDINOTE120,
K_MIDINOTE121,
K_MIDINOTE122,
K_MIDINOTE123,
K_MIDINOTE124,
K_MIDINOTE125,
K_MIDINOTE126,
K_MIDINOTE127,
MAX_KEYS
}
keynum_t;
typedef enum keydest_e { key_game, key_message, key_menu, key_menu_grabbed, key_console, key_void } keydest_t;
extern char key_line[MAX_INPUTLINE];
extern int key_linepos;
extern qboolean key_insert; // insert key toggle (for editing)
extern keydest_t key_dest;
// key_consoleactive bits
// user wants console (halfscreen)
#define KEY_CONSOLEACTIVE_USER 1
// console forced because there's nothing else active (fullscreen)
#define KEY_CONSOLEACTIVE_FORCED 4
extern int key_consoleactive;
extern char *keybindings[MAX_BINDMAPS][MAX_KEYS];
extern int chat_mode; // 0 for say, 1 for say_team, -1 for command
extern char chat_buffer[MAX_INPUTLINE];
extern unsigned int chat_bufferlen;
void Key_ClearEditLine(int edit_line);
void Key_WriteBindings(qfile_t *f);
void Key_Init(void);
void Key_Shutdown(void);
void Key_Init_Cvars(void);
void Key_Event(int key, int ascii, qboolean down);
void Key_ReleaseAll (void);
void Key_ClearStates (void); // FIXME: should this function still exist? Or should Key_ReleaseAll be used instead when shutting down a vid driver?
void Key_EventQueue_Block(void);
void Key_EventQueue_Unblock(void);
qboolean Key_SetBinding (int keynum, int bindmap, const char *binding);
const char *Key_GetBind (int key, int bindmap);
void Key_FindKeysForCommand (const char *command, int *keys, int numkeys, int bindmap);
qboolean Key_SetBindMap(int fg, int bg);
void Key_GetBindMap(int *fg, int *bg);
#endif // __KEYS_H

106
app/jni/lhfont.h Normal file
View file

@ -0,0 +1,106 @@
0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x08,0x08,0x99,0x00,0x83,0xFF,0xFF,0x00,0xE1,0x00,0x99,0x00,0x83,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x8B,0x00,0x85,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8B,0xFF,0x89,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x9D,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x8A,0xFF,0x89,0x00,0x86,0xFF,0x84,0x00,0x89,0xFF,
0x87,0x00,0x85,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x85,0x00,0x84,0xFF,0x88,0x00,0x8B,0xFF,0x88,0x00,0x86,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x86,0xFF,0x9B,0x00,0x84,0xFF,0x85,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x99,0x00,0x83,0xFF,0x87,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x83,0xFF,
0x93,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x84,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x8B,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x87,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x87,0xFF,0x8A,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x8A,0x00,0x82,0xFF,0x8D,0x00,
0x83,0xFF,0x8D,0x00,0x82,0xFF,0x96,0x00,0x8B,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x88,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x87,0xFF,0x89,0x00,0x85,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0x9F,0x00,0x84,0xFF,0x94,0x00,0x8B,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x89,0xFF,0x83,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x8A,0x00,0x84,0xFF,0x86,0x00,0x84,0xFF,0x9F,0x00,0x84,0xFF,0x95,0x00,0x84,0xFF,0x87,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x85,0x00,0x89,0xFF,0x8A,0x00,0x84,0xFF,
0x87,0x00,0x82,0xFF,0x8D,0x00,0x83,0xFF,0x8D,0x00,0x82,0xFF,0x98,0x00,0x83,0xFF,0x87,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x99,0x00,0x84,0xFF,0x85,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x9B,0x00,0x83,0xFF,0x85,0x00,0xFF,0x00,0xB6,0x00,0x86,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x86,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x93,0x00,0xFF,0x00,0xB7,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x86,0xFF,0x92,0x00,0xFF,0x00,0xE0,0x00,0x86,0xFF,0x81,0x00,0x83,0xFF,0x91,0x00,0xFF,0x00,0xE1,0x00,0x85,0xFF,
0x81,0x00,0x83,0xFF,0x91,0x00,0xF3,0x00,0x85,0xFF,0xFF,0x00,0x85,0x00,0xF3,0x00,0x86,0xFF,0xFF,0x00,0x84,0x00,0x93,0x00,0x89,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0x92,0x00,0x8A,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,
0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x86,0x00,0x87,0xFF,0x88,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x82,0x00,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x86,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x8A,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x00,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x81,0x00,0x92,0x00,0x8A,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x93,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,
0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x00,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8D,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x84,0xFF,0x90,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x87,0x00,0x8D,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x81,0x00,0x84,0x00,0x84,0xFF,0x89,0x00,0x88,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x89,0xFF,0x84,0x00,0x83,0xFF,0x8A,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0xA4,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x88,0x00,0x8B,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x82,0x00,0x85,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0xA5,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,
0x87,0x00,0x87,0xFF,0x83,0x00,0x85,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0xA3,0x00,0x83,0xFF,0x94,0x00,0x86,0xFF,0x97,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x97,0x00,0x85,0xFF,0xB7,0x00,0x85,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0xA3,0x00,0x83,0xFF,0x95,0x00,0x85,0xFF,0x97,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x97,0x00,0x85,0xFF,0xB7,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x97,0x00,0x85,0xFF,0xFF,0x00,0xE1,0x00,0x96,0x00,0x86,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x83,0xFF,0x8D,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x89,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x8F,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x93,0x00,0x8D,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8C,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x87,0x00,0x85,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x8E,0x00,0x84,0xFF,0x83,0x00,0x87,0xFF,0x93,0x00,0x8D,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x91,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x84,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,
0x89,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8F,0x00,0x84,0xFF,0x8A,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x8A,0x00,0x83,0xFF,0x8E,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x88,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x85,0xFF,0x8A,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x91,0x00,
0x81,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x85,0xFF,0x89,0x00,0x85,0xFF,0x8A,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x91,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x8E,0x00,0x83,0xFF,0x84,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x92,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x8A,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,
0x8A,0x00,0x84,0xFF,0x8F,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x93,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x83,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x84,0xFF,0x8C,0x00,0x87,0xFF,0x86,0x00,0x87,0xFF,0x94,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x87,0xFF,0x87,0x00,0x85,0xFF,0x95,0x00,0xFF,0x00,0xE4,0x00,0x83,0xFF,0x96,0x00,0xFF,0x00,0xE5,0x00,0x81,0xFF,0x97,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x87,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x8B,0xFF,0x83,0x00,0x85,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0x82,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x8A,0x00,0x89,0xFF,0x86,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x82,0x00,0x87,0xFF,0x88,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x82,0x00,0x81,0x00,
0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,
0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,
0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x00,0x00,0x86,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x84,0x00,0x82,0xFF,0x83,0x00,0x82,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,
0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x81,0xFF,0x83,0x00,0x81,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x86,0xFF,0x00,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x85,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x85,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x82,0x00,0x89,0xFF,0x87,0x00,0x85,0xFF,0x86,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x82,0x00,0x89,0xFF,0x86,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x82,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x82,0x00,0x83,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,
0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xB3,0x00,0x83,0xFF,0xC7,0x00,0xFF,0x00,0xB3,0x00,0x84,0xFF,0xC6,0x00,0x83,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x89,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,
0x87,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x85,0x00,0x82,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x8A,0xFF,0x8A,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x86,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x95,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x8B,0xFF,0x87,0x00,0x84,0xFF,0x94,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x88,0x00,0x88,0xFF,0x89,0x00,
0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0xA5,0x00,0x84,0xFF,0x9D,0x00,0x84,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x89,0x00,0x88,0xFF,0x88,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x84,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x8A,0xFF,0xA5,0x00,0x83,0xFF,0x9F,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x84,0x00,
0x88,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0xA5,0x00,0x83,0xFF,0x9F,0x00,0x83,0xFF,0x89,0x00,0x85,0xFF,0x83,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0xA5,0x00,0x84,0xFF,0x9D,0x00,0x84,0xFF,0x89,0x00,0x86,0xFF,0x82,0x00,0x82,0x00,0x89,0xFF,0x86,0x00,0x85,0xFF,0x87,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x87,0x00,
0x86,0xFF,0x85,0x00,0x8B,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x8B,0xFF,0x87,0x00,0x84,0xFF,0x8E,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x87,0xFF,0x87,0x00,0x85,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x85,0xFF,0x85,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x86,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x8F,0x00,0x83,0xFF,0x81,0x00,0xFF,0x00,0xA5,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,
0x97,0x00,0x84,0xFF,0x88,0x00,0x8A,0xFF,0x82,0x00,0xFF,0x00,0xA5,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0x89,0x00,0x89,0xFF,0x83,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xC5,0x00,0x83,0xFF,0xB5,0x00,0xFF,0x00,0xC5,0x00,0x84,0xFF,0xB4,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x89,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x81,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x95,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x95,0x00,0x83,0xFF,
0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x84,0x00,0x84,0xFF,0x84,0x00,0x83,0xFF,0x82,0x00,0x8C,0xFF,0x97,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x8A,0x00,0xB0,0x00,0x8D,0xFF,0x83,0x00,0x89,0xFF,0x84,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x89,0x00,0x84,0xFF,0x89,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x89,0x00,0xB0,0x00,0x8D,0xFF,0x87,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x85,0x00,0x84,0xFF,
0x82,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x97,0x00,0x84,0xFF,0x8B,0x00,0x84,0xFF,0x88,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x88,0x00,0x95,0x00,0x83,0xFF,0x96,0x00,0x8D,0xFF,0x87,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x86,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x96,0x00,0x84,0xFF,0x8D,0x00,0x84,0xFF,0x83,0x00,0x8F,0xFF,0x81,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x94,0x00,0x84,0xFF,0x87,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x88,0xFF,0x87,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x86,0xFF,0x95,0x00,0x83,0xFF,
0x8F,0x00,0x83,0xFF,0x83,0x00,0x8F,0xFF,0x81,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x95,0x00,0x84,0xFF,0x86,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x89,0x00,0x84,0xFF,0x86,0x00,0x88,0xFF,0x00,0x00,0x82,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0xBA,0x00,0x84,0xFF,0x85,0x00,0x95,0x00,0x83,0xFF,0x96,0x00,0x8D,0xFF,0x83,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x8D,0x00,0x84,0xFF,0x86,0x00,0x86,0xFF,0x82,0x00,0x81,0xFF,0x88,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0xBB,0x00,0x84,0xFF,
0x84,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x8D,0xFF,0x83,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x86,0x00,0x86,0xFF,0x8D,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xBC,0x00,0x84,0xFF,0x83,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x8D,0xFF,0x83,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x85,0x00,0x87,0xFF,0x8D,0x00,0x83,0xFF,0x85,0x00,0x84,0xFF,0x8D,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xBD,0x00,0x84,0xFF,
0x82,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x88,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x8C,0x00,0x83,0xFF,0x86,0x00,0x84,0xFF,0x8B,0x00,0x84,0xFF,0xDD,0x00,0x84,0xFF,0x81,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x89,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x8C,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x89,0x00,0x84,0xFF,0xDF,0x00,0x83,0xFF,0x81,0x00,0xA2,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0xB6,0x00,
0x87,0xFF,0x9A,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0xE6,0x00,0xA2,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0xB7,0x00,0x85,0xFF,0x9C,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xE7,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x89,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0xC3,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x84,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,
0x83,0x00,0x8A,0xFF,0x8A,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x88,0xFF,0x99,0x00,0xA1,0xFF,0x86,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x96,0x00,0xA5,0xFF,0x84,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,
0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x94,0x00,0xA9,0xFF,0x82,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x88,0x00,0x88,0xFF,0x89,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x89,0x00,0x88,0xFF,
0x88,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x84,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x8A,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x84,0x00,0x89,0xFF,0x86,0x00,0x85,0xFF,0x87,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x87,0x00,0x86,0xFF,0x85,0x00,0x8B,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x95,0x00,0xA9,0xFF,0x82,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x85,0x00,0x87,0xFF,0x87,0x00,0x85,0xFF,0x87,0x00,0x89,0xFF,
0x85,0x00,0x89,0xFF,0x89,0x00,0x85,0xFF,0x85,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x98,0x00,0xA5,0xFF,0x84,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xB8,0x00,0xA1,0xFF,0x86,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xE1,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xB2,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x97,0x00,0x85,0xFF,0xFF,0x00,0x94,0x00,0xB1,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x95,0x00,0x87,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x81,0xFF,0xAB,0x00,0x81,0x00,0xAB,0xFF,
0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x83,0xFF,0xA9,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x85,0xFF,0xA7,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x87,0xFF,0xA5,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,
0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,
0x83,0xFF,0x85,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x87,0xFF,0xA5,0x00,0x82,0x00,0xA9,0xFF,0x83,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x85,0xFF,
0xA7,0x00,0x83,0x00,0xA7,0xFF,0x84,0x00,0x8D,0xFF,0x81,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x83,0xFF,0xA9,0x00,0xB1,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x95,0x00,0x87,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x81,0xFF,0xAB,0x00,0xB2,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x97,0x00,0x85,0xFF,0xFF,0x00,0x94,0x00,0xFF,0x00,0xFF,0x00,0x99,0x00,0x83,0xFF,0xFF,0x00,0xE1,0x00,0x99,0x00,0x83,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x8B,0x00,
0x85,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8B,0xFF,0x89,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x9D,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x8A,0xFF,0x89,0x00,0x86,0xFF,0x84,0x00,0x89,0xFF,0x87,0x00,0x85,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x85,0x00,0x84,0xFF,0x88,0x00,0x8B,0xFF,0x88,0x00,0x86,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x86,0xFF,0x9B,0x00,0x84,0xFF,0x85,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,
0x89,0xFF,0x83,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x99,0x00,0x83,0xFF,0x87,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x84,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x8B,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,
0x87,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x87,0xFF,0x8A,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x8A,0x00,0x82,0xFF,0x8D,0x00,0x83,0xFF,0x8D,0x00,0x82,0xFF,0x96,0x00,0x8B,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x88,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x87,0xFF,0x89,0x00,0x85,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0x9F,0x00,0x84,0xFF,0x94,0x00,0x8B,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x8A,0x00,0x84,0xFF,0x86,0x00,0x84,0xFF,0x9F,0x00,0x84,0xFF,0x95,0x00,0x84,0xFF,0x87,0x00,
0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x8D,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x85,0x00,0x89,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x82,0xFF,0x8D,0x00,0x83,0xFF,0x8D,0x00,0x82,0xFF,0x98,0x00,0x83,0xFF,0x87,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x99,0x00,0x84,0xFF,0x85,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,
0x8B,0x00,0x83,0xFF,0x9B,0x00,0x83,0xFF,0x85,0x00,0xFF,0x00,0xB6,0x00,0x86,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x86,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x93,0x00,0xFF,0x00,0xB7,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x86,0xFF,0x92,0x00,0xFF,0x00,0xE0,0x00,0x86,0xFF,0x81,0x00,0x83,0xFF,0x91,0x00,0xFF,0x00,0xE1,0x00,0x85,0xFF,0x81,0x00,0x83,0xFF,0x91,0x00,0xF3,0x00,0x85,0xFF,0xFF,0x00,0x85,0x00,0xF3,0x00,0x86,0xFF,0xFF,0x00,0x84,0x00,0x93,0x00,0x89,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x85,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0x92,0x00,0x8A,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x86,0x00,0x87,0xFF,0x88,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x84,0x00,0x89,0xFF,0x82,0x00,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x8A,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x00,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x92,0x00,0x8A,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x93,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x00,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8D,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x84,0xFF,0x90,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x87,0x00,0x8D,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x84,0x00,0x84,0xFF,0x89,0x00,0x88,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x89,0xFF,0x84,0x00,0x83,0xFF,0x8A,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0xA4,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x85,0x00,
0x83,0xFF,0x88,0x00,0x8B,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x82,0x00,0x85,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0xA5,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x83,0x00,0x85,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0xA3,0x00,0x83,0xFF,0x94,0x00,0x86,0xFF,0x97,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x97,0x00,0x85,0xFF,0xB7,0x00,0x85,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0xA3,0x00,0x83,0xFF,
0x95,0x00,0x85,0xFF,0x97,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x97,0x00,0x85,0xFF,0xB7,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x97,0x00,0x85,0xFF,0xFF,0x00,0xE1,0x00,0x96,0x00,0x86,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x83,0xFF,0x8D,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x8F,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x93,0x00,0x8D,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8C,0x00,0x88,0xFF,
0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x87,0x00,0x85,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x8E,0x00,0x84,0xFF,0x83,0x00,0x87,0xFF,0x93,0x00,0x8D,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x91,0x00,
0x84,0xFF,0x88,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x84,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,0x89,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8C,0x00,0x82,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x81,0x00,
0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0x8F,0x00,0x84,0xFF,0x8A,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x8A,0x00,0x83,0xFF,0x8E,0x00,0x84,0xFF,0x8B,0x00,0x83,0xFF,0xA3,0x00,0x81,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x83,0x00,0x8A,0xFF,0x85,0x00,0x88,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x85,0xFF,0x8A,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x91,0x00,0x81,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,
0x86,0x00,0x85,0xFF,0x89,0x00,0x85,0xFF,0x8A,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x91,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x8E,0x00,0x83,0xFF,0x84,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x92,0x00,
0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x8A,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x8F,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x93,0x00,0x81,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x8A,0xFF,0x85,0x00,0x8A,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,
0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x81,0x00,0x84,0xFF,0x83,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x84,0xFF,0x8C,0x00,0x87,0xFF,0x86,0x00,0x87,0xFF,0x94,0x00,0x81,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x89,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x87,0xFF,
0x87,0x00,0x85,0xFF,0x95,0x00,0xFF,0x00,0xE4,0x00,0x83,0xFF,0x96,0x00,0xFF,0x00,0xE5,0x00,0x81,0xFF,0x97,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x83,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x87,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x85,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0x82,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x83,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x8A,0x00,0x89,0xFF,0x86,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x82,0x00,0x87,0xFF,0x88,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x82,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,
0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x81,0x00,0x81,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x00,0x00,0x86,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,
0x85,0xFF,0x84,0x00,0x82,0xFF,0x83,0x00,0x82,0xFF,0x84,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x85,0x00,0x81,0xFF,0x83,0x00,0x81,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8D,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,
0x8B,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x8D,0xFF,0x83,0x00,0x86,0xFF,0x00,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x81,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x85,0xFF,0x81,0x00,0x85,0xFF,0x83,0x00,0x85,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x82,0x00,0x89,0xFF,0x87,0x00,0x85,0xFF,0x86,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x84,0x00,
0x8A,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x82,0x00,0x89,0xFF,0x86,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x83,0x00,0x84,0xFF,0x82,0x00,0x83,0xFF,0x84,0x00,0x89,0xFF,0x82,0x00,0x83,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x87,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,
0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x83,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xB3,0x00,0x83,0xFF,0xC7,0x00,0xFF,0x00,0xB3,0x00,0x84,0xFF,0xC6,0x00,0x83,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x89,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x8D,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x85,0x00,0x82,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x8A,0xFF,0x8A,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,
0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x88,0xFF,0x88,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x8C,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x86,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x95,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,
0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x8B,0xFF,0x87,0x00,0x84,0xFF,0x94,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x88,0x00,0x88,0xFF,0x89,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0xA5,0x00,0x84,0xFF,0x9D,0x00,0x84,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x87,0x00,0x83,0xFF,0x89,0x00,0x88,0xFF,0x88,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x84,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x8A,0xFF,0xA5,0x00,0x83,0xFF,0x9F,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x85,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0xA5,0x00,0x83,0xFF,0x9F,0x00,0x83,0xFF,0x89,0x00,0x85,0xFF,0x83,0x00,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,
0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0xA5,0x00,0x84,0xFF,0x9D,0x00,0x84,0xFF,0x89,0x00,0x86,0xFF,0x82,0x00,0x82,0x00,0x89,0xFF,0x86,0x00,0x85,0xFF,0x87,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x87,0x00,0x86,0xFF,0x85,0x00,0x8B,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x87,0x00,0x8B,0xFF,0x87,0x00,0x84,0xFF,0x8E,0x00,0x83,0xFF,0x81,0x00,0x83,0x00,0x87,0xFF,
0x87,0x00,0x85,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x85,0xFF,0x85,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x86,0x00,0x8B,0xFF,0x86,0x00,0x84,0xFF,0x8F,0x00,0x83,0xFF,0x81,0x00,0xFF,0x00,0xA5,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x88,0x00,0x8A,0xFF,0x82,0x00,0xFF,0x00,0xA5,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x97,0x00,0x83,0xFF,0x89,0x00,0x89,0xFF,0x83,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xC5,0x00,0x83,0xFF,0xB5,0x00,0xFF,0x00,
0xC5,0x00,0x84,0xFF,0xB4,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x89,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x85,0xFF,0x81,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8C,0x00,0x84,0xFF,0x95,0x00,0x83,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x84,0x00,0x84,0xFF,0x84,0x00,0x83,0xFF,0x82,0x00,0x8C,0xFF,0x97,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0x88,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,
0x89,0x00,0x84,0xFF,0x8A,0x00,0xB0,0x00,0x8D,0xFF,0x83,0x00,0x89,0xFF,0x84,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x97,0x00,0x84,0xFF,0x89,0x00,0x84,0xFF,0x89,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,0x8A,0x00,0x84,0xFF,0x89,0x00,0xB0,0x00,0x8D,0xFF,0x87,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x85,0x00,0x84,0xFF,0x82,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x97,0x00,0x84,0xFF,0x8B,0x00,0x84,0xFF,0x88,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x8D,0x00,0x83,0xFF,0x95,0x00,0x83,0xFF,0x8B,0x00,0x84,0xFF,0x88,0x00,0x95,0x00,0x83,0xFF,0x96,0x00,0x8D,0xFF,0x87,0x00,
0x81,0xFF,0x81,0x00,0x81,0xFF,0x86,0x00,0x84,0xFF,0x87,0x00,0x83,0xFF,0x81,0x00,0x85,0xFF,0x96,0x00,0x84,0xFF,0x8D,0x00,0x84,0xFF,0x83,0x00,0x8F,0xFF,0x81,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x94,0x00,0x84,0xFF,0x87,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x88,0xFF,0x87,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x81,0x00,0x86,0xFF,0x95,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x83,0x00,0x8F,0xFF,0x81,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x95,0x00,0x84,0xFF,0x86,0x00,0x95,0x00,0x83,0xFF,0x98,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x88,0xFF,0x89,0x00,0x84,0xFF,0x86,0x00,0x88,0xFF,0x00,0x00,0x82,0xFF,0x88,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0xBA,0x00,0x84,0xFF,0x85,0x00,0x95,0x00,0x83,0xFF,0x96,0x00,0x8D,0xFF,0x83,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x8D,0x00,0x84,0xFF,0x86,0x00,0x86,0xFF,0x82,0x00,0x81,0xFF,0x88,0x00,0x84,0xFF,0x86,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0xBB,0x00,0x84,0xFF,0x84,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x8D,0xFF,0x83,0x00,0x81,0xFF,0x81,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x82,0x00,0x84,0xFF,0x86,0x00,0x86,0xFF,0x8D,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x85,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xBC,0x00,0x84,0xFF,0x83,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x83,0x00,0x8D,0xFF,0x83,0x00,0x89,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x84,0xFF,0x85,0x00,0x87,0xFF,0x8D,0x00,0x83,0xFF,0x85,0x00,0x84,0xFF,0x8D,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xBD,0x00,0x84,0xFF,0x82,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x86,0x00,0x88,0xFF,0x83,0x00,0x83,0xFF,0x84,0x00,0x84,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x8C,0x00,0x83,0xFF,0x86,0x00,0x84,0xFF,0x8B,0x00,
0x84,0xFF,0xDD,0x00,0x84,0xFF,0x81,0x00,0x95,0x00,0x83,0xFF,0x88,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x89,0x00,0x81,0xFF,0x87,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x8C,0x00,0x83,0xFF,0x87,0x00,0x84,0xFF,0x89,0x00,0x84,0xFF,0xDF,0x00,0x83,0xFF,0x81,0x00,0xA2,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0xB6,0x00,0x87,0xFF,0x9A,0x00,0x84,0xFF,0x87,0x00,0x84,0xFF,0xE6,0x00,0xA2,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0xB7,0x00,0x85,0xFF,0x9C,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0xE7,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,
0x8B,0xFF,0xFF,0x00,0xE1,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x85,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x89,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x89,0x00,0x83,0xFF,0x89,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0xC3,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x84,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x87,0x00,0x8B,0xFF,0x83,0x00,0x8A,0xFF,0x8A,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x85,0x00,0x89,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x88,0xFF,0x99,0x00,0xA1,0xFF,0x86,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x96,0x00,0xA5,0xFF,0x84,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x93,0x00,0x83,0xFF,0x83,0x00,0x8B,0xFF,0x8B,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x94,0x00,0xA9,0xFF,0x82,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,
0x83,0xFF,0x87,0x00,0x83,0xFF,0x88,0x00,0x88,0xFF,0x89,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x88,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x89,0x00,0x88,0xFF,0x88,0x00,0x86,0xFF,0x84,0x00,0x83,0xFF,0x81,0x00,0x83,0xFF,0x85,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x84,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x8A,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,
0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x90,0x00,0x84,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x8F,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x91,0x00,0x83,0xFF,0x85,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x83,0x00,0x83,0xFF,0x87,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,
0x81,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x84,0x00,0x89,0xFF,0x86,0x00,0x85,0xFF,0x87,0x00,0x8A,0xFF,0x84,0x00,0x8A,0xFF,0x87,0x00,0x86,0xFF,0x85,0x00,0x8B,0xFF,0x84,0x00,0x88,0xFF,0x85,0x00,0x89,0xFF,0x86,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x95,0x00,0xA9,0xFF,0x82,0x00,0x81,0x00,0x85,0xFF,0x8F,0x00,0x85,0xFF,0x85,0x00,0x87,0xFF,0x87,0x00,0x85,0xFF,0x87,0x00,0x89,0xFF,0x85,0x00,0x89,0xFF,0x89,0x00,0x85,0xFF,0x85,0x00,0x8B,0xFF,0x85,0x00,0x87,0xFF,0x85,0x00,0x89,0xFF,0x87,0x00,0x87,0xFF,0x87,0x00,0x87,0xFF,0x98,0x00,0xA5,0xFF,0x84,0x00,0x81,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xB8,0x00,0xA1,0xFF,0x86,0x00,0x81,0x00,
0x8B,0xFF,0x83,0x00,0x8B,0xFF,0xFF,0x00,0xE1,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xC2,0x00,0x89,0xFF,0x97,0x00,0x85,0xFF,0xFF,0x00,0x94,0x00,0xC1,0x00,0x8B,0xFF,0x95,0x00,0x87,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x81,0xFF,0xAB,0x00,0x91,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x83,0xFF,0xA9,0x00,0x91,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,
0x85,0xFF,0xA7,0x00,0x91,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x87,0xFF,0xA5,0x00,0x85,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x85,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,
0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x85,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x87,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x85,0x00,0x83,0xFF,0x87,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x86,0x00,0x83,0xFF,0x88,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x89,0xFF,0x89,0x00,0x83,0xFF,0x8B,0x00,0x83,0xFF,0x85,0x00,0x91,0x00,0xAB,0xFF,0x82,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,
0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x87,0xFF,0xA5,0x00,0x92,0x00,0xA9,0xFF,0x83,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x85,0xFF,0xA7,0x00,0x93,0x00,0xA7,0xFF,0x84,0x00,0x8D,0xFF,0x93,0x00,0x89,0xFF,0x84,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x83,0xFF,0xA9,0x00,0xC1,0x00,0x8B,0xFF,0x95,0x00,0x87,0xFF,0x85,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x83,0x00,0x8B,0xFF,0x93,0x00,0x8B,0xFF,0x93,0x00,0x81,0xFF,0xAB,0x00,0xC2,0x00,0x89,0xFF,0x97,0x00,0x85,0xFF,0xFF,0x00,0x94,0x00,0xFF,0x00,
0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x52,0x55,0x45,0x56,0x49,0x53,0x49,0x4F,0x4E,0x2D,0x58,0x46,0x49,0x4C,0x45,0x2E,0x00

1419
app/jni/lhnet.c Normal file

File diff suppressed because it is too large Load diff

52
app/jni/lhnet.h Normal file
View file

@ -0,0 +1,52 @@
// Written by Forest Hale 2003-06-15 and placed into public domain.
#ifndef LHNET_H
#define LHNET_H
typedef enum lhnetaddresstype_e
{
LHNETADDRESSTYPE_NONE,
LHNETADDRESSTYPE_LOOP,
LHNETADDRESSTYPE_INET4,
LHNETADDRESSTYPE_INET6
}
lhnetaddresstype_t;
typedef struct lhnetaddress_s
{
lhnetaddresstype_t addresstype;
int port; // used by LHNETADDRESSTYPE_LOOP
unsigned char storage[256]; // sockaddr_in or sockaddr_in6
}
lhnetaddress_t;
int LHNETADDRESS_FromPort(lhnetaddress_t *address, lhnetaddresstype_t addresstype, int port);
int LHNETADDRESS_FromString(lhnetaddress_t *address, const char *string, int defaultport);
int LHNETADDRESS_ToString(const lhnetaddress_t *address, char *string, int stringbuffersize, int includeport);
int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address);
const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *address, char *ifname, size_t ifnamelength);
int LHNETADDRESS_GetPort(const lhnetaddress_t *address);
int LHNETADDRESS_SetPort(lhnetaddress_t *address, int port);
int LHNETADDRESS_Compare(const lhnetaddress_t *address1, const lhnetaddress_t *address2);
typedef struct lhnetsocket_s
{
lhnetaddress_t address;
int inetsocket;
struct lhnetsocket_s *next, *prev;
}
lhnetsocket_t;
void LHNET_Init(void);
void LHNET_Shutdown(void);
int LHNET_DefaultDSCP(int dscp); // < 0: query; >= 0: set (returns previous value)
void LHNET_SleepUntilPacket_Microseconds(int microseconds);
lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address);
void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket);
lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock);
int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *address);
int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *address);
#endif

1828
app/jni/libcurl.c Normal file

File diff suppressed because it is too large Load diff

44
app/jni/libcurl.h Normal file
View file

@ -0,0 +1,44 @@
enum
{
CURLCBSTATUS_OK = 0,
CURLCBSTATUS_FAILED = -1, // failed for generic reason (e.g. buffer too small)
CURLCBSTATUS_ABORTED = -2, // aborted by curl --cancel
CURLCBSTATUS_SERVERERROR = -3, // only used if no HTTP status code is available
CURLCBSTATUS_UNKNOWN = -4 // should never happen
};
typedef void (*curl_callback_t) (int status, size_t length_received, unsigned char *buffer, void *cbdata);
// code is one of the CURLCBSTATUS constants, or the HTTP error code (when > 0).
void Curl_Run(void);
qboolean Curl_Running(void);
qboolean Curl_Begin_ToFile(const char *URL, double maxspeed, const char *name, int loadtype, qboolean forthismap);
qboolean Curl_Begin_ToMemory(const char *URL, double maxspeed, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata);
qboolean Curl_Begin_ToMemory_POST(const char *URL, const char *extraheaders, double maxspeed, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata);
void Curl_Init(void);
void Curl_Init_Commands(void);
void Curl_Shutdown(void);
void Curl_CancelAll(void);
void Curl_Clear_forthismap(void);
qboolean Curl_Have_forthismap(void);
void Curl_Register_predownload(void);
void Curl_ClearRequirements(void);
void Curl_RequireFile(const char *filename);
void Curl_SendRequirements(void);
typedef struct Curl_downloadinfo_s
{
char filename[MAX_QPATH];
double progress;
double speed;
qboolean queued;
}
Curl_downloadinfo_t;
Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info, char *addinfo, size_t addinfolength);
// this may and should be Z_Free()ed
// the result is actually an array
// an additional info string may be returned in additional_info as a
// pointer to a static string (but the argument may be NULL if the caller
// does not care)

805
app/jni/mathlib.c Normal file
View file

@ -0,0 +1,805 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// mathlib.c -- math primitives
#include "quakedef.h"
#include <math.h>
vec3_t vec3_origin = {0,0,0};
float ixtable[4096];
/*-----------------------------------------------------------------*/
float m_bytenormals[NUMVERTEXNORMALS][3] =
{
{-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325},
};
#if 0
unsigned char NormalToByte(const vec3_t n)
{
int i, best;
float bestdistance, distance;
best = 0;
bestdistance = DotProduct (n, m_bytenormals[0]);
for (i = 1;i < NUMVERTEXNORMALS;i++)
{
distance = DotProduct (n, m_bytenormals[i]);
if (distance > bestdistance)
{
bestdistance = distance;
best = i;
}
}
return best;
}
// note: uses byte partly to force unsigned for the validity check
void ByteToNormal(unsigned char num, vec3_t n)
{
if (num < NUMVERTEXNORMALS)
VectorCopy(m_bytenormals[num], n);
else
VectorClear(n); // FIXME: complain?
}
// assumes "src" is normalized
void PerpendicularVector( vec3_t dst, const vec3_t src )
{
// LordHavoc: optimized to death and beyond
int pos;
float minelem;
if (src[0])
{
dst[0] = 0;
if (src[1])
{
dst[1] = 0;
if (src[2])
{
dst[2] = 0;
pos = 0;
minelem = fabs(src[0]);
if (fabs(src[1]) < minelem)
{
pos = 1;
minelem = fabs(src[1]);
}
if (fabs(src[2]) < minelem)
pos = 2;
dst[pos] = 1;
dst[0] -= src[pos] * src[0];
dst[1] -= src[pos] * src[1];
dst[2] -= src[pos] * src[2];
// normalize the result
VectorNormalize(dst);
}
else
dst[2] = 1;
}
else
{
dst[1] = 1;
dst[2] = 0;
}
}
else
{
dst[0] = 1;
dst[1] = 0;
dst[2] = 0;
}
}
#endif
// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
{
// NOTE: this is consistent to AngleVectors applied to AnglesFromVectors
if (forward[0] == 0 && forward[1] == 0)
{
if(forward[2] > 0)
{
VectorSet(right, 0, -1, 0);
VectorSet(up, -1, 0, 0);
}
else
{
VectorSet(right, 0, -1, 0);
VectorSet(up, 1, 0, 0);
}
}
else
{
right[0] = forward[1];
right[1] = -forward[0];
right[2] = 0;
VectorNormalize(right);
up[0] = (-forward[2]*forward[0]);
up[1] = (-forward[2]*forward[1]);
up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
VectorNormalize(up);
}
}
void VectorVectorsDouble(const double *forward, double *right, double *up)
{
if (forward[0] == 0 && forward[1] == 0)
{
if(forward[2] > 0)
{
VectorSet(right, 0, -1, 0);
VectorSet(up, -1, 0, 0);
}
else
{
VectorSet(right, 0, -1, 0);
VectorSet(up, 1, 0, 0);
}
}
else
{
right[0] = forward[1];
right[1] = -forward[0];
right[2] = 0;
VectorNormalize(right);
up[0] = (-forward[2]*forward[0]);
up[1] = (-forward[2]*forward[1]);
up[2] = (forward[0]*forward[0] + forward[1]*forward[1]);
VectorNormalize(up);
}
}
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
{
float t0, t1;
float angle, c, s;
vec3_t vr, vu, vf;
angle = DEG2RAD(degrees);
c = cos(angle);
s = sin(angle);
VectorCopy(dir, vf);
VectorVectors(vf, vr, vu);
t0 = vr[0] * c + vu[0] * -s;
t1 = vr[0] * s + vu[0] * c;
dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
t0 = vr[1] * c + vu[1] * -s;
t1 = vr[1] * s + vu[1] * c;
dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
t0 = vr[2] * c + vu[2] * -s;
t1 = vr[2] * s + vu[2] * c;
dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
}
/*-----------------------------------------------------------------*/
// returns the smallest integer greater than or equal to "value", or 0 if "value" is too big
unsigned int CeilPowerOf2(unsigned int value)
{
unsigned int ceilvalue;
if (value > (1U << (sizeof(int) * 8 - 1)))
return 0;
ceilvalue = 1;
while (ceilvalue < value)
ceilvalue <<= 1;
return ceilvalue;
}
/*-----------------------------------------------------------------*/
void PlaneClassify(mplane_t *p)
{
// for optimized plane comparisons
if (p->normal[0] == 1)
p->type = 0;
else if (p->normal[1] == 1)
p->type = 1;
else if (p->normal[2] == 1)
p->type = 2;
else
p->type = 3;
// for BoxOnPlaneSide
p->signbits = 0;
if (p->normal[0] < 0) // 1
p->signbits |= 1;
if (p->normal[1] < 0) // 2
p->signbits |= 2;
if (p->normal[2] < 0) // 4
p->signbits |= 4;
}
int BoxOnPlaneSide(const vec3_t emins, const vec3_t emaxs, const mplane_t *p)
{
if (p->type < 3)
return ((emaxs[p->type] >= p->dist) | ((emins[p->type] < p->dist) << 1));
switch(p->signbits)
{
default:
case 0: return (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) < p->dist) << 1));
case 1: return (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) < p->dist) << 1));
case 2: return (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) < p->dist) << 1));
case 3: return (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) < p->dist) << 1));
case 4: return (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
case 5: return (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
case 6: return (((p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
case 7: return (((p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2]) >= p->dist) | (((p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2]) < p->dist) << 1));
}
}
#if 0
int BoxOnPlaneSide_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, const vec_t dist)
{
switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
{
default:
case 0: return (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2]) < dist) << 1));
case 1: return (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2]) < dist) << 1));
case 2: return (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) < dist) << 1));
case 3: return (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) < dist) << 1));
case 4: return (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) < dist) << 1));
case 5: return (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2]) < dist) << 1));
case 6: return (((normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) < dist) << 1));
case 7: return (((normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2]) >= dist) | (((normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2]) < dist) << 1));
}
}
#endif
void BoxPlaneCorners(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec3_t outnear, vec3_t outfar)
{
if (p->type < 3)
{
outnear[0] = outnear[1] = outnear[2] = outfar[0] = outfar[1] = outfar[2] = 0;
outnear[p->type] = emins[p->type];
outfar[p->type] = emaxs[p->type];
return;
}
switch(p->signbits)
{
default:
case 0: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
case 1: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
case 2: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
case 3: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
case 4: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
case 5: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
case 6: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
case 7: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
}
}
void BoxPlaneCorners_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec3_t outnear, vec3_t outfar)
{
switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
{
default:
case 0: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
case 1: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emins[2];break;
case 2: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
case 3: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emaxs[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emins[2];break;
case 4: outnear[0] = emaxs[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
case 5: outnear[0] = emins[0];outnear[1] = emaxs[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emins[1];outfar[2] = emaxs[2];break;
case 6: outnear[0] = emaxs[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emins[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
case 7: outnear[0] = emins[0];outnear[1] = emins[1];outnear[2] = emins[2];outfar[0] = emaxs[0];outfar[1] = emaxs[1];outfar[2] = emaxs[2];break;
}
}
void BoxPlaneCornerDistances(const vec3_t emins, const vec3_t emaxs, const mplane_t *p, vec_t *outneardist, vec_t *outfardist)
{
if (p->type < 3)
{
*outneardist = emins[p->type] - p->dist;
*outfardist = emaxs[p->type] - p->dist;
return;
}
switch(p->signbits)
{
default:
case 0: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;break;
case 1: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;break;
case 2: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;break;
case 3: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;break;
case 4: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;break;
case 5: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emaxs[2] - p->dist;break;
case 6: *outneardist = p->normal[0] * emaxs[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emins[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;break;
case 7: *outneardist = p->normal[0] * emins[0] + p->normal[1] * emins[1] + p->normal[2] * emins[2] - p->dist;*outfardist = p->normal[0] * emaxs[0] + p->normal[1] * emaxs[1] + p->normal[2] * emaxs[2] - p->dist;break;
}
}
void BoxPlaneCornerDistances_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec_t *outneardist, vec_t *outfardist)
{
switch((normal[0] < 0) | ((normal[1] < 0) << 1) | ((normal[2] < 0) << 2))
{
default:
case 0: *outneardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2];break;
case 1: *outneardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2];break;
case 2: *outneardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2];break;
case 3: *outneardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2];break;
case 4: *outneardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emins[2];*outfardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emaxs[2];break;
case 5: *outneardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emins[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emaxs[2];break;
case 6: *outneardist = normal[0] * emaxs[0] + normal[1] * emins[1] + normal[2] * emins[2];*outfardist = normal[0] * emins[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];break;
case 7: *outneardist = normal[0] * emins[0] + normal[1] * emins[1] + normal[2] * emins[2];*outfardist = normal[0] * emaxs[0] + normal[1] * emaxs[1] + normal[2] * emaxs[2];break;
}
}
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
{
double angle, sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
if (forward)
{
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
}
if (right || up)
{
if (angles[ROLL])
{
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
if (right)
{
right[0] = -1*(sr*sp*cy+cr*-sy);
right[1] = -1*(sr*sp*sy+cr*cy);
right[2] = -1*(sr*cp);
}
if (up)
{
up[0] = (cr*sp*cy+-sr*-sy);
up[1] = (cr*sp*sy+-sr*cy);
up[2] = cr*cp;
}
}
else
{
if (right)
{
right[0] = sy;
right[1] = -cy;
right[2] = 0;
}
if (up)
{
up[0] = (sp*cy);
up[1] = (sp*sy);
up[2] = cp;
}
}
}
}
void AngleVectorsFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
{
double angle, sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
if (forward)
{
forward[0] = cp*cy;
forward[1] = cp*sy;
forward[2] = -sp;
}
if (left || up)
{
if (angles[ROLL])
{
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
if (left)
{
left[0] = sr*sp*cy+cr*-sy;
left[1] = sr*sp*sy+cr*cy;
left[2] = sr*cp;
}
if (up)
{
up[0] = cr*sp*cy+-sr*-sy;
up[1] = cr*sp*sy+-sr*cy;
up[2] = cr*cp;
}
}
else
{
if (left)
{
left[0] = -sy;
left[1] = cy;
left[2] = 0;
}
if (up)
{
up[0] = sp*cy;
up[1] = sp*sy;
up[2] = cp;
}
}
}
}
// LordHavoc: calculates pitch/yaw/roll angles from forward and up vectors
void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qboolean flippitch)
{
if (forward[0] == 0 && forward[1] == 0)
{
if(forward[2] > 0)
{
angles[PITCH] = -M_PI * 0.5;
angles[YAW] = up ? atan2(-up[1], -up[0]) : 0;
}
else
{
angles[PITCH] = M_PI * 0.5;
angles[YAW] = up ? atan2(up[1], up[0]) : 0;
}
angles[ROLL] = 0;
}
else
{
angles[YAW] = atan2(forward[1], forward[0]);
angles[PITCH] = -atan2(forward[2], sqrt(forward[0]*forward[0] + forward[1]*forward[1]));
// note: we know that angles[PITCH] is in ]-pi/2..pi/2[ due to atan2(anything, positive)
if (up)
{
vec_t cp = cos(angles[PITCH]), sp = sin(angles[PITCH]);
// note: we know cp > 0, due to the range angles[pitch] is in
vec_t cy = cos(angles[YAW]), sy = sin(angles[YAW]);
vec3_t tleft, tup;
tleft[0] = -sy;
tleft[1] = cy;
tleft[2] = 0;
tup[0] = sp*cy;
tup[1] = sp*sy;
tup[2] = cp;
angles[ROLL] = -atan2(DotProduct(up, tleft), DotProduct(up, tup));
// for up == '0 0 1', this is
// angles[ROLL] = -atan2(0, cp);
// which is 0
}
else
angles[ROLL] = 0;
// so no up vector is equivalent to '1 0 0'!
}
// now convert radians to degrees, and make all values positive
VectorScale(angles, 180.0 / M_PI, angles);
if (flippitch)
angles[PITCH] *= -1;
if (angles[PITCH] < 0) angles[PITCH] += 360;
if (angles[YAW] < 0) angles[YAW] += 360;
if (angles[ROLL] < 0) angles[ROLL] += 360;
#if 0
{
// debugging code
vec3_t tforward, tleft, tup, nforward, nup;
VectorCopy(forward, nforward);
VectorNormalize(nforward);
if (up)
{
VectorCopy(up, nup);
VectorNormalize(nup);
AngleVectors(angles, tforward, tleft, tup);
if (VectorDistance(tforward, nforward) > 0.01 || VectorDistance(tup, nup) > 0.01)
{
Con_Printf("vectoangles('%f %f %f', '%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], nup[0], nup[1], nup[2], angles[0], angles[1], angles[2]);
Con_Printf("^3But that is '%f %f %f', '%f %f %f'\n", tforward[0], tforward[1], tforward[2], tup[0], tup[1], tup[2]);
}
}
else
{
AngleVectors(angles, tforward, tleft, tup);
if (VectorDistance(tforward, nforward) > 0.01)
{
Con_Printf("vectoangles('%f %f %f') = %f %f %f\n", nforward[0], nforward[1], nforward[2], angles[0], angles[1], angles[2]);
Con_Printf("^3But that is '%f %f %f'\n", tforward[0], tforward[1], tforward[2]);
}
}
}
#endif
}
#if 0
void AngleMatrix (const vec3_t angles, const vec3_t translate, vec_t matrix[][4])
{
double angle, sr, sp, sy, cr, cp, cy;
angle = angles[YAW] * (M_PI*2 / 360);
sy = sin(angle);
cy = cos(angle);
angle = angles[PITCH] * (M_PI*2 / 360);
sp = sin(angle);
cp = cos(angle);
angle = angles[ROLL] * (M_PI*2 / 360);
sr = sin(angle);
cr = cos(angle);
matrix[0][0] = cp*cy;
matrix[0][1] = sr*sp*cy+cr*-sy;
matrix[0][2] = cr*sp*cy+-sr*-sy;
matrix[0][3] = translate[0];
matrix[1][0] = cp*sy;
matrix[1][1] = sr*sp*sy+cr*cy;
matrix[1][2] = cr*sp*sy+-sr*cy;
matrix[1][3] = translate[1];
matrix[2][0] = -sp;
matrix[2][1] = sr*cp;
matrix[2][2] = cr*cp;
matrix[2][3] = translate[2];
}
#endif
// LordHavoc: renamed this to Length, and made the normal one a #define
float VectorNormalizeLength (vec3_t v)
{
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
length = sqrt (length);
if (length)
{
ilength = 1/length;
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
return length;
}
/*
================
R_ConcatRotations
================
*/
void R_ConcatRotations (const float in1[3*3], const float in2[3*3], float out[3*3])
{
out[0*3+0] = in1[0*3+0] * in2[0*3+0] + in1[0*3+1] * in2[1*3+0] + in1[0*3+2] * in2[2*3+0];
out[0*3+1] = in1[0*3+0] * in2[0*3+1] + in1[0*3+1] * in2[1*3+1] + in1[0*3+2] * in2[2*3+1];
out[0*3+2] = in1[0*3+0] * in2[0*3+2] + in1[0*3+1] * in2[1*3+2] + in1[0*3+2] * in2[2*3+2];
out[1*3+0] = in1[1*3+0] * in2[0*3+0] + in1[1*3+1] * in2[1*3+0] + in1[1*3+2] * in2[2*3+0];
out[1*3+1] = in1[1*3+0] * in2[0*3+1] + in1[1*3+1] * in2[1*3+1] + in1[1*3+2] * in2[2*3+1];
out[1*3+2] = in1[1*3+0] * in2[0*3+2] + in1[1*3+1] * in2[1*3+2] + in1[1*3+2] * in2[2*3+2];
out[2*3+0] = in1[2*3+0] * in2[0*3+0] + in1[2*3+1] * in2[1*3+0] + in1[2*3+2] * in2[2*3+0];
out[2*3+1] = in1[2*3+0] * in2[0*3+1] + in1[2*3+1] * in2[1*3+1] + in1[2*3+2] * in2[2*3+1];
out[2*3+2] = in1[2*3+0] * in2[0*3+2] + in1[2*3+1] * in2[1*3+2] + in1[2*3+2] * in2[2*3+2];
}
/*
================
R_ConcatTransforms
================
*/
void R_ConcatTransforms (const float in1[3*4], const float in2[3*4], float out[3*4])
{
out[0*4+0] = in1[0*4+0] * in2[0*4+0] + in1[0*4+1] * in2[1*4+0] + in1[0*4+2] * in2[2*4+0];
out[0*4+1] = in1[0*4+0] * in2[0*4+1] + in1[0*4+1] * in2[1*4+1] + in1[0*4+2] * in2[2*4+1];
out[0*4+2] = in1[0*4+0] * in2[0*4+2] + in1[0*4+1] * in2[1*4+2] + in1[0*4+2] * in2[2*4+2];
out[0*4+3] = in1[0*4+0] * in2[0*4+3] + in1[0*4+1] * in2[1*4+3] + in1[0*4+2] * in2[2*4+3] + in1[0*4+3];
out[1*4+0] = in1[1*4+0] * in2[0*4+0] + in1[1*4+1] * in2[1*4+0] + in1[1*4+2] * in2[2*4+0];
out[1*4+1] = in1[1*4+0] * in2[0*4+1] + in1[1*4+1] * in2[1*4+1] + in1[1*4+2] * in2[2*4+1];
out[1*4+2] = in1[1*4+0] * in2[0*4+2] + in1[1*4+1] * in2[1*4+2] + in1[1*4+2] * in2[2*4+2];
out[1*4+3] = in1[1*4+0] * in2[0*4+3] + in1[1*4+1] * in2[1*4+3] + in1[1*4+2] * in2[2*4+3] + in1[1*4+3];
out[2*4+0] = in1[2*4+0] * in2[0*4+0] + in1[2*4+1] * in2[1*4+0] + in1[2*4+2] * in2[2*4+0];
out[2*4+1] = in1[2*4+0] * in2[0*4+1] + in1[2*4+1] * in2[1*4+1] + in1[2*4+2] * in2[2*4+1];
out[2*4+2] = in1[2*4+0] * in2[0*4+2] + in1[2*4+1] * in2[1*4+2] + in1[2*4+2] * in2[2*4+2];
out[2*4+3] = in1[2*4+0] * in2[0*4+3] + in1[2*4+1] * in2[1*4+3] + in1[2*4+2] * in2[2*4+3] + in1[2*4+3];
}
float RadiusFromBounds (const vec3_t mins, const vec3_t maxs)
{
vec3_t m1, m2;
VectorMultiply(mins, mins, m1);
VectorMultiply(maxs, maxs, m2);
return sqrt(max(m1[0], m2[0]) + max(m1[1], m2[1]) + max(m1[2], m2[2]));
}
float RadiusFromBoundsAndOrigin (const vec3_t mins, const vec3_t maxs, const vec3_t origin)
{
vec3_t m1, m2;
VectorSubtract(mins, origin, m1);VectorMultiply(m1, m1, m1);
VectorSubtract(maxs, origin, m2);VectorMultiply(m2, m2, m2);
return sqrt(max(m1[0], m2[0]) + max(m1[1], m2[1]) + max(m1[2], m2[2]));
}
void Mathlib_Init(void)
{
int a;
// LordHavoc: setup 1.0f / N table for quick recipricols of integers
ixtable[0] = 0;
for (a = 1;a < 4096;a++)
ixtable[a] = 1.0f / a;
}
#include "matrixlib.h"
void Matrix4x4_Print(const matrix4x4_t *in)
{
Con_Printf("%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n"
, in->m[0][0], in->m[0][1], in->m[0][2], in->m[0][3]
, in->m[1][0], in->m[1][1], in->m[1][2], in->m[1][3]
, in->m[2][0], in->m[2][1], in->m[2][2], in->m[2][3]
, in->m[3][0], in->m[3][1], in->m[3][2], in->m[3][3]);
}
int Math_atov(const char *s, prvm_vec3_t out)
{
int i;
VectorClear(out);
if (*s == '\'')
s++;
for (i = 0;i < 3;i++)
{
while (*s == ' ' || *s == '\t')
s++;
out[i] = atof (s);
if (out[i] == 0 && *s != '-' && *s != '+' && (*s < '0' || *s > '9'))
break; // not a number
while (*s && *s != ' ' && *s !='\t' && *s != '\'')
s++;
if (*s == '\'')
break;
}
return i;
}
void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f)
{
int i;
VectorCopy(point3f, mins);
VectorCopy(point3f, maxs);
for (i = 1, point3f += 3;i < numpoints;i++, point3f += 3)
{
mins[0] = min(mins[0], point3f[0]);maxs[0] = max(maxs[0], point3f[0]);
mins[1] = min(mins[1], point3f[1]);maxs[1] = max(maxs[1], point3f[1]);
mins[2] = min(mins[2], point3f[2]);maxs[2] = max(maxs[2], point3f[2]);
}
}
// LordHavoc: this has to be done right or you get severe precision breakdown
int LoopingFrameNumberFromDouble(double t, int loopframes)
{
if (loopframes)
return (int)(t - floor(t/loopframes)*loopframes);
else
return (int)t;
}

305
app/jni/mathlib.h Normal file
View file

@ -0,0 +1,305 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// mathlib.h
#ifndef MATHLIB_H
#define MATHLIB_H
#include "qtypes.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
struct mplane_s;
extern vec3_t vec3_origin;
#define float_nanmask (0x7F800000)
#define double_nanmask (0x7FF8000000000000)
#define FLOAT_IS_NAN(x) (((*(int *)&x)&float_nanmask)==float_nanmask)
#define DOUBLE_IS_NAN(x) (((*(long long *)&x)&double_nanmask)==double_nanmask)
#ifdef VEC_64
#define VEC_IS_NAN(x) DOUBLE_IS_NAN(x)
#else
#define VEC_IS_NAN(x) FLOAT_IS_NAN(x)
#endif
#ifdef PRVM_64
#define PRVM_IS_NAN(x) DOUBLE_IS_NAN(x)
#else
#define PRVM_IS_NAN(x) FLOAT_IS_NAN(x)
#endif
#define bound(min,num,max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
#ifndef min
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
#endif
/// LordHavoc: this function never returns exactly MIN or exactly MAX, because
/// of a QuakeC bug in id1 where the line
/// self.nextthink = self.nexthink + random() * 0.5;
/// can result in 0 (self.nextthink is 0 at this point in the code to begin
/// with), causing "stone monsters" that never spawned properly, also MAX is
/// avoided because some people use random() as an index into arrays or for
/// loop conditions, where hitting exactly MAX may be a fatal error
#define lhrandom(MIN,MAX) (((double)(rand() + 0.5) / ((double)RAND_MAX + 1)) * ((MAX)-(MIN)) + (MIN))
#define invpow(base,number) (log(number) / log(base))
/// returns log base 2 of "n"
/// \WARNING: "n" MUST be a power of 2!
#define log2i(n) ((((n) & 0xAAAAAAAA) != 0 ? 1 : 0) | (((n) & 0xCCCCCCCC) != 0 ? 2 : 0) | (((n) & 0xF0F0F0F0) != 0 ? 4 : 0) | (((n) & 0xFF00FF00) != 0 ? 8 : 0) | (((n) & 0xFFFF0000) != 0 ? 16 : 0))
/// \TODO: what is this function supposed to do?
#define bit2i(n) log2i((n) << 1)
/// boolean XOR (why doesn't C have the ^^ operator for this purpose?)
#define boolxor(a,b) (!(a) != !(b))
/// returns the smallest integer greater than or equal to "value", or 0 if "value" is too big
unsigned int CeilPowerOf2(unsigned int value);
#define DEG2RAD(a) ((a) * ((float) M_PI / 180.0f))
#define RAD2DEG(a) ((a) * (180.0f / (float) M_PI))
#define ANGLEMOD(a) ((a) - 360.0 * floor((a) / 360.0))
#define DotProduct2(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1])
#define Vector2Clear(a) ((a)[0]=(a)[1]=0)
#define Vector2Compare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1]))
#define Vector2Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1])
#define Vector2Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]))
#define Vector2Set(a,b,c) ((a)[0]=(b),(a)[1]=(c))
#define Vector2Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale))
#define Vector2Normalize2(v,dest) {float ilength = (float) sqrt(DotProduct2((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;}
#define DotProduct4(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]+(a)[3]*(b)[3])
#define Vector4Clear(a) ((a)[0]=(a)[1]=(a)[2]=(a)[3]=0)
#define Vector4Compare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1])&&((a)[2]==(b)[2])&&((a)[3]==(b)[3]))
#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
#define Vector4Negate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]),(b)[3]=-((a)[3]))
#define Vector4Set(a,b,c,d,e) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d),(a)[3]=(e))
#define Vector4Normalize2(v,dest) {float ilength = (float) sqrt(DotProduct4((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;dest[2] = (v)[2] * ilength;dest[3] = (v)[3] * ilength;}
#define Vector4Subtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
#define Vector4Add(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
#define Vector4Scale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale),(out)[3] = (in)[3] * (scale))
#define Vector4Multiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1],(c)[2]=(a)[2]*(b)[2],(c)[3]=(a)[3]*(b)[3])
#define Vector4MA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2],(c)[3] = (a)[3] + (scale) * (b)[3])
#define Vector4Lerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]), (c)[3] = (v1)[3] + (lerp) * ((v2)[3] - (v1)[3]))
#define VectorNegate(a,b) ((b)[0]=-((a)[0]),(b)[1]=-((a)[1]),(b)[2]=-((a)[2]))
#define VectorSet(a,b,c,d) ((a)[0]=(b),(a)[1]=(c),(a)[2]=(d))
#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
#define VectorMultiply(a,b,c) ((c)[0]=(a)[0]*(b)[0],(c)[1]=(a)[1]*(b)[1],(c)[2]=(a)[2]*(b)[2])
#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
#define VectorNormalize(v) {float ilength = (float) sqrt(DotProduct((v),(v)));if (ilength) ilength = 1.0f / ilength;(v)[0] *= ilength;(v)[1] *= ilength;(v)[2] *= ilength;}
#define VectorNormalize2(v,dest) {float ilength = (float) sqrt(DotProduct((v),(v)));if (ilength) ilength = 1.0f / ilength;dest[0] = (v)[0] * ilength;dest[1] = (v)[1] * ilength;dest[2] = (v)[2] * ilength;}
#define VectorNormalizeDouble(v) {double ilength = sqrt(DotProduct((v),(v)));if (ilength) ilength = 1.0 / ilength;(v)[0] *= ilength;(v)[1] *= ilength;(v)[2] *= ilength;}
#define VectorDistance2(a, b) (((a)[0] - (b)[0]) * ((a)[0] - (b)[0]) + ((a)[1] - (b)[1]) * ((a)[1] - (b)[1]) + ((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))
#define VectorDistance(a, b) (sqrt(VectorDistance2(a,b)))
#define VectorLength(a) (sqrt((double)DotProduct(a, a)))
#define VectorLength2(a) (DotProduct(a, a))
#define VectorScale(in, scale, out) ((out)[0] = (in)[0] * (scale),(out)[1] = (in)[1] * (scale),(out)[2] = (in)[2] * (scale))
#define VectorScaleCast(in, scale, outtype, out) ((out)[0] = (outtype) ((in)[0] * (scale)),(out)[1] = (outtype) ((in)[1] * (scale)),(out)[2] = (outtype) ((in)[2] * (scale)))
#define VectorCompare(a,b) (((a)[0]==(b)[0])&&((a)[1]==(b)[1])&&((a)[2]==(b)[2]))
#define VectorMA(a, scale, b, c) ((c)[0] = (a)[0] + (scale) * (b)[0],(c)[1] = (a)[1] + (scale) * (b)[1],(c)[2] = (a)[2] + (scale) * (b)[2])
#define VectorM(scale1, b1, c) ((c)[0] = (scale1) * (b1)[0],(c)[1] = (scale1) * (b1)[1],(c)[2] = (scale1) * (b1)[2])
#define VectorMAM(scale1, b1, scale2, b2, c) ((c)[0] = (scale1) * (b1)[0] + (scale2) * (b2)[0],(c)[1] = (scale1) * (b1)[1] + (scale2) * (b2)[1],(c)[2] = (scale1) * (b1)[2] + (scale2) * (b2)[2])
#define VectorMAMAM(scale1, b1, scale2, b2, scale3, b3, c) ((c)[0] = (scale1) * (b1)[0] + (scale2) * (b2)[0] + (scale3) * (b3)[0],(c)[1] = (scale1) * (b1)[1] + (scale2) * (b2)[1] + (scale3) * (b3)[1],(c)[2] = (scale1) * (b1)[2] + (scale2) * (b2)[2] + (scale3) * (b3)[2])
#define VectorMAMAMAM(scale1, b1, scale2, b2, scale3, b3, scale4, b4, c) ((c)[0] = (scale1) * (b1)[0] + (scale2) * (b2)[0] + (scale3) * (b3)[0] + (scale4) * (b4)[0],(c)[1] = (scale1) * (b1)[1] + (scale2) * (b2)[1] + (scale3) * (b3)[1] + (scale4) * (b4)[1],(c)[2] = (scale1) * (b1)[2] + (scale2) * (b2)[2] + (scale3) * (b3)[2] + (scale4) * (b4)[2])
#define VectorRandom(v) do{(v)[0] = lhrandom(-1, 1);(v)[1] = lhrandom(-1, 1);(v)[2] = lhrandom(-1, 1);}while(DotProduct(v, v) > 1)
#define VectorLerp(v1,lerp,v2,c) ((c)[0] = (v1)[0] + (lerp) * ((v2)[0] - (v1)[0]), (c)[1] = (v1)[1] + (lerp) * ((v2)[1] - (v1)[1]), (c)[2] = (v1)[2] + (lerp) * ((v2)[2] - (v1)[2]))
#define VectorReflect(a,r,b,c) do{double d;d = DotProduct((a), (b)) * -(1.0 + (r));VectorMA((a), (d), (b), (c));}while(0)
#define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2])
#define BoxInsideBox(a,b,c,d) ((a)[0] >= (c)[0] && (b)[0] <= (d)[0] && (a)[1] >= (c)[1] && (b)[1] <= (d)[1] && (a)[2] >= (c)[2] && (b)[2] <= (d)[2])
#define TriangleBBoxOverlapsBox(a,b,c,d,e) (min((a)[0], min((b)[0], (c)[0])) < (e)[0] && max((a)[0], max((b)[0], (c)[0])) > (d)[0] && min((a)[1], min((b)[1], (c)[1])) < (e)[1] && max((a)[1], max((b)[1], (c)[1])) > (d)[1] && min((a)[2], min((b)[2], (c)[2])) < (e)[2] && max((a)[2], max((b)[2], (c)[2])) > (d)[2])
#define TriangleNormal(a,b,c,n) ( \
(n)[0] = ((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1]), \
(n)[1] = ((a)[2] - (b)[2]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[2] - (b)[2]), \
(n)[2] = ((a)[0] - (b)[0]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[0] - (b)[0]) \
)
/*! Fast PointInfrontOfTriangle.
* subtracts v1 from v0 and v2, combined into a crossproduct, combined with a
* dotproduct of the light location relative to the first point of the
* triangle (any point works, since any triangle is obviously flat), and
* finally a comparison to determine if the light is infront of the triangle
* (the goal of this statement) we do not need to normalize the surface
* normal because both sides of the comparison use it, therefore they are
* both multiplied the same amount... furthermore a subtract can be done on
* the point to eliminate one dotproduct
* this is ((p - a) * cross(a-b,c-b))
*/
#define PointInfrontOfTriangle(p,a,b,c) \
( ((p)[0] - (a)[0]) * (((a)[1] - (b)[1]) * ((c)[2] - (b)[2]) - ((a)[2] - (b)[2]) * ((c)[1] - (b)[1])) \
+ ((p)[1] - (a)[1]) * (((a)[2] - (b)[2]) * ((c)[0] - (b)[0]) - ((a)[0] - (b)[0]) * ((c)[2] - (b)[2])) \
+ ((p)[2] - (a)[2]) * (((a)[0] - (b)[0]) * ((c)[1] - (b)[1]) - ((a)[1] - (b)[1]) * ((c)[0] - (b)[0])) > 0)
#if 0
// readable version, kept only for explanatory reasons
int PointInfrontOfTriangle(const float *p, const float *a, const float *b, const float *c)
{
float dir0[3], dir1[3], normal[3];
// calculate two mostly perpendicular edge directions
VectorSubtract(a, b, dir0);
VectorSubtract(c, b, dir1);
// we have two edge directions, we can calculate a third vector from
// them, which is the direction of the surface normal (its magnitude
// is not 1 however)
CrossProduct(dir0, dir1, normal);
// compare distance of light along normal, with distance of any point
// of the triangle along the same normal (the triangle is planar,
// I.E. flat, so all points give the same answer)
return DotProduct(p, normal) > DotProduct(a, normal);
}
#endif
#define lhcheeserand() (seed = (seed * 987211u) ^ (seed >> 13u) ^ 914867)
#define lhcheeserandom(MIN,MAX) ((double)(lhcheeserand() + 0.5) / ((double)4096.0*1024.0*1024.0) * ((MAX)-(MIN)) + (MIN))
#define VectorCheeseRandom(v) do{(v)[0] = lhcheeserandom(-1, 1);(v)[1] = lhcheeserandom(-1, 1);(v)[2] = lhcheeserandom(-1, 1);}while(DotProduct(v, v) > 1)
/*
// LordHavoc: quaternion math, untested, don't know if these are correct,
// need to add conversion to/from matrices
// LordHavoc: later note: the matrix faq is useful: http://skal.planet-d.net/demo/matrixfaq.htm
// LordHavoc: these are probably very wrong and I'm not sure I care, not used by anything
// returns length of quaternion
#define qlen(a) ((float) sqrt((a)[0]*(a)[0]+(a)[1]*(a)[1]+(a)[2]*(a)[2]+(a)[3]*(a)[3]))
// returns squared length of quaternion
#define qlen2(a) ((a)[0]*(a)[0]+(a)[1]*(a)[1]+(a)[2]*(a)[2]+(a)[3]*(a)[3])
// makes a quaternion from x, y, z, and a rotation angle (in degrees)
#define QuatMake(x,y,z,r,c)\
{\
if (r == 0)\
{\
(c)[0]=(float) ((x) * (1.0f / 0.0f));\
(c)[1]=(float) ((y) * (1.0f / 0.0f));\
(c)[2]=(float) ((z) * (1.0f / 0.0f));\
(c)[3]=(float) 1.0f;\
}\
else\
{\
float r2 = (r) * 0.5 * (M_PI / 180);\
float r2is = 1.0f / sin(r2);\
(c)[0]=(float) ((x)/r2is);\
(c)[1]=(float) ((y)/r2is);\
(c)[2]=(float) ((z)/r2is);\
(c)[3]=(float) (cos(r2));\
}\
}
// makes a quaternion from a vector and a rotation angle (in degrees)
#define QuatFromVec(a,r,c) QuatMake((a)[0],(a)[1],(a)[2],(r))
// copies a quaternion
#define QuatCopy(a,c) {(c)[0]=(a)[0];(c)[1]=(a)[1];(c)[2]=(a)[2];(c)[3]=(a)[3];}
#define QuatSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];(c)[3]=(a)[3]-(b)[3];}
#define QuatAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];(c)[3]=(a)[3]+(b)[3];}
#define QuatScale(a,b,c) {(c)[0]=(a)[0]*b;(c)[1]=(a)[1]*b;(c)[2]=(a)[2]*b;(c)[3]=(a)[3]*b;}
// FIXME: this is wrong, do some more research on quaternions
//#define QuatMultiply(a,b,c) {(c)[0]=(a)[0]*(b)[0];(c)[1]=(a)[1]*(b)[1];(c)[2]=(a)[2]*(b)[2];(c)[3]=(a)[3]*(b)[3];}
// FIXME: this is wrong, do some more research on quaternions
//#define QuatMultiplyAdd(a,b,d,c) {(c)[0]=(a)[0]*(b)[0]+d[0];(c)[1]=(a)[1]*(b)[1]+d[1];(c)[2]=(a)[2]*(b)[2]+d[2];(c)[3]=(a)[3]*(b)[3]+d[3];}
#define qdist(a,b) ((float) sqrt(((b)[0]-(a)[0])*((b)[0]-(a)[0])+((b)[1]-(a)[1])*((b)[1]-(a)[1])+((b)[2]-(a)[2])*((b)[2]-(a)[2])+((b)[3]-(a)[3])*((b)[3]-(a)[3])))
#define qdist2(a,b) (((b)[0]-(a)[0])*((b)[0]-(a)[0])+((b)[1]-(a)[1])*((b)[1]-(a)[1])+((b)[2]-(a)[2])*((b)[2]-(a)[2])+((b)[3]-(a)[3])*((b)[3]-(a)[3]))
*/
#define VectorCopy4(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];(b)[3]=(a)[3];}
vec_t Length (vec3_t v);
/// returns vector length
float VectorNormalizeLength (vec3_t v);
/// returns vector length
float VectorNormalizeLength2 (vec3_t v, vec3_t dest);
#define NUMVERTEXNORMALS 162
extern float m_bytenormals[NUMVERTEXNORMALS][3];
unsigned char NormalToByte(const vec3_t n);
void ByteToNormal(unsigned char num, vec3_t n);
void R_ConcatRotations (const float in1[3*3], const float in2[3*3], float out[3*3]);
void R_ConcatTransforms (const float in1[3*4], const float in2[3*4], float out[3*4]);
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
/// LordHavoc: proper matrix version of AngleVectors
void AngleVectorsFLU (const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up);
/// LordHavoc: builds a [3][4] matrix
void AngleMatrix (const vec3_t angles, const vec3_t translate, vec_t matrix[][4]);
/// LordHavoc: calculates pitch/yaw/roll angles from forward and up vectors
void AnglesFromVectors (vec3_t angles, const vec3_t forward, const vec3_t up, qboolean flippitch);
/// LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up);
void VectorVectorsDouble(const double *forward, double *right, double *up);
void PlaneClassify(struct mplane_s *p);
int BoxOnPlaneSide(const vec3_t emins, const vec3_t emaxs, const struct mplane_s *p);
int BoxOnPlaneSide_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, const vec_t dist);
void BoxPlaneCorners(const vec3_t emins, const vec3_t emaxs, const struct mplane_s *p, vec3_t outnear, vec3_t outfar);
void BoxPlaneCorners_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec3_t outnear, vec3_t outfar);
void BoxPlaneCornerDistances(const vec3_t emins, const vec3_t emaxs, const struct mplane_s *p, vec_t *outnear, vec_t *outfar);
void BoxPlaneCornerDistances_Separate(const vec3_t emins, const vec3_t emaxs, const vec3_t normal, vec_t *outnear, vec_t *outfar);
#define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal))
#define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist)
/// LordHavoc: minimal plane structure
typedef struct tinyplane_s
{
float normal[3], dist;
}
tinyplane_t;
typedef struct tinydoubleplane_s
{
double normal[3], dist;
}
tinydoubleplane_t;
void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees);
float RadiusFromBounds (const vec3_t mins, const vec3_t maxs);
float RadiusFromBoundsAndOrigin (const vec3_t mins, const vec3_t maxs, const vec3_t origin);
struct matrix4x4_s;
/// print a matrix to the console
void Matrix4x4_Print(const struct matrix4x4_s *in);
int Math_atov(const char *s, prvm_vec3_t out);
void BoxFromPoints(vec3_t mins, vec3_t maxs, int numpoints, vec_t *point3f);
int LoopingFrameNumberFromDouble(double t, int loopframes);
void Mathlib_Init(void);
#endif

Some files were not shown because too many files have changed in this diff Show more