summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS11
-rwxr-xr-xem++4
-rwxr-xr-xem-config24
-rwxr-xr-xemar4
-rwxr-xr-xemcc344
-rwxr-xr-xemld60
-rwxr-xr-xemscripten.py17
-rw-r--r--settings.py8
-rw-r--r--src/analyzer.js128
-rw-r--r--src/compiler.js11
-rw-r--r--src/experimental/stringCache.diff147
-rw-r--r--src/gl-matrix.js1952
-rw-r--r--src/intertyper.js45
-rw-r--r--src/jsifier.js93
-rw-r--r--src/library.js393
-rw-r--r--src/library_browser.js346
-rw-r--r--src/library_egl.js26
-rw-r--r--src/library_gc.js167
-rw-r--r--src/library_gl.js2588
-rw-r--r--src/library_glut.js438
-rw-r--r--src/library_sdl.js1209
-rw-r--r--src/library_xlib.js24
-rw-r--r--src/long.js1633
-rw-r--r--src/modules.js5
-rw-r--r--src/parseTools.js158
-rw-r--r--src/postamble.js56
-rw-r--r--src/preamble.js101
-rw-r--r--src/runtime.js78
-rw-r--r--src/settings.js25
-rw-r--r--src/shell.html72
-rw-r--r--src/shell.js47
-rw-r--r--src/utility.js22
-rw-r--r--system/include/SDL/SDL_keycode.h4
-rw-r--r--system/include/X11/X.h717
-rw-r--r--system/include/X11/Xatom.h79
-rw-r--r--system/include/X11/Xfuncproto.h127
-rw-r--r--system/include/X11/Xlib.h4023
-rw-r--r--system/include/X11/Xosdefs.h116
-rw-r--r--system/include/X11/Xutil.h826
-rw-r--r--system/include/X11/keysym.h73
-rw-r--r--system/include/X11/keysymdef.h2389
-rw-r--r--system/include/emscripten.h45
-rw-r--r--system/include/emscripten/emscripten.h145
-rw-r--r--system/include/features.h3
-rw-r--r--system/include/gc.h50
-rw-r--r--system/include/libc/stdio.h9
-rw-r--r--system/include/libc/sys/_default_fcntl.h5
-rw-r--r--system/include/libc/sys/dirent.h4
-rw-r--r--system/include/libc/sys/types.h11
-rw-r--r--system/include/libcxx/ios14
-rw-r--r--system/include/net/if.h61
-rw-r--r--system/include/net/netinet/in.h5
-rw-r--r--system/include/net/netinet/tcp.h246
-rw-r--r--system/include/netdb.h55
-rw-r--r--system/include/pty.h6
-rw-r--r--system/include/sys/ioctl.h20
-rw-r--r--system/include/sys/socket.h14
-rw-r--r--system/include/sys/socketvar.h3
-rw-r--r--system/include/sys/statvfs.h2
-rw-r--r--system/lib/libcxx/Makefile3
-rw-r--r--tests/aniso.c210
-rw-r--r--tests/aniso.pngbin0 -> 35041 bytes
-rw-r--r--tests/bloom.ddsbin0 -> 32896 bytes
-rw-r--r--tests/browser_gc.cpp96
-rw-r--r--tests/browser_harness.html29
-rw-r--r--tests/cases/aliasbitcastdollar.ll27
-rw-r--r--tests/cases/complexphi.ll4
-rw-r--r--tests/cases/dash.ll18
-rw-r--r--tests/cases/emptystruct.ll21
-rw-r--r--tests/cases/frem.ll13
-rw-r--r--tests/cases/frem.txt1
-rw-r--r--tests/cases/funcptr.ll27
-rw-r--r--tests/cases/funcptr.txt1
-rw-r--r--tests/cases/phientryimplicitmoar.ll28
-rw-r--r--tests/cases/phientryimplicitmoar.txt6
-rw-r--r--tests/cases/phinonexist.ll25
-rw-r--r--tests/cases/quotedlabel.ll19
-rw-r--r--tests/cases/subnums.ll18
-rw-r--r--tests/cases/subnums.txt1
-rw-r--r--tests/cases/uadd_overflow.ll25
-rw-r--r--tests/cases/uadd_overflow.txt1
-rw-r--r--tests/cube2hash/Makefile14
-rw-r--r--tests/cube2hash/cube2crypto.c23
-rw-r--r--tests/cube2hash/cube2crypto.h9
-rw-r--r--tests/cube2hash/hashstring.cpp28
-rw-r--r--tests/cube2hash/readme.txt27
-rw-r--r--tests/cube2hash/tiger.c175
-rw-r--r--tests/cube2hash/tiger.h12
-rw-r--r--tests/cube2hash/util.h22
-rw-r--r--tests/cube2md5.cpp28
-rw-r--r--tests/cube2md5.ok264
-rw-r--r--tests/cube2md5.txt37
-rw-r--r--tests/cube_explosion.c235
-rw-r--r--tests/cubegeom.c295
-rw-r--r--tests/cubegeom_color.c295
-rw-r--r--tests/cubegeom_color2.c299
-rw-r--r--tests/cubegeom_fog.c307
-rw-r--r--tests/cubegeom_mt.c300
-rw-r--r--tests/cubegeom_normal.c295
-rw-r--r--tests/cubegeom_normal_dap.c291
-rw-r--r--tests/cubegeom_normal_dap_far.c289
-rw-r--r--tests/cubegeom_normal_dap_far_glda.c280
-rw-r--r--tests/cubegeom_normal_dap_far_glda_quad.c280
-rw-r--r--tests/cubegeom_normal_dap_far_range.c289
-rw-r--r--tests/cubegeom_pre.c307
-rw-r--r--tests/cubegeom_pre2.c348
-rw-r--r--tests/cubegeom_pre3.c348
-rw-r--r--tests/cubegeom_texturematrix.c312
-rw-r--r--tests/emscripten_api_browser.cpp88
-rw-r--r--tests/emscripten_fs_api_browser.cpp69
-rw-r--r--tests/env/output.txt2
-rw-r--r--tests/fcntl/src.c2
-rw-r--r--tests/float_tex.cpp136
-rw-r--r--tests/float_tex.pngbin0 -> 19944 bytes
-rw-r--r--tests/freetype/main_2.c135
-rw-r--r--tests/freetype/main_3.c184
-rw-r--r--tests/freetype/ref_2.txt33
-rw-r--r--tests/freetype/ref_3.txt33
-rw-r--r--tests/freetype/ref_4.txt32
-rw-r--r--tests/gears.pngbin0 -> 7832 bytes
-rw-r--r--tests/gl/LICENSE.TXT11
-rw-r--r--tests/gl/sdl_ogl.c202
-rw-r--r--tests/gl/tutorial2.frag11
-rw-r--r--tests/gl/tutorial2.vert19
-rw-r--r--tests/gl_matrix_identity.c129
-rw-r--r--tests/gl_ps.c230
-rw-r--r--tests/gl_ps.pngbin0 -> 203535 bytes
-rw-r--r--tests/glbook/CH02_HelloTriangle.pngbin0 -> 1009 bytes
-rw-r--r--tests/glbook/CH08_SimpleVertexShader.pngbin0 -> 1600 bytes
-rw-r--r--tests/glbook/CH09_SimpleTexture2D.pngbin0 -> 1943 bytes
-rw-r--r--tests/glbook/CH09_TextureCubemap.pngbin0 -> 3209 bytes
-rw-r--r--tests/glbook/CH09_TextureWrap.pngbin0 -> 1812 bytes
-rw-r--r--tests/glbook/CH10_MultiTexture.pngbin0 -> 59495 bytes
-rw-r--r--tests/glbook/CH13_ParticleSystem.pngbin0 -> 11936 bytes
-rw-r--r--tests/glbook/Chapter_10/MultiTexture/MultiTexture.c227
-rw-r--r--tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c213
-rw-r--r--tests/glbook/Chapter_10/MultiTexture/basemap.tgabin0 -> 786476 bytes
-rw-r--r--tests/glbook/Chapter_10/MultiTexture/lightmap.tgabin0 -> 196626 bytes
-rw-r--r--tests/glbook/Chapter_11/Multisample/Multisample.c302
-rw-r--r--tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c273
-rw-r--r--tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c310
-rw-r--r--tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c294
-rw-r--r--tests/glbook/Chapter_13/ParticleSystem/smoke.tgabin0 -> 49170 bytes
-rw-r--r--tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c306
-rw-r--r--tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c200
-rw-r--r--tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c193
-rw-r--r--tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c209
-rw-r--r--tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c196
-rw-r--r--tests/glbook/Chapter_9/MipMap2D/MipMap2D.c348
-rw-r--r--tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c213
-rw-r--r--tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c199
-rw-r--r--tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c244
-rw-r--r--tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c227
-rw-r--r--tests/glbook/Chapter_9/TextureWrap/TextureWrap.c275
-rw-r--r--tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c257
-rw-r--r--tests/glbook/Common/esShader.c155
-rw-r--r--tests/glbook/Common/esShapes.c280
-rw-r--r--tests/glbook/Common/esTransform.c213
-rw-r--r--tests/glbook/Common/esUtil.c420
-rw-r--r--tests/glbook/Common/esUtil.h281
-rw-r--r--tests/glbook/Makefile60
-rw-r--r--tests/glbook/README.linux32
-rw-r--r--tests/glshaderinfo.cpp52
-rw-r--r--tests/hello_world_gles.c82
-rw-r--r--tests/hello_world_gles_deriv.c730
-rw-r--r--tests/hello_world_gles_shell.html2
-rw-r--r--tests/hello_world_sdl.cpp4
-rw-r--r--tests/htmltest.pngbin0 -> 743 bytes
-rw-r--r--tests/i64_precise.txt128
-rw-r--r--tests/msvc10/README.txt5
-rw-r--r--tests/msvc10/dlmalloc_test.vcxproj89
-rw-r--r--tests/msvc10/emscripten_api_browser.vcxproj89
-rw-r--r--tests/msvc10/fannkuch.vcxproj89
-rw-r--r--tests/msvc10/fasta.vcxproj89
-rw-r--r--tests/msvc10/files.vcxproj89
-rw-r--r--tests/msvc10/glbook_10_MultiTexture.vcxproj110
-rw-r--r--tests/msvc10/glbook_11_Multisample.vcxproj106
-rw-r--r--tests/msvc10/glbook_11_Stencil_Test.vcxproj106
-rw-r--r--tests/msvc10/glbook_13_ParticleSystem.vcxproj109
-rw-r--r--tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj106
-rw-r--r--tests/msvc10/glbook_2_Hello_Triangle.vcxproj106
-rw-r--r--tests/msvc10/glbook_8_Simple_VertexShader.vcxproj106
-rw-r--r--tests/msvc10/glbook_9_MipMap2D.vcxproj106
-rw-r--r--tests/msvc10/glbook_9_Simple_Texture2D.vcxproj106
-rw-r--r--tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj106
-rw-r--r--tests/msvc10/glbook_9_TextureWrap.vcxproj106
-rw-r--r--tests/msvc10/hashtest.vcxproj89
-rw-r--r--tests/msvc10/hello_libcxx.vcxproj89
-rw-r--r--tests/msvc10/hello_malloc.vcxproj89
-rw-r--r--tests/msvc10/hello_world_c.vcxproj89
-rw-r--r--tests/msvc10/hello_world_cpp.vcxproj89
-rw-r--r--tests/msvc10/hello_world_file.vcxproj89
-rw-r--r--tests/msvc10/hello_world_gles.vcxproj89
-rw-r--r--tests/msvc10/hello_world_loop.vcxproj89
-rw-r--r--tests/msvc10/hello_world_loop_malloc.vcxproj89
-rw-r--r--tests/msvc10/hello_world_sdl.vcxproj89
-rw-r--r--tests/msvc10/new.vcxproj89
-rw-r--r--tests/msvc10/raytrace.vcxproj89
-rw-r--r--tests/msvc10/sdl_audio.vcxproj89
-rw-r--r--tests/msvc10/sdl_canvas.vcxproj89
-rw-r--r--tests/msvc10/sdl_gl_read.vcxproj89
-rw-r--r--tests/msvc10/sdl_image.vcxproj89
-rw-r--r--tests/msvc10/sdl_key.vcxproj89
-rw-r--r--tests/msvc10/sdl_mouse.vcxproj89
-rw-r--r--tests/msvc10/sdl_ogl.vcxproj89
-rw-r--r--tests/msvc10/skinning_test_no_simd.vcxproj89
-rw-r--r--tests/msvc10/tests_msvc10.sln286
-rw-r--r--tests/msvc10/tests_msvc10.vcxproj67
-rw-r--r--tests/msvc10/twopart.vcxproj90
-rw-r--r--tests/pre_run_deps.cpp10
-rw-r--r--tests/python/ccproxy.py2
-rwxr-xr-xtests/runner.py2150
-rw-r--r--tests/s3tc.c158
-rw-r--r--tests/s3tc.pngbin0 -> 260282 bytes
-rw-r--r--tests/s3tc_crunch.c210
-rw-r--r--tests/s3tc_crunch.pngbin0 -> 353714 bytes
-rw-r--r--tests/scons/SConstruct5
-rw-r--r--tests/scons/integration.cpp14
-rw-r--r--tests/scons/other.c0
-rw-r--r--tests/screenshot-fog-density.pngbin0 -> 154012 bytes
-rw-r--r--tests/screenshot-fog-exp2.pngbin0 -> 119847 bytes
-rw-r--r--tests/screenshot-fog-linear.pngbin0 -> 247928 bytes
-rw-r--r--tests/screenshot-fog-negative.pngbin0 -> 79537 bytes
-rw-r--r--tests/screenshot-fog-simple.pngbin0 -> 36557 bytes
-rw-r--r--tests/screenshot-gray-purple.pngbin0 -> 242425 bytes
-rw-r--r--tests/screenshot-gray.pngbin0 -> 203336 bytes
-rw-r--r--tests/screenshot.ddsbin0 -> 262272 bytes
-rw-r--r--tests/screenshot.pngbin0 -> 329895 bytes
-rw-r--r--tests/sdl_audio.c56
-rw-r--r--tests/sdl_audio_quickload.c44
-rw-r--r--tests/sdl_canvas.c50
-rw-r--r--tests/sdl_canvas_palette.c58
-rw-r--r--tests/sdl_canvas_palette.pngbin0 -> 3235 bytes
-rw-r--r--tests/sdl_canvas_palette_2.c77
-rw-r--r--tests/sdl_fog_density.c183
-rw-r--r--tests/sdl_fog_exp2.c184
-rw-r--r--tests/sdl_fog_linear.c185
-rw-r--r--tests/sdl_fog_negative.c182
-rw-r--r--tests/sdl_fog_simple.c182
-rw-r--r--tests/sdl_gl_read.c155
-rw-r--r--tests/sdl_image.c34
-rw-r--r--tests/sdl_key.c56
-rw-r--r--tests/sdl_maprgba.c33
-rw-r--r--tests/sdl_maprgba.pngbin0 -> 1875 bytes
-rw-r--r--tests/sdl_mouse.c69
-rw-r--r--tests/sdl_ogl.c175
-rw-r--r--tests/sdl_ogl_defaultMatrixMode.c176
-rw-r--r--tests/sdl_ogl_p.c166
-rw-r--r--tests/sdlglshader.c153
-rw-r--r--tests/sdlglshader.pngbin0 -> 36299 bytes
-rw-r--r--tests/sha1.c241
-rw-r--r--tests/ship.ddsbin0 -> 65664 bytes
-rw-r--r--tests/sounds/LICENSE.txt19
-rw-r--r--tests/sounds/alarmcreatemiltaryfoot_1.wavbin0 -> 443856 bytes
-rw-r--r--tests/sounds/alarmvictory_1.oggbin0 -> 56490 bytes
-rw-r--r--tests/sqlite/benchmark.c1
-rw-r--r--tests/sqlite/benchmark.txt2
-rw-r--r--tests/tex_nonbyte.c206
-rw-r--r--tests/tex_nonbyte.pngbin0 -> 95900 bytes
-rw-r--r--tests/water.ddsbin0 -> 43920 bytes
-rwxr-xr-xthird_party/lzma.js/doit.sh10
-rw-r--r--tools/autodebugger.py68
-rwxr-xr-xtools/bindings_generator.py29
-rw-r--r--tools/bisect_pair.py18
-rw-r--r--tools/clean_webconsole.py34
-rw-r--r--tools/crunch-worker.js124
-rw-r--r--tools/eliminator/eliminator-test-output.js2722
-rw-r--r--tools/eliminator/eliminator-test.js3302
-rw-r--r--tools/eliminator/eliminator.coffee59
-rw-r--r--tools/eliminator/node_modules/coffee-script/lib/command.js2
-rwxr-xr-xtools/emmaken.py4
-rwxr-xr-xtools/emmakenxx.py4
-rw-r--r--tools/file_packager.py399
-rw-r--r--tools/ie7_fix.py14
-rw-r--r--tools/js-optimizer.js203
-rwxr-xr-xtools/ll-strip.py56
-rw-r--r--tools/make_minigzip.py2
-rw-r--r--tools/scan_js.py20
-rw-r--r--tools/scons/site_scons/site_tools/emscripten/emscripten.py2
-rw-r--r--tools/shared.py350
-rw-r--r--tools/test-js-optimizer-output.js7
-rw-r--r--tools/test-js-optimizer-regs-output.js228
-rw-r--r--tools/test-js-optimizer-regs.js233
-rw-r--r--tools/test-js-optimizer.js6
284 files changed, 48366 insertions, 2123 deletions
diff --git a/AUTHORS b/AUTHORS
index 248c345d..866bc0c3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,3 +16,14 @@ under the licensing terms detailed in LICENSE.
* Adrian Taylor <adrian@macrobug.com>
* Richard Assar <richard.assar@gmail.com>
* Nathan Hammond <emscripten@nathanhammond.com>
+* Behdad Esfahbod <behdad@behdad.org>
+* David Benjamin <davidben@mit.edu>
+* Pierre Renaux <pierre@talansoft.com>
+* Brian Anderson <banderson@mozilla.com>
+* Jon Bardin <diclophis@gmail.com>
+* Jukka Jylänki <jujjyl@gmail.com>
+* Aleksander Guryanov <caiiiycuk@gmail.com>
+* Chad Austin <chad@chadaustin.me>
+* nandhp <nandhp@gmail.com>
+* YeZhongWen <linghuye2.0@gmail.com>
+
diff --git a/em++ b/em++
index 5dd860f2..be2ed37b 100755
--- a/em++
+++ b/em++
@@ -4,9 +4,9 @@
See emcc.py. This script forwards to there, noting that we want C++ and not C by default
'''
-import os, sys
+import os, subprocess, sys
from tools import shared
os.environ['EMMAKEN_CXX'] = '1'
-exit(os.execvp(shared.EMCC, [shared.EMCC] + sys.argv[1:]))
+exit(subprocess.call(['python', shared.EMCC] + sys.argv[1:]))
diff --git a/em-config b/em-config
new file mode 100755
index 00000000..dee399ed
--- /dev/null
+++ b/em-config
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+'''
+This is a helper tool which is designed to make it possible
+for other apps to read emscripten's configuration variables
+in a unified way. Usage:
+
+ em-config VAR_NAME
+
+This tool prints the value of the variable to stdout if one
+is found, or exits with 1 if the variable does not exist.
+'''
+
+import os, sys, re
+from tools import shared
+
+if len(sys.argv) != 2 or \
+ not re.match(r"^[\w\W_][\w\W_\d]*$", sys.argv[1]) or \
+ not (sys.argv[1] in dir(shared)):
+ print 'Usage: em-config VAR_NAME'
+ exit(1)
+
+print eval('shared.' + sys.argv[1])
+
diff --git a/emar b/emar
index e64cd8b9..46bc65d7 100755
--- a/emar
+++ b/emar
@@ -7,7 +7,7 @@ emar - ar helper script
This script acts as a frontend replacement for ar. See emcc.
'''
-import os, sys
+import os, subprocess, sys
from tools import shared
DEBUG = os.environ.get('EMCC_DEBUG')
@@ -18,5 +18,5 @@ if DEBUG:
print >> sys.stderr, 'emar:', sys.argv, ' ==> ', newargs
if len(newargs) > 2:
- os.execvp(shared.LLVM_AR, newargs)
+ subprocess.call(newargs)
diff --git a/emcc b/emcc
index 69dd999e..7cc59c53 100755
--- a/emcc
+++ b/emcc
@@ -74,18 +74,10 @@ emcc can be influenced by a few environment variables:
EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang.
'''
-import os, sys, shutil, tempfile, subprocess
+import os, sys, shutil, tempfile, subprocess, shlex
from subprocess import PIPE, STDOUT
from tools import shared
-
-def execute(cmd, *args, **kw):
- try:
- return subprocess.Popen(cmd, *args, **kw).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that)
- except:
- if not isinstance(cmd, str):
- cmd = ' '.join(cmd)
- print >> sys.stderr, 'Invoking Process failed: <<< ' + cmd + ' >>>'
- raise
+from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
@@ -128,7 +120,7 @@ if len(sys.argv) == 1:
if sys.argv[1] == '--version':
print '''emcc (Emscripten GCC-like replacement) 2.0
-Copyright (C) 2011 the Emscripten authors.
+Copyright (C) 2012 the Emscripten authors.
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
'''
@@ -174,6 +166,12 @@ Options that are modified or new in %s include:
2: -O2 LLVM optimizations
3: -O3 LLVM optimizations (default in -O2+)
+ --llvm-lto <level> 0: No LLVM LTO (default in -O0)
+ 1: LLVM LTO (default in -O1+)
+ Note: If LLVM optimizations are not run
+ (see --llvm-opts), setting this to 1 has no
+ effect.
+
--closure <on> 0: No closure compiler (default in -O0, -O1)
1: Run closure compiler (default in -O2, -O3)
@@ -193,10 +191,14 @@ Options that are modified or new in %s include:
script to be run.
--pre-js <file> A file whose contents are added before the
- generated code
+ generated code. This is done *before*
+ optimization, so it will be minified
+ properly if closure compiler is run.
--post-js <file> A file whose contents are added after the
- generated code
+ generated code This is done *before*
+ optimization, so it will be minified
+ properly if closure compiler is run.
--embed-file <file> A file to embed inside the generated
JavaScript. The compiled code will be able
@@ -210,9 +212,14 @@ Options that are modified or new in %s include:
compiled code asynchronously. Otherwise
similar to --embed-file, except that this
option is only relevant when generating
- HTML (it uses asynchronous binary XHRs).
+ HTML (it uses asynchronous binary XHRs),
+ or JS that will be used in a web page.
If a directory is passed here, its entire
contents will be preloaded.
+ Preloaded files are stored in filename.data,
+ where filename.html is the main file you
+ are compiling to. To run your code, you
+ will need both the .html and the .data.
--compression <codec> Compress both the compiled code and embedded/
preloaded files. <codec> should be a triple,
@@ -228,6 +235,10 @@ Options that are modified or new in %s include:
receive an array/typed array and return
an array/typed array.
Compression only works when generating HTML.
+ When compression is on, all filed specified
+ to be preloaded are compressed in one big
+ archive, which is given the same name as the
+ output HTML but with suffix .data.compress
--minify <on> 0: Do not minify the generated JavaScript's
whitespace (default if closure compiler
@@ -255,6 +266,18 @@ Options that are modified or new in %s include:
target other than HTML is specified using
the -o option.
+ --js-library <lib> A JavaScript library to use in addition to
+ those in Emscripten's src/library_*
+
+ -v Turns on verbose output. This will pass
+ -v to Clang, and also enable EMCC_DEBUG
+ to details emcc's operations
+
+ --remove-duplicates If set, will remove duplicate symbols when
+ linking. This can be useful because
+ llvm-link's behavior is not as permissive
+ as ld is.
+
The target file, if specified (-o <target>), defines what will
be generated:
@@ -276,6 +299,9 @@ the source of emcc (search for 'os.environ').
''' % (this, this, this)
exit(0)
+elif len(sys.argv) == 2 and sys.argv[1] == '-v': # -v with no inputs
+ print 'emcc (Emscripten GCC-like replacement) 2.0'
+ exit(subprocess.call([shared.CLANG, '-v']))
# If this is a configure-type thing, do not compile to JavaScript, instead use clang
# to compile to a native binary (using our headers, so things make sense later)
@@ -287,7 +313,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
compiler = shared.to_cc(compiler)
cmd = [compiler] + shared.EMSDK_OPTS + ['-DEMSCRIPTEN'] + sys.argv[1:]
if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', ' '.join(cmd)
- exit(os.execvp(compiler, cmd))
+ exit(subprocess.call(cmd))
if os.environ.get('EMMAKEN_COMPILER'):
CXX = os.environ['EMMAKEN_COMPILER']
@@ -303,27 +329,22 @@ if os.environ.get('EMMAKEN_CXX'):
CC_ADDITIONAL_ARGS = shared.COMPILER_OPTS # + ['-g']?
EMMAKEN_CFLAGS = os.environ.get('EMMAKEN_CFLAGS')
-if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ')
+if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += shlex.split(EMMAKEN_CFLAGS)
# ---------------- Utilities ---------------
SOURCE_SUFFIXES = ('.c', '.cpp', '.cxx', '.cc')
-BITCODE_SUFFIXES = ('.bc', '.o')
+BITCODE_SUFFIXES = ('.bc', '.o', '.obj')
DYNAMICLIB_SUFFIXES = ('.dylib', '.so', '.dll')
STATICLIB_SUFFIXES = ('.a',)
ASSEMBLY_SUFFIXES = ('.ll',)
LIB_PREFIXES = ('', 'lib')
-IMAGE_SUFFIXES = ('.jpg', '.png', '.bmp')
-
-def suffix(name):
- return name.split('.')[:-1]
-
-def unsuffixed(name):
- return '.'.join(name.split('.')[:-1])
-
-def unsuffixed_basename(name):
- return os.path.basename(unsuffixed(name))
+seen_names = {}
+def uniquename(name):
+ if name not in seen_names:
+ seen_names[name] = str(len(seen_names))
+ return unsuffixed(name) + '_' + seen_names[name] + (('.' + suffix(name)) if suffix(name) else '')
# ---------------- End configs -------------
@@ -343,6 +364,12 @@ for i in range(1, len(sys.argv)):
if arg.endswith('.h') and sys.argv[i-1] != '-include':
header = True
+if '-M' in sys.argv or '-MM' in sys.argv:
+ # Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it)
+ cmd = [CC] + shared.COMPILER_OPTS + sys.argv[1:]
+ if DEBUG: print >> sys.stderr, 'emcc, just dependencies: ', ' '.join(cmd)
+ exit(subprocess.call(cmd))
+
# Check if a target is specified
target = None
for i in range(len(sys.argv)-1):
@@ -356,8 +383,9 @@ for i in range(len(sys.argv)-1):
if header: # header or such
if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing
- if DEBUG: print >> sys.stderr, 'Just copy.'
- shutil.copy(sys.argv[-1], sys.argv[-2])
+ sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv)
+ if DEBUG: print >> sys.stderr, 'Just copy:', sys.argv[-1], target
+ shutil.copy(sys.argv[-1], target)
else:
if DEBUG: print >> sys.stderr, 'No-op.'
exit(0)
@@ -371,22 +399,7 @@ else:
temp_dir = tempfile.mkdtemp()
def in_temp(name):
- return os.path.join(temp_dir, name)
-
-class Compression:
- on = False
-
- @staticmethod
- def compressed_name(filename):
- return filename + '.compress'
-
- @staticmethod
- def compress(filename):
- execute(Compression.encoder, stdin=open(filename, 'rb'), stdout=open(Compression.compressed_name(filename), 'wb'))
-
- @staticmethod
- def worth_it(original, compressed):
- return compressed < original - 1500 # save at least one TCP packet or so
+ return os.path.join(temp_dir, os.path.basename(name))
try:
call = CXX if use_cxx else CC
@@ -397,15 +410,19 @@ try:
opt_level = 0
llvm_opts = None
+ llvm_lto = None
closure = None
js_transform = None
- pre_js = None
- post_js = None
+ pre_js = ''
+ post_js = ''
minify_whitespace = None
- data_files = []
+ preload_files = []
+ embed_files = []
compression = None
ignore_dynamic_linking = False
shell_path = shared.path_from_root('src', 'shell.html')
+ js_libraries = []
+ remove_duplicates = False
def check_bad_eq(arg):
assert '=' not in arg, 'Invalid parameter (do not use "=" with "--" options)'
@@ -423,6 +440,11 @@ try:
llvm_opts = eval(newargs[i+1])
newargs[i] = ''
newargs[i+1] = ''
+ elif newargs[i].startswith('--llvm-lto'):
+ check_bad_eq(newargs[i])
+ llvm_lto = eval(newargs[i+1])
+ newargs[i] = ''
+ newargs[i+1] = ''
elif newargs[i].startswith('--closure'):
check_bad_eq(newargs[i])
closure = int(newargs[i+1])
@@ -435,12 +457,12 @@ try:
newargs[i+1] = ''
elif newargs[i].startswith('--pre-js'):
check_bad_eq(newargs[i])
- pre_js = open(newargs[i+1]).read()
+ pre_js += open(newargs[i+1]).read() + '\n'
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--post-js'):
check_bad_eq(newargs[i])
- post_js = open(newargs[i+1]).read()
+ post_js += open(newargs[i+1]).read() + '\n'
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--minify'):
@@ -450,12 +472,12 @@ try:
newargs[i+1] = ''
elif newargs[i].startswith('--embed-file'):
check_bad_eq(newargs[i])
- data_files.append({ 'name': newargs[i+1], 'mode': 'embed' })
+ embed_files.append(newargs[i+1])
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--preload-file'):
check_bad_eq(newargs[i])
- data_files.append({ 'name': newargs[i+1], 'mode': 'preload' })
+ preload_files.append(newargs[i+1])
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i].startswith('--compression'):
@@ -470,23 +492,30 @@ try:
Compression.on = True
newargs[i] = ''
newargs[i+1] = ''
- elif newargs[i] == '-MF': # clang cannot handle this, so we fake it
- f = open(newargs[i+1], 'w')
- f.write('\n')
- f.close()
- newargs[i] = ''
- newargs[i+1] = ''
elif newargs[i] == '--ignore-dynamic-linking':
ignore_dynamic_linking = True
newargs[i] = ''
+ elif newargs[i] == '-v':
+ shared.COMPILER_OPTS += ['-v']
+ DEBUG = 1
+ newargs[i] = ''
elif newargs[i].startswith('--shell-file'):
check_bad_eq(newargs[i])
shell_path = newargs[i+1]
newargs[i] = ''
newargs[i+1] = ''
+ elif newargs[i].startswith('--js-library'):
+ check_bad_eq(newargs[i])
+ js_libraries.append(newargs[i+1])
+ newargs[i] = ''
+ newargs[i+1] = ''
+ elif newargs[i] == '--remove-duplicates':
+ remove_duplicates = True
+ newargs[i] = ''
newargs = [ arg for arg in newargs if arg is not '' ]
if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level]
+ if llvm_lto is None: llvm_lto = llvm_opts > 0
if closure is None: closure = 1 if opt_level >= 2 else 0
if minify_whitespace is None:
minify_whitespace = closure # if closure is run, minify whitespace
@@ -497,9 +526,11 @@ try:
settings_changes = []
for i in range(len(newargs)):
if newargs[i] == '-s':
- assert '=' in newargs[i+1], 'Incorrect syntax for -s (use -s OPT=VAL): ' + newargs[i+1]
- settings_changes.append(newargs[i+1])
- newargs[i] = newargs[i+1] = ''
+ if i+1 < len(newargs) and '=' in newargs[i+1]: # -s OPT=VALUE is for us, -s by itself is a linker option
+ settings_changes.append(newargs[i+1])
+ newargs[i] = newargs[i+1] = ''
+ else:
+ print >> sys.stderr, 'emcc: warning: treating -s as linker option and not as -s OPT=VALUE for js compilation'
elif newargs[i].startswith('--typed-arrays'):
assert '=' not in newargs[i], 'Invalid typed arrays parameter (do not use "=")'
settings_changes.append('USE_TYPED_ARRAYS=' + newargs[i+1])
@@ -511,7 +542,7 @@ try:
input_files = []
has_source_inputs = False
- lib_dirs = []
+ lib_dirs = [shared.path_from_root('system', 'lib')]
libs = []
for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params,
# right now we just assume that what is left contains no more |-x OPT| things
@@ -519,7 +550,7 @@ try:
if i > 0:
prev = newargs[i-1]
- if prev == '-MT': continue # ignore this gcc-style argument
+ if prev in ['-MT', '-install_name']: continue # ignore this gcc-style argument
if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
@@ -531,6 +562,16 @@ try:
# this should be bitcode, make sure it is valid
if arg.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg):
input_files.append(arg)
+ elif arg.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES):
+ # if it's not, and it's a library, just add it to libs to find later
+ l = unsuffixed_basename(arg)
+ for prefix in LIB_PREFIXES:
+ if not prefix: continue
+ if l.startswith(prefix):
+ l = l[len(prefix):]
+ break;
+ libs.append(l)
+ newargs[i] = ''
else:
print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg
else:
@@ -541,6 +582,9 @@ try:
elif arg.startswith('-l'):
libs.append(arg[2:])
newargs[i] = ''
+
+ original_input_files = input_files[:]
+
newargs = [ arg for arg in newargs if arg is not '' ]
# Find library files
@@ -606,7 +650,7 @@ try:
for input_file in input_files:
if input_file.endswith(SOURCE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file
- output_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
temp_files.append(output_file)
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args)
@@ -617,12 +661,12 @@ try:
else: # bitcode
if input_file.endswith(BITCODE_SUFFIXES):
if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file
- temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file):
if DEBUG: print >> sys.stderr, 'emcc: copying library file: ', input_file
- temp_file = in_temp(os.path.basename(input_file))
+ temp_file = in_temp(uniquename(input_file))
shutil.copyfile(input_file, temp_file)
temp_files.append(temp_file)
else: #.ll
@@ -630,7 +674,7 @@ try:
# Note that by assembling the .ll file, then disassembling it later, we will
# remove annotations which is a good thing for compilation time
if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file
- temp_file = in_temp(unsuffixed_basename(input_file) + '.o')
+ temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o')
shared.Building.llvm_as(input_file, temp_file)
temp_files.append(temp_file)
@@ -642,18 +686,16 @@ try:
print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript'
if not specified_target:
for input_file in input_files:
- shutil.move(in_temp(unsuffixed_basename(input_file) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix)
+ shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix)
else:
if len(input_files) == 1:
- shutil.move(in_temp(unsuffixed_basename(input_files[0]) + '.o'), specified_target)
+ shutil.move(in_temp(unsuffixed(uniquename(input_files[0])) + '.o'), specified_target)
else:
- assert not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv)
+ assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files)
# We have a specified target (-o <target>), which is not JavaScript or HTML, and
- # we have multiple files: Link them TODO: llvm link-time opts?
- ld_args = temp_files + ['-b', specified_target]
- #[arg.split('-Wl,')[1] for arg in filter(lambda arg: arg.startswith('-Wl,'), sys.argv)]
- if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(ld_args)
- execute([shared.LLVM_LD, '-disable-opt'] + ld_args)
+ # we have multiple files: Link them
+ if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(temp_files)
+ shared.Building.link(temp_files, specified_target, remove_duplicates=remove_duplicates)
exit(0)
## Continue on to create JavaScript
@@ -671,9 +713,9 @@ try:
# dlmalloc
def create_dlmalloc():
if DEBUG: print >> sys.stderr, 'emcc: building dlmalloc for cache'
- execute([shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr)
+ execute(shared.ENV_PREFIX + ['python', shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr)
# we include the libc++ new stuff here, so that the common case of using just new/delete is quick to link
- execute([shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr)
+ execute(shared.ENV_PREFIX + ['python', shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr)
shared.Building.link([in_temp('dlmalloc.o'), in_temp('new.o')], in_temp('dlmalloc_full.o'))
return in_temp('dlmalloc_full.o')
def fix_dlmalloc():
@@ -699,7 +741,7 @@ try:
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1'
# libcxx might need corrections, so turn them all on. TODO: check which are actually needed
shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
- print >> sys.stderr, 'emcc: warning: using libcxx turns on CORRECT_* options'
+ #print >> sys.stderr, 'emcc: info: using libcxx turns on CORRECT_* options'
libcxx_symbols = map(lambda line: line.strip().split(' ')[1], open(shared.path_from_root('system', 'lib', 'libcxx', 'symbols')).readlines())
libcxx_symbols = filter(lambda symbol: symbol not in dlmalloc_symbols, libcxx_symbols)
libcxx_symbols = set(libcxx_symbols)
@@ -711,7 +753,7 @@ try:
return os.path.join(shared.EMSCRIPTEN_TEMP_DIR, 'libcxxabi', 'libcxxabi.bc')
def fix_libcxxabi():
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1'
- print >> sys.stderr, 'emcc: warning: using libcxxabi, this may need CORRECT_* options'
+ #print >> sys.stderr, 'emcc: info: using libcxxabi, this may need CORRECT_* options'
#shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
libcxxabi_symbols = map(lambda line: line.strip().split(' ')[1], open(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols')).readlines())
libcxxabi_symbols = filter(lambda symbol: symbol not in dlmalloc_symbols, libcxxabi_symbols)
@@ -745,8 +787,7 @@ try:
(not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])):
linker_inputs = temp_files + extra_files_to_link
if DEBUG: print >> sys.stderr, 'emcc: linking: ', linker_inputs
- shared.Building.link(linker_inputs,
- in_temp(target_basename + '.bc'))
+ shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), remove_duplicates=remove_duplicates)
final = in_temp(target_basename + '.bc')
else:
if not LEAVE_INPUTS_RAW:
@@ -772,7 +813,7 @@ try:
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts)
if DEBUG: save_intermediate('opt', 'bc')
# Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript)
- if shared.Building.can_use_unsafe_opts() and shared.Building.can_build_standalone():
+ if llvm_lto and shared.Building.can_use_unsafe_opts() and shared.Building.can_build_standalone():
lto_opts = []
if not shared.Building.can_inline(): lto_opts.append('-disable-inlining')
lto_opts.append('-std-link-opts')
@@ -795,117 +836,29 @@ try:
if AUTODEBUG:
if DEBUG: print >> sys.stderr, 'emcc: autodebug'
- execute(['python', shared.AUTODEBUGGER, final, final + '.ad.ll'])
+ execute(shared.ENV_PREFIX + ['python', shared.AUTODEBUGGER, final, final + '.ad.ll'])
final += '.ad.ll'
if DEBUG: save_intermediate('autodebug', 'll')
# Emscripten
if DEBUG: print >> sys.stderr, 'emcc: LLVM => JS'
- final = shared.Building.emscripten(final, append_ext=False)
+ extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))]
+ final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args)
if DEBUG: save_intermediate('original')
# Embed and preload files
- if len(data_files) > 0:
+ if len(preload_files) + len(embed_files) > 0:
if DEBUG: print >> sys.stderr, 'emcc: setting up files'
- code = ''
-
- # Expand directories into individual files
- def add(mode, dirname, names):
- for name in names:
- combined = os.path.join(dirname, name)
- data_files.append({ 'name': os.path.join(dirname, name), 'mode': mode })
-
- for file_ in data_files:
- if os.path.isdir(file_['name']):
- os.path.walk(file_['name'], add, file_['mode'])
- data_files = filter(lambda file_: not os.path.isdir(file_['name']), data_files)
-
- for file_ in data_files:
- file_['net_name'] = file_['name']
- file_['compressed'] = False
-
+ file_args = []
+ if len(preload_files) > 0:
+ file_args.append('--preload')
+ file_args += preload_files
+ if len(embed_files) > 0:
+ file_args.append('--embed')
+ file_args += embed_files
if Compression.on:
- # Compress each file, if it is worth it
- for file_ in data_files:
- Compression.compress(file_['name'])
- if Compression.worth_it(os.stat(file_['name']).st_size,
- os.stat(Compression.compressed_name(file_['name'])).st_size):
- file_['net_name'] = Compression.compressed_name(file_['name'])
- file_['compressed'] = True
- else:
- if DEBUG: print >> sys.stderr, 'emcc: not compressing %s since not worth it' % file_['name']
- os.remove(Compression.compressed_name(file_['name']))
-
- # Set up folders
- partial_dirs = []
- for file_ in data_files:
- dirname = os.path.dirname(file_['name'])
- parts = dirname.split(os.path.sep)
- if dirname != '' and dirname != os.path.sep:
- for i in range(len(parts)):
- partial = os.path.sep.join(parts[:i])
- if partial not in partial_dirs:
- code += '''FS.createFolder('/%s', '%s', true, false);\n''' % (os.path.sep.join(parts[:i-1]), parts[-1])
- partial_dirs.append(partial)
-
- counter = 0
- for file_ in data_files:
- filename = file_['name']
- if file_['mode'] == 'embed':
- # Embed
- code += '''FS.createDataFile('/', '%s', %s, true, true);\n''' % (os.path.basename(filename), str(map(ord, open(filename, 'rb').read())))
- elif file_['mode'] == 'preload':
- # Preload
- varname = 'filePreload%d' % counter
- counter += 1
- image = filename.endswith(IMAGE_SUFFIXES)
- code += '''
- var %(varname)s = new XMLHttpRequest();
- %(varname)s.open('GET', '%(netname)s', true);
- %(varname)s.responseType = 'arraybuffer';
- %(varname)s.onload = function() {
- var arrayBuffer = %(varname)s.response; // Note: not X.responseText
- assert(arrayBuffer, 'Loading file %(filename)s failed.');
- var byteArray = new Uint8Array(arrayBuffer);
- %(decompress_start)s
- FS.createDataFile('/%(dirname)s', '%(basename)s', byteArray, true, true);
- %(finish)s
- %(decompress_end)s
- };
- addRunDependency();
- %(varname)s.send(null);
-''' % {
- 'varname': varname,
- 'filename': filename,
- 'netname': file_['net_name'],
- 'dirname': os.path.dirname(filename),
- 'basename': os.path.basename(filename),
- 'decompress_start': '' if not file_['compressed'] else 'Module["decompress"](byteArray, function(decompressed) { byteArray = new Uint8Array(decompressed);',
- 'decompress_end': '' if not file_['compressed'] else '});',
- 'finish': 'removeRunDependency();' if not image else '''var bb = new MozBlobBuilder();
- bb.append(byteArray.buffer);
- var b = bb.getBlob();
- var url = window.URL.createObjectURL(b);
- var img = new Image();
- img.onload = function() {
- assert(img.complete, 'Image %(filename)s could not be decoded');
- var canvas = document.createElement('canvas');
- canvas.width = img.width;
- canvas.height = img.height;
- var ctx = canvas.getContext('2d');
- ctx.drawImage(img, 0, 0);
- preloadedImages['%(filename)s'] = ctx.getImageData(0, 0, canvas.width, canvas.height);
- window.URL.revokeObjectURL(url);
- removeRunDependency();
- };
- img.onerror = function(event) {
- console.log('Image %(filename)s could not be decoded: ' + JSON.stringify(event));
- };
- img.src = url;
-''' % { 'filename': filename }
- }
- else:
- assert 0
+ file_args += ['--compress', Compression.encoder, Compression.decoder, Compression.js_name]
+ code = execute(shared.ENV_PREFIX + ['python', shared.FILE_PACKAGER, unsuffixed(target) + '.data'] + file_args, stdout=PIPE)[0]
src = open(final).read().replace('// {{PRE_RUN_ADDITIONS}}', code)
final += '.files.js'
open(final, 'w').write(src)
@@ -916,15 +869,16 @@ try:
if DEBUG: print >> sys.stderr, 'emcc: applying pre/postjses'
src = open(final).read()
final += '.pp.js'
- open(final, 'w').write((pre_js or '') + src + (post_js or ''))
+ open(final, 'w').write(pre_js + src + post_js)
if DEBUG: save_intermediate('pre-post')
# Apply a source code transformation, if requested
if js_transform:
shutil.copyfile(final, final + '.tr.js')
final += '.tr.js'
+ posix = True if not shared.WINDOWS else False
if DEBUG: print >> sys.stderr, 'emcc: applying transform: %s' % js_transform
- execute(js_transform.split(' ') + [os.path.abspath(final)])
+ execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)])
if DEBUG: save_intermediate('transformed')
# It is useful to run several js optimizer passes together, to save on unneeded unparsing/reparsing
@@ -954,18 +908,16 @@ try:
flush_js_optimizer_queue()
- # eliminator
if DEBUG: print >> sys.stderr, 'emcc: running variable eliminator'
final = shared.Building.eliminator(final)
if DEBUG: save_intermediate('eliminator')
- # js optimizer pre-pass
js_optimizer_queue += ['simplifyExpressionsPre']
if shared.Settings.RELOOP:
js_optimizer_queue += ['optimizeShiftsAggressive'] # aggressive shifts optimization requires loops, it breaks on switches
- flush_js_optimizer_queue()
- final = shared.Building.eliminator(final) # aggressive shifts optimization introduces some new variables, remove ones that we can
- if DEBUG: save_intermediate('eliminator')
+ flush_js_optimizer_queue()
+ final = shared.Building.eliminator(final) # aggressive shifts optimization introduces some new variables, remove ones that we can
+ if DEBUG: save_intermediate('eliminator')
if closure:
flush_js_optimizer_queue()
@@ -975,7 +927,6 @@ try:
if DEBUG: save_intermediate('closure')
if opt_level >= 1:
- # js optimizer post-pass
if DEBUG: print >> sys.stderr, 'emcc: running post-closure post-opts'
js_optimizer_queue += ['simplifyExpressionsPost']
@@ -1005,14 +956,25 @@ try:
decoding = '''
var decompressWorker = new Worker('decompress.js');
var decompressCallbacks = [];
+ var decompressions = 0;
Module["decompress"] = function(data, callback) {
var id = decompressCallbacks.length;
decompressCallbacks.push(callback);
decompressWorker.postMessage({ data: data, id: id });
+ if (Module['setStatus']) {
+ decompressions++;
+ Module['setStatus']('Decompressing...');
+ }
};
decompressWorker.onmessage = function(event) {
decompressCallbacks[event.data.id](event.data.data);
decompressCallbacks[event.data.id] = null;
+ if (Module['setStatus']) {
+ decompressions--;
+ if (decompressions == 0) {
+ Module['setStatus']('');
+ }
+ }
};
var compiledCodeXHR = new XMLHttpRequest();
compiledCodeXHR.open('GET', '%s', true);
diff --git a/emld b/emld
deleted file mode 100755
index 954465c6..00000000
--- a/emld
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-
-'''
-emld - linker helper script
-===========================
-
-This script acts as a frontend replacement for the ld linker. See emcc.
-
-We could use the compiler code for this, but here we want to be careful to use all the linker flags we have been passed, sending them to ld.
-'''
-
-import os, sys
-from tools import shared
-
-DEBUG = os.environ.get('EMCC_DEBUG')
-
-if DEBUG:
- print >> sys.stderr, 'emld:', sys.argv
-
-ALLOWED_LINK_ARGS = ['-f', '-help', '-o', '-print-after', '-print-after-all', '-print-before',
- '-print-before-all', '-time-passes', '-v', '-verify-dom-info', '-version' ]
-TWO_PART_DISALLOWED_LINK_ARGS = ['-L'] # Ignore thingsl like |-L .|
-
-# Check for specified target
-target = None
-for i in range(len(sys.argv)-1):
- if sys.argv[i].startswith('-o='):
- raise Exception('Invalid syntax: do not use -o=X, use -o X')
-
- if sys.argv[i] == '-o':
- target = sys.argv[i+1]
- sys.argv = sys.argv[:i] + sys.argv[i+2:]
- break
-
-call = shared.LLVM_LD
-newargs = ['-disable-opt']
-i = 0
-while i < len(sys.argv)-1:
- i += 1
- arg = sys.argv[i]
- if arg.startswith('-'):
- prefix = arg.split('=')[0]
- if prefix in ALLOWED_LINK_ARGS:
- newargs.append(arg)
- if arg in TWO_PART_DISALLOWED_LINK_ARGS:
- i += 1
- elif arg.endswith('.so'):
- continue # .so's do not exist yet, in many cases
- else:
- # not option, so just append
- newargs.append(arg)
-if target:
- actual_target = target
- if target.endswith('.js'):
- actual_target = unsuffixed(target) + '.bc'
- newargs.append('-o=' + actual_target)
-
-if DEBUG: print >> sys.stderr, "emld running:", call, ' '.join(newargs)
-os.execvp(call, [call] + newargs)
-
diff --git a/emscripten.py b/emscripten.py
index 5674c33a..800ca8d7 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
'''
You should normally never use this! Use emcc instead.
@@ -35,7 +35,7 @@ def path_from_root(*pathelems):
temp_files = shared.TempFiles()
-def emscript(infile, settings, outfile):
+def emscript(infile, settings, outfile, libraries=[]):
"""Runs the emscripten LLVM-to-JS compiler.
Args:
@@ -49,7 +49,7 @@ def emscript(infile, settings, outfile):
s.write(settings)
s.close()
compiler = path_from_root('src', 'compiler.js')
- shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, infile], stdout=outfile, cwd=path_from_root('src'))
+ shared.run_js(compiler, shared.COMPILER_ENGINE, [settings_file, infile] + libraries, stdout=outfile, cwd=path_from_root('src'))
outfile.close()
@@ -123,12 +123,15 @@ def main(args):
#print >> sys.stderr, 'new defs:', str(defines).replace(',', ',\n '), '\n\n'
settings.setdefault('C_DEFINES', {}).update(defines)
+ # libraries
+ libraries = args.libraries[0].split(',') if len(args.libraries) > 0 else []
+
# Compile the assembly to Javascript.
- emscript(args.infile, json.dumps(settings), args.outfile)
+ emscript(args.infile, json.dumps(settings), args.outfile, libraries)
if __name__ == '__main__':
parser = optparse.OptionParser(
- usage='usage: %prog [-h] [-O] [-m] [-H HEADERS] [-o OUTFILE] [-s FOO=BAR]* infile',
+ usage='usage: %prog [-h] [-H HEADERS] [-o OUTFILE] [-s FOO=BAR]* infile',
description=('You should normally never use this! Use emcc instead. '
'This is a wrapper around the JS compiler, converting .ll to .js.'),
epilog='')
@@ -136,6 +139,10 @@ if __name__ == '__main__':
default=[],
action='append',
help='System headers (comma separated) whose #defines should be exposed to the compiled code.')
+ parser.add_option('-L', '--libraries',
+ default=[],
+ action='append',
+ help='Library files (comma separated) to use in addition to those in emscripten src/library_*.')
parser.add_option('-o', '--outfile',
default=sys.stdout,
help='Where to write the output; defaults to stdout.')
diff --git a/settings.py b/settings.py
index 48eaa9ab..1133a656 100644
--- a/settings.py
+++ b/settings.py
@@ -1,17 +1,21 @@
# This file will be copied to ~/.emscripten if that file doesn't exist. Or, this is that copy.
# IMPORTANT: Edit the *copy* with the right paths!
+# Note: If you put paths relative to the home directory, do not forget os.path.expanduser
EMSCRIPTEN_ROOT = os.path.expanduser('~/Dev/emscripten') # this helps projects using emscripten find it
-LLVM_ROOT = os.path.expanduser('~/Dev/llvm-3.0/cbuild/bin')
+LLVM_ROOT = os.path.expanduser('~/Dev/llvm/cbuild/bin')
# See below for notes on which JS engine(s) you need
NODE_JS = 'node'
SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-n']
V8_ENGINE = os.path.expanduser('~/Dev/v8/d8')
-TEMP_DIR = '/tmp'
+JAVA = 'java'
+TEMP_DIR = '/tmp' # You will need to modify this on Windows
+
+#CLOSURE_COMPILER = '..' # define this to not use the bundled version
########################################################################################################
diff --git a/src/analyzer.js b/src/analyzer.js
index 8ded86f1..4bf2255e 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -9,7 +9,7 @@ var VAR_NATIVIZED = 'nativized';
var VAR_EMULATED = 'emulated';
var ENTRY_IDENT = toNiceIdent('%0');
-var ENTRY_IDENTS = set(toNiceIdent('%0'), toNiceIdent('%1'));
+var ENTRY_IDENT_IDS = set(0, 1); // XXX
function recomputeLines(func) {
func.lines = func.labels.map(function(label) { return label.lines }).reduce(concatenator, []);
@@ -544,6 +544,10 @@ function analyzer(data, sidePass) {
params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
type: 'i32',
};
+ if (j == 0 && isUnsignedOp(value.op) && sourceBits < 32) {
+ // zext sign correction
+ result.ident = makeSignOp(result.ident, 'i' + sourceBits, 'un', 1, 1);
+ }
if (fraction != 0) {
var other = {
intertype: 'value',
@@ -1176,7 +1180,9 @@ function analyzer(data, sidePass) {
func.labelIdsInverse = {};
func.labelIds[toNiceIdent('%0')] = 0;
func.labelIdsInverse[0] = toNiceIdent('%0');
- func.labelIdCounter = 1;
+ func.labelIds[toNiceIdent('%1')] = 1;
+ func.labelIdsInverse[1] = toNiceIdent('%1');
+ func.labelIdCounter = 2;
func.labels.forEach(function(label) {
func.labelIds[label.ident] = func.labelIdCounter++;
func.labelIdsInverse[func.labelIdCounter-1] = label.ident;
@@ -1202,6 +1208,7 @@ function analyzer(data, sidePass) {
if (phi.intertype == 'phi') {
for (var i = 0; i < phi.params.length; i++) {
phi.params[i].label = func.labelIds[phi.params[i].label];
+ if (!phi.params[i].label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
}
}
});
@@ -1217,9 +1224,10 @@ function analyzer(data, sidePass) {
// So we need to handle that in a special way here.
function getActualLabelId(labelId) {
if (func.labelsDict[labelId]) return labelId;
- if (labelId in ENTRY_IDENTS) {
- assert(func.labelsDict[ENTRY_IDENT]);
- return ENTRY_IDENT;
+ if (labelId in ENTRY_IDENT_IDS) {
+ labelId = func.labelIds[ENTRY_IDENT];
+ assert(func.labelsDict[labelId]);
+ return labelId;
}
return null;
}
@@ -1270,88 +1278,44 @@ function analyzer(data, sidePass) {
recomputeLines(func);
}
- if (!MICRO_OPTS) {
- // 'Emulate' phis, by doing an if where the phi appears in the .ll. For this
- // we need __lastLabel__.
- func.needsLastLabel = false;
- func.labels.forEach(function(label) {
- var phis = [];
- label.lines.forEach(function(phi) {
- if (phi.intertype == 'phi') {
- for (var i = 0; i < phi.params.length; i++) {
- var sourceLabelId = getActualLabelId(phi.params[i].label);
- if (sourceLabelId) {
- var sourceLabel = func.labelsDict[sourceLabelId];
- var lastLine = sourceLabel.lines.slice(-1)[0];
- assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
- lastLine.currLabelId = sourceLabelId;
- }
- }
- phis.push(phi);
- func.needsLastLabel = true;
- }
- });
+ // Properly implement phis, by pushing them back into the branch
+ // that leads to here. We will only have the |var| definition in this location.
- if (phis.length >= 2) {
- // Multiple phis have the semantics that they all occur 'in parallel', i.e., changes to
- // a variable that is the result of a phi should *not* affect the other results. We must
- // therefore be careful!
- phis[phis.length-1].postSet = '; /* post-phi: */';
- for (var i = 0; i < phis.length-1; i++) {
- var ident = phis[i].assignTo;
- var phid = ident+'$phi'
- phis[phis.length-1].postSet += ident + '=' + phid + ';';
- phis[i].assignTo = phid;
- func.variables[phid] = {
- ident: phid,
- type: func.variables[ident].type,
- origin: func.variables[ident].origin,
- lineNum: func.variables[ident].lineNum,
- uses: 1,
- impl: VAR_EMULATED
- };
- }
- }
- });
- } else {
- // MICRO_OPTS == 1: Properly implement phis, by pushing them back into the branch
- // that leads to here. We will only have the |var| definition in this location.
-
- // First, push phis back
- func.labels.forEach(function(label) {
- label.lines.forEach(function(phi) {
- if (phi.intertype == 'phi') {
- for (var i = 0; i < phi.params.length; i++) {
- var param = phi.params[i];
- var sourceLabelId = getActualLabelId(param.label);
- if (sourceLabelId) {
- var sourceLabel = func.labelsDict[sourceLabelId];
- var lastLine = sourceLabel.lines.slice(-1)[0];
- assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
- if (!lastLine.phi) {
- lastLine.phi = true;
- assert(!lastLine.dependent);
- lastLine.dependent = {
- intertype: 'phiassigns',
- params: []
- };
+ // First, push phis back
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ var param = phi.params[i];
+ if (!param.label) warn('phi refers to nonexistent label on line ' + phi.lineNum);
+ var sourceLabelId = getActualLabelId(param.label);
+ if (sourceLabelId) {
+ var sourceLabel = func.labelsDict[sourceLabelId];
+ var lastLine = sourceLabel.lines.slice(-1)[0];
+ assert(lastLine.intertype in LLVM.PHI_REACHERS, 'Only some can lead to labels with phis:' + [func.ident, label.ident, lastLine.intertype]);
+ if (!lastLine.phi) {
+ lastLine.phi = true;
+ assert(!lastLine.dependent);
+ lastLine.dependent = {
+ intertype: 'phiassigns',
+ params: []
};
- lastLine.dependent.params.push({
- intertype: 'phiassign',
- ident: phi.assignTo,
- value: param.value,
- targetLabel: label.ident
- });
- }
+ };
+ lastLine.dependent.params.push({
+ intertype: 'phiassign',
+ ident: phi.assignTo,
+ value: param.value,
+ targetLabel: label.ident
+ });
}
- // The assign to phi is now just a var
- phi.intertype = 'var';
- phi.ident = phi.assignTo;
- phi.assignTo = null;
}
- });
+ // The assign to phi is now just a var
+ phi.intertype = 'var';
+ phi.ident = phi.assignTo;
+ phi.assignTo = null;
+ }
});
- }
+ });
});
this.forwardItem(item, 'StackAnalyzer');
}
diff --git a/src/compiler.js b/src/compiler.js
index c39927e7..89da32d5 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -29,11 +29,14 @@ if (ENVIRONMENT_IS_NODE) {
};
var nodeFS = require('fs');
+ var nodePath = require('path');
read = function(filename) {
+ filename = nodePath['normalize'](filename);
var ret = nodeFS['readFileSync'](filename).toString();
- if (!ret && filename[0] != '/') {
- filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename;
+ // The path is absolute if the normalized version is the same as the resolved.
+ if (!ret && filename != nodePath['resolve'](filename)) {
+ filename = path.join(__dirname, '..', 'src', filename);
ret = nodeFS['readFileSync'](filename).toString();
}
return ret;
@@ -111,6 +114,7 @@ load('settings.js');
var settings_file = arguments_[0];
var ll_file = arguments_[1];
+additionalLibraries = Array.prototype.slice.call(arguments_, 2);
if (settings_file) {
var settings = JSON.parse(read(settings_file));
@@ -119,6 +123,7 @@ if (settings_file) {
}
}
+
if (CORRECT_SIGNS >= 2) {
CORRECT_SIGNS_LINES = set(CORRECT_SIGNS_LINES); // for fast checking
}
@@ -141,6 +146,8 @@ if (PGO) { // by default, correct everything during PGO
EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS);
EXPORTED_GLOBALS = set(EXPORTED_GLOBALS);
+RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG;
+
// Settings sanity checks
assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS == 2, must have normal QUANTUM_SIZE of 4');
diff --git a/src/experimental/stringCache.diff b/src/experimental/stringCache.diff
new file mode 100644
index 00000000..26cbc68c
--- /dev/null
+++ b/src/experimental/stringCache.diff
@@ -0,0 +1,147 @@
+diff --git a/src/library_gl.js b/src/library_gl.js
+index 7471578..9228964 100644
+--- a/src/library_gl.js
++++ b/src/library_gl.js
+@@ -1256,28 +1256,28 @@ var LibraryGL = {
+
+ setClientAttribute: function(name, size, type, stride, pointer) {
+ var attrib = this.clientAttributes[GL.immediate.ATTRIBUTE_BY_NAME[name]];
+ attrib.size = size;
+ attrib.type = type;
+ attrib.stride = stride;
+ attrib.pointer = pointer;
+- attrib.name = name + size;
++ attrib.name = Runtime.getStringConcat(name, size);
+ },
+
+ // Renderers
+ addRendererComponent: function(component) {
+ if (this.rendererComponents[component]) return;
+ this.rendererComponents[component] = 1;
+- this.renderer += component;
++ this.renderer = Runtime.getStringConcat(this.renderer, component);
+ },
+
+ setRenderer: function(renderer) {
+ var name = renderer;
+ if (GL.currProgram && renderer[0] != 'U') {
+- name = 'UD' + GL.currProgram + '|' + renderer; // user-defined program renderer
++ name = Runtime.getStringConcat(Runtime.getStringConcat('UD', GL.currProgram), Runtime.getStringConcat('|', renderer)); // user-defined program renderer
+ }
+ this.renderer = name;
+ if (this.renderers[name]) return this.renderers[name];
+ this.renderers[name] = this.createRenderer(renderer);
+ return this.renderers[name];
+ },
+
+@@ -1300,15 +1300,18 @@ var LibraryGL = {
+ }
+ vertexSize += size * 4; // XXX assuming float
+ } else if (which == 'N') {
+ vertexSize += 4; // 1 char, + alignment
+ } else if (which == 'C') {
+ vertexSize += 4; // Up to 4 chars, + alignment
+ } else {
+- console.log('Warning: Ignoring renderer attribute ' + which);
++#if ASSERTIONS
++ console.log('Warning: Ignoring renderer attribute');
++ console.log(which);
++#endif
+ size = parseInt(renderer[i+1]);
+ vertexSize += size * 4; // XXX assuming float
+ }
+ }
+ assert(positionSize > 0);
+ // TODO: verify vertexSize is equal to the stride in enabled client arrays
+ var useCurrProgram = !!GL.currProgram;
+@@ -1465,30 +1468,30 @@ var LibraryGL = {
+ var renderer = '', bytes = 0;
+ for (var i = 0; i < attributes.length; i++) {
+ var attribute = attributes[i];
+ if (!attribute) break;
+ attribute.offset = attribute.pointer - start;
+ if (attribute.offset > bytes) { // ensure we start where we should
+ assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment
+- renderer += '?' + ((attribute.offset - bytes)/4);
++ renderer = Runtime.getStringConcat(renderer, Runtime.getStringConcat('?', ((attribute.offset - bytes)/4)));
+ bytes += attribute.offset - bytes;
+ }
+- renderer += attribute.name;
++ renderer = Runtime.getStringConcat(renderer, attribute.name);
+ bytes += attribute.size * GL.immediate.byteSizeByType[attribute.type];
+ if (bytes % 4 != 0) bytes += 4 - (bytes % 4); // XXX assuming 4-alignment
+ #if ASSERTIONS
+ assert(0 <= attribute.offset && attribute.offset < stride); // must all be in the same buffer
+ #endif
+ }
+
+ assert(stride == 0 || bytes <= stride);
+
+ if (bytes < stride) { // ensure the size is that of the stride
+ assert((stride - bytes)%4 == 0); // assuming float
+- renderer += '?' + ((stride-bytes)/4);
++ renderer = Runtime.getStringConcat(renderer, Runtime.getStringConcat('?', ((stride-bytes)/4)));
+ bytes = stride;
+ }
+
+ bytes *= count;
+ if (!GL.currArrayBuffer) {
+ GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float
+ }
+@@ -1671,15 +1674,15 @@ var LibraryGL = {
+ },
+
+ glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation
+ glVertexPointer: function(size, type, stride, pointer) {
+ GL.immediate.setClientAttribute('V', size, type, stride, pointer);
+ },
+ glTexCoordPointer: function(size, type, stride, pointer) {
+- GL.immediate.setClientAttribute('T' + GL.immediate.clientActiveTexture, size, type, stride, pointer);
++ GL.immediate.setClientAttribute(Runtime.getStringConcat('T', GL.immediate.clientActiveTexture), size, type, stride, pointer);
+ },
+ glNormalPointer: function(type, stride, pointer) {
+ GL.immediate.setClientAttribute('N', 1, type, stride, pointer);
+ },
+ glColorPointer: function(size, type, stride, pointer) {
+ GL.immediate.setClientAttribute('C', size, type, stride, pointer);
+ },
+diff --git a/src/runtime.js b/src/runtime.js
+index 6a251c4..012a66d 100644
+--- a/src/runtime.js
++++ b/src/runtime.js
+@@ -319,25 +319,34 @@ var Runtime = {
+ if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+ if (!Runtime.warnOnce.shown[text]) {
+ Runtime.warnOnce.shown[text] = 1;
+ Module.printErr(text);
+ }
+ },
+
++ // Cache for JS function wrappers for C functions in FUNCTION_TABLE
+ funcWrappers: {},
+-
+ getFuncWrapper: function(func) {
+ if (!Runtime.funcWrappers[func]) {
+ Runtime.funcWrappers[func] = function() {
+ FUNCTION_TABLE[func].apply(null, arguments);
+ };
+ }
+ return Runtime.funcWrappers[func];
+ },
+
++ // Cache for small recurring strings generated by concatenating other
++ // strings, use this to avoid needless allocation and collection
++ stringCache: {},
++ getStringConcat: function(a, b) {
++ var cacheItem = Runtime.stringCache[a];
++ if (!cacheItem) cacheItem = Runtime.stringCache[a] = {};
++ return cacheItem[b] || (cacheItem[b] = a + b);
++ },
++
+ #if RUNTIME_DEBUG
+ debug: true, // Switch to false at runtime to disable logging at the right times
+
+ printObjectList: [],
+
+ prettyPrint: function(arg) {
+ if (typeof arg == 'undefined') return '!UNDEFINED!';
diff --git a/src/gl-matrix.js b/src/gl-matrix.js
new file mode 100644
index 00000000..a21cd431
--- /dev/null
+++ b/src/gl-matrix.js
@@ -0,0 +1,1952 @@
+(function() {
+
+/**
+ * @fileoverview gl-matrix - High performance matrix and vector operations for WebGL
+ * @author Brandon Jones
+ * @version 1.2.4
+ */
+
+// Modifed for emscripten: Global scoping etc.
+
+/*
+ * Copyright (c) 2011 Brandon Jones
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+
+/**
+ * @class 3 Dimensional Vector
+ * @name vec3
+ */
+var vec3 = {};
+
+/**
+ * @class 3x3 Matrix
+ * @name mat3
+ */
+var mat3 = {};
+
+/**
+ * @class 4x4 Matrix
+ * @name mat4
+ */
+var mat4 = {};
+
+/**
+ * @class Quaternion
+ * @name quat4
+ */
+var quat4 = {};
+
+var MatrixArray = Float32Array;
+
+/*
+ * vec3
+ */
+
+/**
+ * Creates a new instance of a vec3 using the default array type
+ * Any javascript array-like objects containing at least 3 numeric elements can serve as a vec3
+ *
+ * @param {vec3} [vec] vec3 containing values to initialize with
+ *
+ * @returns {vec3} New vec3
+ */
+vec3.create = function (vec) {
+ var dest = new MatrixArray(3);
+
+ if (vec) {
+ dest[0] = vec[0];
+ dest[1] = vec[1];
+ dest[2] = vec[2];
+ } else {
+ dest[0] = dest[1] = dest[2] = 0;
+ }
+
+ return dest;
+};
+
+/**
+ * Copies the values of one vec3 to another
+ *
+ * @param {vec3} vec vec3 containing values to copy
+ * @param {vec3} dest vec3 receiving copied values
+ *
+ * @returns {vec3} dest
+ */
+vec3.set = function (vec, dest) {
+ dest[0] = vec[0];
+ dest[1] = vec[1];
+ dest[2] = vec[2];
+
+ return dest;
+};
+
+/**
+ * Performs a vector addition
+ *
+ * @param {vec3} vec First operand
+ * @param {vec3} vec2 Second operand
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.add = function (vec, vec2, dest) {
+ if (!dest || vec === dest) {
+ vec[0] += vec2[0];
+ vec[1] += vec2[1];
+ vec[2] += vec2[2];
+ return vec;
+ }
+
+ dest[0] = vec[0] + vec2[0];
+ dest[1] = vec[1] + vec2[1];
+ dest[2] = vec[2] + vec2[2];
+ return dest;
+};
+
+/**
+ * Performs a vector subtraction
+ *
+ * @param {vec3} vec First operand
+ * @param {vec3} vec2 Second operand
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.subtract = function (vec, vec2, dest) {
+ if (!dest || vec === dest) {
+ vec[0] -= vec2[0];
+ vec[1] -= vec2[1];
+ vec[2] -= vec2[2];
+ return vec;
+ }
+
+ dest[0] = vec[0] - vec2[0];
+ dest[1] = vec[1] - vec2[1];
+ dest[2] = vec[2] - vec2[2];
+ return dest;
+};
+
+/**
+ * Performs a vector multiplication
+ *
+ * @param {vec3} vec First operand
+ * @param {vec3} vec2 Second operand
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.multiply = function (vec, vec2, dest) {
+ if (!dest || vec === dest) {
+ vec[0] *= vec2[0];
+ vec[1] *= vec2[1];
+ vec[2] *= vec2[2];
+ return vec;
+ }
+
+ dest[0] = vec[0] * vec2[0];
+ dest[1] = vec[1] * vec2[1];
+ dest[2] = vec[2] * vec2[2];
+ return dest;
+};
+
+/**
+ * Negates the components of a vec3
+ *
+ * @param {vec3} vec vec3 to negate
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.negate = function (vec, dest) {
+ if (!dest) { dest = vec; }
+
+ dest[0] = -vec[0];
+ dest[1] = -vec[1];
+ dest[2] = -vec[2];
+ return dest;
+};
+
+/**
+ * Multiplies the components of a vec3 by a scalar value
+ *
+ * @param {vec3} vec vec3 to scale
+ * @param {number} val Value to scale by
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.scale = function (vec, val, dest) {
+ if (!dest || vec === dest) {
+ vec[0] *= val;
+ vec[1] *= val;
+ vec[2] *= val;
+ return vec;
+ }
+
+ dest[0] = vec[0] * val;
+ dest[1] = vec[1] * val;
+ dest[2] = vec[2] * val;
+ return dest;
+};
+
+/**
+ * Generates a unit vector of the same direction as the provided vec3
+ * If vector length is 0, returns [0, 0, 0]
+ *
+ * @param {vec3} vec vec3 to normalize
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.normalize = function (vec, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0], y = vec[1], z = vec[2],
+ len = Math.sqrt(x * x + y * y + z * z);
+
+ if (!len) {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ return dest;
+ } else if (len === 1) {
+ dest[0] = x;
+ dest[1] = y;
+ dest[2] = z;
+ return dest;
+ }
+
+ len = 1 / len;
+ dest[0] = x * len;
+ dest[1] = y * len;
+ dest[2] = z * len;
+ return dest;
+};
+
+/**
+ * Generates the cross product of two vec3s
+ *
+ * @param {vec3} vec First operand
+ * @param {vec3} vec2 Second operand
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.cross = function (vec, vec2, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0], y = vec[1], z = vec[2],
+ x2 = vec2[0], y2 = vec2[1], z2 = vec2[2];
+
+ dest[0] = y * z2 - z * y2;
+ dest[1] = z * x2 - x * z2;
+ dest[2] = x * y2 - y * x2;
+ return dest;
+};
+
+/**
+ * Caclulates the length of a vec3
+ *
+ * @param {vec3} vec vec3 to calculate length of
+ *
+ * @returns {number} Length of vec
+ */
+vec3.length = function (vec) {
+ var x = vec[0], y = vec[1], z = vec[2];
+ return Math.sqrt(x * x + y * y + z * z);
+};
+
+/**
+ * Caclulates the dot product of two vec3s
+ *
+ * @param {vec3} vec First operand
+ * @param {vec3} vec2 Second operand
+ *
+ * @returns {number} Dot product of vec and vec2
+ */
+vec3.dot = function (vec, vec2) {
+ return vec[0] * vec2[0] + vec[1] * vec2[1] + vec[2] * vec2[2];
+};
+
+/**
+ * Generates a unit vector pointing from one vector to another
+ *
+ * @param {vec3} vec Origin vec3
+ * @param {vec3} vec2 vec3 to point to
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.direction = function (vec, vec2, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0] - vec2[0],
+ y = vec[1] - vec2[1],
+ z = vec[2] - vec2[2],
+ len = Math.sqrt(x * x + y * y + z * z);
+
+ if (!len) {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ return dest;
+ }
+
+ len = 1 / len;
+ dest[0] = x * len;
+ dest[1] = y * len;
+ dest[2] = z * len;
+ return dest;
+};
+
+/**
+ * Performs a linear interpolation between two vec3
+ *
+ * @param {vec3} vec First vector
+ * @param {vec3} vec2 Second vector
+ * @param {number} lerp Interpolation amount between the two inputs
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.lerp = function (vec, vec2, lerp, dest) {
+ if (!dest) { dest = vec; }
+
+ dest[0] = vec[0] + lerp * (vec2[0] - vec[0]);
+ dest[1] = vec[1] + lerp * (vec2[1] - vec[1]);
+ dest[2] = vec[2] + lerp * (vec2[2] - vec[2]);
+
+ return dest;
+};
+
+/**
+ * Calculates the euclidian distance between two vec3
+ *
+ * Params:
+ * @param {vec3} vec First vector
+ * @param {vec3} vec2 Second vector
+ *
+ * @returns {number} Distance between vec and vec2
+ */
+vec3.dist = function (vec, vec2) {
+ var x = vec2[0] - vec[0],
+ y = vec2[1] - vec[1],
+ z = vec2[2] - vec[2];
+
+ return Math.sqrt(x*x + y*y + z*z);
+};
+
+/**
+ * Projects the specified vec3 from screen space into object space
+ * Based on the <a href="http://webcvs.freedesktop.org/mesa/Mesa/src/glu/mesa/project.c?revision=1.4&view=markup">Mesa gluUnProject implementation</a>
+ *
+ * @param {vec3} vec Screen-space vector to project
+ * @param {mat4} view View matrix
+ * @param {mat4} proj Projection matrix
+ * @param {vec4} viewport Viewport as given to gl.viewport [x, y, width, height]
+ * @param {vec3} [dest] vec3 receiving unprojected result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+vec3.unproject = function (vec, view, proj, viewport, dest) {
+ if (!dest) { dest = vec; }
+
+ var m = mat4.create();
+ var v = new MatrixArray(4);
+
+ v[0] = (vec[0] - viewport[0]) * 2.0 / viewport[2] - 1.0;
+ v[1] = (vec[1] - viewport[1]) * 2.0 / viewport[3] - 1.0;
+ v[2] = 2.0 * vec[2] - 1.0;
+ v[3] = 1.0;
+
+ mat4.multiply(proj, view, m);
+ if(!mat4.inverse(m)) { return null; }
+
+ mat4.multiplyVec4(m, v);
+ if(v[3] === 0.0) { return null; }
+
+ dest[0] = v[0] / v[3];
+ dest[1] = v[1] / v[3];
+ dest[2] = v[2] / v[3];
+
+ return dest;
+};
+
+/**
+ * Returns a string representation of a vector
+ *
+ * @param {vec3} vec Vector to represent as a string
+ *
+ * @returns {string} String representation of vec
+ */
+vec3.str = function (vec) {
+ return '[' + vec[0] + ', ' + vec[1] + ', ' + vec[2] + ']';
+};
+
+/*
+ * mat3
+ */
+
+/**
+ * Creates a new instance of a mat3 using the default array type
+ * Any javascript array-like object containing at least 9 numeric elements can serve as a mat3
+ *
+ * @param {mat3} [mat] mat3 containing values to initialize with
+ *
+ * @returns {mat3} New mat3
+ */
+mat3.create = function (mat) {
+ var dest = new MatrixArray(9);
+
+ if (mat) {
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+ dest[8] = mat[8];
+ }
+
+ return dest;
+};
+
+/**
+ * Copies the values of one mat3 to another
+ *
+ * @param {mat3} mat mat3 containing values to copy
+ * @param {mat3} dest mat3 receiving copied values
+ *
+ * @returns {mat3} dest
+ */
+mat3.set = function (mat, dest) {
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+ dest[8] = mat[8];
+ return dest;
+};
+
+/**
+ * Sets a mat3 to an identity matrix
+ *
+ * @param {mat3} dest mat3 to set
+ *
+ * @returns dest if specified, otherwise a new mat3
+ */
+mat3.identity = function (dest) {
+ if (!dest) { dest = mat3.create(); }
+ dest[0] = 1;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ dest[4] = 1;
+ dest[5] = 0;
+ dest[6] = 0;
+ dest[7] = 0;
+ dest[8] = 1;
+ return dest;
+};
+
+/**
+ * Transposes a mat3 (flips the values over the diagonal)
+ *
+ * Params:
+ * @param {mat3} mat mat3 to transpose
+ * @param {mat3} [dest] mat3 receiving transposed values. If not specified result is written to mat
+ *
+ * @returns {mat3} dest is specified, mat otherwise
+ */
+mat3.transpose = function (mat, dest) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (!dest || mat === dest) {
+ var a01 = mat[1], a02 = mat[2],
+ a12 = mat[5];
+
+ mat[1] = mat[3];
+ mat[2] = mat[6];
+ mat[3] = a01;
+ mat[5] = mat[7];
+ mat[6] = a02;
+ mat[7] = a12;
+ return mat;
+ }
+
+ dest[0] = mat[0];
+ dest[1] = mat[3];
+ dest[2] = mat[6];
+ dest[3] = mat[1];
+ dest[4] = mat[4];
+ dest[5] = mat[7];
+ dest[6] = mat[2];
+ dest[7] = mat[5];
+ dest[8] = mat[8];
+ return dest;
+};
+
+/**
+ * Copies the elements of a mat3 into the upper 3x3 elements of a mat4
+ *
+ * @param {mat3} mat mat3 containing values to copy
+ * @param {mat4} [dest] mat4 receiving copied values
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat3.toMat4 = function (mat, dest) {
+ if (!dest) { dest = mat4.create(); }
+
+ dest[15] = 1;
+ dest[14] = 0;
+ dest[13] = 0;
+ dest[12] = 0;
+
+ dest[11] = 0;
+ dest[10] = mat[8];
+ dest[9] = mat[7];
+ dest[8] = mat[6];
+
+ dest[7] = 0;
+ dest[6] = mat[5];
+ dest[5] = mat[4];
+ dest[4] = mat[3];
+
+ dest[3] = 0;
+ dest[2] = mat[2];
+ dest[1] = mat[1];
+ dest[0] = mat[0];
+
+ return dest;
+};
+
+/**
+ * Returns a string representation of a mat3
+ *
+ * @param {mat3} mat mat3 to represent as a string
+ *
+ * @param {string} String representation of mat
+ */
+mat3.str = function (mat) {
+ return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] +
+ ', ' + mat[3] + ', ' + mat[4] + ', ' + mat[5] +
+ ', ' + mat[6] + ', ' + mat[7] + ', ' + mat[8] + ']';
+};
+
+/*
+ * mat4
+ */
+
+/**
+ * Creates a new instance of a mat4 using the default array type
+ * Any javascript array-like object containing at least 16 numeric elements can serve as a mat4
+ *
+ * @param {mat4} [mat] mat4 containing values to initialize with
+ *
+ * @returns {mat4} New mat4
+ */
+mat4.create = function (mat) {
+ var dest = new MatrixArray(16);
+
+ if (mat) {
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+ dest[8] = mat[8];
+ dest[9] = mat[9];
+ dest[10] = mat[10];
+ dest[11] = mat[11];
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ }
+
+ return dest;
+};
+
+/**
+ * Copies the values of one mat4 to another
+ *
+ * @param {mat4} mat mat4 containing values to copy
+ * @param {mat4} dest mat4 receiving copied values
+ *
+ * @returns {mat4} dest
+ */
+mat4.set = function (mat, dest) {
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+ dest[8] = mat[8];
+ dest[9] = mat[9];
+ dest[10] = mat[10];
+ dest[11] = mat[11];
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ return dest;
+};
+
+/**
+ * Sets a mat4 to an identity matrix
+ *
+ * @param {mat4} dest mat4 to set
+ *
+ * @returns {mat4} dest
+ */
+mat4.identity = function (dest) {
+ if (!dest) { dest = mat4.create(); }
+ dest[0] = 1;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ dest[4] = 0;
+ dest[5] = 1;
+ dest[6] = 0;
+ dest[7] = 0;
+ dest[8] = 0;
+ dest[9] = 0;
+ dest[10] = 1;
+ dest[11] = 0;
+ dest[12] = 0;
+ dest[13] = 0;
+ dest[14] = 0;
+ dest[15] = 1;
+ return dest;
+};
+
+/**
+ * Transposes a mat4 (flips the values over the diagonal)
+ *
+ * @param {mat4} mat mat4 to transpose
+ * @param {mat4} [dest] mat4 receiving transposed values. If not specified result is written to mat
+ *
+ * @param {mat4} dest is specified, mat otherwise
+ */
+mat4.transpose = function (mat, dest) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (!dest || mat === dest) {
+ var a01 = mat[1], a02 = mat[2], a03 = mat[3],
+ a12 = mat[6], a13 = mat[7],
+ a23 = mat[11];
+
+ mat[1] = mat[4];
+ mat[2] = mat[8];
+ mat[3] = mat[12];
+ mat[4] = a01;
+ mat[6] = mat[9];
+ mat[7] = mat[13];
+ mat[8] = a02;
+ mat[9] = a12;
+ mat[11] = mat[14];
+ mat[12] = a03;
+ mat[13] = a13;
+ mat[14] = a23;
+ return mat;
+ }
+
+ dest[0] = mat[0];
+ dest[1] = mat[4];
+ dest[2] = mat[8];
+ dest[3] = mat[12];
+ dest[4] = mat[1];
+ dest[5] = mat[5];
+ dest[6] = mat[9];
+ dest[7] = mat[13];
+ dest[8] = mat[2];
+ dest[9] = mat[6];
+ dest[10] = mat[10];
+ dest[11] = mat[14];
+ dest[12] = mat[3];
+ dest[13] = mat[7];
+ dest[14] = mat[11];
+ dest[15] = mat[15];
+ return dest;
+};
+
+/**
+ * Calculates the determinant of a mat4
+ *
+ * @param {mat4} mat mat4 to calculate determinant of
+ *
+ * @returns {number} determinant of mat
+ */
+mat4.determinant = function (mat) {
+ // Cache the matrix values (makes for huge speed increases!)
+ var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
+ a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
+ a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
+ a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15];
+
+ return (a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03 + a10 * a31 * a22 * a03 +
+ a20 * a11 * a32 * a03 - a10 * a21 * a32 * a03 - a30 * a21 * a02 * a13 + a20 * a31 * a02 * a13 +
+ a30 * a01 * a22 * a13 - a00 * a31 * a22 * a13 - a20 * a01 * a32 * a13 + a00 * a21 * a32 * a13 +
+ a30 * a11 * a02 * a23 - a10 * a31 * a02 * a23 - a30 * a01 * a12 * a23 + a00 * a31 * a12 * a23 +
+ a10 * a01 * a32 * a23 - a00 * a11 * a32 * a23 - a20 * a11 * a02 * a33 + a10 * a21 * a02 * a33 +
+ a20 * a01 * a12 * a33 - a00 * a21 * a12 * a33 - a10 * a01 * a22 * a33 + a00 * a11 * a22 * a33);
+};
+
+/**
+ * Calculates the inverse matrix of a mat4
+ *
+ * @param {mat4} mat mat4 to calculate inverse of
+ * @param {mat4} [dest] mat4 receiving inverse matrix. If not specified result is written to mat
+ *
+ * @param {mat4} dest is specified, mat otherwise, null if matrix cannot be inverted
+ */
+mat4.inverse = function (mat, dest) {
+ if (!dest) { dest = mat; }
+
+ // Cache the matrix values (makes for huge speed increases!)
+ var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
+ a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
+ a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
+ a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15],
+
+ b00 = a00 * a11 - a01 * a10,
+ b01 = a00 * a12 - a02 * a10,
+ b02 = a00 * a13 - a03 * a10,
+ b03 = a01 * a12 - a02 * a11,
+ b04 = a01 * a13 - a03 * a11,
+ b05 = a02 * a13 - a03 * a12,
+ b06 = a20 * a31 - a21 * a30,
+ b07 = a20 * a32 - a22 * a30,
+ b08 = a20 * a33 - a23 * a30,
+ b09 = a21 * a32 - a22 * a31,
+ b10 = a21 * a33 - a23 * a31,
+ b11 = a22 * a33 - a23 * a32,
+
+ d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06),
+ invDet;
+
+ // Calculate the determinant
+ if (!d) { return null; }
+ invDet = 1 / d;
+
+ dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
+ dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
+ dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
+ dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
+ dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
+ dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
+ dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
+ dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
+ dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
+ dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
+ dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
+ dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
+ dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
+ dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
+ dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
+ dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
+
+ return dest;
+};
+
+/**
+ * Copies the upper 3x3 elements of a mat4 into another mat4
+ *
+ * @param {mat4} mat mat4 containing values to copy
+ * @param {mat4} [dest] mat4 receiving copied values
+ *
+ * @returns {mat4} dest is specified, a new mat4 otherwise
+ */
+mat4.toRotationMat = function (mat, dest) {
+ if (!dest) { dest = mat4.create(); }
+
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+ dest[8] = mat[8];
+ dest[9] = mat[9];
+ dest[10] = mat[10];
+ dest[11] = mat[11];
+ dest[12] = 0;
+ dest[13] = 0;
+ dest[14] = 0;
+ dest[15] = 1;
+
+ return dest;
+};
+
+/**
+ * Copies the upper 3x3 elements of a mat4 into a mat3
+ *
+ * @param {mat4} mat mat4 containing values to copy
+ * @param {mat3} [dest] mat3 receiving copied values
+ *
+ * @returns {mat3} dest is specified, a new mat3 otherwise
+ */
+mat4.toMat3 = function (mat, dest) {
+ if (!dest) { dest = mat3.create(); }
+
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[4];
+ dest[4] = mat[5];
+ dest[5] = mat[6];
+ dest[6] = mat[8];
+ dest[7] = mat[9];
+ dest[8] = mat[10];
+
+ return dest;
+};
+
+/**
+ * Calculates the inverse of the upper 3x3 elements of a mat4 and copies the result into a mat3
+ * The resulting matrix is useful for calculating transformed normals
+ *
+ * Params:
+ * @param {mat4} mat mat4 containing values to invert and copy
+ * @param {mat3} [dest] mat3 receiving values
+ *
+ * @returns {mat3} dest is specified, a new mat3 otherwise, null if the matrix cannot be inverted
+ */
+mat4.toInverseMat3 = function (mat, dest) {
+ // Cache the matrix values (makes for huge speed increases!)
+ var a00 = mat[0], a01 = mat[1], a02 = mat[2],
+ a10 = mat[4], a11 = mat[5], a12 = mat[6],
+ a20 = mat[8], a21 = mat[9], a22 = mat[10],
+
+ b01 = a22 * a11 - a12 * a21,
+ b11 = -a22 * a10 + a12 * a20,
+ b21 = a21 * a10 - a11 * a20,
+
+ d = a00 * b01 + a01 * b11 + a02 * b21,
+ id;
+
+ if (!d) { return null; }
+ id = 1 / d;
+
+ if (!dest) { dest = mat3.create(); }
+
+ dest[0] = b01 * id;
+ dest[1] = (-a22 * a01 + a02 * a21) * id;
+ dest[2] = (a12 * a01 - a02 * a11) * id;
+ dest[3] = b11 * id;
+ dest[4] = (a22 * a00 - a02 * a20) * id;
+ dest[5] = (-a12 * a00 + a02 * a10) * id;
+ dest[6] = b21 * id;
+ dest[7] = (-a21 * a00 + a01 * a20) * id;
+ dest[8] = (a11 * a00 - a01 * a10) * id;
+
+ return dest;
+};
+
+/**
+ * Performs a matrix multiplication
+ *
+ * @param {mat4} mat First operand
+ * @param {mat4} mat2 Second operand
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.multiply = function (mat, mat2, dest) {
+ if (!dest) { dest = mat; }
+
+ // Cache the matrix values (makes for huge speed increases!)
+ var a00 = mat[0], a01 = mat[1], a02 = mat[2], a03 = mat[3],
+ a10 = mat[4], a11 = mat[5], a12 = mat[6], a13 = mat[7],
+ a20 = mat[8], a21 = mat[9], a22 = mat[10], a23 = mat[11],
+ a30 = mat[12], a31 = mat[13], a32 = mat[14], a33 = mat[15],
+
+ b00 = mat2[0], b01 = mat2[1], b02 = mat2[2], b03 = mat2[3],
+ b10 = mat2[4], b11 = mat2[5], b12 = mat2[6], b13 = mat2[7],
+ b20 = mat2[8], b21 = mat2[9], b22 = mat2[10], b23 = mat2[11],
+ b30 = mat2[12], b31 = mat2[13], b32 = mat2[14], b33 = mat2[15];
+
+ dest[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
+ dest[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
+ dest[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
+ dest[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
+ dest[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
+ dest[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
+ dest[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
+ dest[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
+ dest[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
+ dest[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
+ dest[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
+ dest[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
+ dest[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
+ dest[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
+ dest[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
+ dest[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
+
+ return dest;
+};
+
+/**
+ * Transforms a vec3 with the given matrix
+ * 4th vector component is implicitly '1'
+ *
+ * @param {mat4} mat mat4 to transform the vector with
+ * @param {vec3} vec vec3 to transform
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec3} dest if specified, vec otherwise
+ */
+mat4.multiplyVec3 = function (mat, vec, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0], y = vec[1], z = vec[2];
+
+ dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
+ dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
+ dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
+
+ return dest;
+};
+
+/**
+ * Transforms a vec4 with the given matrix
+ *
+ * @param {mat4} mat mat4 to transform the vector with
+ * @param {vec4} vec vec4 to transform
+ * @param {vec4} [dest] vec4 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec4} dest if specified, vec otherwise
+ */
+mat4.multiplyVec4 = function (mat, vec, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0], y = vec[1], z = vec[2], w = vec[3];
+
+ dest[0] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12] * w;
+ dest[1] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13] * w;
+ dest[2] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14] * w;
+ dest[3] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15] * w;
+
+ return dest;
+};
+
+/**
+ * Translates a matrix by the given vector
+ *
+ * @param {mat4} mat mat4 to translate
+ * @param {vec3} vec vec3 specifying the translation
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.translate = function (mat, vec, dest) {
+ var x = vec[0], y = vec[1], z = vec[2],
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23;
+
+ if (!dest || mat === dest) {
+ mat[12] = mat[0] * x + mat[4] * y + mat[8] * z + mat[12];
+ mat[13] = mat[1] * x + mat[5] * y + mat[9] * z + mat[13];
+ mat[14] = mat[2] * x + mat[6] * y + mat[10] * z + mat[14];
+ mat[15] = mat[3] * x + mat[7] * y + mat[11] * z + mat[15];
+ return mat;
+ }
+
+ a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
+ a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
+ a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
+
+ dest[0] = a00; dest[1] = a01; dest[2] = a02; dest[3] = a03;
+ dest[4] = a10; dest[5] = a11; dest[6] = a12; dest[7] = a13;
+ dest[8] = a20; dest[9] = a21; dest[10] = a22; dest[11] = a23;
+
+ dest[12] = a00 * x + a10 * y + a20 * z + mat[12];
+ dest[13] = a01 * x + a11 * y + a21 * z + mat[13];
+ dest[14] = a02 * x + a12 * y + a22 * z + mat[14];
+ dest[15] = a03 * x + a13 * y + a23 * z + mat[15];
+ return dest;
+};
+
+/**
+ * Scales a matrix by the given vector
+ *
+ * @param {mat4} mat mat4 to scale
+ * @param {vec3} vec vec3 specifying the scale for each axis
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @param {mat4} dest if specified, mat otherwise
+ */
+mat4.scale = function (mat, vec, dest) {
+ var x = vec[0], y = vec[1], z = vec[2];
+
+ if (!dest || mat === dest) {
+ mat[0] *= x;
+ mat[1] *= x;
+ mat[2] *= x;
+ mat[3] *= x;
+ mat[4] *= y;
+ mat[5] *= y;
+ mat[6] *= y;
+ mat[7] *= y;
+ mat[8] *= z;
+ mat[9] *= z;
+ mat[10] *= z;
+ mat[11] *= z;
+ return mat;
+ }
+
+ dest[0] = mat[0] * x;
+ dest[1] = mat[1] * x;
+ dest[2] = mat[2] * x;
+ dest[3] = mat[3] * x;
+ dest[4] = mat[4] * y;
+ dest[5] = mat[5] * y;
+ dest[6] = mat[6] * y;
+ dest[7] = mat[7] * y;
+ dest[8] = mat[8] * z;
+ dest[9] = mat[9] * z;
+ dest[10] = mat[10] * z;
+ dest[11] = mat[11] * z;
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ return dest;
+};
+
+/**
+ * Rotates a matrix by the given angle around the specified axis
+ * If rotating around a primary axis (X,Y,Z) one of the specialized rotation functions should be used instead for performance
+ *
+ * @param {mat4} mat mat4 to rotate
+ * @param {number} angle Angle (in radians) to rotate
+ * @param {vec3} axis vec3 representing the axis to rotate around
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.rotate = function (mat, angle, axis, dest) {
+ var x = axis[0], y = axis[1], z = axis[2],
+ len = Math.sqrt(x * x + y * y + z * z),
+ s, c, t,
+ a00, a01, a02, a03,
+ a10, a11, a12, a13,
+ a20, a21, a22, a23,
+ b00, b01, b02,
+ b10, b11, b12,
+ b20, b21, b22;
+
+ if (!len) { return null; }
+ if (len !== 1) {
+ len = 1 / len;
+ x *= len;
+ y *= len;
+ z *= len;
+ }
+
+ s = Math.sin(angle);
+ c = Math.cos(angle);
+ t = 1 - c;
+
+ a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3];
+ a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7];
+ a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11];
+
+ // Construct the elements of the rotation matrix
+ b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
+ b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
+ b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
+
+ if (!dest) {
+ dest = mat;
+ } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ }
+
+ // Perform rotation-specific matrix multiplication
+ dest[0] = a00 * b00 + a10 * b01 + a20 * b02;
+ dest[1] = a01 * b00 + a11 * b01 + a21 * b02;
+ dest[2] = a02 * b00 + a12 * b01 + a22 * b02;
+ dest[3] = a03 * b00 + a13 * b01 + a23 * b02;
+
+ dest[4] = a00 * b10 + a10 * b11 + a20 * b12;
+ dest[5] = a01 * b10 + a11 * b11 + a21 * b12;
+ dest[6] = a02 * b10 + a12 * b11 + a22 * b12;
+ dest[7] = a03 * b10 + a13 * b11 + a23 * b12;
+
+ dest[8] = a00 * b20 + a10 * b21 + a20 * b22;
+ dest[9] = a01 * b20 + a11 * b21 + a21 * b22;
+ dest[10] = a02 * b20 + a12 * b21 + a22 * b22;
+ dest[11] = a03 * b20 + a13 * b21 + a23 * b22;
+ return dest;
+};
+
+/**
+ * Rotates a matrix by the given angle around the X axis
+ *
+ * @param {mat4} mat mat4 to rotate
+ * @param {number} angle Angle (in radians) to rotate
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.rotateX = function (mat, angle, dest) {
+ var s = Math.sin(angle),
+ c = Math.cos(angle),
+ a10 = mat[4],
+ a11 = mat[5],
+ a12 = mat[6],
+ a13 = mat[7],
+ a20 = mat[8],
+ a21 = mat[9],
+ a22 = mat[10],
+ a23 = mat[11];
+
+ if (!dest) {
+ dest = mat;
+ } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ dest[4] = a10 * c + a20 * s;
+ dest[5] = a11 * c + a21 * s;
+ dest[6] = a12 * c + a22 * s;
+ dest[7] = a13 * c + a23 * s;
+
+ dest[8] = a10 * -s + a20 * c;
+ dest[9] = a11 * -s + a21 * c;
+ dest[10] = a12 * -s + a22 * c;
+ dest[11] = a13 * -s + a23 * c;
+ return dest;
+};
+
+/**
+ * Rotates a matrix by the given angle around the Y axis
+ *
+ * @param {mat4} mat mat4 to rotate
+ * @param {number} angle Angle (in radians) to rotate
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.rotateY = function (mat, angle, dest) {
+ var s = Math.sin(angle),
+ c = Math.cos(angle),
+ a00 = mat[0],
+ a01 = mat[1],
+ a02 = mat[2],
+ a03 = mat[3],
+ a20 = mat[8],
+ a21 = mat[9],
+ a22 = mat[10],
+ a23 = mat[11];
+
+ if (!dest) {
+ dest = mat;
+ } else if (mat !== dest) { // If the source and destination differ, copy the unchanged rows
+ dest[4] = mat[4];
+ dest[5] = mat[5];
+ dest[6] = mat[6];
+ dest[7] = mat[7];
+
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ dest[0] = a00 * c + a20 * -s;
+ dest[1] = a01 * c + a21 * -s;
+ dest[2] = a02 * c + a22 * -s;
+ dest[3] = a03 * c + a23 * -s;
+
+ dest[8] = a00 * s + a20 * c;
+ dest[9] = a01 * s + a21 * c;
+ dest[10] = a02 * s + a22 * c;
+ dest[11] = a03 * s + a23 * c;
+ return dest;
+};
+
+/**
+ * Rotates a matrix by the given angle around the Z axis
+ *
+ * @param {mat4} mat mat4 to rotate
+ * @param {number} angle Angle (in radians) to rotate
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to mat
+ *
+ * @returns {mat4} dest if specified, mat otherwise
+ */
+mat4.rotateZ = function (mat, angle, dest) {
+ var s = Math.sin(angle),
+ c = Math.cos(angle),
+ a00 = mat[0],
+ a01 = mat[1],
+ a02 = mat[2],
+ a03 = mat[3],
+ a10 = mat[4],
+ a11 = mat[5],
+ a12 = mat[6],
+ a13 = mat[7];
+
+ if (!dest) {
+ dest = mat;
+ } else if (mat !== dest) { // If the source and destination differ, copy the unchanged last row
+ dest[8] = mat[8];
+ dest[9] = mat[9];
+ dest[10] = mat[10];
+ dest[11] = mat[11];
+
+ dest[12] = mat[12];
+ dest[13] = mat[13];
+ dest[14] = mat[14];
+ dest[15] = mat[15];
+ }
+
+ // Perform axis-specific matrix multiplication
+ dest[0] = a00 * c + a10 * s;
+ dest[1] = a01 * c + a11 * s;
+ dest[2] = a02 * c + a12 * s;
+ dest[3] = a03 * c + a13 * s;
+
+ dest[4] = a00 * -s + a10 * c;
+ dest[5] = a01 * -s + a11 * c;
+ dest[6] = a02 * -s + a12 * c;
+ dest[7] = a03 * -s + a13 * c;
+
+ return dest;
+};
+
+/**
+ * Generates a frustum matrix with the given bounds
+ *
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @param {mat4} [dest] mat4 frustum matrix will be written into
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat4.frustum = function (left, right, bottom, top, near, far, dest) {
+ if (!dest) { dest = mat4.create(); }
+ var rl = (right - left),
+ tb = (top - bottom),
+ fn = (far - near);
+ dest[0] = (near * 2) / rl;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ dest[4] = 0;
+ dest[5] = (near * 2) / tb;
+ dest[6] = 0;
+ dest[7] = 0;
+ dest[8] = (right + left) / rl;
+ dest[9] = (top + bottom) / tb;
+ dest[10] = -(far + near) / fn;
+ dest[11] = -1;
+ dest[12] = 0;
+ dest[13] = 0;
+ dest[14] = -(far * near * 2) / fn;
+ dest[15] = 0;
+ return dest;
+};
+
+/**
+ * Generates a perspective projection matrix with the given bounds
+ *
+ * @param {number} fovy Vertical field of view
+ * @param {number} aspect Aspect ratio. typically viewport width/height
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @param {mat4} [dest] mat4 frustum matrix will be written into
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat4.perspective = function (fovy, aspect, near, far, dest) {
+ var top = near * Math.tan(fovy * Math.PI / 360.0),
+ right = top * aspect;
+ return mat4.frustum(-right, right, -top, top, near, far, dest);
+};
+
+/**
+ * Generates a orthogonal projection matrix with the given bounds
+ *
+ * @param {number} left Left bound of the frustum
+ * @param {number} right Right bound of the frustum
+ * @param {number} bottom Bottom bound of the frustum
+ * @param {number} top Top bound of the frustum
+ * @param {number} near Near bound of the frustum
+ * @param {number} far Far bound of the frustum
+ * @param {mat4} [dest] mat4 frustum matrix will be written into
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat4.ortho = function (left, right, bottom, top, near, far, dest) {
+ if (!dest) { dest = mat4.create(); }
+ var rl = (right - left),
+ tb = (top - bottom),
+ fn = (far - near);
+ dest[0] = 2 / rl;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ dest[4] = 0;
+ dest[5] = 2 / tb;
+ dest[6] = 0;
+ dest[7] = 0;
+ dest[8] = 0;
+ dest[9] = 0;
+ dest[10] = -2 / fn;
+ dest[11] = 0;
+ dest[12] = -(left + right) / rl;
+ dest[13] = -(top + bottom) / tb;
+ dest[14] = -(far + near) / fn;
+ dest[15] = 1;
+ return dest;
+};
+
+/**
+ * Generates a look-at matrix with the given eye position, focal point, and up axis
+ *
+ * @param {vec3} eye Position of the viewer
+ * @param {vec3} center Point the viewer is looking at
+ * @param {vec3} up vec3 pointing "up"
+ * @param {mat4} [dest] mat4 frustum matrix will be written into
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat4.lookAt = function (eye, center, up, dest) {
+ if (!dest) { dest = mat4.create(); }
+
+ var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
+ eyex = eye[0],
+ eyey = eye[1],
+ eyez = eye[2],
+ upx = up[0],
+ upy = up[1],
+ upz = up[2],
+ centerx = center[0],
+ centery = center[1],
+ centerz = center[2];
+
+ if (eyex === centerx && eyey === centery && eyez === centerz) {
+ return mat4.identity(dest);
+ }
+
+ //vec3.direction(eye, center, z);
+ z0 = eyex - centerx;
+ z1 = eyey - centery;
+ z2 = eyez - centerz;
+
+ // normalize (no check needed for 0 because of early return)
+ len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
+ z0 *= len;
+ z1 *= len;
+ z2 *= len;
+
+ //vec3.normalize(vec3.cross(up, z, x));
+ x0 = upy * z2 - upz * z1;
+ x1 = upz * z0 - upx * z2;
+ x2 = upx * z1 - upy * z0;
+ len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
+ if (!len) {
+ x0 = 0;
+ x1 = 0;
+ x2 = 0;
+ } else {
+ len = 1 / len;
+ x0 *= len;
+ x1 *= len;
+ x2 *= len;
+ }
+
+ //vec3.normalize(vec3.cross(z, x, y));
+ y0 = z1 * x2 - z2 * x1;
+ y1 = z2 * x0 - z0 * x2;
+ y2 = z0 * x1 - z1 * x0;
+
+ len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
+ if (!len) {
+ y0 = 0;
+ y1 = 0;
+ y2 = 0;
+ } else {
+ len = 1 / len;
+ y0 *= len;
+ y1 *= len;
+ y2 *= len;
+ }
+
+ dest[0] = x0;
+ dest[1] = y0;
+ dest[2] = z0;
+ dest[3] = 0;
+ dest[4] = x1;
+ dest[5] = y1;
+ dest[6] = z1;
+ dest[7] = 0;
+ dest[8] = x2;
+ dest[9] = y2;
+ dest[10] = z2;
+ dest[11] = 0;
+ dest[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
+ dest[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
+ dest[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
+ dest[15] = 1;
+
+ return dest;
+};
+
+/**
+ * Creates a matrix from a quaternion rotation and vector translation
+ * This is equivalent to (but much faster than):
+ *
+ * mat4.identity(dest);
+ * mat4.translate(dest, vec);
+ * var quatMat = mat4.create();
+ * quat4.toMat4(quat, quatMat);
+ * mat4.multiply(dest, quatMat);
+ *
+ * @param {quat4} quat Rotation quaternion
+ * @param {vec3} vec Translation vector
+ * @param {mat4} [dest] mat4 receiving operation result. If not specified result is written to a new mat4
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+mat4.fromRotationTranslation = function (quat, vec, dest) {
+ if (!dest) { dest = mat4.create(); }
+
+ // Quaternion math
+ var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ dest[0] = 1 - (yy + zz);
+ dest[1] = xy + wz;
+ dest[2] = xz - wy;
+ dest[3] = 0;
+ dest[4] = xy - wz;
+ dest[5] = 1 - (xx + zz);
+ dest[6] = yz + wx;
+ dest[7] = 0;
+ dest[8] = xz + wy;
+ dest[9] = yz - wx;
+ dest[10] = 1 - (xx + yy);
+ dest[11] = 0;
+ dest[12] = vec[0];
+ dest[13] = vec[1];
+ dest[14] = vec[2];
+ dest[15] = 1;
+
+ return dest;
+};
+
+/**
+ * Returns a string representation of a mat4
+ *
+ * @param {mat4} mat mat4 to represent as a string
+ *
+ * @returns {string} String representation of mat
+ */
+mat4.str = function (mat) {
+ return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] +
+ ', ' + mat[4] + ', ' + mat[5] + ', ' + mat[6] + ', ' + mat[7] +
+ ', ' + mat[8] + ', ' + mat[9] + ', ' + mat[10] + ', ' + mat[11] +
+ ', ' + mat[12] + ', ' + mat[13] + ', ' + mat[14] + ', ' + mat[15] + ']';
+};
+
+/*
+ * quat4
+ */
+
+/**
+ * Creates a new instance of a quat4 using the default array type
+ * Any javascript array containing at least 4 numeric elements can serve as a quat4
+ *
+ * @param {quat4} [quat] quat4 containing values to initialize with
+ *
+ * @returns {quat4} New quat4
+ */
+quat4.create = function (quat) {
+ var dest = new MatrixArray(4);
+
+ if (quat) {
+ dest[0] = quat[0];
+ dest[1] = quat[1];
+ dest[2] = quat[2];
+ dest[3] = quat[3];
+ }
+
+ return dest;
+};
+
+/**
+ * Copies the values of one quat4 to another
+ *
+ * @param {quat4} quat quat4 containing values to copy
+ * @param {quat4} dest quat4 receiving copied values
+ *
+ * @returns {quat4} dest
+ */
+quat4.set = function (quat, dest) {
+ dest[0] = quat[0];
+ dest[1] = quat[1];
+ dest[2] = quat[2];
+ dest[3] = quat[3];
+
+ return dest;
+};
+
+/**
+ * Calculates the W component of a quat4 from the X, Y, and Z components.
+ * Assumes that quaternion is 1 unit in length.
+ * Any existing W component will be ignored.
+ *
+ * @param {quat4} quat quat4 to calculate W component of
+ * @param {quat4} [dest] quat4 receiving calculated values. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.calculateW = function (quat, dest) {
+ var x = quat[0], y = quat[1], z = quat[2];
+
+ if (!dest || quat === dest) {
+ quat[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return quat;
+ }
+ dest[0] = x;
+ dest[1] = y;
+ dest[2] = z;
+ dest[3] = -Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
+ return dest;
+};
+
+/**
+ * Calculates the dot product of two quaternions
+ *
+ * @param {quat4} quat First operand
+ * @param {quat4} quat2 Second operand
+ *
+ * @return {number} Dot product of quat and quat2
+ */
+quat4.dot = function(quat, quat2){
+ return quat[0]*quat2[0] + quat[1]*quat2[1] + quat[2]*quat2[2] + quat[3]*quat2[3];
+};
+
+/**
+ * Calculates the inverse of a quat4
+ *
+ * @param {quat4} quat quat4 to calculate inverse of
+ * @param {quat4} [dest] quat4 receiving inverse values. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.inverse = function(quat, dest) {
+ var q0 = quat[0], q1 = quat[1], q2 = quat[2], q3 = quat[3],
+ dot = q0*q0 + q1*q1 + q2*q2 + q3*q3,
+ invDot = dot ? 1.0/dot : 0;
+
+ // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
+
+ if(!dest || quat === dest) {
+ quat[0] *= -invDot;
+ quat[1] *= -invDot;
+ quat[2] *= -invDot;
+ quat[3] *= invDot;
+ return quat;
+ }
+ dest[0] = -quat[0]*invDot;
+ dest[1] = -quat[1]*invDot;
+ dest[2] = -quat[2]*invDot;
+ dest[3] = quat[3]*invDot;
+ return dest;
+};
+
+
+/**
+ * Calculates the conjugate of a quat4
+ * If the quaternion is normalized, this function is faster than quat4.inverse and produces the same result.
+ *
+ * @param {quat4} quat quat4 to calculate conjugate of
+ * @param {quat4} [dest] quat4 receiving conjugate values. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.conjugate = function (quat, dest) {
+ if (!dest || quat === dest) {
+ quat[0] *= -1;
+ quat[1] *= -1;
+ quat[2] *= -1;
+ return quat;
+ }
+ dest[0] = -quat[0];
+ dest[1] = -quat[1];
+ dest[2] = -quat[2];
+ dest[3] = quat[3];
+ return dest;
+};
+
+/**
+ * Calculates the length of a quat4
+ *
+ * Params:
+ * @param {quat4} quat quat4 to calculate length of
+ *
+ * @returns Length of quat
+ */
+quat4.length = function (quat) {
+ var x = quat[0], y = quat[1], z = quat[2], w = quat[3];
+ return Math.sqrt(x * x + y * y + z * z + w * w);
+};
+
+/**
+ * Generates a unit quaternion of the same direction as the provided quat4
+ * If quaternion length is 0, returns [0, 0, 0, 0]
+ *
+ * @param {quat4} quat quat4 to normalize
+ * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.normalize = function (quat, dest) {
+ if (!dest) { dest = quat; }
+
+ var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
+ len = Math.sqrt(x * x + y * y + z * z + w * w);
+ if (len === 0) {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 0;
+ return dest;
+ }
+ len = 1 / len;
+ dest[0] = x * len;
+ dest[1] = y * len;
+ dest[2] = z * len;
+ dest[3] = w * len;
+
+ return dest;
+};
+
+/**
+ * Performs quaternion addition
+ *
+ * @param {quat4} quat First operand
+ * @param {quat4} quat2 Second operand
+ * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.add = function (quat, quat2, dest) {
+ if(!dest || quat === dest) {
+ quat[0] += quat2[0];
+ quat[1] += quat2[1];
+ quat[2] += quat2[2];
+ quat[3] += quat2[3];
+ return quat;
+ }
+ dest[0] = quat[0]+quat2[0];
+ dest[1] = quat[1]+quat2[1];
+ dest[2] = quat[2]+quat2[2];
+ dest[3] = quat[3]+quat2[3];
+ return dest;
+};
+
+/**
+ * Performs a quaternion multiplication
+ *
+ * @param {quat4} quat First operand
+ * @param {quat4} quat2 Second operand
+ * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.multiply = function (quat, quat2, dest) {
+ if (!dest) { dest = quat; }
+
+ var qax = quat[0], qay = quat[1], qaz = quat[2], qaw = quat[3],
+ qbx = quat2[0], qby = quat2[1], qbz = quat2[2], qbw = quat2[3];
+
+ dest[0] = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
+ dest[1] = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
+ dest[2] = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
+ dest[3] = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
+
+ return dest;
+};
+
+/**
+ * Transforms a vec3 with the given quaternion
+ *
+ * @param {quat4} quat quat4 to transform the vector with
+ * @param {vec3} vec vec3 to transform
+ * @param {vec3} [dest] vec3 receiving operation result. If not specified result is written to vec
+ *
+ * @returns dest if specified, vec otherwise
+ */
+quat4.multiplyVec3 = function (quat, vec, dest) {
+ if (!dest) { dest = vec; }
+
+ var x = vec[0], y = vec[1], z = vec[2],
+ qx = quat[0], qy = quat[1], qz = quat[2], qw = quat[3],
+
+ // calculate quat * vec
+ ix = qw * x + qy * z - qz * y,
+ iy = qw * y + qz * x - qx * z,
+ iz = qw * z + qx * y - qy * x,
+ iw = -qx * x - qy * y - qz * z;
+
+ // calculate result * inverse quat
+ dest[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
+ dest[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
+ dest[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
+
+ return dest;
+};
+
+/**
+ * Multiplies the components of a quaternion by a scalar value
+ *
+ * @param {quat4} quat to scale
+ * @param {number} val Value to scale by
+ * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.scale = function (quat, val, dest) {
+ if(!dest || quat === dest) {
+ quat[0] *= val;
+ quat[1] *= val;
+ quat[2] *= val;
+ quat[3] *= val;
+ return quat;
+ }
+ dest[0] = quat[0]*val;
+ dest[1] = quat[1]*val;
+ dest[2] = quat[2]*val;
+ dest[3] = quat[3]*val;
+ return dest;
+};
+
+/**
+ * Calculates a 3x3 matrix from the given quat4
+ *
+ * @param {quat4} quat quat4 to create matrix from
+ * @param {mat3} [dest] mat3 receiving operation result
+ *
+ * @returns {mat3} dest if specified, a new mat3 otherwise
+ */
+quat4.toMat3 = function (quat, dest) {
+ if (!dest) { dest = mat3.create(); }
+
+ var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ dest[0] = 1 - (yy + zz);
+ dest[1] = xy + wz;
+ dest[2] = xz - wy;
+
+ dest[3] = xy - wz;
+ dest[4] = 1 - (xx + zz);
+ dest[5] = yz + wx;
+
+ dest[6] = xz + wy;
+ dest[7] = yz - wx;
+ dest[8] = 1 - (xx + yy);
+
+ return dest;
+};
+
+/**
+ * Calculates a 4x4 matrix from the given quat4
+ *
+ * @param {quat4} quat quat4 to create matrix from
+ * @param {mat4} [dest] mat4 receiving operation result
+ *
+ * @returns {mat4} dest if specified, a new mat4 otherwise
+ */
+quat4.toMat4 = function (quat, dest) {
+ if (!dest) { dest = mat4.create(); }
+
+ var x = quat[0], y = quat[1], z = quat[2], w = quat[3],
+ x2 = x + x,
+ y2 = y + y,
+ z2 = z + z,
+
+ xx = x * x2,
+ xy = x * y2,
+ xz = x * z2,
+ yy = y * y2,
+ yz = y * z2,
+ zz = z * z2,
+ wx = w * x2,
+ wy = w * y2,
+ wz = w * z2;
+
+ dest[0] = 1 - (yy + zz);
+ dest[1] = xy + wz;
+ dest[2] = xz - wy;
+ dest[3] = 0;
+
+ dest[4] = xy - wz;
+ dest[5] = 1 - (xx + zz);
+ dest[6] = yz + wx;
+ dest[7] = 0;
+
+ dest[8] = xz + wy;
+ dest[9] = yz - wx;
+ dest[10] = 1 - (xx + yy);
+ dest[11] = 0;
+
+ dest[12] = 0;
+ dest[13] = 0;
+ dest[14] = 0;
+ dest[15] = 1;
+
+ return dest;
+};
+
+/**
+ * Performs a spherical linear interpolation between two quat4
+ *
+ * @param {quat4} quat First quaternion
+ * @param {quat4} quat2 Second quaternion
+ * @param {number} slerp Interpolation amount between the two inputs
+ * @param {quat4} [dest] quat4 receiving operation result. If not specified result is written to quat
+ *
+ * @returns {quat4} dest if specified, quat otherwise
+ */
+quat4.slerp = function (quat, quat2, slerp, dest) {
+ if (!dest) { dest = quat; }
+
+ var cosHalfTheta = quat[0] * quat2[0] + quat[1] * quat2[1] + quat[2] * quat2[2] + quat[3] * quat2[3],
+ halfTheta,
+ sinHalfTheta,
+ ratioA,
+ ratioB;
+
+ if (Math.abs(cosHalfTheta) >= 1.0) {
+ if (dest !== quat) {
+ dest[0] = quat[0];
+ dest[1] = quat[1];
+ dest[2] = quat[2];
+ dest[3] = quat[3];
+ }
+ return dest;
+ }
+
+ halfTheta = Math.acos(cosHalfTheta);
+ sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
+
+ if (Math.abs(sinHalfTheta) < 0.001) {
+ dest[0] = (quat[0] * 0.5 + quat2[0] * 0.5);
+ dest[1] = (quat[1] * 0.5 + quat2[1] * 0.5);
+ dest[2] = (quat[2] * 0.5 + quat2[2] * 0.5);
+ dest[3] = (quat[3] * 0.5 + quat2[3] * 0.5);
+ return dest;
+ }
+
+ ratioA = Math.sin((1 - slerp) * halfTheta) / sinHalfTheta;
+ ratioB = Math.sin(slerp * halfTheta) / sinHalfTheta;
+
+ dest[0] = (quat[0] * ratioA + quat2[0] * ratioB);
+ dest[1] = (quat[1] * ratioA + quat2[1] * ratioB);
+ dest[2] = (quat[2] * ratioA + quat2[2] * ratioB);
+ dest[3] = (quat[3] * ratioA + quat2[3] * ratioB);
+
+ return dest;
+};
+
+/**
+ * Returns a string representation of a quaternion
+ *
+ * @param {quat4} quat quat4 to represent as a string
+ *
+ * @returns {string} String representation of quat
+ */
+quat4.str = function (quat) {
+ return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']';
+};
+
+
+return {
+ vec3: vec3,
+ mat3: mat3,
+ mat4: mat4,
+ quat4: quat4
+};
+
+})();
+
diff --git a/src/intertyper.js b/src/intertyper.js
index c5a9583b..fbad353a 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -69,12 +69,12 @@ function intertyper(data, sidePass, baseLineNums) {
if (mainPass && (line[0] == '%' || line[0] == '@')) {
// If this isn't a type, it's a global variable, make a note of the information now, we will need it later
- var testType = /[@%\w\d\.\" ]+ = type .*/.exec(line);
+ var testType = /[@%\w\d\.\" $-]+ = type .*/.exec(line);
if (!testType) {
- var global = /([@%\w\d\.\" ]+) = .*/.exec(line);
+ var global = /([@%\w\d\.\" $-]+) = .*/.exec(line);
var globalIdent = toNiceIdent(global[1]);
- var testAlias = /[@%\w\d\.\" ]+ = alias .*/.exec(line);
- var testString = /^[^"]+c\"[^"]+"/.exec(line);
+ var testAlias = /[@%\w\d\.\" $-]+ = alias .*/.exec(line);
+ var testString = /[@%\w\d\.\" $-]+ = [\w ]+ \[\d+ x i8] c".*/.exec(line);
Variables.globals[globalIdent] = {
name: globalIdent,
alias: !!testAlias,
@@ -118,7 +118,7 @@ function intertyper(data, sidePass, baseLineNums) {
var func = funcHeader.processItem(tokenizer.processItem({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true))[0];
if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) {
- warn('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data');
+ warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data');
SKIP_STACK_IN_SMALL = 0;
}
@@ -338,7 +338,8 @@ function intertyper(data, sidePass, baseLineNums) {
return '/dev/null';
} else if (item.indent === 0) {
if ((tokensLength >= 1 && token0Text.substr(-1) == ':') ||
- (tokensLength >= 3 && token1Text == '<label>'))
+ (tokensLength >= 3 && token1Text == '<label>') ||
+ (tokensLength >= 2 && token1Text == ':'))
return 'Label';
if (tokensLength >= 4 && token0Text == 'declare')
return 'External';
@@ -349,6 +350,10 @@ function intertyper(data, sidePass, baseLineNums) {
return 'FuncHeader';
if (tokensLength >= 1 && token0Text == '}')
return 'FuncEnd';
+ if (token0Text == 'module' && token1Text == 'asm') {
+ warn('Ignoring module asm: ' + item.tokens[2].text);
+ return '/dev/null';
+ }
}
if (tokensLength >= 3 && (token0Text == 'call' || token1Text == 'call'))
return 'Call';
@@ -547,13 +552,15 @@ function intertyper(data, sidePass, baseLineNums) {
// label
substrate.addActor('Label', {
processItem: function(item) {
+ var rawLabel = item.tokens[0].text.substr(-1) == ':' ?
+ '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) :
+ (item.tokens[1].text == '<label>' ?
+ '%' + item.tokens[2].text.substr(1) :
+ '%' + item.tokens[0].text)
+ var niceLabel = toNiceIdent(rawLabel);
return [{
intertype: 'label',
- ident: toNiceIdent(
- item.tokens[0].text.substr(-1) == ':' ?
- '%' + item.tokens[0].text.substr(0, item.tokens[0].text.length-1) :
- '%' + item.tokens[2].text.substr(1)
- ),
+ ident: niceLabel,
lineNum: item.lineNum
}];
}
@@ -657,17 +664,19 @@ function intertyper(data, sidePass, baseLineNums) {
item.type = item.tokens[1].text;
Types.needAnalysis[item.type] = 0;
while (['@', '%'].indexOf(item.tokens[2].text[0]) == -1 && !(item.tokens[2].text in PARSABLE_LLVM_FUNCTIONS) &&
- item.tokens[2].text != 'null') {
- // We cannot compile assembly. If you hit this, perhaps tell the compiler not
- // to generate arch-specific code? |-U__i386__ -U__x86_64__| might help, it undefines
- // the standard archs.
+ item.tokens[2].text != 'null' && item.tokens[2].text != 'asm') {
assert(item.tokens[2].text != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
item.tokens.splice(2, 1);
}
var tokensLeft = item.tokens.slice(2);
item.ident = eatLLVMIdent(tokensLeft);
- // We cannot compile assembly, see above.
- assert(item.ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
+ if (item.ident == 'asm') {
+ // Inline assembly is just JavaScript that we paste into the code
+ item.intertype = 'value';
+ if (tokensLeft[0].text == 'sideeffect') tokensLeft.splice(0, 1);
+ item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2);
+ return { forward: null, ret: [item], item: item };
+ }
if (item.ident.substr(-2) == '()') {
// See comment in isStructType()
item.ident = item.ident.substr(0, item.ident.length-2);
@@ -785,7 +794,7 @@ function intertyper(data, sidePass, baseLineNums) {
value: parseLLVMSegment(typeToken.concat(subSegments[0]))
};
return ret;
- });
+ }).filter(function(param) { return param.value && param.value.ident != 'undef' });
this.forwardItem(item, 'Reintegrator');
}
});
diff --git a/src/jsifier.js b/src/jsifier.js
index 5ad1573b..01ecd7d3 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -71,7 +71,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
}
} else {
- libFuncsToInclude = ['memcpy', 'memset', 'malloc', 'free'];
+ libFuncsToInclude = ['memcpy', 'memset', 'malloc', 'free', '$Browser'];
}
libFuncsToInclude.forEach(function(ident) {
data.functionStubs.push({
@@ -166,23 +166,27 @@ function JSify(data, functionsOnly, givenFunctions) {
ret[index++] = 0;
}
// Add current value(s)
- var currValue = flatten(values[i]);
+ var currValue = values[i];
if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') {
// 'flatten' out the 64-bit value into two 32-bit halves
- ret[index++] = currValue>>>0;
+ var parts = parseI64Constant(currValue, true);
+ ret[index++] = parts[0];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- ret[index++] = Math.floor(currValue/4294967296);
+ ret[index++] = parts[1];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- } else if (typeof currValue == 'object') {
- for (var j = 0; j < currValue.length; j++) {
- ret[index++] = currValue[j];
- }
} else {
- ret[index++] = currValue;
+ currValue = flatten(currValue);
+ if (typeof currValue == 'object') {
+ for (var j = 0; j < currValue.length; j++) {
+ ret[index++] = currValue[j];
+ }
+ } else {
+ ret[index++] = currValue;
+ }
}
i += 1;
}
@@ -279,7 +283,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var val = LibraryManager.library[shortident];
var padding;
if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
- padding = [item.type].concat(zeros(Runtime.getNativeFieldSize(item.type)));
+ padding = [item.type].concat(zeros(Runtime.getNativeFieldSize(item.type)-1));
} else {
padding = makeEmptyStruct(item.type);
}
@@ -371,11 +375,15 @@ function JSify(data, functionsOnly, givenFunctions) {
processItem: function(item) {
function addFromLibrary(ident) {
if (ident in addedLibraryItems) return '';
+ addedLibraryItems[ident] = true;
+
+ // dependencies can be JS functions, which we just run
+ if (typeof ident == 'function') return ident();
+
// Don't replace implemented functions with library ones (which can happen when we add dependencies).
// Note: We don't return the dependencies here. Be careful not to end up where this matters
if (('_' + ident) in Functions.implementedFunctions) return '';
- addedLibraryItems[ident] = true;
var snippet = LibraryManager.library[ident];
var redirectedIdent = null;
var deps = LibraryManager.library[ident + '__deps'] || [];
@@ -400,7 +408,8 @@ function JSify(data, functionsOnly, givenFunctions) {
// name the function; overwrite if it's already named
snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
if (LIBRARY_DEBUG) {
- snippet = snippet.replace('{', '{ print("[library call:' + ident + ']"); ');
+ snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
+ snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
}
}
@@ -423,7 +432,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
ident = '_' + ident;
}
- var text = (deps ? '\n' + deps.map(addFromLibrary).join('\n') : '');
+ var text = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
text += isFunction ? snippet : 'var ' + ident + '=' + snippet + ';';
if (ident in EXPORTED_FUNCTIONS) {
text += '\nModule["' + ident + '"] = ' + ident + ';';
@@ -441,6 +450,9 @@ function JSify(data, functionsOnly, givenFunctions) {
item.JS = addFromLibrary(shortident);
} else {
item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
+ if (WARN_ON_UNDEFINED_SYMBOLS) {
+ warn('Unresolved symbol: ' + item.ident);
+ }
}
return ret;
}
@@ -540,15 +552,12 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
- if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n";
+ if (LABEL_DEBUG) func.JS += " Module.print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n";
if (true) { // TODO: optimize away when not needed
if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
func.JS += ' var __label__;\n';
}
- if (func.needsLastLabel) {
- func.JS += ' var __lastLabel__ = null;\n';
- }
// Walk function blocks and generate JS
function walkBlock(block, indent) {
@@ -558,7 +567,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!label) return '';
var ret = '';
if (LABEL_DEBUG) {
- ret += indent + "print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
+ ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
}
if (EXECUTION_TIMEOUT > 0) {
ret += indent + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n';
@@ -739,7 +748,7 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('noop', function(item) {
return ';';
});
- makeFuncLineActor('var', function(item) { // assigns into phis become simple vars when MICRO_OPTS
+ makeFuncLineActor('var', function(item) { // assigns into phis become simple vars
return 'var ' + item.ident + ';';
});
makeFuncLineActor('store', function(item) {
@@ -753,6 +762,10 @@ function JSify(data, functionsOnly, givenFunctions) {
}
switch (impl) {
case VAR_NATIVIZED:
+ if (isNumber(item.ident)) {
+ // Direct write to a memory address; this may be an intentional segfault, if not, it is a bug in the source
+ return 'throw "fault on write to ' + item.ident + '";';
+ }
return item.ident + '=' + value + ';'; // We have the actual value here
break;
case VAR_EMULATED:
@@ -780,11 +793,8 @@ function JSify(data, functionsOnly, givenFunctions) {
return label;
}
- function makeBranch(label, lastLabel, labelIsVariable) {
+ function makeBranch(label, lastLabel, labelIsVariable) { // lastLabel is deprecated
var pre = '';
- if (!MICRO_OPTS && lastLabel) {
- pre = '__lastLabel__ = ' + getLabelId(lastLabel) + '; ';
- }
if (label[0] == 'B') {
assert(!labelIsVariable, 'Cannot handle branches to variables with special branching options');
var parts = label.split('|');
@@ -951,7 +961,7 @@ function JSify(data, functionsOnly, givenFunctions) {
+ '}\n';
}
if (LABEL_DEBUG) {
- ret += "print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+ ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+ "INDENT = INDENT.substr(0, INDENT.length-2);\n";
}
ret += 'return';
@@ -961,7 +971,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret + ';';
});
makeFuncLineActor('resume', function(item) {
- return (EXCEPTION_DEBUG ? 'print("Resuming exception");' : '') +
+ return (EXCEPTION_DEBUG ? 'Module.print("Resuming exception");' : '') +
'throw ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') + ';';
});
makeFuncLineActor('invoke', function(item) {
@@ -974,7 +984,7 @@ function JSify(data, functionsOnly, givenFunctions) {
+ '} catch(e) { '
+ 'if (typeof e != "number") throw e; '
+ 'if (ABORT) throw e; __THREW__ = true; '
- + (EXCEPTION_DEBUG ? 'print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
+ + (EXCEPTION_DEBUG ? 'Module.print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
+ 'return null } })();';
if (item.assignTo) {
ret = 'var ' + item.assignTo + ' = ' + ret;
@@ -1021,7 +1031,16 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('extractvalue', function(item) {
assert(item.indexes.length == 1); // TODO: use getelementptr parsing stuff, for depth. For now, we assume that LLVM aggregates are flat,
// and we emulate them using simple JS objects { f1: , f2: , } etc., for speed
- return item.ident + '.f' + item.indexes[0][0].text;
+ var index = item.indexes[0][0].text;
+ var valueType = Types.types[item.type].fields[index];
+ if (USE_TYPED_ARRAYS != 2 || valueType != 'i64') {
+ return item.ident + '.f' + index;
+ } else {
+ var assignTo = item.assignTo;
+ item.assignTo = null;
+ return 'var ' + assignTo + '$0 = ' + item.ident + '.f' + index + '[0];' +
+ 'var ' + assignTo + '$1 = ' + item.ident + '.f' + index + '[1];';
+ }
});
makeFuncLineActor('insertvalue', function(item) {
assert(item.indexes.length == 1); // TODO: see extractvalue
@@ -1043,20 +1062,6 @@ function JSify(data, functionsOnly, givenFunctions) {
return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum));
}
});
- makeFuncLineActor('phi', function(item) {
- var params = item.params;
- assert(!MICRO_OPTS);
- function makeOne(i) {
- if (i === params.length-1) {
- return finalizeLLVMParameter(params[i].value);
- }
- return '__lastLabel__ == ' + getLabelId(params[i].label) + ' ? ' +
- finalizeLLVMParameter(params[i].value) + ' : (' + makeOne(i+1) + ')';
- }
- var ret = makeOne(0);
- if (item.postSet) ret += item.postSet;
- return ret;
- });
makeFuncLineActor('mathop', processMathop);
@@ -1195,6 +1200,12 @@ function JSify(data, functionsOnly, givenFunctions) {
// This is the main pass. Print out the generated code that we have here, together with the
// rest of the output that we started to print out earlier (see comment on the
// "Final shape that will be created").
+ if (PRECISE_I64_MATH && preciseI64MathUsed) {
+ print(read('long.js'));
+ } else {
+ print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included');
+ print('var i64Math = null;');
+ }
var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet);
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
if (RUNTIME_TYPE_INFO) {
diff --git a/src/library.js b/src/library.js
index ebd80daf..bb73c48a 100644
--- a/src/library.js
+++ b/src/library.js
@@ -26,8 +26,16 @@ LibraryManager.library = {
_impure_ptr: 0,
$FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'],
- $FS__postset: '__ATINIT__.unshift({ func: function() { FS.ignorePermissions = false; if (!FS.init.initialized) FS.init() } });' +
- '__ATEXIT__.push({ func: function() { FS.quit() } });',
+ $FS__postset: '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
+ '__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' +
+ '__ATEXIT__.push({ func: function() { FS.quit() } });' +
+ // export some names through closure
+ 'Module["FS_createFolder"] = FS.createFolder;' +
+ 'Module["FS_createPath"] = FS.createPath;' +
+ 'Module["FS_createDataFile"] = FS.createDataFile;' +
+ 'Module["FS_createLazyFile"] = FS.createLazyFile;' +
+ 'Module["FS_createLink"] = FS.createLink;' +
+ 'Module["FS_createDevice"] = FS.createDevice;',
$FS: {
// The path to the current folder.
currentPath: '/',
@@ -86,6 +94,23 @@ LibraryManager.library = {
parentPath: null,
parentObject: null
};
+#if FS_LOG
+ var inputPath = path;
+ function log() {
+ Module['print']('FS.analyzePath("' + inputPath + '", ' +
+ dontResolveLastLink + ', ' +
+ linksVisited + ') => {' +
+ 'isRoot: ' + ret.isRoot + ', ' +
+ 'exists: ' + ret.exists + ', ' +
+ 'error: ' + ret.error + ', ' +
+ 'name: "' + ret.name + '", ' +
+ 'path: "' + ret.path + '", ' +
+ 'object: ' + ret.object + ', ' +
+ 'parentExists: ' + ret.parentExists + ', ' +
+ 'parentPath: "' + ret.parentPath + '", ' +
+ 'parentObject: ' + ret.parentObject + '}');
+ }
+#endif
path = FS.absolutePath(path);
if (path == '/') {
ret.isRoot = true;
@@ -123,8 +148,12 @@ LibraryManager.library = {
break;
}
var link = FS.absolutePath(current.link, traversed.join('/'));
- return FS.analyzePath([link].concat(path).join('/'),
- dontResolveLastLink, linksVisited + 1);
+ ret = FS.analyzePath([link].concat(path).join('/'),
+ dontResolveLastLink, linksVisited + 1);
+#if FS_LOG
+ log();
+#endif
+ return ret;
}
traversed.push(target);
if (path.length == 0) {
@@ -133,8 +162,10 @@ LibraryManager.library = {
ret.object = current;
}
}
- return ret;
}
+#if FS_LOG
+ log();
+#endif
return ret;
},
// Finds the file system object at a given path. If dontResolveLastLink is
@@ -152,6 +183,13 @@ LibraryManager.library = {
},
// Creates a file system record: file, link, device or folder.
createObject: function(parent, name, properties, canRead, canWrite) {
+#if FS_LOG
+ Module['print']('FS.createObject("' + parent + '", ' +
+ '"' + name + '", ' +
+ JSON.stringify(properties) + ', ' +
+ canRead + ', ' +
+ canWrite + ')');
+#endif
if (!parent) parent = '/';
if (typeof parent === 'string') parent = FS.findObject(parent);
@@ -226,11 +264,20 @@ LibraryManager.library = {
var properties = {isDevice: false, contents: data};
return FS.createFile(parent, name, properties, canRead, canWrite);
},
- // Creates a file record for lazy-loading from a URL.
+ // Creates a file record for lazy-loading from a URL. XXX This requires a synchronous
+ // XHR, which is not possible in browsers except in a web worker! Use preloading,
+ // either --preload-file in emcc or FS.createPreloadedFile
createLazyFile: function(parent, name, url, canRead, canWrite) {
var properties = {isDevice: false, url: url};
return FS.createFile(parent, name, properties, canRead, canWrite);
},
+ // Preloads a file asynchronously. You can call this before run, for example in
+ // preRun. run will be delayed until this file arrives and is set up.
+ createPreloadedFile: function(parent, name, url, canRead, canWrite) {
+ Browser.asyncLoad(url, function(data) {
+ FS.createDataFile(parent, name, data, canRead, canWrite);
+ });
+ },
// Creates a link to a sepcific local path.
createLink: function(parent, name, target, canRead, canWrite) {
var properties = {isDevice: false, link: target};
@@ -309,6 +356,7 @@ LibraryManager.library = {
typeof window.prompt == 'function') {
// Browser.
result = window.prompt('Input: ');
+ if (result === null) result = String.fromCharCode(0); // cancel ==> EOF
} else if (typeof readline == 'function') {
// Command line.
result = readline();
@@ -340,8 +388,10 @@ LibraryManager.library = {
if (!error.printer) error.printer = Module['print'];
if (!error.buffer) error.buffer = [];
- // Create the temporary folder.
- FS.createFolder('/', 'tmp', true, true);
+ // Create the temporary folder, if not already created
+ try {
+ FS.createFolder('/', 'tmp', true, true);
+ } catch(e) {}
// Create the I/O devices.
var devFolder = FS.createFolder('/', 'dev', true, true);
@@ -408,6 +458,21 @@ LibraryManager.library = {
// Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed
if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output('\n'.charCodeAt(0));
if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output('\n'.charCodeAt(0));
+ },
+
+ // Standardizes a path. Useful for making comparisons of pathnames work in a consistent manner.
+ // For example, ./file and file are really the same, so this function will remove ./
+ standardizePath: function(path) {
+ if (path.substr(0, 2) == './') path = path.substr(2);
+ return path;
+ },
+
+ deleteFile: function(path) {
+ var path = FS.analyzePath(path);
+ if (!path.parentExists || !path.exists) {
+ throw 'Invalid path ' + path;
+ }
+ delete path.parentObject.contents[path.name];
}
},
@@ -1430,7 +1495,7 @@ LibraryManager.library = {
lseek: function(fildes, offset, whence) {
// off_t lseek(int fildes, off_t offset, int whence);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html
- if (FS.streams[fildes] && !FS.streams[fildes].isDevice) {
+ if (FS.streams[fildes] && !FS.streams[fildes].object.isDevice) {
var stream = FS.streams[fildes];
var position = offset;
if (whence === 1) { // SEEK_CUR.
@@ -1821,7 +1886,7 @@ LibraryManager.library = {
#if CATCH_EXIT_CODE
throw new ExitStatus();
-#else
+#else
throw 'exit(' + status + ') called, at ' + new Error().stack;
#endif
},
@@ -2171,6 +2236,9 @@ LibraryManager.library = {
if (!self.called) {
STATICTOP = alignMemoryPage(STATICTOP); // make sure we start out aligned
self.called = true;
+#if GC_SUPPORT
+ _sbrk.DYNAMIC_START = STATICTOP;
+#endif
}
var ret = STATICTOP;
if (bytes != 0) Runtime.staticAlloc(bytes);
@@ -2196,6 +2264,15 @@ LibraryManager.library = {
// TODO: Document.
_scanString__deps: ['_isFloat'],
_scanString: function(format, get, unget, varargs) {
+ if (!__scanString.whiteSpace) {
+ __scanString.whiteSpace = {};
+ __scanString.whiteSpace[' '.charCodeAt(0)] = 1;
+ __scanString.whiteSpace['\t'.charCodeAt(0)] = 1;
+ __scanString.whiteSpace['\n'.charCodeAt(0)] = 1;
+ __scanString.whiteSpace[' '] = 1;
+ __scanString.whiteSpace['\t'] = 1;
+ __scanString.whiteSpace['\n'] = 1;
+ }
// Supports %x, %4x, %d.%d, %s, %f, %lf.
// TODO: Support all format specifiers.
format = Pointer_stringify(format);
@@ -2203,6 +2280,7 @@ LibraryManager.library = {
var argsi = 0;
var fields = 0;
var argIndex = 0;
+ var next;
for (var formatIndex = 0; formatIndex < format.length; formatIndex++) {
if (next <= 0) return fields;
var next = get();
@@ -2218,11 +2296,14 @@ LibraryManager.library = {
if (formatIndex != maxSpecifierStart) {
max_ = parseInt(format.slice(maxSpecifierStart, formatIndex), 10);
}
- // TODO: Handle type size modifier.
var long_ = false;
+ var half = false;
if (format[formatIndex] == 'l') {
long_ = true;
formatIndex++;
+ } else if (format[formatIndex] == 'h') {
+ half = true;
+ formatIndex++;
}
var type = format[formatIndex];
formatIndex++;
@@ -2242,13 +2323,18 @@ LibraryManager.library = {
buffer.pop();
unget();
}
+ unget();
+ next = get();
} else {
+ var first = true;
while ((curr < max_ || isNaN(max_)) && next > 0) {
- if ((type === 'd' && next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
- (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
- next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
- next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0))) ||
- (type === 's') &&
+ if (!(next in __scanString.whiteSpace) && // stop on whitespace
+ (type == 's' ||
+ ((type === 'd' || type == 'u') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
+ (first && next == '-'.charCodeAt(0)))) ||
+ (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
+ next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
+ next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0)))) &&
(formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up
buffer.push(String.fromCharCode(next));
next = get();
@@ -2256,6 +2342,7 @@ LibraryManager.library = {
} else {
break;
}
+ first = false;
}
}
if (buffer.length === 0) return 0; // Failure.
@@ -2263,8 +2350,12 @@ LibraryManager.library = {
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getNativeFieldSize('void*');
switch (type) {
- case 'd':
- {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}}
+ case 'd': case 'u':
+ if (half) {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i16') }}};
+ } else {
+ {{{ makeSetValue('argPtr', 0, 'parseInt(text, 10)', 'i32') }}};
+ }
break;
case 'x':
{{{ makeSetValue('argPtr', 0, 'parseInt(text, 16)', 'i32') }}}
@@ -2284,6 +2375,12 @@ LibraryManager.library = {
break;
}
fields++;
+ } else if (format[formatIndex] in __scanString.whiteSpace) {
+ while (next in __scanString.whiteSpace) {
+ next = get();
+ if (next <= 0) return fields; // End of input.
+ }
+ unget();
} else {
// Not a specifier.
if (format[formatIndex].charCodeAt(0) !== next) {
@@ -2442,6 +2539,10 @@ LibraryManager.library = {
var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
argSize = argSize || 4;
var currArg = getNextArg('i' + (argSize * 8));
+#if PRECISE_I64_MATH == 1
+ var origArg = currArg;
+#endif
+ var argText;
#if USE_TYPED_ARRAYS == 2
// Flatten i64-1 [low, high] into a (slightly rounded) double
if (argSize == 8) {
@@ -2455,11 +2556,16 @@ LibraryManager.library = {
}
// Format the number.
var currAbsArg = Math.abs(currArg);
- var argText;
var prefix = '';
if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1]); else
+#endif
argText = reSign(currArg, 8 * argSize, 1).toString(10);
} else if (next == 'u'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else
+#endif
argText = unSign(currArg, 8 * argSize, 1).toString(10);
currArg = Math.abs(currArg);
} else if (next == 'o'.charCodeAt(0)) {
@@ -2611,24 +2717,19 @@ LibraryManager.library = {
});
} else if (next == 's'.charCodeAt(0)) {
// String.
- var arg = getNextArg('i8*');
- var copiedString;
- if (arg) {
- copiedString = String_copy(arg);
- if (precisionSet && copiedString.length > precision) {
- copiedString = copiedString.slice(0, precision);
- }
- } else {
- copiedString = intArrayFromString('(null)', true);
- }
+ var arg = getNextArg('i8*') || 0; // 0 holds '(null)'
+ var argLength = String_len(arg);
+ if (precisionSet) argLength = Math.min(String_len(arg), precision);
if (!flagLeftAlign) {
- while (copiedString.length < width--) {
+ while (argLength < width--) {
ret.push(' '.charCodeAt(0));
}
}
- ret = ret.concat(copiedString);
+ for (var i = 0; i < argLength; i++) {
+ ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
+ }
if (flagLeftAlign) {
- while (copiedString.length < width--) {
+ while (argLength < width--) {
ret.push(' '.charCodeAt(0));
}
}
@@ -2753,7 +2854,7 @@ LibraryManager.library = {
streamObj.error = true;
return -1;
} else {
- return {{{ makeGetValue('_fgetc.ret', '0', 'i8') }}};
+ return {{{ makeGetValue('_fgetc.ret', '0', 'i8', null, 1) }}};
}
},
getc: 'fgetc',
@@ -3248,8 +3349,9 @@ LibraryManager.library = {
}
var info = FS.streams[stream];
if (!info) return -1;
- return allocate(info.object.contents.slice(offset, offset+num),
- 'i8', ALLOC_NORMAL);
+ var contents = info.object.contents;
+ contents = Array.prototype.slice.call(contents, offset, offset+num);
+ return allocate(contents, 'i8', ALLOC_NORMAL);
},
__01mmap64_: 'mmap',
@@ -3311,9 +3413,9 @@ LibraryManager.library = {
},
__cxa_atexit: 'atexit',
- abort: function(code) {
+ abort: function() {
ABORT = true;
- throw 'ABORT: ' + code + ', at ' + (new Error().stack);
+ throw 'abort() at ' + (new Error().stack);
},
bsearch: function(key, base, num, size, compar) {
@@ -3357,6 +3459,8 @@ LibraryManager.library = {
strtod__deps: ['isspace', 'isdigit'],
strtod: function(str, endptr) {
+ var origin = str;
+
// Skip space.
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
@@ -3373,26 +3477,35 @@ LibraryManager.library = {
var ret = 0;
// Get whole part.
+ var whole = false;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
+ whole = true;
ret = ret*10 + chr - '0'.charCodeAt(0);
str++;
}
// Get fractional part.
+ var fraction = false;
if ({{{ makeGetValue('str', 0, 'i8') }}} == '.'.charCodeAt(0)) {
str++;
var mul = 1/10;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
+ fraction = true;
ret += mul*(chr - '0'.charCodeAt(0));
mul /= 10;
str++;
}
}
+ if (!whole && !fraction) {
+ {{{ makeSetValue('endptr', 0, 'origin', '*') }}}
+ return 0;
+ }
+
// Get exponent part.
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (chr == 'e'.charCodeAt(0) || chr == 'E'.charCodeAt(0)) {
@@ -3424,6 +3537,9 @@ LibraryManager.library = {
return ret * multiplier;
},
+ strtod_l: 'strtod', // no locale support yet
+ strtold: 'strtod', // XXX add real support for long double
+ strtold_l: 'strtold', // no locale support yet
_parseInt__deps: ['isspace', '__setErrNo', '$ERRNO_CODES'],
_parseInt: function(str, endptr, base, min, max, bits, unsign) {
@@ -3564,7 +3680,7 @@ LibraryManager.library = {
ENV['USER'] = 'root';
ENV['PATH'] = '/';
ENV['PWD'] = '/';
- ENV['HOME'] = '/';
+ ENV['HOME'] = '/home/emscripten';
ENV['LANG'] = 'en_US.UTF-8';
ENV['_'] = './this.program';
// Allocate memory.
@@ -3900,19 +4016,35 @@ LibraryManager.library = {
},
strspn: function(pstr, pset) {
- var str = String_copy(pstr, true);
- var set = String_copy(pset);
- var i = 0;
- while (set.indexOf(str[i]) != -1) i++; // Must halt, as 0 is in str but not set
- return i;
+ var str = pstr, set, strcurr, setcurr;
+ while (1) {
+ strcurr = {{{ makeGetValue('str', '0', 'i8') }}};
+ if (!strcurr) return str - pstr;
+ set = pset;
+ while (1) {
+ setcurr = {{{ makeGetValue('set', '0', 'i8') }}};
+ if (!setcurr || setcurr == strcurr) break;
+ set++;
+ }
+ if (!setcurr) return str - pstr;
+ str++;
+ }
},
strcspn: function(pstr, pset) {
- var str = String_copy(pstr, true);
- var set = String_copy(pset, true);
- var i = 0;
- while (set.indexOf(str[i]) == -1) i++; // Must halt, as 0 is in both
- return i;
+ var str = pstr, set, strcurr, setcurr;
+ while (1) {
+ strcurr = {{{ makeGetValue('str', '0', 'i8') }}};
+ if (!strcurr) return str - pstr;
+ set = pset;
+ while (1) {
+ setcurr = {{{ makeGetValue('set', '0', 'i8') }}};
+ if (!setcurr || setcurr == strcurr) break;
+ set++;
+ }
+ if (setcurr) return str - pstr;
+ str++;
+ }
},
strcpy: function(pdest, psrc) {
@@ -3941,6 +4073,28 @@ LibraryManager.library = {
}
return pdest;
},
+
+ strlwr__deps:['tolower'],
+ strlwr: function(pstr){
+ var i = 0;
+ while(1) {
+ var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
+ if(x == 0) break;
+ {{{ makeSetValue('pstr', 'i', '_tolower(x)', 'i8') }}};
+ i++;
+ }
+ },
+
+ strupr__deps:['toupper'],
+ strupr: function(pstr){
+ var i = 0;
+ while(1) {
+ var x = {{{ makeGetValue('pstr', 'i', 'i8') }}};
+ if(x == 0) break;
+ {{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}};
+ i++;
+ }
+ },
strcat__deps: ['strlen'],
strcat: function(pdest, psrc) {
@@ -4071,10 +4225,36 @@ LibraryManager.library = {
return newStr;
},
+ strndup__deps: ['strdup'],
+ strndup: function(ptr, size) {
+ var len = String_len(ptr);
+
+ if (size >= len) {
+ return _strdup(ptr);
+ }
+
+ if (size < 0) {
+ size = 0;
+ }
+
+ var newStr = _malloc(size + 1);
+ {{{ makeCopyValues('newStr', 'ptr', 'size', 'null', null, 1) }}};
+ {{{ makeSetValue('newStr', 'size', '0', 'i8') }}};
+ return newStr;
+ },
+
strpbrk: function(ptr1, ptr2) {
- var searchSet = Runtime.set.apply(null, String_copy(ptr2));
- while ({{{ makeGetValue('ptr1', 0, 'i8') }}}) {
- if ({{{ makeGetValue('ptr1', 0, 'i8') }}} in searchSet) return ptr1;
+ var curr;
+ var searchSet = {};
+ while (1) {
+ var curr = {{{ makeGetValue('ptr2++', 0, 'i8') }}};
+ if (!curr) break;
+ searchSet[curr] = 1;
+ }
+ while (1) {
+ curr = {{{ makeGetValue('ptr1', 0, 'i8') }}};
+ if (!curr) break;
+ if (curr in searchSet) return ptr1;
ptr1++;
}
return 0;
@@ -4202,11 +4382,13 @@ LibraryManager.library = {
isdigit: function(chr) {
return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0);
},
+ isdigit_l: 'isdigit', // no locale support yet
isxdigit: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) ||
(chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0));
},
+ isxdigit_l: 'isxdigit', // no locale support yet
isalnum: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) ||
@@ -4336,6 +4518,21 @@ LibraryManager.library = {
*/
},
+ llvm_bswap_i16: function(x) {
+ x = unSign(x, 32);
+ var bytes = [];
+ bytes[0] = x & 255;
+ x >>= 8;
+ bytes[1] = x & 255;
+ x >>= 8;
+ var ret = 0;
+ ret <<= 8;
+ ret += bytes[0];
+ ret <<= 8;
+ ret += bytes[1];
+ return ret;
+ },
+
llvm_bswap_i32: function(x) {
x = unSign(x, 32);
var bytes = [];
@@ -4350,7 +4547,7 @@ LibraryManager.library = {
}
return ret;
},
-
+
llvm_ctlz_i32: function(x) {
for (var i=0; i<32; i++) {
if ( (x & (1 << (31-i))) != 0 ) {
@@ -4529,12 +4726,12 @@ LibraryManager.library = {
// return the type of the catch block which should be called.
for (var i = 0; i < typeArray.length; i++) {
if (___cxa_does_inherit(typeArray[i], throwntype, thrown))
- return { 'f0':thrown, 'f1':typeArray[i]};
+ return { f0:thrown, f1:typeArray[i] };
}
// Shouldn't happen unless we have bogus data in typeArray
// or encounter a type for which emscripten doesn't have suitable
// typeinfo defined. Best-efforts match just in case.
- return {'f0':thrown,'f1':throwntype};
+ return { f0:thrown, f1 :throwntype };
},
// Recursively walks up the base types of 'possibilityType'
@@ -4596,17 +4793,75 @@ LibraryManager.library = {
// type_info for void*.
_ZTIPv: [0],
+ llvm_uadd_with_overflow_i8: function(x, y) {
+ x = x & 0xff;
+ y = y & 0xff;
+ return {
+ f0: (x+y) & 0xff,
+ f1: x+y > 255
+ };
+ },
+
+ llvm_umul_with_overflow_i8: function(x, y) {
+ x = x & 0xff;
+ y = y & 0xff;
+ return {
+ f0: (x*y) & 0xff,
+ f1: x*y > 255
+ };
+ },
+
+ llvm_uadd_with_overflow_i16: function(x, y) {
+ x = x & 0xffff;
+ y = y & 0xffff;
+ return {
+ f0: (x+y) & 0xffff,
+ f1: x+y > 65535
+ };
+ },
+
+ llvm_umul_with_overflow_i16: function(x, y) {
+ x = x & 0xffff;
+ y = y & 0xffff;
+ return {
+ f0: (x*y) & 0xffff,
+ f1: x*y > 65535
+ };
+ },
+
llvm_uadd_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x+y,
- f1: 0 // We never overflow... for now
+ f0: (x+y)>>>0,
+ f1: x+y > 4294967295
};
},
llvm_umul_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x*y,
- f1: 0 // We never overflow... for now
+ f0: (x*y)>>>0,
+ f1: x*y > 4294967295
+ };
+ },
+
+ llvm_uadd_with_overflow_i64__deps: [function() { preciseI64MathUsed = 1 }],
+ llvm_uadd_with_overflow_i64: function(xl, xh, yl, yh) {
+ i64Math.add(xl, xh, yl, yh);
+ return {
+ f0: i64Math.result,
+ f1: 0 // XXX Need to hack support for this in long.js
+ };
+ },
+
+ llvm_umul_with_overflow_i64__deps: [function() { preciseI64MathUsed = 1 }],
+ llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
+ i64Math.mul(xl, xh, yl, yh);
+ return {
+ f0: i64Math.result,
+ f1: 0 // XXX Need to hack support for this in long.js
};
},
@@ -4649,6 +4904,11 @@ LibraryManager.library = {
llvm_lifetime_start: function() {},
llvm_lifetime_end: function() {},
+ llvm_invariant_start: function() {},
+ llvm_invariant_end: function() {},
+
+ llvm_objectsize_i32: function() { return -1 }, // TODO: support this
+
// ==========================================================================
// math.h
// ==========================================================================
@@ -4873,7 +5133,7 @@ LibraryManager.library = {
if (isNaN(x)) return {{{ cDefine('FP_NAN') }}};
if (!isFinite(x)) return {{{ cDefine('FP_INFINITE') }}};
if (x == 0) return {{{ cDefine('FP_ZERO') }}};
- // FP_SUBNORMAL..?
+ // FP_SUBNORMAL..?
return {{{ cDefine('FP_NORMAL') }}};
},
__fpclassifyd: '__fpclassifyf',
@@ -5277,6 +5537,7 @@ LibraryManager.library = {
// TODO: Implement.
return 0;
},
+ strftime_l: 'strftime', // no locale support yet
strptime: function(buf, format, tm) {
// char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
@@ -5284,6 +5545,7 @@ LibraryManager.library = {
// TODO: Implement.
return 0;
},
+ strptime_l: 'strptime', // no locale support yet
getdate: function(string) {
// struct tm *getdate(const char *string);
@@ -5990,6 +6252,10 @@ LibraryManager.library = {
return eval(Pointer_stringify(ptr));
},
+ emscripten_random: function() {
+ return Math.random();
+ },
+
$Profiling: {
max_: 0,
times: null,
@@ -6021,3 +6287,12 @@ LibraryManager.library = {
}
};
+function autoAddDeps(object, name) {
+ name = [name];
+ for (var item in object) {
+ if (item.substr(-6) != '__deps' && !object[item + '__deps']) {
+ object[item + '__deps'] = name;
+ }
+ }
+}
+
diff --git a/src/library_browser.js b/src/library_browser.js
index 55de7a5c..f12e966e 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -3,45 +3,321 @@
// Utilities for browser environments
mergeInto(LibraryManager.library, {
+ $Browser__postset: 'Module["requestFullScreen"] = function() { Browser.requestFullScreen() };\n' + // exports
+ 'Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };\n' +
+ 'Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };\n' +
+ 'Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };\n',
$Browser: {
- // Given binary data for an image, in a format like PNG or JPG, we convert it
- // to flat pixel data. We do so using the browser's native code.
- decodeImage: function(pixels, format) {
- function encodeBase64(data) {
- var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
- var PAD = '=';
- var ret = '';
- var leftchar = 0;
- var leftbits = 0;
- for (var i = 0; i < data.length; i++) {
- leftchar = (leftchar << 8) | data[i];
- leftbits += 8;
- while (leftbits >= 6) {
- var curr = (leftchar >> (leftbits-6)) & 0x3f;
- leftbits -= 6;
- ret += BASE[curr];
- }
+ mainLoop: {
+ scheduler: null,
+ shouldPause: false,
+ paused: false,
+ queue: [],
+ pause: function() {
+ Browser.mainLoop.shouldPause = true;
+ },
+ resume: function() {
+ if (Browser.mainLoop.paused) {
+ Browser.mainLoop.paused = false;
+ Browser.mainLoop.scheduler();
}
- if (leftbits == 2) {
- ret += BASE[(leftchar&3) << 4];
- ret += PAD + PAD;
- } else if (leftbits == 4) {
- ret += BASE[(leftchar&0xf) << 2];
- ret += PAD;
+ Browser.mainLoop.shouldPause = false;
+ },
+ },
+ pointerLock: false,
+ moduleContextCreatedCallbacks: [],
+
+ createContext: function(canvas, useWebGL, setInModule) {
+#if !USE_TYPED_ARRAYS
+ if (useWebGL) {
+ Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
+ return null;
+ }
+#endif
+ try {
+ var ctx = canvas.getContext(useWebGL ? 'experimental-webgl' : '2d');
+ if (!ctx) throw ':(';
+ } catch (e) {
+ Module.print('Could not create canvas - ' + e);
+ return null;
+ }
+ if (useWebGL) {
+#if GL_DEBUG
+ // Useful to debug native webgl apps: var Module = { printErr: function(x) { console.log(x) } };
+ var tempCtx = ctx;
+ var wrapper = {};
+ for (var prop in tempCtx) {
+ (function(prop) {
+ switch (typeof tempCtx[prop]) {
+ case 'function': {
+ wrapper[prop] = function() {
+ if (GL.debug) {
+ var printArgs = Array.prototype.slice.call(arguments).map(Runtime.prettyPrint);
+ Module.printErr('[gl_f:' + prop + ':' + printArgs + ']');
+ }
+ var ret = tempCtx[prop].apply(tempCtx, arguments);
+ if (GL.debug && typeof ret != 'undefined') {
+ Module.printErr('[ gl:' + prop + ':return:' + Runtime.prettyPrint(ret) + ']');
+ }
+ return ret;
+ }
+ break;
+ }
+ case 'number': case 'string': {
+ wrapper.__defineGetter__(prop, function() {
+ //Module.printErr('[gl_g:' + prop + ':' + tempCtx[prop] + ']');
+ return tempCtx[prop];
+ });
+ wrapper.__defineSetter__(prop, function(value) {
+ if (GL.debug) {
+ Module.printErr('[gl_s:' + prop + ':' + value + ']');
+ }
+ tempCtx[prop] = value;
+ });
+ break;
+ }
+ }
+ })(prop);
+ }
+ ctx = wrapper;
+#endif
+ // Set the background of the WebGL canvas to black
+ canvas.style.backgroundColor = "black";
+
+ // Warn on context loss
+ canvas.addEventListener('webglcontextlost', function(event) {
+ alert('WebGL context lost. You will need to reload the page.');
+ }, false);
+ }
+ if (setInModule) {
+ Module.ctx = ctx;
+ Module.useWebGL = useWebGL;
+ Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
+ }
+ return ctx;
+ },
+
+ requestFullScreen: function() {
+ var canvas = Module.canvas;
+ function fullScreenChange() {
+ if (Module['onFullScreen']) Module['onFullScreen']();
+ if (document['webkitFullScreenElement'] === canvas ||
+ document['mozFullScreenElement'] === canvas ||
+ document['fullScreenElement'] === canvas) {
+ canvas.requestPointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'];
+ canvas.requestPointerLock();
+ }
+ }
+
+ document.addEventListener('fullscreenchange', fullScreenChange, false);
+ document.addEventListener('mozfullscreenchange', fullScreenChange, false);
+ document.addEventListener('webkitfullscreenchange', fullScreenChange, false);
+
+ function pointerLockChange() {
+ Browser.pointerLock = document['pointerLockElement'] === canvas ||
+ document['mozPointerLockElement'] === canvas ||
+ document['webkitPointerLockElement'] === canvas;
+ }
+
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+
+ canvas.requestFullScreen = canvas['requestFullScreen'] ||
+ canvas['mozRequestFullScreen'] ||
+ (canvas['webkitRequestFullScreen'] ? function() { canvas['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
+ canvas.requestFullScreen();
+ },
+
+ requestAnimationFrame: function(func) {
+ if (!window.requestAnimationFrame) {
+ window.requestAnimationFrame = window['requestAnimationFrame'] ||
+ window['mozRequestAnimationFrame'] ||
+ window['webkitRequestAnimationFrame'] ||
+ window['msRequestAnimationFrame'] ||
+ window['oRequestAnimationFrame'] ||
+ window['setTimeout'];
+ }
+ window.requestAnimationFrame(func);
+ },
+
+ getMovementX: function(event) {
+ return event['movementX'] ||
+ event['mozMovementX'] ||
+ event['webkitMovementX'] ||
+ 0;
+ },
+
+ getMovementY: function(event) {
+ return event['movementY'] ||
+ event['mozMovementY'] ||
+ event['webkitMovementY'] ||
+ 0;
+ },
+
+ xhrLoad: function(url, onload, onerror) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = function() {
+ if (xhr.status == 200) {
+ onload(xhr.response);
+ } else {
+ onerror();
}
- return ret;
- }
- var image = new Image();
- image.src = 'data:image/' + format + ';base64,' + encodeBase64(pixels);
- assert(image.complete, 'Image could not be decoded'); // page reload might fix it, decoding is async... need .onload handler...
- var canvas = document.createElement('canvas');
- canvas.width = image.width;
- canvas.height = image.height;
- var ctx = canvas.getContext('2d');
- ctx.drawImage(image, 0, 0);
- var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
- return imageData;
+ };
+ xhr.onerror = onerror;
+ xhr.send(null);
},
+
+ asyncLoad: function(url, callback) {
+ Browser.xhrLoad(url, function(arrayBuffer) {
+ assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
+ callback(new Uint8Array(arrayBuffer));
+ removeRunDependency();
+ }, function(event) {
+ throw 'Loading data file "' + url + '" failed.';
+ });
+ addRunDependency();
+ }
+ },
+
+ emscripten_async_wget: function(url, file, onload, onerror) {
+ url = Pointer_stringify(url);
+
+ Browser.xhrLoad(url, function(response) {
+ var absolute = Pointer_stringify(file);
+ var index = absolute.lastIndexOf('/');
+ FS.createDataFile(
+ absolute.substr(0, index),
+ absolute.substr(index +1),
+ new Uint8Array(response),
+ true, true);
+
+ if (onload) {
+ FUNCTION_TABLE[onload](file);
+ }
+ }, function(event) {
+ if (onerror) {
+ FUNCTION_TABLE[onerror](file);
+ }
+ });
+ },
+
+ emscripten_async_run_script__deps: ['emscripten_run_script'],
+ emscripten_async_run_script: function(script, millis) {
+ Module['noExitRuntime'] = true;
+
+ // TODO: cache these to avoid generating garbage
+ setTimeout(function() {
+ _emscripten_run_script(script);
+ }, millis);
+ },
+
+ emscripten_set_main_loop: function(func, fps) {
+ Module['noExitRuntime'] = true;
+
+ var jsFunc = FUNCTION_TABLE[func];
+ var wrapper = function() {
+ if (Browser.mainLoop.queue.length > 0) {
+ Browser.mainLoop.queue.shift()();
+ setTimeout(wrapper, 0);
+ return;
+ }
+ if (Browser.mainLoop.shouldPause) {
+ // catch pauses from non-main loop sources
+ Browser.mainLoop.paused = true;
+ Browser.mainLoop.shouldPause = false;
+ return;
+ }
+ jsFunc();
+ if (Browser.mainLoop.shouldPause) {
+ // catch pauses from the main loop itself
+ Browser.mainLoop.paused = true;
+ Browser.mainLoop.shouldPause = false;
+ return;
+ }
+ Browser.mainLoop.scheduler();
+ }
+ if (fps && fps > 0) {
+ Browser.mainLoop.scheduler = function() {
+ setTimeout(wrapper, 1000/fps); // doing this each time means that on exception, we stop
+ }
+ } else {
+ Browser.mainLoop.scheduler = function() {
+ Browser.requestAnimationFrame(wrapper);
+ }
+ }
+ Browser.mainLoop.scheduler();
+ },
+
+ emscripten_cancel_main_loop: function() {
+ Browser.mainLoop.scheduler = null;
+ Browser.mainLoop.shouldPause = true;
+ },
+
+ emscripten_pause_main_loop: function() {
+ Browser.mainLoop.pause();
+ },
+
+ emscripten_resume_main_loop: function() {
+ Browser.mainLoop.resume();
+ },
+
+ emscripten_push_main_loop_blocker: function(func) {
+ Browser.mainLoop.queue.push(FUNCTION_TABLE[func]);
+ },
+
+ emscripten_async_call: function(func, millis) {
+ Module['noExitRuntime'] = true;
+
+ var asyncCall = Runtime.getFuncWrapper(func);
+ if (millis >= 0) {
+ setTimeout(asyncCall, millis);
+ } else {
+ Browser.requestAnimationFrame(asyncCall);
+ }
+ },
+
+ emscripten_hide_mouse: function() {
+ var styleSheet = document.styleSheets[0];
+ var rules = styleSheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ if (rules[i].cssText.substr(0, 5) == 'canvas') {
+ styleSheet.deleteRule(i);
+ i--;
+ }
+ }
+ styleSheet.insertRule('canvas.emscripten { border: 1px solid black; cursor: none; }', 0);
+ },
+
+ emscripten_set_canvas_size: function(width, height) {
+ Module['canvas'].width = width;
+ Module['canvas'].height = height;
+ },
+
+ emscripten_get_now: function() {
+ if (window['performance'] && window['performance']['now']) {
+ return window['performance']['now']();
+ } else {
+ return Date.now();
+ }
}
});
+/* Useful stuff for browser debugging
+
+function slowLog(label, text) {
+ if (!slowLog.labels) slowLog.labels = {};
+ if (!slowLog.labels[label]) slowLog.labels[label] = 0;
+ var now = Date.now();
+ if (now - slowLog.labels[label] > 1000) {
+ Module.print(label + ': ' + text);
+ slowLog.labels[label] = now;
+ }
+}
+
+*/
+
diff --git a/src/library_egl.js b/src/library_egl.js
new file mode 100644
index 00000000..635e00a7
--- /dev/null
+++ b/src/library_egl.js
@@ -0,0 +1,26 @@
+
+var LibraryEGL = {
+ eglGetDisplay: function(x_display) { return 3 },
+ eglInitialize: function(display, majorVersion, minorVersion) { return 1 },
+ eglGetConfigs: function(display, hmm1, hmm2, numConfigs) { return 1 },
+ eglChooseConfig: function(display, attribList, config, hmm, numConfigs) { return 1 },
+ eglCreateWindowSurface: function(display, config, hWnd, hmm) { return 4 },
+
+ eglCreateContext__deps: ['glutCreateWindow', '$GL'],
+ eglCreateContext: function(display, config, hmm, contextAttribs) {
+ _glutCreateWindow();
+ return 1;
+ },
+
+ // EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+ eglQuerySurface: function(display, surface, attribute, value) { return 0 },
+
+ // EGLAPI EGLint EGLAPIENTRY eglGetError(void);
+ eglGetError: function() { return 0x3000 /* EGL_SUCCESS */ },
+
+ eglMakeCurrent: function(display, surface, surface_, context) { return 1 },
+ eglSwapBuffers: function() {},
+};
+
+mergeInto(LibraryManager.library, LibraryEGL);
+
diff --git a/src/library_gc.js b/src/library_gc.js
new file mode 100644
index 00000000..bf0a6aff
--- /dev/null
+++ b/src/library_gc.js
@@ -0,0 +1,167 @@
+
+if (GC_SUPPORT) {
+ var LibraryGC = {
+ $GC__deps: ['sbrk'],
+ $GC: {
+ ALLOCATIONS_TO_GC: 1*1024*1024,
+
+ sizes: {}, // if in this map, then a live allocated object. this is iterable
+ scannables: {},
+ finalizers: {},
+ finalizerArgs: {},
+
+ totalAllocations: 0, // bytes of all currently active objects
+ recentAllocations: 0, // bytes allocated since last gc. ignores free()s
+
+ init: function() {
+ assert(!GC.initted);
+ GC.initted = true;
+ if (ENVIRONMENT_IS_WEB) {
+ setInterval(function() {
+ GC.maybeCollect();
+ }, 1000);
+ } else {
+#if ASSERTIONS
+ Module.print('No HTML intervals, so you need to call GC.maybeCollect() or GC.collect() manually');
+#endif
+ }
+ },
+
+ malloc: function(bytes, clear, scannable) {
+ if (!bytes) return 0;
+ var ptr;
+ if (clear) {
+ ptr = _calloc(1, bytes);
+ } else {
+ ptr = _malloc(bytes);
+ }
+ GC.scannables[ptr] = scannable;
+ GC.sizes[ptr] = bytes;
+ GC.totalAllocations += bytes;
+ GC.recentAllocations += bytes;
+ return ptr;
+ },
+
+ free: function(ptr) { // does not check if anything refers to it, this is a forced free
+ var finalizer = GC.finalizers[ptr];
+ if (finalizer) {
+ Runtime.getFuncWrapper(finalizer)(ptr, GC.finalizerArgs[ptr]);
+ GC.finalizers[ptr] = 0;
+ }
+ _free(ptr);
+ delete GC.sizes[ptr];
+ GC.totalAllocations -= GC.sizes[ptr];
+ },
+
+ registerFinalizer: function(ptr, func, arg, oldFunc, oldArg) {
+ var finalizer = GC.finalizers[ptr];
+ if (finalizer) {
+ if (oldFunc) {
+ {{{ makeSetValue('oldFunc', '0', 'finalizer', 'i32') }}};
+ }
+ if (oldArg) {
+ {{{ makeSetValue('oldArg', '0', 'GC.finalizerArgs[ptr]', 'i32') }}};
+ }
+ }
+ GC.finalizers[ptr] = func;
+ GC.finalizerArgs[ptr] = arg;
+ },
+
+ maybeCollect: function() {
+ if (GC.needCollect()) GC.collect();
+ },
+
+ needCollect: function() {
+ return GC.recentAllocations >= GC.ALLOCATIONS_TO_GC; // TODO: time, etc.
+ },
+
+ collect: function() {
+ GC.prep();
+ GC.mark();
+ GC.sweep();
+ GC.recentAllocations = 0;
+ },
+
+ scan: function(start, end) { // scans a memory region and adds new reachable objects
+ for (var i = start; i < end; i += {{{ Runtime.getNativeTypeSize('void*') }}}) {
+ var ptr = {{{ makeGetValue('i', '0', 'void*') }}};
+ if (GC.sizes[ptr] && !GC.reachable[ptr]) {
+ GC.reachable[ptr] = 1;
+ if (GC.scannables[ptr]) {
+ GC.reachableList.push(ptr);
+ }
+ }
+ }
+ },
+
+ prep: function() { // Clear reachables and scan for roots
+ GC.reachable = {}; // 1 if reachable. XXX
+ GC.reachableList = []; // each reachable is added once to this. XXX
+ // static data areas
+ var staticStart = STACK_MAX;
+ var staticEnd = _sbrk.DYNAMIC_START || STATICTOP; // after DYNAMIC_START, sbrk manages it (but it might not exist yet)
+ GC.scan(staticStart, staticEnd);
+ // TODO: scan stack and registers. Currently we assume we run from a timeout or such, so no stack/regs
+ // stack: STACK_ROOT to STACKTOP
+ // registers: call scanners
+ },
+
+ mark: function() { // mark all reachable from roots
+ for (var i = 0; i < GC.reachableList.length; i++) { // note that the list length changes as we push more
+ var ptr = GC.reachableList[i];
+ GC.scan(ptr, ptr + GC.sizes[ptr]);
+ }
+ },
+
+ sweep: function() { // traverse all objects and free all unreachable
+ var freeList = [];
+ for (var ptr in GC.sizes) {
+ if (!GC.reachable[ptr]) {
+ freeList.push(parseInt(ptr));
+ }
+ }
+ for (var i = 0; i < freeList.length; i++) {
+ GC.free(freeList[i]);
+ }
+ }
+ },
+
+ GC_INIT__deps: ['$GC'],
+ GC_INIT: function() {
+ GC.init();
+ },
+
+ GC_MALLOC__deps: ['$GC'],
+ GC_MALLOC: function(bytes) {
+ return GC.malloc(bytes, true, true);
+ },
+
+ GC_MALLOC_ATOMIC__deps: ['$GC'],
+ GC_MALLOC_ATOMIC: function(bytes) {
+ return GC.malloc(bytes, false, false);
+ },
+
+ GC_FREE__deps: ['$GC'],
+ GC_FREE: function(ptr) {
+ GC.free(ptr);
+ },
+
+ GC_REGISTER_FINALIZER_NO_ORDER__deps: ['$GC'],
+ GC_REGISTER_FINALIZER_NO_ORDER: function(ptr, func, arg, old_func, old_arg) {
+ GC.registerFinalizer(ptr, func, arg, old_func, old_arg);
+ },
+
+ GC_MAYBE_COLLECT__deps: ['$GC'],
+ GC_MAYBE_COLLECT: function() {
+ GC.maybeCollect();
+ },
+
+ GC_FORCE_COLLECT__deps: ['$GC'],
+ GC_FORCE_COLLECT: function() {
+ GC.collect();
+ }
+ };
+
+ mergeInto(LibraryManager.library, LibraryGC);
+}
+
diff --git a/src/library_gl.js b/src/library_gl.js
index 1d47f584..f3cea384 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1,339 +1,840 @@
-//"use strict";
-
-// XXX FIXME Hardcoded '4' in many places, here and in library_SDL, for RGBA
+/*
+ * GL support. See https://github.com/kripken/emscripten/wiki/OpenGL-support
+ * for current status.
+ */
var LibraryGL = {
+ $GL__postset: 'GL.init()',
$GL: {
- hashtable: function(name) {
- if (!this._hashtables) {
- this._hashtables = {};
- }
- if (!(name in this._hashtables)) {
- this._hashtables[name] = {
- table: {},
- counter: 1,
- add: function(obj) {
- var id = this.counter++;
- this.table[id] = obj;
- return id;
- },
- get: function(id) {
- if( id == 0 ) return null;
-#if ASSERTIONS
- assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name);
+#if GL_DEBUG
+ debug: true,
#endif
- return this.table[id];
- },
- remove: function(id) {
- if( id == 0 ) return;
-#if ASSERTIONS
- assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name);
+
+ counter: 1,
+ buffers: {},
+ programs: {},
+ framebuffers: {},
+ renderbuffers: {},
+ textures: {},
+ uniforms: {},
+ shaders: {},
+
+ packAlignment: 4, // default alignment is 4 bytes
+ unpackAlignment: 4, // default alignment is 4 bytes
+
+ init: function() {
+ Browser.moduleContextCreatedCallbacks.push(GL.initExtensions);
+ },
+
+ // Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters
+ scan: function(table, object) {
+ for (var item in table) {
+ if (table[item] == object) return item;
+ }
+ return 0;
+ },
+
+ // Find a token in a shader source string
+ findToken: function(source, token) {
+ function isIdentChar(ch) {
+ if (ch >= 48 && ch <= 57) // 0-9
+ return true;
+ if (ch >= 65 && ch <= 90) // A-Z
+ return true;
+ if (ch >= 97 && ch <= 122) // a-z
+ return true;
+ return false;
+ }
+ var i = -1;
+ do {
+ i = source.indexOf(token, i + 1);
+ if (i < 0) {
+ break;
+ }
+ if (i > 0 && isIdentChar(source[i - 1])) {
+ continue;
+ }
+ i += token.length;
+ if (i < source.length - 1 && isIdentChar(source[i + 1])) {
+ continue;
+ }
+ return true;
+ } while (true);
+ return false;
+ },
+
+ getSource: function(shader, count, string, length) {
+ var source = '';
+ for (var i = 0; i < count; ++i) {
+ var frag;
+ if (length) {
+ var len = {{{ makeGetValue('length', 'i*4', 'i32') }}};
+ if (len < 0) {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
+ } else {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}}, len);
+ }
+ } else {
+ frag = Pointer_stringify({{{ makeGetValue('string', 'i*4', 'i32') }}});
+ }
+ source += frag;
+ }
+ // Let's see if we need to enable the standard derivatives extension
+ type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */);
+ if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) {
+ if (GL.findToken(source, "dFdx") ||
+ GL.findToken(source, "dFdy") ||
+ GL.findToken(source, "fwidth")) {
+ source = "#extension GL_OES_standard_derivatives : enable\n" + source;
+ var extension = Module.ctx.getExtension("OES_standard_derivatives");
+#if GL_DEBUG
+ if (!extension) {
+ Module.printErr("Shader attempts to use the standard derivatives extension which is not available.");
+ }
#endif
- delete this.table[id];
+ }
+ }
+ return source;
+ },
+
+ computeImageSize: function(width, height, sizePerPixel, alignment) {
+ function roundedToNextMultipleOf(x, y) {
+ return Math.floor((x + y - 1) / y) * y
+ }
+ var plainRowSize = width * sizePerPixel;
+ var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment);
+ return (height <= 0) ? 0 :
+ ((height - 1) * alignedRowSize + plainRowSize);
+ },
+
+ getTexPixelData: function(type, format, width, height, pixels, internalFormat) {
+ var sizePerPixel;
+ switch (type) {
+ case 0x1401 /* GL_UNSIGNED_BYTE */:
+ switch (format) {
+ case 0x1906 /* GL_ALPHA */:
+ case 0x1909 /* GL_LUMINANCE */:
+ sizePerPixel = 1;
+ break;
+ case 0x1907 /* GL_RGB */:
+ sizePerPixel = 3;
+ break;
+ case 0x1908 /* GL_RGBA */:
+ sizePerPixel = 4;
+ break;
+ case 0x190A /* GL_LUMINANCE_ALPHA */:
+ sizePerPixel = 2;
+ break;
+ default:
+ throw 'Invalid format (' + format + ')';
}
- };
+ break;
+ case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */:
+ case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */:
+ case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */:
+ sizePerPixel = 2;
+ break;
+ case 0x1406 /* GL_FLOAT */:
+ assert(GL.floatExt, 'Must have OES_texture_float to use float textures');
+ switch (format) {
+ case 0x1907 /* GL_RGB */:
+ sizePerPixel = 3*4;
+ break;
+ case 0x1908 /* GL_RGBA */:
+ sizePerPixel = 4*4;
+ break;
+ default:
+ throw 'Invalid format (' + format + ')';
+ }
+ internalFormat = Module.ctx.RGBA;
+ break;
+ default:
+ throw 'Invalid type (' + type + ')';
+ }
+ var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment);
+ if (type == 0x1401 /* GL_UNSIGNED_BYTE */) {
+ pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+bytes') }}};
+ } else if (type == 0x1406 /* GL_FLOAT */) {
+ pixels = {{{ makeHEAPView('F32', 'pixels', 'pixels+bytes') }}};
+ } else {
+ pixels = {{{ makeHEAPView('U16', 'pixels', 'pixels+bytes') }}};
+ }
+ return {
+ pixels: pixels,
+ internalFormat: internalFormat
}
- return this._hashtables[name];
},
+
+ initExtensions: function() {
+ if (GL.initExtensions.done) return;
+ GL.initExtensions.done = true;
+
+ GL.compressionExt = Module.ctx.getExtension('WEBGL_compressed_texture_s3tc') ||
+ Module.ctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') ||
+ Module.ctx.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
+
+ GL.anisotropicExt = Module.ctx.getExtension('EXT_texture_filter_anisotropic') ||
+ Module.ctx.getExtension('MOZ_EXT_texture_filter_anisotropic') ||
+ Module.ctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
+
+ GL.floatExt = Module.ctx.getExtension('OES_texture_float');
+ }
+ },
+
+ glPixelStorei: function(pname, param) {
+ if (pname == 0x0D05 /* GL_PACK_ALIGNMENT */) {
+ GL.packAlignment = param;
+ } else if (pname == 0x0cf5 /* GL_UNPACK_ALIGNMENT */) {
+ GL.unpackAlignment = param;
+ }
+ Module.ctx.pixelStorei(pname, param);
},
glGetString: function(name_) {
switch(name_) {
- case Module.ctx.VENDOR:
- case Module.ctx.RENDERER:
- case Module.ctx.VERSION:
+ case 0x1F00 /* GL_VENDOR */:
+ case 0x1F01 /* GL_RENDERER */:
+ case 0x1F02 /* GL_VERSION */:
return allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL);
- case 0x1F03: // Extensions
+ case 0x1F03 /* GL_EXTENSIONS */:
return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ')), 'i8', ALLOC_NORMAL);
+ case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */:
+ return allocate(intArrayFromString('OpenGL ES GLSL 1.00 (WebGL)'), 'i8', ALLOC_NORMAL);
default:
throw 'Failure: Invalid glGetString value: ' + name_;
}
},
glGetIntegerv: function(name_, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getParameter(name_)', 'i32') }}};
+ switch(name_) { // Handle a few trivial GLES values
+ case 0x8DFA: // GL_SHADER_COMPILER
+ {{{ makeSetValue('p', '0', '1', 'i32') }}};
+ return;
+ case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS
+ {{{ makeSetValue('p', '0', '0', 'i32') }}};
+ return;
+ }
+ var result = Module.ctx.getParameter(name_);
+ switch (typeof(result)) {
+ case "number":
+ {{{ makeSetValue('p', '0', 'result', 'i32') }}};
+ break;
+ case "boolean":
+ {{{ makeSetValue('p', '0', 'result ? 1 : 0', 'i8') }}};
+ break;
+ case "string":
+ throw 'Native code calling glGetIntegerv(' + name_ + ') on a name which returns a string!';
+ case "object":
+ if (result === null) {
+ {{{ makeSetValue('p', '0', '0', 'i32') }}};
+ } else if (result instanceof Float32Array ||
+ result instanceof Uint32Array ||
+ result instanceof Int32Array ||
+ result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ {{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}};
+ }
+ } else if (result instanceof WebGLBuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'i32') }}};
+ } else if (result instanceof WebGLProgram) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'i32') }}};
+ } else if (result instanceof WebGLFramebuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'i32') }}};
+ } else if (result instanceof WebGLRenderbuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'i32') }}};
+ } else if (result instanceof WebGLTexture) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'i32') }}};
+ } else {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Native code calling glGetIntegerv(' + name_ + ') and it returns undefined';
+ default:
+ throw 'Why did we hit the default case?';
+ }
+ },
+
+ glGetFloatv: function(name_, p) {
+ var result = Module.ctx.getParameter(name_);
+ switch (typeof(result)) {
+ case "number":
+ {{{ makeSetValue('p', '0', 'result', 'float') }}};
+ break;
+ case "boolean":
+ {{{ makeSetValue('p', '0', 'result ? 1.0 : 0.0', 'float') }}};
+ break;
+ case "string":
+ {{{ makeSetValue('p', '0', '0', 'float') }}};
+ case "object":
+ if (result === null) {
+ throw 'Native code calling glGetFloatv(' + name_ + ') and it returns null';
+ } else if (result instanceof Float32Array ||
+ result instanceof Uint32Array ||
+ result instanceof Int32Array ||
+ result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ {{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}};
+ }
+ } else if (result instanceof WebGLBuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'float') }}};
+ } else if (result instanceof WebGLProgram) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'float') }}};
+ } else if (result instanceof WebGLFramebuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'float') }}};
+ } else if (result instanceof WebGLRenderbuffer) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'float') }}};
+ } else if (result instanceof WebGLTexture) {
+ {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'float') }}};
+ } else {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Native code calling glGetFloatv(' + name_ + ') and it returns undefined';
+ default:
+ throw 'Why did we hit the default case?';
+ }
+ },
+
+ glGetBooleanv: function(name_, p) {
+ var result = Module.ctx.getParameter(name_);
+ switch (typeof(result)) {
+ case "number":
+ {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}};
+ break;
+ case "boolean":
+ {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}};
+ break;
+ case "string":
+ throw 'Native code calling glGetBooleanv(' + name_ + ') on a name which returns a string!';
+ case "object":
+ if (result === null) {
+ {{{ makeSetValue('p', '0', '0', 'i8') }}};
+ } else if (result instanceof Float32Array ||
+ result instanceof Uint32Array ||
+ result instanceof Int32Array ||
+ result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ {{{ makeSetValue('p', 'i', 'result[i] != 0', 'i8') }}};
+ }
+ } else if (result instanceof WebGLBuffer ||
+ result instanceof WebGLProgram ||
+ result instanceof WebGLFramebuffer ||
+ result instanceof WebGLRenderbuffer ||
+ result instanceof WebGLTexture) {
+ {{{ makeSetValue('p', '0', '1', 'i8') }}}; // non-zero ID is always 1!
+ } else {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Unknown object returned from WebGL getParameter';
+ default:
+ throw 'Why did we hit the default case?';
+ }
},
- glGenTextures__deps: ['$GL'],
glGenTextures: function(n, textures) {
for (var i = 0; i < n; i++) {
- var id = GL.hashtable("texture").add(Module.ctx.createTexture());
- {{{ makeSetValue('textures', 'i', 'id', 'i32') }}};
+ var id = GL.counter++;
+ GL.textures[id] = Module.ctx.createTexture();
+ {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}};
}
},
glDeleteTextures: function(n, textures) {
for (var i = 0; i < n; i++) {
- var id = {{{ makeGetValue('textures', 'i', 'i32') }}};
- Module.ctx.deleteTexture(GL.hashtable("texture").get(id));
- GL.hashtable("texture").remove(id);
+ var id = {{{ makeGetValue('textures', 'i*4', 'i32') }}};
+ Module.ctx.deleteTexture(GL.textures[id]);
+ GL.textures[id] = null;
}
},
- glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) {
+ glCompressedTexImage2D: function(target, level, internalFormat, width, height, border, imageSize, data) {
+ assert(GL.compressionExt);
+ if (data) {
+ data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}};
+ } else {
+ data = null;
+ }
+ Module.ctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data);
+ },
+
+ glCompressedTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, imageSize, data) {
+ assert(GL.compressionExt);
+ if (data) {
+ data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}};
+ } else {
+ data = null;
+ }
+ Module.ctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, data);
+ },
+
+ glTexImage2D: function(target, level, internalFormat, width, height, border, format, type, pixels) {
if (pixels) {
- pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize
+ var data = GL.getTexPixelData(type, format, width, height, pixels, internalFormat);
+ pixels = data.pixels;
+ internalFormat = data.internalFormat;
+ } else {
+ pixels = null;
}
- Module.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ Module.ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
},
glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) {
if (pixels) {
- pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize
+ var data = GL.getTexPixelData(type, format, width, height, pixels, -1);
+ pixels = data.pixels;
+ } else {
+ pixels = null;
}
Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
},
+ glReadPixels: function(x, y, width, height, format, type, pixels) {
+ Module.ctx.readPixels(x, y, width, height, format, type, HEAPU8.subarray(pixels));
+ },
+
glBindTexture: function(target, texture) {
- Module.ctx.bindTexture(target, GL.hashtable("texture").get(texture));
+ Module.ctx.bindTexture(target, texture ? GL.textures[texture] : null);
+ },
+
+ glGetTexParameterfv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'float') }}};
+ },
+
+ glGetTexParameteriv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'i32') }}};
+ },
+
+ glIsTexture: function(texture) {
+ var fb = GL.textures[texture];
+ if (typeof(fb) == 'undefined') {
+ return 0;
+ }
+ return Module.ctx.isTexture(fb);
},
- glGenBuffers__deps: ['$GL'],
glGenBuffers: function(n, buffers) {
for (var i = 0; i < n; i++) {
- var id = GL.hashtable("buffer").add(Module.ctx.createBuffer());
- {{{ makeSetValue('buffers', 'i', 'id', 'i32') }}};
+ var id = GL.counter++;
+ GL.buffers[id] = Module.ctx.createBuffer();
+ {{{ makeSetValue('buffers', 'i*4', 'id', 'i32') }}};
}
},
glDeleteBuffers: function(n, buffers) {
for (var i = 0; i < n; i++) {
- var id = {{{ makeGetValue('buffers', 'i', 'i32') }}};
- Module.ctx.deleteBuffer(GL.hashtable("buffer").get(id));
- GL.hashtable("buffer").remove(id);
+ var id = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
+ Module.ctx.deleteBuffer(GL.buffers[id]);
+ GL.buffers[id] = null;
}
},
+ glGetBufferParameteriv: function(target, value, data) {
+ {{{ makeSetValue('data', '0', 'Module.ctx.getBufferParameter(target, value)', 'i32') }}};
+ },
+
glBufferData: function(target, size, data, usage) {
- var floatArray = new Float32Array(TypedArray_copy(data, size));
- Module.ctx.bufferData(target, floatArray, usage);
+ Module.ctx.bufferData(target, HEAPU8.subarray(data, data+size), usage);
+ },
+
+ glBufferSubData: function(target, offset, size, data) {
+ var floatArray = {{{ makeHEAPView('F32', 'data', 'data+size') }}};
+ Module.ctx.bufferSubData(target, offset, floatArray);
+ },
+
+ glIsBuffer: function(buffer) {
+ var fb = GL.buffers[buffer];
+ if (typeof(fb) == 'undefined') {
+ return 0;
+ }
+ return Module.ctx.isBuffer(fb);
+ },
+
+ glGenRenderbuffers: function(n, renderbuffers) {
+ for (var i = 0; i < n; i++) {
+ var id = GL.counter++;
+ GL.renderbuffers[id] = Module.ctx.createRenderbuffer();
+ {{{ makeSetValue('renderbuffers', 'i*4', 'id', 'i32') }}};
+ }
+ },
+
+ glDeleteRenderbuffers: function(n, renderbuffers) {
+ for (var i = 0; i < n; i++) {
+ var id = {{{ makeGetValue('renderbuffers', 'i*4', 'i32') }}};
+ Module.ctx.deleteRenderbuffer(GL.renderbuffers[id]);
+ GL.renderbuffers[id];
+ }
+ },
+
+ glBindRenderbuffer: function(target, renderbuffer) {
+ Module.ctx.bindRenderbuffer(target, renderbuffer ? GL.renderbuffers[renderbuffer] : null);
+ },
+
+ glGetRenderbufferParameteriv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.ctx.getRenderbufferParameter(target, pname)', 'i32') }}};
+ },
+
+ glIsRenderbuffer: function(renderbuffer) {
+ var fb = GL.renderbuffers[renderbuffer];
+ if (typeof(fb) == 'undefined') {
+ return 0;
+ }
+ return Module.ctx.isRenderbuffer(fb);
+ },
+
+ glGetUniformfv: function(program, location, params) {
+ var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]);
+ if (typeof data == 'number') {
+ {{{ makeSetValue('params', '0', 'data', 'float') }}};
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ {{{ makeSetValue('params', 'i', 'data[i]', 'float') }}};
+ }
+ }
+ },
+
+ glGetUniformiv: function(program, location, params) {
+ var data = Module.ctx.getUniform(GL.programs[program], GL.uniforms[location]);
+ if (typeof data == 'number' || typeof data == 'boolean') {
+ {{{ makeSetValue('params', '0', 'data', 'i32') }}};
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ {{{ makeSetValue('params', 'i', 'data[i]', 'i32') }}};
+ }
+ }
},
- glBindAttribLocation_deps: ['$GL'],
glGetUniformLocation: function(program, name) {
name = Pointer_stringify(name);
- return GL.hashtable("uniform").add(
- Module.ctx.getUniformLocation(GL.hashtable("program").get(program), name));
+ var loc = Module.ctx.getUniformLocation(GL.programs[program], name);
+ if (!loc) return -1;
+ var id = GL.counter++;
+ GL.uniforms[id] = loc;
+ return id;
+ },
+
+ glGetVertexAttribfv: function(index, pname, params) {
+ var data = Module.ctx.getVertexAttrib(index, pname);
+ if (typeof data == 'number') {
+ {{{ makeSetValue('params', '0', 'data', 'float') }}};
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ {{{ makeSetValue('params', 'i', 'data[i]', 'float') }}};
+ }
+ }
+ },
+
+ glGetVertexAttribiv: function(index, pname, params) {
+ var data = Module.ctx.getVertexAttrib(index, pname);
+ if (typeof data == 'number' || typeof data == 'boolean') {
+ {{{ makeSetValue('params', '0', 'data', 'i32') }}};
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ {{{ makeSetValue('params', 'i', 'data[i]', 'i32') }}};
+ }
+ }
+ },
+
+ glGetVertexAttribPointerv: function(index, pname, pointer) {
+ {{{ makeSetValue('pointer', '0', 'Module.ctx.getVertexAttribOffset(index, pname)', 'i32') }}};
+ },
+
+ glGetActiveUniform: function(program, index, bufSize, length, size, type, name) {
+ program = GL.programs[program];
+ var info = Module.ctx.getActiveUniform(program, index);
+
+ var infoname = info.name.slice(0, bufSize - 1);
+ writeStringToMemory(infoname, name);
+
+ if (length) {
+ {{{ makeSetValue('length', '0', 'infoname.length', 'i32') }}};
+ }
+ if (size) {
+ {{{ makeSetValue('size', '0', 'info.size', 'i32') }}};
+ }
+ if (type) {
+ {{{ makeSetValue('type', '0', 'info.type', 'i32') }}};
+ }
},
- glUniform1f: function(Location, v0) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform1f(Location, v0);
+ glUniform1f: function(location, v0) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform1f(location, v0);
},
- glUniform2f: function(Location, v0, v1) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform2f(Location, v0, v1);
+ glUniform2f: function(location, v0, v1) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform2f(location, v0, v1);
},
- glUniform3f: function(Location, v0, v1, v2) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform3f(Location, v0, v1, v2);
+ glUniform3f: function(location, v0, v1, v2) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform3f(location, v0, v1, v2);
},
- glUniform4f: function(Location, v0, v1, v2, v3) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform4f(Location, v0, v1, v2, v3);
+ glUniform4f: function(location, v0, v1, v2, v3) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform4f(location, v0, v1, v2, v3);
},
- glUniform1i: function(Location, v0) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform1i(Location, v0);
+ glUniform1i: function(location, v0) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform1i(location, v0);
},
- glUniform2i: function(Location, v0, v1) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform2i(Location, v0, v1);
+ glUniform2i: function(location, v0, v1) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform2i(location, v0, v1);
},
- glUniform3i: function(Location, v0, v1, v2) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform3i(Location, v0, v1, v2);
+ glUniform3i: function(location, v0, v1, v2) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform3i(location, v0, v1, v2);
},
- glUniform4i: function(Location, v0, v1, v2, v3) {
- Location = GL.hashtable("uniform").get(Location);
- Module.ctx.uniform4i(Location, v0, v1, v2, v3);
+ glUniform4i: function(location, v0, v1, v2, v3) {
+ location = GL.uniforms[location];
+ Module.ctx.uniform4i(location, v0, v1, v2, v3);
},
- glUniform1fv: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform1fv(Location, value);
+ glUniform1iv: function(location, count, value) {
+ location = GL.uniforms[location];
+ value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform1iv(location, value);
},
- glUniform2fv: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform2iv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 2;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform2fv(Location, value);
+ value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform2iv(location, value);
},
- glUniform3fv: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform3iv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 3;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform3fv(Location, value);
+ value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform3iv(location, value);
},
- glUniform4fv: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform4iv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 4;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform4fv(Location, value);
+ value = {{{ makeHEAPView('32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform4iv(location, value);
},
- glUniform1fi: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
- value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform1fi(Location, value);
+ glUniform1fv: function(location, count, value) {
+ location = GL.uniforms[location];
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform1fv(location, value);
},
- glUniform2fi: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform2fv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 2;
- value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform2fi(Location, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform2fv(location, value);
},
- glUniform3fi: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform3fv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 3;
- value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform3fi(Location, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform3fv(location, value);
},
- glUniform4fi: function(Location, count, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniform4fv: function(location, count, value) {
+ location = GL.uniforms[location];
count *= 4;
- value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniform4fi(Location, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniform4fv(location, value);
},
- glUniformMatrix2fv: function(Location, count, transpose, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniformMatrix2fv: function(location, count, transpose, value) {
+ location = GL.uniforms[location];
count *= 4;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniformMatrix2fv(Location, transpose, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniformMatrix2fv(location, transpose, value);
},
- glUniformMatrix3fv: function(Location, count, transpose, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniformMatrix3fv: function(location, count, transpose, value) {
+ location = GL.uniforms[location];
count *= 9;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniformMatrix3fv(Location, transpose, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniformMatrix3fv(location, transpose, value);
},
- glUniformMatrix4fv: function(Location, count, transpose, value) {
- Location = GL.hashtable("uniform").get(Location);
+ glUniformMatrix4fv: function(location, count, transpose, value) {
+ location = GL.uniforms[location];
count *= 16;
- value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize
- Module.ctx.uniformMatrix4fv(Location, transpose, value);
+ value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ Module.ctx.uniformMatrix4fv(location, transpose, value);
},
glBindBuffer: function(target, buffer) {
- Module.ctx.bindBuffer(target, GL.hashtable("buffer").get(buffer));
+ Module.ctx.bindBuffer(target, buffer ? GL.buffers[buffer] : null);
},
glVertexAttrib1fv: function(index, v) {
- v = new Float32Array(TypedArray_copy(v, 1*4)); // TODO: optimize
+ v = {{{ makeHEAPView('F32', 'v', 'v+1*4') }}};
Module.ctx.vertexAttrib1fv(index, v);
},
glVertexAttrib2fv: function(index, v) {
- v = new Float32Array(TypedArray_copy(v, 2*4)); // TODO: optimize
+ v = {{{ makeHEAPView('F32', 'v', 'v+2*4') }}};
Module.ctx.vertexAttrib2fv(index, v);
},
glVertexAttrib3fv: function(index, v) {
- v = new Float32Array(TypedArray_copy(v, 3*4)); // TODO: optimize
+ v = {{{ makeHEAPView('F32', 'v', 'v+3*4') }}};
Module.ctx.vertexAttrib3fv(index, v);
},
glVertexAttrib4fv: function(index, v) {
- v = new Float32Array(TypedArray_copy(v, 4*4)); // TODO: optimize
+ v = {{{ makeHEAPView('F32', 'v', 'v+4*4') }}};
Module.ctx.vertexAttrib4fv(index, v);
},
glGetAttribLocation: function(program, name) {
- program = GL.hashtable("program").get(program);
+ program = GL.programs[program];
name = Pointer_stringify(name);
- Module.ctx.getAttribLocation(program, name);
+ return Module.ctx.getAttribLocation(program, name);
+ },
+
+ glGetActiveAttrib: function(program, index, bufSize, length, size, type, name) {
+ program = GL.programs[program];
+ var info = Module.ctx.getActiveAttrib(program, index);
+
+ var infoname = info.name.slice(0, bufSize - 1);
+ writeStringToMemory(infoname, name);
+
+ if (length) {
+ {{{ makeSetValue('length', '0', 'infoname.length', 'i32') }}};
+ }
+ if (size) {
+ {{{ makeSetValue('size', '0', 'info.size', 'i32') }}};
+ }
+ if (type) {
+ {{{ makeSetValue('type', '0', 'info.type', 'i32') }}};
+ }
},
- glCreateShader_deps: ['$GL'],
glCreateShader: function(shaderType) {
- var shader = Module.ctx.createShader(shaderType);
- return GL.hashtable("shader").add(shader);
+ var id = GL.counter++;
+ GL.shaders[id] = Module.ctx.createShader(shaderType);
+ return id;
+ },
+
+ glDeleteShader: function(shader) {
+ Module.ctx.deleteShader(GL.shaders[shader]);
+ GL.shaders[shader] = null;
+ },
+
+ glDetachShader: function(program, shader) {
+ Module.ctx.detachShader(GL.programs[program],
+ GL.shaders[shader]);
+ },
+
+ glGetAttachedShaders: function(program, maxCount, count, shaders) {
+ var result = Module.ctx.getAttachedShaders(GL.programs[program]);
+ var len = result.length;
+ if (len > maxCount) {
+ len = maxCount;
+ }
+ {{{ makeSetValue('count', '0', 'len', 'i32') }}};
+ for (var i = 0; i < len; ++i) {
+ {{{ makeSetValue('shaders', 'i*4', 'GL.shaders[result[i]]', 'i32') }}};
+ }
},
- glShaderSource_deps: ['$GL'],
glShaderSource: function(shader, count, string, length) {
- var source = "";
- for (var i = 0; i < count; ++i) {
- var frag = string[i];
- if (length) {
- var len = {{{ makeGetValue('length', 'i', 'i32') }}};
- if (len < 0) {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}});
- } else {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}, len);
- }
- } else {
- frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}});
- }
- if (source.length) {
- source += "\n";
- }
- source += frag;
+ var source = GL.getSource(shader, count, string, length);
+ Module.ctx.shaderSource(GL.shaders[shader], source);
+ },
+
+ glGetShaderSource: function(shader, bufSize, length, source) {
+ var result = Module.ctx.getShaderSource(GL.shaders[shader]);
+ result.slice(0, bufSize - 1);
+ writeStringToMemory(result, source);
+ if (length) {
+ {{{ makeSetValue('length', '0', 'result.length', 'i32') }}};
}
- Module.ctx.shaderSource(GL.hashtable("shader").get(shader), source);
},
- glCompileShader_deps: ['$GL'],
glCompileShader: function(shader) {
- Module.ctx.compileShader(GL.hashtable("shader").get(shader));
+ Module.ctx.compileShader(GL.shaders[shader]);
},
- glGetShaderInfoLog_deps: ['$GL'],
glGetShaderInfoLog: function(shader, maxLength, length, infoLog) {
- var log = Module.ctx.getShaderInfoLog(GL.hashtable("shader").get(shader));
- log.slice(0, maxLength - 1);
+ var log = Module.ctx.getShaderInfoLog(GL.shaders[shader]);
+ // Work around a bug in Chromium which causes getShaderInfoLog to return null
+ if (!log) {
+ log = "";
+ }
+ log = log.substr(0, maxLength - 1);
writeStringToMemory(log, infoLog);
if (length) {
- {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}}
+ {{{ makeSetValue('length', '0', 'log.length', 'i32') }}}
}
},
-
- glGetShaderiv_deps: ['$GL'],
- glGetShaderiv : function(shader, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.hashtable("shader").get(shader),pname)', 'i32') }}};
+
+ glGetShaderiv : function(shader, pname, p) {
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ {{{ makeSetValue('p', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[shader]).length + 1', 'i32') }}};
+ } else {
+ {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.shaders[shader], pname)', 'i32') }}};
+ }
},
- glGetProgramiv_deps: ['$GL'],
- glGetProgramiv : function(program, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.hashtable("program").get(program),pname)', 'i32') }}};
+ glGetProgramiv : function(program, pname, p) {
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ {{{ makeSetValue('p', '0', 'Module.ctx.getProgramInfoLog(GL.programs[program]).length + 1', 'i32') }}};
+ } else {
+ {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.programs[program], pname)', 'i32') }}};
+ }
+ },
+
+ glIsShader: function(shader) {
+ var fb = GL.shaders[shader];
+ if (typeof(fb) == 'undefined') {
+ return 0;
+ }
+ return Module.ctx.isShader(fb);
},
- glCreateProgram_deps: ['$GL'],
glCreateProgram: function() {
- return GL.hashtable("program").add(Module.ctx.createProgram());
+ var id = GL.counter++;
+ GL.programs[id] = Module.ctx.createProgram();
+ return id;
+ },
+
+ glDeleteProgram: function(program) {
+ Module.ctx.deleteProgram(GL.programs[program]);
+ GL.programs[program] = null;
},
- glAttachShader_deps: ['$GL'],
glAttachShader: function(program, shader) {
- Module.ctx.attachShader(GL.hashtable("program").get(program),
- GL.hashtable("shader").get(shader));
+ Module.ctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
+ },
+
+ glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) {
+ var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType);
+ {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}};
+ {{{ makeSetValue('range', '4', 'result.rangeMax', 'i32') }}};
+ {{{ makeSetValue('precision', '0', 'result.precision', 'i32') }}};
},
- glLinkProgram_deps: ['$GL'],
glLinkProgram: function(program) {
- Module.ctx.linkProgram(GL.hashtable("program").get(program));
+ Module.ctx.linkProgram(GL.programs[program]);
},
- glGetProgramInfoLog_deps: ['$GL'],
glGetProgramInfoLog: function(program, maxLength, length, infoLog) {
- var log = Module.ctx.getProgramInfoLog(GL.hashtable("program").get(program));
+ var log = Module.ctx.getProgramInfoLog(GL.programs[program]);
// Work around a bug in Chromium which causes getProgramInfoLog to return null
if (!log) {
log = "";
@@ -341,292 +842,1639 @@ var LibraryGL = {
log = log.substr(0, maxLength - 1);
writeStringToMemory(log, infoLog);
if (length) {
- {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}}
+ {{{ makeSetValue('length', '0', 'log.length', 'i32') }}}
}
},
- glUseProgram_deps: ['$Gl'],
glUseProgram: function(program) {
- Module.ctx.useProgram(GL.hashtable("program").get(program));
+ Module.ctx.useProgram(program ? GL.programs[program] : null);
+ },
+
+ glValidateProgram: function(program) {
+ Module.ctx.validateProgram(GL.programs[program]);
+ },
+
+ glIsProgram: function(program) {
+ var fb = GL.programs[program];
+ if (typeof(fb) == 'undefined') {
+ return 0;
+ }
+ return Module.ctx.isProgram(fb);
},
- glBindAttribLocation_deps: ['$GL'],
glBindAttribLocation: function(program, index, name) {
name = Pointer_stringify(name);
- Module.ctx.bindAttribLocation(GL.hashtable("program").get(program), index, name);
+ Module.ctx.bindAttribLocation(GL.programs[program], index, name);
},
- glBindFramebuffer_deps: ['$GL'],
glBindFramebuffer: function(target, framebuffer) {
- Module.ctx.bindFramebuffer(target, GL.hashtable("framebuffer").get(framebuffer));
+ Module.ctx.bindFramebuffer(target, framebuffer ? GL.framebuffers[framebuffer] : null);
},
- glGenFramebuffers_deps: ['$GL'],
glGenFramebuffers: function(n, ids) {
for (var i = 0; i < n; ++i) {
- var fb = GL.hashtable("framebuffer").add(Module.ctx.createFramebuffer());
- {{{ makeSetValue('ids', 'i', 'fb', 'i32') }}};
+ var id = GL.counter++;
+ GL.framebuffers[id] = Module.ctx.createFramebuffer();
+ {{{ makeSetValue('ids', 'i*4', 'id', 'i32') }}};
}
},
- glDeleteFramebuffers_deps: ['$GL'],
glDeleteFramebuffers: function(n, framebuffers) {
for (var i = 0; i < n; ++i) {
- var fb = GL.hashtable("framebuffer").get({{{ makeGetValue('framebuffers', 'i', 'i32' ) }}});
- Module.ctx.deleteFramebuffer(fb);
+ var id = {{{ makeGetValue('framebuffers', 'i*4', 'i32') }}};
+ Module.ctx.deleteFramebuffer(GL.framebuffers[id]);
+ GL.framebuffers[id] = null;
}
},
- glFramebufferRenderbuffer_deps: ['$GL'],
glFramebufferRenderbuffer: function(target, attachment, renderbuffertarget, renderbuffer) {
Module.ctx.framebufferRenderbuffer(target, attachment, renderbuffertarget,
- GL.hashtable("renderbuffer").get(renderbuffer));
+ GL.renderbuffers[renderbuffer]);
},
- glFramebufferTexture2D_deps: ['$GL'],
glFramebufferTexture2D: function(target, attachment, textarget, texture, level) {
Module.ctx.framebufferTexture2D(target, attachment, textarget,
- GL.hashtable("texture").get(texture), level);
+ GL.textures[texture], level);
},
- glGetFramebufferAttachmentParameteriv_deps: ['$GL'],
glGetFramebufferAttachmentParameteriv: function(target, attachment, pname, params) {
var result = Module.ctx.getFramebufferAttachmentParameter(target, attachment, pname);
{{{ makeSetValue('params', '0', 'params', 'i32') }}};
},
- glIsFramebuffer_deps: ['$GL'],
glIsFramebuffer: function(framebuffer) {
- var fb = GL.hashtable("framebuffer").get(framebuffer);
+ var fb = GL.framebuffers[framebuffer];
if (typeof(fb) == 'undefined') {
- return false;
+ return 0;
}
return Module.ctx.isFramebuffer(fb);
},
-};
+ // GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL
+
+ $GLEmulation__postset: 'GLEmulation.init();',
+ $GLEmulation: {
+ // Fog support. Partial, we assume shaders are used that implement fog. We just pass them uniforms
+ fogStart: 0,
+ fogEnd: 1,
+ fogDensity: 1.0,
+ fogColor: null,
+ fogMode: 0x0800, // GL_EXP
+ fogEnabled: false,
+
+ init: function() {
+ GLEmulation.fogColor = new Float32Array(4);
+
+ // Add some emulation workarounds
+ Module.printErr('WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work');
+
+ // XXX some of the capabilities we don't support may lead to incorrect rendering, if we do not emulate them in shaders
+ var validCapabilities = {
+ 0x0B44: 1, // GL_CULL_FACE
+ 0x0BE2: 1, // GL_BLEND
+ 0x0BD0: 1, // GL_DITHER,
+ 0x0B90: 1, // GL_STENCIL_TEST
+ 0x0B71: 1, // GL_DEPTH_TEST
+ 0x0C11: 1, // GL_SCISSOR_TEST
+ 0x8037: 1, // GL_POLYGON_OFFSET_FILL
+ 0x809E: 1, // GL_SAMPLE_ALPHA_TO_COVERAGE
+ 0x80A0: 1 // GL_SAMPLE_COVERAGE
+ };
+ _glEnable = function(cap) {
+ // Clean up the renderer on any change to the rendering state. The optimization of
+ // skipping renderer setup is aimed at the case of multiple glDraw* right after each other
+ if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup();
+ if (cap == 0x0B60 /* GL_FOG */) {
+ GLEmulation.fogEnabled = true;
+ return;
+ } else if (!(cap in validCapabilities)) {
+ return;
+ }
+ Module.ctx.enable(cap);
+ };
+ _glDisable = function(cap) {
+ if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup();
+ if (cap == 0x0B60 /* GL_FOG */) {
+ GLEmulation.fogEnabled = false;
+ return;
+ } else if (!(cap in validCapabilities)) {
+ return;
+ }
+ Module.ctx.disable(cap);
+ };
+ _glIsEnabled = function(cap) {
+ if (cap == 0x0B60 /* GL_FOG */) {
+ return GLEmulation.fogEnabled ? 1 : 0;
+ } else if (!(cap in validCapabilities)) {
+ return 0;
+ }
+ return Module.ctx.isEnabled(cap);
+ };
+
+ var glGetIntegerv = _glGetIntegerv;
+ _glGetIntegerv = function(pname, params) {
+ switch (pname) {
+ case 0x84E2: pname = Module.ctx.MAX_TEXTURE_IMAGE_UNITS /* fake it */; break; // GL_MAX_TEXTURE_UNITS
+ case 0x8B4A: { // GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB
+ var result = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_UNIFORM_VECTORS);
+ {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply
+ return;
+ }
+ case 0x8B49: { // GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB
+ var result = Module.ctx.getParameter(Module.ctx.MAX_FRAGMENT_UNIFORM_VECTORS);
+ {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply
+ return;
+ }
+ case 0x8B4B: { // GL_MAX_VARYING_FLOATS_ARB
+ var result = Module.ctx.getParameter(Module.ctx.MAX_VARYING_VECTORS);
+ {{{ makeSetValue('params', '0', 'result*4', 'i32') }}}; // GLES gives num of 4-element vectors, GL wants individual components, so multiply
+ return;
+ }
+ case 0x8871: pname = Module.ctx.MAX_COMBINED_TEXTURE_IMAGE_UNITS /* close enough */; break; // GL_MAX_TEXTURE_COORDS
+ }
+ glGetIntegerv(pname, params);
+ };
+
+ var glGetString = _glGetString;
+ _glGetString = function(name_) {
+ switch(name_) {
+ case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support
+ return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') +
+ ' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' +
+ (GL.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') +
+ (GL.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '')
+ ), 'i8', ALLOC_NORMAL);
+ }
+ return glGetString(name_);
+ };
+
+ // Do some automatic rewriting to work around GLSL differences. Note that this must be done in
+ // tandem with the rest of the program, by itself it cannot suffice.
+ // Note that we need to remember shader types for this rewriting, saving sources makes it easier to debug.
+ GL.shaderInfos = {};
+#if GL_DEBUG
+ GL.shaderSources = {};
+ GL.shaderOriginalSources = {};
+#endif
+ var glCreateShader = _glCreateShader;
+ _glCreateShader = function(shaderType) {
+ var id = glCreateShader(shaderType);
+ GL.shaderInfos[id] = {
+ type: shaderType,
+ ftransform: false
+ };
+ return id;
+ };
+
+ var glShaderSource = _glShaderSource;
+ _glShaderSource = function(shader, count, string, length) {
+ var source = GL.getSource(shader, count, string, length);
+#if GL_DEBUG
+ GL.shaderOriginalSources[shader] = source;
+#endif
+ // XXX We add attributes and uniforms to shaders. The program can ask for the # of them, and see the
+ // ones we generated, potentially confusing it? Perhaps we should hide them.
+ if (GL.shaderInfos[shader].type == Module.ctx.VERTEX_SHADER) {
+ // Replace ftransform() with explicit project/modelview transforms, and add position and matrix info.
+ var has_pm = source.search(/u_projection/) >= 0;
+ var has_mm = source.search(/u_modelView/) >= 0;
+ var has_pv = source.search(/a_position/) >= 0;
+ var need_pm = 0, need_mm = 0, need_pv = 0;
+ var old = source;
+ source = source.replace(/ftransform\(\)/g, '(u_projection * u_modelView * a_position)');
+ if (old != source) need_pm = need_mm = need_pv = 1;
+ old = source;
+ source = source.replace(/gl_ProjectionMatrix/g, 'u_projection');
+ if (old != source) need_pm = 1;
+ old = source;
+ source = source.replace(/gl_ModelViewMatrixTranspose\[2\]/g, 'vec4(u_modelView[0][2], u_modelView[1][2], u_modelView[2][2], u_modelView[3][2])'); // XXX extremely inefficient
+ if (old != source) need_mm = 1;
+ old = source;
+ source = source.replace(/gl_ModelViewMatrix/g, 'u_modelView');
+ if (old != source) need_mm = 1;
+ old = source;
+ source = source.replace(/gl_Vertex/g, 'a_position');
+ if (old != source) need_pv = 1;
+ old = source;
+ source = source.replace(/gl_ModelViewProjectionMatrix/g, '(u_projection * u_modelView)');
+ if (old != source) need_pm = need_mm = 1;
+ if (need_pv && !has_pv) source = 'attribute vec4 a_position; \n' + source;
+ if (need_mm && !has_mm) source = 'uniform mat4 u_modelView; \n' + source;
+ if (need_pm && !has_pm) source = 'uniform mat4 u_projection; \n' + source;
+ GL.shaderInfos[shader].ftransform = need_pm || need_mm || need_pv; // we will need to provide the fixed function stuff as attributes and uniforms
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ // XXX To handle both regular texture mapping and cube mapping, we use vec4 for tex coordinates.
+ var old = source;
+ var need_vtc = source.search('v_texCoord' + i) == -1;
+ source = source.replace(new RegExp('gl_TexCoord\\[' + i + '\\]', 'g'), 'v_texCoord' + i)
+ .replace(new RegExp('gl_MultiTexCoord' + i, 'g'), 'a_texCoord' + i);
+ if (source != old) {
+ source = 'attribute vec4 a_texCoord' + i + '; \n' + source;
+ if (need_vtc) {
+ source = 'varying vec4 v_texCoord' + i + '; \n' + source;
+ }
+ }
+
+ old = source;
+ source = source.replace(new RegExp('gl_TextureMatrix\\[' + i + '\\]', 'g'), 'u_textureMatrix' + i);
+ if (source != old) {
+ source = 'uniform mat4 u_textureMatrix' + i + '; \n' + source;
+ }
+ }
+ if (source.indexOf('gl_FrontColor') >= 0) {
+ source = 'varying vec4 v_color; \n' +
+ source.replace(/gl_FrontColor/g, 'v_color');
+ }
+ if (source.indexOf('gl_Color') >= 0) {
+ source = 'attribute vec4 a_color; \n' +
+ 'uniform vec4 u_color; \n' +
+ 'uniform int u_hasColorAttrib; \n' +
+ source.replace(/gl_Color/g, '(u_hasColorAttrib > 0 ? a_color : u_color)');
+ }
+ if (source.indexOf('gl_Normal') >= 0) {
+ source = 'attribute vec3 a_normal; \n' +
+ source.replace(/gl_Normal/g, 'a_normal');
+ }
+ // fog
+ if (source.indexOf('gl_FogFragCoord') >= 0) {
+ source = 'varying float v_fogFragCoord; \n' +
+ source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
+ }
+ } else { // Fragment shader
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ var old = source;
+ source = source.replace(new RegExp('gl_TexCoord\\[' + i + '\\]', 'g'), 'v_texCoord' + i);
+ if (source != old) {
+ source = 'varying vec4 v_texCoord' + i + '; \n' + source;
+ }
+ }
+ if (source.indexOf('gl_Color') >= 0) {
+ source = 'varying vec4 v_color; \n' + source.replace(/gl_Color/g, 'v_color');
+ }
+ if (source.indexOf('gl_Fog.color') >= 0) {
+ source = 'uniform vec4 u_fogColor; \n' +
+ source.replace(/gl_Fog.color/g, 'u_fogColor');
+ }
+ if (source.indexOf('gl_Fog.end') >= 0) {
+ source = 'uniform float u_fogEnd; \n' +
+ source.replace(/gl_Fog.end/g, 'u_fogEnd');
+ }
+ if (source.indexOf('gl_Fog.scale') >= 0) {
+ source = 'uniform float u_fogScale; \n' +
+ source.replace(/gl_Fog.scale/g, 'u_fogScale');
+ }
+ if (source.indexOf('gl_Fog.density') >= 0) {
+ source = 'uniform float u_fogDensity; \n' +
+ source.replace(/gl_Fog.density/g, 'u_fogDensity');
+ }
+ if (source.indexOf('gl_FogFragCoord') >= 0) {
+ source = 'varying float v_fogFragCoord; \n' +
+ source.replace(/gl_FogFragCoord/g, 'v_fogFragCoord');
+ }
+ source = 'precision mediump float;\n' + source;
+ }
+#if GL_DEBUG
+ GL.shaderSources[shader] = source;
+#endif
+ Module.ctx.shaderSource(GL.shaders[shader], source);
+ };
+
+ var glCompileShader = _glCompileShader;
+ _glCompileShader = function(shader) {
+ Module.ctx.compileShader(GL.shaders[shader]);
+ if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) {
+ Module.printErr('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader]));
+ Module.printErr('Info: ' + JSON.stringify(GL.shaderInfos[shader]));
+#if GL_DEBUG
+ Module.printErr('Original source: ' + GL.shaderOriginalSources[shader]);
+ Module.printErr('Source: ' + GL.shaderSources[shader]);
+ throw 'Shader compilation halt';
+#else
+ Module.printErr('Enable GL_DEBUG to see shader source');
+#endif
+ }
+ };
+
+ GL.programShaders = {};
+ var glAttachShader = _glAttachShader;
+ _glAttachShader = function(program, shader) {
+ if (!GL.programShaders[program]) GL.programShaders[program] = [];
+ GL.programShaders[program].push(shader);
+ glAttachShader(program, shader);
+ };
+
+ var glUseProgram = _glUseProgram;
+ _glUseProgram = function(program) {
+#if GL_DEBUG
+ if (GL.debug) {
+ Module.printErr('[using program with shaders]');
+ if (program) {
+ GL.programShaders[program].forEach(function(shader) {
+ Module.printErr(' shader ' + shader + ', original source: ' + GL.shaderOriginalSources[shader]);
+ Module.printErr(' Source: ' + GL.shaderSources[shader]);
+ });
+ }
+ }
+#endif
+ GL.currProgram = program;
+ glUseProgram(program);
+ }
+ var glDeleteProgram = _glDeleteProgram;
+ _glDeleteProgram = function(program) {
+ glDeleteProgram(program);
+ if (program == GL.currProgram) GL.currProgram = 0;
+ };
+
+ // If attribute 0 was not bound, bind it to 0 for WebGL performance reasons. Track if 0 is free for that.
+ var zeroUsedPrograms = {};
+ var glBindAttribLocation = _glBindAttribLocation;
+ _glBindAttribLocation = function(program, index, name) {
+ if (index == 0) zeroUsedPrograms[program] = true;
+ glBindAttribLocation(program, index, name);
+ };
+ var glLinkProgram = _glLinkProgram;
+ _glLinkProgram = function(program) {
+ if (!(program in zeroUsedPrograms)) {
+ Module.ctx.bindAttribLocation(GL.programs[program], 0, 'a_position');
+ }
+ glLinkProgram(program);
+ };
+
+ var glBindBuffer = _glBindBuffer;
+ _glBindBuffer = function(target, buffer) {
+ glBindBuffer(target, buffer);
+ if (target == Module.ctx.ARRAY_BUFFER) {
+ GL.currArrayBuffer = buffer;
+ } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) {
+ GL.currElementArrayBuffer = buffer;
+ }
+ };
+
+ var glDeleteBuffers = _glDeleteBuffers;
+ _glDeleteBuffers = function(n, buffers) {
+ glDeleteBuffers(n, buffers);
+ for (var i = 0; i < n; i++) {
+ var buffer = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
+ if (buffer == GL.currArrayBuffer) GL.currArrayBuffer = 0;
+ if (buffer == GL.currElementArrayBuffer) GL.currElementArrayBuffer = 0;
+ }
+ };
+
+ var glGetFloatv = _glGetFloatv;
+ _glGetFloatv = function(pname, params) {
+ if (pname == 0x0BA6) { // GL_MODELVIEW_MATRIX
+ HEAPF32.set(GL.immediate.matrix['m'], params >> 2);
+ } else if (pname == 0x0BA7) { // GL_PROJECTION_MATRIX
+ HEAPF32.set(GL.immediate.matrix['p'], params >> 2);
+ } else if (pname == 0x0BA8) { // GL_TEXTURE_MATRIX
+ HEAPF32.set(GL.immediate.matrix['t' + GL.immediate.clientActiveTexture], params >> 2);
+ } else if (pname == 0x0B66) { // GL_FOG_COLOR
+ HEAPF32.set(GLEmulation.fogColor, params >> 2);
+ } else if (pname == 0x0B63) { // GL_FOG_START
+ {{{ makeSetValue('params', '0', 'GLEmulation.fogStart', 'float') }}};
+ } else if (pname == 0x0B64) { // GL_FOG_END
+ {{{ makeSetValue('params', '0', 'GLEmulation.fogEnd', 'float') }}};
+ } else if (pname == 0x0B62) { // GL_FOG_DENSITY
+ {{{ makeSetValue('params', '0', 'GLEmulation.fogDensity', 'float') }}};
+ } else if (pname == 0x0B65) { // GL_FOG_MODE
+ {{{ makeSetValue('params', '0', 'GLEmulation.fogMode', 'float') }}};
+ } else {
+ glGetFloatv(pname, params);
+ }
+ };
-// Simple pass-through functions
-[[0, 'shadeModel fogi fogfv getError finish flush'],
- [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus activeTexture'],
- [2, 'pixelStorei vertexAttrib1f depthRange polygonOffset blendFunc'],
- [3, 'texParameteri texParameterf drawArrays vertexAttrib2f'],
- [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements'],
- [5, 'vertexAttrib4f'],
- [6, 'vertexAttribPointer']].forEach(function(data) {
- var num = data[0];
- var names = data[1];
- var args = range(num).map(function(i) { return 'x' + i }).join(', ');
- var stub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })';
- names.split(' ').forEach(function(name_) {
- var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1);
-#if ASSERTIONS
- assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName);
-#endif
- LibraryGL[cName] = eval(stub.replace('NAME', name_));
- //print(cName + ': ' + LibraryGL[cName]);
- });
-});
+ var glHint = _glHint;
+ _glHint = function(target, mode) {
+ if (target == 0x84EF) { // GL_TEXTURE_COMPRESSION_HINT
+ return;
+ }
+ glHint(target, mode);
+ };
+ },
-var LibraryGLUT = {
- $GLUT: {
- initTime: null,
- idleFunc: null,
- keyboardFunc: null,
- keyboardUpFunc: null,
- specialFunc: null,
- specialUpFunc: null,
- reshapeFunc: null,
- passiveMotionFunc: null,
- mouseFunc: null,
- lastX: 0,
- lastY: 0,
-
- onMousemove: function(event) {
- GLUT.lastX = event['clientX'];
- GLUT.lastY = event['clientY'];
- if (GLUT.passiveMotionFunc) {
- FUNCTION_TABLE[GLUT.passiveMotionFunc](GLUT.lastX, GLUT.lastY);
+ getProcAddress: function(name) {
+ name = name.replace('EXT', '').replace('ARB', '');
+ // Do the translation carefully because of closure
+ switch (name) {
+ case 'glCreateShaderObject': case 'glCreateShader': func = _glCreateShader; break;
+ case 'glCreateProgramObject': case 'glCreateProgram': func = _glCreateProgram; break;
+ case 'glAttachObject': case 'glAttachShader': func = _glAttachShader; break;
+ case 'glUseProgramObject': case 'glUseProgram': func = _glUseProgram; break;
+ case 'glDeleteObject': func = function(id) {
+ if (GL.programs[id]) {
+ _glDeleteProgram(id);
+ } else if (GL.shaders[id]) {
+ _glDeleteShader(id);
+ } else {
+ Module.printErr('WARNING: deleteObject received invalid id: ' + id);
+ }
+ }; break;
+ case 'glGetObjectParameteriv': func = function(id, type, result) {
+ if (GL.programs[id]) {
+ if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB
+ {{{ makeSetValue('result', '0', 'Module.ctx.getProgramInfoLog(GL.programs[id]).length', 'i32') }}};
+ return;
+ }
+ _glGetProgramiv(id, type, result);
+ } else if (GL.shaders[id]) {
+ if (type == 0x8B84) { // GL_OBJECT_INFO_LOG_LENGTH_ARB
+ {{{ makeSetValue('result', '0', 'Module.ctx.getShaderInfoLog(GL.shaders[id]).length', 'i32') }}};
+ return;
+ }
+ _glGetShaderiv(id, type, result);
+ } else {
+ Module.printErr('WARNING: getObjectParameteriv received invalid id: ' + id);
+ }
+ }; break;
+ case 'glGetInfoLog': func = function(id, maxLength, length, infoLog) {
+ if (GL.programs[id]) {
+ _glGetProgramInfoLog(id, maxLength, length, infoLog);
+ } else if (GL.shaders[id]) {
+ _glGetShaderInfoLog(id, maxLength, length, infoLog);
+ } else {
+ Module.printErr('WARNING: getObjectParameteriv received invalid id: ' + id);
+ }
+ }; break;
+ case 'glBindProgram': func = function(type, id) {
+ assert(id == 0);
+ }; break;
+ case 'glDrawRangeElements': func = _glDrawRangeElements; break;
+ case 'glShaderSource': func = _glShaderSource; break;
+ case 'glCompileShader': func = _glCompileShader; break;
+ case 'glLinkProgram': func = _glLinkProgram; break;
+ case 'glGetUniformLocation': func = _glGetUniformLocation; break;
+ case 'glUniform1f': func = _glUniform1f; break;
+ case 'glUniform2f': func = _glUniform2f; break;
+ case 'glUniform3f': func = _glUniform3f; break;
+ case 'glUniform4f': func = _glUniform4f; break;
+ case 'glUniform1fv': func = _glUniform1fv; break;
+ case 'glUniform2fv': func = _glUniform2fv; break;
+ case 'glUniform3fv': func = _glUniform3fv; break;
+ case 'glUniform4fv': func = _glUniform4fv; break;
+ case 'glUniform1i': func = _glUniform1i; break;
+ case 'glUniform2i': func = _glUniform2i; break;
+ case 'glUniform3i': func = _glUniform3i; break;
+ case 'glUniform4i': func = _glUniform4i; break;
+ case 'glUniform1iv': func = _glUniform1iv; break;
+ case 'glUniform2iv': func = _glUniform2iv; break;
+ case 'glUniform3iv': func = _glUniform3iv; break;
+ case 'glUniform4iv': func = _glUniform4iv; break;
+ case 'glBindAttribLocation': func = _glBindAttribLocation; break;
+ case 'glGetActiveUniform': func = _glGetActiveUniform; break;
+ case 'glGenBuffers': func = _glGenBuffers; break;
+ case 'glBindBuffer': func = _glBindBuffer; break;
+ case 'glBufferData': func = _glBufferData; break;
+ case 'glBufferSubData': func = _glBufferSubData; break;
+ case 'glDeleteBuffers': func = _glDeleteBuffers; break;
+ case 'glActiveTexture': func = _glActiveTexture; break;
+ case 'glClientActiveTexture': func = _glClientActiveTexture; break;
+ case 'glGetProgramiv': func = _glGetProgramiv; break;
+ case 'glEnableVertexAttribArray': func = _glEnableVertexAttribArray; break;
+ case 'glDisableVertexAttribArray': func = _glDisableVertexAttribArray; break;
+ case 'glVertexAttribPointer': func = _glVertexAttribPointer; break;
+ case 'glBindRenderbuffer': func = _glBindRenderbuffer; break;
+ case 'glDeleteRenderbuffers': func = _glDeleteRenderbuffers; break;
+ case 'glGenRenderbuffers': func = _glGenRenderbuffers; break;
+ case 'glCompressedTexImage2D': func = _glCompressedTexImage2D; break;
+ case 'glCompressedTexSubImage2D': func = _glCompressedTexSubImage2D; break;
+ case 'glBindFramebuffer': func = _glBindFramebuffer; break;
+ case 'glGenFramebuffers': func = _glGenFramebuffers; break;
+ case 'glDeleteFramebuffers': func = _glDeleteFramebuffers; break;
+ case 'glFramebufferRenderbuffer': func = _glFramebufferRenderbuffer; break;
+ case 'glFramebufferTexture2D': func = _glFramebufferTexture2D; break;
+ case 'glGetFramebufferAttachmentParameteriv': func = _glGetFramebufferAttachmentParameteriv; break;
+ case 'glIsFramebuffer': func = _glIsFramebuffer; break;
+ case 'glCheckFramebufferStatus': func = _glCheckFramebufferStatus; break;
+ case 'glRenderbufferStorage': func = _glRenderbufferStorage; break;
+ default: {
+ Module.printErr('WARNING: getProcAddress failed for ' + name);
+ func = function() {
+ Module.printErr('WARNING: empty replacement for ' + name + ' called, no-op');
+ return 0;
+ };
}
+ }
+ return Runtime.addFunction(func);
+ }
+ },
+
+ // GL Immediate mode
+
+ $GLImmediate__postset: 'Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });',
+ $GLImmediate__deps: ['$Browser'],
+ $GLImmediate: {
+ MAX_TEXTURES: 7,
+
+ // Vertex and index data
+ vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer). Default view is F32
+ vertexDataU8: null, // U8 view
+ tempData: null,
+ indexData: null,
+ vertexCounter: 0,
+ mode: 0,
+
+ rendererCache: {},
+ rendererComponents: {}, // small cache for calls inside glBegin/end. counts how many times the element was seen
+ rendererComponentPointer: 0, // next place to start a glBegin/end component
+ lastRenderer: null, // used to avoid cleaning up and re-preparing the same renderer
+ lastArrayBuffer: null, // used in conjunction with lastRenderer
+ lastProgram: null, // ""
+
+ // The following data structures are used for OpenGL Immediate Mode matrix routines.
+ matrix: {},
+ matrixStack: {},
+ currentMatrix: 'm', // default is modelview
+ tempMatrix: null,
+ matricesModified: false,
+
+ // Clientside attributes
+ VERTEX: 0,
+ NORMAL: 1,
+ COLOR: 2,
+ TEXTURE0: 3,
+ TEXTURE1: 4,
+ TEXTURE2: 5,
+ TEXTURE3: 6,
+ TEXTURE4: 7,
+ TEXTURE5: 8,
+ TEXTURE6: 9,
+ NUM_ATTRIBUTES: 10,
+ NUM_TEXTURES: 7,
+ ATTRIBUTE_BY_NAME: {},
+
+ totalEnabledClientAttributes: 0,
+ enabledClientAttributes: [0, 0],
+ clientAttributes: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}], // raw data, including possible unneeded ones
+ liveClientAttributes: [], // the ones actually alive in the current computation, sorted
+ modifiedClientAttributes: false,
+ clientActiveTexture: 0,
+ clientColor: null,
+
+ byteSizeByType: {
+ 0x1400: 1, // GL_BYTE
+ 0x1401: 1, // GL_UNSIGNED_BYTE
+ 0x1402: 2, // GL_SHORT
+ 0x1403: 2, // GL_UNSIGNED_SHORT
+ 0x1404: 4, // GL_INT
+ 0x1405: 4, // GL_UNSIGNED_INT
+ 0x1406: 4 // GL_FLOAT
},
- getSpecialKey: function(keycode) {
- var key = null;
- switch (keycode) {
- case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break;
- case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break;
- case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break;
- case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break;
- case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break;
- case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break;
- case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break;
- case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break;
- case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break;
- case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break;
- case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break;
- case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break;
- case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break;
- case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break;
- case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break;
- case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break;
- case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break;
- case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break;
- case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break;
- case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break;
- case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break;
- };
- return key;
+ setClientAttribute: function(name, size, type, stride, pointer) {
+ var attrib = this.clientAttributes[GL.immediate.ATTRIBUTE_BY_NAME[name]];
+ attrib.name = name;
+ attrib.size = size;
+ attrib.type = type;
+ attrib.stride = stride;
+ attrib.pointer = pointer;
+ this.modifiedClientAttributes = true;
},
- onKeydown: function(event) {
- if (GLUT.specialFunc || GLUT.keyboardFunc) {
- var key = GLUT.getSpecialKey(event['keyCode']);
- if (key !== null) {
- if( GLUT.specialFunc ) FUNCTION_TABLE[GLUT.specialFunc](key, GLUT.lastX, GLUT.lastY);
+ // Temporary buffers
+ MAX_TEMP_BUFFER_SIZE: 2*1024*1024,
+ tempBufferIndexLookup: null,
+ tempVertexBuffers: null,
+ tempIndexBuffers: null,
+ tempQuadIndexBuffer: null,
+
+ generateTempBuffers: function() {
+ function ceilPower2(x) {
+ return Math.pow(2, Math.ceil(Math.log(i || 1)/Math.log(2)));
+ }
+ this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1);
+ var last = -1, curr = -1;
+ for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
+ var size = ceilPower2(i);
+ if (size != last) {
+ curr++;
+ last = size;
}
- else if( GLUT.keyboardFunc ) {
- FUNCTION_TABLE[GLUT.keyboardFunc](event['keyCode'], GLUT.lastX, GLUT.lastY);
+ this.tempBufferIndexLookup[i] = curr;
+ }
+ this.tempVertexBuffers = [];
+ this.tempIndexBuffers = [];
+ last = -1;
+ for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
+ var size = ceilPower2(i);
+ curr = this.tempBufferIndexLookup[i];
+ if (size != last) {
+ this.tempVertexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
+ this.tempIndexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
+ last = size;
}
}
+
+ // GL_QUAD indexes can be precalculated
+ this.tempQuadIndexBuffer = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer);
+ var numIndexes = this.MAX_TEMP_BUFFER_SIZE >> 1;
+ var quadIndexes = new Uint16Array(numIndexes);
+ var i = 0, v = 0;
+ while (1) {
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+1;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+2;
+ if (i >= numIndexes) break;
+ quadIndexes[i++] = v+3;
+ if (i >= numIndexes) break;
+ v += 4;
+ }
+ Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, quadIndexes, Module.ctx.STATIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
},
-
- onKeyup: function(event) {
- if (GLUT.specialUpFunc || GLUT.keyboardUpFunc) {
- var key = GLUT.getSpecialKey(event['keyCode']);
- if (key !== null) {
- if(GLUT.specialFunc) FUNCTION_TABLE[GLUT.specialUpFunc](key, GLUT.lastX, GLUT.lastY);
- }
- else if(GLUT.keyboardUpFunc) {
- FUNCTION_TABLE[GLUT.keyboardUpFunc](event['keyCode'], GLUT.lastX, GLUT.lastY);
+
+ // Renderers
+ addRendererComponent: function(name, size, type) {
+ if (!this.rendererComponents[name]) {
+ this.rendererComponents[name] = 1;
+#if ASSERTIONS
+ assert(!this.enabledClientAttributes[this.ATTRIBUTE_BY_NAME[name]]); // cannot get mixed up with this, for example we will disable this later
+#endif
+ this.enabledClientAttributes[this.ATTRIBUTE_BY_NAME[name]] = true;
+ this.setClientAttribute(name, size, type, 0, this.rendererComponentPointer);
+ this.rendererComponentPointer += size * this.byteSizeByType[type];
+ } else {
+ this.rendererComponents[name]++;
+ }
+ },
+
+ disableBeginEndClientAttributes: function() {
+ for (var name in this.rendererComponents) {
+ this.enabledClientAttributes[this.ATTRIBUTE_BY_NAME[name]] = false;
+ }
+ },
+
+ getRenderer: function() {
+ // return a renderer object given the liveClientAttributes
+ // we maintain a cache of renderers, optimized to not generate garbage
+ var attributes = GL.immediate.liveClientAttributes;
+ var cacheItem = GL.immediate.rendererCache;
+ for (var i = 0; i < attributes.length; i++) {
+ var attribute = attributes[i];
+ if (!cacheItem[attribute.name]) cacheItem[attribute.name] = {};
+ cacheItem = cacheItem[attribute.name];
+ if (!cacheItem[attribute.size]) cacheItem[attribute.size] = {};
+ cacheItem = cacheItem[attribute.size];
+ if (!cacheItem[attribute.type]) cacheItem[attribute.type] = {};
+ cacheItem = cacheItem[attribute.type];
+ }
+ if (GLEmulation.fogEnabled) {
+ var fogParam = GLEmulation.fogMode;
+ } else {
+ var fogParam = 0; // all valid modes are non-zero
+ }
+ if (!cacheItem[fogParam]) cacheItem[fogParam] = {};
+ cacheItem = cacheItem[fogParam];
+ if (GL.currProgram) { // Note the order here; this one is last, and optional
+ if (!cacheItem[GL.currProgram]) cacheItem[GL.currProgram] = {};
+ cacheItem = cacheItem[GL.currProgram];
+ }
+ if (!cacheItem.renderer) {
+#if GL_DEBUG
+ Module.printErr('generating renderer for ' + JSON.stringify(attributes));
+#endif
+ cacheItem.renderer = this.createRenderer();
+ }
+ return cacheItem.renderer;
+ },
+
+ createRenderer: function(renderer) {
+ var useCurrProgram = !!GL.currProgram;
+ var hasTextures = false, textureSizes = [], textureTypes = [], textureOffsets = [];
+ for (var i = 0; i < GL.immediate.NUM_TEXTURES; i++) {
+ if (GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) {
+ textureSizes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].size;
+ textureTypes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].type;
+ textureOffsets[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].offset;
+ hasTextures = true;
}
}
+ var stride = GL.immediate.stride;
+ var positionSize = GL.immediate.clientAttributes[GL.immediate.VERTEX].size;
+ var positionType = GL.immediate.clientAttributes[GL.immediate.VERTEX].type;
+ var positionOffset = GL.immediate.clientAttributes[GL.immediate.VERTEX].offset;
+ var colorSize = 0, colorType, colorOffset;
+ if (GL.immediate.enabledClientAttributes[GL.immediate.COLOR]) {
+ colorSize = GL.immediate.clientAttributes[GL.immediate.COLOR].size;
+ colorType = GL.immediate.clientAttributes[GL.immediate.COLOR].type;
+ colorOffset = GL.immediate.clientAttributes[GL.immediate.COLOR].offset;
+ }
+ var normalSize = 0, normalType, normalOffset;
+ if (GL.immediate.enabledClientAttributes[GL.immediate.NORMAL]) {
+ normalSize = GL.immediate.clientAttributes[GL.immediate.NORMAL].size;
+ normalType = GL.immediate.clientAttributes[GL.immediate.NORMAL].type;
+ normalOffset = GL.immediate.clientAttributes[GL.immediate.NORMAL].offset;
+ }
+ var ret = {
+ init: function() {
+ if (useCurrProgram) {
+ if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) {
+ this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][0]];
+ this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][1]];
+ } else {
+ this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][1]];
+ this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][0]];
+ }
+ this.program = GL.programs[GL.currProgram];
+ } else {
+ // IMPORTANT NOTE: If you parameterize the shader source based on any runtime values
+ // in order to create the least expensive shader possible based on the features being
+ // used, you should also update the code in the beginning of getRenderer to make sure
+ // that you cache the renderer based on the said parameters.
+ this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER);
+ var zero = positionSize == 2 ? '0, ' : '';
+ if (GLEmulation.fogEnabled) {
+ switch (GLEmulation.fogMode) {
+ case 0x0801: // GL_EXP2
+ // fog = exp(-(gl_Fog.density * gl_FogFragCoord)^2)
+ var fogFormula = ' float fog = exp(-u_fogDensity * u_fogDensity * ecDistance * ecDistance); \n';
+ break;
+ case 0x2601: // GL_LINEAR
+ // fog = (gl_Fog.end - gl_FogFragCoord) * gl_fog.scale
+ var fogFormula = ' float fog = (u_fogEnd - ecDistance) * u_fogScale; \n';
+ break;
+ default: // default to GL_EXP
+ // fog = exp(-gl_Fog.density * gl_FogFragCoord)
+ var fogFormula = ' float fog = exp(-u_fogDensity * ecDistance); \n';
+ break;
+ }
+ }
+ Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n' +
+ 'attribute vec2 a_texCoord0; \n' +
+ (hasTextures ? 'varying vec2 v_texCoord; \n' : '') +
+ 'varying vec4 v_color; \n' +
+ (colorSize ? 'attribute vec4 a_color; \n': 'uniform vec4 u_color; \n') +
+ (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord; \n' : '') +
+ 'uniform mat4 u_modelView; \n' +
+ 'uniform mat4 u_projection; \n' +
+ 'void main() \n' +
+ '{ \n' +
+ ' vec4 ecPosition = (u_modelView * vec4(a_position, ' + zero + '1.0)); \n' + // eye-coordinate position
+ ' gl_Position = u_projection * ecPosition; \n' +
+ (hasTextures ? 'v_texCoord = a_texCoord0; \n' : '') +
+ (colorSize ? 'v_color = a_color; \n' : 'v_color = u_color; \n') +
+ (GLEmulation.fogEnabled ? 'v_fogFragCoord = abs(ecPosition.z);\n' : '') +
+ '} \n');
+ Module.ctx.compileShader(this.vertexShader);
+
+ this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER);
+ Module.ctx.shaderSource(this.fragmentShader, 'precision mediump float; \n' +
+ 'varying vec2 v_texCoord; \n' +
+ 'uniform sampler2D u_texture; \n' +
+ 'varying vec4 v_color; \n' +
+ (GLEmulation.fogEnabled ? (
+ 'varying float v_fogFragCoord; \n' +
+ 'uniform vec4 u_fogColor; \n' +
+ 'uniform float u_fogEnd; \n' +
+ 'uniform float u_fogScale; \n' +
+ 'uniform float u_fogDensity; \n' +
+ 'float ffog(in float ecDistance) { \n' +
+ fogFormula +
+ ' fog = clamp(fog, 0.0, 1.0); \n' +
+ ' return fog; \n' +
+ '} \n'
+ ) : '') +
+ 'void main() \n' +
+ '{ \n' +
+ (hasTextures ? 'gl_FragColor = v_color * texture2D( u_texture, v_texCoord );\n' :
+ 'gl_FragColor = v_color;\n') +
+ (GLEmulation.fogEnabled ? 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a); \n' : '') +
+ '} \n');
+ Module.ctx.compileShader(this.fragmentShader);
+
+ this.program = Module.ctx.createProgram();
+ Module.ctx.attachShader(this.program, this.vertexShader);
+ Module.ctx.attachShader(this.program, this.fragmentShader);
+ Module.ctx.bindAttribLocation(this.program, 0, 'a_position');
+ Module.ctx.linkProgram(this.program);
+ }
+
+ this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position');
+ this.texCoordLocations = [];
+ for (var i = 0; i < textureSizes.length; i++) {
+ if (textureSizes[i]) {
+ this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, 'a_texCoord' + i);
+ }
+ }
+ this.textureMatrixLocations = [];
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i);
+ }
+ this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color');
+ this.normalLocation = Module.ctx.getAttribLocation(this.program, 'a_normal');
+
+ this.textureLocation = Module.ctx.getUniformLocation(this.program, 'u_texture'); // only for immediate mode with no shaders, so only one is enough
+ this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView');
+ this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection');
+ this.hasColorAttribLocation = Module.ctx.getUniformLocation(this.program, 'u_hasColorAttrib');
+ this.colorUniformLocation = Module.ctx.getUniformLocation(this.program, 'u_color');
+
+ this.hasTextures = hasTextures;
+ this.hasColorAttrib = colorSize > 0 && this.colorLocation >= 0;
+ this.hasColorUniform = !!this.colorUniformLocation;
+ this.hasNormal = normalSize > 0 && this.normalLocation >= 0;
+
+ this.floatType = Module.ctx.FLOAT; // minor optimization
+
+ this.fogColorLocation = Module.ctx.getUniformLocation(this.program, 'u_fogColor');
+ this.fogEndLocation = Module.ctx.getUniformLocation(this.program, 'u_fogEnd');
+ this.fogScaleLocation = Module.ctx.getUniformLocation(this.program, 'u_fogScale');
+ this.fogDensityLocation = Module.ctx.getUniformLocation(this.program, 'u_fogDensity');
+ this.hasFog = !!(this.fogColorLocation || this.fogEndLocation ||
+ this.fogScaleLocation || this.fogDensityLocation);
+ },
+
+ prepare: function() {
+ // Calculate the array buffer
+ var arrayBuffer;
+ if (!GL.currArrayBuffer) {
+ var start = GL.immediate.firstVertex*GL.immediate.stride;
+ var end = GL.immediate.lastVertex*GL.immediate.stride;
+ assert(end <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too much vertex data');
+ arrayBuffer = GL.immediate.tempVertexBuffers[GL.immediate.tempBufferIndexLookup[end]];
+ // TODO: consider using the last buffer we bound, if it was larger. downside is larger buffer, but we might avoid rebinding and preparing
+ } else {
+ arrayBuffer = GL.currArrayBuffer;
+ }
+
+ // If the array buffer is unchanged and the renderer as well, then we can avoid all the work here
+ // XXX We use some heuristics here, and this may not work in all cases. Try disabling this if you
+ // have odd glitches (by setting canSkip always to 0, or even cleaning up the renderer right
+ // after rendering)
+ var lastRenderer = GL.immediate.lastRenderer;
+ var canSkip = this == lastRenderer &&
+ arrayBuffer == GL.immediate.lastArrayBuffer &&
+ (GL.currProgram || this.program) == GL.immediate.lastProgram &&
+ !GL.immediate.matricesModified;
+ if (!canSkip && lastRenderer) lastRenderer.cleanup();
+ if (!GL.currArrayBuffer) {
+ // Bind the array buffer and upload data after cleaning up the previous renderer
+ if (arrayBuffer != GL.immediate.lastArrayBuffer) {
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, arrayBuffer);
+ }
+ Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, GL.immediate.vertexData.subarray(start >> 2, end >> 2));
+ }
+ if (canSkip) return;
+ GL.immediate.lastRenderer = this;
+ GL.immediate.lastArrayBuffer = arrayBuffer;
+ GL.immediate.lastProgram = GL.currProgram || this.program;
+ GL.immediate.matricesModified = false;
+
+ if (!GL.currProgram) {
+ Module.ctx.useProgram(this.program);
+ }
+
+ if (this.modelViewLocation) Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']);
+ if (this.projectionLocation) Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix['p']);
+
+ Module.ctx.vertexAttribPointer(this.positionLocation, positionSize, positionType, false,
+ stride, positionOffset);
+ Module.ctx.enableVertexAttribArray(this.positionLocation);
+ if (this.hasTextures) {
+ for (var i = 0; i < textureSizes.length; i++) {
+ if (textureSizes[i] && this.texCoordLocations[i] >= 0) {
+ Module.ctx.vertexAttribPointer(this.texCoordLocations[i], textureSizes[i], textureTypes[i], false,
+ stride, textureOffsets[i]);
+ Module.ctx.enableVertexAttribArray(this.texCoordLocations[i]);
+ }
+ }
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ if (this.textureMatrixLocations[i]) { // XXX might we need this even without the condition we are currently in?
+ Module.ctx.uniformMatrix4fv(this.textureMatrixLocations[i], false, GL.immediate.matrix['t' + i]);
+ }
+ }
+ }
+ if (this.hasColorAttrib) {
+ Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true,
+ stride, colorOffset);
+ Module.ctx.enableVertexAttribArray(this.colorLocation);
+ Module.ctx.uniform1i(this.hasColorAttribLocation, 1);
+ } else if (this.hasColorUniform) {
+ Module.ctx.uniform1i(this.hasColorAttribLocation, 0);
+ Module.ctx.uniform4fv(this.colorUniformLocation, GL.immediate.clientColor);
+ }
+ if (this.hasNormal) {
+ Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true,
+ stride, normalOffset);
+ Module.ctx.enableVertexAttribArray(this.normalLocation);
+ }
+ if (!useCurrProgram) { // otherwise, the user program will set the sampler2D binding and uniform itself
+ var texture = Module.ctx.getParameter(Module.ctx.TEXTURE_BINDING_2D);
+ Module.ctx.activeTexture(Module.ctx.TEXTURE0);
+ Module.ctx.bindTexture(Module.ctx.TEXTURE_2D, texture);
+ Module.ctx.uniform1i(this.textureLocation, 0);
+ }
+ if (this.hasFog) {
+ if (this.fogColorLocation) Module.ctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor);
+ if (this.fogEndLocation) Module.ctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd);
+ if (this.fogScaleLocation) Module.ctx.uniform1f(this.fogScaleLocation, 1/(GLEmulation.fogEnd - GLEmulation.fogStart));
+ if (this.fogDensityLocation) Module.ctx.uniform1f(this.fogDensityLocation, GLEmulation.fogDensity);
+ }
+ },
+
+ cleanup: function() {
+ Module.ctx.disableVertexAttribArray(this.positionLocation);
+ if (this.hasTextures) {
+ for (var i = 0; i < textureSizes.length; i++) {
+ if (textureSizes[i] && this.texCoordLocations[i] >= 0) {
+ Module.ctx.disableVertexAttribArray(this.texCoordLocations[i]);
+ }
+ }
+ }
+ if (this.hasColorAttrib) {
+ Module.ctx.disableVertexAttribArray(this.colorLocation);
+ }
+ if (this.hasNormal) {
+ Module.ctx.disableVertexAttribArray(this.normalLocation);
+ }
+ if (!GL.currProgram) {
+ Module.ctx.useProgram(null);
+ }
+ if (!GL.currArrayBuffer) {
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
+ }
+
+ GL.immediate.lastRenderer = null;
+ GL.immediate.lastArrayBuffer = null;
+ GL.immediate.lastProgram = null;
+ GL.immediate.matricesModified = true;
+ }
+ };
+ ret.init();
+ return ret;
},
-
- onMouseButtonDown: function(event){
- GLUT.lastX = event['clientX'];
- GLUT.lastY = event['clientY'];
-
- if(GLUT.mouseFunc){
- FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY);
+
+ // Main functions
+ initted: false,
+ init: function() {
+ Module.printErr('WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports');
+ GL.immediate.initted = true;
+
+ if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case
+
+ this.matrixStack['m'] = [];
+ this.matrixStack['p'] = [];
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ this.matrixStack['t' + i] = [];
}
+
+ this.ATTRIBUTE_BY_NAME['V'] = 0;
+ this.ATTRIBUTE_BY_NAME['N'] = 1;
+ this.ATTRIBUTE_BY_NAME['C'] = 2;
+ this.ATTRIBUTE_BY_NAME['T0'] = 3;
+ this.ATTRIBUTE_BY_NAME['T1'] = 4;
+ this.ATTRIBUTE_BY_NAME['T2'] = 5;
+ this.ATTRIBUTE_BY_NAME['T3'] = 6;
+ this.ATTRIBUTE_BY_NAME['T4'] = 7;
+ this.ATTRIBUTE_BY_NAME['T5'] = 8;
+ this.ATTRIBUTE_BY_NAME['T6'] = 9;
+
+ // Initialize matrix library
+
+ GL.immediate.matrix['m'] = GL.immediate.matrix.lib.mat4.create();
+ GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix['m']);
+ GL.immediate.matrix['p'] = GL.immediate.matrix.lib.mat4.create();
+ GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix['p']);
+ for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) {
+ GL.immediate.matrix['t' + i] = GL.immediate.matrix.lib.mat4.create();
+ }
+
+ // Buffers for data
+ this.tempData = new Float32Array(this.MAX_TEMP_BUFFER_SIZE >> 2);
+ this.indexData = new Uint16Array(this.MAX_TEMP_BUFFER_SIZE >> 1);
+
+ this.vertexDataU8 = new Uint8Array(this.tempData.buffer);
+
+ this.generateTempBuffers();
+
+ this.clientColor = new Float32Array([1, 1, 1, 1]);
+
+ // Replace some functions with immediate-mode aware versions. If there are no client
+ // attributes enabled, and we use webgl-friendly modes (no GL_QUADS), then no need
+ // for emulation
+ _glDrawArrays = function(mode, first, count) {
+ if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6) {
+ Module.ctx.drawArrays(mode, first, count);
+ return;
+ }
+ GL.immediate.prepareClientAttributes(count, false);
+ GL.immediate.mode = mode;
+ if (!GL.currArrayBuffer) {
+ GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', 'GL.immediate.vertexPointer + (first+count)*GL.immediate.stride') }}}; // XXX assuming float
+ GL.immediate.firstVertex = first;
+ GL.immediate.lastVertex = first + count;
+ }
+ GL.immediate.flush(null, first);
+ GL.immediate.mode = 0;
+ };
+
+ _glDrawElements = function(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements
+ if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) {
+ Module.ctx.drawElements(mode, count, type, indices);
+ return;
+ }
+ if (!GL.currElementArrayBuffer) {
+ assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now
+ }
+ GL.immediate.prepareClientAttributes(count, false);
+ GL.immediate.mode = mode;
+ if (!GL.currArrayBuffer) {
+ GL.immediate.firstVertex = end ? start : TOTAL_MEMORY; // if we don't know the start, set an invalid value and we will calculate it later from the indices
+ GL.immediate.lastVertex = end ? end+1 : 0;
+ GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', '(end ? GL.immediate.vertexPointer + (end+1)*GL.immediate.stride : TOTAL_MEMORY)') }}}; // XXX assuming float
+ }
+ GL.immediate.flush(count, 0, indices);
+ GL.immediate.mode = 0;
+ };
},
-
- onMouseButtonUp: function(event){
- GLUT.lastX = event['clientX'];
- GLUT.lastY = event['clientY'];
- if(GLUT.mouseFunc) {
- FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY);
+ // Prepares and analyzes client attributes.
+ // Modifies liveClientAttributes, stride, vertexPointer, vertexCounter
+ // count: number of elements we will draw
+ // beginEnd: whether we are drawing the results of a begin/end block
+ prepareClientAttributes: function(count, beginEnd) {
+ // If no client attributes were modified since we were last called, do nothing. Note that this
+ // does not work for glBegin/End, where we generate renderer components dynamically and then
+ // disable them ourselves, but it does help with glDrawElements/Arrays.
+ if (!this.modifiedClientAttributes) {
+ return;
+ }
+ this.modifiedClientAttributes = false;
+
+ var stride = 0, start;
+ var attributes = GL.immediate.liveClientAttributes;
+ attributes.length = 0;
+ for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) {
+ if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]);
+ }
+ attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) });
+ start = attributes[0].pointer;
+ for (var i = 0; i < attributes.length; i++) {
+ var attribute = attributes[i];
+ if (!attribute) break;
+#if ASSERTIONS
+ assert(stride == 0 || stride == attribute.stride); // must all be in the same buffer
+#endif
+ if (attribute.stride) stride = attribute.stride;
+ }
+
+ var bytes = 0;
+ for (var i = 0; i < attributes.length; i++) {
+ var attribute = attributes[i];
+ if (!attribute) break;
+ attribute.offset = attribute.pointer - start;
+ if (attribute.offset > bytes) { // ensure we start where we should
+ assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment
+ bytes += attribute.offset - bytes;
+ }
+ bytes += attribute.size * GL.immediate.byteSizeByType[attribute.type];
+ if (bytes % 4 != 0) bytes += 4 - (bytes % 4); // XXX assuming 4-alignment
+ }
+ assert(stride == 0 || bytes <= stride);
+ if (bytes < stride) { // ensure the size is that of the stride
+ bytes = stride;
+ }
+ GL.immediate.stride = bytes;
+
+ if (!beginEnd) {
+ bytes *= count;
+ if (!GL.currArrayBuffer) {
+ GL.immediate.vertexPointer = start;
+ }
+ GL.immediate.vertexCounter = bytes / 4; // XXX assuming float
}
},
+
+ flush: function(numProvidedIndexes, startIndex, ptr) {
+ startIndex = startIndex || 0;
+ ptr = ptr || 0;
+
+ var renderer = this.getRenderer();
+
+ // Generate index data in a format suitable for GLES 2.0/WebGL
+ var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; // XXX assuming float
+ assert(numVertexes % 1 == 0);
+
+ var emulatedElementArrayBuffer = false;
+ var numIndexes = 0;
+ if (numProvidedIndexes) {
+ numIndexes = numProvidedIndexes;
+ if (!GL.currArrayBuffer && GL.immediate.firstVertex > GL.immediate.lastVertex) {
+ // Figure out the first and last vertex from the index data
+ assert(!GL.currElementArrayBuffer); // If we are going to upload array buffer data, we need to find which range to
+ // upload based on the indices. If they are in a buffer on the GPU, that is very
+ // inconvenient! So if you do not have an array buffer, you should also not have
+ // an element array buffer. But best is to use both buffers!
+ for (var i = 0; i < numProvidedIndexes; i++) {
+ var currIndex = {{{ makeGetValue('ptr', 'i*2', 'i16', null, 1) }}};
+ GL.immediate.firstVertex = Math.min(GL.immediate.firstVertex, currIndex);
+ GL.immediate.lastVertex = Math.max(GL.immediate.lastVertex, currIndex+1);
+ }
+ }
+ if (!GL.currElementArrayBuffer) {
+ // If no element array buffer is bound, then indices is a literal pointer to clientside data
+ assert(numProvidedIndexes << 1 <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)');
+ var indexBuffer = GL.immediate.tempIndexBuffers[GL.immediate.tempBufferIndexLookup[numProvidedIndexes << 1]];
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}});
+ ptr = 0;
+ emulatedElementArrayBuffer = true;
+ }
+ } else if (GL.immediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes
+ if (GL.immediate.mode != 7) throw 'unsupported immediate mode ' + GL.immediate.mode; // GL_QUADS
+ // GL.immediate.firstVertex is the first vertex we want. Quad indexes are in the pattern
+ // 0 1 2, 0 2 3, 4 5 6, 4 6 7, so we need to look at index firstVertex * 1.5 to see it.
+ // Then since indexes are 2 bytes each, that means 3
+ assert(GL.immediate.firstVertex % 4 == 0);
+ ptr = GL.immediate.firstVertex*3;
+ var numQuads = numVertexes / 4;
+ numIndexes = numQuads * 6; // 0 1 2, 0 2 3 pattern
+ assert(ptr + (numIndexes << 1) <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)');
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempQuadIndexBuffer);
+ emulatedElementArrayBuffer = true;
+ }
+
+ renderer.prepare();
+
+ if (numIndexes) {
+ Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, ptr);
+ } else {
+ Module.ctx.drawArrays(GL.immediate.mode, startIndex, numVertexes);
+ }
+
+ if (emulatedElementArrayBuffer) {
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.buffers[GL.currElementArrayBuffer] || null);
+ }
+ }
+ },
+
+ $GLImmediateSetup__deps: ['$GLImmediate', function() { return 'GL.immediate = GLImmediate; GL.immediate.matrix.lib = ' + read('gl-matrix.js') + ';\n' }],
+ $GLImmediateSetup: {},
+
+ glBegin__deps: ['$GLImmediateSetup'],
+ glBegin: function(mode) {
+ GL.immediate.mode = mode;
+ GL.immediate.vertexCounter = 0;
+ GL.immediate.rendererComponents = {}; // XXX
+ GL.immediate.rendererComponentPointer = 0;
+ GL.immediate.vertexData = GL.immediate.tempData;
+ },
+
+ glEnd: function() {
+ GL.immediate.prepareClientAttributes(GL.immediate.rendererComponents['V'], true);
+ GL.immediate.firstVertex = 0;
+ GL.immediate.lastVertex = GL.immediate.vertexCounter / (GL.immediate.stride >> 2);
+ GL.immediate.flush();
+ GL.immediate.disableBeginEndClientAttributes();
+ GL.immediate.mode = 0;
},
- glutInit__deps: ['$GLUT'],
- glutInit: function(argcp, argv) {
- // Ignore arguments
- GLUT.initTime = Date.now();
- window.addEventListener("keydown", GLUT.onKeydown, true);
- window.addEventListener("keyup", GLUT.onKeyup, true);
- window.addEventListener("mousemove", GLUT.onMousemove, true);
- window.addEventListener("mousedown", GLUT.onMouseButtonDown, true);
- window.addEventListener("mouseup", GLUT.onMouseButtonUp, true);
+ glVertex3f: function(x, y, z) {
+#if ASSERTIONS
+ assert(GL.immediate.mode); // must be in begin/end
+#endif
+ GL.immediate.vertexData[GL.immediate.vertexCounter++] = x;
+ GL.immediate.vertexData[GL.immediate.vertexCounter++] = y;
+ GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0;
+#if ASSERTIONS
+ assert(GL.immediate.vertexCounter << 2 < GL.immediate.MAX_TEMP_BUFFER_SIZE);
+#endif
+ GL.immediate.addRendererComponent('V', 3, Module.ctx.FLOAT);
},
+ glVertex2f: 'glVertex3f',
- glutInitWindowSize: function(width, height) {
- Module['canvas'].width = width;
- Module['canvas'].height = height;
+ glVertex3fv__deps: ['glVertex3f'],
+ glVertex3fv: function(p) {
+ _glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}});
},
- glutGet: function(type) {
- switch (type) {
- case 700: /* GLUT_ELAPSED_TIME */
- var now = Date.now();
- return now - GLUT.initTime;
+ glTexCoord2i: function(u, v) {
+#if ASSERTIONS
+ assert(GL.immediate.mode); // must be in begin/end
+#endif
+ GL.immediate.vertexData[GL.immediate.vertexCounter++] = u;
+ GL.immediate.vertexData[GL.immediate.vertexCounter++] = v;
+ GL.immediate.addRendererComponent('T0', 2, Module.ctx.FLOAT);
+ },
+ glTexCoord2f: 'glTexCoord2i',
+
+ glTexCoord2fv__deps: ['glTexCoord2f'],
+ glTexCoord2fv: function(v) {
+ _glTexCoord2f({{{ makeGetValue('v', '0', 'float') }}}, {{{ makeGetValue('v', '4', 'float') }}});
+ },
+
+ glColor4f: function(r, g, b, a) {
+ // TODO: make ub the default, not f, save a few mathops
+ if (GL.immediate.mode) {
+ var start = GL.immediate.vertexCounter << 2;
+ GL.immediate.vertexDataU8[start + 0] = r * 255;
+ GL.immediate.vertexDataU8[start + 1] = g * 255;
+ GL.immediate.vertexDataU8[start + 2] = b * 255;
+ GL.immediate.vertexDataU8[start + 3] = a * 255;
+ GL.immediate.vertexCounter++;
+ GL.immediate.addRendererComponent('C', 4, Module.ctx.UNSIGNED_BYTE);
+ } else {
+ GL.immediate.clientColor[0] = r;
+ GL.immediate.clientColor[1] = g;
+ GL.immediate.clientColor[2] = b;
+ GL.immediate.clientColor[3] = a;
+ }
+ },
+ glColor4d: 'glColor4f',
+ glColor4ub__deps: ['glColor4f'],
+ glColor4ub: function(r, g, b, a) {
+ _glColor4f((r&255)/255, (g&255)/255, (b&255)/255, (a&255)/255);
+ },
+ glColor4us__deps: ['glColor4f'],
+ glColor4us: function(r, g, b, a) {
+ _glColor4f((r&65535)/65535, (g&65535)/65535, (b&65535)/65535, (a&65535)/65535);
+ },
+ glColor4ui__deps: ['glColor4f'],
+ glColor4ui: function(r, g, b, a) {
+ _glColor4f((r>>>0)/4294967295, (g>>>0)/4294967295, (b>>>0)/4294967295, (a>>>0)/4294967295);
+ },
+ glColor3f__deps: ['glColor4f'],
+ glColor3f: function(r, g, b) {
+ _glColor4f(r, g, b, 1);
+ },
+ glColor3d: 'glColor3f',
+ glColor3ub__deps: ['glColor4ub'],
+ glColor3ub: function(r, g, b) {
+ _glColor4ub(r, g, b, 255);
+ },
+ glColor3us__deps: ['glColor4us'],
+ glColor3us: function(r, g, b) {
+ _glColor4us(r, g, b, 65535);
+ },
+ glColor3ui__deps: ['glColor4ui'],
+ glColor3ui: function(r, g, b) {
+ _glColor4ui(r, g, b, 4294967295);
+ },
+
+ glColor3ubv__deps: ['glColor3ub'],
+ glColor3ubv: function(p) {
+ _glColor3ub({{{ makeGetValue('p', '0', 'i8') }}}, {{{ makeGetValue('p', '1', 'i8') }}}, {{{ makeGetValue('p', '2', 'i8') }}});
+ },
+ glColor3usv__deps: ['glColor3us'],
+ glColor3usv: function(p) {
+ _glColor3us({{{ makeGetValue('p', '0', 'i16') }}}, {{{ makeGetValue('p', '2', 'i16') }}}, {{{ makeGetValue('p', '4', 'i16') }}});
+ },
+ glColor3uiv__deps: ['glColor3ui'],
+ glColor3uiv: function(p) {
+ _glColor3ui({{{ makeGetValue('p', '0', 'i32') }}}, {{{ makeGetValue('p', '4', 'i32') }}}, {{{ makeGetValue('p', '8', 'i32') }}});
+ },
+ glColor3fv__deps: ['glColor3f'],
+ glColor3fv: function(p) {
+ _glColor3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}});
+ },
+ glColor4fv__deps: ['glColor4f'],
+ glColor4fv: function(p) {
+ _glColor4f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}}, {{{ makeGetValue('p', '12', 'float') }}});
+ },
+
+ glFogf: function(pname, param) { // partial support, TODO
+ switch(pname) {
+ case 0x0B63: // GL_FOG_START
+ GLEmulation.fogStart = param; break;
+ case 0x0B64: // GL_FOG_END
+ GLEmulation.fogEnd = param; break;
+ case 0x0B62: // GL_FOG_DENSITY
+ GLEmulation.fogDensity = param; break;
+ case 0x0B65: // GL_FOG_MODE
+ switch (param) {
+ case 0x0801: // GL_EXP2
+ case 0x2601: // GL_LINEAR
+ GLEmulation.fogMode = param; break;
+ default: // default to GL_EXP
+ GLEmulation.fogMode = 0x0800 /* GL_EXP */; break;
+ }
+ break;
+ }
+ },
+ glFogi__deps: ['glFogf'],
+ glFogi: function(pname, param) {
+ return _glFogf(pname, param);
+ },
+ glFogfv__deps: ['glFogf'],
+ glFogfv: function(pname, param) { // partial support, TODO
+ switch(pname) {
+ case 0x0B66: // GL_FOG_COLOR
+ GLEmulation.fogColor[0] = {{{ makeGetValue('param', '0', 'float') }}};
+ GLEmulation.fogColor[1] = {{{ makeGetValue('param', '4', 'float') }}};
+ GLEmulation.fogColor[2] = {{{ makeGetValue('param', '8', 'float') }}};
+ GLEmulation.fogColor[3] = {{{ makeGetValue('param', '12', 'float') }}};
+ break;
+ case 0x0B63: // GL_FOG_START
+ case 0x0B64: // GL_FOG_END
+ _glFogf(pname, {{{ makeGetValue('param', '0', 'float') }}}); break;
+ }
+ },
+ glFogiv__deps: ['glFogf'],
+ glFogiv: function(pname, param) {
+ switch(pname) {
+ case 0x0B66: // GL_FOG_COLOR
+ GLEmulation.fogColor[0] = ({{{ makeGetValue('param', '0', 'i32') }}}/2147483647)/2.0+0.5;
+ GLEmulation.fogColor[1] = ({{{ makeGetValue('param', '4', 'i32') }}}/2147483647)/2.0+0.5;
+ GLEmulation.fogColor[2] = ({{{ makeGetValue('param', '8', 'i32') }}}/2147483647)/2.0+0.5;
+ GLEmulation.fogColor[3] = ({{{ makeGetValue('param', '12', 'i32') }}}/2147483647)/2.0+0.5;
+ break;
default:
- throw "glutGet(" + type + ") not implemented yet";
+ _glFogf(pname, {{{ makeGetValue('param', '0', 'i32') }}}); break;
}
},
+ glFogx: 'glFogi',
+ glFogxv: 'glFogiv',
+
+ glPolygonMode: function(){}, // TODO
+
+ glAlphaFunc: function(){}, // TODO
+
+ glNormal3f: function(){}, // TODO
- glutDisplayFunc: function(func) {
- var RAF = window['setTimeout'];
- if (window['requestAnimationFrame']) {
- RAF = window['requestAnimationFrame'];
- } else if (window['mozRequestAnimationFrame']) {
- RAF = window['mozRequestAnimationFrame'];
- } else if (window['webkitRequestAnimationFrame']) {
- RAF = window['webkitRequestAnimationFrame'];
- } else if (window['msRequestAnimationFrame']) {
- RAF = window['msRequestAnimationFrame'];
+ // Additional non-GLES rendering calls
+
+ glDrawRangeElements: function(mode, start, end, count, type, indices) {
+ _glDrawElements(mode, count, type, indices, start, end);
+ },
+
+ // ClientState/gl*Pointer
+
+ glEnableClientState: function(cap, disable) {
+ var attrib;
+ switch(cap) {
+ case 0x8078: // GL_TEXTURE_COORD_ARRAY
+ attrib = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; break;
+ case 0x8074: // GL_VERTEX_ARRAY
+ attrib = GL.immediate.VERTEX; break;
+ case 0x8075: // GL_NORMAL_ARRAY
+ attrib = GL.immediate.NORMAL; break;
+ case 0x8076: // GL_COLOR_ARRAY
+ attrib = GL.immediate.COLOR; break;
+ default:
+ throw 'unhandled clientstate: ' + cap;
}
- RAF.apply(window, [function() {
- if (GLUT.reshapeFunc) {
- FUNCTION_TABLE[GLUT.reshapeFunc](Module['canvas'].width,
- Module['canvas'].height);
- }
- if (GLUT.idleFunc) {
- FUNCTION_TABLE[GLUT.idleFunc]();
- }
- FUNCTION_TABLE[func]();
- _glutDisplayFunc(func);
- }]);
+ if (disable && GL.immediate.enabledClientAttributes[attrib]) {
+ GL.immediate.enabledClientAttributes[attrib] = false;
+ GL.immediate.totalEnabledClientAttributes--;
+ } else if (!disable && !GL.immediate.enabledClientAttributes[attrib]) {
+ GL.immediate.enabledClientAttributes[attrib] = true;
+ GL.immediate.totalEnabledClientAttributes++;
+ }
+ GL.immediate.modifiedClientAttributes = true;
+ },
+ glDisableClientState: function(cap) {
+ _glEnableClientState(cap, 1);
},
- glutIdleFunc: function(func) {
- GLUT.idleFunc = func;
+ glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation
+ glVertexPointer: function(size, type, stride, pointer) {
+ GL.immediate.setClientAttribute('V', size, type, stride, pointer);
},
-
- glutKeyboardFunc: function(func) {
- GLUT.keyboardFunc = func;
+ glTexCoordPointer: function(size, type, stride, pointer) {
+ GL.immediate.setClientAttribute('T' + GL.immediate.clientActiveTexture, size, type, stride, pointer);
},
-
- glutKeyboardUpFunc: function(func) {
- GLUT.keyboardUpFunc = func;
+ glNormalPointer: function(type, stride, pointer) {
+ GL.immediate.setClientAttribute('N', 3, type, stride, pointer);
+ },
+ glColorPointer: function(size, type, stride, pointer) {
+ GL.immediate.setClientAttribute('C', size, type, stride, pointer);
},
- glutSpecialFunc: function(func) {
- GLUT.specialFunc = func;
+ glClientActiveTexture: function(texture) {
+ GL.immediate.clientActiveTexture = texture - 0x84C0; // GL_TEXTURE0
},
- glutSpecialUpFunc: function(func) {
- GLUT.specialUpFunc = func;
+ // OpenGL Immediate Mode matrix routines.
+ // Note that in the future we might make these available only in certain modes.
+ glMatrixMode__deps: ['$GL', '$GLImmediateSetup', '$GLEmulation'], // emulation is not strictly needed, this is a workaround
+ glMatrixMode: function(mode) {
+ if (mode == 0x1700 /* GL_MODELVIEW */) {
+ GL.immediate.currentMatrix = 'm';
+ } else if (mode == 0x1701 /* GL_PROJECTION */) {
+ GL.immediate.currentMatrix = 'p';
+ } else if (mode == 0x1702) { // GL_TEXTURE
+ GL.immediate.currentMatrix = 't' + GL.immediate.clientActiveTexture;
+ } else {
+ throw "Wrong mode " + mode + " passed to glMatrixMode";
+ }
},
- glutReshapeFunc: function(func) {
- GLUT.reshapeFunc = func;
+ glPushMatrix: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrixStack[GL.immediate.currentMatrix].push(
+ Array.prototype.slice.call(GL.immediate.matrix[GL.immediate.currentMatrix]));
},
-
- glutPassiveMotionFunc: function(func) {
- GLUT.passiveMotionFunc = func;
+
+ glPopMatrix: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix[GL.immediate.currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop();
},
-
- glutMouseFunc: function(func) {
- GLUT.mouseFunc = func;
+
+ glLoadIdentity__deps: ['$GL', '$GLImmediateSetup'],
+ glLoadIdentity: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[GL.immediate.currentMatrix]);
},
- glutCreateWindow: function(name) {
-#if USE_TYPED_ARRAYS
- try {
- var ctx = Module.canvas.getContext('experimental-webgl');
- if (!ctx) throw 'Could not create canvas :(';
- Module.ctx = ctx;
- // Set the background of the canvas to black, because glut gives us a
- // window which has a black background by default.
- Module.canvas.style.backgroundColor = "black";
- } catch (e) {
- Module.print('(canvas not available)');
- }
-#else
- Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
+ glLoadMatrixd: function(matrix) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]);
+ },
+
+ glLoadMatrixf: function(matrix) {
+#if GL_DEBUG
+ if (GL.debug) Module.printErr('glLoadMatrixf receiving: ' + Array.prototype.slice.call(HEAPF32.subarray(matrix >> 2, (matrix >> 2) + 16)));
#endif
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]);
+ },
+
+ glLoadTransposeMatrixd: function(matrix) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]);
+ GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]);
+ },
+
+ glLoadTransposeMatrixf: function(matrix) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]);
+ GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]);
+ },
+
+ glMultMatrixd: function(matrix) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix],
+ {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}});
+ },
+
+ glMultMatrixf: function(matrix) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix],
+ {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}});
+ },
+
+ glMultTransposeMatrixd: function(matrix) {
+ GL.immediate.matricesModified = true;
+ var colMajor = GL.immediate.matrix.lib.mat4.create();
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, colMajor);
+ GL.immediate.matrix.lib.mat4.transpose(colMajor);
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor);
+ },
+
+ glMultTransposeMatrixf: function(matrix) {
+ GL.immediate.matricesModified = true;
+ var colMajor = GL.immediate.matrix.lib.mat4.create();
+ GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, colMajor);
+ GL.immediate.matrix.lib.mat4.transpose(colMajor);
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor);
+ },
+
+ glFrustum: function(left, right, bottom, top_, nearVal, farVal) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix],
+ GL.immediate.matrix.lib.mat4.frustum(left, right, bottom, top_, nearVal, farVal));
+ },
+
+ glOrtho: function(left, right, bottom, top_, nearVal, farVal) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix],
+ GL.immediate.matrix.lib.mat4.ortho(left, right, bottom, top_, nearVal, farVal));
+ },
+ glOrthof: 'glOrtho',
+
+ glScaled: function(x, y, z) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.scale(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]);
+ },
+ glScalef: 'glScaled',
+
+ glTranslated: function(x, y, z) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.translate(GL.immediate.matrix[GL.immediate.currentMatrix], [x, y, z]);
},
+ glTranslatef: 'glTranslated',
- glutInitDisplayMode: function(mode) {},
- glutMainLoop: function() {},
- glutSwapBuffers: function() {},
- glutPostRedisplay: function() {},
+ glRotated: function(angle, x, y, z) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.rotate(GL.immediate.matrix[GL.immediate.currentMatrix], angle*Math.PI/180, [x, y, z]);
+ },
+ glRotatef: 'glRotated',
+
+ // GLU
+
+ gluPerspective: function(fov, aspect, near, far) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix],
+ GL.immediate.matrix.lib.mat4.perspective(fov, aspect, near, far, GL.immediate.currentMatrix));
+ },
+
+ gluLookAt: function(ex, ey, ez, cx, cy, cz, ux, uy, uz) {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.lookAt(GL.immediate.matrix[GL.immediate.currentMatrix], [ex, ey, ez],
+ [cx, cy, cz], [ux, uy, uz]);
+ },
+
+ gluProject: function(objX, objY, objZ, model, proj, view, winX, winY, winZ) {
+ // The algorithm for this functions comes from Mesa
+
+ var inVec = new Float32Array(4);
+ var outVec = new Float32Array(4);
+ GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'model', 'model+16*8') }}},
+ [objX, objY, objZ, 1.0], outVec);
+ GL.immediate.matrix.lib.mat4.multiplyVec4({{{ makeHEAPView('F64', 'proj', 'proj+16*8') }}},
+ outVec, inVec);
+ if (inVec[3] == 0.0) {
+ return 0 /* GL_FALSE */;
+ }
+ inVec[0] /= inVec[3];
+ inVec[1] /= inVec[3];
+ inVec[2] /= inVec[3];
+ // Map x, y and z to range 0-1 */
+ inVec[0] = inVec[0] * 0.5 + 0.5;
+ inVec[1] = inVec[1] * 0.5 + 0.5;
+ inVec[2] = inVec[2] * 0.5 + 0.5;
+ // Map x, y to viewport
+ inVec[0] = inVec[0] * {{{ makeGetValue('view', '2*4', 'i32') }}} + {{{ makeGetValue('view', '0*4', 'i32') }}};
+ inVec[1] = inVec[1] * {{{ makeGetValue('view', '3*4', 'i32') }}} + {{{ makeGetValue('view', '1*4', 'i32') }}};
+
+ {{{ makeSetValue('winX', '0', 'inVec[0]', 'double') }}};
+ {{{ makeSetValue('winY', '0', 'inVec[1]', 'double') }}};
+ {{{ makeSetValue('winZ', '0', 'inVec[2]', 'double') }}};
+
+ return 1 /* GL_TRUE */;
+ },
+
+ gluUnProject: function(winX, winY, winZ, model, proj, view, objX, objY, objZ) {
+ var result = GL.immediate.matrix.lib.mat4.unproject([winX, winY, winZ],
+ {{{ makeHEAPView('F64', 'model', 'model+16*8') }}},
+ {{{ makeHEAPView('F64', 'proj', 'proj+16*8') }}},
+ {{{ makeHEAPView('32', 'view', 'view+4*4') }}});
+
+ if (result === null) {
+ return 0 /* GL_FALSE */;
+ }
+
+ {{{ makeSetValue('objX', '0', 'result[0]', 'double') }}};
+ {{{ makeSetValue('objY', '0', 'result[1]', 'double') }}};
+ {{{ makeSetValue('objZ', '0', 'result[2]', 'double') }}};
+
+ return 1 /* GL_TRUE */;
+ }
};
+// Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name
+[[0, 'shadeModel getError* finish flush'],
+ [1, 'clearDepth clearDepth[f] depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask checkFramebufferStatus* generateMipmap activeTexture blendEquation sampleCoverage isEnabled*'],
+ [2, 'blendFunc blendEquationSeparate depthRange depthRange[f] stencilMaskSeparate hint polygonOffset'],
+ [3, 'texParameteri texParameterf drawArrays vertexAttrib2f stencilFunc stencilOp'],
+ [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage blendFuncSeparate blendColor stencilFuncSeparate stencilOpSeparate'],
+ [5, 'vertexAttrib4f'],
+ [6, 'vertexAttribPointer'],
+ [8, 'copyTexImage2D copyTexSubImage2D']].forEach(function(data) {
+ var num = data[0];
+ var names = data[1];
+ var args = range(num).map(function(i) { return 'x' + i }).join(', ');
+ var plainStub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })';
+ var returnStub = '(function(' + args + ') { ' + (num > 0 ? 'return Module.ctx.NAME(' + args + ')' : '') + ' })';
+ names.split(' ').forEach(function(name) {
+ var stub = plainStub;
+ if (name[name.length-1] == '*') {
+ name = name.substr(0, name.length-1);
+ stub = returnStub;
+ }
+ var cName = name;
+ if (name.indexOf('[') >= 0) {
+ cName = name.replace('[', '').replace(']', '');
+ name = cName.substr(0, cName.length-1);
+ }
+ var cName = 'gl' + cName[0].toUpperCase() + cName.substr(1);
+ assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName);
+ LibraryGL[cName] = eval(stub.replace('NAME', name));
+ });
+});
+
+autoAddDeps(LibraryGL, '$GL');
+
+// Emulation requires everything else, potentially
+LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.slice(0);
+for (var item in LibraryGL) {
+ if (item != '$GLEmulation' && item.substr(-6) != '__deps' && item.substr(-9) != '__postset' && item.substr(0, 2) == 'gl') {
+ LibraryGL.$GLEmulation__deps.push(item);
+ }
+}
+
mergeInto(LibraryManager.library, LibraryGL);
-mergeInto(LibraryManager.library, LibraryGLUT);
diff --git a/src/library_glut.js b/src/library_glut.js
new file mode 100644
index 00000000..d33f8436
--- /dev/null
+++ b/src/library_glut.js
@@ -0,0 +1,438 @@
+
+var LibraryGLUT = {
+ $GLUT: {
+ initTime: null,
+ idleFunc: null,
+ displayFunc: null,
+ keyboardFunc: null,
+ keyboardUpFunc: null,
+ specialFunc: null,
+ specialUpFunc: null,
+ reshapeFunc: null,
+ motionFunc: null,
+ passiveMotionFunc: null,
+ mouseFunc: null,
+ lastX: 0,
+ lastY: 0,
+ buttons: 0,
+ modifiers: 0,
+ initWindowWidth: 256,
+ initWindowHeight: 256,
+ // Set when going fullscreen
+ windowX: 0,
+ windowY: 0,
+ windowWidth: 0,
+ windowHeight: 0,
+
+ savePosition: function(event) {
+ /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */
+ GLUT.lastX = event['clientX'] - Module['canvas'].offsetLeft;
+ GLUT.lastY = event['clientY'] - Module['canvas'].offsetTop;
+ },
+
+ saveModifiers: function(event) {
+ GLUT.modifiers = 0;
+ if (event['shiftKey'])
+ GLUT.modifiers += 1; /* GLUT_ACTIVE_SHIFT */
+ if (event['ctrlKey'])
+ GLUT.modifiers += 2; /* GLUT_ACTIVE_CTRL */
+ if (event['altKey'])
+ GLUT.modifiers += 4; /* GLUT_ACTIVE_ALT */
+ },
+
+ onMousemove: function(event) {
+ /* Send motion event only if the motion changed, prevents
+ * spamming our app with uncessary callback call. It does happen in
+ * Chrome on Windows.
+ */
+ var newX = event['clientX'] - Module['canvas'].offsetLeft;
+ var newY = event['clientY'] - Module['canvas'].offsetTop;
+ if (newX == GLUT.lastX && newY == GLUT.lastY)
+ return;
+
+ GLUT.savePosition(event);
+ if (GLUT.buttons == 0 && event.target == Module["canvas"] && GLUT.passiveMotionFunc) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.passiveMotionFunc](GLUT.lastX, GLUT.lastY);
+ } else if (GLUT.buttons != 0 && GLUT.motionFunc) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.motionFunc](GLUT.lastX, GLUT.lastY);
+ }
+ },
+
+ getSpecialKey: function(keycode) {
+ var key = null;
+ switch (keycode) {
+ case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break;
+ case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break;
+ case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break;
+ case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break;
+ case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break;
+ case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break;
+ case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break;
+ case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break;
+ case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break;
+ case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break;
+ case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break;
+ case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break;
+ case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break;
+ case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break;
+ case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break;
+ case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break;
+ case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break;
+ case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break;
+ case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break;
+ case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break;
+ case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break;
+
+ case 16 /*DOM_VK_SHIFT*/:
+ case 0x05 /*DOM_VK_LEFT_SHIFT*/:
+ key = 112 /* GLUT_KEY_SHIFT_L */;
+ break;
+ case 0x06 /*DOM_VK_RIGHT_SHIFT*/:
+ key = 113 /* GLUT_KEY_SHIFT_R */;
+ break;
+
+ case 17 /*DOM_VK_CONTROL*/:
+ case 0x03 /*DOM_VK_LEFT_CONTROL*/:
+ key = 114 /* GLUT_KEY_CONTROL_L */;
+ break;
+ case 0x04 /*DOM_VK_RIGHT_CONTROL*/:
+ key = 115 /* GLUT_KEY_CONTROL_R */;
+ break;
+
+ case 18 /*DOM_VK_ALT*/:
+ case 0x02 /*DOM_VK_LEFT_ALT*/:
+ key = 116 /* GLUT_KEY_ALT_L */;
+ break;
+ case 0x01 /*DOM_VK_RIGHT_ALT*/:
+ key = 117 /* GLUT_KEY_ALT_R */;
+ break;
+ };
+ return key;
+ },
+
+ getASCIIKey: function(event) {
+ if (event['ctrlKey'] || event['altKey'] || event['metaKey']) return null;
+
+ var keycode = event['keyCode'];
+
+ /* The exact list is soooo hard to find in a canonical place! */
+
+ if (48 <= keycode && keycode <= 57)
+ return keycode; // numeric TODO handle shift?
+ if (65 <= keycode && keycode <= 90)
+ return event['shiftKey'] ? keycode : keycode + 32;
+ if (106 <= keycode && keycode <= 111)
+ return keycode - 106 + 42; // *,+-./ TODO handle shift?
+
+ switch (keycode) {
+ case 27: // escape
+ case 32: // space
+ case 61: // equal
+ return keycode;
+ }
+
+ var s = event['shiftKey'];
+ switch (keycode) {
+ case 186: return s ? 58 : 59; // colon / semi-colon
+ case 187: return s ? 43 : 61; // add / equal (these two may be wrong)
+ case 188: return s ? 60 : 44; // less-than / comma
+ case 189: return s ? 95 : 45; // dash
+ case 190: return s ? 62 : 46; // greater-than / period
+ case 191: return s ? 63 : 47; // forward slash
+ case 219: return s ? 123 : 91; // open bracket
+ case 220: return s ? 124 : 47; // back slash
+ case 221: return s ? 125 : 93; // close braket
+ case 222: return s ? 34 : 39; // single quote
+ }
+
+ return null;
+ },
+
+ onKeydown: function(event) {
+ if (GLUT.specialFunc || GLUT.keyboardFunc) {
+ var key = GLUT.getSpecialKey(event['keyCode']);
+ if (key !== null) {
+ if( GLUT.specialFunc ) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.specialFunc](key, GLUT.lastX, GLUT.lastY);
+ }
+ }
+ else
+ {
+ key = GLUT.getASCIIKey(event);
+ if( key !== null && GLUT.keyboardFunc ) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY);
+ }
+ }
+ }
+ },
+
+ onKeyup: function(event) {
+ if (GLUT.specialUpFunc || GLUT.keyboardUpFunc) {
+ var key = GLUT.getSpecialKey(event['keyCode']);
+ if (key !== null) {
+ if(GLUT.specialUpFunc) {
+ event.preventDefault ();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.specialUpFunc](key, GLUT.lastX, GLUT.lastY);
+ }
+ }
+ else
+ {
+ key = GLUT.getASCIIKey(event);
+ if( key !== null && GLUT.keyboardUpFunc ) {
+ event.preventDefault ();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.keyboardUpFunc](key, GLUT.lastX, GLUT.lastY);
+ }
+ }
+ }
+ },
+
+ onMouseButtonDown: function(event){
+ GLUT.savePosition(event);
+ GLUT.buttons |= (1 << event['button']);
+
+ if(event.target == Module["canvas"] && GLUT.mouseFunc){
+ try {
+ event.target.setCapture();
+ } catch (e) {}
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY);
+ }
+ },
+
+ onMouseButtonUp: function(event){
+ GLUT.savePosition(event);
+ GLUT.buttons &= ~(1 << event['button']);
+
+ if(GLUT.mouseFunc) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY);
+ }
+ },
+
+ // TODO add fullscreen API ala:
+ // http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
+ onFullScreenEventChange: function(event){
+ var width;
+ var height;
+ if (document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
+ width = screen["width"];
+ height = screen["height"];
+ } else {
+ width = GLUT.windowWidth;
+ height = GLUT.windowHeight;
+ // TODO set position
+ document.removeEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true);
+ document.removeEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true);
+ document.removeEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true);
+ }
+ Module['canvas'].width = width;
+ Module['canvas'].height = height;
+ /* Can't call _glutReshapeWindow as that requests cancelling fullscreen. */
+ if (GLUT.reshapeFunc) {
+ // console.log("GLUT.reshapeFunc (from FS): " + width + ", " + height);
+ FUNCTION_TABLE[GLUT.reshapeFunc](width, height);
+ }
+ _glutPostRedisplay();
+ },
+
+ requestFullScreen: function() {
+ var RFS = Module["canvas"]['requestFullscreen'] ||
+ Module["canvas"]['requestFullScreen'] ||
+ Module["canvas"]['mozRequestFullScreen'] ||
+ Module["canvas"]['webkitRequestFullScreen'] ||
+ (function() {});
+ RFS.apply(Module["canvas"], []);
+ },
+
+ cancelFullScreen: function() {
+ var CFS = document['exitFullscreen'] ||
+ document['cancelFullScreen'] ||
+ document['mozCancelFullScreen'] ||
+ document['webkitCancelFullScreen'] ||
+ (function() {});
+ CFS.apply(document, []);
+ }
+ },
+
+ glutGetModifiers: function() { return GLUT.modifiers; },
+
+ glutInit: function(argcp, argv) {
+ // Ignore arguments
+ GLUT.initTime = Date.now();
+ },
+
+ glutInitWindowSize: function(width, height) {
+ Module['canvas'].width = GLUT.initWindowWidth = width;
+ Module['canvas'].height = GLUT.initWindowHeight = height;
+ },
+
+ glutInitWindowPosition: function(x, y) {
+ // Ignore for now
+ },
+
+ glutGet: function(type) {
+ switch (type) {
+ case 100: /* GLUT_WINDOW_X */
+ return 0; /* TODO */
+ case 101: /* GLUT_WINDOW_Y */
+ return 0; /* TODO */
+ case 102: /* GLUT_WINDOW_WIDTH */
+ return Module['canvas'].width;
+ case 103: /* GLUT_WINDOW_HEIGHT */
+ return Module['canvas'].height;
+ case 500: /* GLUT_INIT_WINDOW_X */
+ return 0; /* TODO */
+ case 501: /* GLUT_INIT_WINDOW_Y */
+ return 0; /* TODO */
+ case 502: /* GLUT_INIT_WINDOW_WIDTH */
+ return GLUT.initWindowWidth;
+ case 503: /* GLUT_INIT_WINDOW_HEIGHT */
+ return GLUT.initWindowHeight;
+ case 700: /* GLUT_ELAPSED_TIME */
+ var now = Date.now();
+ return now - GLUT.initTime;
+
+ default:
+ throw "glutGet(" + type + ") not implemented yet";
+ }
+ },
+
+ glutIdleFunc: function(func) {
+ var callback = function() {
+ if (GLUT.idleFunc) {
+ FUNCTION_TABLE[GLUT.idleFunc]();
+ window.setTimeout(callback, 0);
+ }
+ }
+ if (!GLUT.idleFunc)
+ window.setTimeout(callback, 0);
+ GLUT.idleFunc = func;
+ },
+
+ glutTimerFunc: function(msec, func, value) {
+ window.setTimeout(function() { FUNCTION_TABLE[func](value); }, msec);
+ },
+
+ glutDisplayFunc: function(func) {
+ GLUT.displayFunc = func;
+ },
+
+ glutKeyboardFunc: function(func) {
+ GLUT.keyboardFunc = func;
+ },
+
+ glutKeyboardUpFunc: function(func) {
+ GLUT.keyboardUpFunc = func;
+ },
+
+ glutSpecialFunc: function(func) {
+ GLUT.specialFunc = func;
+ },
+
+ glutSpecialUpFunc: function(func) {
+ GLUT.specialUpFunc = func;
+ },
+
+ glutReshapeFunc: function(func) {
+ GLUT.reshapeFunc = func;
+ },
+
+ glutMotionFunc: function(func) {
+ GLUT.motionFunc = func;
+ },
+
+ glutPassiveMotionFunc: function(func) {
+ GLUT.passiveMotionFunc = func;
+ },
+
+ glutMouseFunc: function(func) {
+ GLUT.mouseFunc = func;
+ },
+
+ glutCreateWindow__deps: ['$Browser'],
+ glutCreateWindow: function(name) {
+ Module.ctx = Browser.createContext(Module['canvas'], true, true);
+ return 1;
+ },
+
+ glutReshapeWindow__deps: ['$GLUT', 'glutPostRedisplay'],
+ glutReshapeWindow: function(width, height) {
+ GLUT.cancelFullScreen();
+ // console.log("glutReshapeWindow: " + width + ", " + height);
+ Module['canvas'].width = width;
+ Module['canvas'].height = height;
+ if (GLUT.reshapeFunc) {
+ // console.log("GLUT.reshapeFunc: " + width + ", " + height);
+ FUNCTION_TABLE[GLUT.reshapeFunc](width, height);
+ }
+ _glutPostRedisplay();
+ },
+
+ glutPositionWindow__deps: ['$GLUT', 'glutPostRedisplay'],
+ glutPositionWindow: function(x, y) {
+ GLUT.cancelFullScreen();
+ /* TODO */
+ _glutPostRedisplay();
+ },
+
+ glutFullScreen__deps: ['$GLUT', 'glutPostRedisplay'],
+ glutFullScreen: function() {
+ GLUT.windowX = 0; // TODO
+ GLUT.windowY = 0; // TODO
+ GLUT.windowWidth = Module['canvas'].width;
+ GLUT.windowHeight = Module['canvas'].height;
+ document.addEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true);
+ document.addEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true);
+ document.addEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true);
+ GLUT.requestFullScreen();
+ },
+
+ glutInitDisplayMode: function(mode) {},
+ glutSwapBuffers: function() {},
+
+ glutPostRedisplay: function() {
+ if (GLUT.displayFunc) {
+ Browser.requestAnimationFrame(FUNCTION_TABLE[GLUT.displayFunc]);
+ }
+ },
+
+ glutMainLoop__deps: ['$GLUT', 'glutReshapeWindow', 'glutPostRedisplay'],
+ glutMainLoop: function() {
+
+ window.addEventListener("keydown", GLUT.onKeydown, true);
+ window.addEventListener("keyup", GLUT.onKeyup, true);
+ window.addEventListener("mousemove", GLUT.onMousemove, true);
+ window.addEventListener("mousedown", GLUT.onMouseButtonDown, true);
+ window.addEventListener("mouseup", GLUT.onMouseButtonUp, true);
+
+ __ATEXIT__.push({ func: function() {
+ window.removeEventListener("keydown", GLUT.onKeydown, true);
+ window.removeEventListener("keyup", GLUT.onKeyup, true);
+ window.removeEventListener("mousemove", GLUT.onMousemove, true);
+ window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true);
+ window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true);
+ Module["canvas"].width = Module["canvas"].height = 1;
+ } });
+
+ _glutReshapeWindow(Module['canvas'].width, Module['canvas'].height);
+ _glutPostRedisplay();
+ throw 'GLUT mainloop called, simulating infinite loop by throwing so we get right into the JS event loop';
+ },
+
+};
+
+autoAddDeps(LibraryGLUT, '$GLUT');
+mergeInto(LibraryManager.library, LibraryGLUT);
+
diff --git a/src/library_sdl.js b/src/library_sdl.js
index cd86fb93..73848502 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1,124 +1,187 @@
//"use strict";
-// To use emscripten's SDL library here, you need to define
-// Module.canvas.
-//
-// More specifically, our SDL implementation will look for
-// Module.canvas. You should fill it using something like
-//
-// function onLoad() {
-// // Pass canvas and context to the generated code
-// Module.canvas = document.getElementById('canvas');
-// }
-//
-// Note that this must be called during onload, since you will
-// only be able to access the canvas element in the page after
-// it loads. You will likely also want to disable running by
-// default, with something like
-//
-// var Module = {
-// noInitialRun: true
-// };
-//
-// which is defined BEFORE you load the compiled code.
-
-// The test_emcc test in the tests/runner.py will test this
-// in its last phase, where it generates HTML. You can see
-// a concrete example there. The HTML source is in src/shell.html.
-// Here is a more comprehensive example:
-
-/*
-<html>
- <head>
- <title>Demo</title>
- <script type='text/javascript'>
- var Module = {
- noInitialRun: true
- };
+// See browser tests for examples (tests/runner.py, search for sdl_). Run with
+// python tests/runner.py browser
- // implement print
- var print = function(text) {
- var element = document.getElementById('output')
- element.innerHTML = text.replace('\n', '<br>', 'g') + element.innerHTML;
- }
- </script>
- <script src='doom.ccsimple.js' type='text/javascript'></script>
- <script type='text/javascript'>
- function onLoad() {
- // Pass canvas and context to the generated code, and do the actual run() here
- Module.canvas = document.getElementById('canvas');
- Module.run();
- }
- </script>
- <body onload='onLoad()' style='background-color: black; color: white'>
- <center>
- <canvas id='canvas' width='320' height='200'></canvas>
- </center>
- <div id='output'></div>
- </body>
-</html>
-*/
-
-// Other stuff to take into account:
-//
-// * Make sure alpha values are proper in your input. If they are all 0, everything will be transparent!
-//
-// * Your code should not write a 32-bit value and expect that to set an RGBA pixel.
-// The reason is that that data will be read as 8-bit values, and according to the
-// load-store consistency assumption, it should be written that way (see docs/paper.pdf).
-// Instead, do something like *ptr++ = R; *ptr++ = G; *ptr++ = B;
-//
-// * A normal C++ main loop with SDL_Delay will not work in JavaScript - there is no way
-// to wait for a short time without locking up the web page entirely. The simplest
-// solution here is to have a singleIteration() function which is a single loop
-// iteration, and from JS to do something like setInterval(_singleIteration, 1/30)
-//
-// * SDL_Quit does nothing.
-
-mergeInto(LibraryManager.library, {
- //$SDL__deps: ['$Browser'],
+var LibrarySDL = {
+ $SDL__deps: ['$FS', '$Browser'],
$SDL: {
defaults: {
width: 320,
height: 200,
- copyScreenOnLock: false
+ copyOnLock: true
},
+ version: null,
+
surfaces: {},
events: [],
+ fonts: [null],
+
+ audios: [null],
+ music: {
+ audio: null,
+ volume: 1.0
+ },
+ mixerFrequency: 22050,
+ mixerFormat: 0x8010, // AUDIO_S16LSB
+ mixerNumChannels: 2,
+ mixerChunkSize: 1024,
+
+ keyboardState: null,
+ shiftKey: false,
+ ctrlKey: false,
+ altKey: false,
+
+ startTime: null,
+ mouseX: 0,
+ mouseY: 0,
+ buttonState: 0,
+ DOMButtons: [0, 0, 0],
+
+ DOMEventToSDLEvent: {},
+
+ keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h
+ 38: 1106, // up arrow
+ 40: 1105, // down arrow
+ 37: 1104, // left arrow
+ 39: 1103, // right arrow
+
+ 33: 1099, // pagedup
+ 34: 1102, // pagedown
- keyCodes: {
- 38: 273, // up arrow
- 40: 274, // down arrow
- 37: 276, // left arrow
- 39: 275, // right arrow
17: 305, // control (right, or left)
18: 308, // alt
- 109: 45, // minus
- 16: 304 // shift
+ 173: 45, // minus
+ 16: 304, // shift
+
+ 96: 88 | 1<<10, // keypad 0
+ 97: 89 | 1<<10, // keypad 1
+ 98: 90 | 1<<10, // keypad 2
+ 99: 91 | 1<<10, // keypad 3
+ 100: 92 | 1<<10, // keypad 4
+ 101: 93 | 1<<10, // keypad 5
+ 102: 94 | 1<<10, // keypad 6
+ 103: 95 | 1<<10, // keypad 7
+ 104: 96 | 1<<10, // keypad 8
+ 105: 97 | 1<<10, // keypad 9
+
+ 112: 58 | 1<<10, // F1
+ 113: 59 | 1<<10, // F2
+ 114: 60 | 1<<10, // F3
+ 115: 61 | 1<<10, // F4
+ 116: 62 | 1<<10, // F5
+ 117: 63 | 1<<10, // F6
+ 118: 64 | 1<<10, // F7
+ 119: 65 | 1<<10, // F8
+ 120: 66 | 1<<10, // F9
+ 121: 67 | 1<<10, // F10
+ 122: 68 | 1<<10, // F11
+ 123: 69 | 1<<10, // F12
+
+ 188: 44, // comma
+ 190: 46, // period
+ 191: 47, // slash (/)
+ 192: 96, // backtick/backquote (`)
+ },
+
+ scanCodes: { // SDL keycode ==> SDL scancode. See SDL_scancode.h
+ 97: 4, // A
+ 98: 5,
+ 99: 6,
+ 100: 7,
+ 101: 8,
+ 102: 9,
+ 103: 10,
+ 104: 11,
+ 105: 12,
+ 106: 13,
+ 107: 14,
+ 108: 15,
+ 109: 16,
+ 110: 17,
+ 111: 18,
+ 112: 19,
+ 113: 20,
+ 114: 21,
+ 115: 22,
+ 116: 23,
+ 117: 24,
+ 118: 25,
+ 119: 26,
+ 120: 27,
+ 121: 28,
+ 122: 29, // Z
+ 44: 54, // comma
+ 46: 55, // period
+ 47: 56, // slash
+ 49: 30, // 1
+ 50: 31,
+ 51: 32,
+ 52: 33,
+ 53: 34,
+ 54: 35,
+ 55: 36,
+ 56: 37,
+ 57: 38, // 9
+ 48: 39, // 0
+ 13: 40, // return
+ 9: 43, // tab
+ 27: 41, // escape
+ 32: 44, // space
+ 92: 49, // backslash
+ 305: 224, // ctrl
+ 308: 226, // alt
},
structs: {
Rect: Runtime.generateStructInfo([
- ['i16', 'x'], ['i16', 'y'], ['i16', 'w'], ['i16', 'h'],
+ ['i32', 'x'], ['i32', 'y'], ['i32', 'w'], ['i32', 'h'],
]),
PixelFormat: Runtime.generateStructInfo([
+ ['i32', 'format'],
['void*', 'palette'], ['i8', 'BitsPerPixel'], ['i8', 'BytesPerPixel'],
+ ['i8', 'padding1'], ['i8', 'padding2'],
+ ['i32', 'Rmask'], ['i32', 'Gmask'], ['i32', 'Bmask'], ['i32', 'Amask'],
['i8', 'Rloss'], ['i8', 'Gloss'], ['i8', 'Bloss'], ['i8', 'Aloss'],
- ['i8', 'Rshift'], ['i8', 'Gshift'], ['i8', 'Bshift'], ['i8', 'Ashift'],
- ['i32', 'Rmask'], ['i32', 'Gmask'], ['i32', 'Bmask'], ['i32', 'Amask'] // Docs say i8, ./include/SDL_video.h says i32...
+ ['i8', 'Rshift'], ['i8', 'Gshift'], ['i8', 'Bshift'], ['i8', 'Ashift']
]),
KeyboardEvent: Runtime.generateStructInfo([
- ['i8', 'type'],
- ['i8', 'which'],
+ ['i32', 'type'],
+ ['i32', 'windowID'],
['i8', 'state'],
+ ['i8', 'repeat'],
+ ['i8', 'padding2'],
+ ['i8', 'padding3'],
['i32', 'keysym']
]),
keysym: Runtime.generateStructInfo([
- ['i8', 'scancode'],
+ ['i32', 'scancode'],
['i32', 'sym'],
- ['i32', 'mod'],
- ['i16', 'unicode']
+ ['i16', 'mod'],
+ ['i32', 'unicode']
+ ]),
+ MouseMotionEvent: Runtime.generateStructInfo([
+ ['i32', 'type'],
+ ['i32', 'windowID'],
+ ['i8', 'state'],
+ ['i8', 'padding1'],
+ ['i8', 'padding2'],
+ ['i8', 'padding3'],
+ ['i32', 'x'],
+ ['i32', 'y'],
+ ['i32', 'xrel'],
+ ['i32', 'yrel']
+ ]),
+ MouseButtonEvent: Runtime.generateStructInfo([
+ ['i32', 'type'],
+ ['i32', 'windowID'],
+ ['i8', 'button'],
+ ['i8', 'state'],
+ ['i8', 'padding1'],
+ ['i8', 'padding2'],
+ ['i32', 'x'],
+ ['i32', 'y']
]),
AudioSpec: Runtime.generateStructInfo([
['i32', 'freq'],
@@ -129,68 +192,143 @@ mergeInto(LibraryManager.library, {
['i32', 'size'],
['void*', 'callback'],
['void*', 'userdata']
+ ]),
+ version: Runtime.generateStructInfo([
+ ['i8', 'major'],
+ ['i8', 'minor'],
+ ['i8', 'patch']
])
},
- makeSurface: function(width, height, flags) {
+ loadRect: function(rect) {
+ return {
+ x: {{{ makeGetValue('rect + SDL.structs.Rect.x', '0', 'i32') }}},
+ y: {{{ makeGetValue('rect + SDL.structs.Rect.y', '0', 'i32') }}},
+ w: {{{ makeGetValue('rect + SDL.structs.Rect.w', '0', 'i32') }}},
+ h: {{{ makeGetValue('rect + SDL.structs.Rect.h', '0', 'i32') }}}
+ };
+ },
+
+ // Load SDL color into a CSS-style color specification
+ loadColorToCSSRGB: function(color) {
+ var rgba = {{{ makeGetValue('color', '0', 'i32') }}};
+ return 'rgb(' + (rgba&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba >> 16)&255) + ')';
+ },
+ loadColorToCSSRGBA: function(color) {
+ var rgba = {{{ makeGetValue('color', '0', 'i32') }}};
+ return 'rgba(' + (rgba&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba >> 16)&255) + ',' + (((rgba >> 24)&255)/255) + ')';
+ },
+
+ translateColorToCSSRGBA: function(rgba) {
+ return 'rgba(' + ((rgba >> 24)&255) + ',' + ((rgba >> 16)&255) + ',' + ((rgba >> 8)&255) + ',' + ((rgba&255)/255) + ')';
+ },
+
+ translateRGBAToCSSRGBA: function(r, g, b, a) {
+ return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')';
+ },
+
+ translateRGBAToColor: function(r, g, b, a) {
+ return (r << 24) + (g << 16) + (b << 8) + a;
+ },
+
+ makeSurface: function(width, height, flags, usePageCanvas, source, rmask, gmask, bmask, amask) {
+ flags = flags || 0;
var surf = _malloc(14*Runtime.QUANTUM_SIZE); // SDL_Surface has 14 fields of quantum size
- var buffer = _malloc(width*height*4);
+ var buffer = _malloc(width*height*4); // TODO: only allocate when locked the first time
var pixelFormat = _malloc(18*Runtime.QUANTUM_SIZE);
flags |= 1; // SDL_HWSURFACE - this tells SDL_MUSTLOCK that this needs to be locked
+ //surface with SDL_HWPALETTE flag is 8bpp surface (1 byte)
+ var is_SDL_HWPALETTE = flags & 0x00200000;
+ var bpp = is_SDL_HWPALETTE ? 1 : 4;
+
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*0', '0', 'flags', 'i32') }}} // SDL_Surface.flags
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*1', '0', 'pixelFormat', 'void*') }}} // SDL_Surface.format TODO
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*2', '0', 'width', 'i32') }}} // SDL_Surface.w
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*3', '0', 'height', 'i32') }}} // SDL_Surface.h
- {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*4', '0', 'width*4', 'i16') }}} // SDL_Surface.pitch, assuming RGBA for now,
+ {{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*4', '0', 'width * bpp', 'i32') }}} // SDL_Surface.pitch, assuming RGBA or indexed for now,
// since that is what ImageData gives us in browsers
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*5', '0', 'buffer', 'void*') }}} // SDL_Surface.pixels
{{{ makeSetValue('surf+Runtime.QUANTUM_SIZE*6', '0', '0', 'i32*') }}} // SDL_Surface.offset
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.format', '0', '-2042224636', 'i32') }}} // SDL_PIXELFORMAT_RGBA8888
{{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.palette', '0', '0', 'i32') }}} // TODO
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BitsPerPixel', '0', '32', 'i8') }}} // TODO
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BytesPerPixel', '0', '4', 'i8') }}} // TODO
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BitsPerPixel', '0', 'bpp * 8', 'i8') }}}
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.BytesPerPixel', '0', 'bpp', 'i8') }}}
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Rmask', '0', '0xff', 'i32') }}}
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Gmask', '0', '0xff', 'i32') }}}
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Bmask', '0', '0xff', 'i32') }}}
- {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Amask', '0', '0xff', 'i32') }}}
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Rmask', '0', 'rmask || 0x000000ff', 'i32') }}}
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Gmask', '0', 'gmask || 0x0000ff00', 'i32') }}}
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Bmask', '0', 'bmask || 0x00ff0000', 'i32') }}}
+ {{{ makeSetValue('pixelFormat + SDL.structs.PixelFormat.Amask', '0', 'amask || 0xff000000', 'i32') }}}
// Decide if we want to use WebGL or not
var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL
-
+ var canvas;
+ if (!usePageCanvas) {
+ canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ } else {
+ canvas = Module['canvas'];
+ }
+ var ctx = Browser.createContext(canvas, useWebGL, usePageCanvas);
SDL.surfaces[surf] = {
width: width,
height: height,
- canvas: Module['canvas'],
- ctx: SDL.createContext(useWebGL),
+ canvas: canvas,
+ ctx: ctx,
surf: surf,
buffer: buffer,
pixelFormat: pixelFormat,
- alpha: 255
+ alpha: 255,
+ flags: flags,
+ locked: 0,
+ usePageCanvas: usePageCanvas,
+ source: source,
+
+ isFlagSet: function (flag) {
+ return flags & flag;
+ }
};
+
return surf;
},
- createContext: function(useWebGL) {
-#if !USE_TYPED_ARRAYS
- if (useWebGL) {
- Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
- return null;
+ // Copy data from the C++-accessible storage to the canvas backing
+ // for surface with HWPALETTE flag(8bpp depth)
+ copyIndexedColorData: function(surfData, rX, rY, rW, rH) {
+ // HWPALETTE works with palette
+ // setted by SDL_SetColors
+ if (!surfData.colors) {
+ return;
}
-#endif
- try {
- var ctx = Module.canvas.getContext(useWebGL ? 'experimental-webgl' : '2d');
- if (!ctx) throw 'Could not create canvas :(';
- if (useWebGL) {
- // Set the background of the WebGL canvas to black, because SDL gives us a
- // window which has a black background by default.
- Module.canvas.style.backgroundColor = "black";
+
+ var fullWidth = Module['canvas'].width;
+ var fullHeight = Module['canvas'].height;
+
+ var startX = rX || 0;
+ var startY = rY || 0;
+ var endX = (rW || (fullWidth - startX)) + startX;
+ var endY = (rH || (fullHeight - startY)) + startY;
+
+ var buffer = surfData.buffer;
+ var data = surfData.image.data;
+ var colors = surfData.colors;
+
+ for (var y = startY; y < endY; ++y) {
+ var indexBase = y * fullWidth;
+ var colorBase = indexBase * 4;
+ for (var x = startX; x < endX; ++x) {
+ // HWPALETTE have only 256 colors (not rgba)
+ var index = {{{ makeGetValue('buffer + indexBase + x', '0', 'i8', null, true) }}};
+ var color = colors[index] || [Math.floor(Math.random()*255),Math.floor(Math.random()*255),Math.floor(Math.random()*255)]; // XXX
+ var colorOffset = colorBase + x * 4;
+
+ data[colorOffset ] = color[0];
+ data[colorOffset +1] = color[1];
+ data[colorOffset +2] = color[2];
+ //unused: data[colorOffset +3] = color[3];
}
- return Module.ctx = ctx;
- } catch (e) {
- Module.print('(canvas not available)');
- return null;
}
},
@@ -198,61 +336,233 @@ mergeInto(LibraryManager.library, {
_free(SDL.surfaces[surf].buffer);
_free(SDL.surfaces[surf].pixelFormat);
_free(surf);
- delete SDL.surfaces[surf];
+ SDL.surfaces[surf] = null;
},
receiveEvent: function(event) {
switch(event.type) {
- case 'keydown': case 'keyup':
- //print('zz receive Event: ' + event.keyCode);
+ case 'mousemove':
+ // workaround for firefox bug 750111
+ event['movementX'] = event['mozMovementX'];
+ event['movementY'] = event['mozMovementY'];
+ // fall through
+ case 'keydown': case 'keyup': case 'mousedown': case 'mouseup': case 'DOMMouseScroll':
+ if (event.type == 'DOMMouseScroll') {
+ event = {
+ type: 'mousedown',
+ button: event.detail > 0 ? 4 : 3,
+ pageX: event.pageX,
+ pageY: event.pageY
+ };
+ } else if (event.type == 'mousedown') {
+ SDL.DOMButtons[event.button] = 1;
+ } else if (event.type == 'mouseup') {
+ if (!SDL.DOMButtons[event.button]) return false; // ignore extra ups, can happen if we leave the canvas while pressing down, then return,
+ // since we add a mouseup in that case
+ SDL.DOMButtons[event.button] = 0;
+ }
+
SDL.events.push(event);
+ if (SDL.events.length >= 10000) {
+ Module.printErr('SDL event queue full, dropping earliest event');
+ SDL.events.shift();
+ }
+ if ((event.keyCode >= 37 && event.keyCode <= 40) || // arrow keys
+ event.keyCode == 32 || // space
+ event.keyCode == 33 || event.keyCode == 34) { // page up/down
+ event.preventDefault();
+ }
+ break;
+ case 'mouseout':
+ // Un-press all pressed mouse buttons, because we might miss the release outside of the canvas
+ for (var i = 0; i < 3; i++) {
+ if (SDL.DOMButtons[i]) {
+ SDL.events.push({
+ type: 'mouseup',
+ button: i,
+ pageX: event.pageX,
+ pageY: event.pageY
+ });
+ SDL.DOMButtons[i] = 0;
+ }
+ }
+ break;
}
- //event.preventDefault();
return false;
},
-
+
makeCEvent: function(event, ptr) {
if (typeof event === 'number') {
// This is a pointer to a native C event that was SDL_PushEvent'ed
- _memcpy(ptr, event, SDL.structs.KeyboardEvent.__size__);
+ _memcpy(ptr, event, SDL.structs.KeyboardEvent.__size__); // XXX
return;
}
switch(event.type) {
- case 'keydown': case 'keyup':
+ case 'keydown': case 'keyup': {
var down = event.type === 'keydown';
- var key = SDL.keyCodes[event.keyCode] || event.keyCode;
+ //Module.print('Received key event: ' + event.keyCode);
+ var key = event.keyCode;
if (key >= 65 && key <= 90) {
- key = String.fromCharCode(key).toLowerCase().charCodeAt(0);
+ key += 32; // make lowercase for SDL
+ } else {
+ key = SDL.keyCodes[event.keyCode] || event.keyCode;
}
- //print('zz passing over Event: ' + key);
- {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'down ? 2 : 3', 'i8') }}}
- {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.which', '1', 'i8') }}}
+ var scan;
+ if (key >= 1024) {
+ scan = key - 1024;
+ } else {
+ scan = SDL.scanCodes[key] || key;
+ }
+ {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}
+ //{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.which', '1', 'i32') }}}
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.state', 'down ? 1 : 0', 'i8') }}}
+ {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.repeat', '0', 'i8') }}} // TODO
- {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'key', 'i8') }}}
+ {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'scan', 'i32') }}}
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.sym', 'key', 'i32') }}}
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', '0', 'i32') }}}
- //{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'key', 'i32') }}}
+ {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'key', 'i32') }}}
+
+ {{{ makeSetValue('SDL.keyboardState', 'SDL.keyCodes[event.keyCode] || event.keyCode', 'event.type == "keydown"', 'i8') }}};
+ SDL.shiftKey = event.shiftKey;
+ SDL.ctrlKey = event.ctrlKey;
+ SDL.altKey = event.altKey;
+
+ break;
+ }
+ case 'mousedown': case 'mouseup':
+ if (event.type == 'mousedown') {
+ // SDL_BUTTON(x) is defined as (1 << ((x)-1)). SDL buttons are 1-3,
+ // and DOM buttons are 0-2, so this means that the below formula is
+ // correct.
+ SDL.buttonState |= 1 << event.button;
+ } else if (event.type == 'mouseup') {
+ SDL.buttonState = 0;
+ }
+ // fall through
+ case 'mousemove': {
+ if (Browser.pointerLock) {
+ // When the pointer is locked, calculate the coordinates
+ // based on the movement of the mouse.
+ var movementX = Browser.getMovementX(event);
+ var movementY = Browser.getMovementY(event);
+ var x = SDL.mouseX + movementX;
+ var y = SDL.mouseY + movementY;
+ } else {
+ // Otherwise, calculate the movement based on the changes
+ // in the coordinates.
+ var x = event.pageX - Module["canvas"].offsetLeft;
+ var y = event.pageY - Module["canvas"].offsetTop;
+ var movementX = x - SDL.mouseX;
+ var movementY = y - SDL.mouseY;
+ }
+ if (event.type != 'mousemove') {
+ var down = event.type === 'mousedown';
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.button', 'event.button+1', 'i8') }}}; // DOM buttons are 0-2, SDL 1-3
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.state', 'down ? 1 : 0', 'i8') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.x', 'x', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseButtonEvent.y', 'y', 'i32') }}};
+ } else {
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.state', 'SDL.buttonState', 'i8') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.x', 'x', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.y', 'y', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'movementX', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'movementY', 'i32') }}};
+ }
+ SDL.mouseX = x;
+ SDL.mouseY = y;
break;
- case 'keypress': break // TODO
- default:
- throw 'Unhandled SDL event: ' + event.type;
+ }
+ default: throw 'Unhandled SDL event: ' + event.type;
+ }
+ },
+
+ estimateTextWidth: function(fontData, text) {
+ var h = fontData.size;
+ var fontString = h + 'px sans-serif';
+ // TODO: use temp context, not screen's, to avoid affecting its performance?
+ var tempCtx = SDL.surfaces[SDL.screen].ctx;
+ tempCtx.save();
+ tempCtx.font = fontString;
+ var ret = tempCtx.measureText(text).width | 0;
+ tempCtx.restore();
+ return ret;
+ },
+
+ // Sound
+
+ allocateChannels: function(num) { // called from Mix_AllocateChannels and init
+ if (SDL.numChannels && SDL.numChannels >= num) return;
+ SDL.numChannels = num;
+ SDL.channels = [];
+ for (var i = 0; i < num; i++) {
+ SDL.channels[i] = {
+ audio: null,
+ volume: 1.0
+ };
+ }
+ },
+
+ setGetVolume: function(info, volume) {
+ if (!info) return 0;
+ var ret = info.volume * 128; // MIX_MAX_VOLUME
+ if (volume != -1) {
+ info.volume = volume / 128;
+ if (info.audio) info.audio.volume = info.volume;
+ }
+ return ret;
+ },
+
+ // Debugging
+
+ debugSurface: function(surfData) {
+ console.log('dumping surface ' + [surfData.surf, surfData.source, surfData.width, surfData.height]);
+ var image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
+ var data = image.data;
+ var num = Math.min(surfData.width, surfData.height);
+ for (var i = 0; i < num; i++) {
+ console.log(' diagonal ' + i + ':' + [data[i*surfData.width*4 + i*4 + 0], data[i*surfData.width*4 + i*4 + 1], data[i*surfData.width*4 + i*4 + 2], data[i*surfData.width*4 + i*4 + 3]]);
}
}
},
- SDL_Init__deps: ['$SDL'],
+ SDL_Linked_Version: function() {
+ if (SDL.version === null) {
+ SDL.version = _malloc(SDL.structs.version.__size__);
+ {{{ makeSetValue('SDL.version + SDL.structs.version.major', '0', '1', 'i8') }}}
+ {{{ makeSetValue('SDL.version + SDL.structs.version.minor', '0', '3', 'i8') }}}
+ {{{ makeSetValue('SDL.version + SDL.structs.version.patch', '0', '0', 'i8') }}}
+ }
+ return SDL.version;
+ },
+
SDL_Init: function(what) {
SDL.startTime = Date.now();
- ['keydown', 'keyup', 'keypress'].forEach(function(event) {
+ ['keydown', 'keyup'].forEach(function(event) {
addEventListener(event, SDL.receiveEvent, true);
});
+ SDL.keyboardState = _malloc(0x10000);
+ _memset(SDL.keyboardState, 0, 0x10000);
+ // Initialize this structure carefully for closure
+ SDL.DOMEventToSDLEvent['keydown'] = 0x300 /* SDL_KEYDOWN */;
+ SDL.DOMEventToSDLEvent['keyup'] = 0x301 /* SDL_KEYUP */;
+ SDL.DOMEventToSDLEvent['mousedown'] = 0x401 /* SDL_MOUSEBUTTONDOWN */;
+ SDL.DOMEventToSDLEvent['mouseup'] = 0x402 /* SDL_MOUSEBUTTONUP */;
+ SDL.DOMEventToSDLEvent['mousemove'] = 0x400 /* SDL_MOUSEMOTION */;
return 0; // success
},
- SDL_WasInit: function() { return 0 }, // TODO
+ SDL_WasInit__deps: ['SDL_Init'],
+ SDL_WasInit: function() {
+ if (SDL.startTime === null) {
+ _SDL_Init();
+ }
+ return 1;
+ },
SDL_GetVideoInfo: function() {
// %struct.SDL_VideoInfo = type { i32, i32, %struct.SDL_PixelFormat*, i32, i32 } - 5 fields of quantum size
@@ -269,61 +579,146 @@ mergeInto(LibraryManager.library, {
return -1; // -1 == all modes are ok. TODO
},
- SDL_GL_SetAttribute: function(attr, value) {
- // TODO
+ SDL_VideoModeOK: function(width, height, depth, flags) {
+ // SDL_VideoModeOK returns 0 if the requested mode is not supported under any bit depth, or returns the
+ // bits-per-pixel of the closest available mode with the given width, height and requested surface flags
+ return depth; // all modes are ok.
+ },
+
+ SDL_VideoDriverName: function(buf, max_size) {
+ if (SDL.startTime === null) {
+ return 0; //return NULL
+ }
+ //driverName - emscripten_sdl_driver
+ var driverName = [101, 109, 115, 99, 114, 105, 112, 116, 101,
+ 110, 95, 115, 100, 108, 95, 100, 114, 105, 118, 101, 114];
+
+ var index = 0;
+ var size = driverName.length;
+
+ if (max_size <= size) {
+ size = max_size - 1; //-1 cause null-terminator
+ }
+
+ while (index < size) {
+ var value = driverName[index];
+ {{{ makeSetValue('buf', 'index', 'value', 'i8') }}};
+ index++;
+ }
+
+ {{{ makeSetValue('buf', 'index', '0', 'i8') }}};
+ return buf;
},
SDL_SetVideoMode: function(width, height, depth, flags) {
+ ['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mouseout'].forEach(function(event) {
+ Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
+ });
Module['canvas'].width = width;
Module['canvas'].height = height;
- return SDL.screen = SDL.makeSurface(width, height, flags);
+ return SDL.screen = SDL.makeSurface(width, height, flags, true, 'screen');
+ },
+
+ SDL_GetVideoSurface: function() {
+ return SDL.screen;
+ },
+
+ SDL_QuitSubSystem: function(flags) {
+ Module.print('SDL_QuitSubSystem called (and ignored)');
},
SDL_Quit: function() {
+ for (var i = 0; i < SDL.audios; i++) {
+ SDL.audios[i].pause();
+ }
Module.print('SDL_Quit called (and ignored)');
},
+ // Copy data from the canvas backing to a C++-accessible storage
SDL_LockSurface: function(surf) {
var surfData = SDL.surfaces[surf];
+
+ surfData.locked++;
+ if (surfData.locked > 1) return 0;
+
if (!surfData.image) {
surfData.image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
- var data = surfData.image.data;
- var num = data.length;
- for (var i = 0; i < num/4; i++) {
- data[i*4+3] = 255; // opacity, as canvases blend alpha
+ if (surf == SDL.screen) {
+ var data = surfData.image.data;
+ var num = data.length;
+ for (var i = 0; i < num/4; i++) {
+ data[i*4+3] = 255; // opacity, as canvases blend alpha
+ }
}
}
- if (SDL.defaults.copyScreenOnLock) {
+ if (SDL.defaults.copyOnLock) {
// Copy pixel data to somewhere accessible to 'C/C++'
+ if (surfData.isFlagSet(0x00200000 /* SDL_HWPALETTE */)) {
+ // If this is neaded then
+ // we should compact the data from 32bpp to 8bpp index.
+ // I think best way to implement this is use
+ // additional colorMap hash (color->index).
+ // Something like this:
+ //
+ // var size = surfData.width * surfData.height;
+ // var data = '';
+ // for (var i = 0; i<size; i++) {
+ // var color = SDL.translateRGBAToColor(
+ // surfData.image.data[i*4 ],
+ // surfData.image.data[i*4 +1],
+ // surfData.image.data[i*4 +2],
+ // 255);
+ // var index = surfData.colorMap[color];
+ // {{{ makeSetValue('surfData.buffer', 'i', 'index', 'i8') }}};
+ // }
+ throw 'CopyOnLock is not supported for SDL_LockSurface with SDL_HWPALETTE flag set' + new Error().stack;
+ } else {
+#if USE_TYPED_ARRAYS == 2
+ HEAPU8.set(surfData.image.data, surfData.buffer);
+#else
var num2 = surfData.image.data.length;
for (var i = 0; i < num2; i++) {
{{{ makeSetValue('surfData.buffer', 'i', 'surfData.image.data[i]', 'i8') }}};
}
+#endif
+ }
}
+
// Mark in C/C++-accessible SDL structure
// SDL_Surface has the following fields: Uint32 flags, SDL_PixelFormat *format; int w, h; Uint16 pitch; void *pixels; ...
// So we have fields all of the same size, and 5 of them before us.
// TODO: Use macros like in library.js
{{{ makeSetValue('surf', '5*Runtime.QUANTUM_SIZE', 'surfData.buffer', 'void*') }}};
+
+ return 0;
},
+ // Copy data from the C++-accessible storage to the canvas backing
SDL_UnlockSurface: function(surf) {
var surfData = SDL.surfaces[surf];
+
+ surfData.locked--;
+ if (surfData.locked > 0) return;
+
// Copy pixel data to image
- var num = surfData.image.data.length;
- if (!surfData.colors) {
+ if (surfData.isFlagSet(0x00200000 /* SDL_HWPALETTE */)) {
+ SDL.copyIndexedColorData(surfData);
+ } else if (!surfData.colors) {
+ var num = surfData.image.data.length;
var data = surfData.image.data;
var buffer = surfData.buffer;
#if USE_TYPED_ARRAYS == 2
assert(buffer % 4 == 0, 'Invalid buffer offset: ' + buffer);
var src = buffer >> 2;
var dst = 0;
+ var isScreen = surf == SDL.screen;
while (dst < num) {
+ // TODO: access underlying data buffer and write in 32-bit chunks or more
var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
- data[dst] = val & 0xff;
+ data[dst ] = val & 0xff;
data[dst+1] = (val >> 8) & 0xff;
data[dst+2] = (val >> 16) & 0xff;
- data[dst+3] = 0xff;
+ data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
src++;
dst += 4;
}
@@ -331,7 +726,7 @@ mergeInto(LibraryManager.library, {
for (var i = 0; i < num; i++) {
// We may need to correct signs here. Potentially you can hardcode a write of 255 to alpha, say, and
// the compiler may decide to write -1 in the llvm bitcode...
- data[i] = {{{ makeGetValue('buffer', 'i', 'i8') + (CORRECT_SIGNS ? '&0xff' : '') }}};
+ data[i] = {{{ makeGetValue('buffer', 'i', 'i8', null, true) }}};
if (i % 4 == 3) data[i] = 0xff;
}
#endif
@@ -345,7 +740,7 @@ mergeInto(LibraryManager.library, {
var base = y*width*4;
for (var x = 0; x < width; x++) {
// See comment above about signs
- var val = {{{ makeGetValue('s++', '0', 'i8') + (CORRECT_SIGNS ? '&0xff' : '') }}};
+ var val = {{{ makeGetValue('s++', '0', 'i8', null, true) }}};
var color = colors[val] || [Math.floor(Math.random()*255),Math.floor(Math.random()*255),Math.floor(Math.random()*255)]; // XXX
var start = base + x*4;
data[start] = color[0];
@@ -361,15 +756,20 @@ mergeInto(LibraryManager.library, {
},
SDL_Flip: function(surf) {
- // We actually do this in Unlock...
+ // We actually do this in Unlock, since the screen surface has as its canvas
+ // backing the page canvas element
},
SDL_UpdateRect: function(surf, x, y, w, h) {
// We actually do the whole screen in Unlock...
},
+ SDL_UpdateRects: function(surf, numrects, rects) {
+ // We actually do the whole screen in Unlock...
+ },
+
SDL_Delay: function(delay) {
- Module.print('SDL_Delay called! - potential infinite loop');
+ throw 'SDL_Delay called! Potential infinite loop, quitting. ' + new Error().stack;
},
SDL_WM_SetCaption: function(title, icon) {
@@ -381,6 +781,37 @@ mergeInto(LibraryManager.library, {
// TODO
},
+ SDL_GetKeyboardState: function() {
+ return SDL.keyboardState;
+ },
+
+ SDL_GetKeyState__deps: ['SDL_GetKeyboardState'],
+ SDL_GetKeyState: function() {
+ return _SDL_GetKeyboardState();
+ },
+
+ SDL_GetModState: function() {
+ // TODO: numlock, capslock, etc.
+ return (SDL.shiftKey ? 0x0001 & 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT
+ (SDL.ctrlKey ? 0x0040 & 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL
+ (SDL.altKey ? 0x0100 & 0x0200 : 0); // KMOD_LALT & KMOD_RALT
+ },
+
+ SDL_GetMouseState: function(x, y) {
+ if (x) {{{ makeSetValue('x', '0', 'SDL.mouseX', 'i32') }}};
+ if (y) {{{ makeSetValue('y', '0', 'SDL.mouseY', 'i32') }}};
+ return 0;
+ },
+
+ SDL_WarpMouse: function(x, y) {
+ return; // TODO: implement this in a non-buggy way. Need to keep relative mouse movements correct after calling this
+ SDL.events.push({
+ type: 'mousemove',
+ pageX: x + Module['canvas'].offsetLeft,
+ pageY: y + Module['canvas'].offsetTop
+ });
+ },
+
SDL_ShowCursor: function(toggle) {
// TODO
},
@@ -390,55 +821,74 @@ mergeInto(LibraryManager.library, {
},
SDL_CreateRGBSurface: function(flags, width, height, depth, rmask, gmask, bmask, amask) {
- return SDL.makeSurface(width, height, flags);
+ return SDL.makeSurface(width, height, flags, false, 'CreateRGBSurface', rmask, gmask, bmask, amask);
+ },
+
+ SDL_DisplayFormatAlpha: function(surf) {
+ var oldData = SDL.surfaces[surf];
+ var ret = SDL.makeSurface(oldData.width, oldData.height, oldData.flags, false, 'copy:' + oldData.source);
+ var newData = SDL.surfaces[ret];
+ //newData.ctx.putImageData(oldData.ctx.getImageData(0, 0, oldData.width, oldData.height), 0, 0);
+ newData.ctx.drawImage(oldData.canvas, 0, 0);
+ return ret;
},
SDL_FreeSurface: function(surf) {
- SDL.freeSurface(surf);
+ if (surf) SDL.freeSurface(surf);
},
SDL_UpperBlit: function(src, srcrect, dst, dstrect) {
- assert(!srcrect && !dstrect); // TODO
var srcData = SDL.surfaces[src];
var dstData = SDL.surfaces[dst];
- assert(srcData.width === dstData.width && srcData.height === dstData.height);
- {{{ makeCopyValues('dstData.buffer', 'srcData.buffer', 'srcData.width*srcData.height*4', 'i8', null, 1) }}}
+ var sr, dr;
+ if (srcrect) {
+ sr = SDL.loadRect(srcrect);
+ } else {
+ sr = { x: 0, y: 0, w: srcData.width, h: srcData.height };
+ }
+ if (dstrect) {
+ dr = SDL.loadRect(dstrect);
+ } else {
+ dr = { x: 0, y: 0, w: -1, h: -1 };
+ }
+ dstData.ctx.drawImage(srcData.canvas, sr.x, sr.y, sr.w, sr.h, dr.x, dr.y, sr.w, sr.h);
+ if (dst != SDL.screen) {
+ // XXX As in IMG_Load, for compatibility we write out |pixels|
+ console.log('WARNING: copying canvas data to memory for compatibility');
+ _SDL_LockSurface(dst);
+ dstData.locked--; // The surface is not actually locked in this hack
+ }
return 0;
},
SDL_FillRect: function(surf, rect, color) {
var surfData = SDL.surfaces[surf];
- var c1 = color & 0xff;
- var c2 = (color >> 8) & 0xff;
- var c3 = (color >> 16) & 0xff;
- var rx = {{{ makeGetValue('rect + SDL.structs.Rect.x', '0', 'i16') }}};
- var ry = {{{ makeGetValue('rect + SDL.structs.Rect.y', '0', 'i16') }}};
- var rw = {{{ makeGetValue('rect + SDL.structs.Rect.w', '0', 'i16') }}};
- var rh = {{{ makeGetValue('rect + SDL.structs.Rect.h', '0', 'i16') }}};
- var data = surfData.image.data;
- var width = surfData.width;
- for (var y = ry; y < ry + rh; y++) {
- var base = y*width*4;
- for (var x = rx; x < rx + rw; x++) {
- var start = x*4 + base;
- data[start] = c1;
- data[start+1] = c2;
- data[start+2] = c3;
- }
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+
+ if (surfData.isFlagSet(0x00200000 /* SDL_HWPALETTE */)) {
+ //in SDL_HWPALETTE color is index (0..255)
+ //so we should translate 1 byte value to
+ //32 bit canvas
+ color = surfData.colors[color] || [0, 0, 0, 255];
+ color = SDL.translateRGBAToColor(color[0], color[1], color[2], 255);
}
+
+ var r = rect ? SDL.loadRect(rect) : { x: 0, y: 0, w: surfData.width, h: surfData.height };
+ surfData.ctx.save();
+ surfData.ctx.fillStyle = SDL.translateColorToCSSRGBA(color);
+ surfData.ctx.fillRect(r.x, r.y, r.w, r.h);
+ surfData.ctx.restore();
},
SDL_BlitSurface__deps: ['SDL_UpperBlit'],
SDL_BlitSurface: function(src, srcrect, dst, dstrect) {
- return _SDL_Blit(src, srcrect, dst, dstrect);
+ return _SDL_UpperBlit(src, srcrect, dst, dstrect);
},
SDL_SetAlpha: function(surf, flag, alpha) {
SDL.surfaces[surf].alpha = alpha;
},
- SDL_GL_SwapBuffers: function() {},
-
SDL_GetTicks: function() {
return Math.floor(Date.now() - SDL.startTime);
},
@@ -453,44 +903,102 @@ mergeInto(LibraryManager.library, {
SDL_PushEvent: function(ptr) {
SDL.events.push(ptr); // XXX Should we copy it? Not clear from API
-
return 0;
},
+ SDL_PeepEvents: function(events, numEvents, action, from, to) {
+ switch(action) {
+ case 2: { // SDL_GETEVENT
+ assert(numEvents == 1);
+ var got = 0;
+ while (SDL.events.length > 0 && numEvents > 0) {
+ var type = SDL.DOMEventToSDLEvent[SDL.events[0].type];
+ if (type < from || type > to) break;
+ SDL.makeCEvent(SDL.events.shift(), events);
+ got++;
+ numEvents--;
+ // events += sizeof(..)
+ }
+ return got;
+ }
+ default: throw 'SDL_PeepEvents does not yet support that action: ' + action;
+ }
+ },
+
+ SDL_PumpEvents: function(){},
+
SDL_SetColors: function(surf, colors, firstColor, nColors) {
var surfData = SDL.surfaces[surf];
- surfData.colors = [];
- for (var i = firstColor; i < nColors; i++) {
- surfData.colors[i] = Array_copy(colors + i*4, colors + i*4 + 4);
+
+ // we should create colors array
+ // only once cause client code
+ // often wants to change portion
+ // of palette not all palette.
+ if (!surfData.colors) {
+ surfData.colors = [];
+ }
+
+ for (var i = firstColor; i < firstColor + nColors; i++) {
+ surfData.colors[i] = [
+ {{{ makeGetValue('colors', 'i*4', 'i8', null, true) }}},
+ {{{ makeGetValue('colors', 'i*4 + 1', 'i8', null, true) }}},
+ {{{ makeGetValue('colors', 'i*4 + 2', 'i8', null, true) }}},
+ {{{ makeGetValue('colors', 'i*4 + 3', 'i8', null, true) }}}
+ ];
}
+
return 1;
},
SDL_MapRGB: function(fmt, r, g, b) {
// Canvas screens are always RGBA
- return r + (g << 8) + (b << 16);
+ return 0xff+((b&0xff)<<8)+((g&0xff)<<16)+((r&0xff)<<24)
+ },
+
+ SDL_MapRGBA: function(fmt, r, g, b, a) {
+ // Canvas screens are always RGBA
+ return (a&0xff)+((b&0xff)<<8)+((g&0xff)<<16)+((r&0xff)<<24)
},
SDL_WM_GrabInput: function() {},
- SDL_ShowCursor: function() {},
// SDL_Image
+ IMG_Init: function(flags) {
+ return flags; // We support JPG, PNG, TIF because browsers do
+ },
+
+ IMG_Load__deps: ['SDL_LockSurface'],
IMG_Load: function(filename) {
- filename = Pointer_stringify(filename);
- var raw = preloadedImages[filename];
- assert(raw, 'Cannot find preloaded image ' + filename);
- var surf = SDL.makeSurface(raw.width, raw.height, 0);
- // XXX Extremely inefficient!
- for (var i = 0; i < raw.width*raw.height*4; i++) {
- {{{ makeSetValue('SDL.surfaces[surf].buffer', 'i', 'raw.data[i]', 'i8') }}}
+ filename = FS.standardizePath(Pointer_stringify(filename));
+ if (filename[0] == '/') {
+ // Convert the path to relative
+ filename = filename.substr(1);
}
+ var raw = Module["preloadedImages"][filename];
+ if (!raw) {
+ Runtime.warnOnce('Cannot find preloaded image ' + filename);
+ return 0;
+ }
+ var surf = SDL.makeSurface(raw.width, raw.height, 0, false, 'load:' + filename);
+ var surfData = SDL.surfaces[surf];
+ surfData.ctx.drawImage(raw, 0, 0, raw.width, raw.height, 0, 0, raw.width, raw.height);
+ // XXX SDL does not specify that loaded images must have available pixel data, in fact
+ // there are cases where you just want to blit them, so you just need the hardware
+ // accelerated version. However, code everywhere seems to assume that the pixels
+ // are in fact available, so we retrieve it here. This does add overhead though.
+ _SDL_LockSurface(surf);
+ surfData.locked--; // The surface is not actually locked in this hack
return surf;
},
+ SDL_LoadBMP: 'IMG_Load',
+ SDL_LoadBMP_RW: 'IMG_Load',
// SDL_Audio
SDL_OpenAudio: function(desired, obtained) {
+ SDL.allocateChannels(32);
+
// FIXME: Assumes 16-bit audio
assert(obtained === 0, 'Cannot return obtained SDL audio params');
@@ -559,29 +1067,319 @@ mergeInto(LibraryManager.library, {
SDL_CondWait: function() {},
SDL_DestroyCond: function() {},
-//SDL_CreateYUVOverlay
-//SDL_CreateThread, SDL_WaitThread etc
+ SDL_StartTextInput: function() {}, // TODO
+ SDL_StopTextInput: function() {}, // TODO
// SDL Mixer
- Mix_OpenAudio: function() { return 0 },
+ Mix_OpenAudio: function(frequency, format, channels, chunksize) {
+ SDL.allocateChannels(32);
+ SDL.mixerFrequency = frequency;
+ SDL.mixerFormat = format;
+ SDL.mixerNumChannels = channels;
+ SDL.mixerChunkSize = chunksize;
+ return 0;
+ },
+
+ Mix_CloseAudio: 'SDL_CloseAudio',
+
+ Mix_AllocateChannels: function(num) {
+ SDL.allocateChannels(num);
+ return num;
+ },
+
+ Mix_ChannelFinished: function(func) {
+ SDL.channelFinished = func;
+ },
+
+ Mix_Volume: function(channel, volume) {
+ if (channel == -1) {
+ for (var i = 0; i < SDL.numChannels-1; i++) {
+ _Mix_Volume(i, volume);
+ }
+ return _Mix_Volume(SDL.numChannels-1, volume);
+ }
+ return SDL.setGetVolume(SDL.channels[channel], volume);
+ },
+
+ Mix_SetPanning: function() {
+ return 0; // error
+ },
+
+ Mix_LoadWAV_RW: function(filename, freesrc) {
+ filename = FS.standardizePath(Pointer_stringify(filename));
+ var raw = Module["preloadedAudios"][filename];
+ if (!raw) {
+ Runtime.warnOnce('Cannot find preloaded audio ' + filename);
+ return 0;
+ }
+ var id = SDL.audios.length;
+ SDL.audios.push({
+ source: filename,
+ audio: raw
+ });
+ return id;
+ },
+
+ Mix_QuickLoad_RAW: function(mem, len) {
+ var audio = new Audio();
+ audio['mozSetup'](SDL.mixerNumChannels, SDL.mixerFrequency);
+ var numSamples = (len / (SDL.mixerNumChannels * 2)) | 0;
+ var buffer = new Float32Array(numSamples);
+ for (var i = 0; i < numSamples; ++i) {
+ buffer[i] = ({{{ makeGetValue('mem', 'i*2', 'i16', 0, 0) }}}) / 0x8000; // hardcoded 16-bit audio, signed (TODO: reSign if not ta2?)
+ }
+ var id = SDL.audios.length;
+ SDL.audios.push({
+ source: '',
+ audio: audio,
+ buffer: buffer
+ });
+ return id;
+ },
+
+ Mix_FreeChunk: function(id) {
+ SDL.audios[id] = null;
+ },
+
+ Mix_PlayChannel: function(channel, id, loops) {
+ // TODO: handle loops
+ var info = SDL.audios[id];
+ if (!info) return 0;
+ var audio = info.audio;
+ if (!audio) return 0;
+ if (channel == -1) {
+ channel = 0;
+ for (var i = 0; i < SDL.numChannels; i++) {
+ if (!SDL.channels[i].audio) {
+ channel = i;
+ break;
+ }
+ }
+ }
+ var channelInfo = SDL.channels[channel];
+ channelInfo.audio = audio = audio.cloneNode(true);
+ if (SDL.channelFinished) {
+ audio['onended'] = function() { // TODO: cache these
+ Runtime.getFuncWrapper(SDL.channelFinished)(channel);
+ }
+ }
+ if (info.buffer) {
+ audio['mozSetup'](SDL.mixerNumChannels, SDL.mixerFrequency);
+ audio["mozWriteAudio"](info.buffer);
+ } else {
+ audio.play();
+ }
+ audio.volume = channelInfo.volume;
+ return channel;
+ },
+ Mix_PlayChannelTimed: 'Mix_PlayChannel', // XXX ignore Timing
+
+ Mix_FadingChannel: function(channel) {
+ return 0; // MIX_NO_FADING, TODO
+ },
+
+ Mix_HaltChannel: function(channel) {
+ var info = SDL.channels[channel];
+ if (info.audio) {
+ info.audio.pause();
+ info.audio = null;
+ }
+ if (SDL.channelFinished) {
+ Runtime.getFuncWrapper(SDL.channelFinished)(channel);
+ }
+ return 0;
+ },
+ Mix_HookMusicFinished__deps: ['Mix_HaltMusic'],
Mix_HookMusicFinished: function(func) {
- SDL.hookMusicFinished = func; // TODO: use this
+ SDL.hookMusicFinished = func;
+ if (SDL.music.audio) { // ensure the callback will be called, if a music is already playing
+ SDL.music.audio['onended'] = _Mix_HaltMusic;
+ }
},
- Mix_VolumeMusic: function(func) {
- return 0; // TODO
+ Mix_VolumeMusic: function(volume) {
+ return SDL.setGetVolume(SDL.music, volume);
+ },
+
+ Mix_LoadMUS: 'Mix_LoadWAV_RW',
+
+ Mix_FreeMusic: 'Mix_FreeChunk',
+
+ Mix_PlayMusic__deps: ['Mix_HaltMusic'],
+ Mix_PlayMusic: function(id, loops) {
+ loops = Math.max(loops, 1);
+ var audio = SDL.audios[id].audio;
+ if (!audio) return 0;
+ audio.loop = loops != 1; // TODO: handle N loops for finite N
+ if (SDL.audios[id].buffer) {
+ audio["mozWriteAudio"](SDL.audios[id].buffer);
+ } else {
+ audio.play();
+ }
+ audio.volume = SDL.music.volume;
+ audio['onended'] = _Mix_HaltMusic; // will send callback
+ SDL.music.audio = audio;
+ return 0;
+ },
+
+ Mix_PauseMusic: function() {
+ var audio = SDL.music.audio;
+ if (!audio) return 0;
+ audio.pause();
+ return 0;
+ },
+
+ Mix_ResumeMusic: function() {
+ var audio = SDL.music.audio;
+ if (!audio) return 0;
+ audio.play();
+ return 0;
+ },
+
+ Mix_HaltMusic: function() {
+ var audio = SDL.music.audio;
+ if (!audio) return 0;
+ audio.src = audio.src; // rewind
+ audio.pause();
+ SDL.music.audio = null;
+ if (SDL.hookMusicFinished) {
+ FUNCTION_TABLE[SDL.hookMusicFinished]();
+ }
+ return 0;
+ },
+
+ Mix_FadeInMusicPos: 'Mix_PlayMusic', // XXX ignore fading in effect
+
+ Mix_FadeOutMusic: 'Mix_HaltMusic', // XXX ignore fading out effect
+
+ Mix_PlayingMusic: function() {
+ return (SDL.music.audio && !SDL.music.audio.paused) ? 1 : 0;
+ },
+
+ Mix_PausedMusic: function() {
+ return (SDL.music.audio && SDL.music.audio.paused) ? 1 : 0;
},
// SDL TTF
TTF_Init: function() { return 0 },
+ TTF_OpenFont: function(filename, size) {
+ filename = FS.standardizePath(Pointer_stringify(filename));
+ var id = SDL.fonts.length;
+ SDL.fonts.push({
+ name: filename, // but we don't actually do anything with it..
+ size: size
+ });
+ return id;
+ },
+
+ TTF_RenderText_Solid: function(font, text, color) {
+ // XXX the font and color are ignored
+ text = Pointer_stringify(text) || ' '; // if given an empty string, still return a valid surface
+ var fontData = SDL.fonts[font];
+ var w = SDL.estimateTextWidth(fontData, text);
+ var h = fontData.size;
+ var color = SDL.loadColorToCSSRGB(color); // XXX alpha breaks fonts?
+ var fontString = h + 'px sans-serif';
+ var surf = SDL.makeSurface(w, h, 0, false, 'text:' + text); // bogus numbers..
+ var surfData = SDL.surfaces[surf];
+ surfData.ctx.save();
+ surfData.ctx.fillStyle = color;
+ surfData.ctx.font = fontString;
+ surfData.ctx.textBaseline = 'top';
+ surfData.ctx.fillText(text, 0, 0);
+ surfData.ctx.restore();
+ return surf;
+ },
+ TTF_RenderText_Blended: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid
+ TTF_RenderText_Shaded: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid
+
+ TTF_SizeText: function(font, text, w, h) {
+ var fontData = SDL.fonts[font];
+ if (w) {
+ {{{ makeSetValue('w', '0', 'SDL.estimateTextWidth(fontData, Pointer_stringify(text))', 'i32') }}};
+ }
+ if (h) {
+ {{{ makeSetValue('h', '0', 'fontData.size', 'i32') }}};
+ }
+ return 0;
+ },
+
+ TTF_FontAscent: function(font) {
+ var fontData = SDL.fonts[font];
+ return Math.floor(fontData.size*0.98); // XXX
+ },
+
+ TTF_FontDescent: function(font) {
+ var fontData = SDL.fonts[font];
+ return Math.floor(fontData.size*0.02); // XXX
+ },
+
+ // SDL gfx
+
+ boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+ // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc.
+ surfData.ctx.save();
+ surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
+ surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1);
+ surfData.ctx.restore();
+ },
+
+ rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+ surfData.ctx.save();
+ surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
+ surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1);
+ surfData.ctx.restore();
+ },
+
+ lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+ surfData.ctx.save();
+ surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
+ surfData.ctx.beginPath();
+ surfData.ctx.moveTo(x1, y1);
+ surfData.ctx.lineTo(x2, y2);
+ surfData.ctx.stroke();
+ surfData.ctx.restore();
+ },
+
+ pixelRGBA__deps: ['boxRGBA'],
+ pixelRGBA: function(surf, x1, y1, r, g, b, a) {
+ // This cannot be fast, to render many pixels this way!
+ _boxRGBA(surf, x1, y1, x1, y1, r, g, b, a);
+ },
+
+ // GL
+
+ SDL_GL_SetAttribute: function(attr, value) {
+ console.log('TODO: SDL_GL_SetAttribute');
+ },
+
+ SDL_GL_GetProcAddress__deps: ['$GLEmulation'],
+ SDL_GL_GetProcAddress: function(name_) {
+ return GLEmulation.getProcAddress(Pointer_stringify(name_));
+ },
+
+ SDL_GL_SwapBuffers: function() {},
+
// Misc
SDL_InitSubSystem: function(flags) { return 0 },
+ SDL_NumJoysticks: function() { return 0 },
+
+ SDL_RWFromFile: function(filename, mode) {
+ return filename; // XXX We just forward the filename
+ },
+
SDL_EnableUNICODE: function(on) {
var ret = SDL.unicode || 0;
SDL.unicode = on;
@@ -596,6 +1394,9 @@ mergeInto(LibraryManager.library, {
SDL_RemoveTimer: function(id) {
window.clearTimeout(id);
return true;
- },
-});
+ }
+};
+
+autoAddDeps(LibrarySDL, '$SDL');
+mergeInto(LibraryManager.library, LibrarySDL);
diff --git a/src/library_xlib.js b/src/library_xlib.js
new file mode 100644
index 00000000..a110c786
--- /dev/null
+++ b/src/library_xlib.js
@@ -0,0 +1,24 @@
+
+var LibraryXlib = {
+ XOpenDisplay: function() {
+ return 1; // We support 1 display, the canvas
+ },
+
+ XCreateWindow: function(display, parent, x, y, width, height, border_width, depth, class_, visual, valuemask, attributes) {
+ // All we can do is set the width and height
+ Module['canvas'].width = width;
+ Module['canvas'].height = height;
+ return 2;
+ },
+
+ XChangeWindowAttributes: function(){},
+ XSetWMHints: function(){},
+ XMapWindow: function(){},
+ XStoreName: function(){},
+ XInternAtom: function(display, name_, hmm) { return 0 },
+ XSendEvent: function(){},
+ XPending: function(display) { return 0 },
+};
+
+mergeInto(LibraryManager.library, LibraryXlib);
+
diff --git a/src/long.js b/src/long.js
new file mode 100644
index 00000000..71cffa79
--- /dev/null
+++ b/src/long.js
@@ -0,0 +1,1633 @@
+// TODO: strip out parts of this we do not need
+
+//======= begin closure i64 code =======
+
+// Copyright 2009 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Defines a Long class for representing a 64-bit two's-complement
+ * integer value, which faithfully simulates the behavior of a Java "long". This
+ * implementation is derived from LongLib in GWT.
+ *
+ */
+
+var i64Math = (function() { // Emscripten wrapper
+var goog = { math: {} };
+
+
+/**
+ * Constructs a 64-bit two's-complement integer, given its low and high 32-bit
+ * values as *signed* integers. See the from* functions below for more
+ * convenient ways of constructing Longs.
+ *
+ * The internal representation of a long is the two given signed, 32-bit values.
+ * We use 32-bit pieces because these are the size of integers on which
+ * Javascript performs bit-operations. For operations like addition and
+ * multiplication, we split each number into 16-bit pieces, which can easily be
+ * multiplied within Javascript's floating-point representation without overflow
+ * or change in sign.
+ *
+ * In the algorithms below, we frequently reduce the negative case to the
+ * positive case by negating the input(s) and then post-processing the result.
+ * Note that we must ALWAYS check specially whether those values are MIN_VALUE
+ * (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
+ * a positive number, it overflows back into a negative). Not handling this
+ * case would often result in infinite recursion.
+ *
+ * @param {number} low The low (signed) 32 bits of the long.
+ * @param {number} high The high (signed) 32 bits of the long.
+ * @constructor
+ */
+goog.math.Long = function(low, high) {
+ /**
+ * @type {number}
+ * @private
+ */
+ this.low_ = low | 0; // force into 32 signed bits.
+
+ /**
+ * @type {number}
+ * @private
+ */
+ this.high_ = high | 0; // force into 32 signed bits.
+};
+
+
+// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
+// from* methods on which they depend.
+
+
+/**
+ * A cache of the Long representations of small integer values.
+ * @type {!Object}
+ * @private
+ */
+goog.math.Long.IntCache_ = {};
+
+
+/**
+ * Returns a Long representing the given (32-bit) integer value.
+ * @param {number} value The 32-bit integer in question.
+ * @return {!goog.math.Long} The corresponding Long value.
+ */
+goog.math.Long.fromInt = function(value) {
+ if (-128 <= value && value < 128) {
+ var cachedObj = goog.math.Long.IntCache_[value];
+ if (cachedObj) {
+ return cachedObj;
+ }
+ }
+
+ var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0);
+ if (-128 <= value && value < 128) {
+ goog.math.Long.IntCache_[value] = obj;
+ }
+ return obj;
+};
+
+
+/**
+ * Returns a Long representing the given value, provided that it is a finite
+ * number. Otherwise, zero is returned.
+ * @param {number} value The number in question.
+ * @return {!goog.math.Long} The corresponding Long value.
+ */
+goog.math.Long.fromNumber = function(value) {
+ if (isNaN(value) || !isFinite(value)) {
+ return goog.math.Long.ZERO;
+ } else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) {
+ return goog.math.Long.MIN_VALUE;
+ } else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) {
+ return goog.math.Long.MAX_VALUE;
+ } else if (value < 0) {
+ return goog.math.Long.fromNumber(-value).negate();
+ } else {
+ return new goog.math.Long(
+ (value % goog.math.Long.TWO_PWR_32_DBL_) | 0,
+ (value / goog.math.Long.TWO_PWR_32_DBL_) | 0);
+ }
+};
+
+
+/**
+ * Returns a Long representing the 64-bit integer that comes by concatenating
+ * the given high and low bits. Each is assumed to use 32 bits.
+ * @param {number} lowBits The low 32-bits.
+ * @param {number} highBits The high 32-bits.
+ * @return {!goog.math.Long} The corresponding Long value.
+ */
+goog.math.Long.fromBits = function(lowBits, highBits) {
+ return new goog.math.Long(lowBits, highBits);
+};
+
+
+/**
+ * Returns a Long representation of the given string, written using the given
+ * radix.
+ * @param {string} str The textual representation of the Long.
+ * @param {number=} opt_radix The radix in which the text is written.
+ * @return {!goog.math.Long} The corresponding Long value.
+ */
+goog.math.Long.fromString = function(str, opt_radix) {
+ if (str.length == 0) {
+ throw Error('number format error: empty string');
+ }
+
+ var radix = opt_radix || 10;
+ if (radix < 2 || 36 < radix) {
+ throw Error('radix out of range: ' + radix);
+ }
+
+ if (str.charAt(0) == '-') {
+ return goog.math.Long.fromString(str.substring(1), radix).negate();
+ } else if (str.indexOf('-') >= 0) {
+ throw Error('number format error: interior "-" character: ' + str);
+ }
+
+ // Do several (8) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8));
+
+ var result = goog.math.Long.ZERO;
+ for (var i = 0; i < str.length; i += 8) {
+ var size = Math.min(8, str.length - i);
+ var value = parseInt(str.substring(i, i + size), radix);
+ if (size < 8) {
+ var power = goog.math.Long.fromNumber(Math.pow(radix, size));
+ result = result.multiply(power).add(goog.math.Long.fromNumber(value));
+ } else {
+ result = result.multiply(radixToPower);
+ result = result.add(goog.math.Long.fromNumber(value));
+ }
+ }
+ return result;
+};
+
+
+// NOTE: the compiler should inline these constant values below and then remove
+// these variables, so there should be no runtime penalty for these.
+
+
+/**
+ * Number used repeated below in calculations. This must appear before the
+ * first call to any from* function below.
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_32_DBL_ =
+ goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_31_DBL_ =
+ goog.math.Long.TWO_PWR_32_DBL_ / 2;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_48_DBL_ =
+ goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_64_DBL_ =
+ goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_;
+
+
+/**
+ * @type {number}
+ * @private
+ */
+goog.math.Long.TWO_PWR_63_DBL_ =
+ goog.math.Long.TWO_PWR_64_DBL_ / 2;
+
+
+/** @type {!goog.math.Long} */
+goog.math.Long.ZERO = goog.math.Long.fromInt(0);
+
+
+/** @type {!goog.math.Long} */
+goog.math.Long.ONE = goog.math.Long.fromInt(1);
+
+
+/** @type {!goog.math.Long} */
+goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1);
+
+
+/** @type {!goog.math.Long} */
+goog.math.Long.MAX_VALUE =
+ goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
+
+
+/** @type {!goog.math.Long} */
+goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0);
+
+
+/**
+ * @type {!goog.math.Long}
+ * @private
+ */
+goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24);
+
+
+/** @return {number} The value, assuming it is a 32-bit integer. */
+goog.math.Long.prototype.toInt = function() {
+ return this.low_;
+};
+
+
+/** @return {number} The closest floating-point representation to this value. */
+goog.math.Long.prototype.toNumber = function() {
+ return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ +
+ this.getLowBitsUnsigned();
+};
+
+
+/**
+ * @param {number=} opt_radix The radix in which the text should be written.
+ * @return {string} The textual representation of this value.
+ */
+goog.math.Long.prototype.toString = function(opt_radix) {
+ var radix = opt_radix || 10;
+ if (radix < 2 || 36 < radix) {
+ throw Error('radix out of range: ' + radix);
+ }
+
+ if (this.isZero()) {
+ return '0';
+ }
+
+ if (this.isNegative()) {
+ if (this.equals(goog.math.Long.MIN_VALUE)) {
+ // We need to change the Long value before it can be negated, so we remove
+ // the bottom-most digit in this base and then recurse to do the rest.
+ var radixLong = goog.math.Long.fromNumber(radix);
+ var div = this.div(radixLong);
+ var rem = div.multiply(radixLong).subtract(this);
+ return div.toString(radix) + rem.toInt().toString(radix);
+ } else {
+ return '-' + this.negate().toString(radix);
+ }
+ }
+
+ // Do several (6) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6));
+
+ var rem = this;
+ var result = '';
+ while (true) {
+ var remDiv = rem.div(radixToPower);
+ var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
+ var digits = intval.toString(radix);
+
+ rem = remDiv;
+ if (rem.isZero()) {
+ return digits + result;
+ } else {
+ while (digits.length < 6) {
+ digits = '0' + digits;
+ }
+ result = '' + digits + result;
+ }
+ }
+};
+
+
+/** @return {number} The high 32-bits as a signed value. */
+goog.math.Long.prototype.getHighBits = function() {
+ return this.high_;
+};
+
+
+/** @return {number} The low 32-bits as a signed value. */
+goog.math.Long.prototype.getLowBits = function() {
+ return this.low_;
+};
+
+
+/** @return {number} The low 32-bits as an unsigned value. */
+goog.math.Long.prototype.getLowBitsUnsigned = function() {
+ return (this.low_ >= 0) ?
+ this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_;
+};
+
+
+/**
+ * @return {number} Returns the number of bits needed to represent the absolute
+ * value of this Long.
+ */
+goog.math.Long.prototype.getNumBitsAbs = function() {
+ if (this.isNegative()) {
+ if (this.equals(goog.math.Long.MIN_VALUE)) {
+ return 64;
+ } else {
+ return this.negate().getNumBitsAbs();
+ }
+ } else {
+ var val = this.high_ != 0 ? this.high_ : this.low_;
+ for (var bit = 31; bit > 0; bit--) {
+ if ((val & (1 << bit)) != 0) {
+ break;
+ }
+ }
+ return this.high_ != 0 ? bit + 33 : bit + 1;
+ }
+};
+
+
+/** @return {boolean} Whether this value is zero. */
+goog.math.Long.prototype.isZero = function() {
+ return this.high_ == 0 && this.low_ == 0;
+};
+
+
+/** @return {boolean} Whether this value is negative. */
+goog.math.Long.prototype.isNegative = function() {
+ return this.high_ < 0;
+};
+
+
+/** @return {boolean} Whether this value is odd. */
+goog.math.Long.prototype.isOdd = function() {
+ return (this.low_ & 1) == 1;
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long equals the other.
+ */
+goog.math.Long.prototype.equals = function(other) {
+ return (this.high_ == other.high_) && (this.low_ == other.low_);
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long does not equal the other.
+ */
+goog.math.Long.prototype.notEquals = function(other) {
+ return (this.high_ != other.high_) || (this.low_ != other.low_);
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long is less than the other.
+ */
+goog.math.Long.prototype.lessThan = function(other) {
+ return this.compare(other) < 0;
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long is less than or equal to the other.
+ */
+goog.math.Long.prototype.lessThanOrEqual = function(other) {
+ return this.compare(other) <= 0;
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long is greater than the other.
+ */
+goog.math.Long.prototype.greaterThan = function(other) {
+ return this.compare(other) > 0;
+};
+
+
+/**
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {boolean} Whether this Long is greater than or equal to the other.
+ */
+goog.math.Long.prototype.greaterThanOrEqual = function(other) {
+ return this.compare(other) >= 0;
+};
+
+
+/**
+ * Compares this Long with the given one.
+ * @param {goog.math.Long} other Long to compare against.
+ * @return {number} 0 if they are the same, 1 if the this is greater, and -1
+ * if the given one is greater.
+ */
+goog.math.Long.prototype.compare = function(other) {
+ if (this.equals(other)) {
+ return 0;
+ }
+
+ var thisNeg = this.isNegative();
+ var otherNeg = other.isNegative();
+ if (thisNeg && !otherNeg) {
+ return -1;
+ }
+ if (!thisNeg && otherNeg) {
+ return 1;
+ }
+
+ // at this point, the signs are the same, so subtraction will not overflow
+ if (this.subtract(other).isNegative()) {
+ return -1;
+ } else {
+ return 1;
+ }
+};
+
+
+/** @return {!goog.math.Long} The negation of this value. */
+goog.math.Long.prototype.negate = function() {
+ if (this.equals(goog.math.Long.MIN_VALUE)) {
+ return goog.math.Long.MIN_VALUE;
+ } else {
+ return this.not().add(goog.math.Long.ONE);
+ }
+};
+
+
+/**
+ * Returns the sum of this and the given Long.
+ * @param {goog.math.Long} other Long to add to this one.
+ * @return {!goog.math.Long} The sum of this and the given Long.
+ */
+goog.math.Long.prototype.add = function(other) {
+ // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
+
+ var a48 = this.high_ >>> 16;
+ var a32 = this.high_ & 0xFFFF;
+ var a16 = this.low_ >>> 16;
+ var a00 = this.low_ & 0xFFFF;
+
+ var b48 = other.high_ >>> 16;
+ var b32 = other.high_ & 0xFFFF;
+ var b16 = other.low_ >>> 16;
+ var b00 = other.low_ & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 + b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 + b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 + b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 + b48;
+ c48 &= 0xFFFF;
+ return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
+};
+
+
+/**
+ * Returns the difference of this and the given Long.
+ * @param {goog.math.Long} other Long to subtract from this.
+ * @return {!goog.math.Long} The difference of this and the given Long.
+ */
+goog.math.Long.prototype.subtract = function(other) {
+ return this.add(other.negate());
+};
+
+
+/**
+ * Returns the product of this and the given long.
+ * @param {goog.math.Long} other Long to multiply with this.
+ * @return {!goog.math.Long} The product of this and the other.
+ */
+goog.math.Long.prototype.multiply = function(other) {
+ if (this.isZero()) {
+ return goog.math.Long.ZERO;
+ } else if (other.isZero()) {
+ return goog.math.Long.ZERO;
+ }
+
+ if (this.equals(goog.math.Long.MIN_VALUE)) {
+ return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
+ } else if (other.equals(goog.math.Long.MIN_VALUE)) {
+ return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
+ }
+
+ if (this.isNegative()) {
+ if (other.isNegative()) {
+ return this.negate().multiply(other.negate());
+ } else {
+ return this.negate().multiply(other).negate();
+ }
+ } else if (other.isNegative()) {
+ return this.multiply(other.negate()).negate();
+ }
+
+ // If both longs are small, use float multiplication
+ if (this.lessThan(goog.math.Long.TWO_PWR_24_) &&
+ other.lessThan(goog.math.Long.TWO_PWR_24_)) {
+ return goog.math.Long.fromNumber(this.toNumber() * other.toNumber());
+ }
+
+ // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+ // We can skip products that would overflow.
+
+ var a48 = this.high_ >>> 16;
+ var a32 = this.high_ & 0xFFFF;
+ var a16 = this.low_ >>> 16;
+ var a00 = this.low_ & 0xFFFF;
+
+ var b48 = other.high_ >>> 16;
+ var b32 = other.high_ & 0xFFFF;
+ var b16 = other.low_ >>> 16;
+ var b00 = other.low_ & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 * b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 * b00;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c16 += a00 * b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 * b00;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a16 * b16;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a00 * b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
+ c48 &= 0xFFFF;
+ return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
+};
+
+
+/**
+ * Returns this Long divided by the given one.
+ * @param {goog.math.Long} other Long by which to divide.
+ * @return {!goog.math.Long} This Long divided by the given one.
+ */
+goog.math.Long.prototype.div = function(other) {
+ if (other.isZero()) {
+ throw Error('division by zero');
+ } else if (this.isZero()) {
+ return goog.math.Long.ZERO;
+ }
+
+ if (this.equals(goog.math.Long.MIN_VALUE)) {
+ if (other.equals(goog.math.Long.ONE) ||
+ other.equals(goog.math.Long.NEG_ONE)) {
+ return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
+ } else if (other.equals(goog.math.Long.MIN_VALUE)) {
+ return goog.math.Long.ONE;
+ } else {
+ // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
+ var halfThis = this.shiftRight(1);
+ var approx = halfThis.div(other).shiftLeft(1);
+ if (approx.equals(goog.math.Long.ZERO)) {
+ return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE;
+ } else {
+ var rem = this.subtract(other.multiply(approx));
+ var result = approx.add(rem.div(other));
+ return result;
+ }
+ }
+ } else if (other.equals(goog.math.Long.MIN_VALUE)) {
+ return goog.math.Long.ZERO;
+ }
+
+ if (this.isNegative()) {
+ if (other.isNegative()) {
+ return this.negate().div(other.negate());
+ } else {
+ return this.negate().div(other).negate();
+ }
+ } else if (other.isNegative()) {
+ return this.div(other.negate()).negate();
+ }
+
+ // Repeat the following until the remainder is less than other: find a
+ // floating-point that approximates remainder / other *from below*, add this
+ // into the result, and subtract it from the remainder. It is critical that
+ // the approximate value is less than or equal to the real value so that the
+ // remainder never becomes negative.
+ var res = goog.math.Long.ZERO;
+ var rem = this;
+ while (rem.greaterThanOrEqual(other)) {
+ // Approximate the result of division. This may be a little greater or
+ // smaller than the actual value.
+ var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
+
+ // We will tweak the approximate result by changing it in the 48-th digit or
+ // the smallest non-fractional digit, whichever is larger.
+ var log2 = Math.ceil(Math.log(approx) / Math.LN2);
+ var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
+
+ // Decrease the approximation until it is smaller than the remainder. Note
+ // that if it is too large, the product overflows and is negative.
+ var approxRes = goog.math.Long.fromNumber(approx);
+ var approxRem = approxRes.multiply(other);
+ while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
+ approx -= delta;
+ approxRes = goog.math.Long.fromNumber(approx);
+ approxRem = approxRes.multiply(other);
+ }
+
+ // We know the answer can't be zero... and actually, zero would cause
+ // infinite recursion since we would make no progress.
+ if (approxRes.isZero()) {
+ approxRes = goog.math.Long.ONE;
+ }
+
+ res = res.add(approxRes);
+ rem = rem.subtract(approxRem);
+ }
+ return res;
+};
+
+
+/**
+ * Returns this Long modulo the given one.
+ * @param {goog.math.Long} other Long by which to mod.
+ * @return {!goog.math.Long} This Long modulo the given one.
+ */
+goog.math.Long.prototype.modulo = function(other) {
+ return this.subtract(this.div(other).multiply(other));
+};
+
+
+/** @return {!goog.math.Long} The bitwise-NOT of this value. */
+goog.math.Long.prototype.not = function() {
+ return goog.math.Long.fromBits(~this.low_, ~this.high_);
+};
+
+
+/**
+ * Returns the bitwise-AND of this Long and the given one.
+ * @param {goog.math.Long} other The Long with which to AND.
+ * @return {!goog.math.Long} The bitwise-AND of this and the other.
+ */
+goog.math.Long.prototype.and = function(other) {
+ return goog.math.Long.fromBits(this.low_ & other.low_,
+ this.high_ & other.high_);
+};
+
+
+/**
+ * Returns the bitwise-OR of this Long and the given one.
+ * @param {goog.math.Long} other The Long with which to OR.
+ * @return {!goog.math.Long} The bitwise-OR of this and the other.
+ */
+goog.math.Long.prototype.or = function(other) {
+ return goog.math.Long.fromBits(this.low_ | other.low_,
+ this.high_ | other.high_);
+};
+
+
+/**
+ * Returns the bitwise-XOR of this Long and the given one.
+ * @param {goog.math.Long} other The Long with which to XOR.
+ * @return {!goog.math.Long} The bitwise-XOR of this and the other.
+ */
+goog.math.Long.prototype.xor = function(other) {
+ return goog.math.Long.fromBits(this.low_ ^ other.low_,
+ this.high_ ^ other.high_);
+};
+
+
+/**
+ * Returns this Long with bits shifted to the left by the given amount.
+ * @param {number} numBits The number of bits by which to shift.
+ * @return {!goog.math.Long} This shifted to the left by the given amount.
+ */
+goog.math.Long.prototype.shiftLeft = function(numBits) {
+ numBits &= 63;
+ if (numBits == 0) {
+ return this;
+ } else {
+ var low = this.low_;
+ if (numBits < 32) {
+ var high = this.high_;
+ return goog.math.Long.fromBits(
+ low << numBits,
+ (high << numBits) | (low >>> (32 - numBits)));
+ } else {
+ return goog.math.Long.fromBits(0, low << (numBits - 32));
+ }
+ }
+};
+
+
+/**
+ * Returns this Long with bits shifted to the right by the given amount.
+ * @param {number} numBits The number of bits by which to shift.
+ * @return {!goog.math.Long} This shifted to the right by the given amount.
+ */
+goog.math.Long.prototype.shiftRight = function(numBits) {
+ numBits &= 63;
+ if (numBits == 0) {
+ return this;
+ } else {
+ var high = this.high_;
+ if (numBits < 32) {
+ var low = this.low_;
+ return goog.math.Long.fromBits(
+ (low >>> numBits) | (high << (32 - numBits)),
+ high >> numBits);
+ } else {
+ return goog.math.Long.fromBits(
+ high >> (numBits - 32),
+ high >= 0 ? 0 : -1);
+ }
+ }
+};
+
+
+/**
+ * Returns this Long with bits shifted to the right by the given amount, with
+ * the new top bits matching the current sign bit.
+ * @param {number} numBits The number of bits by which to shift.
+ * @return {!goog.math.Long} This shifted to the right by the given amount, with
+ * zeros placed into the new leading bits.
+ */
+goog.math.Long.prototype.shiftRightUnsigned = function(numBits) {
+ numBits &= 63;
+ if (numBits == 0) {
+ return this;
+ } else {
+ var high = this.high_;
+ if (numBits < 32) {
+ var low = this.low_;
+ return goog.math.Long.fromBits(
+ (low >>> numBits) | (high << (32 - numBits)),
+ high >>> numBits);
+ } else if (numBits == 32) {
+ return goog.math.Long.fromBits(high, 0);
+ } else {
+ return goog.math.Long.fromBits(high >>> (numBits - 32), 0);
+ }
+ }
+};
+
+//======= begin jsbn =======
+
+var navigator = { appName: 'Modern Browser' }; // polyfill a little
+
+// Copyright (c) 2005 Tom Wu
+// All Rights Reserved.
+// http://www-cs-students.stanford.edu/~tjw/jsbn/
+
+/*
+ * Copyright (c) 2003-2005 Tom Wu
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * In addition, the following condition applies:
+ *
+ * All redistributions must retain an intact copy of this copyright notice
+ * and disclaimer.
+ */
+
+// Basic JavaScript BN library - subset useful for RSA encryption.
+
+// Bits per digit
+var dbits;
+
+// JavaScript engine analysis
+var canary = 0xdeadbeefcafe;
+var j_lm = ((canary&0xffffff)==0xefcafe);
+
+// (public) Constructor
+function BigInteger(a,b,c) {
+ if(a != null)
+ if("number" == typeof a) this.fromNumber(a,b,c);
+ else if(b == null && "string" != typeof a) this.fromString(a,256);
+ else this.fromString(a,b);
+}
+
+// return new, unset BigInteger
+function nbi() { return new BigInteger(null); }
+
+// am: Compute w_j += (x*this_i), propagate carries,
+// c is initial carry, returns final carry.
+// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
+// We need to select the fastest one that works in this environment.
+
+// am1: use a single mult and divide to get the high bits,
+// max digit bits should be 26 because
+// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
+function am1(i,x,w,j,c,n) {
+ while(--n >= 0) {
+ var v = x*this[i++]+w[j]+c;
+ c = Math.floor(v/0x4000000);
+ w[j++] = v&0x3ffffff;
+ }
+ return c;
+}
+// am2 avoids a big mult-and-extract completely.
+// Max digit bits should be <= 30 because we do bitwise ops
+// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
+function am2(i,x,w,j,c,n) {
+ var xl = x&0x7fff, xh = x>>15;
+ while(--n >= 0) {
+ var l = this[i]&0x7fff;
+ var h = this[i++]>>15;
+ var m = xh*l+h*xl;
+ l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
+ c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
+ w[j++] = l&0x3fffffff;
+ }
+ return c;
+}
+// Alternately, set max digit bits to 28 since some
+// browsers slow down when dealing with 32-bit numbers.
+function am3(i,x,w,j,c,n) {
+ var xl = x&0x3fff, xh = x>>14;
+ while(--n >= 0) {
+ var l = this[i]&0x3fff;
+ var h = this[i++]>>14;
+ var m = xh*l+h*xl;
+ l = xl*l+((m&0x3fff)<<14)+w[j]+c;
+ c = (l>>28)+(m>>14)+xh*h;
+ w[j++] = l&0xfffffff;
+ }
+ return c;
+}
+if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+ BigInteger.prototype.am = am2;
+ dbits = 30;
+}
+else if(j_lm && (navigator.appName != "Netscape")) {
+ BigInteger.prototype.am = am1;
+ dbits = 26;
+}
+else { // Mozilla/Netscape seems to prefer am3
+ BigInteger.prototype.am = am3;
+ dbits = 28;
+}
+
+BigInteger.prototype.DB = dbits;
+BigInteger.prototype.DM = ((1<<dbits)-1);
+BigInteger.prototype.DV = (1<<dbits);
+
+var BI_FP = 52;
+BigInteger.prototype.FV = Math.pow(2,BI_FP);
+BigInteger.prototype.F1 = BI_FP-dbits;
+BigInteger.prototype.F2 = 2*dbits-BI_FP;
+
+// Digit conversions
+var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
+var BI_RC = new Array();
+var rr,vv;
+rr = "0".charCodeAt(0);
+for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+rr = "a".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+rr = "A".charCodeAt(0);
+for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+
+function int2char(n) { return BI_RM.charAt(n); }
+function intAt(s,i) {
+ var c = BI_RC[s.charCodeAt(i)];
+ return (c==null)?-1:c;
+}
+
+// (protected) copy this to r
+function bnpCopyTo(r) {
+ for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
+ r.t = this.t;
+ r.s = this.s;
+}
+
+// (protected) set from integer value x, -DV <= x < DV
+function bnpFromInt(x) {
+ this.t = 1;
+ this.s = (x<0)?-1:0;
+ if(x > 0) this[0] = x;
+ else if(x < -1) this[0] = x+DV;
+ else this.t = 0;
+}
+
+// return bigint initialized to value
+function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+
+// (protected) set from string and radix
+function bnpFromString(s,b) {
+ var k;
+ if(b == 16) k = 4;
+ else if(b == 8) k = 3;
+ else if(b == 256) k = 8; // byte array
+ else if(b == 2) k = 1;
+ else if(b == 32) k = 5;
+ else if(b == 4) k = 2;
+ else { this.fromRadix(s,b); return; }
+ this.t = 0;
+ this.s = 0;
+ var i = s.length, mi = false, sh = 0;
+ while(--i >= 0) {
+ var x = (k==8)?s[i]&0xff:intAt(s,i);
+ if(x < 0) {
+ if(s.charAt(i) == "-") mi = true;
+ continue;
+ }
+ mi = false;
+ if(sh == 0)
+ this[this.t++] = x;
+ else if(sh+k > this.DB) {
+ this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
+ this[this.t++] = (x>>(this.DB-sh));
+ }
+ else
+ this[this.t-1] |= x<<sh;
+ sh += k;
+ if(sh >= this.DB) sh -= this.DB;
+ }
+ if(k == 8 && (s[0]&0x80) != 0) {
+ this.s = -1;
+ if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
+ }
+ this.clamp();
+ if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) clamp off excess high words
+function bnpClamp() {
+ var c = this.s&this.DM;
+ while(this.t > 0 && this[this.t-1] == c) --this.t;
+}
+
+// (public) return string representation in given radix
+function bnToString(b) {
+ if(this.s < 0) return "-"+this.negate().toString(b);
+ var k;
+ if(b == 16) k = 4;
+ else if(b == 8) k = 3;
+ else if(b == 2) k = 1;
+ else if(b == 32) k = 5;
+ else if(b == 4) k = 2;
+ else return this.toRadix(b);
+ var km = (1<<k)-1, d, m = false, r = "", i = this.t;
+ var p = this.DB-(i*this.DB)%k;
+ if(i-- > 0) {
+ if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
+ while(i >= 0) {
+ if(p < k) {
+ d = (this[i]&((1<<p)-1))<<(k-p);
+ d |= this[--i]>>(p+=this.DB-k);
+ }
+ else {
+ d = (this[i]>>(p-=k))&km;
+ if(p <= 0) { p += this.DB; --i; }
+ }
+ if(d > 0) m = true;
+ if(m) r += int2char(d);
+ }
+ }
+ return m?r:"0";
+}
+
+// (public) -this
+function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+
+// (public) |this|
+function bnAbs() { return (this.s<0)?this.negate():this; }
+
+// (public) return + if this > a, - if this < a, 0 if equal
+function bnCompareTo(a) {
+ var r = this.s-a.s;
+ if(r != 0) return r;
+ var i = this.t;
+ r = i-a.t;
+ if(r != 0) return r;
+ while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
+ return 0;
+}
+
+// returns bit length of the integer x
+function nbits(x) {
+ var r = 1, t;
+ if((t=x>>>16) != 0) { x = t; r += 16; }
+ if((t=x>>8) != 0) { x = t; r += 8; }
+ if((t=x>>4) != 0) { x = t; r += 4; }
+ if((t=x>>2) != 0) { x = t; r += 2; }
+ if((t=x>>1) != 0) { x = t; r += 1; }
+ return r;
+}
+
+// (public) return the number of bits in "this"
+function bnBitLength() {
+ if(this.t <= 0) return 0;
+ return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+}
+
+// (protected) r = this << n*DB
+function bnpDLShiftTo(n,r) {
+ var i;
+ for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
+ for(i = n-1; i >= 0; --i) r[i] = 0;
+ r.t = this.t+n;
+ r.s = this.s;
+}
+
+// (protected) r = this >> n*DB
+function bnpDRShiftTo(n,r) {
+ for(var i = n; i < this.t; ++i) r[i-n] = this[i];
+ r.t = Math.max(this.t-n,0);
+ r.s = this.s;
+}
+
+// (protected) r = this << n
+function bnpLShiftTo(n,r) {
+ var bs = n%this.DB;
+ var cbs = this.DB-bs;
+ var bm = (1<<cbs)-1;
+ var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
+ for(i = this.t-1; i >= 0; --i) {
+ r[i+ds+1] = (this[i]>>cbs)|c;
+ c = (this[i]&bm)<<bs;
+ }
+ for(i = ds-1; i >= 0; --i) r[i] = 0;
+ r[ds] = c;
+ r.t = this.t+ds+1;
+ r.s = this.s;
+ r.clamp();
+}
+
+// (protected) r = this >> n
+function bnpRShiftTo(n,r) {
+ r.s = this.s;
+ var ds = Math.floor(n/this.DB);
+ if(ds >= this.t) { r.t = 0; return; }
+ var bs = n%this.DB;
+ var cbs = this.DB-bs;
+ var bm = (1<<bs)-1;
+ r[0] = this[ds]>>bs;
+ for(var i = ds+1; i < this.t; ++i) {
+ r[i-ds-1] |= (this[i]&bm)<<cbs;
+ r[i-ds] = this[i]>>bs;
+ }
+ if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
+ r.t = this.t-ds;
+ r.clamp();
+}
+
+// (protected) r = this - a
+function bnpSubTo(a,r) {
+ var i = 0, c = 0, m = Math.min(a.t,this.t);
+ while(i < m) {
+ c += this[i]-a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ if(a.t < this.t) {
+ c -= a.s;
+ while(i < this.t) {
+ c += this[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += this.s;
+ }
+ else {
+ c += this.s;
+ while(i < a.t) {
+ c -= a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c -= a.s;
+ }
+ r.s = (c<0)?-1:0;
+ if(c < -1) r[i++] = this.DV+c;
+ else if(c > 0) r[i++] = c;
+ r.t = i;
+ r.clamp();
+}
+
+// (protected) r = this * a, r != this,a (HAC 14.12)
+// "this" should be the larger one if appropriate.
+function bnpMultiplyTo(a,r) {
+ var x = this.abs(), y = a.abs();
+ var i = x.t;
+ r.t = i+y.t;
+ while(--i >= 0) r[i] = 0;
+ for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
+ r.s = 0;
+ r.clamp();
+ if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+}
+
+// (protected) r = this^2, r != this (HAC 14.16)
+function bnpSquareTo(r) {
+ var x = this.abs();
+ var i = r.t = 2*x.t;
+ while(--i >= 0) r[i] = 0;
+ for(i = 0; i < x.t-1; ++i) {
+ var c = x.am(i,x[i],r,2*i,0,1);
+ if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
+ r[i+x.t] -= x.DV;
+ r[i+x.t+1] = 1;
+ }
+ }
+ if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
+ r.s = 0;
+ r.clamp();
+}
+
+// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
+// r != q, this != m. q or r may be null.
+function bnpDivRemTo(m,q,r) {
+ var pm = m.abs();
+ if(pm.t <= 0) return;
+ var pt = this.abs();
+ if(pt.t < pm.t) {
+ if(q != null) q.fromInt(0);
+ if(r != null) this.copyTo(r);
+ return;
+ }
+ if(r == null) r = nbi();
+ var y = nbi(), ts = this.s, ms = m.s;
+ var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
+ if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
+ else { pm.copyTo(y); pt.copyTo(r); }
+ var ys = y.t;
+ var y0 = y[ys-1];
+ if(y0 == 0) return;
+ var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
+ var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
+ var i = r.t, j = i-ys, t = (q==null)?nbi():q;
+ y.dlShiftTo(j,t);
+ if(r.compareTo(t) >= 0) {
+ r[r.t++] = 1;
+ r.subTo(t,r);
+ }
+ BigInteger.ONE.dlShiftTo(ys,t);
+ t.subTo(y,y); // "negative" y so we can replace sub with am later
+ while(y.t < ys) y[y.t++] = 0;
+ while(--j >= 0) {
+ // Estimate quotient digit
+ var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
+ if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
+ y.dlShiftTo(j,t);
+ r.subTo(t,r);
+ while(r[i] < --qd) r.subTo(t,r);
+ }
+ }
+ if(q != null) {
+ r.drShiftTo(ys,q);
+ if(ts != ms) BigInteger.ZERO.subTo(q,q);
+ }
+ r.t = ys;
+ r.clamp();
+ if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
+ if(ts < 0) BigInteger.ZERO.subTo(r,r);
+}
+
+// (public) this mod a
+function bnMod(a) {
+ var r = nbi();
+ this.abs().divRemTo(a,null,r);
+ if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
+ return r;
+}
+
+// Modular reduction using "classic" algorithm
+function Classic(m) { this.m = m; }
+function cConvert(x) {
+ if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+ else return x;
+}
+function cRevert(x) { return x; }
+function cReduce(x) { x.divRemTo(this.m,null,x); }
+function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+Classic.prototype.convert = cConvert;
+Classic.prototype.revert = cRevert;
+Classic.prototype.reduce = cReduce;
+Classic.prototype.mulTo = cMulTo;
+Classic.prototype.sqrTo = cSqrTo;
+
+// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
+// justification:
+// xy == 1 (mod m)
+// xy = 1+km
+// xy(2-xy) = (1+km)(1-km)
+// x[y(2-xy)] = 1-k^2m^2
+// x[y(2-xy)] == 1 (mod m^2)
+// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+// JS multiply "overflows" differently from C/C++, so care is needed here.
+function bnpInvDigit() {
+ if(this.t < 1) return 0;
+ var x = this[0];
+ if((x&1) == 0) return 0;
+ var y = x&3; // y == 1/x mod 2^2
+ y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
+ y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
+ y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
+ // last step - calculate inverse mod DV directly;
+ // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+ y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
+ // we really want the negative inverse, and -DV < y < DV
+ return (y>0)?this.DV-y:-y;
+}
+
+// Montgomery reduction
+function Montgomery(m) {
+ this.m = m;
+ this.mp = m.invDigit();
+ this.mpl = this.mp&0x7fff;
+ this.mph = this.mp>>15;
+ this.um = (1<<(m.DB-15))-1;
+ this.mt2 = 2*m.t;
+}
+
+// xR mod m
+function montConvert(x) {
+ var r = nbi();
+ x.abs().dlShiftTo(this.m.t,r);
+ r.divRemTo(this.m,null,r);
+ if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
+ return r;
+}
+
+// x/R mod m
+function montRevert(x) {
+ var r = nbi();
+ x.copyTo(r);
+ this.reduce(r);
+ return r;
+}
+
+// x = x/R mod m (HAC 14.32)
+function montReduce(x) {
+ while(x.t <= this.mt2) // pad x so am has enough room later
+ x[x.t++] = 0;
+ for(var i = 0; i < this.m.t; ++i) {
+ // faster way of calculating u0 = x[i]*mp mod DV
+ var j = x[i]&0x7fff;
+ var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
+ // use am to combine the multiply-shift-add into one call
+ j = i+this.m.t;
+ x[j] += this.m.am(0,u0,x,i,0,this.m.t);
+ // propagate carry
+ while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
+ }
+ x.clamp();
+ x.drShiftTo(this.m.t,x);
+ if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+}
+
+// r = "x^2/R mod m"; x != r
+function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+
+// r = "xy/R mod m"; x,y != r
+function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+
+Montgomery.prototype.convert = montConvert;
+Montgomery.prototype.revert = montRevert;
+Montgomery.prototype.reduce = montReduce;
+Montgomery.prototype.mulTo = montMulTo;
+Montgomery.prototype.sqrTo = montSqrTo;
+
+// (protected) true iff this is even
+function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+
+// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
+function bnpExp(e,z) {
+ if(e > 0xffffffff || e < 1) return BigInteger.ONE;
+ var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
+ g.copyTo(r);
+ while(--i >= 0) {
+ z.sqrTo(r,r2);
+ if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
+ else { var t = r; r = r2; r2 = t; }
+ }
+ return z.revert(r);
+}
+
+// (public) this^e % m, 0 <= e < 2^32
+function bnModPowInt(e,m) {
+ var z;
+ if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+ return this.exp(e,z);
+}
+
+// protected
+BigInteger.prototype.copyTo = bnpCopyTo;
+BigInteger.prototype.fromInt = bnpFromInt;
+BigInteger.prototype.fromString = bnpFromString;
+BigInteger.prototype.clamp = bnpClamp;
+BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
+BigInteger.prototype.drShiftTo = bnpDRShiftTo;
+BigInteger.prototype.lShiftTo = bnpLShiftTo;
+BigInteger.prototype.rShiftTo = bnpRShiftTo;
+BigInteger.prototype.subTo = bnpSubTo;
+BigInteger.prototype.multiplyTo = bnpMultiplyTo;
+BigInteger.prototype.squareTo = bnpSquareTo;
+BigInteger.prototype.divRemTo = bnpDivRemTo;
+BigInteger.prototype.invDigit = bnpInvDigit;
+BigInteger.prototype.isEven = bnpIsEven;
+BigInteger.prototype.exp = bnpExp;
+
+// public
+BigInteger.prototype.toString = bnToString;
+BigInteger.prototype.negate = bnNegate;
+BigInteger.prototype.abs = bnAbs;
+BigInteger.prototype.compareTo = bnCompareTo;
+BigInteger.prototype.bitLength = bnBitLength;
+BigInteger.prototype.mod = bnMod;
+BigInteger.prototype.modPowInt = bnModPowInt;
+
+// "constants"
+BigInteger.ZERO = nbv(0);
+BigInteger.ONE = nbv(1);
+
+// jsbn2 stuff
+
+// (protected) convert from radix string
+function bnpFromRadix(s,b) {
+ this.fromInt(0);
+ if(b == null) b = 10;
+ var cs = this.chunkSize(b);
+ var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
+ for(var i = 0; i < s.length; ++i) {
+ var x = intAt(s,i);
+ if(x < 0) {
+ if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
+ continue;
+ }
+ w = b*w+x;
+ if(++j >= cs) {
+ this.dMultiply(d);
+ this.dAddOffset(w,0);
+ j = 0;
+ w = 0;
+ }
+ }
+ if(j > 0) {
+ this.dMultiply(Math.pow(b,j));
+ this.dAddOffset(w,0);
+ }
+ if(mi) BigInteger.ZERO.subTo(this,this);
+}
+
+// (protected) return x s.t. r^x < DV
+function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
+
+// (public) 0 if this == 0, 1 if this > 0
+function bnSigNum() {
+ if(this.s < 0) return -1;
+ else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
+ else return 1;
+}
+
+// (protected) this *= n, this >= 0, 1 < n < DV
+function bnpDMultiply(n) {
+ this[this.t] = this.am(0,n-1,this,0,0,this.t);
+ ++this.t;
+ this.clamp();
+}
+
+// (protected) this += n << w words, this >= 0
+function bnpDAddOffset(n,w) {
+ if(n == 0) return;
+ while(this.t <= w) this[this.t++] = 0;
+ this[w] += n;
+ while(this[w] >= this.DV) {
+ this[w] -= this.DV;
+ if(++w >= this.t) this[this.t++] = 0;
+ ++this[w];
+ }
+}
+
+// (protected) convert to radix string
+function bnpToRadix(b) {
+ if(b == null) b = 10;
+ if(this.signum() == 0 || b < 2 || b > 36) return "0";
+ var cs = this.chunkSize(b);
+ var a = Math.pow(b,cs);
+ var d = nbv(a), y = nbi(), z = nbi(), r = "";
+ this.divRemTo(d,y,z);
+ while(y.signum() > 0) {
+ r = (a+z.intValue()).toString(b).substr(1) + r;
+ y.divRemTo(d,y,z);
+ }
+ return z.intValue().toString(b) + r;
+}
+
+// (public) return value as integer
+function bnIntValue() {
+ if(this.s < 0) {
+ if(this.t == 1) return this[0]-this.DV;
+ else if(this.t == 0) return -1;
+ }
+ else if(this.t == 1) return this[0];
+ else if(this.t == 0) return 0;
+ // assumes 16 < DB < 32
+ return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
+}
+
+// (protected) r = this + a
+function bnpAddTo(a,r) {
+ var i = 0, c = 0, m = Math.min(a.t,this.t);
+ while(i < m) {
+ c += this[i]+a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ if(a.t < this.t) {
+ c += a.s;
+ while(i < this.t) {
+ c += this[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += this.s;
+ }
+ else {
+ c += this.s;
+ while(i < a.t) {
+ c += a[i];
+ r[i++] = c&this.DM;
+ c >>= this.DB;
+ }
+ c += a.s;
+ }
+ r.s = (c<0)?-1:0;
+ if(c > 0) r[i++] = c;
+ else if(c < -1) r[i++] = this.DV+c;
+ r.t = i;
+ r.clamp();
+}
+
+BigInteger.prototype.fromRadix = bnpFromRadix;
+BigInteger.prototype.chunkSize = bnpChunkSize;
+BigInteger.prototype.signum = bnSigNum;
+BigInteger.prototype.dMultiply = bnpDMultiply;
+BigInteger.prototype.dAddOffset = bnpDAddOffset;
+BigInteger.prototype.toRadix = bnpToRadix;
+BigInteger.prototype.intValue = bnIntValue;
+BigInteger.prototype.addTo = bnpAddTo;
+
+//======= end jsbn =======
+
+// Emscripten wrapper
+var Wrapper = {
+ result: [0, 0], // return result stored here
+ add: function(xl, xh, yl, yh) {
+ var x = new goog.math.Long(xl, xh);
+ var y = new goog.math.Long(yl, yh);
+ var ret = x.add(y);
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ },
+ subtract: function(xl, xh, yl, yh) {
+ var x = new goog.math.Long(xl, xh);
+ var y = new goog.math.Long(yl, yh);
+ var ret = x.subtract(y);
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ },
+ multiply: function(xl, xh, yl, yh) {
+ var x = new goog.math.Long(xl, xh);
+ var y = new goog.math.Long(yl, yh);
+ var ret = x.multiply(y);
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ },
+ makeTwo32: function() {
+ Wrapper.two32 = new BigInteger();
+ Wrapper.two32.fromString('4294967296', 10);
+ },
+ lh2bignum: function(l, h) {
+ var a = new BigInteger();
+ a.fromString(h.toString(), 10);
+ var b = new BigInteger();
+ a.multiplyTo(Wrapper.two32, b);
+ var c = new BigInteger();
+ c.fromString(l.toString(), 10);
+ var d = new BigInteger();
+ c.addTo(b, d);
+ return d;
+ },
+ divide: function(xl, xh, yl, yh, unsigned) {
+ if (!Wrapper.two32) Wrapper.makeTwo32();
+ if (!unsigned) {
+ var x = new goog.math.Long(xl, xh);
+ var y = new goog.math.Long(yl, yh);
+ var ret = x.div(y);
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ } else {
+ // slow precise bignum division
+ var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0);
+ var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0);
+ var z = new BigInteger();
+ x.divRemTo(y, z, null);
+ var l = new BigInteger();
+ var h = new BigInteger();
+ z.divRemTo(Wrapper.two32, h, l);
+ Wrapper.result[0] = parseInt(l.toString()) | 0;
+ Wrapper.result[1] = parseInt(h.toString()) | 0;
+ }
+ },
+ modulo: function(xl, xh, yl, yh, unsigned) {
+ if (!Wrapper.two32) Wrapper.makeTwo32();
+ if (!unsigned) {
+ var x = new goog.math.Long(xl, xh);
+ var y = new goog.math.Long(yl, yh);
+ var ret = x.modulo(y);
+ Wrapper.result[0] = ret.low_;
+ Wrapper.result[1] = ret.high_;
+ } else {
+ // slow precise bignum division
+ var x = Wrapper.lh2bignum(xl >>> 0, xh >>> 0);
+ var y = Wrapper.lh2bignum(yl >>> 0, yh >>> 0);
+ var z = new BigInteger();
+ x.divRemTo(y, null, z);
+ var l = new BigInteger();
+ var h = new BigInteger();
+ z.divRemTo(Wrapper.two32, h, l);
+ Wrapper.result[0] = parseInt(l.toString()) | 0;
+ Wrapper.result[1] = parseInt(h.toString()) | 0;
+ }
+ },
+ stringify: function(l, h, unsigned) {
+ var ret = new goog.math.Long(l, h).toString();
+ if (unsigned && ret[0] == '-') {
+ // unsign slowly using jsbn bignums
+ if (!Wrapper.two64) {
+ Wrapper.two64 = new BigInteger();
+ Wrapper.two64.fromString('18446744073709551616', 10);
+ }
+ var bignum = new BigInteger();
+ bignum.fromString(ret, 10);
+ ret = new BigInteger();
+ Wrapper.two64.addTo(bignum, ret);
+ ret = ret.toString(10);
+ }
+ return ret;
+ }
+};
+return Wrapper;
+})();
+
+//======= end closure i64 code =======
+
diff --git a/src/modules.js b/src/modules.js
index fd22b9fe..0f3b483b 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -259,8 +259,9 @@ var LibraryManager = {
load: function() {
assert(!this.library);
- for (var suffix in set('', '_sdl', '_browser', '_gl')) {
- eval(processMacros(preprocess(read('library' + suffix + '.js'))));
+ var libraries = ['library.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js'].concat(additionalLibraries);
+ for (var i = 0; i < libraries.length; i++) {
+ eval(processMacros(preprocess(read(libraries[i]))));
}
},
diff --git a/src/parseTools.js b/src/parseTools.js
index 520d278e..86e3c643 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -123,7 +123,7 @@ function isPointerType(type) {
function isStructType(type) {
if (isPointerType(type)) return false;
if (/^\[\d+\ x\ (.*)\]/.test(type)) return true; // [15 x ?] blocks. Like structs
- if (/<?{ [^}]* }>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
+ if (/<?{ ?[^}]* ?}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
// See comment in isStructPointerType()
return type[0] == '%';
}
@@ -169,7 +169,15 @@ function isFunctionDef(token, out) {
function isFunctionType(type, out) {
type = type.replace(/"[^"]+"/g, '".."');
- var parts = type.split(' ');
+ var parts;
+ // hackish, but quick splitting of function def parts. this must be fast as it happens a lot
+ if (type[0] != '[') {
+ parts = type.split(' ');
+ } else {
+ var index = type.search(']');
+ index += type.substr(index).search(' ');
+ parts = [type.substr(0, index), type.substr(index+1)];
+ }
if (pointingLevels(type) !== 1) return false;
var text = removeAllPointing(parts.slice(1).join(' '));
if (!text) return false;
@@ -412,7 +420,7 @@ function cleanSegment(segment) {
return segment;
}
-var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']);
+var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'frem', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']);
var PARSABLE_LLVM_FUNCTIONS = set('getelementptr', 'bitcast');
mergeInto(PARSABLE_LLVM_FUNCTIONS, MATHOPS);
@@ -499,7 +507,7 @@ function IEEEUnHex(stringy) {
while (stringy.length < 16) stringy = '0' + stringy;
if (FAKE_X86_FP80 && stringy.length > 16) {
stringy = stringy.substr(stringy.length-16, 16);
- warnOnce('.ll contains floating-point values with more than 64 bits. Faking values for them. If they are used, this will almost certainly fail!');
+ warnOnce('.ll contains floating-point values with more than 64 bits. Faking values for them. If they are used, this will almost certainly break horribly!');
}
assert(stringy.length === 16, 'Can only unhex 16-digit double numbers, nothing platform-specific'); // |long double| can cause x86_fp80 which causes this
var top = eval('0x' + stringy[0]);
@@ -683,16 +691,14 @@ function parseArbitraryInt(str, bits) {
return ret;
}
-function parseI64Constant(str) {
- assert(USE_TYPED_ARRAYS == 2);
-
+function parseI64Constant(str, legalized) {
if (!isNumber(str)) {
// This is a variable. Copy it, so we do not modify the original
return legalizedI64s ? str : makeCopyI64(str);
}
var parsed = parseArbitraryInt(str, 64);
- if (legalizedI64s) return parsed;
+ if (legalizedI64s || legalized) return parsed;
return '[' + parsed[0] + ',' + parsed[1] + ']';
}
@@ -769,7 +775,7 @@ function generateStructTypes(type) {
if (USE_TYPED_ARRAYS == 2 && type == 'i64') {
return ['i64', 0, 0, 0, 'i32', 0, 0, 0];
}
- return [type].concat(zeros(Runtime.getNativeFieldSize(type)));
+ return [type].concat(zeros(Runtime.getNativeFieldSize(type)-1));
}
// Avoid multiple concats by finding the size first. This is much faster
@@ -988,7 +994,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
value = range(typeData.fields.length).map(function(i) { return value + '.f' + i });
}
for (var i = 0; i < typeData.fields.length; i++) {
- ret.push(makeSetValue(ptr, pos + typeData.flatIndexes[i], value[i], typeData.fields[i], noNeedFirst));
+ ret.push(makeSetValue(ptr, getFastValue(pos, '+', typeData.flatIndexes[i]), value[i], typeData.fields[i], noNeedFirst));
}
return ret.join('; ');
}
@@ -1145,6 +1151,13 @@ function makeCopyValues(dest, src, num, type, modifier, align, sep) {
}
}
+function makeHEAPView(which, start, end) {
+ // Assumes USE_TYPED_ARRAYS == 2
+ var size = parseInt(which.replace('U', '').replace('F', ''))/8;
+ var mod = size == 1 ? '' : ('>>' + log2(size));
+ return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
+}
+
var PLUS_MUL = set('+', '*');
var MUL_DIV = set('*', '/');
var PLUS_MINUS = set('+', '-');
@@ -1158,7 +1171,7 @@ function getFastValue(a, op, b, type) {
if (op == 'pow') {
return Math.pow(a, b).toString();
} else {
- return eval(a + op + b).toString();
+ return eval(a + op + '(' + b + ')').toString(); // parens protect us from "5 - -12" being seen as "5--12" which is "(5--)12"
}
}
if (op == 'pow') {
@@ -1204,7 +1217,7 @@ function getFastValue(a, op, b, type) {
return a;
}
}
- return a + op + b;
+ return '(' + a + ')' + op + '(' + b + ')';
}
function getFastValues(list, op, type) {
@@ -1251,7 +1264,7 @@ function makePointer(slab, pos, allocator, type) {
var evaled = typeof slab === 'string' ? eval(slab) : slab;
de = dedup(evaled);
if (de.length === 1 && de[0] === 0) {
- slab = evaled.length;
+ slab = types.length;
}
// TODO: if not all zeros, at least filter out items with type === 0. requires cleverness to know how to skip at runtime though. also
// be careful of structure padding
@@ -1288,17 +1301,11 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) {
}
} else { // USE_TYPED_ARRAYS == 2)
if (isPointerType(type)) type = 'i32'; // Hardcoded 32-bit
- var warn64 = function() {
- warnOnce('.ll contains i64 or double values. These 64-bit values are dangerous in USE_TYPED_ARRAYS == 2. ' +
- 'We store i64 as i32, and double as float. This can cause serious problems!');
- };
switch(type) {
case 'i1': case 'i8': return [unsigned ? 'HEAPU8' : 'HEAP8']; break;
case 'i16': return [unsigned ? 'HEAPU16' : 'HEAP16']; break;
- case 'i64': warn64();
- case 'i32': return [unsigned ? 'HEAPU32' : 'HEAP32']; break;
- case 'float': return ['HEAPF32']; break;
- case 'double': warn64(); return ['HEAPF32']; break;
+ case 'i32': case 'i64': return [unsigned ? 'HEAPU32' : 'HEAP32']; break;
+ case 'float': case 'double': return ['HEAPF32']; break;
default: {
throw 'what, exactly, can we do for unknown types in TA2?! ' + new Error().stack;
}
@@ -1315,28 +1322,35 @@ function finalizeLLVMFunctionCall(item, noIndexizeFunctions) {
// Warn about some types of casts, then fall through to the handling code below
var oldType = item.params[0].type;
var newType = item.type;
- if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType) &&
- countNormalArgs(oldType) != countNormalArgs(newType)) {
- warn('Casting a function pointer type to another with a different number of arguments. See more info in the source (grep for this text). ' +
- oldType + ' ==> ' + newType);
- // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
- // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
- // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
- // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
- // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
- // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
- // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
- // is easily possible, you place the two fields on the stack and call the function (you know to place the
- // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
- // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
- // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
- // corner case it is, does not appear to happen with nested structures!)
- //
- // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
- // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
- // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
- // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
- // is inefficient, and worth avoiding if you can).
+ if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType)) {
+ var oldCount = countNormalArgs(oldType);
+ var newCount = countNormalArgs(newType);
+ if (oldCount != newCount && oldCount && newCount) {
+ warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the compiler source');
+ if (VERBOSE) {
+ warnOnce('Casting a function pointer type to another with a different number of arguments: ' + oldType + ' vs. ' + newType + ', on ' + item.params[0].ident);
+ }
+ // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
+ // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
+ // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
+ // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
+ // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
+ // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
+ // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
+ // is easily possible, you place the two fields on the stack and call the function (you know to place the
+ // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
+ // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
+ // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
+ // corner case it is, does not appear to happen with nested structures!)
+ //
+ // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
+ // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
+ // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
+ // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
+ // is inefficient, and worth avoiding if you can).
+ //
+ // Note that removing all arguments is acceptable, as a vast to void ()*.
+ }
}
}
var temp = {
@@ -1412,7 +1426,7 @@ function handleOverflow(text, bits) {
// TODO: handle overflows of i64s
if (!bits) return text;
var correct = correctOverflows();
- warn(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits + ' at line ' + Framework.currItem.lineNum);
+ warnOnce(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits);
if (CHECK_OVERFLOWS) return 'CHECK_OVERFLOW(' + text + ', ' + bits + ', ' + Math.floor(correctSpecificOverflow() && !PGO) + (
PGO ? ', "' + Debugging.getIdentifier() + '"' : ''
) + ')';
@@ -1537,7 +1551,8 @@ function makeRounding(value, bits, signed, floatConversion) {
// TODO: handle roundings of i64s
assert(bits);
// C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that.
- if (bits <= 32 && signed) return '((' + value + ')|0)'; // This is fast and even correct, for all cases
+ if (bits <= 32 && signed) return '((' + value + ')&-1)'; // This is fast and even correct, for all cases. Note that it is the same
+ // as |0, but &-1 hints to the js optimizer that this is a rounding correction
// Do Math.floor, which is reasonably fast, if we either don't care, or if we can be sure
// the value is non-negative
if (!correctRoundings() || (!signed && !floatConversion)) return 'Math.floor(' + value + ')';
@@ -1561,6 +1576,8 @@ function isSignedOp(op, variant) {
}
var legalizedI64s = USE_TYPED_ARRAYS == 2; // We do not legalize globals, but do legalize function lines. This will be true in the latter case
+var preciseI64MathUsed = false; // Set to true if we actually use precise i64 math: If PRECISE_I64_MATH is set, and also such math is actually
+ // needed (+,-,*,/,% - we do not need it for bitops)
function processMathop(item) {
var op = item.op;
@@ -1617,6 +1634,11 @@ function processMathop(item) {
return result;
}
}
+ function i64PreciseOp(type, lastArg) {
+ preciseI64MathUsed = true;
+ return finish(['(i64Math.' + type + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 +
+ (lastArg ? ',' + lastArg : '') + '),i64Math.result[0])', 'i64Math.result[1]']);
+ }
switch (op) {
// basic integer ops
case 'or': {
@@ -1702,11 +1724,46 @@ function processMathop(item) {
case 'ptrtoint': return makeI64(idents[0], 0);
case 'inttoptr': return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32
// Dangerous, rounded operations. TODO: Fully emulate
- case 'add': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1])));
- case 'sub': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1])));
- case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's')));
- case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u')));
- case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u')));
+ case 'add': {
+ if (PRECISE_I64_MATH) {
+ return i64PreciseOp('add');
+ } else {
+ warnI64_1();
+ return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1])));
+ }
+ }
+ case 'sub': {
+ if (PRECISE_I64_MATH) {
+ return i64PreciseOp('subtract');
+ } else {
+ warnI64_1();
+ return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1])));
+ }
+ }
+ case 'sdiv': case 'udiv': {
+ if (PRECISE_I64_MATH) {
+ return i64PreciseOp('divide', op[0] === 'u');
+ } else {
+ warnI64_1();
+ return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's')));
+ }
+ }
+ case 'mul': {
+ if (PRECISE_I64_MATH) {
+ return i64PreciseOp('multiply');
+ } else {
+ warnI64_1();
+ return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u')));
+ }
+ }
+ case 'urem': case 'srem': {
+ if (PRECISE_I64_MATH) {
+ return i64PreciseOp('modulo', op[0] === 'u');
+ } else {
+ warnI64_1();
+ return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u')));
+ }
+ }
case 'bitcast': {
// Pointers are not 64-bit, so there is really only one possible type of bitcast here, int to float or vice versa
assert(USE_TYPED_ARRAYS == 2, 'Can only bitcast ints <-> floats with typed arrays mode 2');
@@ -1782,6 +1839,7 @@ function processMathop(item) {
case 'fsub': return getFastValue(idents[0], '-', idents[1], item.type);
case 'fdiv': return getFastValue(idents[0], '/', idents[1], item.type);
case 'fmul': return getFastValue(idents[0], '*', idents[1], item.type);
+ case 'frem': return getFastValue(idents[0], '%', idents[1], item.type);
case 'uitofp': case 'sitofp': return idents[0];
case 'fptoui': case 'fptosi': return makeRounding(idents[0], bitsLeft, op === 'fptosi', true);
diff --git a/src/postamble.js b/src/postamble.js
index 4a2fbf60..10ac1888 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -32,29 +32,61 @@ Module.callMain = function callMain(args) {
function run(args) {
args = args || Module['arguments'];
- initRuntime();
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ while (Module['preRun'].length > 0) {
+ Module['preRun'].pop()();
+ if (runDependencies > 0) {
+ // preRun added a dependency, run will be called later
+ return 0;
+ }
+ }
+ }
- var ret = null;
- if (Module['_main']) {
- ret = Module.callMain(args);
- if (!Module['noExitRuntime']) {
- exitRuntime();
+ function doRun() {
+ var ret = 0;
+ if (Module['_main']) {
+ preMain();
+ ret = Module.callMain(args);
+ if (!Module['noExitRuntime']) {
+ exitRuntime();
+ }
+ }
+ if (Module['postRun']) {
+ if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
+ while (Module['postRun'].length > 0) {
+ Module['postRun'].pop()();
+ }
}
+ return ret;
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ return 0;
+ } else {
+ return doRun();
}
- return ret;
}
Module['run'] = run;
// {{PRE_RUN_ADDITIONS}}
-if (Module['preRun']) {
- Module['preRun']();
-}
+initRuntime();
#if INVOKE_RUN
#else
addRunDependency();
#endif
+if (Module['noInitialRun']) {
+ addRunDependency();
+}
if (runDependencies == 0) {
var ret = run();
@@ -65,7 +97,3 @@ if (runDependencies == 0) {
// {{POST_RUN_ADDITIONS}}
-if (Module['postRun']) {
- Module['postRun']();
-}
-
diff --git a/src/preamble.js b/src/preamble.js
index db092045..ae00b796 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -76,7 +76,7 @@ function SAFE_HEAP_STORE(dest, value, type, ignore) {
Module.print('SAFE_HEAP store: ' + [dest, type, value, ignore]);
#endif
- if (!ignore && !value && value !== 0 && value !== false && !isNaN(value)) { // false can be the result of a mathop comparator; NaN can be the result of a math function
+ if (!ignore && !value && (value === null || value === undefined)) {
throw('Warning: Writing an invalid value of ' + JSON.stringify(value) + ' at ' + dest + ' :: ' + new Error().stack + '\n');
}
SAFE_HEAP_ACCESS(dest, type, true, ignore);
@@ -104,7 +104,7 @@ function SAFE_HEAP_STORE(dest, value, type, ignore) {
}
function SAFE_HEAP_LOAD(dest, type, unsigned, ignore) {
- SAFE_HEAP_ACCESS(dest, type, ignore);
+ SAFE_HEAP_ACCESS(dest, type, false, ignore);
#if SAFE_HEAP_LOG
Module.print('SAFE_HEAP load: ' + [dest, type, getValue(dest, type, 1), ignore]);
@@ -315,18 +315,27 @@ var globalScope = this;
// -s EXPORTED_FUNCTIONS='["_func1","_func2"]'
//
// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
-// @param returnType The return type of the function, one of the JS types 'number' or 'string' (use 'number' for any C pointer).
-// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType.
+// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
+// 'array' for JavaScript arrays and typed arrays).
+// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
+// except that 'array' is not possible (there is no way for us to know the length of the array)
// @param args An array of the arguments to the function, as native JS values (as in returnType)
// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
// @return The return value, as a native JS value (as in returnType)
function ccall(ident, returnType, argTypes, args) {
+ var stack = 0;
function toC(value, type) {
if (type == 'string') {
- var ret = STACKTOP;
- Runtime.stackAlloc(value.length+1);
+ if (value === null || value === undefined || value === 0) return 0; // null string
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length+1);
writeStringToMemory(value, ret);
return ret;
+ } else if (type == 'array') {
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length);
+ writeArrayToMemory(value, ret);
+ return ret;
}
return value;
}
@@ -334,6 +343,7 @@ function ccall(ident, returnType, argTypes, args) {
if (type == 'string') {
return Pointer_stringify(value);
}
+ assert(type != 'array');
return value;
}
try {
@@ -348,7 +358,9 @@ function ccall(ident, returnType, argTypes, args) {
var cArgs = args ? args.map(function(arg) {
return toC(arg, argTypes[i++]);
}) : [];
- return fromC(func.apply(null, cArgs), returnType);
+ var ret = fromC(func.apply(null, cArgs), returnType);
+ if (stack) Runtime.stackRestore(stack);
+ return ret;
}
Module["ccall"] = ccall;
@@ -365,6 +377,7 @@ function cwrap(ident, returnType, argTypes) {
return ccall(ident, returnType, argTypes, Array.prototype.slice.call(arguments));
}
}
+Module["cwrap"] = cwrap;
// Sets a value in memory in a dynamic way at run-time. Uses the
// type data. This is the same as makeSetValue, except that
@@ -693,12 +706,15 @@ function callRuntimeCallbacks(callbacks) {
}
var __ATINIT__ = []; // functions called during startup
+var __ATMAIN__ = []; // functions called when main() is to be run
var __ATEXIT__ = []; // functions called during shutdown
function initRuntime() {
callRuntimeCallbacks(__ATINIT__);
}
-
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
function exitRuntime() {
callRuntimeCallbacks(__ATEXIT__);
@@ -706,37 +722,6 @@ function exitRuntime() {
CorrectionsMonitor.print();
}
-
-// Copies a list of num items on the HEAP into a
-// a normal JavaScript array of numbers
-function Array_copy(ptr, num) {
-#if USE_TYPED_ARRAYS == 1
- // TODO: In the SAFE_HEAP case, do some reading here, for debugging purposes - currently this is an 'unnoticed read'.
- return Array.prototype.slice.call(IHEAP.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view'
- // Consider making a typed array here, for speed?
-#endif
-#if USE_TYPED_ARRAYS == 2
- return Array.prototype.slice.call(HEAP8.subarray(ptr, ptr+num)); // Make a normal array out of the typed 'view'
- // Consider making a typed array here, for speed?
-#endif
- return HEAP.slice(ptr, ptr+num);
-}
-Module['Array_copy'] = Array_copy;
-
-#if USE_TYPED_ARRAYS
-// Copies a list of num items on the HEAP into a
-// JavaScript typed array.
-function TypedArray_copy(ptr, num) {
- // TODO: optimize this!
- var arr = new Uint8Array(num);
- for (var i = 0; i < num; ++i) {
- arr[i] = {{{ makeGetValue('ptr', 'i', 'i8') }}};
- }
- return arr.buffer;
-}
-Module['TypedArray_copy'] = TypedArray_copy;
-#endif
-
function String_len(ptr) {
var i = 0;
while ({{{ makeGetValue('ptr', 'i', 'i8') }}}) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds
@@ -744,26 +729,18 @@ function String_len(ptr) {
}
Module['String_len'] = String_len;
-// Copies a C-style string, terminated by a zero, from the HEAP into
-// a normal JavaScript array of numbers
-function String_copy(ptr, addZero) {
- var len = String_len(ptr);
- if (addZero) len++;
- var ret = Array_copy(ptr, len);
- if (addZero) ret[len-1] = 0;
- return ret;
-}
-Module['String_copy'] = String_copy;
-
// Tools
// This processes a JS string into a C-line array of numbers, 0-terminated.
// For LLVM-originating strings, see parser.js:parseLLVMString function
-function intArrayFromString(stringy, dontAddNull) {
+function intArrayFromString(stringy, dontAddNull, length /* optional */) {
var ret = [];
var t;
var i = 0;
- while (i < stringy.length) {
+ if (length === undefined) {
+ length = stringy.length;
+ }
+ while (i < length) {
var chr = stringy.charCodeAt(i);
if (chr > 0xFF) {
#if ASSERTIONS
@@ -817,6 +794,13 @@ function writeStringToMemory(string, buffer, dontAddNull) {
}
Module['writeStringToMemory'] = writeStringToMemory;
+function writeArrayToMemory(array, buffer) {
+ for (var i = 0; i < array.length; i++) {
+ {{{ makeSetValue('buffer', 'i', 'array[i]', 'i8') }}};
+ }
+}
+Module['writeArrayToMemory'] = writeArrayToMemory;
+
var STRING_TABLE = [];
{{{ unSign }}}
@@ -824,8 +808,11 @@ var STRING_TABLE = [];
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
-// decrement it. Incrementing must happen in Module.preRun
-// or PRE_RUN_ADDITIONS (used by emcc to add file preloading).
+// decrement it. Incrementing must happen in a place like
+// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
+// Note that you can add dependencies in preRun, even though
+// it happens right before run - run will be postponed until
+// the dependencies are met.
var runDependencies = 0;
function addRunDependency() {
runDependencies++;
@@ -833,6 +820,7 @@ function addRunDependency() {
Module['monitorRunDependencies'](runDependencies);
}
}
+Module['addRunDependency'] = addRunDependency;
function removeRunDependency() {
runDependencies--;
if (Module['monitorRunDependencies']) {
@@ -840,10 +828,7 @@ function removeRunDependency() {
}
if (runDependencies == 0) run();
}
-
-// Preloading
-
-var preloadedImages = {}; // maps url to image data
+Module['removeRunDependency'] = removeRunDependency;
// === Body ===
diff --git a/src/runtime.js b/src/runtime.js
index 852d08d8..1f8a618f 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -306,7 +306,85 @@ var Runtime = {
});
}
return ret;
+ },
+
+ addFunction: function(func) {
+ var ret = FUNCTION_TABLE.length;
+ FUNCTION_TABLE.push(func);
+ FUNCTION_TABLE.push(0);
+ return ret;
+ },
+
+ warnOnce: function(text) {
+ if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+ if (!Runtime.warnOnce.shown[text]) {
+ Runtime.warnOnce.shown[text] = 1;
+ Module.printErr(text);
+ }
+ },
+
+ funcWrappers: {},
+
+ getFuncWrapper: function(func) {
+ if (!Runtime.funcWrappers[func]) {
+ Runtime.funcWrappers[func] = function() {
+ FUNCTION_TABLE[func].apply(null, arguments);
+ };
+ }
+ return Runtime.funcWrappers[func];
+ },
+
+#if RUNTIME_DEBUG
+ debug: true, // Switch to false at runtime to disable logging at the right times
+
+ printObjectList: [],
+
+ prettyPrint: function(arg) {
+ if (typeof arg == 'undefined') return '!UNDEFINED!';
+ if (typeof arg == 'boolean') arg = arg + 0;
+ if (!arg) return arg;
+ var index = Runtime.printObjectList.indexOf(arg);
+ if (index >= 0) return '<' + arg + '|' + index + '>';
+ if (arg.toString() == '[object HTMLImageElement]') {
+ return arg + '\n\n';
+ }
+ if (arg.byteLength) {
+ return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that
+ var buf = new ArrayBuffer(32);
+ var i8buf = new Int8Array(buf);
+ var i16buf = new Int16Array(buf);
+ var f32buf = new Float32Array(buf);
+ switch(arg.toString()) {
+ case '[object Uint8Array]':
+ i8buf.set(arg.subarray(0, 32));
+ break;
+ case '[object Float32Array]':
+ f32buf.set(arg.subarray(0, 5));
+ break;
+ case '[object Uint16Array]':
+ i16buf.set(arg.subarray(0, 16));
+ break;
+ default:
+ alert('unknown array for debugging: ' + arg);
+ throw 'see alert';
+ }
+ var ret = '{' + arg.byteLength + ':\n';
+ var arr = Array.prototype.slice.call(i8buf);
+ ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n';
+ arr = Array.prototype.slice.call(f32buf, 0, 8);
+ ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}';
+ return ret;
+ }
+ if (typeof arg == 'object') {
+ Runtime.printObjectList.push(arg);
+ return '<' + arg + '|' + (Runtime.printObjectList.length-1) + '>';
+ }
+ if (typeof arg == 'number') {
+ if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')';
+ }
+ return arg;
}
+#endif
};
Runtime.stackAlloc = unInline('stackAlloc', ['size']);
diff --git a/src/settings.js b/src/settings.js
index bb4d0f27..16c28529 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -26,6 +26,7 @@ var ASSERTIONS = 1; // Whether we should add runtime assertions, for example to
// exceed it's size, whether all allocations (stack and static) are
// of positive size, etc., whether we should throw if we encounter a bad __label__, i.e.,
// if code flow runs into a fault
+var VERBOSE = 0; // When set to 1, will generate more verbose output during compilation.
var INVOKE_RUN = 1; // Whether we will call run(). Disable if you embed the generated
// code in your own, and will call run() yourself at the right time
@@ -67,6 +68,8 @@ var DOUBLE_MODE = 1; // How to load and store 64-bit doubles. Without typed arra
// then load it aligned, and that load-store will make JS engines alter it if it is being
// stored to a typed array for security reasons. That will 'fix' the number from being a
// NaN or an infinite number.
+var PRECISE_I64_MATH = 1; // If enabled, i64 addition etc. is emulated - which is slow but precise. If disabled,
+ // we use the 'double trick' which is fast but incurs rounding at high values.
var CLOSURE_ANNOTATIONS = 0; // If set, the generated code will be annotated for the closure
// compiler. This potentially lets closure optimize the code better.
@@ -98,7 +101,14 @@ var SAFE_HEAP_LOG = 0; // Log out all SAFE_HEAP operations
var LABEL_DEBUG = 0; // Print out labels and functions as we enter them
var EXCEPTION_DEBUG = 1; // Print out exceptions in emscriptened code
-var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js)
+
+var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js). You can also unset
+ // Runtime.debug at runtime for logging to cease, and can set it when you
+ // want it back. A simple way to set it in C++ is
+ // emscripten_run_script("Runtime.debug = ...;");
+var GL_DEBUG = 0; // Print out all calls into WebGL. As with LIBRARY_DEBUG, you can set a runtime
+ // option, in this case GL.debug.
+
var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catch exceptions. If the code you
// are compiling does not actually rely on catching exceptions (but the
// compiler generates code for it, maybe because of stdlibc++ stuff),
@@ -136,6 +146,9 @@ var CORRECT_OVERFLOWS = 1; // Experimental code that tries to prevent unexpected
var CORRECT_ROUNDINGS = 1; // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no direct way to do that:
// Math.floor is to negative, ceil to positive. With CORRECT_ROUNDINGS,
// we will do slow but correct C rounding operations.
+var FS_LOG = 0; // Log all FS operations. This is especially helpful when you're porting
+ // a new project and want to see a list of file system operations happening
+ // so that you can create a virtual file system with all of the required files.
var PGO = 0; // Profile-guided optimization.
// When run with the CHECK_* options, will not fail on errors. Instead, will
@@ -201,6 +214,16 @@ var FAKE_X86_FP80 = 1; // Replaces x86_fp80 with double. This loses precision. I
// if you can, to get the original source code to build without x86_fp80
// (which is nonportable anyhow).
+var GC_SUPPORT = 1; // Enables GC, see gc.h (this does not add overhead, so it is on by default)
+
+var WARN_ON_UNDEFINED_SYMBOLS = 0; // If set to 1, we will warn on any undefined symbols that
+ // are not resolved by the library_*.js files. We by default
+ // do not warn because (1) it is normal in large projects to
+ // not implement everything, when you know what is not
+ // going to actually be called (and don't want to mess with
+ // the existing buildsystem), and (2) functions might be
+ // implemented later on, say in --pre-js
+
// Compiler debugging options
var DEBUG_TAGS_SHOWING = [];
// Some useful items:
diff --git a/src/shell.html b/src/shell.html
index 2f83f9f9..c04ae84b 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -1,39 +1,79 @@
-<html>
+<!doctype html>
+<html lang="en-us">
<head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Emscripten-Generated Code</title>
+ <style>
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ canvas.emscripten { border: 1px solid black; }
+ textarea.emscripten { font-family: monospace; width: 80%; }
+ div.emscripten { text-align: center; }
+ </style>
+ </head>
<body>
- <center>
- <canvas id='canvas' width='256' height='256'></canvas>
- </center>
- <hr>
- <div id='output'></div>
- <hr>
- <center><div id='status'></div></center>
+ <hr/>
+ <div class="emscripten" id="status">Downloading...</div>
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <hr/>
+ <div class="emscripten"><input type="button" value="fullscreen" onclick="Module.requestFullScreen()"></div>
+ <hr/>
+ <textarea class="emscripten" id="output" rows="8"></textarea>
<hr>
<script type='text/javascript'>
// connect to canvas
var Module = {
+ preRun: [],
+ postRun: [],
print: (function() {
var element = document.getElementById('output');
+ element.value = ''; // clear browser cache
return function(text) {
- text = text.replace(/&/g, "&amp;");
- text = text.replace(/</g, "&lt;");
- text = text.replace(/>/g, "&gt;");
- text = text.replace('\n', '<br>', 'g');
- element.innerHTML += text + '<br>';
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&amp;");
+ //text = text.replace(/</g, "&lt;");
+ //text = text.replace(/>/g, "&gt;");
+ //text = text.replace('\n', '<br>', 'g');
+ element.value += text + "\n";
+ element.scrollTop = 99999; // focus on bottom
};
})(),
+ printErr: function(text) {
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\n'); // fast, straight to the real console
+ } else {
+ console.log(text);
+ }
+ },
canvas: document.getElementById('canvas'),
+ setStatus: function(text) {
+ if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ document.getElementById('status').innerHTML = text;
+ if (text) {
+ var counter = 0;
+ Module.setStatus.interval = setInterval(function() {
+ counter++;
+ counter %= 3;
+ var dots = ' ';
+ for (var i = 0; i < counter; i++) dots += '.';
+ dots += '*';
+ for (var i = counter; i < 2; i++) dots += '.';
+ document.getElementById('status').innerHTML = text.replace('...', dots);
+ }, 300);
+ }
+ },
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
- document.getElementById('status').innerHTML = left ? 'Downloading files: ' + (this.totalDependencies-left) + '/' + this.totalDependencies :
- 'All downloads complete.';
+ Module.setStatus(left ? 'Preparing: ' + (this.totalDependencies-left) + '/' + this.totalDependencies + '...' : 'All downloads complete.');
}
};
+ Module.setStatus('Downloading...');
+ </script>
+ <script type='text/javascript'>
{{{ SCRIPT_CODE }}}
+
</script>
</body>
</html>
-
diff --git a/src/shell.js b/src/shell.js
index 5b6419c0..891a6328 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -24,11 +24,14 @@ if (ENVIRONMENT_IS_NODE) {
};
var nodeFS = require('fs');
+ var nodePath = require('path');
Module['read'] = function(filename) {
+ filename = nodePath['normalize'](filename);
var ret = nodeFS['readFileSync'](filename).toString();
- if (!ret && filename[0] != '/') {
- filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename;
+ // The path is absolute if the normalized version is the same as the resolved.
+ if (!ret && filename != nodePath['resolve'](filename)) {
+ filename = path.join(__dirname, '..', 'src', filename);
ret = nodeFS['readFileSync'](filename).toString();
}
return ret;
@@ -38,11 +41,12 @@ if (ENVIRONMENT_IS_NODE) {
globalEval(read(f));
};
- Module['arguments'] = process['argv'].slice(2);
-
+ if (!Module['arguments']) {
+ Module['arguments'] = process['argv'].slice(2);
+ }
} else if (ENVIRONMENT_IS_SHELL) {
Module['print'] = print;
- Module['printErr'] = printErr;
+ if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm
// Polyfill over SpiderMonkey/V8 differences
if (typeof read != 'undefined') {
@@ -51,12 +55,13 @@ if (ENVIRONMENT_IS_NODE) {
Module['read'] = function(f) { snarf(f) };
}
- if (typeof scriptArgs != 'undefined') {
- Module['arguments'] = scriptArgs;
- } else if (typeof arguments != 'undefined') {
- Module['arguments'] = arguments;
+ if (!Module['arguments']) {
+ if (typeof scriptArgs != 'undefined') {
+ Module['arguments'] = scriptArgs;
+ } else if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
}
-
} else if (ENVIRONMENT_IS_WEB) {
if (!Module['print']) {
Module['print'] = function(x) {
@@ -77,8 +82,10 @@ if (ENVIRONMENT_IS_NODE) {
return xhr.responseText;
};
- if (typeof arguments != 'undefined') {
- Module['arguments'] = arguments;
+ if (!Module['arguments']) {
+ if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
}
} else if (ENVIRONMENT_IS_WORKER) {
// We can do very little here...
@@ -97,17 +104,25 @@ if (!Module['load'] == 'undefined' && Module['read']) {
globalEval(Module['read'](f));
};
}
-if (!Module['printErr']) {
- Module['printErr'] = function(){};
-}
if (!Module['print']) {
- Module['print'] = Module['printErr'];
+ Module['print'] = function(){};
+}
+if (!Module['printErr']) {
+ Module['printErr'] = Module['print'];
}
if (!Module['arguments']) {
Module['arguments'] = [];
}
// *** Environment setup code ***
+// Closure helpers
+Module.print = Module['print'];
+Module.printErr = Module['printErr'];
+
+// Callbacks
+if (!Module['preRun']) Module['preRun'] = [];
+if (!Module['postRun']) Module['postRun'] = [];
+
{{BODY}}
// {{MODULE_ADDITIONS}}
diff --git a/src/utility.js b/src/utility.js
index 31eff100..42e8ede4 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -40,7 +40,7 @@ function dumpKeys(item) {
function assertEq(a, b) {
if (a !== b) {
- print('Stack: ' + new Error().stack);
+ printErr('Stack: ' + new Error().stack);
throw 'Should have been equal: ' + a + ' : ' + b;
}
return false;
@@ -50,7 +50,7 @@ function assertTrue(a, msg) {
if (!a) {
msg = 'Assertion failed: ' + msg;
print(msg);
- print('Stack: ' + new Error().stack);
+ printErr('Stack: ' + new Error().stack);
throw msg;
}
}
@@ -62,15 +62,21 @@ function warn(a, msg) {
a = false;
}
if (!a) {
- dprint('Warning: ' + msg);
+ printErr('Warning: ' + msg);
}
}
-function warnOnce(msg) {
- if (!warnOnce.msgs) warnOnce.msgs = {};
- if (msg in warnOnce.msgs) return;
- warnOnce.msgs[msg] = true;
- dprint('Warning: ' + msg);
+function warnOnce(a, msg) {
+ if (!msg) {
+ msg = a;
+ a = false;
+ }
+ if (!a) {
+ if (!warnOnce.msgs) warnOnce.msgs = {};
+ if (msg in warnOnce.msgs) return;
+ warnOnce.msgs[msg] = true;
+ printErr('Warning: ' + msg);
+ }
}
function dedup(items, ident) {
diff --git a/system/include/SDL/SDL_keycode.h b/system/include/SDL/SDL_keycode.h
index 5be1f715..472ca28e 100644
--- a/system/include/SDL/SDL_keycode.h
+++ b/system/include/SDL/SDL_keycode.h
@@ -41,7 +41,9 @@
*/
typedef Sint32 SDL_Keycode;
-#define SDLK_SCANCODE_MASK (1<<30)
+// XXX Emscripten: We use a mask of 10, which is closer to old SDL, and gives
+// a better chance of SDL 1.X apps working
+#define SDLK_SCANCODE_MASK (1<<10)
#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
enum
diff --git a/system/include/X11/X.h b/system/include/X11/X.h
new file mode 100644
index 00000000..5cf695d7
--- /dev/null
+++ b/system/include/X11/X.h
@@ -0,0 +1,717 @@
+/* Definitions for the X window system likely to be used by applications */
+
+#ifndef X_H
+#define X_H
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#define X_PROTOCOL 11 /* current protocol version */
+#define X_PROTOCOL_REVISION 0 /* current minor version */
+
+/* Resources */
+
+/*
+ * _XSERVER64 must ONLY be defined when compiling X server sources on
+ * systems where unsigned long is not 32 bits, must NOT be used in
+ * client or library code.
+ */
+#ifndef _XSERVER64
+# ifndef _XTYPEDEF_XID
+# define _XTYPEDEF_XID
+typedef unsigned long XID;
+# endif
+# ifndef _XTYPEDEF_MASK
+# define _XTYPEDEF_MASK
+typedef unsigned long Mask;
+# endif
+# ifndef _XTYPEDEF_ATOM
+# define _XTYPEDEF_ATOM
+typedef unsigned long Atom; /* Also in Xdefs.h */
+# endif
+typedef unsigned long VisualID;
+typedef unsigned long Time;
+#else
+# include <X11/Xmd.h>
+# ifndef _XTYPEDEF_XID
+# define _XTYPEDEF_XID
+typedef CARD32 XID;
+# endif
+# ifndef _XTYPEDEF_MASK
+# define _XTYPEDEF_MASK
+typedef CARD32 Mask;
+# endif
+# ifndef _XTYPEDEF_ATOM
+# define _XTYPEDEF_ATOM
+typedef CARD32 Atom;
+# endif
+typedef CARD32 VisualID;
+typedef CARD32 Time;
+#endif
+
+typedef XID Window;
+typedef XID Drawable;
+#ifndef _XTYPEDEF_FONT
+# define _XTYPEDEF_FONT
+typedef XID Font;
+#endif
+typedef XID Pixmap;
+typedef XID Cursor;
+typedef XID Colormap;
+typedef XID GContext;
+typedef XID KeySym;
+
+typedef unsigned char KeyCode;
+
+/*****************************************************************
+ * RESERVED RESOURCE AND CONSTANT DEFINITIONS
+ *****************************************************************/
+
+#ifndef None
+#define None 0L /* universal null resource or null atom */
+#endif
+
+#define ParentRelative 1L /* background pixmap in CreateWindow
+ and ChangeWindowAttributes */
+
+#define CopyFromParent 0L /* border pixmap in CreateWindow
+ and ChangeWindowAttributes
+ special VisualID and special window
+ class passed to CreateWindow */
+
+#define PointerWindow 0L /* destination window in SendEvent */
+#define InputFocus 1L /* destination window in SendEvent */
+
+#define PointerRoot 1L /* focus window in SetInputFocus */
+
+#define AnyPropertyType 0L /* special Atom, passed to GetProperty */
+
+#define AnyKey 0L /* special Key Code, passed to GrabKey */
+
+#define AnyButton 0L /* special Button Code, passed to GrabButton */
+
+#define AllTemporary 0L /* special Resource ID passed to KillClient */
+
+#define CurrentTime 0L /* special Time */
+
+#define NoSymbol 0L /* special KeySym */
+
+/*****************************************************************
+ * EVENT DEFINITIONS
+ *****************************************************************/
+
+/* Input Event Masks. Used as event-mask window attribute and as arguments
+ to Grab requests. Not to be confused with event names. */
+
+#define NoEventMask 0L
+#define KeyPressMask (1L<<0)
+#define KeyReleaseMask (1L<<1)
+#define ButtonPressMask (1L<<2)
+#define ButtonReleaseMask (1L<<3)
+#define EnterWindowMask (1L<<4)
+#define LeaveWindowMask (1L<<5)
+#define PointerMotionMask (1L<<6)
+#define PointerMotionHintMask (1L<<7)
+#define Button1MotionMask (1L<<8)
+#define Button2MotionMask (1L<<9)
+#define Button3MotionMask (1L<<10)
+#define Button4MotionMask (1L<<11)
+#define Button5MotionMask (1L<<12)
+#define ButtonMotionMask (1L<<13)
+#define KeymapStateMask (1L<<14)
+#define ExposureMask (1L<<15)
+#define VisibilityChangeMask (1L<<16)
+#define StructureNotifyMask (1L<<17)
+#define ResizeRedirectMask (1L<<18)
+#define SubstructureNotifyMask (1L<<19)
+#define SubstructureRedirectMask (1L<<20)
+#define FocusChangeMask (1L<<21)
+#define PropertyChangeMask (1L<<22)
+#define ColormapChangeMask (1L<<23)
+#define OwnerGrabButtonMask (1L<<24)
+
+/* Event names. Used in "type" field in XEvent structures. Not to be
+confused with event masks above. They start from 2 because 0 and 1
+are reserved in the protocol for errors and replies. */
+
+#define KeyPress 2
+#define KeyRelease 3
+#define ButtonPress 4
+#define ButtonRelease 5
+#define MotionNotify 6
+#define EnterNotify 7
+#define LeaveNotify 8
+#define FocusIn 9
+#define FocusOut 10
+#define KeymapNotify 11
+#define Expose 12
+#define GraphicsExpose 13
+#define NoExpose 14
+#define VisibilityNotify 15
+#define CreateNotify 16
+#define DestroyNotify 17
+#define UnmapNotify 18
+#define MapNotify 19
+#define MapRequest 20
+#define ReparentNotify 21
+#define ConfigureNotify 22
+#define ConfigureRequest 23
+#define GravityNotify 24
+#define ResizeRequest 25
+#define CirculateNotify 26
+#define CirculateRequest 27
+#define PropertyNotify 28
+#define SelectionClear 29
+#define SelectionRequest 30
+#define SelectionNotify 31
+#define ColormapNotify 32
+#define ClientMessage 33
+#define MappingNotify 34
+#define GenericEvent 35
+#define LASTEvent 36 /* must be bigger than any event # */
+
+
+/* Key masks. Used as modifiers to GrabButton and GrabKey, results of QueryPointer,
+ state in various key-, mouse-, and button-related events. */
+
+#define ShiftMask (1<<0)
+#define LockMask (1<<1)
+#define ControlMask (1<<2)
+#define Mod1Mask (1<<3)
+#define Mod2Mask (1<<4)
+#define Mod3Mask (1<<5)
+#define Mod4Mask (1<<6)
+#define Mod5Mask (1<<7)
+
+/* modifier names. Used to build a SetModifierMapping request or
+ to read a GetModifierMapping request. These correspond to the
+ masks defined above. */
+#define ShiftMapIndex 0
+#define LockMapIndex 1
+#define ControlMapIndex 2
+#define Mod1MapIndex 3
+#define Mod2MapIndex 4
+#define Mod3MapIndex 5
+#define Mod4MapIndex 6
+#define Mod5MapIndex 7
+
+
+/* button masks. Used in same manner as Key masks above. Not to be confused
+ with button names below. */
+
+#define Button1Mask (1<<8)
+#define Button2Mask (1<<9)
+#define Button3Mask (1<<10)
+#define Button4Mask (1<<11)
+#define Button5Mask (1<<12)
+
+#define AnyModifier (1<<15) /* used in GrabButton, GrabKey */
+
+
+/* button names. Used as arguments to GrabButton and as detail in ButtonPress
+ and ButtonRelease events. Not to be confused with button masks above.
+ Note that 0 is already defined above as "AnyButton". */
+
+#define Button1 1
+#define Button2 2
+#define Button3 3
+#define Button4 4
+#define Button5 5
+
+/* Notify modes */
+
+#define NotifyNormal 0
+#define NotifyGrab 1
+#define NotifyUngrab 2
+#define NotifyWhileGrabbed 3
+
+#define NotifyHint 1 /* for MotionNotify events */
+
+/* Notify detail */
+
+#define NotifyAncestor 0
+#define NotifyVirtual 1
+#define NotifyInferior 2
+#define NotifyNonlinear 3
+#define NotifyNonlinearVirtual 4
+#define NotifyPointer 5
+#define NotifyPointerRoot 6
+#define NotifyDetailNone 7
+
+/* Visibility notify */
+
+#define VisibilityUnobscured 0
+#define VisibilityPartiallyObscured 1
+#define VisibilityFullyObscured 2
+
+/* Circulation request */
+
+#define PlaceOnTop 0
+#define PlaceOnBottom 1
+
+/* protocol families */
+
+#define FamilyInternet 0 /* IPv4 */
+#define FamilyDECnet 1
+#define FamilyChaos 2
+#define FamilyInternet6 6 /* IPv6 */
+
+/* authentication families not tied to a specific protocol */
+#define FamilyServerInterpreted 5
+
+/* Property notification */
+
+#define PropertyNewValue 0
+#define PropertyDelete 1
+
+/* Color Map notification */
+
+#define ColormapUninstalled 0
+#define ColormapInstalled 1
+
+/* GrabPointer, GrabButton, GrabKeyboard, GrabKey Modes */
+
+#define GrabModeSync 0
+#define GrabModeAsync 1
+
+/* GrabPointer, GrabKeyboard reply status */
+
+#define GrabSuccess 0
+#define AlreadyGrabbed 1
+#define GrabInvalidTime 2
+#define GrabNotViewable 3
+#define GrabFrozen 4
+
+/* AllowEvents modes */
+
+#define AsyncPointer 0
+#define SyncPointer 1
+#define ReplayPointer 2
+#define AsyncKeyboard 3
+#define SyncKeyboard 4
+#define ReplayKeyboard 5
+#define AsyncBoth 6
+#define SyncBoth 7
+
+/* Used in SetInputFocus, GetInputFocus */
+
+#define RevertToNone (int)None
+#define RevertToPointerRoot (int)PointerRoot
+#define RevertToParent 2
+
+/*****************************************************************
+ * ERROR CODES
+ *****************************************************************/
+
+#define Success 0 /* everything's okay */
+#define BadRequest 1 /* bad request code */
+#define BadValue 2 /* int parameter out of range */
+#define BadWindow 3 /* parameter not a Window */
+#define BadPixmap 4 /* parameter not a Pixmap */
+#define BadAtom 5 /* parameter not an Atom */
+#define BadCursor 6 /* parameter not a Cursor */
+#define BadFont 7 /* parameter not a Font */
+#define BadMatch 8 /* parameter mismatch */
+#define BadDrawable 9 /* parameter not a Pixmap or Window */
+#define BadAccess 10 /* depending on context:
+ - key/button already grabbed
+ - attempt to free an illegal
+ cmap entry
+ - attempt to store into a read-only
+ color map entry.
+ - attempt to modify the access control
+ list from other than the local host.
+ */
+#define BadAlloc 11 /* insufficient resources */
+#define BadColor 12 /* no such colormap */
+#define BadGC 13 /* parameter not a GC */
+#define BadIDChoice 14 /* choice not in range or already used */
+#define BadName 15 /* font or color name doesn't exist */
+#define BadLength 16 /* Request length incorrect */
+#define BadImplementation 17 /* server is defective */
+
+#define FirstExtensionError 128
+#define LastExtensionError 255
+
+/*****************************************************************
+ * WINDOW DEFINITIONS
+ *****************************************************************/
+
+/* Window classes used by CreateWindow */
+/* Note that CopyFromParent is already defined as 0 above */
+
+#define InputOutput 1
+#define InputOnly 2
+
+/* Window attributes for CreateWindow and ChangeWindowAttributes */
+
+#define CWBackPixmap (1L<<0)
+#define CWBackPixel (1L<<1)
+#define CWBorderPixmap (1L<<2)
+#define CWBorderPixel (1L<<3)
+#define CWBitGravity (1L<<4)
+#define CWWinGravity (1L<<5)
+#define CWBackingStore (1L<<6)
+#define CWBackingPlanes (1L<<7)
+#define CWBackingPixel (1L<<8)
+#define CWOverrideRedirect (1L<<9)
+#define CWSaveUnder (1L<<10)
+#define CWEventMask (1L<<11)
+#define CWDontPropagate (1L<<12)
+#define CWColormap (1L<<13)
+#define CWCursor (1L<<14)
+
+/* ConfigureWindow structure */
+
+#define CWX (1<<0)
+#define CWY (1<<1)
+#define CWWidth (1<<2)
+#define CWHeight (1<<3)
+#define CWBorderWidth (1<<4)
+#define CWSibling (1<<5)
+#define CWStackMode (1<<6)
+
+
+/* Bit Gravity */
+
+#define ForgetGravity 0
+#define NorthWestGravity 1
+#define NorthGravity 2
+#define NorthEastGravity 3
+#define WestGravity 4
+#define CenterGravity 5
+#define EastGravity 6
+#define SouthWestGravity 7
+#define SouthGravity 8
+#define SouthEastGravity 9
+#define StaticGravity 10
+
+/* Window gravity + bit gravity above */
+
+#define UnmapGravity 0
+
+/* Used in CreateWindow for backing-store hint */
+
+#define NotUseful 0
+#define WhenMapped 1
+#define Always 2
+
+/* Used in GetWindowAttributes reply */
+
+#define IsUnmapped 0
+#define IsUnviewable 1
+#define IsViewable 2
+
+/* Used in ChangeSaveSet */
+
+#define SetModeInsert 0
+#define SetModeDelete 1
+
+/* Used in ChangeCloseDownMode */
+
+#define DestroyAll 0
+#define RetainPermanent 1
+#define RetainTemporary 2
+
+/* Window stacking method (in configureWindow) */
+
+#define Above 0
+#define Below 1
+#define TopIf 2
+#define BottomIf 3
+#define Opposite 4
+
+/* Circulation direction */
+
+#define RaiseLowest 0
+#define LowerHighest 1
+
+/* Property modes */
+
+#define PropModeReplace 0
+#define PropModePrepend 1
+#define PropModeAppend 2
+
+/*****************************************************************
+ * GRAPHICS DEFINITIONS
+ *****************************************************************/
+
+/* graphics functions, as in GC.alu */
+
+#define GXclear 0x0 /* 0 */
+#define GXand 0x1 /* src AND dst */
+#define GXandReverse 0x2 /* src AND NOT dst */
+#define GXcopy 0x3 /* src */
+#define GXandInverted 0x4 /* NOT src AND dst */
+#define GXnoop 0x5 /* dst */
+#define GXxor 0x6 /* src XOR dst */
+#define GXor 0x7 /* src OR dst */
+#define GXnor 0x8 /* NOT src AND NOT dst */
+#define GXequiv 0x9 /* NOT src XOR dst */
+#define GXinvert 0xa /* NOT dst */
+#define GXorReverse 0xb /* src OR NOT dst */
+#define GXcopyInverted 0xc /* NOT src */
+#define GXorInverted 0xd /* NOT src OR dst */
+#define GXnand 0xe /* NOT src OR NOT dst */
+#define GXset 0xf /* 1 */
+
+/* LineStyle */
+
+#define LineSolid 0
+#define LineOnOffDash 1
+#define LineDoubleDash 2
+
+/* capStyle */
+
+#define CapNotLast 0
+#define CapButt 1
+#define CapRound 2
+#define CapProjecting 3
+
+/* joinStyle */
+
+#define JoinMiter 0
+#define JoinRound 1
+#define JoinBevel 2
+
+/* fillStyle */
+
+#define FillSolid 0
+#define FillTiled 1
+#define FillStippled 2
+#define FillOpaqueStippled 3
+
+/* fillRule */
+
+#define EvenOddRule 0
+#define WindingRule 1
+
+/* subwindow mode */
+
+#define ClipByChildren 0
+#define IncludeInferiors 1
+
+/* SetClipRectangles ordering */
+
+#define Unsorted 0
+#define YSorted 1
+#define YXSorted 2
+#define YXBanded 3
+
+/* CoordinateMode for drawing routines */
+
+#define CoordModeOrigin 0 /* relative to the origin */
+#define CoordModePrevious 1 /* relative to previous point */
+
+/* Polygon shapes */
+
+#define Complex 0 /* paths may intersect */
+#define Nonconvex 1 /* no paths intersect, but not convex */
+#define Convex 2 /* wholly convex */
+
+/* Arc modes for PolyFillArc */
+
+#define ArcChord 0 /* join endpoints of arc */
+#define ArcPieSlice 1 /* join endpoints to center of arc */
+
+/* GC components: masks used in CreateGC, CopyGC, ChangeGC, OR'ed into
+ GC.stateChanges */
+
+#define GCFunction (1L<<0)
+#define GCPlaneMask (1L<<1)
+#define GCForeground (1L<<2)
+#define GCBackground (1L<<3)
+#define GCLineWidth (1L<<4)
+#define GCLineStyle (1L<<5)
+#define GCCapStyle (1L<<6)
+#define GCJoinStyle (1L<<7)
+#define GCFillStyle (1L<<8)
+#define GCFillRule (1L<<9)
+#define GCTile (1L<<10)
+#define GCStipple (1L<<11)
+#define GCTileStipXOrigin (1L<<12)
+#define GCTileStipYOrigin (1L<<13)
+#define GCFont (1L<<14)
+#define GCSubwindowMode (1L<<15)
+#define GCGraphicsExposures (1L<<16)
+#define GCClipXOrigin (1L<<17)
+#define GCClipYOrigin (1L<<18)
+#define GCClipMask (1L<<19)
+#define GCDashOffset (1L<<20)
+#define GCDashList (1L<<21)
+#define GCArcMode (1L<<22)
+
+#define GCLastBit 22
+/*****************************************************************
+ * FONTS
+ *****************************************************************/
+
+/* used in QueryFont -- draw direction */
+
+#define FontLeftToRight 0
+#define FontRightToLeft 1
+
+#define FontChange 255
+
+/*****************************************************************
+ * IMAGING
+ *****************************************************************/
+
+/* ImageFormat -- PutImage, GetImage */
+
+#define XYBitmap 0 /* depth 1, XYFormat */
+#define XYPixmap 1 /* depth == drawable depth */
+#define ZPixmap 2 /* depth == drawable depth */
+
+/*****************************************************************
+ * COLOR MAP STUFF
+ *****************************************************************/
+
+/* For CreateColormap */
+
+#define AllocNone 0 /* create map with no entries */
+#define AllocAll 1 /* allocate entire map writeable */
+
+
+/* Flags used in StoreNamedColor, StoreColors */
+
+#define DoRed (1<<0)
+#define DoGreen (1<<1)
+#define DoBlue (1<<2)
+
+/*****************************************************************
+ * CURSOR STUFF
+ *****************************************************************/
+
+/* QueryBestSize Class */
+
+#define CursorShape 0 /* largest size that can be displayed */
+#define TileShape 1 /* size tiled fastest */
+#define StippleShape 2 /* size stippled fastest */
+
+/*****************************************************************
+ * KEYBOARD/POINTER STUFF
+ *****************************************************************/
+
+#define AutoRepeatModeOff 0
+#define AutoRepeatModeOn 1
+#define AutoRepeatModeDefault 2
+
+#define LedModeOff 0
+#define LedModeOn 1
+
+/* masks for ChangeKeyboardControl */
+
+#define KBKeyClickPercent (1L<<0)
+#define KBBellPercent (1L<<1)
+#define KBBellPitch (1L<<2)
+#define KBBellDuration (1L<<3)
+#define KBLed (1L<<4)
+#define KBLedMode (1L<<5)
+#define KBKey (1L<<6)
+#define KBAutoRepeatMode (1L<<7)
+
+#define MappingSuccess 0
+#define MappingBusy 1
+#define MappingFailed 2
+
+#define MappingModifier 0
+#define MappingKeyboard 1
+#define MappingPointer 2
+
+/*****************************************************************
+ * SCREEN SAVER STUFF
+ *****************************************************************/
+
+#define DontPreferBlanking 0
+#define PreferBlanking 1
+#define DefaultBlanking 2
+
+#define DisableScreenSaver 0
+#define DisableScreenInterval 0
+
+#define DontAllowExposures 0
+#define AllowExposures 1
+#define DefaultExposures 2
+
+/* for ForceScreenSaver */
+
+#define ScreenSaverReset 0
+#define ScreenSaverActive 1
+
+/*****************************************************************
+ * HOSTS AND CONNECTIONS
+ *****************************************************************/
+
+/* for ChangeHosts */
+
+#define HostInsert 0
+#define HostDelete 1
+
+/* for ChangeAccessControl */
+
+#define EnableAccess 1
+#define DisableAccess 0
+
+/* Display classes used in opening the connection
+ * Note that the statically allocated ones are even numbered and the
+ * dynamically changeable ones are odd numbered */
+
+#define StaticGray 0
+#define GrayScale 1
+#define StaticColor 2
+#define PseudoColor 3
+#define TrueColor 4
+#define DirectColor 5
+
+
+/* Byte order used in imageByteOrder and bitmapBitOrder */
+
+#define LSBFirst 0
+#define MSBFirst 1
+
+#endif /* X_H */
diff --git a/system/include/X11/Xatom.h b/system/include/X11/Xatom.h
new file mode 100644
index 00000000..485a4236
--- /dev/null
+++ b/system/include/X11/Xatom.h
@@ -0,0 +1,79 @@
+#ifndef XATOM_H
+#define XATOM_H 1
+
+/* THIS IS A GENERATED FILE
+ *
+ * Do not change! Changing this file implies a protocol change!
+ */
+
+#define XA_PRIMARY ((Atom) 1)
+#define XA_SECONDARY ((Atom) 2)
+#define XA_ARC ((Atom) 3)
+#define XA_ATOM ((Atom) 4)
+#define XA_BITMAP ((Atom) 5)
+#define XA_CARDINAL ((Atom) 6)
+#define XA_COLORMAP ((Atom) 7)
+#define XA_CURSOR ((Atom) 8)
+#define XA_CUT_BUFFER0 ((Atom) 9)
+#define XA_CUT_BUFFER1 ((Atom) 10)
+#define XA_CUT_BUFFER2 ((Atom) 11)
+#define XA_CUT_BUFFER3 ((Atom) 12)
+#define XA_CUT_BUFFER4 ((Atom) 13)
+#define XA_CUT_BUFFER5 ((Atom) 14)
+#define XA_CUT_BUFFER6 ((Atom) 15)
+#define XA_CUT_BUFFER7 ((Atom) 16)
+#define XA_DRAWABLE ((Atom) 17)
+#define XA_FONT ((Atom) 18)
+#define XA_INTEGER ((Atom) 19)
+#define XA_PIXMAP ((Atom) 20)
+#define XA_POINT ((Atom) 21)
+#define XA_RECTANGLE ((Atom) 22)
+#define XA_RESOURCE_MANAGER ((Atom) 23)
+#define XA_RGB_COLOR_MAP ((Atom) 24)
+#define XA_RGB_BEST_MAP ((Atom) 25)
+#define XA_RGB_BLUE_MAP ((Atom) 26)
+#define XA_RGB_DEFAULT_MAP ((Atom) 27)
+#define XA_RGB_GRAY_MAP ((Atom) 28)
+#define XA_RGB_GREEN_MAP ((Atom) 29)
+#define XA_RGB_RED_MAP ((Atom) 30)
+#define XA_STRING ((Atom) 31)
+#define XA_VISUALID ((Atom) 32)
+#define XA_WINDOW ((Atom) 33)
+#define XA_WM_COMMAND ((Atom) 34)
+#define XA_WM_HINTS ((Atom) 35)
+#define XA_WM_CLIENT_MACHINE ((Atom) 36)
+#define XA_WM_ICON_NAME ((Atom) 37)
+#define XA_WM_ICON_SIZE ((Atom) 38)
+#define XA_WM_NAME ((Atom) 39)
+#define XA_WM_NORMAL_HINTS ((Atom) 40)
+#define XA_WM_SIZE_HINTS ((Atom) 41)
+#define XA_WM_ZOOM_HINTS ((Atom) 42)
+#define XA_MIN_SPACE ((Atom) 43)
+#define XA_NORM_SPACE ((Atom) 44)
+#define XA_MAX_SPACE ((Atom) 45)
+#define XA_END_SPACE ((Atom) 46)
+#define XA_SUPERSCRIPT_X ((Atom) 47)
+#define XA_SUPERSCRIPT_Y ((Atom) 48)
+#define XA_SUBSCRIPT_X ((Atom) 49)
+#define XA_SUBSCRIPT_Y ((Atom) 50)
+#define XA_UNDERLINE_POSITION ((Atom) 51)
+#define XA_UNDERLINE_THICKNESS ((Atom) 52)
+#define XA_STRIKEOUT_ASCENT ((Atom) 53)
+#define XA_STRIKEOUT_DESCENT ((Atom) 54)
+#define XA_ITALIC_ANGLE ((Atom) 55)
+#define XA_X_HEIGHT ((Atom) 56)
+#define XA_QUAD_WIDTH ((Atom) 57)
+#define XA_WEIGHT ((Atom) 58)
+#define XA_POINT_SIZE ((Atom) 59)
+#define XA_RESOLUTION ((Atom) 60)
+#define XA_COPYRIGHT ((Atom) 61)
+#define XA_NOTICE ((Atom) 62)
+#define XA_FONT_NAME ((Atom) 63)
+#define XA_FAMILY_NAME ((Atom) 64)
+#define XA_FULL_NAME ((Atom) 65)
+#define XA_CAP_HEIGHT ((Atom) 66)
+#define XA_WM_CLASS ((Atom) 67)
+#define XA_WM_TRANSIENT_FOR ((Atom) 68)
+
+#define XA_LAST_PREDEFINED ((Atom) 68)
+#endif /* XATOM_H */
diff --git a/system/include/X11/Xfuncproto.h b/system/include/X11/Xfuncproto.h
new file mode 100644
index 00000000..b5b572a3
--- /dev/null
+++ b/system/include/X11/Xfuncproto.h
@@ -0,0 +1,127 @@
+/* Xfuncproto.h. Generated from Xfuncproto.h.in by configure. */
+/*
+ *
+Copyright 1989, 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ */
+
+/* Definitions to make function prototypes manageable */
+
+#ifndef _XFUNCPROTO_H_
+#define _XFUNCPROTO_H_
+
+#ifndef NeedFunctionPrototypes
+#define NeedFunctionPrototypes 1
+#endif /* NeedFunctionPrototypes */
+
+#ifndef NeedVarargsPrototypes
+#define NeedVarargsPrototypes 1
+#endif /* NeedVarargsPrototypes */
+
+#if NeedFunctionPrototypes
+
+#ifndef NeedNestedPrototypes
+#define NeedNestedPrototypes 1
+#endif /* NeedNestedPrototypes */
+
+#ifndef _Xconst
+#define _Xconst const
+#endif /* _Xconst */
+
+/* Function prototype configuration (see configure for more info) */
+#ifndef NARROWPROTO
+#define NARROWPROTO /**/
+#endif
+#ifndef FUNCPROTO
+#define FUNCPROTO 15
+#endif
+
+#ifndef NeedWidePrototypes
+#ifdef NARROWPROTO
+#define NeedWidePrototypes 0
+#else
+#define NeedWidePrototypes 1 /* default to make interropt. easier */
+#endif
+#endif /* NeedWidePrototypes */
+
+#endif /* NeedFunctionPrototypes */
+
+#ifndef _XFUNCPROTOBEGIN
+#if defined(__cplusplus) || defined(c_plusplus) /* for C++ V2.0 */
+#define _XFUNCPROTOBEGIN extern "C" { /* do not leave open across includes */
+#define _XFUNCPROTOEND }
+#else
+#define _XFUNCPROTOBEGIN
+#define _XFUNCPROTOEND
+#endif
+#endif /* _XFUNCPROTOBEGIN */
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+# define _X_SENTINEL(x) __attribute__ ((__sentinel__(x)))
+# define _X_ATTRIBUTE_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+# define _X_SENTINEL(x)
+# define _X_ATTRIBUTE_PRINTF(x,y)
+#endif /* GNUC >= 4 */
+
+#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__)
+# define _X_EXPORT __attribute__((visibility("default")))
+# define _X_HIDDEN __attribute__((visibility("hidden")))
+# define _X_INTERNAL __attribute__((visibility("internal")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define _X_EXPORT __global
+# define _X_HIDDEN __hidden
+# define _X_INTERNAL __hidden
+#else /* not gcc >= 4 and not Sun Studio >= 8 */
+# define _X_EXPORT
+# define _X_HIDDEN
+# define _X_INTERNAL
+#endif /* GNUC >= 4 */
+
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 303)
+# define _X_LIKELY(x) __builtin_expect(!!(x), 1)
+# define _X_UNLIKELY(x) __builtin_expect(!!(x), 0)
+# define _X_INLINE inline
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+# define _X_LIKELY(x) (x)
+# define _X_UNLIKELY(x) (x)
+# define _X_INLINE inline
+#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
+# define _X_LIKELY(x) (x)
+# define _X_UNLIKELY(x) (x)
+# define _X_INLINE
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 301)
+# define _X_DEPRECATED __attribute__((deprecated))
+#else /* not gcc >= 3.1 */
+# define _X_DEPRECATED
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)
+# define _X_NORETURN __attribute((noreturn))
+#else
+# define _X_NORETURN
+#endif /* GNUC */
+
+#endif /* _XFUNCPROTO_H_ */
diff --git a/system/include/X11/Xlib.h b/system/include/X11/Xlib.h
new file mode 100644
index 00000000..7c8bc515
--- /dev/null
+++ b/system/include/X11/Xlib.h
@@ -0,0 +1,4023 @@
+/*
+
+Copyright 1985, 1986, 1987, 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+
+/*
+ * Xlib.h - Header definition and support file for the C subroutine
+ * interface library (Xlib) to the X Window System Protocol (V11).
+ * Structures and symbols starting with "_" are private to the library.
+ */
+#ifndef _XLIB_H_
+#define _XLIB_H_
+
+#define XlibSpecificationRelease 6
+
+#include <sys/types.h>
+
+#if defined(__SCO__) || defined(__UNIXWARE__)
+#include <stdint.h>
+#endif
+
+#include <X11/X.h>
+
+/* applications should not depend on these two headers being included! */
+#include <X11/Xfuncproto.h>
+#include <X11/Xosdefs.h>
+
+#ifndef X_WCHAR
+#include <stddef.h>
+#else
+#ifdef __UNIXOS2__
+#include <stdlib.h>
+#else
+/* replace this with #include or typedef appropriate for your system */
+typedef unsigned long wchar_t;
+#endif
+#endif
+
+#if defined(ISC) && defined(USE_XMBTOWC)
+#define wctomb(a,b) _Xwctomb(a,b)
+#define mblen(a,b) _Xmblen(a,b)
+#ifndef USE_XWCHAR_STRING
+#define mbtowc(a,b,c) _Xmbtowc(a,b,c)
+#endif
+#endif
+
+extern int
+_Xmblen(
+#ifdef ISC
+ char const *str,
+ size_t len
+#else
+ char *str,
+ int len
+#endif
+ );
+
+/* API mentioning "UTF8" or "utf8" is an XFree86 extension, introduced in
+ November 2000. Its presence is indicated through the following macro. */
+#define X_HAVE_UTF8_STRING 1
+
+typedef char *XPointer;
+
+#define Bool int
+#define Status int
+#define True 1
+#define False 0
+
+#define QueuedAlready 0
+#define QueuedAfterReading 1
+#define QueuedAfterFlush 2
+
+#define ConnectionNumber(dpy) (((_XPrivDisplay)dpy)->fd)
+#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root)
+#define DefaultScreen(dpy) (((_XPrivDisplay)dpy)->default_screen)
+#define DefaultRootWindow(dpy) (ScreenOfDisplay(dpy,DefaultScreen(dpy))->root)
+#define DefaultVisual(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_visual)
+#define DefaultGC(dpy, scr) (ScreenOfDisplay(dpy,scr)->default_gc)
+#define BlackPixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->black_pixel)
+#define WhitePixel(dpy, scr) (ScreenOfDisplay(dpy,scr)->white_pixel)
+#define AllPlanes ((unsigned long)~0L)
+#define QLength(dpy) (((_XPrivDisplay)dpy)->qlen)
+#define DisplayWidth(dpy, scr) (ScreenOfDisplay(dpy,scr)->width)
+#define DisplayHeight(dpy, scr) (ScreenOfDisplay(dpy,scr)->height)
+#define DisplayWidthMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mwidth)
+#define DisplayHeightMM(dpy, scr)(ScreenOfDisplay(dpy,scr)->mheight)
+#define DisplayPlanes(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth)
+#define DisplayCells(dpy, scr) (DefaultVisual(dpy,scr)->map_entries)
+#define ScreenCount(dpy) (((_XPrivDisplay)dpy)->nscreens)
+#define ServerVendor(dpy) (((_XPrivDisplay)dpy)->vendor)
+#define ProtocolVersion(dpy) (((_XPrivDisplay)dpy)->proto_major_version)
+#define ProtocolRevision(dpy) (((_XPrivDisplay)dpy)->proto_minor_version)
+#define VendorRelease(dpy) (((_XPrivDisplay)dpy)->release)
+#define DisplayString(dpy) (((_XPrivDisplay)dpy)->display_name)
+#define DefaultDepth(dpy, scr) (ScreenOfDisplay(dpy,scr)->root_depth)
+#define DefaultColormap(dpy, scr)(ScreenOfDisplay(dpy,scr)->cmap)
+#define BitmapUnit(dpy) (((_XPrivDisplay)dpy)->bitmap_unit)
+#define BitmapBitOrder(dpy) (((_XPrivDisplay)dpy)->bitmap_bit_order)
+#define BitmapPad(dpy) (((_XPrivDisplay)dpy)->bitmap_pad)
+#define ImageByteOrder(dpy) (((_XPrivDisplay)dpy)->byte_order)
+#ifdef CRAY /* unable to get WORD64 without pulling in other symbols */
+#define NextRequest(dpy) XNextRequest(dpy)
+#else
+#define NextRequest(dpy) (((_XPrivDisplay)dpy)->request + 1)
+#endif
+#define LastKnownRequestProcessed(dpy) (((_XPrivDisplay)dpy)->last_request_read)
+
+/* macros for screen oriented applications (toolkit) */
+#define ScreenOfDisplay(dpy, scr)(&((_XPrivDisplay)dpy)->screens[scr])
+#define DefaultScreenOfDisplay(dpy) ScreenOfDisplay(dpy,DefaultScreen(dpy))
+#define DisplayOfScreen(s) ((s)->display)
+#define RootWindowOfScreen(s) ((s)->root)
+#define BlackPixelOfScreen(s) ((s)->black_pixel)
+#define WhitePixelOfScreen(s) ((s)->white_pixel)
+#define DefaultColormapOfScreen(s)((s)->cmap)
+#define DefaultDepthOfScreen(s) ((s)->root_depth)
+#define DefaultGCOfScreen(s) ((s)->default_gc)
+#define DefaultVisualOfScreen(s)((s)->root_visual)
+#define WidthOfScreen(s) ((s)->width)
+#define HeightOfScreen(s) ((s)->height)
+#define WidthMMOfScreen(s) ((s)->mwidth)
+#define HeightMMOfScreen(s) ((s)->mheight)
+#define PlanesOfScreen(s) ((s)->root_depth)
+#define CellsOfScreen(s) (DefaultVisualOfScreen((s))->map_entries)
+#define MinCmapsOfScreen(s) ((s)->min_maps)
+#define MaxCmapsOfScreen(s) ((s)->max_maps)
+#define DoesSaveUnders(s) ((s)->save_unders)
+#define DoesBackingStore(s) ((s)->backing_store)
+#define EventMaskOfScreen(s) ((s)->root_input_mask)
+
+/*
+ * Extensions need a way to hang private data on some structures.
+ */
+typedef struct _XExtData {
+ int number; /* number returned by XRegisterExtension */
+ struct _XExtData *next; /* next item on list of data for structure */
+ int (*free_private)( /* called to free private storage */
+ struct _XExtData *extension
+ );
+ XPointer private_data; /* data private to this extension. */
+} XExtData;
+
+/*
+ * This file contains structures used by the extension mechanism.
+ */
+typedef struct { /* public to extension, cannot be changed */
+ int extension; /* extension number */
+ int major_opcode; /* major op-code assigned by server */
+ int first_event; /* first event number for the extension */
+ int first_error; /* first error number for the extension */
+} XExtCodes;
+
+/*
+ * Data structure for retrieving info about pixmap formats.
+ */
+
+typedef struct {
+ int depth;
+ int bits_per_pixel;
+ int scanline_pad;
+} XPixmapFormatValues;
+
+
+/*
+ * Data structure for setting graphics context.
+ */
+typedef struct {
+ int function; /* logical operation */
+ unsigned long plane_mask;/* plane mask */
+ unsigned long foreground;/* foreground pixel */
+ unsigned long background;/* background pixel */
+ int line_width; /* line width */
+ int line_style; /* LineSolid, LineOnOffDash, LineDoubleDash */
+ int cap_style; /* CapNotLast, CapButt,
+ CapRound, CapProjecting */
+ int join_style; /* JoinMiter, JoinRound, JoinBevel */
+ int fill_style; /* FillSolid, FillTiled,
+ FillStippled, FillOpaeueStippled */
+ int fill_rule; /* EvenOddRule, WindingRule */
+ int arc_mode; /* ArcChord, ArcPieSlice */
+ Pixmap tile; /* tile pixmap for tiling operations */
+ Pixmap stipple; /* stipple 1 plane pixmap for stipping */
+ int ts_x_origin; /* offset for tile or stipple operations */
+ int ts_y_origin;
+ Font font; /* default text font for text operations */
+ int subwindow_mode; /* ClipByChildren, IncludeInferiors */
+ Bool graphics_exposures;/* boolean, should exposures be generated */
+ int clip_x_origin; /* origin for clipping */
+ int clip_y_origin;
+ Pixmap clip_mask; /* bitmap clipping; other calls for rects */
+ int dash_offset; /* patterned/dashed line information */
+ char dashes;
+} XGCValues;
+
+/*
+ * Graphics context. The contents of this structure are implementation
+ * dependent. A GC should be treated as opaque by application code.
+ */
+
+typedef struct _XGC
+#ifdef XLIB_ILLEGAL_ACCESS
+{
+ XExtData *ext_data; /* hook for extension to hang data */
+ GContext gid; /* protocol ID for graphics context */
+ /* there is more to this structure, but it is private to Xlib */
+}
+#endif
+*GC;
+
+/*
+ * Visual structure; contains information about colormapping possible.
+ */
+typedef struct {
+ XExtData *ext_data; /* hook for extension to hang data */
+ VisualID visualid; /* visual id of this visual */
+#if defined(__cplusplus) || defined(c_plusplus)
+ int c_class; /* C++ class of screen (monochrome, etc.) */
+#else
+ int class; /* class of screen (monochrome, etc.) */
+#endif
+ unsigned long red_mask, green_mask, blue_mask; /* mask values */
+ int bits_per_rgb; /* log base 2 of distinct color values */
+ int map_entries; /* color map entries */
+} Visual;
+
+/*
+ * Depth structure; contains information for each possible depth.
+ */
+typedef struct {
+ int depth; /* this depth (Z) of the depth */
+ int nvisuals; /* number of Visual types at this depth */
+ Visual *visuals; /* list of visuals possible at this depth */
+} Depth;
+
+/*
+ * Information about the screen. The contents of this structure are
+ * implementation dependent. A Screen should be treated as opaque
+ * by application code.
+ */
+
+struct _XDisplay; /* Forward declare before use for C++ */
+
+typedef struct {
+ XExtData *ext_data; /* hook for extension to hang data */
+ struct _XDisplay *display;/* back pointer to display structure */
+ Window root; /* Root window id. */
+ int width, height; /* width and height of screen */
+ int mwidth, mheight; /* width and height of in millimeters */
+ int ndepths; /* number of depths possible */
+ Depth *depths; /* list of allowable depths on the screen */
+ int root_depth; /* bits per pixel */
+ Visual *root_visual; /* root visual */
+ GC default_gc; /* GC for the root root visual */
+ Colormap cmap; /* default color map */
+ unsigned long white_pixel;
+ unsigned long black_pixel; /* White and Black pixel values */
+ int max_maps, min_maps; /* max and min color maps */
+ int backing_store; /* Never, WhenMapped, Always */
+ Bool save_unders;
+ long root_input_mask; /* initial root input mask */
+} Screen;
+
+/*
+ * Format structure; describes ZFormat data the screen will understand.
+ */
+typedef struct {
+ XExtData *ext_data; /* hook for extension to hang data */
+ int depth; /* depth of this image format */
+ int bits_per_pixel; /* bits/pixel at this depth */
+ int scanline_pad; /* scanline must padded to this multiple */
+} ScreenFormat;
+
+/*
+ * Data structure for setting window attributes.
+ */
+typedef struct {
+ Pixmap background_pixmap; /* background or None or ParentRelative */
+ unsigned long background_pixel; /* background pixel */
+ Pixmap border_pixmap; /* border of the window */
+ unsigned long border_pixel; /* border pixel value */
+ int bit_gravity; /* one of bit gravity values */
+ int win_gravity; /* one of the window gravity values */
+ int backing_store; /* NotUseful, WhenMapped, Always */
+ unsigned long backing_planes;/* planes to be preseved if possible */
+ unsigned long backing_pixel;/* value to use in restoring planes */
+ Bool save_under; /* should bits under be saved? (popups) */
+ long event_mask; /* set of events that should be saved */
+ long do_not_propagate_mask; /* set of events that should not propagate */
+ Bool override_redirect; /* boolean value for override-redirect */
+ Colormap colormap; /* color map to be associated with window */
+ Cursor cursor; /* cursor to be displayed (or None) */
+} XSetWindowAttributes;
+
+typedef struct {
+ int x, y; /* location of window */
+ int width, height; /* width and height of window */
+ int border_width; /* border width of window */
+ int depth; /* depth of window */
+ Visual *visual; /* the associated visual structure */
+ Window root; /* root of screen containing window */
+#if defined(__cplusplus) || defined(c_plusplus)
+ int c_class; /* C++ InputOutput, InputOnly*/
+#else
+ int class; /* InputOutput, InputOnly*/
+#endif
+ int bit_gravity; /* one of bit gravity values */
+ int win_gravity; /* one of the window gravity values */
+ int backing_store; /* NotUseful, WhenMapped, Always */
+ unsigned long backing_planes;/* planes to be preserved if possible */
+ unsigned long backing_pixel;/* value to be used when restoring planes */
+ Bool save_under; /* boolean, should bits under be saved? */
+ Colormap colormap; /* color map to be associated with window */
+ Bool map_installed; /* boolean, is color map currently installed*/
+ int map_state; /* IsUnmapped, IsUnviewable, IsViewable */
+ long all_event_masks; /* set of events all people have interest in*/
+ long your_event_mask; /* my event mask */
+ long do_not_propagate_mask; /* set of events that should not propagate */
+ Bool override_redirect; /* boolean value for override-redirect */
+ Screen *screen; /* back pointer to correct screen */
+} XWindowAttributes;
+
+/*
+ * Data structure for host setting; getting routines.
+ *
+ */
+
+typedef struct {
+ int family; /* for example FamilyInternet */
+ int length; /* length of address, in bytes */
+ char *address; /* pointer to where to find the bytes */
+} XHostAddress;
+
+/*
+ * Data structure for ServerFamilyInterpreted addresses in host routines
+ */
+typedef struct {
+ int typelength; /* length of type string, in bytes */
+ int valuelength; /* length of value string, in bytes */
+ char *type; /* pointer to where to find the type string */
+ char *value; /* pointer to where to find the address */
+} XServerInterpretedAddress;
+
+/*
+ * Data structure for "image" data, used by image manipulation routines.
+ */
+typedef struct _XImage {
+ int width, height; /* size of image */
+ int xoffset; /* number of pixels offset in X direction */
+ int format; /* XYBitmap, XYPixmap, ZPixmap */
+ char *data; /* pointer to image data */
+ int byte_order; /* data byte order, LSBFirst, MSBFirst */
+ int bitmap_unit; /* quant. of scanline 8, 16, 32 */
+ int bitmap_bit_order; /* LSBFirst, MSBFirst */
+ int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
+ int depth; /* depth of image */
+ int bytes_per_line; /* accelarator to next line */
+ int bits_per_pixel; /* bits per pixel (ZPixmap) */
+ unsigned long red_mask; /* bits in z arrangment */
+ unsigned long green_mask;
+ unsigned long blue_mask;
+ XPointer obdata; /* hook for the object routines to hang on */
+ struct funcs { /* image manipulation routines */
+ struct _XImage *(*create_image)(
+ struct _XDisplay* /* display */,
+ Visual* /* visual */,
+ unsigned int /* depth */,
+ int /* format */,
+ int /* offset */,
+ char* /* data */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* bitmap_pad */,
+ int /* bytes_per_line */);
+ int (*destroy_image) (struct _XImage *);
+ unsigned long (*get_pixel) (struct _XImage *, int, int);
+ int (*put_pixel) (struct _XImage *, int, int, unsigned long);
+ struct _XImage *(*sub_image)(struct _XImage *, int, int, unsigned int, unsigned int);
+ int (*add_pixel) (struct _XImage *, long);
+ } f;
+} XImage;
+
+/*
+ * Data structure for XReconfigureWindow
+ */
+typedef struct {
+ int x, y;
+ int width, height;
+ int border_width;
+ Window sibling;
+ int stack_mode;
+} XWindowChanges;
+
+/*
+ * Data structure used by color operations
+ */
+typedef struct {
+ unsigned long pixel;
+ unsigned short red, green, blue;
+ char flags; /* do_red, do_green, do_blue */
+ char pad;
+} XColor;
+
+/*
+ * Data structures for graphics operations. On most machines, these are
+ * congruent with the wire protocol structures, so reformatting the data
+ * can be avoided on these architectures.
+ */
+typedef struct {
+ short x1, y1, x2, y2;
+} XSegment;
+
+typedef struct {
+ short x, y;
+} XPoint;
+
+typedef struct {
+ short x, y;
+ unsigned short width, height;
+} XRectangle;
+
+typedef struct {
+ short x, y;
+ unsigned short width, height;
+ short angle1, angle2;
+} XArc;
+
+
+/* Data structure for XChangeKeyboardControl */
+
+typedef struct {
+ int key_click_percent;
+ int bell_percent;
+ int bell_pitch;
+ int bell_duration;
+ int led;
+ int led_mode;
+ int key;
+ int auto_repeat_mode; /* On, Off, Default */
+} XKeyboardControl;
+
+/* Data structure for XGetKeyboardControl */
+
+typedef struct {
+ int key_click_percent;
+ int bell_percent;
+ unsigned int bell_pitch, bell_duration;
+ unsigned long led_mask;
+ int global_auto_repeat;
+ char auto_repeats[32];
+} XKeyboardState;
+
+/* Data structure for XGetMotionEvents. */
+
+typedef struct {
+ Time time;
+ short x, y;
+} XTimeCoord;
+
+/* Data structure for X{Set,Get}ModifierMapping */
+
+typedef struct {
+ int max_keypermod; /* The server's max # of keys per modifier */
+ KeyCode *modifiermap; /* An 8 by max_keypermod array of modifiers */
+} XModifierKeymap;
+
+
+/*
+ * Display datatype maintaining display specific data.
+ * The contents of this structure are implementation dependent.
+ * A Display should be treated as opaque by application code.
+ */
+#ifndef XLIB_ILLEGAL_ACCESS
+typedef struct _XDisplay Display;
+#endif
+
+struct _XPrivate; /* Forward declare before use for C++ */
+struct _XrmHashBucketRec;
+
+typedef struct
+#ifdef XLIB_ILLEGAL_ACCESS
+_XDisplay
+#endif
+{
+ XExtData *ext_data; /* hook for extension to hang data */
+ struct _XPrivate *private1;
+ int fd; /* Network socket. */
+ int private2;
+ int proto_major_version;/* major version of server's X protocol */
+ int proto_minor_version;/* minor version of servers X protocol */
+ char *vendor; /* vendor of the server hardware */
+ XID private3;
+ XID private4;
+ XID private5;
+ int private6;
+ XID (*resource_alloc)( /* allocator function */
+ struct _XDisplay*
+ );
+ int byte_order; /* screen byte order, LSBFirst, MSBFirst */
+ int bitmap_unit; /* padding and data requirements */
+ int bitmap_pad; /* padding requirements on bitmaps */
+ int bitmap_bit_order; /* LeastSignificant or MostSignificant */
+ int nformats; /* number of pixmap formats in list */
+ ScreenFormat *pixmap_format; /* pixmap format list */
+ int private8;
+ int release; /* release of the server */
+ struct _XPrivate *private9, *private10;
+ int qlen; /* Length of input event queue */
+ unsigned long last_request_read; /* seq number of last event read */
+ unsigned long request; /* sequence number of last request. */
+ XPointer private11;
+ XPointer private12;
+ XPointer private13;
+ XPointer private14;
+ unsigned max_request_size; /* maximum number 32 bit words in request*/
+ struct _XrmHashBucketRec *db;
+ int (*private15)(
+ struct _XDisplay*
+ );
+ char *display_name; /* "host:display" string used on this connect*/
+ int default_screen; /* default screen for operations */
+ int nscreens; /* number of screens on this server*/
+ Screen *screens; /* pointer to list of screens */
+ unsigned long motion_buffer; /* size of motion buffer */
+ unsigned long private16;
+ int min_keycode; /* minimum defined keycode */
+ int max_keycode; /* maximum defined keycode */
+ XPointer private17;
+ XPointer private18;
+ int private19;
+ char *xdefaults; /* contents of defaults from server */
+ /* there is more to this structure, but it is private to Xlib */
+}
+#ifdef XLIB_ILLEGAL_ACCESS
+Display,
+#endif
+*_XPrivDisplay;
+
+#undef _XEVENT_
+#ifndef _XEVENT_
+/*
+ * Definitions of specific events.
+ */
+typedef struct {
+ int type; /* of event */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* "event" window it is reported relative to */
+ Window root; /* root window that the event occurred on */
+ Window subwindow; /* child window */
+ Time time; /* milliseconds */
+ int x, y; /* pointer x, y coordinates in event window */
+ int x_root, y_root; /* coordinates relative to root */
+ unsigned int state; /* key or button mask */
+ unsigned int keycode; /* detail */
+ Bool same_screen; /* same screen flag */
+} XKeyEvent;
+typedef XKeyEvent XKeyPressedEvent;
+typedef XKeyEvent XKeyReleasedEvent;
+
+typedef struct {
+ int type; /* of event */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* "event" window it is reported relative to */
+ Window root; /* root window that the event occurred on */
+ Window subwindow; /* child window */
+ Time time; /* milliseconds */
+ int x, y; /* pointer x, y coordinates in event window */
+ int x_root, y_root; /* coordinates relative to root */
+ unsigned int state; /* key or button mask */
+ unsigned int button; /* detail */
+ Bool same_screen; /* same screen flag */
+} XButtonEvent;
+typedef XButtonEvent XButtonPressedEvent;
+typedef XButtonEvent XButtonReleasedEvent;
+
+typedef struct {
+ int type; /* of event */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* "event" window reported relative to */
+ Window root; /* root window that the event occurred on */
+ Window subwindow; /* child window */
+ Time time; /* milliseconds */
+ int x, y; /* pointer x, y coordinates in event window */
+ int x_root, y_root; /* coordinates relative to root */
+ unsigned int state; /* key or button mask */
+ char is_hint; /* detail */
+ Bool same_screen; /* same screen flag */
+} XMotionEvent;
+typedef XMotionEvent XPointerMovedEvent;
+
+typedef struct {
+ int type; /* of event */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* "event" window reported relative to */
+ Window root; /* root window that the event occurred on */
+ Window subwindow; /* child window */
+ Time time; /* milliseconds */
+ int x, y; /* pointer x, y coordinates in event window */
+ int x_root, y_root; /* coordinates relative to root */
+ int mode; /* NotifyNormal, NotifyGrab, NotifyUngrab */
+ int detail;
+ /*
+ * NotifyAncestor, NotifyVirtual, NotifyInferior,
+ * NotifyNonlinear,NotifyNonlinearVirtual
+ */
+ Bool same_screen; /* same screen flag */
+ Bool focus; /* boolean focus */
+ unsigned int state; /* key or button mask */
+} XCrossingEvent;
+typedef XCrossingEvent XEnterWindowEvent;
+typedef XCrossingEvent XLeaveWindowEvent;
+
+typedef struct {
+ int type; /* FocusIn or FocusOut */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* window of event */
+ int mode; /* NotifyNormal, NotifyWhileGrabbed,
+ NotifyGrab, NotifyUngrab */
+ int detail;
+ /*
+ * NotifyAncestor, NotifyVirtual, NotifyInferior,
+ * NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer,
+ * NotifyPointerRoot, NotifyDetailNone
+ */
+} XFocusChangeEvent;
+typedef XFocusChangeEvent XFocusInEvent;
+typedef XFocusChangeEvent XFocusOutEvent;
+
+/* generated on EnterWindow and FocusIn when KeyMapState selected */
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ char key_vector[32];
+} XKeymapEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ int x, y;
+ int width, height;
+ int count; /* if non-zero, at least this many more */
+} XExposeEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Drawable drawable;
+ int x, y;
+ int width, height;
+ int count; /* if non-zero, at least this many more */
+ int major_code; /* core is CopyArea or CopyPlane */
+ int minor_code; /* not defined in the core */
+} XGraphicsExposeEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Drawable drawable;
+ int major_code; /* core is CopyArea or CopyPlane */
+ int minor_code; /* not defined in the core */
+} XNoExposeEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ int state; /* Visibility state */
+} XVisibilityEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window parent; /* parent of the window */
+ Window window; /* window id of window created */
+ int x, y; /* window location */
+ int width, height; /* size of window */
+ int border_width; /* border width */
+ Bool override_redirect; /* creation should be overridden */
+} XCreateWindowEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+} XDestroyWindowEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ Bool from_configure;
+} XUnmapEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ Bool override_redirect; /* boolean, is override set... */
+} XMapEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window parent;
+ Window window;
+} XMapRequestEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ Window parent;
+ int x, y;
+ Bool override_redirect;
+} XReparentEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ int x, y;
+ int width, height;
+ int border_width;
+ Window above;
+ Bool override_redirect;
+} XConfigureEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ int x, y;
+} XGravityEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ int width, height;
+} XResizeRequestEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window parent;
+ Window window;
+ int x, y;
+ int width, height;
+ int border_width;
+ Window above;
+ int detail; /* Above, Below, TopIf, BottomIf, Opposite */
+ unsigned long value_mask;
+} XConfigureRequestEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window event;
+ Window window;
+ int place; /* PlaceOnTop, PlaceOnBottom */
+} XCirculateEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window parent;
+ Window window;
+ int place; /* PlaceOnTop, PlaceOnBottom */
+} XCirculateRequestEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ Atom atom;
+ Time time;
+ int state; /* NewValue, Deleted */
+} XPropertyEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ Atom selection;
+ Time time;
+} XSelectionClearEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window owner;
+ Window requestor;
+ Atom selection;
+ Atom target;
+ Atom property;
+ Time time;
+} XSelectionRequestEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window requestor;
+ Atom selection;
+ Atom target;
+ Atom property; /* ATOM or None */
+ Time time;
+} XSelectionEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ Colormap colormap; /* COLORMAP or None */
+#if defined(__cplusplus) || defined(c_plusplus)
+ Bool c_new; /* C++ */
+#else
+ Bool new;
+#endif
+ int state; /* ColormapInstalled, ColormapUninstalled */
+} XColormapEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window;
+ Atom message_type;
+ int format;
+ union {
+ char b[20];
+ short s[10];
+ long l[5];
+ } data;
+} XClientMessageEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* unused */
+ int request; /* one of MappingModifier, MappingKeyboard,
+ MappingPointer */
+ int first_keycode; /* first keycode */
+ int count; /* defines range of change w. first_keycode*/
+} XMappingEvent;
+
+typedef struct {
+ int type;
+ Display *display; /* Display the event was read from */
+ XID resourceid; /* resource id */
+ unsigned long serial; /* serial number of failed request */
+ unsigned char error_code; /* error code of failed request */
+ unsigned char request_code; /* Major op-code of failed request */
+ unsigned char minor_code; /* Minor op-code of failed request */
+} XErrorEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display;/* Display the event was read from */
+ Window window; /* window on which event was requested in event mask */
+} XAnyEvent;
+
+
+/***************************************************************
+ *
+ * GenericEvent. This event is the standard event for all newer extensions.
+ */
+
+typedef struct
+ {
+ int type; /* of event. Always GenericEvent */
+ unsigned long serial; /* # of last request processed */
+ Bool send_event; /* true if from SendEvent request */
+ Display *display; /* Display the event was read from */
+ int extension; /* major opcode of extension that caused the event */
+ int evtype; /* actual event type. */
+ } XGenericEvent;
+
+typedef struct {
+ int type; /* of event. Always GenericEvent */
+ unsigned long serial; /* # of last request processed */
+ Bool send_event; /* true if from SendEvent request */
+ Display *display; /* Display the event was read from */
+ int extension; /* major opcode of extension that caused the event */
+ int evtype; /* actual event type. */
+ unsigned int cookie;
+ void *data;
+} XGenericEventCookie;
+
+/*
+ * this union is defined so Xlib can always use the same sized
+ * event structure internally, to avoid memory fragmentation.
+ */
+typedef union _XEvent {
+ int type; /* must not be changed; first element */
+ XAnyEvent xany;
+ XKeyEvent xkey;
+ XButtonEvent xbutton;
+ XMotionEvent xmotion;
+ XCrossingEvent xcrossing;
+ XFocusChangeEvent xfocus;
+ XExposeEvent xexpose;
+ XGraphicsExposeEvent xgraphicsexpose;
+ XNoExposeEvent xnoexpose;
+ XVisibilityEvent xvisibility;
+ XCreateWindowEvent xcreatewindow;
+ XDestroyWindowEvent xdestroywindow;
+ XUnmapEvent xunmap;
+ XMapEvent xmap;
+ XMapRequestEvent xmaprequest;
+ XReparentEvent xreparent;
+ XConfigureEvent xconfigure;
+ XGravityEvent xgravity;
+ XResizeRequestEvent xresizerequest;
+ XConfigureRequestEvent xconfigurerequest;
+ XCirculateEvent xcirculate;
+ XCirculateRequestEvent xcirculaterequest;
+ XPropertyEvent xproperty;
+ XSelectionClearEvent xselectionclear;
+ XSelectionRequestEvent xselectionrequest;
+ XSelectionEvent xselection;
+ XColormapEvent xcolormap;
+ XClientMessageEvent xclient;
+ XMappingEvent xmapping;
+ XErrorEvent xerror;
+ XKeymapEvent xkeymap;
+ XGenericEvent xgeneric;
+ XGenericEventCookie xcookie;
+ long pad[24];
+} XEvent;
+#endif
+
+#define XAllocID(dpy) ((*((_XPrivDisplay)dpy)->resource_alloc)((dpy)))
+
+/*
+ * per character font metric information.
+ */
+typedef struct {
+ short lbearing; /* origin to left edge of raster */
+ short rbearing; /* origin to right edge of raster */
+ short width; /* advance to next char's origin */
+ short ascent; /* baseline to top edge of raster */
+ short descent; /* baseline to bottom edge of raster */
+ unsigned short attributes; /* per char flags (not predefined) */
+} XCharStruct;
+
+/*
+ * To allow arbitrary information with fonts, there are additional properties
+ * returned.
+ */
+typedef struct {
+ Atom name;
+ unsigned long card32;
+} XFontProp;
+
+typedef struct {
+ XExtData *ext_data; /* hook for extension to hang data */
+ Font fid; /* Font id for this font */
+ unsigned direction; /* hint about direction the font is painted */
+ unsigned min_char_or_byte2;/* first character */
+ unsigned max_char_or_byte2;/* last character */
+ unsigned min_byte1; /* first row that exists */
+ unsigned max_byte1; /* last row that exists */
+ Bool all_chars_exist;/* flag if all characters have non-zero size*/
+ unsigned default_char; /* char to print for undefined character */
+ int n_properties; /* how many properties there are */
+ XFontProp *properties; /* pointer to array of additional properties*/
+ XCharStruct min_bounds; /* minimum bounds over all existing char*/
+ XCharStruct max_bounds; /* maximum bounds over all existing char*/
+ XCharStruct *per_char; /* first_char to last_char information */
+ int ascent; /* log. extent above baseline for spacing */
+ int descent; /* log. descent below baseline for spacing */
+} XFontStruct;
+
+/*
+ * PolyText routines take these as arguments.
+ */
+typedef struct {
+ char *chars; /* pointer to string */
+ int nchars; /* number of characters */
+ int delta; /* delta between strings */
+ Font font; /* font to print it in, None don't change */
+} XTextItem;
+
+typedef struct { /* normal 16 bit characters are two bytes */
+ unsigned char byte1;
+ unsigned char byte2;
+} XChar2b;
+
+typedef struct {
+ XChar2b *chars; /* two byte characters */
+ int nchars; /* number of characters */
+ int delta; /* delta between strings */
+ Font font; /* font to print it in, None don't change */
+} XTextItem16;
+
+
+typedef union { Display *display;
+ GC gc;
+ Visual *visual;
+ Screen *screen;
+ ScreenFormat *pixmap_format;
+ XFontStruct *font; } XEDataObject;
+
+typedef struct {
+ XRectangle max_ink_extent;
+ XRectangle max_logical_extent;
+} XFontSetExtents;
+
+/* unused:
+typedef void (*XOMProc)();
+ */
+
+typedef struct _XOM *XOM;
+typedef struct _XOC *XOC, *XFontSet;
+
+typedef struct {
+ char *chars;
+ int nchars;
+ int delta;
+ XFontSet font_set;
+} XmbTextItem;
+
+typedef struct {
+ wchar_t *chars;
+ int nchars;
+ int delta;
+ XFontSet font_set;
+} XwcTextItem;
+
+#define XNRequiredCharSet "requiredCharSet"
+#define XNQueryOrientation "queryOrientation"
+#define XNBaseFontName "baseFontName"
+#define XNOMAutomatic "omAutomatic"
+#define XNMissingCharSet "missingCharSet"
+#define XNDefaultString "defaultString"
+#define XNOrientation "orientation"
+#define XNDirectionalDependentDrawing "directionalDependentDrawing"
+#define XNContextualDrawing "contextualDrawing"
+#define XNFontInfo "fontInfo"
+
+typedef struct {
+ int charset_count;
+ char **charset_list;
+} XOMCharSetList;
+
+typedef enum {
+ XOMOrientation_LTR_TTB,
+ XOMOrientation_RTL_TTB,
+ XOMOrientation_TTB_LTR,
+ XOMOrientation_TTB_RTL,
+ XOMOrientation_Context
+} XOrientation;
+
+typedef struct {
+ int num_orientation;
+ XOrientation *orientation; /* Input Text description */
+} XOMOrientation;
+
+typedef struct {
+ int num_font;
+ XFontStruct **font_struct_list;
+ char **font_name_list;
+} XOMFontInfo;
+
+typedef struct _XIM *XIM;
+typedef struct _XIC *XIC;
+
+typedef void (*XIMProc)(
+ XIM,
+ XPointer,
+ XPointer
+);
+
+typedef Bool (*XICProc)(
+ XIC,
+ XPointer,
+ XPointer
+);
+
+typedef void (*XIDProc)(
+ Display*,
+ XPointer,
+ XPointer
+);
+
+typedef unsigned long XIMStyle;
+
+typedef struct {
+ unsigned short count_styles;
+ XIMStyle *supported_styles;
+} XIMStyles;
+
+#define XIMPreeditArea 0x0001L
+#define XIMPreeditCallbacks 0x0002L
+#define XIMPreeditPosition 0x0004L
+#define XIMPreeditNothing 0x0008L
+#define XIMPreeditNone 0x0010L
+#define XIMStatusArea 0x0100L
+#define XIMStatusCallbacks 0x0200L
+#define XIMStatusNothing 0x0400L
+#define XIMStatusNone 0x0800L
+
+#define XNVaNestedList "XNVaNestedList"
+#define XNQueryInputStyle "queryInputStyle"
+#define XNClientWindow "clientWindow"
+#define XNInputStyle "inputStyle"
+#define XNFocusWindow "focusWindow"
+#define XNResourceName "resourceName"
+#define XNResourceClass "resourceClass"
+#define XNGeometryCallback "geometryCallback"
+#define XNDestroyCallback "destroyCallback"
+#define XNFilterEvents "filterEvents"
+#define XNPreeditStartCallback "preeditStartCallback"
+#define XNPreeditDoneCallback "preeditDoneCallback"
+#define XNPreeditDrawCallback "preeditDrawCallback"
+#define XNPreeditCaretCallback "preeditCaretCallback"
+#define XNPreeditStateNotifyCallback "preeditStateNotifyCallback"
+#define XNPreeditAttributes "preeditAttributes"
+#define XNStatusStartCallback "statusStartCallback"
+#define XNStatusDoneCallback "statusDoneCallback"
+#define XNStatusDrawCallback "statusDrawCallback"
+#define XNStatusAttributes "statusAttributes"
+#define XNArea "area"
+#define XNAreaNeeded "areaNeeded"
+#define XNSpotLocation "spotLocation"
+#define XNColormap "colorMap"
+#define XNStdColormap "stdColorMap"
+#define XNForeground "foreground"
+#define XNBackground "background"
+#define XNBackgroundPixmap "backgroundPixmap"
+#define XNFontSet "fontSet"
+#define XNLineSpace "lineSpace"
+#define XNCursor "cursor"
+
+#define XNQueryIMValuesList "queryIMValuesList"
+#define XNQueryICValuesList "queryICValuesList"
+#define XNVisiblePosition "visiblePosition"
+#define XNR6PreeditCallback "r6PreeditCallback"
+#define XNStringConversionCallback "stringConversionCallback"
+#define XNStringConversion "stringConversion"
+#define XNResetState "resetState"
+#define XNHotKey "hotKey"
+#define XNHotKeyState "hotKeyState"
+#define XNPreeditState "preeditState"
+#define XNSeparatorofNestedList "separatorofNestedList"
+
+#define XBufferOverflow -1
+#define XLookupNone 1
+#define XLookupChars 2
+#define XLookupKeySym 3
+#define XLookupBoth 4
+
+typedef void *XVaNestedList;
+
+typedef struct {
+ XPointer client_data;
+ XIMProc callback;
+} XIMCallback;
+
+typedef struct {
+ XPointer client_data;
+ XICProc callback;
+} XICCallback;
+
+typedef unsigned long XIMFeedback;
+
+#define XIMReverse 1L
+#define XIMUnderline (1L<<1)
+#define XIMHighlight (1L<<2)
+#define XIMPrimary (1L<<5)
+#define XIMSecondary (1L<<6)
+#define XIMTertiary (1L<<7)
+#define XIMVisibleToForward (1L<<8)
+#define XIMVisibleToBackword (1L<<9)
+#define XIMVisibleToCenter (1L<<10)
+
+typedef struct _XIMText {
+ unsigned short length;
+ XIMFeedback *feedback;
+ Bool encoding_is_wchar;
+ union {
+ char *multi_byte;
+ wchar_t *wide_char;
+ } string;
+} XIMText;
+
+typedef unsigned long XIMPreeditState;
+
+#define XIMPreeditUnKnown 0L
+#define XIMPreeditEnable 1L
+#define XIMPreeditDisable (1L<<1)
+
+typedef struct _XIMPreeditStateNotifyCallbackStruct {
+ XIMPreeditState state;
+} XIMPreeditStateNotifyCallbackStruct;
+
+typedef unsigned long XIMResetState;
+
+#define XIMInitialState 1L
+#define XIMPreserveState (1L<<1)
+
+typedef unsigned long XIMStringConversionFeedback;
+
+#define XIMStringConversionLeftEdge (0x00000001)
+#define XIMStringConversionRightEdge (0x00000002)
+#define XIMStringConversionTopEdge (0x00000004)
+#define XIMStringConversionBottomEdge (0x00000008)
+#define XIMStringConversionConcealed (0x00000010)
+#define XIMStringConversionWrapped (0x00000020)
+
+typedef struct _XIMStringConversionText {
+ unsigned short length;
+ XIMStringConversionFeedback *feedback;
+ Bool encoding_is_wchar;
+ union {
+ char *mbs;
+ wchar_t *wcs;
+ } string;
+} XIMStringConversionText;
+
+typedef unsigned short XIMStringConversionPosition;
+
+typedef unsigned short XIMStringConversionType;
+
+#define XIMStringConversionBuffer (0x0001)
+#define XIMStringConversionLine (0x0002)
+#define XIMStringConversionWord (0x0003)
+#define XIMStringConversionChar (0x0004)
+
+typedef unsigned short XIMStringConversionOperation;
+
+#define XIMStringConversionSubstitution (0x0001)
+#define XIMStringConversionRetrieval (0x0002)
+
+typedef enum {
+ XIMForwardChar, XIMBackwardChar,
+ XIMForwardWord, XIMBackwardWord,
+ XIMCaretUp, XIMCaretDown,
+ XIMNextLine, XIMPreviousLine,
+ XIMLineStart, XIMLineEnd,
+ XIMAbsolutePosition,
+ XIMDontChange
+} XIMCaretDirection;
+
+typedef struct _XIMStringConversionCallbackStruct {
+ XIMStringConversionPosition position;
+ XIMCaretDirection direction;
+ XIMStringConversionOperation operation;
+ unsigned short factor;
+ XIMStringConversionText *text;
+} XIMStringConversionCallbackStruct;
+
+typedef struct _XIMPreeditDrawCallbackStruct {
+ int caret; /* Cursor offset within pre-edit string */
+ int chg_first; /* Starting change position */
+ int chg_length; /* Length of the change in character count */
+ XIMText *text;
+} XIMPreeditDrawCallbackStruct;
+
+typedef enum {
+ XIMIsInvisible, /* Disable caret feedback */
+ XIMIsPrimary, /* UI defined caret feedback */
+ XIMIsSecondary /* UI defined caret feedback */
+} XIMCaretStyle;
+
+typedef struct _XIMPreeditCaretCallbackStruct {
+ int position; /* Caret offset within pre-edit string */
+ XIMCaretDirection direction; /* Caret moves direction */
+ XIMCaretStyle style; /* Feedback of the caret */
+} XIMPreeditCaretCallbackStruct;
+
+typedef enum {
+ XIMTextType,
+ XIMBitmapType
+} XIMStatusDataType;
+
+typedef struct _XIMStatusDrawCallbackStruct {
+ XIMStatusDataType type;
+ union {
+ XIMText *text;
+ Pixmap bitmap;
+ } data;
+} XIMStatusDrawCallbackStruct;
+
+typedef struct _XIMHotKeyTrigger {
+ KeySym keysym;
+ int modifier;
+ int modifier_mask;
+} XIMHotKeyTrigger;
+
+typedef struct _XIMHotKeyTriggers {
+ int num_hot_key;
+ XIMHotKeyTrigger *key;
+} XIMHotKeyTriggers;
+
+typedef unsigned long XIMHotKeyState;
+
+#define XIMHotKeyStateON (0x0001L)
+#define XIMHotKeyStateOFF (0x0002L)
+
+typedef struct {
+ unsigned short count_values;
+ char **supported_values;
+} XIMValuesList;
+
+_XFUNCPROTOBEGIN
+
+#if defined(WIN32) && !defined(_XLIBINT_)
+#define _Xdebug (*_Xdebug_p)
+#endif
+
+extern int _Xdebug;
+
+extern XFontStruct *XLoadQueryFont(
+ Display* /* display */,
+ _Xconst char* /* name */
+);
+
+extern XFontStruct *XQueryFont(
+ Display* /* display */,
+ XID /* font_ID */
+);
+
+
+extern XTimeCoord *XGetMotionEvents(
+ Display* /* display */,
+ Window /* w */,
+ Time /* start */,
+ Time /* stop */,
+ int* /* nevents_return */
+);
+
+extern XModifierKeymap *XDeleteModifiermapEntry(
+ XModifierKeymap* /* modmap */,
+#if NeedWidePrototypes
+ unsigned int /* keycode_entry */,
+#else
+ KeyCode /* keycode_entry */,
+#endif
+ int /* modifier */
+);
+
+extern XModifierKeymap *XGetModifierMapping(
+ Display* /* display */
+);
+
+extern XModifierKeymap *XInsertModifiermapEntry(
+ XModifierKeymap* /* modmap */,
+#if NeedWidePrototypes
+ unsigned int /* keycode_entry */,
+#else
+ KeyCode /* keycode_entry */,
+#endif
+ int /* modifier */
+);
+
+extern XModifierKeymap *XNewModifiermap(
+ int /* max_keys_per_mod */
+);
+
+extern XImage *XCreateImage(
+ Display* /* display */,
+ Visual* /* visual */,
+ unsigned int /* depth */,
+ int /* format */,
+ int /* offset */,
+ char* /* data */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* bitmap_pad */,
+ int /* bytes_per_line */
+);
+extern Status XInitImage(
+ XImage* /* image */
+);
+extern XImage *XGetImage(
+ Display* /* display */,
+ Drawable /* d */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned long /* plane_mask */,
+ int /* format */
+);
+extern XImage *XGetSubImage(
+ Display* /* display */,
+ Drawable /* d */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned long /* plane_mask */,
+ int /* format */,
+ XImage* /* dest_image */,
+ int /* dest_x */,
+ int /* dest_y */
+);
+
+/*
+ * X function declarations.
+ */
+extern Display *XOpenDisplay(
+ _Xconst char* /* display_name */
+);
+
+extern void XrmInitialize(
+ void
+);
+
+extern char *XFetchBytes(
+ Display* /* display */,
+ int* /* nbytes_return */
+);
+extern char *XFetchBuffer(
+ Display* /* display */,
+ int* /* nbytes_return */,
+ int /* buffer */
+);
+extern char *XGetAtomName(
+ Display* /* display */,
+ Atom /* atom */
+);
+extern Status XGetAtomNames(
+ Display* /* dpy */,
+ Atom* /* atoms */,
+ int /* count */,
+ char** /* names_return */
+);
+extern char *XGetDefault(
+ Display* /* display */,
+ _Xconst char* /* program */,
+ _Xconst char* /* option */
+);
+extern char *XDisplayName(
+ _Xconst char* /* string */
+);
+extern char *XKeysymToString(
+ KeySym /* keysym */
+);
+
+extern int (*XSynchronize(
+ Display* /* display */,
+ Bool /* onoff */
+))(
+ Display* /* display */
+);
+extern int (*XSetAfterFunction(
+ Display* /* display */,
+ int (*) (
+ Display* /* display */
+ ) /* procedure */
+))(
+ Display* /* display */
+);
+extern Atom XInternAtom(
+ Display* /* display */,
+ _Xconst char* /* atom_name */,
+ Bool /* only_if_exists */
+);
+extern Status XInternAtoms(
+ Display* /* dpy */,
+ char** /* names */,
+ int /* count */,
+ Bool /* onlyIfExists */,
+ Atom* /* atoms_return */
+);
+extern Colormap XCopyColormapAndFree(
+ Display* /* display */,
+ Colormap /* colormap */
+);
+extern Colormap XCreateColormap(
+ Display* /* display */,
+ Window /* w */,
+ Visual* /* visual */,
+ int /* alloc */
+);
+extern Cursor XCreatePixmapCursor(
+ Display* /* display */,
+ Pixmap /* source */,
+ Pixmap /* mask */,
+ XColor* /* foreground_color */,
+ XColor* /* background_color */,
+ unsigned int /* x */,
+ unsigned int /* y */
+);
+extern Cursor XCreateGlyphCursor(
+ Display* /* display */,
+ Font /* source_font */,
+ Font /* mask_font */,
+ unsigned int /* source_char */,
+ unsigned int /* mask_char */,
+ XColor _Xconst * /* foreground_color */,
+ XColor _Xconst * /* background_color */
+);
+extern Cursor XCreateFontCursor(
+ Display* /* display */,
+ unsigned int /* shape */
+);
+extern Font XLoadFont(
+ Display* /* display */,
+ _Xconst char* /* name */
+);
+extern GC XCreateGC(
+ Display* /* display */,
+ Drawable /* d */,
+ unsigned long /* valuemask */,
+ XGCValues* /* values */
+);
+extern GContext XGContextFromGC(
+ GC /* gc */
+);
+extern void XFlushGC(
+ Display* /* display */,
+ GC /* gc */
+);
+extern Pixmap XCreatePixmap(
+ Display* /* display */,
+ Drawable /* d */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int /* depth */
+);
+extern Pixmap XCreateBitmapFromData(
+ Display* /* display */,
+ Drawable /* d */,
+ _Xconst char* /* data */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+extern Pixmap XCreatePixmapFromBitmapData(
+ Display* /* display */,
+ Drawable /* d */,
+ char* /* data */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned long /* fg */,
+ unsigned long /* bg */,
+ unsigned int /* depth */
+);
+extern Window XCreateSimpleWindow(
+ Display* /* display */,
+ Window /* parent */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int /* border_width */,
+ unsigned long /* border */,
+ unsigned long /* background */
+);
+extern Window XGetSelectionOwner(
+ Display* /* display */,
+ Atom /* selection */
+);
+extern Window XCreateWindow(
+ Display* /* display */,
+ Window /* parent */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int /* border_width */,
+ int /* depth */,
+ unsigned int /* class */,
+ Visual* /* visual */,
+ unsigned long /* valuemask */,
+ XSetWindowAttributes* /* attributes */
+);
+extern Colormap *XListInstalledColormaps(
+ Display* /* display */,
+ Window /* w */,
+ int* /* num_return */
+);
+extern char **XListFonts(
+ Display* /* display */,
+ _Xconst char* /* pattern */,
+ int /* maxnames */,
+ int* /* actual_count_return */
+);
+extern char **XListFontsWithInfo(
+ Display* /* display */,
+ _Xconst char* /* pattern */,
+ int /* maxnames */,
+ int* /* count_return */,
+ XFontStruct** /* info_return */
+);
+extern char **XGetFontPath(
+ Display* /* display */,
+ int* /* npaths_return */
+);
+extern char **XListExtensions(
+ Display* /* display */,
+ int* /* nextensions_return */
+);
+extern Atom *XListProperties(
+ Display* /* display */,
+ Window /* w */,
+ int* /* num_prop_return */
+);
+extern XHostAddress *XListHosts(
+ Display* /* display */,
+ int* /* nhosts_return */,
+ Bool* /* state_return */
+);
+extern KeySym XKeycodeToKeysym(
+ Display* /* display */,
+#if NeedWidePrototypes
+ unsigned int /* keycode */,
+#else
+ KeyCode /* keycode */,
+#endif
+ int /* index */
+);
+extern KeySym XLookupKeysym(
+ XKeyEvent* /* key_event */,
+ int /* index */
+);
+extern KeySym *XGetKeyboardMapping(
+ Display* /* display */,
+#if NeedWidePrototypes
+ unsigned int /* first_keycode */,
+#else
+ KeyCode /* first_keycode */,
+#endif
+ int /* keycode_count */,
+ int* /* keysyms_per_keycode_return */
+);
+extern KeySym XStringToKeysym(
+ _Xconst char* /* string */
+);
+extern long XMaxRequestSize(
+ Display* /* display */
+);
+extern long XExtendedMaxRequestSize(
+ Display* /* display */
+);
+extern char *XResourceManagerString(
+ Display* /* display */
+);
+extern char *XScreenResourceString(
+ Screen* /* screen */
+);
+extern unsigned long XDisplayMotionBufferSize(
+ Display* /* display */
+);
+extern VisualID XVisualIDFromVisual(
+ Visual* /* visual */
+);
+
+/* multithread routines */
+
+extern Status XInitThreads(
+ void
+);
+
+extern void XLockDisplay(
+ Display* /* display */
+);
+
+extern void XUnlockDisplay(
+ Display* /* display */
+);
+
+/* routines for dealing with extensions */
+
+extern XExtCodes *XInitExtension(
+ Display* /* display */,
+ _Xconst char* /* name */
+);
+
+extern XExtCodes *XAddExtension(
+ Display* /* display */
+);
+extern XExtData *XFindOnExtensionList(
+ XExtData** /* structure */,
+ int /* number */
+);
+extern XExtData **XEHeadOfExtensionList(
+ XEDataObject /* object */
+);
+
+/* these are routines for which there are also macros */
+extern Window XRootWindow(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern Window XDefaultRootWindow(
+ Display* /* display */
+);
+extern Window XRootWindowOfScreen(
+ Screen* /* screen */
+);
+extern Visual *XDefaultVisual(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern Visual *XDefaultVisualOfScreen(
+ Screen* /* screen */
+);
+extern GC XDefaultGC(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern GC XDefaultGCOfScreen(
+ Screen* /* screen */
+);
+extern unsigned long XBlackPixel(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern unsigned long XWhitePixel(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern unsigned long XAllPlanes(
+ void
+);
+extern unsigned long XBlackPixelOfScreen(
+ Screen* /* screen */
+);
+extern unsigned long XWhitePixelOfScreen(
+ Screen* /* screen */
+);
+extern unsigned long XNextRequest(
+ Display* /* display */
+);
+extern unsigned long XLastKnownRequestProcessed(
+ Display* /* display */
+);
+extern char *XServerVendor(
+ Display* /* display */
+);
+extern char *XDisplayString(
+ Display* /* display */
+);
+extern Colormap XDefaultColormap(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern Colormap XDefaultColormapOfScreen(
+ Screen* /* screen */
+);
+extern Display *XDisplayOfScreen(
+ Screen* /* screen */
+);
+extern Screen *XScreenOfDisplay(
+ Display* /* display */,
+ int /* screen_number */
+);
+extern Screen *XDefaultScreenOfDisplay(
+ Display* /* display */
+);
+extern long XEventMaskOfScreen(
+ Screen* /* screen */
+);
+
+extern int XScreenNumberOfScreen(
+ Screen* /* screen */
+);
+
+typedef int (*XErrorHandler) ( /* WARNING, this type not in Xlib spec */
+ Display* /* display */,
+ XErrorEvent* /* error_event */
+);
+
+extern XErrorHandler XSetErrorHandler (
+ XErrorHandler /* handler */
+);
+
+
+typedef int (*XIOErrorHandler) ( /* WARNING, this type not in Xlib spec */
+ Display* /* display */
+);
+
+extern XIOErrorHandler XSetIOErrorHandler (
+ XIOErrorHandler /* handler */
+);
+
+
+extern XPixmapFormatValues *XListPixmapFormats(
+ Display* /* display */,
+ int* /* count_return */
+);
+extern int *XListDepths(
+ Display* /* display */,
+ int /* screen_number */,
+ int* /* count_return */
+);
+
+/* ICCCM routines for things that don't require special include files; */
+/* other declarations are given in Xutil.h */
+extern Status XReconfigureWMWindow(
+ Display* /* display */,
+ Window /* w */,
+ int /* screen_number */,
+ unsigned int /* mask */,
+ XWindowChanges* /* changes */
+);
+
+extern Status XGetWMProtocols(
+ Display* /* display */,
+ Window /* w */,
+ Atom** /* protocols_return */,
+ int* /* count_return */
+);
+extern Status XSetWMProtocols(
+ Display* /* display */,
+ Window /* w */,
+ Atom* /* protocols */,
+ int /* count */
+);
+extern Status XIconifyWindow(
+ Display* /* display */,
+ Window /* w */,
+ int /* screen_number */
+);
+extern Status XWithdrawWindow(
+ Display* /* display */,
+ Window /* w */,
+ int /* screen_number */
+);
+extern Status XGetCommand(
+ Display* /* display */,
+ Window /* w */,
+ char*** /* argv_return */,
+ int* /* argc_return */
+);
+extern Status XGetWMColormapWindows(
+ Display* /* display */,
+ Window /* w */,
+ Window** /* windows_return */,
+ int* /* count_return */
+);
+extern Status XSetWMColormapWindows(
+ Display* /* display */,
+ Window /* w */,
+ Window* /* colormap_windows */,
+ int /* count */
+);
+extern void XFreeStringList(
+ char** /* list */
+);
+extern int XSetTransientForHint(
+ Display* /* display */,
+ Window /* w */,
+ Window /* prop_window */
+);
+
+/* The following are given in alphabetical order */
+
+extern int XActivateScreenSaver(
+ Display* /* display */
+);
+
+extern int XAddHost(
+ Display* /* display */,
+ XHostAddress* /* host */
+);
+
+extern int XAddHosts(
+ Display* /* display */,
+ XHostAddress* /* hosts */,
+ int /* num_hosts */
+);
+
+extern int XAddToExtensionList(
+ struct _XExtData** /* structure */,
+ XExtData* /* ext_data */
+);
+
+extern int XAddToSaveSet(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern Status XAllocColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ XColor* /* screen_in_out */
+);
+
+extern Status XAllocColorCells(
+ Display* /* display */,
+ Colormap /* colormap */,
+ Bool /* contig */,
+ unsigned long* /* plane_masks_return */,
+ unsigned int /* nplanes */,
+ unsigned long* /* pixels_return */,
+ unsigned int /* npixels */
+);
+
+extern Status XAllocColorPlanes(
+ Display* /* display */,
+ Colormap /* colormap */,
+ Bool /* contig */,
+ unsigned long* /* pixels_return */,
+ int /* ncolors */,
+ int /* nreds */,
+ int /* ngreens */,
+ int /* nblues */,
+ unsigned long* /* rmask_return */,
+ unsigned long* /* gmask_return */,
+ unsigned long* /* bmask_return */
+);
+
+extern Status XAllocNamedColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ _Xconst char* /* color_name */,
+ XColor* /* screen_def_return */,
+ XColor* /* exact_def_return */
+);
+
+extern int XAllowEvents(
+ Display* /* display */,
+ int /* event_mode */,
+ Time /* time */
+);
+
+extern int XAutoRepeatOff(
+ Display* /* display */
+);
+
+extern int XAutoRepeatOn(
+ Display* /* display */
+);
+
+extern int XBell(
+ Display* /* display */,
+ int /* percent */
+);
+
+extern int XBitmapBitOrder(
+ Display* /* display */
+);
+
+extern int XBitmapPad(
+ Display* /* display */
+);
+
+extern int XBitmapUnit(
+ Display* /* display */
+);
+
+extern int XCellsOfScreen(
+ Screen* /* screen */
+);
+
+extern int XChangeActivePointerGrab(
+ Display* /* display */,
+ unsigned int /* event_mask */,
+ Cursor /* cursor */,
+ Time /* time */
+);
+
+extern int XChangeGC(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* valuemask */,
+ XGCValues* /* values */
+);
+
+extern int XChangeKeyboardControl(
+ Display* /* display */,
+ unsigned long /* value_mask */,
+ XKeyboardControl* /* values */
+);
+
+extern int XChangeKeyboardMapping(
+ Display* /* display */,
+ int /* first_keycode */,
+ int /* keysyms_per_keycode */,
+ KeySym* /* keysyms */,
+ int /* num_codes */
+);
+
+extern int XChangePointerControl(
+ Display* /* display */,
+ Bool /* do_accel */,
+ Bool /* do_threshold */,
+ int /* accel_numerator */,
+ int /* accel_denominator */,
+ int /* threshold */
+);
+
+extern int XChangeProperty(
+ Display* /* display */,
+ Window /* w */,
+ Atom /* property */,
+ Atom /* type */,
+ int /* format */,
+ int /* mode */,
+ _Xconst unsigned char* /* data */,
+ int /* nelements */
+);
+
+extern int XChangeSaveSet(
+ Display* /* display */,
+ Window /* w */,
+ int /* change_mode */
+);
+
+extern int XChangeWindowAttributes(
+ Display* /* display */,
+ Window /* w */,
+ unsigned long /* valuemask */,
+ XSetWindowAttributes* /* attributes */
+);
+
+extern Bool XCheckIfEvent(
+ Display* /* display */,
+ XEvent* /* event_return */,
+ Bool (*) (
+ Display* /* display */,
+ XEvent* /* event */,
+ XPointer /* arg */
+ ) /* predicate */,
+ XPointer /* arg */
+);
+
+extern Bool XCheckMaskEvent(
+ Display* /* display */,
+ long /* event_mask */,
+ XEvent* /* event_return */
+);
+
+extern Bool XCheckTypedEvent(
+ Display* /* display */,
+ int /* event_type */,
+ XEvent* /* event_return */
+);
+
+extern Bool XCheckTypedWindowEvent(
+ Display* /* display */,
+ Window /* w */,
+ int /* event_type */,
+ XEvent* /* event_return */
+);
+
+extern Bool XCheckWindowEvent(
+ Display* /* display */,
+ Window /* w */,
+ long /* event_mask */,
+ XEvent* /* event_return */
+);
+
+extern int XCirculateSubwindows(
+ Display* /* display */,
+ Window /* w */,
+ int /* direction */
+);
+
+extern int XCirculateSubwindowsDown(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XCirculateSubwindowsUp(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XClearArea(
+ Display* /* display */,
+ Window /* w */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ Bool /* exposures */
+);
+
+extern int XClearWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XCloseDisplay(
+ Display* /* display */
+);
+
+extern int XConfigureWindow(
+ Display* /* display */,
+ Window /* w */,
+ unsigned int /* value_mask */,
+ XWindowChanges* /* values */
+);
+
+extern int XConnectionNumber(
+ Display* /* display */
+);
+
+extern int XConvertSelection(
+ Display* /* display */,
+ Atom /* selection */,
+ Atom /* target */,
+ Atom /* property */,
+ Window /* requestor */,
+ Time /* time */
+);
+
+extern int XCopyArea(
+ Display* /* display */,
+ Drawable /* src */,
+ Drawable /* dest */,
+ GC /* gc */,
+ int /* src_x */,
+ int /* src_y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* dest_x */,
+ int /* dest_y */
+);
+
+extern int XCopyGC(
+ Display* /* display */,
+ GC /* src */,
+ unsigned long /* valuemask */,
+ GC /* dest */
+);
+
+extern int XCopyPlane(
+ Display* /* display */,
+ Drawable /* src */,
+ Drawable /* dest */,
+ GC /* gc */,
+ int /* src_x */,
+ int /* src_y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* dest_x */,
+ int /* dest_y */,
+ unsigned long /* plane */
+);
+
+extern int XDefaultDepth(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDefaultDepthOfScreen(
+ Screen* /* screen */
+);
+
+extern int XDefaultScreen(
+ Display* /* display */
+);
+
+extern int XDefineCursor(
+ Display* /* display */,
+ Window /* w */,
+ Cursor /* cursor */
+);
+
+extern int XDeleteProperty(
+ Display* /* display */,
+ Window /* w */,
+ Atom /* property */
+);
+
+extern int XDestroyWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XDestroySubwindows(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XDoesBackingStore(
+ Screen* /* screen */
+);
+
+extern Bool XDoesSaveUnders(
+ Screen* /* screen */
+);
+
+extern int XDisableAccessControl(
+ Display* /* display */
+);
+
+
+extern int XDisplayCells(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDisplayHeight(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDisplayHeightMM(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDisplayKeycodes(
+ Display* /* display */,
+ int* /* min_keycodes_return */,
+ int* /* max_keycodes_return */
+);
+
+extern int XDisplayPlanes(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDisplayWidth(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDisplayWidthMM(
+ Display* /* display */,
+ int /* screen_number */
+);
+
+extern int XDrawArc(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* angle1 */,
+ int /* angle2 */
+);
+
+extern int XDrawArcs(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XArc* /* arcs */,
+ int /* narcs */
+);
+
+extern int XDrawImageString(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* string */,
+ int /* length */
+);
+
+extern int XDrawImageString16(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst XChar2b* /* string */,
+ int /* length */
+);
+
+extern int XDrawLine(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x1 */,
+ int /* y1 */,
+ int /* x2 */,
+ int /* y2 */
+);
+
+extern int XDrawLines(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XPoint* /* points */,
+ int /* npoints */,
+ int /* mode */
+);
+
+extern int XDrawPoint(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */
+);
+
+extern int XDrawPoints(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XPoint* /* points */,
+ int /* npoints */,
+ int /* mode */
+);
+
+extern int XDrawRectangle(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XDrawRectangles(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XRectangle* /* rectangles */,
+ int /* nrectangles */
+);
+
+extern int XDrawSegments(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XSegment* /* segments */,
+ int /* nsegments */
+);
+
+extern int XDrawString(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* string */,
+ int /* length */
+);
+
+extern int XDrawString16(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst XChar2b* /* string */,
+ int /* length */
+);
+
+extern int XDrawText(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ XTextItem* /* items */,
+ int /* nitems */
+);
+
+extern int XDrawText16(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ XTextItem16* /* items */,
+ int /* nitems */
+);
+
+extern int XEnableAccessControl(
+ Display* /* display */
+);
+
+extern int XEventsQueued(
+ Display* /* display */,
+ int /* mode */
+);
+
+extern Status XFetchName(
+ Display* /* display */,
+ Window /* w */,
+ char** /* window_name_return */
+);
+
+extern int XFillArc(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* angle1 */,
+ int /* angle2 */
+);
+
+extern int XFillArcs(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XArc* /* arcs */,
+ int /* narcs */
+);
+
+extern int XFillPolygon(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XPoint* /* points */,
+ int /* npoints */,
+ int /* shape */,
+ int /* mode */
+);
+
+extern int XFillRectangle(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XFillRectangles(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XRectangle* /* rectangles */,
+ int /* nrectangles */
+);
+
+extern int XFlush(
+ Display* /* display */
+);
+
+extern int XForceScreenSaver(
+ Display* /* display */,
+ int /* mode */
+);
+
+extern int XFree(
+ void* /* data */
+);
+
+extern int XFreeColormap(
+ Display* /* display */,
+ Colormap /* colormap */
+);
+
+extern int XFreeColors(
+ Display* /* display */,
+ Colormap /* colormap */,
+ unsigned long* /* pixels */,
+ int /* npixels */,
+ unsigned long /* planes */
+);
+
+extern int XFreeCursor(
+ Display* /* display */,
+ Cursor /* cursor */
+);
+
+extern int XFreeExtensionList(
+ char** /* list */
+);
+
+extern int XFreeFont(
+ Display* /* display */,
+ XFontStruct* /* font_struct */
+);
+
+extern int XFreeFontInfo(
+ char** /* names */,
+ XFontStruct* /* free_info */,
+ int /* actual_count */
+);
+
+extern int XFreeFontNames(
+ char** /* list */
+);
+
+extern int XFreeFontPath(
+ char** /* list */
+);
+
+extern int XFreeGC(
+ Display* /* display */,
+ GC /* gc */
+);
+
+extern int XFreeModifiermap(
+ XModifierKeymap* /* modmap */
+);
+
+extern int XFreePixmap(
+ Display* /* display */,
+ Pixmap /* pixmap */
+);
+
+extern int XGeometry(
+ Display* /* display */,
+ int /* screen */,
+ _Xconst char* /* position */,
+ _Xconst char* /* default_position */,
+ unsigned int /* bwidth */,
+ unsigned int /* fwidth */,
+ unsigned int /* fheight */,
+ int /* xadder */,
+ int /* yadder */,
+ int* /* x_return */,
+ int* /* y_return */,
+ int* /* width_return */,
+ int* /* height_return */
+);
+
+extern int XGetErrorDatabaseText(
+ Display* /* display */,
+ _Xconst char* /* name */,
+ _Xconst char* /* message */,
+ _Xconst char* /* default_string */,
+ char* /* buffer_return */,
+ int /* length */
+);
+
+extern int XGetErrorText(
+ Display* /* display */,
+ int /* code */,
+ char* /* buffer_return */,
+ int /* length */
+);
+
+extern Bool XGetFontProperty(
+ XFontStruct* /* font_struct */,
+ Atom /* atom */,
+ unsigned long* /* value_return */
+);
+
+extern Status XGetGCValues(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* valuemask */,
+ XGCValues* /* values_return */
+);
+
+extern Status XGetGeometry(
+ Display* /* display */,
+ Drawable /* d */,
+ Window* /* root_return */,
+ int* /* x_return */,
+ int* /* y_return */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */,
+ unsigned int* /* border_width_return */,
+ unsigned int* /* depth_return */
+);
+
+extern Status XGetIconName(
+ Display* /* display */,
+ Window /* w */,
+ char** /* icon_name_return */
+);
+
+extern int XGetInputFocus(
+ Display* /* display */,
+ Window* /* focus_return */,
+ int* /* revert_to_return */
+);
+
+extern int XGetKeyboardControl(
+ Display* /* display */,
+ XKeyboardState* /* values_return */
+);
+
+extern int XGetPointerControl(
+ Display* /* display */,
+ int* /* accel_numerator_return */,
+ int* /* accel_denominator_return */,
+ int* /* threshold_return */
+);
+
+extern int XGetPointerMapping(
+ Display* /* display */,
+ unsigned char* /* map_return */,
+ int /* nmap */
+);
+
+extern int XGetScreenSaver(
+ Display* /* display */,
+ int* /* timeout_return */,
+ int* /* interval_return */,
+ int* /* prefer_blanking_return */,
+ int* /* allow_exposures_return */
+);
+
+extern Status XGetTransientForHint(
+ Display* /* display */,
+ Window /* w */,
+ Window* /* prop_window_return */
+);
+
+extern int XGetWindowProperty(
+ Display* /* display */,
+ Window /* w */,
+ Atom /* property */,
+ long /* long_offset */,
+ long /* long_length */,
+ Bool /* delete */,
+ Atom /* req_type */,
+ Atom* /* actual_type_return */,
+ int* /* actual_format_return */,
+ unsigned long* /* nitems_return */,
+ unsigned long* /* bytes_after_return */,
+ unsigned char** /* prop_return */
+);
+
+extern Status XGetWindowAttributes(
+ Display* /* display */,
+ Window /* w */,
+ XWindowAttributes* /* window_attributes_return */
+);
+
+extern int XGrabButton(
+ Display* /* display */,
+ unsigned int /* button */,
+ unsigned int /* modifiers */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ unsigned int /* event_mask */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */,
+ Window /* confine_to */,
+ Cursor /* cursor */
+);
+
+extern int XGrabKey(
+ Display* /* display */,
+ int /* keycode */,
+ unsigned int /* modifiers */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */
+);
+
+extern int XGrabKeyboard(
+ Display* /* display */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */,
+ Time /* time */
+);
+
+extern int XGrabPointer(
+ Display* /* display */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ unsigned int /* event_mask */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */,
+ Window /* confine_to */,
+ Cursor /* cursor */,
+ Time /* time */
+);
+
+extern int XGrabServer(
+ Display* /* display */
+);
+
+extern int XHeightMMOfScreen(
+ Screen* /* screen */
+);
+
+extern int XHeightOfScreen(
+ Screen* /* screen */
+);
+
+extern int XIfEvent(
+ Display* /* display */,
+ XEvent* /* event_return */,
+ Bool (*) (
+ Display* /* display */,
+ XEvent* /* event */,
+ XPointer /* arg */
+ ) /* predicate */,
+ XPointer /* arg */
+);
+
+extern int XImageByteOrder(
+ Display* /* display */
+);
+
+extern int XInstallColormap(
+ Display* /* display */,
+ Colormap /* colormap */
+);
+
+extern KeyCode XKeysymToKeycode(
+ Display* /* display */,
+ KeySym /* keysym */
+);
+
+extern int XKillClient(
+ Display* /* display */,
+ XID /* resource */
+);
+
+extern Status XLookupColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ _Xconst char* /* color_name */,
+ XColor* /* exact_def_return */,
+ XColor* /* screen_def_return */
+);
+
+extern int XLowerWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XMapRaised(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XMapSubwindows(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XMapWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XMaskEvent(
+ Display* /* display */,
+ long /* event_mask */,
+ XEvent* /* event_return */
+);
+
+extern int XMaxCmapsOfScreen(
+ Screen* /* screen */
+);
+
+extern int XMinCmapsOfScreen(
+ Screen* /* screen */
+);
+
+extern int XMoveResizeWindow(
+ Display* /* display */,
+ Window /* w */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XMoveWindow(
+ Display* /* display */,
+ Window /* w */,
+ int /* x */,
+ int /* y */
+);
+
+extern int XNextEvent(
+ Display* /* display */,
+ XEvent* /* event_return */
+);
+
+extern int XNoOp(
+ Display* /* display */
+);
+
+extern Status XParseColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ _Xconst char* /* spec */,
+ XColor* /* exact_def_return */
+);
+
+extern int XParseGeometry(
+ _Xconst char* /* parsestring */,
+ int* /* x_return */,
+ int* /* y_return */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */
+);
+
+extern int XPeekEvent(
+ Display* /* display */,
+ XEvent* /* event_return */
+);
+
+extern int XPeekIfEvent(
+ Display* /* display */,
+ XEvent* /* event_return */,
+ Bool (*) (
+ Display* /* display */,
+ XEvent* /* event */,
+ XPointer /* arg */
+ ) /* predicate */,
+ XPointer /* arg */
+);
+
+extern int XPending(
+ Display* /* display */
+);
+
+extern int XPlanesOfScreen(
+ Screen* /* screen */
+);
+
+extern int XProtocolRevision(
+ Display* /* display */
+);
+
+extern int XProtocolVersion(
+ Display* /* display */
+);
+
+
+extern int XPutBackEvent(
+ Display* /* display */,
+ XEvent* /* event */
+);
+
+extern int XPutImage(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ XImage* /* image */,
+ int /* src_x */,
+ int /* src_y */,
+ int /* dest_x */,
+ int /* dest_y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XQLength(
+ Display* /* display */
+);
+
+extern Status XQueryBestCursor(
+ Display* /* display */,
+ Drawable /* d */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */
+);
+
+extern Status XQueryBestSize(
+ Display* /* display */,
+ int /* class */,
+ Drawable /* which_screen */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */
+);
+
+extern Status XQueryBestStipple(
+ Display* /* display */,
+ Drawable /* which_screen */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */
+);
+
+extern Status XQueryBestTile(
+ Display* /* display */,
+ Drawable /* which_screen */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */
+);
+
+extern int XQueryColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ XColor* /* def_in_out */
+);
+
+extern int XQueryColors(
+ Display* /* display */,
+ Colormap /* colormap */,
+ XColor* /* defs_in_out */,
+ int /* ncolors */
+);
+
+extern Bool XQueryExtension(
+ Display* /* display */,
+ _Xconst char* /* name */,
+ int* /* major_opcode_return */,
+ int* /* first_event_return */,
+ int* /* first_error_return */
+);
+
+extern int XQueryKeymap(
+ Display* /* display */,
+ char [32] /* keys_return */
+);
+
+extern Bool XQueryPointer(
+ Display* /* display */,
+ Window /* w */,
+ Window* /* root_return */,
+ Window* /* child_return */,
+ int* /* root_x_return */,
+ int* /* root_y_return */,
+ int* /* win_x_return */,
+ int* /* win_y_return */,
+ unsigned int* /* mask_return */
+);
+
+extern int XQueryTextExtents(
+ Display* /* display */,
+ XID /* font_ID */,
+ _Xconst char* /* string */,
+ int /* nchars */,
+ int* /* direction_return */,
+ int* /* font_ascent_return */,
+ int* /* font_descent_return */,
+ XCharStruct* /* overall_return */
+);
+
+extern int XQueryTextExtents16(
+ Display* /* display */,
+ XID /* font_ID */,
+ _Xconst XChar2b* /* string */,
+ int /* nchars */,
+ int* /* direction_return */,
+ int* /* font_ascent_return */,
+ int* /* font_descent_return */,
+ XCharStruct* /* overall_return */
+);
+
+extern Status XQueryTree(
+ Display* /* display */,
+ Window /* w */,
+ Window* /* root_return */,
+ Window* /* parent_return */,
+ Window** /* children_return */,
+ unsigned int* /* nchildren_return */
+);
+
+extern int XRaiseWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XReadBitmapFile(
+ Display* /* display */,
+ Drawable /* d */,
+ _Xconst char* /* filename */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */,
+ Pixmap* /* bitmap_return */,
+ int* /* x_hot_return */,
+ int* /* y_hot_return */
+);
+
+extern int XReadBitmapFileData(
+ _Xconst char* /* filename */,
+ unsigned int* /* width_return */,
+ unsigned int* /* height_return */,
+ unsigned char** /* data_return */,
+ int* /* x_hot_return */,
+ int* /* y_hot_return */
+);
+
+extern int XRebindKeysym(
+ Display* /* display */,
+ KeySym /* keysym */,
+ KeySym* /* list */,
+ int /* mod_count */,
+ _Xconst unsigned char* /* string */,
+ int /* bytes_string */
+);
+
+extern int XRecolorCursor(
+ Display* /* display */,
+ Cursor /* cursor */,
+ XColor* /* foreground_color */,
+ XColor* /* background_color */
+);
+
+extern int XRefreshKeyboardMapping(
+ XMappingEvent* /* event_map */
+);
+
+extern int XRemoveFromSaveSet(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XRemoveHost(
+ Display* /* display */,
+ XHostAddress* /* host */
+);
+
+extern int XRemoveHosts(
+ Display* /* display */,
+ XHostAddress* /* hosts */,
+ int /* num_hosts */
+);
+
+extern int XReparentWindow(
+ Display* /* display */,
+ Window /* w */,
+ Window /* parent */,
+ int /* x */,
+ int /* y */
+);
+
+extern int XResetScreenSaver(
+ Display* /* display */
+);
+
+extern int XResizeWindow(
+ Display* /* display */,
+ Window /* w */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XRestackWindows(
+ Display* /* display */,
+ Window* /* windows */,
+ int /* nwindows */
+);
+
+extern int XRotateBuffers(
+ Display* /* display */,
+ int /* rotate */
+);
+
+extern int XRotateWindowProperties(
+ Display* /* display */,
+ Window /* w */,
+ Atom* /* properties */,
+ int /* num_prop */,
+ int /* npositions */
+);
+
+extern int XScreenCount(
+ Display* /* display */
+);
+
+extern int XSelectInput(
+ Display* /* display */,
+ Window /* w */,
+ long /* event_mask */
+);
+
+extern Status XSendEvent(
+ Display* /* display */,
+ Window /* w */,
+ Bool /* propagate */,
+ long /* event_mask */,
+ XEvent* /* event_send */
+);
+
+extern int XSetAccessControl(
+ Display* /* display */,
+ int /* mode */
+);
+
+extern int XSetArcMode(
+ Display* /* display */,
+ GC /* gc */,
+ int /* arc_mode */
+);
+
+extern int XSetBackground(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* background */
+);
+
+extern int XSetClipMask(
+ Display* /* display */,
+ GC /* gc */,
+ Pixmap /* pixmap */
+);
+
+extern int XSetClipOrigin(
+ Display* /* display */,
+ GC /* gc */,
+ int /* clip_x_origin */,
+ int /* clip_y_origin */
+);
+
+extern int XSetClipRectangles(
+ Display* /* display */,
+ GC /* gc */,
+ int /* clip_x_origin */,
+ int /* clip_y_origin */,
+ XRectangle* /* rectangles */,
+ int /* n */,
+ int /* ordering */
+);
+
+extern int XSetCloseDownMode(
+ Display* /* display */,
+ int /* close_mode */
+);
+
+extern int XSetCommand(
+ Display* /* display */,
+ Window /* w */,
+ char** /* argv */,
+ int /* argc */
+);
+
+extern int XSetDashes(
+ Display* /* display */,
+ GC /* gc */,
+ int /* dash_offset */,
+ _Xconst char* /* dash_list */,
+ int /* n */
+);
+
+extern int XSetFillRule(
+ Display* /* display */,
+ GC /* gc */,
+ int /* fill_rule */
+);
+
+extern int XSetFillStyle(
+ Display* /* display */,
+ GC /* gc */,
+ int /* fill_style */
+);
+
+extern int XSetFont(
+ Display* /* display */,
+ GC /* gc */,
+ Font /* font */
+);
+
+extern int XSetFontPath(
+ Display* /* display */,
+ char** /* directories */,
+ int /* ndirs */
+);
+
+extern int XSetForeground(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* foreground */
+);
+
+extern int XSetFunction(
+ Display* /* display */,
+ GC /* gc */,
+ int /* function */
+);
+
+extern int XSetGraphicsExposures(
+ Display* /* display */,
+ GC /* gc */,
+ Bool /* graphics_exposures */
+);
+
+extern int XSetIconName(
+ Display* /* display */,
+ Window /* w */,
+ _Xconst char* /* icon_name */
+);
+
+extern int XSetInputFocus(
+ Display* /* display */,
+ Window /* focus */,
+ int /* revert_to */,
+ Time /* time */
+);
+
+extern int XSetLineAttributes(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned int /* line_width */,
+ int /* line_style */,
+ int /* cap_style */,
+ int /* join_style */
+);
+
+extern int XSetModifierMapping(
+ Display* /* display */,
+ XModifierKeymap* /* modmap */
+);
+
+extern int XSetPlaneMask(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* plane_mask */
+);
+
+extern int XSetPointerMapping(
+ Display* /* display */,
+ _Xconst unsigned char* /* map */,
+ int /* nmap */
+);
+
+extern int XSetScreenSaver(
+ Display* /* display */,
+ int /* timeout */,
+ int /* interval */,
+ int /* prefer_blanking */,
+ int /* allow_exposures */
+);
+
+extern int XSetSelectionOwner(
+ Display* /* display */,
+ Atom /* selection */,
+ Window /* owner */,
+ Time /* time */
+);
+
+extern int XSetState(
+ Display* /* display */,
+ GC /* gc */,
+ unsigned long /* foreground */,
+ unsigned long /* background */,
+ int /* function */,
+ unsigned long /* plane_mask */
+);
+
+extern int XSetStipple(
+ Display* /* display */,
+ GC /* gc */,
+ Pixmap /* stipple */
+);
+
+extern int XSetSubwindowMode(
+ Display* /* display */,
+ GC /* gc */,
+ int /* subwindow_mode */
+);
+
+extern int XSetTSOrigin(
+ Display* /* display */,
+ GC /* gc */,
+ int /* ts_x_origin */,
+ int /* ts_y_origin */
+);
+
+extern int XSetTile(
+ Display* /* display */,
+ GC /* gc */,
+ Pixmap /* tile */
+);
+
+extern int XSetWindowBackground(
+ Display* /* display */,
+ Window /* w */,
+ unsigned long /* background_pixel */
+);
+
+extern int XSetWindowBackgroundPixmap(
+ Display* /* display */,
+ Window /* w */,
+ Pixmap /* background_pixmap */
+);
+
+extern int XSetWindowBorder(
+ Display* /* display */,
+ Window /* w */,
+ unsigned long /* border_pixel */
+);
+
+extern int XSetWindowBorderPixmap(
+ Display* /* display */,
+ Window /* w */,
+ Pixmap /* border_pixmap */
+);
+
+extern int XSetWindowBorderWidth(
+ Display* /* display */,
+ Window /* w */,
+ unsigned int /* width */
+);
+
+extern int XSetWindowColormap(
+ Display* /* display */,
+ Window /* w */,
+ Colormap /* colormap */
+);
+
+extern int XStoreBuffer(
+ Display* /* display */,
+ _Xconst char* /* bytes */,
+ int /* nbytes */,
+ int /* buffer */
+);
+
+extern int XStoreBytes(
+ Display* /* display */,
+ _Xconst char* /* bytes */,
+ int /* nbytes */
+);
+
+extern int XStoreColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ XColor* /* color */
+);
+
+extern int XStoreColors(
+ Display* /* display */,
+ Colormap /* colormap */,
+ XColor* /* color */,
+ int /* ncolors */
+);
+
+extern int XStoreName(
+ Display* /* display */,
+ Window /* w */,
+ _Xconst char* /* window_name */
+);
+
+extern int XStoreNamedColor(
+ Display* /* display */,
+ Colormap /* colormap */,
+ _Xconst char* /* color */,
+ unsigned long /* pixel */,
+ int /* flags */
+);
+
+extern int XSync(
+ Display* /* display */,
+ Bool /* discard */
+);
+
+extern int XTextExtents(
+ XFontStruct* /* font_struct */,
+ _Xconst char* /* string */,
+ int /* nchars */,
+ int* /* direction_return */,
+ int* /* font_ascent_return */,
+ int* /* font_descent_return */,
+ XCharStruct* /* overall_return */
+);
+
+extern int XTextExtents16(
+ XFontStruct* /* font_struct */,
+ _Xconst XChar2b* /* string */,
+ int /* nchars */,
+ int* /* direction_return */,
+ int* /* font_ascent_return */,
+ int* /* font_descent_return */,
+ XCharStruct* /* overall_return */
+);
+
+extern int XTextWidth(
+ XFontStruct* /* font_struct */,
+ _Xconst char* /* string */,
+ int /* count */
+);
+
+extern int XTextWidth16(
+ XFontStruct* /* font_struct */,
+ _Xconst XChar2b* /* string */,
+ int /* count */
+);
+
+extern Bool XTranslateCoordinates(
+ Display* /* display */,
+ Window /* src_w */,
+ Window /* dest_w */,
+ int /* src_x */,
+ int /* src_y */,
+ int* /* dest_x_return */,
+ int* /* dest_y_return */,
+ Window* /* child_return */
+);
+
+extern int XUndefineCursor(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XUngrabButton(
+ Display* /* display */,
+ unsigned int /* button */,
+ unsigned int /* modifiers */,
+ Window /* grab_window */
+);
+
+extern int XUngrabKey(
+ Display* /* display */,
+ int /* keycode */,
+ unsigned int /* modifiers */,
+ Window /* grab_window */
+);
+
+extern int XUngrabKeyboard(
+ Display* /* display */,
+ Time /* time */
+);
+
+extern int XUngrabPointer(
+ Display* /* display */,
+ Time /* time */
+);
+
+extern int XUngrabServer(
+ Display* /* display */
+);
+
+extern int XUninstallColormap(
+ Display* /* display */,
+ Colormap /* colormap */
+);
+
+extern int XUnloadFont(
+ Display* /* display */,
+ Font /* font */
+);
+
+extern int XUnmapSubwindows(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XUnmapWindow(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern int XVendorRelease(
+ Display* /* display */
+);
+
+extern int XWarpPointer(
+ Display* /* display */,
+ Window /* src_w */,
+ Window /* dest_w */,
+ int /* src_x */,
+ int /* src_y */,
+ unsigned int /* src_width */,
+ unsigned int /* src_height */,
+ int /* dest_x */,
+ int /* dest_y */
+);
+
+extern int XWidthMMOfScreen(
+ Screen* /* screen */
+);
+
+extern int XWidthOfScreen(
+ Screen* /* screen */
+);
+
+extern int XWindowEvent(
+ Display* /* display */,
+ Window /* w */,
+ long /* event_mask */,
+ XEvent* /* event_return */
+);
+
+extern int XWriteBitmapFile(
+ Display* /* display */,
+ _Xconst char* /* filename */,
+ Pixmap /* bitmap */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* x_hot */,
+ int /* y_hot */
+);
+
+extern Bool XSupportsLocale (void);
+
+extern char *XSetLocaleModifiers(
+ const char* /* modifier_list */
+);
+
+extern XOM XOpenOM(
+ Display* /* display */,
+ struct _XrmHashBucketRec* /* rdb */,
+ _Xconst char* /* res_name */,
+ _Xconst char* /* res_class */
+);
+
+extern Status XCloseOM(
+ XOM /* om */
+);
+
+extern char *XSetOMValues(
+ XOM /* om */,
+ ...
+) _X_SENTINEL(0);
+
+extern char *XGetOMValues(
+ XOM /* om */,
+ ...
+) _X_SENTINEL(0);
+
+extern Display *XDisplayOfOM(
+ XOM /* om */
+);
+
+extern char *XLocaleOfOM(
+ XOM /* om */
+);
+
+extern XOC XCreateOC(
+ XOM /* om */,
+ ...
+) _X_SENTINEL(0);
+
+extern void XDestroyOC(
+ XOC /* oc */
+);
+
+extern XOM XOMOfOC(
+ XOC /* oc */
+);
+
+extern char *XSetOCValues(
+ XOC /* oc */,
+ ...
+) _X_SENTINEL(0);
+
+extern char *XGetOCValues(
+ XOC /* oc */,
+ ...
+) _X_SENTINEL(0);
+
+extern XFontSet XCreateFontSet(
+ Display* /* display */,
+ _Xconst char* /* base_font_name_list */,
+ char*** /* missing_charset_list */,
+ int* /* missing_charset_count */,
+ char** /* def_string */
+);
+
+extern void XFreeFontSet(
+ Display* /* display */,
+ XFontSet /* font_set */
+);
+
+extern int XFontsOfFontSet(
+ XFontSet /* font_set */,
+ XFontStruct*** /* font_struct_list */,
+ char*** /* font_name_list */
+);
+
+extern char *XBaseFontNameListOfFontSet(
+ XFontSet /* font_set */
+);
+
+extern char *XLocaleOfFontSet(
+ XFontSet /* font_set */
+);
+
+extern Bool XContextDependentDrawing(
+ XFontSet /* font_set */
+);
+
+extern Bool XDirectionalDependentDrawing(
+ XFontSet /* font_set */
+);
+
+extern Bool XContextualDrawing(
+ XFontSet /* font_set */
+);
+
+extern XFontSetExtents *XExtentsOfFontSet(
+ XFontSet /* font_set */
+);
+
+extern int XmbTextEscapement(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern int XwcTextEscapement(
+ XFontSet /* font_set */,
+ _Xconst wchar_t* /* text */,
+ int /* num_wchars */
+);
+
+extern int Xutf8TextEscapement(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern int XmbTextExtents(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern int XwcTextExtents(
+ XFontSet /* font_set */,
+ _Xconst wchar_t* /* text */,
+ int /* num_wchars */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern int Xutf8TextExtents(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern Status XmbTextPerCharExtents(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */,
+ XRectangle* /* ink_extents_buffer */,
+ XRectangle* /* logical_extents_buffer */,
+ int /* buffer_size */,
+ int* /* num_chars */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern Status XwcTextPerCharExtents(
+ XFontSet /* font_set */,
+ _Xconst wchar_t* /* text */,
+ int /* num_wchars */,
+ XRectangle* /* ink_extents_buffer */,
+ XRectangle* /* logical_extents_buffer */,
+ int /* buffer_size */,
+ int* /* num_chars */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern Status Xutf8TextPerCharExtents(
+ XFontSet /* font_set */,
+ _Xconst char* /* text */,
+ int /* bytes_text */,
+ XRectangle* /* ink_extents_buffer */,
+ XRectangle* /* logical_extents_buffer */,
+ int /* buffer_size */,
+ int* /* num_chars */,
+ XRectangle* /* overall_ink_return */,
+ XRectangle* /* overall_logical_return */
+);
+
+extern void XmbDrawText(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ XmbTextItem* /* text_items */,
+ int /* nitems */
+);
+
+extern void XwcDrawText(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ XwcTextItem* /* text_items */,
+ int /* nitems */
+);
+
+extern void Xutf8DrawText(
+ Display* /* display */,
+ Drawable /* d */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ XmbTextItem* /* text_items */,
+ int /* nitems */
+);
+
+extern void XmbDrawString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern void XwcDrawString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst wchar_t* /* text */,
+ int /* num_wchars */
+);
+
+extern void Xutf8DrawString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern void XmbDrawImageString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern void XwcDrawImageString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst wchar_t* /* text */,
+ int /* num_wchars */
+);
+
+extern void Xutf8DrawImageString(
+ Display* /* display */,
+ Drawable /* d */,
+ XFontSet /* font_set */,
+ GC /* gc */,
+ int /* x */,
+ int /* y */,
+ _Xconst char* /* text */,
+ int /* bytes_text */
+);
+
+extern XIM XOpenIM(
+ Display* /* dpy */,
+ struct _XrmHashBucketRec* /* rdb */,
+ char* /* res_name */,
+ char* /* res_class */
+);
+
+extern Status XCloseIM(
+ XIM /* im */
+);
+
+extern char *XGetIMValues(
+ XIM /* im */, ...
+) _X_SENTINEL(0);
+
+extern char *XSetIMValues(
+ XIM /* im */, ...
+) _X_SENTINEL(0);
+
+extern Display *XDisplayOfIM(
+ XIM /* im */
+);
+
+extern char *XLocaleOfIM(
+ XIM /* im*/
+);
+
+extern XIC XCreateIC(
+ XIM /* im */, ...
+) _X_SENTINEL(0);
+
+extern void XDestroyIC(
+ XIC /* ic */
+);
+
+extern void XSetICFocus(
+ XIC /* ic */
+);
+
+extern void XUnsetICFocus(
+ XIC /* ic */
+);
+
+extern wchar_t *XwcResetIC(
+ XIC /* ic */
+);
+
+extern char *XmbResetIC(
+ XIC /* ic */
+);
+
+extern char *Xutf8ResetIC(
+ XIC /* ic */
+);
+
+extern char *XSetICValues(
+ XIC /* ic */, ...
+) _X_SENTINEL(0);
+
+extern char *XGetICValues(
+ XIC /* ic */, ...
+) _X_SENTINEL(0);
+
+extern XIM XIMOfIC(
+ XIC /* ic */
+);
+
+extern Bool XFilterEvent(
+ XEvent* /* event */,
+ Window /* window */
+);
+
+extern int XmbLookupString(
+ XIC /* ic */,
+ XKeyPressedEvent* /* event */,
+ char* /* buffer_return */,
+ int /* bytes_buffer */,
+ KeySym* /* keysym_return */,
+ Status* /* status_return */
+);
+
+extern int XwcLookupString(
+ XIC /* ic */,
+ XKeyPressedEvent* /* event */,
+ wchar_t* /* buffer_return */,
+ int /* wchars_buffer */,
+ KeySym* /* keysym_return */,
+ Status* /* status_return */
+);
+
+extern int Xutf8LookupString(
+ XIC /* ic */,
+ XKeyPressedEvent* /* event */,
+ char* /* buffer_return */,
+ int /* bytes_buffer */,
+ KeySym* /* keysym_return */,
+ Status* /* status_return */
+);
+
+extern XVaNestedList XVaCreateNestedList(
+ int /*unused*/, ...
+) _X_SENTINEL(0);
+
+/* internal connections for IMs */
+
+extern Bool XRegisterIMInstantiateCallback(
+ Display* /* dpy */,
+ struct _XrmHashBucketRec* /* rdb */,
+ char* /* res_name */,
+ char* /* res_class */,
+ XIDProc /* callback */,
+ XPointer /* client_data */
+);
+
+extern Bool XUnregisterIMInstantiateCallback(
+ Display* /* dpy */,
+ struct _XrmHashBucketRec* /* rdb */,
+ char* /* res_name */,
+ char* /* res_class */,
+ XIDProc /* callback */,
+ XPointer /* client_data */
+);
+
+typedef void (*XConnectionWatchProc)(
+ Display* /* dpy */,
+ XPointer /* client_data */,
+ int /* fd */,
+ Bool /* opening */, /* open or close flag */
+ XPointer* /* watch_data */ /* open sets, close uses */
+);
+
+
+extern Status XInternalConnectionNumbers(
+ Display* /* dpy */,
+ int** /* fd_return */,
+ int* /* count_return */
+);
+
+extern void XProcessInternalConnection(
+ Display* /* dpy */,
+ int /* fd */
+);
+
+extern Status XAddConnectionWatch(
+ Display* /* dpy */,
+ XConnectionWatchProc /* callback */,
+ XPointer /* client_data */
+);
+
+extern void XRemoveConnectionWatch(
+ Display* /* dpy */,
+ XConnectionWatchProc /* callback */,
+ XPointer /* client_data */
+);
+
+extern void XSetAuthorization(
+ char * /* name */,
+ int /* namelen */,
+ char * /* data */,
+ int /* datalen */
+);
+
+extern int _Xmbtowc(
+ wchar_t * /* wstr */,
+#ifdef ISC
+ char const * /* str */,
+ size_t /* len */
+#else
+ char * /* str */,
+ int /* len */
+#endif
+);
+
+extern int _Xwctomb(
+ char * /* str */,
+ wchar_t /* wc */
+);
+
+extern Bool XGetEventData(
+ Display* /* dpy */,
+ XGenericEventCookie* /* cookie*/
+);
+
+extern void XFreeEventData(
+ Display* /* dpy */,
+ XGenericEventCookie* /* cookie*/
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XLIB_H_ */
diff --git a/system/include/X11/Xosdefs.h b/system/include/X11/Xosdefs.h
new file mode 100644
index 00000000..33eaee43
--- /dev/null
+++ b/system/include/X11/Xosdefs.h
@@ -0,0 +1,116 @@
+/*
+ * O/S-dependent (mis)feature macro definitions
+ *
+Copyright 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ */
+
+#ifndef _XOSDEFS_H_
+# define _XOSDEFS_H_
+
+/*
+ * X_NOT_POSIX means does not have POSIX header files. Lack of this
+ * symbol does NOT mean that the POSIX environment is the default.
+ * You may still have to define _POSIX_SOURCE to get it.
+ */
+
+
+# ifdef _SCO_DS
+# ifndef __SCO__
+# define __SCO__
+# endif
+# endif
+
+# ifdef __i386__
+# ifdef SYSV
+# if !defined(__SCO__) && \
+ !defined(__UNIXWARE__) && !defined(__sun)
+# if !defined(_POSIX_SOURCE)
+# define X_NOT_POSIX
+# endif
+# endif
+# endif
+# endif
+
+# ifdef __sun
+/* Imake configs define SVR4 on Solaris, but cc & gcc only define __SVR4
+ * This check allows non-Imake configured programs to build correctly.
+ */
+# if defined(__SVR4) && !defined(SVR4)
+# define SVR4 1
+# endif
+# ifdef SVR4
+/* define this to whatever it needs to be */
+# define X_POSIX_C_SOURCE 199300L
+# endif
+# endif
+
+# ifdef WIN32
+# ifndef _POSIX_
+# define X_NOT_POSIX
+# endif
+# endif
+
+
+# ifdef __APPLE__
+# define NULL_NOT_ZERO
+
+/* Defining any of these will sanitize the namespace to JUST want is defined by
+ * that particular standard. If that happens, we don't get some expected
+ * prototypes, typedefs, etc (like fd_mask). We can define _DARWIN_C_SOURCE to
+ * loosen our belts a tad.
+ */
+# if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE)
+# ifndef _DARWIN_C_SOURCE
+# define _DARWIN_C_SOURCE
+# endif
+# endif
+
+# endif
+
+# ifdef __GNU__
+# ifndef PATH_MAX
+# define PATH_MAX 4096
+# endif
+# ifndef MAXPATHLEN
+# define MAXPATHLEN 4096
+# endif
+# endif
+
+# if defined(__SCO__) || defined(__UNIXWARE__)
+# ifndef PATH_MAX
+# define PATH_MAX 1024
+# endif
+# ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+# endif
+# endif
+
+# if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) \
+ || defined(__APPLE__) || defined(__DragonFly__)
+# ifndef CSRG_BASED
+# define CSRG_BASED
+# endif
+# endif
+
+#endif /* _XOSDEFS_H_ */
+
diff --git a/system/include/X11/Xutil.h b/system/include/X11/Xutil.h
new file mode 100644
index 00000000..8ff34d9f
--- /dev/null
+++ b/system/include/X11/Xutil.h
@@ -0,0 +1,826 @@
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifndef _XUTIL_H_
+#define _XUTIL_H_
+
+/* You must include <X11/Xlib.h> before including this file */
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+/*
+ * Bitmask returned by XParseGeometry(). Each bit tells if the corresponding
+ * value (x, y, width, height) was found in the parsed string.
+ */
+#define NoValue 0x0000
+#define XValue 0x0001
+#define YValue 0x0002
+#define WidthValue 0x0004
+#define HeightValue 0x0008
+#define AllValues 0x000F
+#define XNegative 0x0010
+#define YNegative 0x0020
+
+/*
+ * new version containing base_width, base_height, and win_gravity fields;
+ * used with WM_NORMAL_HINTS.
+ */
+typedef struct {
+ long flags; /* marks which fields in this structure are defined */
+ int x, y; /* obsolete for new window mgrs, but clients */
+ int width, height; /* should set so old wm's don't mess up */
+ int min_width, min_height;
+ int max_width, max_height;
+ int width_inc, height_inc;
+ struct {
+ int x; /* numerator */
+ int y; /* denominator */
+ } min_aspect, max_aspect;
+ int base_width, base_height; /* added by ICCCM version 1 */
+ int win_gravity; /* added by ICCCM version 1 */
+} XSizeHints;
+
+/*
+ * The next block of definitions are for window manager properties that
+ * clients and applications use for communication.
+ */
+
+/* flags argument in size hints */
+#define USPosition (1L << 0) /* user specified x, y */
+#define USSize (1L << 1) /* user specified width, height */
+
+#define PPosition (1L << 2) /* program specified position */
+#define PSize (1L << 3) /* program specified size */
+#define PMinSize (1L << 4) /* program specified minimum size */
+#define PMaxSize (1L << 5) /* program specified maximum size */
+#define PResizeInc (1L << 6) /* program specified resize increments */
+#define PAspect (1L << 7) /* program specified min and max aspect ratios */
+#define PBaseSize (1L << 8) /* program specified base for incrementing */
+#define PWinGravity (1L << 9) /* program specified window gravity */
+
+/* obsolete */
+#define PAllHints (PPosition|PSize|PMinSize|PMaxSize|PResizeInc|PAspect)
+
+
+
+typedef struct {
+ long flags; /* marks which fields in this structure are defined */
+ Bool input; /* does this application rely on the window manager to
+ get keyboard input? */
+ int initial_state; /* see below */
+ Pixmap icon_pixmap; /* pixmap to be used as icon */
+ Window icon_window; /* window to be used as icon */
+ int icon_x, icon_y; /* initial position of icon */
+ Pixmap icon_mask; /* icon mask bitmap */
+ XID window_group; /* id of related window group */
+ /* this structure may be extended in the future */
+} XWMHints;
+
+/* definition for flags of XWMHints */
+
+#define InputHint (1L << 0)
+#define StateHint (1L << 1)
+#define IconPixmapHint (1L << 2)
+#define IconWindowHint (1L << 3)
+#define IconPositionHint (1L << 4)
+#define IconMaskHint (1L << 5)
+#define WindowGroupHint (1L << 6)
+#define AllHints (InputHint|StateHint|IconPixmapHint|IconWindowHint| \
+IconPositionHint|IconMaskHint|WindowGroupHint)
+#define XUrgencyHint (1L << 8)
+
+/* definitions for initial window state */
+#define WithdrawnState 0 /* for windows that are not mapped */
+#define NormalState 1 /* most applications want to start this way */
+#define IconicState 3 /* application wants to start as an icon */
+
+/*
+ * Obsolete states no longer defined by ICCCM
+ */
+#define DontCareState 0 /* don't know or care */
+#define ZoomState 2 /* application wants to start zoomed */
+#define InactiveState 4 /* application believes it is seldom used; */
+ /* some wm's may put it on inactive menu */
+
+
+/*
+ * new structure for manipulating TEXT properties; used with WM_NAME,
+ * WM_ICON_NAME, WM_CLIENT_MACHINE, and WM_COMMAND.
+ */
+typedef struct {
+ unsigned char *value; /* same as Property routines */
+ Atom encoding; /* prop type */
+ int format; /* prop data format: 8, 16, or 32 */
+ unsigned long nitems; /* number of data items in value */
+} XTextProperty;
+
+#define XNoMemory -1
+#define XLocaleNotSupported -2
+#define XConverterNotFound -3
+
+typedef enum {
+ XStringStyle, /* STRING */
+ XCompoundTextStyle, /* COMPOUND_TEXT */
+ XTextStyle, /* text in owner's encoding (current locale)*/
+ XStdICCTextStyle, /* STRING, else COMPOUND_TEXT */
+ /* The following is an XFree86 extension, introduced in November 2000 */
+ XUTF8StringStyle /* UTF8_STRING */
+} XICCEncodingStyle;
+
+typedef struct {
+ int min_width, min_height;
+ int max_width, max_height;
+ int width_inc, height_inc;
+} XIconSize;
+
+typedef struct {
+ char *res_name;
+ char *res_class;
+} XClassHint;
+
+#ifdef XUTIL_DEFINE_FUNCTIONS
+extern int XDestroyImage(
+ XImage *ximage);
+extern unsigned long XGetPixel(
+ XImage *ximage,
+ int x, int y);
+extern int XPutPixel(
+ XImage *ximage,
+ int x, int y,
+ unsigned long pixel);
+extern XImage *XSubImage(
+ XImage *ximage,
+ int x, int y,
+ unsigned int width, unsigned int height);
+extern int XAddPixel(
+ XImage *ximage,
+ long value);
+#else
+/*
+ * These macros are used to give some sugar to the image routines so that
+ * naive people are more comfortable with them.
+ */
+#define XDestroyImage(ximage) \
+ ((*((ximage)->f.destroy_image))((ximage)))
+#define XGetPixel(ximage, x, y) \
+ ((*((ximage)->f.get_pixel))((ximage), (x), (y)))
+#define XPutPixel(ximage, x, y, pixel) \
+ ((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel)))
+#define XSubImage(ximage, x, y, width, height) \
+ ((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height)))
+#define XAddPixel(ximage, value) \
+ ((*((ximage)->f.add_pixel))((ximage), (value)))
+#endif
+
+/*
+ * Compose sequence status structure, used in calling XLookupString.
+ */
+typedef struct _XComposeStatus {
+ XPointer compose_ptr; /* state table pointer */
+ int chars_matched; /* match state */
+} XComposeStatus;
+
+/*
+ * Keysym macros, used on Keysyms to test for classes of symbols
+ */
+#define IsKeypadKey(keysym) \
+ (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal))
+
+#define IsPrivateKeypadKey(keysym) \
+ (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
+
+#define IsCursorKey(keysym) \
+ (((KeySym)(keysym) >= XK_Home) && ((KeySym)(keysym) < XK_Select))
+
+#define IsPFKey(keysym) \
+ (((KeySym)(keysym) >= XK_KP_F1) && ((KeySym)(keysym) <= XK_KP_F4))
+
+#define IsFunctionKey(keysym) \
+ (((KeySym)(keysym) >= XK_F1) && ((KeySym)(keysym) <= XK_F35))
+
+#define IsMiscFunctionKey(keysym) \
+ (((KeySym)(keysym) >= XK_Select) && ((KeySym)(keysym) <= XK_Break))
+
+#ifdef XK_XKB_KEYS
+#define IsModifierKey(keysym) \
+ ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \
+ || (((KeySym)(keysym) >= XK_ISO_Lock) && \
+ ((KeySym)(keysym) <= XK_ISO_Last_Group_Lock)) \
+ || ((KeySym)(keysym) == XK_Mode_switch) \
+ || ((KeySym)(keysym) == XK_Num_Lock))
+#else
+#define IsModifierKey(keysym) \
+ ((((KeySym)(keysym) >= XK_Shift_L) && ((KeySym)(keysym) <= XK_Hyper_R)) \
+ || ((KeySym)(keysym) == XK_Mode_switch) \
+ || ((KeySym)(keysym) == XK_Num_Lock))
+#endif
+/*
+ * opaque reference to Region data type
+ */
+typedef struct _XRegion *Region;
+
+/* Return values from XRectInRegion() */
+
+#define RectangleOut 0
+#define RectangleIn 1
+#define RectanglePart 2
+
+
+/*
+ * Information used by the visual utility routines to find desired visual
+ * type from the many visuals a display may support.
+ */
+
+typedef struct {
+ Visual *visual;
+ VisualID visualid;
+ int screen;
+ int depth;
+#if defined(__cplusplus) || defined(c_plusplus)
+ int c_class; /* C++ */
+#else
+ int class;
+#endif
+ unsigned long red_mask;
+ unsigned long green_mask;
+ unsigned long blue_mask;
+ int colormap_size;
+ int bits_per_rgb;
+} XVisualInfo;
+
+#define VisualNoMask 0x0
+#define VisualIDMask 0x1
+#define VisualScreenMask 0x2
+#define VisualDepthMask 0x4
+#define VisualClassMask 0x8
+#define VisualRedMaskMask 0x10
+#define VisualGreenMaskMask 0x20
+#define VisualBlueMaskMask 0x40
+#define VisualColormapSizeMask 0x80
+#define VisualBitsPerRGBMask 0x100
+#define VisualAllMask 0x1FF
+
+/*
+ * This defines a window manager property that clients may use to
+ * share standard color maps of type RGB_COLOR_MAP:
+ */
+typedef struct {
+ Colormap colormap;
+ unsigned long red_max;
+ unsigned long red_mult;
+ unsigned long green_max;
+ unsigned long green_mult;
+ unsigned long blue_max;
+ unsigned long blue_mult;
+ unsigned long base_pixel;
+ VisualID visualid; /* added by ICCCM version 1 */
+ XID killid; /* added by ICCCM version 1 */
+} XStandardColormap;
+
+#define ReleaseByFreeingColormap ((XID) 1L) /* for killid field above */
+
+
+/*
+ * return codes for XReadBitmapFile and XWriteBitmapFile
+ */
+#define BitmapSuccess 0
+#define BitmapOpenFailed 1
+#define BitmapFileInvalid 2
+#define BitmapNoMemory 3
+
+/****************************************************************
+ *
+ * Context Management
+ *
+ ****************************************************************/
+
+
+/* Associative lookup table return codes */
+
+#define XCSUCCESS 0 /* No error. */
+#define XCNOMEM 1 /* Out of memory */
+#define XCNOENT 2 /* No entry in table */
+
+typedef int XContext;
+
+#define XUniqueContext() ((XContext) XrmUniqueQuark())
+#define XStringToContext(string) ((XContext) XrmStringToQuark(string))
+
+_XFUNCPROTOBEGIN
+
+/* The following declarations are alphabetized. */
+
+extern XClassHint *XAllocClassHint (
+ void
+);
+
+extern XIconSize *XAllocIconSize (
+ void
+);
+
+extern XSizeHints *XAllocSizeHints (
+ void
+);
+
+extern XStandardColormap *XAllocStandardColormap (
+ void
+);
+
+extern XWMHints *XAllocWMHints (
+ void
+);
+
+extern int XClipBox(
+ Region /* r */,
+ XRectangle* /* rect_return */
+);
+
+extern Region XCreateRegion(
+ void
+);
+
+extern const char *XDefaultString (void);
+
+extern int XDeleteContext(
+ Display* /* display */,
+ XID /* rid */,
+ XContext /* context */
+);
+
+extern int XDestroyRegion(
+ Region /* r */
+);
+
+extern int XEmptyRegion(
+ Region /* r */
+);
+
+extern int XEqualRegion(
+ Region /* r1 */,
+ Region /* r2 */
+);
+
+extern int XFindContext(
+ Display* /* display */,
+ XID /* rid */,
+ XContext /* context */,
+ XPointer* /* data_return */
+);
+
+extern Status XGetClassHint(
+ Display* /* display */,
+ Window /* w */,
+ XClassHint* /* class_hints_return */
+);
+
+extern Status XGetIconSizes(
+ Display* /* display */,
+ Window /* w */,
+ XIconSize** /* size_list_return */,
+ int* /* count_return */
+);
+
+extern Status XGetNormalHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints_return */
+);
+
+extern Status XGetRGBColormaps(
+ Display* /* display */,
+ Window /* w */,
+ XStandardColormap** /* stdcmap_return */,
+ int* /* count_return */,
+ Atom /* property */
+);
+
+extern Status XGetSizeHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints_return */,
+ Atom /* property */
+);
+
+extern Status XGetStandardColormap(
+ Display* /* display */,
+ Window /* w */,
+ XStandardColormap* /* colormap_return */,
+ Atom /* property */
+);
+
+extern Status XGetTextProperty(
+ Display* /* display */,
+ Window /* window */,
+ XTextProperty* /* text_prop_return */,
+ Atom /* property */
+);
+
+extern XVisualInfo *XGetVisualInfo(
+ Display* /* display */,
+ long /* vinfo_mask */,
+ XVisualInfo* /* vinfo_template */,
+ int* /* nitems_return */
+);
+
+extern Status XGetWMClientMachine(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop_return */
+);
+
+extern XWMHints *XGetWMHints(
+ Display* /* display */,
+ Window /* w */
+);
+
+extern Status XGetWMIconName(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop_return */
+);
+
+extern Status XGetWMName(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop_return */
+);
+
+extern Status XGetWMNormalHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints_return */,
+ long* /* supplied_return */
+);
+
+extern Status XGetWMSizeHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints_return */,
+ long* /* supplied_return */,
+ Atom /* property */
+);
+
+extern Status XGetZoomHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* zhints_return */
+);
+
+extern int XIntersectRegion(
+ Region /* sra */,
+ Region /* srb */,
+ Region /* dr_return */
+);
+
+extern void XConvertCase(
+ KeySym /* sym */,
+ KeySym* /* lower */,
+ KeySym* /* upper */
+);
+
+extern int XLookupString(
+ XKeyEvent* /* event_struct */,
+ char* /* buffer_return */,
+ int /* bytes_buffer */,
+ KeySym* /* keysym_return */,
+ XComposeStatus* /* status_in_out */
+);
+
+extern Status XMatchVisualInfo(
+ Display* /* display */,
+ int /* screen */,
+ int /* depth */,
+ int /* class */,
+ XVisualInfo* /* vinfo_return */
+);
+
+extern int XOffsetRegion(
+ Region /* r */,
+ int /* dx */,
+ int /* dy */
+);
+
+extern Bool XPointInRegion(
+ Region /* r */,
+ int /* x */,
+ int /* y */
+);
+
+extern Region XPolygonRegion(
+ XPoint* /* points */,
+ int /* n */,
+ int /* fill_rule */
+);
+
+extern int XRectInRegion(
+ Region /* r */,
+ int /* x */,
+ int /* y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+);
+
+extern int XSaveContext(
+ Display* /* display */,
+ XID /* rid */,
+ XContext /* context */,
+ _Xconst char* /* data */
+);
+
+extern int XSetClassHint(
+ Display* /* display */,
+ Window /* w */,
+ XClassHint* /* class_hints */
+);
+
+extern int XSetIconSizes(
+ Display* /* display */,
+ Window /* w */,
+ XIconSize* /* size_list */,
+ int /* count */
+);
+
+extern int XSetNormalHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints */
+);
+
+extern void XSetRGBColormaps(
+ Display* /* display */,
+ Window /* w */,
+ XStandardColormap* /* stdcmaps */,
+ int /* count */,
+ Atom /* property */
+);
+
+extern int XSetSizeHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints */,
+ Atom /* property */
+);
+
+extern int XSetStandardProperties(
+ Display* /* display */,
+ Window /* w */,
+ _Xconst char* /* window_name */,
+ _Xconst char* /* icon_name */,
+ Pixmap /* icon_pixmap */,
+ char** /* argv */,
+ int /* argc */,
+ XSizeHints* /* hints */
+);
+
+extern void XSetTextProperty(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop */,
+ Atom /* property */
+);
+
+extern void XSetWMClientMachine(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop */
+);
+
+extern int XSetWMHints(
+ Display* /* display */,
+ Window /* w */,
+ XWMHints* /* wm_hints */
+);
+
+extern void XSetWMIconName(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop */
+);
+
+extern void XSetWMName(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* text_prop */
+);
+
+extern void XSetWMNormalHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints */
+);
+
+extern void XSetWMProperties(
+ Display* /* display */,
+ Window /* w */,
+ XTextProperty* /* window_name */,
+ XTextProperty* /* icon_name */,
+ char** /* argv */,
+ int /* argc */,
+ XSizeHints* /* normal_hints */,
+ XWMHints* /* wm_hints */,
+ XClassHint* /* class_hints */
+);
+
+extern void XmbSetWMProperties(
+ Display* /* display */,
+ Window /* w */,
+ _Xconst char* /* window_name */,
+ _Xconst char* /* icon_name */,
+ char** /* argv */,
+ int /* argc */,
+ XSizeHints* /* normal_hints */,
+ XWMHints* /* wm_hints */,
+ XClassHint* /* class_hints */
+);
+
+extern void Xutf8SetWMProperties(
+ Display* /* display */,
+ Window /* w */,
+ _Xconst char* /* window_name */,
+ _Xconst char* /* icon_name */,
+ char** /* argv */,
+ int /* argc */,
+ XSizeHints* /* normal_hints */,
+ XWMHints* /* wm_hints */,
+ XClassHint* /* class_hints */
+);
+
+extern void XSetWMSizeHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* hints */,
+ Atom /* property */
+);
+
+extern int XSetRegion(
+ Display* /* display */,
+ GC /* gc */,
+ Region /* r */
+);
+
+extern void XSetStandardColormap(
+ Display* /* display */,
+ Window /* w */,
+ XStandardColormap* /* colormap */,
+ Atom /* property */
+);
+
+extern int XSetZoomHints(
+ Display* /* display */,
+ Window /* w */,
+ XSizeHints* /* zhints */
+);
+
+extern int XShrinkRegion(
+ Region /* r */,
+ int /* dx */,
+ int /* dy */
+);
+
+extern Status XStringListToTextProperty(
+ char** /* list */,
+ int /* count */,
+ XTextProperty* /* text_prop_return */
+);
+
+extern int XSubtractRegion(
+ Region /* sra */,
+ Region /* srb */,
+ Region /* dr_return */
+);
+
+extern int XmbTextListToTextProperty(
+ Display* display,
+ char** list,
+ int count,
+ XICCEncodingStyle style,
+ XTextProperty* text_prop_return
+);
+
+extern int XwcTextListToTextProperty(
+ Display* display,
+ wchar_t** list,
+ int count,
+ XICCEncodingStyle style,
+ XTextProperty* text_prop_return
+);
+
+extern int Xutf8TextListToTextProperty(
+ Display* display,
+ char** list,
+ int count,
+ XICCEncodingStyle style,
+ XTextProperty* text_prop_return
+);
+
+extern void XwcFreeStringList(
+ wchar_t** list
+);
+
+extern Status XTextPropertyToStringList(
+ XTextProperty* /* text_prop */,
+ char*** /* list_return */,
+ int* /* count_return */
+);
+
+extern int XmbTextPropertyToTextList(
+ Display* display,
+ const XTextProperty* text_prop,
+ char*** list_return,
+ int* count_return
+);
+
+extern int XwcTextPropertyToTextList(
+ Display* display,
+ const XTextProperty* text_prop,
+ wchar_t*** list_return,
+ int* count_return
+);
+
+extern int Xutf8TextPropertyToTextList(
+ Display* display,
+ const XTextProperty* text_prop,
+ char*** list_return,
+ int* count_return
+);
+
+extern int XUnionRectWithRegion(
+ XRectangle* /* rectangle */,
+ Region /* src_region */,
+ Region /* dest_region_return */
+);
+
+extern int XUnionRegion(
+ Region /* sra */,
+ Region /* srb */,
+ Region /* dr_return */
+);
+
+extern int XWMGeometry(
+ Display* /* display */,
+ int /* screen_number */,
+ _Xconst char* /* user_geometry */,
+ _Xconst char* /* default_geometry */,
+ unsigned int /* border_width */,
+ XSizeHints* /* hints */,
+ int* /* x_return */,
+ int* /* y_return */,
+ int* /* width_return */,
+ int* /* height_return */,
+ int* /* gravity_return */
+);
+
+extern int XXorRegion(
+ Region /* sra */,
+ Region /* srb */,
+ Region /* dr_return */
+);
+
+_XFUNCPROTOEND
+
+#endif /* _XUTIL_H_ */
diff --git a/system/include/X11/keysym.h b/system/include/X11/keysym.h
new file mode 100644
index 00000000..641b25bf
--- /dev/null
+++ b/system/include/X11/keysym.h
@@ -0,0 +1,73 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/* default keysyms */
+#define XK_MISCELLANY
+#define XK_XKB_KEYS
+#define XK_LATIN1
+#define XK_LATIN2
+#define XK_LATIN3
+#define XK_LATIN4
+#define XK_LATIN8
+#define XK_LATIN9
+#define XK_CAUCASUS
+#define XK_GREEK
+#define XK_KATAKANA
+#define XK_ARABIC
+#define XK_CYRILLIC
+#define XK_HEBREW
+#define XK_THAI
+#define XK_KOREAN
+#define XK_ARMENIAN
+#define XK_GEORGIAN
+#define XK_VIETNAMESE
+#define XK_CURRENCY
+#define XK_MATHEMATICAL
+#define XK_BRAILLE
+
+#include <X11/keysymdef.h>
+
diff --git a/system/include/X11/keysymdef.h b/system/include/X11/keysymdef.h
new file mode 100644
index 00000000..ec125a65
--- /dev/null
+++ b/system/include/X11/keysymdef.h
@@ -0,0 +1,2389 @@
+/***********************************************************
+Copyright 1987, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * The "X11 Window System Protocol" standard defines in Appendix A the
+ * keysym codes. These 29-bit integer values identify characters or
+ * functions associated with each key (e.g., via the visible
+ * engraving) of a keyboard layout. This file assigns mnemonic macro
+ * names for these keysyms.
+ *
+ * This file is also compiled (by src/util/makekeys.c in libX11) into
+ * hash tables that can be accessed with X11 library functions such as
+ * XStringToKeysym() and XKeysymToString().
+ *
+ * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode
+ * character, this is noted in a comment that provides both the U+xxxx
+ * Unicode position, as well as the official Unicode name of the
+ * character.
+ *
+ * Where the correspondence is either not one-to-one or semantically
+ * unclear, the Unicode position and name are enclosed in
+ * parentheses. Such legacy keysyms should be considered deprecated
+ * and are not recommended for use in future keyboard mappings.
+ *
+ * For any future extension of the keysyms with characters already
+ * found in ISO 10646 / Unicode, the following algorithm shall be
+ * used. The new keysym code position will simply be the character's
+ * Unicode number plus 0x01000000. The keysym values in the range
+ * 0x01000100 to 0x0110ffff are reserved to represent Unicode
+ * characters in the range U+0100 to U+10FFFF.
+ *
+ * While most newer Unicode-based X11 clients do already accept
+ * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it
+ * will remain necessary for clients -- in the interest of
+ * compatibility with existing servers -- to also understand the
+ * existing legacy keysym values in the range 0x0100 to 0x20ff.
+ *
+ * Where several mnemonic names are defined for the same keysym in this
+ * file, all but the first one listed should be considered deprecated.
+ *
+ * Mnemonic names for keysyms are defined in this file with lines
+ * that match one of these Perl regular expressions:
+ *
+ * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U+([0-9A-F]{4,6}) (.*) \*\/\s*$/
+ * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/
+ * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/
+ *
+ * Before adding new keysyms, please do consider the following: In
+ * addition to the keysym names defined in this file, the
+ * XStringToKeysym() and XKeysymToString() functions will also handle
+ * any keysym string of the form "U0020" to "U007E" and "U00A0" to
+ * "U10FFFF" for all possible Unicode characters. In other words,
+ * every possible Unicode character has already a keysym string
+ * defined algorithmically, even if it is not listed here. Therefore,
+ * defining an additional keysym macro is only necessary where a
+ * non-hexadecimal mnemonic name is needed, or where the new keysym
+ * does not represent any existing Unicode character.
+ *
+ * When adding new keysyms to this file, do not forget to also update the
+ * following:
+ *
+ * - the mappings in src/KeyBind.c in the repo
+ * git://anongit.freedesktop.org/xorg/lib/libX11
+ *
+ * - the protocol specification in specs/XProtocol/X11.keysyms
+ * in the repo git://anongit.freedesktop.org/xorg/doc/xorg-docs
+ *
+ */
+
+#define XK_VoidSymbol 0xffffff /* Void symbol */
+
+#ifdef XK_MISCELLANY
+/*
+ * TTY function keys, cleverly chosen to map to ASCII, for convenience of
+ * programming, but could have been arbitrary (at the cost of lookup
+ * tables in client code).
+ */
+
+#define XK_BackSpace 0xff08 /* Back space, back char */
+#define XK_Tab 0xff09
+#define XK_Linefeed 0xff0a /* Linefeed, LF */
+#define XK_Clear 0xff0b
+#define XK_Return 0xff0d /* Return, enter */
+#define XK_Pause 0xff13 /* Pause, hold */
+#define XK_Scroll_Lock 0xff14
+#define XK_Sys_Req 0xff15
+#define XK_Escape 0xff1b
+#define XK_Delete 0xffff /* Delete, rubout */
+
+
+
+/* International & multi-key character composition */
+
+#define XK_Multi_key 0xff20 /* Multi-key character compose */
+#define XK_Codeinput 0xff37
+#define XK_SingleCandidate 0xff3c
+#define XK_MultipleCandidate 0xff3d
+#define XK_PreviousCandidate 0xff3e
+
+/* Japanese keyboard support */
+
+#define XK_Kanji 0xff21 /* Kanji, Kanji convert */
+#define XK_Muhenkan 0xff22 /* Cancel Conversion */
+#define XK_Henkan_Mode 0xff23 /* Start/Stop Conversion */
+#define XK_Henkan 0xff23 /* Alias for Henkan_Mode */
+#define XK_Romaji 0xff24 /* to Romaji */
+#define XK_Hiragana 0xff25 /* to Hiragana */
+#define XK_Katakana 0xff26 /* to Katakana */
+#define XK_Hiragana_Katakana 0xff27 /* Hiragana/Katakana toggle */
+#define XK_Zenkaku 0xff28 /* to Zenkaku */
+#define XK_Hankaku 0xff29 /* to Hankaku */
+#define XK_Zenkaku_Hankaku 0xff2a /* Zenkaku/Hankaku toggle */
+#define XK_Touroku 0xff2b /* Add to Dictionary */
+#define XK_Massyo 0xff2c /* Delete from Dictionary */
+#define XK_Kana_Lock 0xff2d /* Kana Lock */
+#define XK_Kana_Shift 0xff2e /* Kana Shift */
+#define XK_Eisu_Shift 0xff2f /* Alphanumeric Shift */
+#define XK_Eisu_toggle 0xff30 /* Alphanumeric toggle */
+#define XK_Kanji_Bangou 0xff37 /* Codeinput */
+#define XK_Zen_Koho 0xff3d /* Multiple/All Candidate(s) */
+#define XK_Mae_Koho 0xff3e /* Previous Candidate */
+
+/* 0xff31 thru 0xff3f are under XK_KOREAN */
+
+/* Cursor control & motion */
+
+#define XK_Home 0xff50
+#define XK_Left 0xff51 /* Move left, left arrow */
+#define XK_Up 0xff52 /* Move up, up arrow */
+#define XK_Right 0xff53 /* Move right, right arrow */
+#define XK_Down 0xff54 /* Move down, down arrow */
+#define XK_Prior 0xff55 /* Prior, previous */
+#define XK_Page_Up 0xff55
+#define XK_Next 0xff56 /* Next */
+#define XK_Page_Down 0xff56
+#define XK_End 0xff57 /* EOL */
+#define XK_Begin 0xff58 /* BOL */
+
+
+/* Misc functions */
+
+#define XK_Select 0xff60 /* Select, mark */
+#define XK_Print 0xff61
+#define XK_Execute 0xff62 /* Execute, run, do */
+#define XK_Insert 0xff63 /* Insert, insert here */
+#define XK_Undo 0xff65
+#define XK_Redo 0xff66 /* Redo, again */
+#define XK_Menu 0xff67
+#define XK_Find 0xff68 /* Find, search */
+#define XK_Cancel 0xff69 /* Cancel, stop, abort, exit */
+#define XK_Help 0xff6a /* Help */
+#define XK_Break 0xff6b
+#define XK_Mode_switch 0xff7e /* Character set switch */
+#define XK_script_switch 0xff7e /* Alias for mode_switch */
+#define XK_Num_Lock 0xff7f
+
+/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
+
+#define XK_KP_Space 0xff80 /* Space */
+#define XK_KP_Tab 0xff89
+#define XK_KP_Enter 0xff8d /* Enter */
+#define XK_KP_F1 0xff91 /* PF1, KP_A, ... */
+#define XK_KP_F2 0xff92
+#define XK_KP_F3 0xff93
+#define XK_KP_F4 0xff94
+#define XK_KP_Home 0xff95
+#define XK_KP_Left 0xff96
+#define XK_KP_Up 0xff97
+#define XK_KP_Right 0xff98
+#define XK_KP_Down 0xff99
+#define XK_KP_Prior 0xff9a
+#define XK_KP_Page_Up 0xff9a
+#define XK_KP_Next 0xff9b
+#define XK_KP_Page_Down 0xff9b
+#define XK_KP_End 0xff9c
+#define XK_KP_Begin 0xff9d
+#define XK_KP_Insert 0xff9e
+#define XK_KP_Delete 0xff9f
+#define XK_KP_Equal 0xffbd /* Equals */
+#define XK_KP_Multiply 0xffaa
+#define XK_KP_Add 0xffab
+#define XK_KP_Separator 0xffac /* Separator, often comma */
+#define XK_KP_Subtract 0xffad
+#define XK_KP_Decimal 0xffae
+#define XK_KP_Divide 0xffaf
+
+#define XK_KP_0 0xffb0
+#define XK_KP_1 0xffb1
+#define XK_KP_2 0xffb2
+#define XK_KP_3 0xffb3
+#define XK_KP_4 0xffb4
+#define XK_KP_5 0xffb5
+#define XK_KP_6 0xffb6
+#define XK_KP_7 0xffb7
+#define XK_KP_8 0xffb8
+#define XK_KP_9 0xffb9
+
+
+
+/*
+ * Auxiliary functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufacturers have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ */
+
+#define XK_F1 0xffbe
+#define XK_F2 0xffbf
+#define XK_F3 0xffc0
+#define XK_F4 0xffc1
+#define XK_F5 0xffc2
+#define XK_F6 0xffc3
+#define XK_F7 0xffc4
+#define XK_F8 0xffc5
+#define XK_F9 0xffc6
+#define XK_F10 0xffc7
+#define XK_F11 0xffc8
+#define XK_L1 0xffc8
+#define XK_F12 0xffc9
+#define XK_L2 0xffc9
+#define XK_F13 0xffca
+#define XK_L3 0xffca
+#define XK_F14 0xffcb
+#define XK_L4 0xffcb
+#define XK_F15 0xffcc
+#define XK_L5 0xffcc
+#define XK_F16 0xffcd
+#define XK_L6 0xffcd
+#define XK_F17 0xffce
+#define XK_L7 0xffce
+#define XK_F18 0xffcf
+#define XK_L8 0xffcf
+#define XK_F19 0xffd0
+#define XK_L9 0xffd0
+#define XK_F20 0xffd1
+#define XK_L10 0xffd1
+#define XK_F21 0xffd2
+#define XK_R1 0xffd2
+#define XK_F22 0xffd3
+#define XK_R2 0xffd3
+#define XK_F23 0xffd4
+#define XK_R3 0xffd4
+#define XK_F24 0xffd5
+#define XK_R4 0xffd5
+#define XK_F25 0xffd6
+#define XK_R5 0xffd6
+#define XK_F26 0xffd7
+#define XK_R6 0xffd7
+#define XK_F27 0xffd8
+#define XK_R7 0xffd8
+#define XK_F28 0xffd9
+#define XK_R8 0xffd9
+#define XK_F29 0xffda
+#define XK_R9 0xffda
+#define XK_F30 0xffdb
+#define XK_R10 0xffdb
+#define XK_F31 0xffdc
+#define XK_R11 0xffdc
+#define XK_F32 0xffdd
+#define XK_R12 0xffdd
+#define XK_F33 0xffde
+#define XK_R13 0xffde
+#define XK_F34 0xffdf
+#define XK_R14 0xffdf
+#define XK_F35 0xffe0
+#define XK_R15 0xffe0
+
+/* Modifiers */
+
+#define XK_Shift_L 0xffe1 /* Left shift */
+#define XK_Shift_R 0xffe2 /* Right shift */
+#define XK_Control_L 0xffe3 /* Left control */
+#define XK_Control_R 0xffe4 /* Right control */
+#define XK_Caps_Lock 0xffe5 /* Caps lock */
+#define XK_Shift_Lock 0xffe6 /* Shift lock */
+
+#define XK_Meta_L 0xffe7 /* Left meta */
+#define XK_Meta_R 0xffe8 /* Right meta */
+#define XK_Alt_L 0xffe9 /* Left alt */
+#define XK_Alt_R 0xffea /* Right alt */
+#define XK_Super_L 0xffeb /* Left super */
+#define XK_Super_R 0xffec /* Right super */
+#define XK_Hyper_L 0xffed /* Left hyper */
+#define XK_Hyper_R 0xffee /* Right hyper */
+#endif /* XK_MISCELLANY */
+
+/*
+ * Keyboard (XKB) Extension function and modifier keys
+ * (from Appendix C of "The X Keyboard Extension: Protocol Specification")
+ * Byte 3 = 0xfe
+ */
+
+#ifdef XK_XKB_KEYS
+#define XK_ISO_Lock 0xfe01
+#define XK_ISO_Level2_Latch 0xfe02
+#define XK_ISO_Level3_Shift 0xfe03
+#define XK_ISO_Level3_Latch 0xfe04
+#define XK_ISO_Level3_Lock 0xfe05
+#define XK_ISO_Level5_Shift 0xfe11
+#define XK_ISO_Level5_Latch 0xfe12
+#define XK_ISO_Level5_Lock 0xfe13
+#define XK_ISO_Group_Shift 0xff7e /* Alias for mode_switch */
+#define XK_ISO_Group_Latch 0xfe06
+#define XK_ISO_Group_Lock 0xfe07
+#define XK_ISO_Next_Group 0xfe08
+#define XK_ISO_Next_Group_Lock 0xfe09
+#define XK_ISO_Prev_Group 0xfe0a
+#define XK_ISO_Prev_Group_Lock 0xfe0b
+#define XK_ISO_First_Group 0xfe0c
+#define XK_ISO_First_Group_Lock 0xfe0d
+#define XK_ISO_Last_Group 0xfe0e
+#define XK_ISO_Last_Group_Lock 0xfe0f
+
+#define XK_ISO_Left_Tab 0xfe20
+#define XK_ISO_Move_Line_Up 0xfe21
+#define XK_ISO_Move_Line_Down 0xfe22
+#define XK_ISO_Partial_Line_Up 0xfe23
+#define XK_ISO_Partial_Line_Down 0xfe24
+#define XK_ISO_Partial_Space_Left 0xfe25
+#define XK_ISO_Partial_Space_Right 0xfe26
+#define XK_ISO_Set_Margin_Left 0xfe27
+#define XK_ISO_Set_Margin_Right 0xfe28
+#define XK_ISO_Release_Margin_Left 0xfe29
+#define XK_ISO_Release_Margin_Right 0xfe2a
+#define XK_ISO_Release_Both_Margins 0xfe2b
+#define XK_ISO_Fast_Cursor_Left 0xfe2c
+#define XK_ISO_Fast_Cursor_Right 0xfe2d
+#define XK_ISO_Fast_Cursor_Up 0xfe2e
+#define XK_ISO_Fast_Cursor_Down 0xfe2f
+#define XK_ISO_Continuous_Underline 0xfe30
+#define XK_ISO_Discontinuous_Underline 0xfe31
+#define XK_ISO_Emphasize 0xfe32
+#define XK_ISO_Center_Object 0xfe33
+#define XK_ISO_Enter 0xfe34
+
+#define XK_dead_grave 0xfe50
+#define XK_dead_acute 0xfe51
+#define XK_dead_circumflex 0xfe52
+#define XK_dead_tilde 0xfe53
+#define XK_dead_perispomeni 0xfe53 /* alias for dead_tilde */
+#define XK_dead_macron 0xfe54
+#define XK_dead_breve 0xfe55
+#define XK_dead_abovedot 0xfe56
+#define XK_dead_diaeresis 0xfe57
+#define XK_dead_abovering 0xfe58
+#define XK_dead_doubleacute 0xfe59
+#define XK_dead_caron 0xfe5a
+#define XK_dead_cedilla 0xfe5b
+#define XK_dead_ogonek 0xfe5c
+#define XK_dead_iota 0xfe5d
+#define XK_dead_voiced_sound 0xfe5e
+#define XK_dead_semivoiced_sound 0xfe5f
+#define XK_dead_belowdot 0xfe60
+#define XK_dead_hook 0xfe61
+#define XK_dead_horn 0xfe62
+#define XK_dead_stroke 0xfe63
+#define XK_dead_abovecomma 0xfe64
+#define XK_dead_psili 0xfe64 /* alias for dead_abovecomma */
+#define XK_dead_abovereversedcomma 0xfe65
+#define XK_dead_dasia 0xfe65 /* alias for dead_abovereversedcomma */
+#define XK_dead_doublegrave 0xfe66
+#define XK_dead_belowring 0xfe67
+#define XK_dead_belowmacron 0xfe68
+#define XK_dead_belowcircumflex 0xfe69
+#define XK_dead_belowtilde 0xfe6a
+#define XK_dead_belowbreve 0xfe6b
+#define XK_dead_belowdiaeresis 0xfe6c
+#define XK_dead_invertedbreve 0xfe6d
+#define XK_dead_belowcomma 0xfe6e
+#define XK_dead_currency 0xfe6f
+
+/* dead vowels for universal syllable entry */
+#define XK_dead_a 0xfe80
+#define XK_dead_A 0xfe81
+#define XK_dead_e 0xfe82
+#define XK_dead_E 0xfe83
+#define XK_dead_i 0xfe84
+#define XK_dead_I 0xfe85
+#define XK_dead_o 0xfe86
+#define XK_dead_O 0xfe87
+#define XK_dead_u 0xfe88
+#define XK_dead_U 0xfe89
+#define XK_dead_small_schwa 0xfe8a
+#define XK_dead_capital_schwa 0xfe8b
+
+#define XK_First_Virtual_Screen 0xfed0
+#define XK_Prev_Virtual_Screen 0xfed1
+#define XK_Next_Virtual_Screen 0xfed2
+#define XK_Last_Virtual_Screen 0xfed4
+#define XK_Terminate_Server 0xfed5
+
+#define XK_AccessX_Enable 0xfe70
+#define XK_AccessX_Feedback_Enable 0xfe71
+#define XK_RepeatKeys_Enable 0xfe72
+#define XK_SlowKeys_Enable 0xfe73
+#define XK_BounceKeys_Enable 0xfe74
+#define XK_StickyKeys_Enable 0xfe75
+#define XK_MouseKeys_Enable 0xfe76
+#define XK_MouseKeys_Accel_Enable 0xfe77
+#define XK_Overlay1_Enable 0xfe78
+#define XK_Overlay2_Enable 0xfe79
+#define XK_AudibleBell_Enable 0xfe7a
+
+#define XK_Pointer_Left 0xfee0
+#define XK_Pointer_Right 0xfee1
+#define XK_Pointer_Up 0xfee2
+#define XK_Pointer_Down 0xfee3
+#define XK_Pointer_UpLeft 0xfee4
+#define XK_Pointer_UpRight 0xfee5
+#define XK_Pointer_DownLeft 0xfee6
+#define XK_Pointer_DownRight 0xfee7
+#define XK_Pointer_Button_Dflt 0xfee8
+#define XK_Pointer_Button1 0xfee9
+#define XK_Pointer_Button2 0xfeea
+#define XK_Pointer_Button3 0xfeeb
+#define XK_Pointer_Button4 0xfeec
+#define XK_Pointer_Button5 0xfeed
+#define XK_Pointer_DblClick_Dflt 0xfeee
+#define XK_Pointer_DblClick1 0xfeef
+#define XK_Pointer_DblClick2 0xfef0
+#define XK_Pointer_DblClick3 0xfef1
+#define XK_Pointer_DblClick4 0xfef2
+#define XK_Pointer_DblClick5 0xfef3
+#define XK_Pointer_Drag_Dflt 0xfef4
+#define XK_Pointer_Drag1 0xfef5
+#define XK_Pointer_Drag2 0xfef6
+#define XK_Pointer_Drag3 0xfef7
+#define XK_Pointer_Drag4 0xfef8
+#define XK_Pointer_Drag5 0xfefd
+
+#define XK_Pointer_EnableKeys 0xfef9
+#define XK_Pointer_Accelerate 0xfefa
+#define XK_Pointer_DfltBtnNext 0xfefb
+#define XK_Pointer_DfltBtnPrev 0xfefc
+
+#endif /* XK_XKB_KEYS */
+
+/*
+ * 3270 Terminal Keys
+ * Byte 3 = 0xfd
+ */
+
+#ifdef XK_3270
+#define XK_3270_Duplicate 0xfd01
+#define XK_3270_FieldMark 0xfd02
+#define XK_3270_Right2 0xfd03
+#define XK_3270_Left2 0xfd04
+#define XK_3270_BackTab 0xfd05
+#define XK_3270_EraseEOF 0xfd06
+#define XK_3270_EraseInput 0xfd07
+#define XK_3270_Reset 0xfd08
+#define XK_3270_Quit 0xfd09
+#define XK_3270_PA1 0xfd0a
+#define XK_3270_PA2 0xfd0b
+#define XK_3270_PA3 0xfd0c
+#define XK_3270_Test 0xfd0d
+#define XK_3270_Attn 0xfd0e
+#define XK_3270_CursorBlink 0xfd0f
+#define XK_3270_AltCursor 0xfd10
+#define XK_3270_KeyClick 0xfd11
+#define XK_3270_Jump 0xfd12
+#define XK_3270_Ident 0xfd13
+#define XK_3270_Rule 0xfd14
+#define XK_3270_Copy 0xfd15
+#define XK_3270_Play 0xfd16
+#define XK_3270_Setup 0xfd17
+#define XK_3270_Record 0xfd18
+#define XK_3270_ChangeScreen 0xfd19
+#define XK_3270_DeleteWord 0xfd1a
+#define XK_3270_ExSelect 0xfd1b
+#define XK_3270_CursorSelect 0xfd1c
+#define XK_3270_PrintScreen 0xfd1d
+#define XK_3270_Enter 0xfd1e
+#endif /* XK_3270 */
+
+/*
+ * Latin 1
+ * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
+ * Byte 3 = 0
+ */
+#ifdef XK_LATIN1
+#define XK_space 0x0020 /* U+0020 SPACE */
+#define XK_exclam 0x0021 /* U+0021 EXCLAMATION MARK */
+#define XK_quotedbl 0x0022 /* U+0022 QUOTATION MARK */
+#define XK_numbersign 0x0023 /* U+0023 NUMBER SIGN */
+#define XK_dollar 0x0024 /* U+0024 DOLLAR SIGN */
+#define XK_percent 0x0025 /* U+0025 PERCENT SIGN */
+#define XK_ampersand 0x0026 /* U+0026 AMPERSAND */
+#define XK_apostrophe 0x0027 /* U+0027 APOSTROPHE */
+#define XK_quoteright 0x0027 /* deprecated */
+#define XK_parenleft 0x0028 /* U+0028 LEFT PARENTHESIS */
+#define XK_parenright 0x0029 /* U+0029 RIGHT PARENTHESIS */
+#define XK_asterisk 0x002a /* U+002A ASTERISK */
+#define XK_plus 0x002b /* U+002B PLUS SIGN */
+#define XK_comma 0x002c /* U+002C COMMA */
+#define XK_minus 0x002d /* U+002D HYPHEN-MINUS */
+#define XK_period 0x002e /* U+002E FULL STOP */
+#define XK_slash 0x002f /* U+002F SOLIDUS */
+#define XK_0 0x0030 /* U+0030 DIGIT ZERO */
+#define XK_1 0x0031 /* U+0031 DIGIT ONE */
+#define XK_2 0x0032 /* U+0032 DIGIT TWO */
+#define XK_3 0x0033 /* U+0033 DIGIT THREE */
+#define XK_4 0x0034 /* U+0034 DIGIT FOUR */
+#define XK_5 0x0035 /* U+0035 DIGIT FIVE */
+#define XK_6 0x0036 /* U+0036 DIGIT SIX */
+#define XK_7 0x0037 /* U+0037 DIGIT SEVEN */
+#define XK_8 0x0038 /* U+0038 DIGIT EIGHT */
+#define XK_9 0x0039 /* U+0039 DIGIT NINE */
+#define XK_colon 0x003a /* U+003A COLON */
+#define XK_semicolon 0x003b /* U+003B SEMICOLON */
+#define XK_less 0x003c /* U+003C LESS-THAN SIGN */
+#define XK_equal 0x003d /* U+003D EQUALS SIGN */
+#define XK_greater 0x003e /* U+003E GREATER-THAN SIGN */
+#define XK_question 0x003f /* U+003F QUESTION MARK */
+#define XK_at 0x0040 /* U+0040 COMMERCIAL AT */
+#define XK_A 0x0041 /* U+0041 LATIN CAPITAL LETTER A */
+#define XK_B 0x0042 /* U+0042 LATIN CAPITAL LETTER B */
+#define XK_C 0x0043 /* U+0043 LATIN CAPITAL LETTER C */
+#define XK_D 0x0044 /* U+0044 LATIN CAPITAL LETTER D */
+#define XK_E 0x0045 /* U+0045 LATIN CAPITAL LETTER E */
+#define XK_F 0x0046 /* U+0046 LATIN CAPITAL LETTER F */
+#define XK_G 0x0047 /* U+0047 LATIN CAPITAL LETTER G */
+#define XK_H 0x0048 /* U+0048 LATIN CAPITAL LETTER H */
+#define XK_I 0x0049 /* U+0049 LATIN CAPITAL LETTER I */
+#define XK_J 0x004a /* U+004A LATIN CAPITAL LETTER J */
+#define XK_K 0x004b /* U+004B LATIN CAPITAL LETTER K */
+#define XK_L 0x004c /* U+004C LATIN CAPITAL LETTER L */
+#define XK_M 0x004d /* U+004D LATIN CAPITAL LETTER M */
+#define XK_N 0x004e /* U+004E LATIN CAPITAL LETTER N */
+#define XK_O 0x004f /* U+004F LATIN CAPITAL LETTER O */
+#define XK_P 0x0050 /* U+0050 LATIN CAPITAL LETTER P */
+#define XK_Q 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */
+#define XK_R 0x0052 /* U+0052 LATIN CAPITAL LETTER R */
+#define XK_S 0x0053 /* U+0053 LATIN CAPITAL LETTER S */
+#define XK_T 0x0054 /* U+0054 LATIN CAPITAL LETTER T */
+#define XK_U 0x0055 /* U+0055 LATIN CAPITAL LETTER U */
+#define XK_V 0x0056 /* U+0056 LATIN CAPITAL LETTER V */
+#define XK_W 0x0057 /* U+0057 LATIN CAPITAL LETTER W */
+#define XK_X 0x0058 /* U+0058 LATIN CAPITAL LETTER X */
+#define XK_Y 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */
+#define XK_Z 0x005a /* U+005A LATIN CAPITAL LETTER Z */
+#define XK_bracketleft 0x005b /* U+005B LEFT SQUARE BRACKET */
+#define XK_backslash 0x005c /* U+005C REVERSE SOLIDUS */
+#define XK_bracketright 0x005d /* U+005D RIGHT SQUARE BRACKET */
+#define XK_asciicircum 0x005e /* U+005E CIRCUMFLEX ACCENT */
+#define XK_underscore 0x005f /* U+005F LOW LINE */
+#define XK_grave 0x0060 /* U+0060 GRAVE ACCENT */
+#define XK_quoteleft 0x0060 /* deprecated */
+#define XK_a 0x0061 /* U+0061 LATIN SMALL LETTER A */
+#define XK_b 0x0062 /* U+0062 LATIN SMALL LETTER B */
+#define XK_c 0x0063 /* U+0063 LATIN SMALL LETTER C */
+#define XK_d 0x0064 /* U+0064 LATIN SMALL LETTER D */
+#define XK_e 0x0065 /* U+0065 LATIN SMALL LETTER E */
+#define XK_f 0x0066 /* U+0066 LATIN SMALL LETTER F */
+#define XK_g 0x0067 /* U+0067 LATIN SMALL LETTER G */
+#define XK_h 0x0068 /* U+0068 LATIN SMALL LETTER H */
+#define XK_i 0x0069 /* U+0069 LATIN SMALL LETTER I */
+#define XK_j 0x006a /* U+006A LATIN SMALL LETTER J */
+#define XK_k 0x006b /* U+006B LATIN SMALL LETTER K */
+#define XK_l 0x006c /* U+006C LATIN SMALL LETTER L */
+#define XK_m 0x006d /* U+006D LATIN SMALL LETTER M */
+#define XK_n 0x006e /* U+006E LATIN SMALL LETTER N */
+#define XK_o 0x006f /* U+006F LATIN SMALL LETTER O */
+#define XK_p 0x0070 /* U+0070 LATIN SMALL LETTER P */
+#define XK_q 0x0071 /* U+0071 LATIN SMALL LETTER Q */
+#define XK_r 0x0072 /* U+0072 LATIN SMALL LETTER R */
+#define XK_s 0x0073 /* U+0073 LATIN SMALL LETTER S */
+#define XK_t 0x0074 /* U+0074 LATIN SMALL LETTER T */
+#define XK_u 0x0075 /* U+0075 LATIN SMALL LETTER U */
+#define XK_v 0x0076 /* U+0076 LATIN SMALL LETTER V */
+#define XK_w 0x0077 /* U+0077 LATIN SMALL LETTER W */
+#define XK_x 0x0078 /* U+0078 LATIN SMALL LETTER X */
+#define XK_y 0x0079 /* U+0079 LATIN SMALL LETTER Y */
+#define XK_z 0x007a /* U+007A LATIN SMALL LETTER Z */
+#define XK_braceleft 0x007b /* U+007B LEFT CURLY BRACKET */
+#define XK_bar 0x007c /* U+007C VERTICAL LINE */
+#define XK_braceright 0x007d /* U+007D RIGHT CURLY BRACKET */
+#define XK_asciitilde 0x007e /* U+007E TILDE */
+
+#define XK_nobreakspace 0x00a0 /* U+00A0 NO-BREAK SPACE */
+#define XK_exclamdown 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */
+#define XK_cent 0x00a2 /* U+00A2 CENT SIGN */
+#define XK_sterling 0x00a3 /* U+00A3 POUND SIGN */
+#define XK_currency 0x00a4 /* U+00A4 CURRENCY SIGN */
+#define XK_yen 0x00a5 /* U+00A5 YEN SIGN */
+#define XK_brokenbar 0x00a6 /* U+00A6 BROKEN BAR */
+#define XK_section 0x00a7 /* U+00A7 SECTION SIGN */
+#define XK_diaeresis 0x00a8 /* U+00A8 DIAERESIS */
+#define XK_copyright 0x00a9 /* U+00A9 COPYRIGHT SIGN */
+#define XK_ordfeminine 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */
+#define XK_guillemotleft 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+#define XK_notsign 0x00ac /* U+00AC NOT SIGN */
+#define XK_hyphen 0x00ad /* U+00AD SOFT HYPHEN */
+#define XK_registered 0x00ae /* U+00AE REGISTERED SIGN */
+#define XK_macron 0x00af /* U+00AF MACRON */
+#define XK_degree 0x00b0 /* U+00B0 DEGREE SIGN */
+#define XK_plusminus 0x00b1 /* U+00B1 PLUS-MINUS SIGN */
+#define XK_twosuperior 0x00b2 /* U+00B2 SUPERSCRIPT TWO */
+#define XK_threesuperior 0x00b3 /* U+00B3 SUPERSCRIPT THREE */
+#define XK_acute 0x00b4 /* U+00B4 ACUTE ACCENT */
+#define XK_mu 0x00b5 /* U+00B5 MICRO SIGN */
+#define XK_paragraph 0x00b6 /* U+00B6 PILCROW SIGN */
+#define XK_periodcentered 0x00b7 /* U+00B7 MIDDLE DOT */
+#define XK_cedilla 0x00b8 /* U+00B8 CEDILLA */
+#define XK_onesuperior 0x00b9 /* U+00B9 SUPERSCRIPT ONE */
+#define XK_masculine 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */
+#define XK_guillemotright 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+#define XK_onequarter 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */
+#define XK_onehalf 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */
+#define XK_threequarters 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */
+#define XK_questiondown 0x00bf /* U+00BF INVERTED QUESTION MARK */
+#define XK_Agrave 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */
+#define XK_Aacute 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */
+#define XK_Acircumflex 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+#define XK_Atilde 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */
+#define XK_Adiaeresis 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */
+#define XK_Aring 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */
+#define XK_AE 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */
+#define XK_Ccedilla 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */
+#define XK_Egrave 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */
+#define XK_Eacute 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
+#define XK_Ecircumflex 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+#define XK_Ediaeresis 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */
+#define XK_Igrave 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */
+#define XK_Iacute 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */
+#define XK_Icircumflex 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+#define XK_Idiaeresis 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */
+#define XK_ETH 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */
+#define XK_Eth 0x00d0 /* deprecated */
+#define XK_Ntilde 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */
+#define XK_Ograve 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */
+#define XK_Oacute 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */
+#define XK_Ocircumflex 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+#define XK_Otilde 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */
+#define XK_Odiaeresis 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */
+#define XK_multiply 0x00d7 /* U+00D7 MULTIPLICATION SIGN */
+#define XK_Oslash 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
+#define XK_Ooblique 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
+#define XK_Ugrave 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */
+#define XK_Uacute 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */
+#define XK_Ucircumflex 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+#define XK_Udiaeresis 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */
+#define XK_Yacute 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */
+#define XK_THORN 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */
+#define XK_Thorn 0x00de /* deprecated */
+#define XK_ssharp 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */
+#define XK_agrave 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */
+#define XK_aacute 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */
+#define XK_acircumflex 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */
+#define XK_atilde 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */
+#define XK_adiaeresis 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */
+#define XK_aring 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */
+#define XK_ae 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */
+#define XK_ccedilla 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */
+#define XK_egrave 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */
+#define XK_eacute 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
+#define XK_ecircumflex 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */
+#define XK_ediaeresis 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */
+#define XK_igrave 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */
+#define XK_iacute 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */
+#define XK_icircumflex 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */
+#define XK_idiaeresis 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */
+#define XK_eth 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */
+#define XK_ntilde 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */
+#define XK_ograve 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */
+#define XK_oacute 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */
+#define XK_ocircumflex 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */
+#define XK_otilde 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */
+#define XK_odiaeresis 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */
+#define XK_division 0x00f7 /* U+00F7 DIVISION SIGN */
+#define XK_oslash 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
+#define XK_ooblique 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
+#define XK_ugrave 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */
+#define XK_uacute 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */
+#define XK_ucircumflex 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */
+#define XK_udiaeresis 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */
+#define XK_yacute 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */
+#define XK_thorn 0x00fe /* U+00FE LATIN SMALL LETTER THORN */
+#define XK_ydiaeresis 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
+#endif /* XK_LATIN1 */
+
+/*
+ * Latin 2
+ * Byte 3 = 1
+ */
+
+#ifdef XK_LATIN2
+#define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
+#define XK_breve 0x01a2 /* U+02D8 BREVE */
+#define XK_Lstroke 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */
+#define XK_Lcaron 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */
+#define XK_Sacute 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */
+#define XK_Scaron 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */
+#define XK_Scedilla 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */
+#define XK_Tcaron 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */
+#define XK_Zacute 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */
+#define XK_Zcaron 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */
+#define XK_Zabovedot 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+#define XK_aogonek 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */
+#define XK_ogonek 0x01b2 /* U+02DB OGONEK */
+#define XK_lstroke 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */
+#define XK_lcaron 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */
+#define XK_sacute 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */
+#define XK_caron 0x01b7 /* U+02C7 CARON */
+#define XK_scaron 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */
+#define XK_scedilla 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */
+#define XK_tcaron 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */
+#define XK_zacute 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */
+#define XK_doubleacute 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */
+#define XK_zcaron 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */
+#define XK_zabovedot 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */
+#define XK_Racute 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */
+#define XK_Abreve 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */
+#define XK_Lacute 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */
+#define XK_Cacute 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */
+#define XK_Ccaron 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */
+#define XK_Eogonek 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */
+#define XK_Ecaron 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */
+#define XK_Dcaron 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */
+#define XK_Dstroke 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */
+#define XK_Nacute 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */
+#define XK_Ncaron 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */
+#define XK_Odoubleacute 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+#define XK_Rcaron 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */
+#define XK_Uring 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */
+#define XK_Udoubleacute 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+#define XK_Tcedilla 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */
+#define XK_racute 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */
+#define XK_abreve 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */
+#define XK_lacute 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */
+#define XK_cacute 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */
+#define XK_ccaron 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */
+#define XK_eogonek 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */
+#define XK_ecaron 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */
+#define XK_dcaron 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */
+#define XK_dstroke 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */
+#define XK_nacute 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */
+#define XK_ncaron 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */
+#define XK_odoubleacute 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+#define XK_udoubleacute 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+#define XK_rcaron 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */
+#define XK_uring 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */
+#define XK_tcedilla 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */
+#define XK_abovedot 0x01ff /* U+02D9 DOT ABOVE */
+#endif /* XK_LATIN2 */
+
+/*
+ * Latin 3
+ * Byte 3 = 2
+ */
+
+#ifdef XK_LATIN3
+#define XK_Hstroke 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */
+#define XK_Hcircumflex 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+#define XK_Iabovedot 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */
+#define XK_Gbreve 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */
+#define XK_Jcircumflex 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+#define XK_hstroke 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */
+#define XK_hcircumflex 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */
+#define XK_idotless 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */
+#define XK_gbreve 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */
+#define XK_jcircumflex 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */
+#define XK_Cabovedot 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */
+#define XK_Ccircumflex 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+#define XK_Gabovedot 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */
+#define XK_Gcircumflex 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+#define XK_Ubreve 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */
+#define XK_Scircumflex 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+#define XK_cabovedot 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */
+#define XK_ccircumflex 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */
+#define XK_gabovedot 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */
+#define XK_gcircumflex 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */
+#define XK_ubreve 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */
+#define XK_scircumflex 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */
+#endif /* XK_LATIN3 */
+
+
+/*
+ * Latin 4
+ * Byte 3 = 3
+ */
+
+#ifdef XK_LATIN4
+#define XK_kra 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */
+#define XK_kappa 0x03a2 /* deprecated */
+#define XK_Rcedilla 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */
+#define XK_Itilde 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */
+#define XK_Lcedilla 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */
+#define XK_Emacron 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */
+#define XK_Gcedilla 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */
+#define XK_Tslash 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */
+#define XK_rcedilla 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */
+#define XK_itilde 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */
+#define XK_lcedilla 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */
+#define XK_emacron 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */
+#define XK_gcedilla 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */
+#define XK_tslash 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */
+#define XK_ENG 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */
+#define XK_eng 0x03bf /* U+014B LATIN SMALL LETTER ENG */
+#define XK_Amacron 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */
+#define XK_Iogonek 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */
+#define XK_Eabovedot 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */
+#define XK_Imacron 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */
+#define XK_Ncedilla 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */
+#define XK_Omacron 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */
+#define XK_Kcedilla 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */
+#define XK_Uogonek 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */
+#define XK_Utilde 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */
+#define XK_Umacron 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */
+#define XK_amacron 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */
+#define XK_iogonek 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */
+#define XK_eabovedot 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */
+#define XK_imacron 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */
+#define XK_ncedilla 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */
+#define XK_omacron 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */
+#define XK_kcedilla 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */
+#define XK_uogonek 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */
+#define XK_utilde 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */
+#define XK_umacron 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */
+#endif /* XK_LATIN4 */
+
+/*
+ * Latin 8
+ */
+#ifdef XK_LATIN8
+#define XK_Babovedot 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */
+#define XK_babovedot 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */
+#define XK_Dabovedot 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */
+#define XK_Wgrave 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */
+#define XK_Wacute 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */
+#define XK_dabovedot 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */
+#define XK_Ygrave 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */
+#define XK_Fabovedot 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */
+#define XK_fabovedot 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */
+#define XK_Mabovedot 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */
+#define XK_mabovedot 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */
+#define XK_Pabovedot 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */
+#define XK_wgrave 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */
+#define XK_pabovedot 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */
+#define XK_wacute 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */
+#define XK_Sabovedot 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */
+#define XK_ygrave 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */
+#define XK_Wdiaeresis 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */
+#define XK_wdiaeresis 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */
+#define XK_sabovedot 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */
+#define XK_Wcircumflex 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+#define XK_Tabovedot 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */
+#define XK_Ycircumflex 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+#define XK_wcircumflex 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */
+#define XK_tabovedot 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */
+#define XK_ycircumflex 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+#endif /* XK_LATIN8 */
+
+/*
+ * Latin 9
+ * Byte 3 = 0x13
+ */
+
+#ifdef XK_LATIN9
+#define XK_OE 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */
+#define XK_oe 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */
+#define XK_Ydiaeresis 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */
+#endif /* XK_LATIN9 */
+
+/*
+ * Katakana
+ * Byte 3 = 4
+ */
+
+#ifdef XK_KATAKANA
+#define XK_overline 0x047e /* U+203E OVERLINE */
+#define XK_kana_fullstop 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */
+#define XK_kana_openingbracket 0x04a2 /* U+300C LEFT CORNER BRACKET */
+#define XK_kana_closingbracket 0x04a3 /* U+300D RIGHT CORNER BRACKET */
+#define XK_kana_comma 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */
+#define XK_kana_conjunctive 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */
+#define XK_kana_middledot 0x04a5 /* deprecated */
+#define XK_kana_WO 0x04a6 /* U+30F2 KATAKANA LETTER WO */
+#define XK_kana_a 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */
+#define XK_kana_i 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */
+#define XK_kana_u 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */
+#define XK_kana_e 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */
+#define XK_kana_o 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */
+#define XK_kana_ya 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */
+#define XK_kana_yu 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */
+#define XK_kana_yo 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */
+#define XK_kana_tsu 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */
+#define XK_kana_tu 0x04af /* deprecated */
+#define XK_prolongedsound 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+#define XK_kana_A 0x04b1 /* U+30A2 KATAKANA LETTER A */
+#define XK_kana_I 0x04b2 /* U+30A4 KATAKANA LETTER I */
+#define XK_kana_U 0x04b3 /* U+30A6 KATAKANA LETTER U */
+#define XK_kana_E 0x04b4 /* U+30A8 KATAKANA LETTER E */
+#define XK_kana_O 0x04b5 /* U+30AA KATAKANA LETTER O */
+#define XK_kana_KA 0x04b6 /* U+30AB KATAKANA LETTER KA */
+#define XK_kana_KI 0x04b7 /* U+30AD KATAKANA LETTER KI */
+#define XK_kana_KU 0x04b8 /* U+30AF KATAKANA LETTER KU */
+#define XK_kana_KE 0x04b9 /* U+30B1 KATAKANA LETTER KE */
+#define XK_kana_KO 0x04ba /* U+30B3 KATAKANA LETTER KO */
+#define XK_kana_SA 0x04bb /* U+30B5 KATAKANA LETTER SA */
+#define XK_kana_SHI 0x04bc /* U+30B7 KATAKANA LETTER SI */
+#define XK_kana_SU 0x04bd /* U+30B9 KATAKANA LETTER SU */
+#define XK_kana_SE 0x04be /* U+30BB KATAKANA LETTER SE */
+#define XK_kana_SO 0x04bf /* U+30BD KATAKANA LETTER SO */
+#define XK_kana_TA 0x04c0 /* U+30BF KATAKANA LETTER TA */
+#define XK_kana_CHI 0x04c1 /* U+30C1 KATAKANA LETTER TI */
+#define XK_kana_TI 0x04c1 /* deprecated */
+#define XK_kana_TSU 0x04c2 /* U+30C4 KATAKANA LETTER TU */
+#define XK_kana_TU 0x04c2 /* deprecated */
+#define XK_kana_TE 0x04c3 /* U+30C6 KATAKANA LETTER TE */
+#define XK_kana_TO 0x04c4 /* U+30C8 KATAKANA LETTER TO */
+#define XK_kana_NA 0x04c5 /* U+30CA KATAKANA LETTER NA */
+#define XK_kana_NI 0x04c6 /* U+30CB KATAKANA LETTER NI */
+#define XK_kana_NU 0x04c7 /* U+30CC KATAKANA LETTER NU */
+#define XK_kana_NE 0x04c8 /* U+30CD KATAKANA LETTER NE */
+#define XK_kana_NO 0x04c9 /* U+30CE KATAKANA LETTER NO */
+#define XK_kana_HA 0x04ca /* U+30CF KATAKANA LETTER HA */
+#define XK_kana_HI 0x04cb /* U+30D2 KATAKANA LETTER HI */
+#define XK_kana_FU 0x04cc /* U+30D5 KATAKANA LETTER HU */
+#define XK_kana_HU 0x04cc /* deprecated */
+#define XK_kana_HE 0x04cd /* U+30D8 KATAKANA LETTER HE */
+#define XK_kana_HO 0x04ce /* U+30DB KATAKANA LETTER HO */
+#define XK_kana_MA 0x04cf /* U+30DE KATAKANA LETTER MA */
+#define XK_kana_MI 0x04d0 /* U+30DF KATAKANA LETTER MI */
+#define XK_kana_MU 0x04d1 /* U+30E0 KATAKANA LETTER MU */
+#define XK_kana_ME 0x04d2 /* U+30E1 KATAKANA LETTER ME */
+#define XK_kana_MO 0x04d3 /* U+30E2 KATAKANA LETTER MO */
+#define XK_kana_YA 0x04d4 /* U+30E4 KATAKANA LETTER YA */
+#define XK_kana_YU 0x04d5 /* U+30E6 KATAKANA LETTER YU */
+#define XK_kana_YO 0x04d6 /* U+30E8 KATAKANA LETTER YO */
+#define XK_kana_RA 0x04d7 /* U+30E9 KATAKANA LETTER RA */
+#define XK_kana_RI 0x04d8 /* U+30EA KATAKANA LETTER RI */
+#define XK_kana_RU 0x04d9 /* U+30EB KATAKANA LETTER RU */
+#define XK_kana_RE 0x04da /* U+30EC KATAKANA LETTER RE */
+#define XK_kana_RO 0x04db /* U+30ED KATAKANA LETTER RO */
+#define XK_kana_WA 0x04dc /* U+30EF KATAKANA LETTER WA */
+#define XK_kana_N 0x04dd /* U+30F3 KATAKANA LETTER N */
+#define XK_voicedsound 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */
+#define XK_semivoicedsound 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+#define XK_kana_switch 0xff7e /* Alias for mode_switch */
+#endif /* XK_KATAKANA */
+
+/*
+ * Arabic
+ * Byte 3 = 5
+ */
+
+#ifdef XK_ARABIC
+#define XK_Farsi_0 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */
+#define XK_Farsi_1 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */
+#define XK_Farsi_2 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */
+#define XK_Farsi_3 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */
+#define XK_Farsi_4 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */
+#define XK_Farsi_5 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */
+#define XK_Farsi_6 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */
+#define XK_Farsi_7 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */
+#define XK_Farsi_8 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */
+#define XK_Farsi_9 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */
+#define XK_Arabic_percent 0x100066a /* U+066A ARABIC PERCENT SIGN */
+#define XK_Arabic_superscript_alef 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */
+#define XK_Arabic_tteh 0x1000679 /* U+0679 ARABIC LETTER TTEH */
+#define XK_Arabic_peh 0x100067e /* U+067E ARABIC LETTER PEH */
+#define XK_Arabic_tcheh 0x1000686 /* U+0686 ARABIC LETTER TCHEH */
+#define XK_Arabic_ddal 0x1000688 /* U+0688 ARABIC LETTER DDAL */
+#define XK_Arabic_rreh 0x1000691 /* U+0691 ARABIC LETTER RREH */
+#define XK_Arabic_comma 0x05ac /* U+060C ARABIC COMMA */
+#define XK_Arabic_fullstop 0x10006d4 /* U+06D4 ARABIC FULL STOP */
+#define XK_Arabic_0 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */
+#define XK_Arabic_1 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */
+#define XK_Arabic_2 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */
+#define XK_Arabic_3 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */
+#define XK_Arabic_4 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */
+#define XK_Arabic_5 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */
+#define XK_Arabic_6 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */
+#define XK_Arabic_7 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */
+#define XK_Arabic_8 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */
+#define XK_Arabic_9 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */
+#define XK_Arabic_semicolon 0x05bb /* U+061B ARABIC SEMICOLON */
+#define XK_Arabic_question_mark 0x05bf /* U+061F ARABIC QUESTION MARK */
+#define XK_Arabic_hamza 0x05c1 /* U+0621 ARABIC LETTER HAMZA */
+#define XK_Arabic_maddaonalef 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+#define XK_Arabic_hamzaonalef 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+#define XK_Arabic_hamzaonwaw 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+#define XK_Arabic_hamzaunderalef 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+#define XK_Arabic_hamzaonyeh 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+#define XK_Arabic_alef 0x05c7 /* U+0627 ARABIC LETTER ALEF */
+#define XK_Arabic_beh 0x05c8 /* U+0628 ARABIC LETTER BEH */
+#define XK_Arabic_tehmarbuta 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */
+#define XK_Arabic_teh 0x05ca /* U+062A ARABIC LETTER TEH */
+#define XK_Arabic_theh 0x05cb /* U+062B ARABIC LETTER THEH */
+#define XK_Arabic_jeem 0x05cc /* U+062C ARABIC LETTER JEEM */
+#define XK_Arabic_hah 0x05cd /* U+062D ARABIC LETTER HAH */
+#define XK_Arabic_khah 0x05ce /* U+062E ARABIC LETTER KHAH */
+#define XK_Arabic_dal 0x05cf /* U+062F ARABIC LETTER DAL */
+#define XK_Arabic_thal 0x05d0 /* U+0630 ARABIC LETTER THAL */
+#define XK_Arabic_ra 0x05d1 /* U+0631 ARABIC LETTER REH */
+#define XK_Arabic_zain 0x05d2 /* U+0632 ARABIC LETTER ZAIN */
+#define XK_Arabic_seen 0x05d3 /* U+0633 ARABIC LETTER SEEN */
+#define XK_Arabic_sheen 0x05d4 /* U+0634 ARABIC LETTER SHEEN */
+#define XK_Arabic_sad 0x05d5 /* U+0635 ARABIC LETTER SAD */
+#define XK_Arabic_dad 0x05d6 /* U+0636 ARABIC LETTER DAD */
+#define XK_Arabic_tah 0x05d7 /* U+0637 ARABIC LETTER TAH */
+#define XK_Arabic_zah 0x05d8 /* U+0638 ARABIC LETTER ZAH */
+#define XK_Arabic_ain 0x05d9 /* U+0639 ARABIC LETTER AIN */
+#define XK_Arabic_ghain 0x05da /* U+063A ARABIC LETTER GHAIN */
+#define XK_Arabic_tatweel 0x05e0 /* U+0640 ARABIC TATWEEL */
+#define XK_Arabic_feh 0x05e1 /* U+0641 ARABIC LETTER FEH */
+#define XK_Arabic_qaf 0x05e2 /* U+0642 ARABIC LETTER QAF */
+#define XK_Arabic_kaf 0x05e3 /* U+0643 ARABIC LETTER KAF */
+#define XK_Arabic_lam 0x05e4 /* U+0644 ARABIC LETTER LAM */
+#define XK_Arabic_meem 0x05e5 /* U+0645 ARABIC LETTER MEEM */
+#define XK_Arabic_noon 0x05e6 /* U+0646 ARABIC LETTER NOON */
+#define XK_Arabic_ha 0x05e7 /* U+0647 ARABIC LETTER HEH */
+#define XK_Arabic_heh 0x05e7 /* deprecated */
+#define XK_Arabic_waw 0x05e8 /* U+0648 ARABIC LETTER WAW */
+#define XK_Arabic_alefmaksura 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */
+#define XK_Arabic_yeh 0x05ea /* U+064A ARABIC LETTER YEH */
+#define XK_Arabic_fathatan 0x05eb /* U+064B ARABIC FATHATAN */
+#define XK_Arabic_dammatan 0x05ec /* U+064C ARABIC DAMMATAN */
+#define XK_Arabic_kasratan 0x05ed /* U+064D ARABIC KASRATAN */
+#define XK_Arabic_fatha 0x05ee /* U+064E ARABIC FATHA */
+#define XK_Arabic_damma 0x05ef /* U+064F ARABIC DAMMA */
+#define XK_Arabic_kasra 0x05f0 /* U+0650 ARABIC KASRA */
+#define XK_Arabic_shadda 0x05f1 /* U+0651 ARABIC SHADDA */
+#define XK_Arabic_sukun 0x05f2 /* U+0652 ARABIC SUKUN */
+#define XK_Arabic_madda_above 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */
+#define XK_Arabic_hamza_above 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */
+#define XK_Arabic_hamza_below 0x1000655 /* U+0655 ARABIC HAMZA BELOW */
+#define XK_Arabic_jeh 0x1000698 /* U+0698 ARABIC LETTER JEH */
+#define XK_Arabic_veh 0x10006a4 /* U+06A4 ARABIC LETTER VEH */
+#define XK_Arabic_keheh 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */
+#define XK_Arabic_gaf 0x10006af /* U+06AF ARABIC LETTER GAF */
+#define XK_Arabic_noon_ghunna 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */
+#define XK_Arabic_heh_doachashmee 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+#define XK_Farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */
+#define XK_Arabic_farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */
+#define XK_Arabic_yeh_baree 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */
+#define XK_Arabic_heh_goal 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */
+#define XK_Arabic_switch 0xff7e /* Alias for mode_switch */
+#endif /* XK_ARABIC */
+
+/*
+ * Cyrillic
+ * Byte 3 = 6
+ */
+#ifdef XK_CYRILLIC
+#define XK_Cyrillic_GHE_bar 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */
+#define XK_Cyrillic_ghe_bar 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */
+#define XK_Cyrillic_ZHE_descender 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */
+#define XK_Cyrillic_zhe_descender 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */
+#define XK_Cyrillic_KA_descender 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */
+#define XK_Cyrillic_ka_descender 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */
+#define XK_Cyrillic_KA_vertstroke 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */
+#define XK_Cyrillic_ka_vertstroke 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */
+#define XK_Cyrillic_EN_descender 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */
+#define XK_Cyrillic_en_descender 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */
+#define XK_Cyrillic_U_straight 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */
+#define XK_Cyrillic_u_straight 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */
+#define XK_Cyrillic_U_straight_bar 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */
+#define XK_Cyrillic_u_straight_bar 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */
+#define XK_Cyrillic_HA_descender 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */
+#define XK_Cyrillic_ha_descender 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */
+#define XK_Cyrillic_CHE_descender 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */
+#define XK_Cyrillic_che_descender 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */
+#define XK_Cyrillic_CHE_vertstroke 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */
+#define XK_Cyrillic_che_vertstroke 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */
+#define XK_Cyrillic_SHHA 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */
+#define XK_Cyrillic_shha 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */
+
+#define XK_Cyrillic_SCHWA 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */
+#define XK_Cyrillic_schwa 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */
+#define XK_Cyrillic_I_macron 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */
+#define XK_Cyrillic_i_macron 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */
+#define XK_Cyrillic_O_bar 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */
+#define XK_Cyrillic_o_bar 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */
+#define XK_Cyrillic_U_macron 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */
+#define XK_Cyrillic_u_macron 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */
+
+#define XK_Serbian_dje 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */
+#define XK_Macedonia_gje 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */
+#define XK_Cyrillic_io 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */
+#define XK_Ukrainian_ie 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */
+#define XK_Ukranian_je 0x06a4 /* deprecated */
+#define XK_Macedonia_dse 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */
+#define XK_Ukrainian_i 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+#define XK_Ukranian_i 0x06a6 /* deprecated */
+#define XK_Ukrainian_yi 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */
+#define XK_Ukranian_yi 0x06a7 /* deprecated */
+#define XK_Cyrillic_je 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */
+#define XK_Serbian_je 0x06a8 /* deprecated */
+#define XK_Cyrillic_lje 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */
+#define XK_Serbian_lje 0x06a9 /* deprecated */
+#define XK_Cyrillic_nje 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */
+#define XK_Serbian_nje 0x06aa /* deprecated */
+#define XK_Serbian_tshe 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */
+#define XK_Macedonia_kje 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */
+#define XK_Ukrainian_ghe_with_upturn 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */
+#define XK_Byelorussian_shortu 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */
+#define XK_Cyrillic_dzhe 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */
+#define XK_Serbian_dze 0x06af /* deprecated */
+#define XK_numerosign 0x06b0 /* U+2116 NUMERO SIGN */
+#define XK_Serbian_DJE 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */
+#define XK_Macedonia_GJE 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */
+#define XK_Cyrillic_IO 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */
+#define XK_Ukrainian_IE 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+#define XK_Ukranian_JE 0x06b4 /* deprecated */
+#define XK_Macedonia_DSE 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */
+#define XK_Ukrainian_I 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+#define XK_Ukranian_I 0x06b6 /* deprecated */
+#define XK_Ukrainian_YI 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */
+#define XK_Ukranian_YI 0x06b7 /* deprecated */
+#define XK_Cyrillic_JE 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */
+#define XK_Serbian_JE 0x06b8 /* deprecated */
+#define XK_Cyrillic_LJE 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */
+#define XK_Serbian_LJE 0x06b9 /* deprecated */
+#define XK_Cyrillic_NJE 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */
+#define XK_Serbian_NJE 0x06ba /* deprecated */
+#define XK_Serbian_TSHE 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */
+#define XK_Macedonia_KJE 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */
+#define XK_Ukrainian_GHE_WITH_UPTURN 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
+#define XK_Byelorussian_SHORTU 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */
+#define XK_Cyrillic_DZHE 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */
+#define XK_Serbian_DZE 0x06bf /* deprecated */
+#define XK_Cyrillic_yu 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */
+#define XK_Cyrillic_a 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */
+#define XK_Cyrillic_be 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */
+#define XK_Cyrillic_tse 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */
+#define XK_Cyrillic_de 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */
+#define XK_Cyrillic_ie 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */
+#define XK_Cyrillic_ef 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */
+#define XK_Cyrillic_ghe 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */
+#define XK_Cyrillic_ha 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */
+#define XK_Cyrillic_i 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */
+#define XK_Cyrillic_shorti 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */
+#define XK_Cyrillic_ka 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */
+#define XK_Cyrillic_el 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */
+#define XK_Cyrillic_em 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */
+#define XK_Cyrillic_en 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */
+#define XK_Cyrillic_o 0x06cf /* U+043E CYRILLIC SMALL LETTER O */
+#define XK_Cyrillic_pe 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */
+#define XK_Cyrillic_ya 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */
+#define XK_Cyrillic_er 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */
+#define XK_Cyrillic_es 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */
+#define XK_Cyrillic_te 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */
+#define XK_Cyrillic_u 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */
+#define XK_Cyrillic_zhe 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */
+#define XK_Cyrillic_ve 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */
+#define XK_Cyrillic_softsign 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */
+#define XK_Cyrillic_yeru 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */
+#define XK_Cyrillic_ze 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */
+#define XK_Cyrillic_sha 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */
+#define XK_Cyrillic_e 0x06dc /* U+044D CYRILLIC SMALL LETTER E */
+#define XK_Cyrillic_shcha 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */
+#define XK_Cyrillic_che 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */
+#define XK_Cyrillic_hardsign 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */
+#define XK_Cyrillic_YU 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */
+#define XK_Cyrillic_A 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */
+#define XK_Cyrillic_BE 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */
+#define XK_Cyrillic_TSE 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */
+#define XK_Cyrillic_DE 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */
+#define XK_Cyrillic_IE 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */
+#define XK_Cyrillic_EF 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */
+#define XK_Cyrillic_GHE 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */
+#define XK_Cyrillic_HA 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */
+#define XK_Cyrillic_I 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */
+#define XK_Cyrillic_SHORTI 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */
+#define XK_Cyrillic_KA 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */
+#define XK_Cyrillic_EL 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */
+#define XK_Cyrillic_EM 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */
+#define XK_Cyrillic_EN 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */
+#define XK_Cyrillic_O 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */
+#define XK_Cyrillic_PE 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */
+#define XK_Cyrillic_YA 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */
+#define XK_Cyrillic_ER 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */
+#define XK_Cyrillic_ES 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */
+#define XK_Cyrillic_TE 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */
+#define XK_Cyrillic_U 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */
+#define XK_Cyrillic_ZHE 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */
+#define XK_Cyrillic_VE 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */
+#define XK_Cyrillic_SOFTSIGN 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */
+#define XK_Cyrillic_YERU 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */
+#define XK_Cyrillic_ZE 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */
+#define XK_Cyrillic_SHA 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */
+#define XK_Cyrillic_E 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */
+#define XK_Cyrillic_SHCHA 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */
+#define XK_Cyrillic_CHE 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */
+#define XK_Cyrillic_HARDSIGN 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */
+#endif /* XK_CYRILLIC */
+
+/*
+ * Greek
+ * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7)
+ * Byte 3 = 7
+ */
+
+#ifdef XK_GREEK
+#define XK_Greek_ALPHAaccent 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */
+#define XK_Greek_EPSILONaccent 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */
+#define XK_Greek_ETAaccent 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */
+#define XK_Greek_IOTAaccent 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */
+#define XK_Greek_IOTAdieresis 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+#define XK_Greek_IOTAdiaeresis 0x07a5 /* old typo */
+#define XK_Greek_OMICRONaccent 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */
+#define XK_Greek_UPSILONaccent 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */
+#define XK_Greek_UPSILONdieresis 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+#define XK_Greek_OMEGAaccent 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */
+#define XK_Greek_accentdieresis 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */
+#define XK_Greek_horizbar 0x07af /* U+2015 HORIZONTAL BAR */
+#define XK_Greek_alphaaccent 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */
+#define XK_Greek_epsilonaccent 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */
+#define XK_Greek_etaaccent 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */
+#define XK_Greek_iotaaccent 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */
+#define XK_Greek_iotadieresis 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+#define XK_Greek_iotaaccentdieresis 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+#define XK_Greek_omicronaccent 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */
+#define XK_Greek_upsilonaccent 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */
+#define XK_Greek_upsilondieresis 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+#define XK_Greek_upsilonaccentdieresis 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+#define XK_Greek_omegaaccent 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */
+#define XK_Greek_ALPHA 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */
+#define XK_Greek_BETA 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */
+#define XK_Greek_GAMMA 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */
+#define XK_Greek_DELTA 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */
+#define XK_Greek_EPSILON 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */
+#define XK_Greek_ZETA 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */
+#define XK_Greek_ETA 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */
+#define XK_Greek_THETA 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */
+#define XK_Greek_IOTA 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */
+#define XK_Greek_KAPPA 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */
+#define XK_Greek_LAMDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */
+#define XK_Greek_LAMBDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */
+#define XK_Greek_MU 0x07cc /* U+039C GREEK CAPITAL LETTER MU */
+#define XK_Greek_NU 0x07cd /* U+039D GREEK CAPITAL LETTER NU */
+#define XK_Greek_XI 0x07ce /* U+039E GREEK CAPITAL LETTER XI */
+#define XK_Greek_OMICRON 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */
+#define XK_Greek_PI 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */
+#define XK_Greek_RHO 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */
+#define XK_Greek_SIGMA 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */
+#define XK_Greek_TAU 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */
+#define XK_Greek_UPSILON 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */
+#define XK_Greek_PHI 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */
+#define XK_Greek_CHI 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */
+#define XK_Greek_PSI 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */
+#define XK_Greek_OMEGA 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */
+#define XK_Greek_alpha 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */
+#define XK_Greek_beta 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */
+#define XK_Greek_gamma 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */
+#define XK_Greek_delta 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */
+#define XK_Greek_epsilon 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */
+#define XK_Greek_zeta 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */
+#define XK_Greek_eta 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */
+#define XK_Greek_theta 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */
+#define XK_Greek_iota 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */
+#define XK_Greek_kappa 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */
+#define XK_Greek_lamda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */
+#define XK_Greek_lambda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */
+#define XK_Greek_mu 0x07ec /* U+03BC GREEK SMALL LETTER MU */
+#define XK_Greek_nu 0x07ed /* U+03BD GREEK SMALL LETTER NU */
+#define XK_Greek_xi 0x07ee /* U+03BE GREEK SMALL LETTER XI */
+#define XK_Greek_omicron 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */
+#define XK_Greek_pi 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */
+#define XK_Greek_rho 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */
+#define XK_Greek_sigma 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */
+#define XK_Greek_finalsmallsigma 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */
+#define XK_Greek_tau 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */
+#define XK_Greek_upsilon 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */
+#define XK_Greek_phi 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */
+#define XK_Greek_chi 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */
+#define XK_Greek_psi 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */
+#define XK_Greek_omega 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */
+#define XK_Greek_switch 0xff7e /* Alias for mode_switch */
+#endif /* XK_GREEK */
+
+/*
+ * Technical
+ * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html)
+ * Byte 3 = 8
+ */
+
+#ifdef XK_TECHNICAL
+#define XK_leftradical 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */
+#define XK_topleftradical 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/
+#define XK_horizconnector 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/
+#define XK_topintegral 0x08a4 /* U+2320 TOP HALF INTEGRAL */
+#define XK_botintegral 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */
+#define XK_vertconnector 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/
+#define XK_topleftsqbracket 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */
+#define XK_botleftsqbracket 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */
+#define XK_toprightsqbracket 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */
+#define XK_botrightsqbracket 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */
+#define XK_topleftparens 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */
+#define XK_botleftparens 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */
+#define XK_toprightparens 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */
+#define XK_botrightparens 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */
+#define XK_leftmiddlecurlybrace 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */
+#define XK_rightmiddlecurlybrace 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */
+#define XK_topleftsummation 0x08b1
+#define XK_botleftsummation 0x08b2
+#define XK_topvertsummationconnector 0x08b3
+#define XK_botvertsummationconnector 0x08b4
+#define XK_toprightsummation 0x08b5
+#define XK_botrightsummation 0x08b6
+#define XK_rightmiddlesummation 0x08b7
+#define XK_lessthanequal 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */
+#define XK_notequal 0x08bd /* U+2260 NOT EQUAL TO */
+#define XK_greaterthanequal 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */
+#define XK_integral 0x08bf /* U+222B INTEGRAL */
+#define XK_therefore 0x08c0 /* U+2234 THEREFORE */
+#define XK_variation 0x08c1 /* U+221D PROPORTIONAL TO */
+#define XK_infinity 0x08c2 /* U+221E INFINITY */
+#define XK_nabla 0x08c5 /* U+2207 NABLA */
+#define XK_approximate 0x08c8 /* U+223C TILDE OPERATOR */
+#define XK_similarequal 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */
+#define XK_ifonlyif 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */
+#define XK_implies 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */
+#define XK_identical 0x08cf /* U+2261 IDENTICAL TO */
+#define XK_radical 0x08d6 /* U+221A SQUARE ROOT */
+#define XK_includedin 0x08da /* U+2282 SUBSET OF */
+#define XK_includes 0x08db /* U+2283 SUPERSET OF */
+#define XK_intersection 0x08dc /* U+2229 INTERSECTION */
+#define XK_union 0x08dd /* U+222A UNION */
+#define XK_logicaland 0x08de /* U+2227 LOGICAL AND */
+#define XK_logicalor 0x08df /* U+2228 LOGICAL OR */
+#define XK_partialderivative 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */
+#define XK_function 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */
+#define XK_leftarrow 0x08fb /* U+2190 LEFTWARDS ARROW */
+#define XK_uparrow 0x08fc /* U+2191 UPWARDS ARROW */
+#define XK_rightarrow 0x08fd /* U+2192 RIGHTWARDS ARROW */
+#define XK_downarrow 0x08fe /* U+2193 DOWNWARDS ARROW */
+#endif /* XK_TECHNICAL */
+
+/*
+ * Special
+ * (from the DEC VT100 Special Graphics Character Set)
+ * Byte 3 = 9
+ */
+
+#ifdef XK_SPECIAL
+#define XK_blank 0x09df
+#define XK_soliddiamond 0x09e0 /* U+25C6 BLACK DIAMOND */
+#define XK_checkerboard 0x09e1 /* U+2592 MEDIUM SHADE */
+#define XK_ht 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */
+#define XK_ff 0x09e3 /* U+240C SYMBOL FOR FORM FEED */
+#define XK_cr 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */
+#define XK_lf 0x09e5 /* U+240A SYMBOL FOR LINE FEED */
+#define XK_nl 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */
+#define XK_vt 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */
+#define XK_lowrightcorner 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */
+#define XK_uprightcorner 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */
+#define XK_upleftcorner 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */
+#define XK_lowleftcorner 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */
+#define XK_crossinglines 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+#define XK_horizlinescan1 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */
+#define XK_horizlinescan3 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */
+#define XK_horizlinescan5 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */
+#define XK_horizlinescan7 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */
+#define XK_horizlinescan9 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */
+#define XK_leftt 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+#define XK_rightt 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+#define XK_bott 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+#define XK_topt 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+#define XK_vertbar 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */
+#endif /* XK_SPECIAL */
+
+/*
+ * Publishing
+ * (these are probably from a long forgotten DEC Publishing
+ * font that once shipped with DECwrite)
+ * Byte 3 = 0x0a
+ */
+
+#ifdef XK_PUBLISHING
+#define XK_emspace 0x0aa1 /* U+2003 EM SPACE */
+#define XK_enspace 0x0aa2 /* U+2002 EN SPACE */
+#define XK_em3space 0x0aa3 /* U+2004 THREE-PER-EM SPACE */
+#define XK_em4space 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */
+#define XK_digitspace 0x0aa5 /* U+2007 FIGURE SPACE */
+#define XK_punctspace 0x0aa6 /* U+2008 PUNCTUATION SPACE */
+#define XK_thinspace 0x0aa7 /* U+2009 THIN SPACE */
+#define XK_hairspace 0x0aa8 /* U+200A HAIR SPACE */
+#define XK_emdash 0x0aa9 /* U+2014 EM DASH */
+#define XK_endash 0x0aaa /* U+2013 EN DASH */
+#define XK_signifblank 0x0aac /*(U+2423 OPEN BOX)*/
+#define XK_ellipsis 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */
+#define XK_doubbaselinedot 0x0aaf /* U+2025 TWO DOT LEADER */
+#define XK_onethird 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */
+#define XK_twothirds 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */
+#define XK_onefifth 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */
+#define XK_twofifths 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */
+#define XK_threefifths 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */
+#define XK_fourfifths 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */
+#define XK_onesixth 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */
+#define XK_fivesixths 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */
+#define XK_careof 0x0ab8 /* U+2105 CARE OF */
+#define XK_figdash 0x0abb /* U+2012 FIGURE DASH */
+#define XK_leftanglebracket 0x0abc /*(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)*/
+#define XK_decimalpoint 0x0abd /*(U+002E FULL STOP)*/
+#define XK_rightanglebracket 0x0abe /*(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)*/
+#define XK_marker 0x0abf
+#define XK_oneeighth 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */
+#define XK_threeeighths 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */
+#define XK_fiveeighths 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */
+#define XK_seveneighths 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */
+#define XK_trademark 0x0ac9 /* U+2122 TRADE MARK SIGN */
+#define XK_signaturemark 0x0aca /*(U+2613 SALTIRE)*/
+#define XK_trademarkincircle 0x0acb
+#define XK_leftopentriangle 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/
+#define XK_rightopentriangle 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/
+#define XK_emopencircle 0x0ace /*(U+25CB WHITE CIRCLE)*/
+#define XK_emopenrectangle 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/
+#define XK_leftsinglequotemark 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */
+#define XK_rightsinglequotemark 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */
+#define XK_leftdoublequotemark 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */
+#define XK_rightdoublequotemark 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */
+#define XK_prescription 0x0ad4 /* U+211E PRESCRIPTION TAKE */
+#define XK_minutes 0x0ad6 /* U+2032 PRIME */
+#define XK_seconds 0x0ad7 /* U+2033 DOUBLE PRIME */
+#define XK_latincross 0x0ad9 /* U+271D LATIN CROSS */
+#define XK_hexagram 0x0ada
+#define XK_filledrectbullet 0x0adb /*(U+25AC BLACK RECTANGLE)*/
+#define XK_filledlefttribullet 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/
+#define XK_filledrighttribullet 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/
+#define XK_emfilledcircle 0x0ade /*(U+25CF BLACK CIRCLE)*/
+#define XK_emfilledrect 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/
+#define XK_enopencircbullet 0x0ae0 /*(U+25E6 WHITE BULLET)*/
+#define XK_enopensquarebullet 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/
+#define XK_openrectbullet 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/
+#define XK_opentribulletup 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/
+#define XK_opentribulletdown 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/
+#define XK_openstar 0x0ae5 /*(U+2606 WHITE STAR)*/
+#define XK_enfilledcircbullet 0x0ae6 /*(U+2022 BULLET)*/
+#define XK_enfilledsqbullet 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/
+#define XK_filledtribulletup 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/
+#define XK_filledtribulletdown 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/
+#define XK_leftpointer 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/
+#define XK_rightpointer 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/
+#define XK_club 0x0aec /* U+2663 BLACK CLUB SUIT */
+#define XK_diamond 0x0aed /* U+2666 BLACK DIAMOND SUIT */
+#define XK_heart 0x0aee /* U+2665 BLACK HEART SUIT */
+#define XK_maltesecross 0x0af0 /* U+2720 MALTESE CROSS */
+#define XK_dagger 0x0af1 /* U+2020 DAGGER */
+#define XK_doubledagger 0x0af2 /* U+2021 DOUBLE DAGGER */
+#define XK_checkmark 0x0af3 /* U+2713 CHECK MARK */
+#define XK_ballotcross 0x0af4 /* U+2717 BALLOT X */
+#define XK_musicalsharp 0x0af5 /* U+266F MUSIC SHARP SIGN */
+#define XK_musicalflat 0x0af6 /* U+266D MUSIC FLAT SIGN */
+#define XK_malesymbol 0x0af7 /* U+2642 MALE SIGN */
+#define XK_femalesymbol 0x0af8 /* U+2640 FEMALE SIGN */
+#define XK_telephone 0x0af9 /* U+260E BLACK TELEPHONE */
+#define XK_telephonerecorder 0x0afa /* U+2315 TELEPHONE RECORDER */
+#define XK_phonographcopyright 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */
+#define XK_caret 0x0afc /* U+2038 CARET */
+#define XK_singlelowquotemark 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */
+#define XK_doublelowquotemark 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */
+#define XK_cursor 0x0aff
+#endif /* XK_PUBLISHING */
+
+/*
+ * APL
+ * Byte 3 = 0x0b
+ */
+
+#ifdef XK_APL
+#define XK_leftcaret 0x0ba3 /*(U+003C LESS-THAN SIGN)*/
+#define XK_rightcaret 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/
+#define XK_downcaret 0x0ba8 /*(U+2228 LOGICAL OR)*/
+#define XK_upcaret 0x0ba9 /*(U+2227 LOGICAL AND)*/
+#define XK_overbar 0x0bc0 /*(U+00AF MACRON)*/
+#define XK_downtack 0x0bc2 /* U+22A4 DOWN TACK */
+#define XK_upshoe 0x0bc3 /*(U+2229 INTERSECTION)*/
+#define XK_downstile 0x0bc4 /* U+230A LEFT FLOOR */
+#define XK_underbar 0x0bc6 /*(U+005F LOW LINE)*/
+#define XK_jot 0x0bca /* U+2218 RING OPERATOR */
+#define XK_quad 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */
+#define XK_uptack 0x0bce /* U+22A5 UP TACK */
+#define XK_circle 0x0bcf /* U+25CB WHITE CIRCLE */
+#define XK_upstile 0x0bd3 /* U+2308 LEFT CEILING */
+#define XK_downshoe 0x0bd6 /*(U+222A UNION)*/
+#define XK_rightshoe 0x0bd8 /*(U+2283 SUPERSET OF)*/
+#define XK_leftshoe 0x0bda /*(U+2282 SUBSET OF)*/
+#define XK_lefttack 0x0bdc /* U+22A3 LEFT TACK */
+#define XK_righttack 0x0bfc /* U+22A2 RIGHT TACK */
+#endif /* XK_APL */
+
+/*
+ * Hebrew
+ * Byte 3 = 0x0c
+ */
+
+#ifdef XK_HEBREW
+#define XK_hebrew_doublelowline 0x0cdf /* U+2017 DOUBLE LOW LINE */
+#define XK_hebrew_aleph 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */
+#define XK_hebrew_bet 0x0ce1 /* U+05D1 HEBREW LETTER BET */
+#define XK_hebrew_beth 0x0ce1 /* deprecated */
+#define XK_hebrew_gimel 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */
+#define XK_hebrew_gimmel 0x0ce2 /* deprecated */
+#define XK_hebrew_dalet 0x0ce3 /* U+05D3 HEBREW LETTER DALET */
+#define XK_hebrew_daleth 0x0ce3 /* deprecated */
+#define XK_hebrew_he 0x0ce4 /* U+05D4 HEBREW LETTER HE */
+#define XK_hebrew_waw 0x0ce5 /* U+05D5 HEBREW LETTER VAV */
+#define XK_hebrew_zain 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */
+#define XK_hebrew_zayin 0x0ce6 /* deprecated */
+#define XK_hebrew_chet 0x0ce7 /* U+05D7 HEBREW LETTER HET */
+#define XK_hebrew_het 0x0ce7 /* deprecated */
+#define XK_hebrew_tet 0x0ce8 /* U+05D8 HEBREW LETTER TET */
+#define XK_hebrew_teth 0x0ce8 /* deprecated */
+#define XK_hebrew_yod 0x0ce9 /* U+05D9 HEBREW LETTER YOD */
+#define XK_hebrew_finalkaph 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */
+#define XK_hebrew_kaph 0x0ceb /* U+05DB HEBREW LETTER KAF */
+#define XK_hebrew_lamed 0x0cec /* U+05DC HEBREW LETTER LAMED */
+#define XK_hebrew_finalmem 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */
+#define XK_hebrew_mem 0x0cee /* U+05DE HEBREW LETTER MEM */
+#define XK_hebrew_finalnun 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */
+#define XK_hebrew_nun 0x0cf0 /* U+05E0 HEBREW LETTER NUN */
+#define XK_hebrew_samech 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */
+#define XK_hebrew_samekh 0x0cf1 /* deprecated */
+#define XK_hebrew_ayin 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */
+#define XK_hebrew_finalpe 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */
+#define XK_hebrew_pe 0x0cf4 /* U+05E4 HEBREW LETTER PE */
+#define XK_hebrew_finalzade 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */
+#define XK_hebrew_finalzadi 0x0cf5 /* deprecated */
+#define XK_hebrew_zade 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */
+#define XK_hebrew_zadi 0x0cf6 /* deprecated */
+#define XK_hebrew_qoph 0x0cf7 /* U+05E7 HEBREW LETTER QOF */
+#define XK_hebrew_kuf 0x0cf7 /* deprecated */
+#define XK_hebrew_resh 0x0cf8 /* U+05E8 HEBREW LETTER RESH */
+#define XK_hebrew_shin 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */
+#define XK_hebrew_taw 0x0cfa /* U+05EA HEBREW LETTER TAV */
+#define XK_hebrew_taf 0x0cfa /* deprecated */
+#define XK_Hebrew_switch 0xff7e /* Alias for mode_switch */
+#endif /* XK_HEBREW */
+
+/*
+ * Thai
+ * Byte 3 = 0x0d
+ */
+
+#ifdef XK_THAI
+#define XK_Thai_kokai 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */
+#define XK_Thai_khokhai 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */
+#define XK_Thai_khokhuat 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */
+#define XK_Thai_khokhwai 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */
+#define XK_Thai_khokhon 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */
+#define XK_Thai_khorakhang 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */
+#define XK_Thai_ngongu 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */
+#define XK_Thai_chochan 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */
+#define XK_Thai_choching 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */
+#define XK_Thai_chochang 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */
+#define XK_Thai_soso 0x0dab /* U+0E0B THAI CHARACTER SO SO */
+#define XK_Thai_chochoe 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */
+#define XK_Thai_yoying 0x0dad /* U+0E0D THAI CHARACTER YO YING */
+#define XK_Thai_dochada 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */
+#define XK_Thai_topatak 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */
+#define XK_Thai_thothan 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */
+#define XK_Thai_thonangmontho 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */
+#define XK_Thai_thophuthao 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */
+#define XK_Thai_nonen 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */
+#define XK_Thai_dodek 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */
+#define XK_Thai_totao 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */
+#define XK_Thai_thothung 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */
+#define XK_Thai_thothahan 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */
+#define XK_Thai_thothong 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */
+#define XK_Thai_nonu 0x0db9 /* U+0E19 THAI CHARACTER NO NU */
+#define XK_Thai_bobaimai 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */
+#define XK_Thai_popla 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */
+#define XK_Thai_phophung 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */
+#define XK_Thai_fofa 0x0dbd /* U+0E1D THAI CHARACTER FO FA */
+#define XK_Thai_phophan 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */
+#define XK_Thai_fofan 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */
+#define XK_Thai_phosamphao 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */
+#define XK_Thai_moma 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */
+#define XK_Thai_yoyak 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */
+#define XK_Thai_rorua 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */
+#define XK_Thai_ru 0x0dc4 /* U+0E24 THAI CHARACTER RU */
+#define XK_Thai_loling 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */
+#define XK_Thai_lu 0x0dc6 /* U+0E26 THAI CHARACTER LU */
+#define XK_Thai_wowaen 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */
+#define XK_Thai_sosala 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */
+#define XK_Thai_sorusi 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */
+#define XK_Thai_sosua 0x0dca /* U+0E2A THAI CHARACTER SO SUA */
+#define XK_Thai_hohip 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */
+#define XK_Thai_lochula 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */
+#define XK_Thai_oang 0x0dcd /* U+0E2D THAI CHARACTER O ANG */
+#define XK_Thai_honokhuk 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */
+#define XK_Thai_paiyannoi 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */
+#define XK_Thai_saraa 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */
+#define XK_Thai_maihanakat 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */
+#define XK_Thai_saraaa 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */
+#define XK_Thai_saraam 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */
+#define XK_Thai_sarai 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */
+#define XK_Thai_saraii 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */
+#define XK_Thai_saraue 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */
+#define XK_Thai_sarauee 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */
+#define XK_Thai_sarau 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */
+#define XK_Thai_sarauu 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */
+#define XK_Thai_phinthu 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */
+#define XK_Thai_maihanakat_maitho 0x0dde
+#define XK_Thai_baht 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */
+#define XK_Thai_sarae 0x0de0 /* U+0E40 THAI CHARACTER SARA E */
+#define XK_Thai_saraae 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */
+#define XK_Thai_sarao 0x0de2 /* U+0E42 THAI CHARACTER SARA O */
+#define XK_Thai_saraaimaimuan 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */
+#define XK_Thai_saraaimaimalai 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */
+#define XK_Thai_lakkhangyao 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */
+#define XK_Thai_maiyamok 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */
+#define XK_Thai_maitaikhu 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */
+#define XK_Thai_maiek 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */
+#define XK_Thai_maitho 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */
+#define XK_Thai_maitri 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */
+#define XK_Thai_maichattawa 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */
+#define XK_Thai_thanthakhat 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */
+#define XK_Thai_nikhahit 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */
+#define XK_Thai_leksun 0x0df0 /* U+0E50 THAI DIGIT ZERO */
+#define XK_Thai_leknung 0x0df1 /* U+0E51 THAI DIGIT ONE */
+#define XK_Thai_leksong 0x0df2 /* U+0E52 THAI DIGIT TWO */
+#define XK_Thai_leksam 0x0df3 /* U+0E53 THAI DIGIT THREE */
+#define XK_Thai_leksi 0x0df4 /* U+0E54 THAI DIGIT FOUR */
+#define XK_Thai_lekha 0x0df5 /* U+0E55 THAI DIGIT FIVE */
+#define XK_Thai_lekhok 0x0df6 /* U+0E56 THAI DIGIT SIX */
+#define XK_Thai_lekchet 0x0df7 /* U+0E57 THAI DIGIT SEVEN */
+#define XK_Thai_lekpaet 0x0df8 /* U+0E58 THAI DIGIT EIGHT */
+#define XK_Thai_lekkao 0x0df9 /* U+0E59 THAI DIGIT NINE */
+#endif /* XK_THAI */
+
+/*
+ * Korean
+ * Byte 3 = 0x0e
+ */
+
+#ifdef XK_KOREAN
+
+#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */
+#define XK_Hangul_Start 0xff32 /* Hangul start */
+#define XK_Hangul_End 0xff33 /* Hangul end, English start */
+#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */
+#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */
+#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */
+#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */
+#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */
+#define XK_Hangul_Banja 0xff39 /* Banja mode */
+#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */
+#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */
+#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */
+#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */
+#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */
+#define XK_Hangul_Special 0xff3f /* Special symbols */
+#define XK_Hangul_switch 0xff7e /* Alias for mode_switch */
+
+/* Hangul Consonant Characters */
+#define XK_Hangul_Kiyeog 0x0ea1
+#define XK_Hangul_SsangKiyeog 0x0ea2
+#define XK_Hangul_KiyeogSios 0x0ea3
+#define XK_Hangul_Nieun 0x0ea4
+#define XK_Hangul_NieunJieuj 0x0ea5
+#define XK_Hangul_NieunHieuh 0x0ea6
+#define XK_Hangul_Dikeud 0x0ea7
+#define XK_Hangul_SsangDikeud 0x0ea8
+#define XK_Hangul_Rieul 0x0ea9
+#define XK_Hangul_RieulKiyeog 0x0eaa
+#define XK_Hangul_RieulMieum 0x0eab
+#define XK_Hangul_RieulPieub 0x0eac
+#define XK_Hangul_RieulSios 0x0ead
+#define XK_Hangul_RieulTieut 0x0eae
+#define XK_Hangul_RieulPhieuf 0x0eaf
+#define XK_Hangul_RieulHieuh 0x0eb0
+#define XK_Hangul_Mieum 0x0eb1
+#define XK_Hangul_Pieub 0x0eb2
+#define XK_Hangul_SsangPieub 0x0eb3
+#define XK_Hangul_PieubSios 0x0eb4
+#define XK_Hangul_Sios 0x0eb5
+#define XK_Hangul_SsangSios 0x0eb6
+#define XK_Hangul_Ieung 0x0eb7
+#define XK_Hangul_Jieuj 0x0eb8
+#define XK_Hangul_SsangJieuj 0x0eb9
+#define XK_Hangul_Cieuc 0x0eba
+#define XK_Hangul_Khieuq 0x0ebb
+#define XK_Hangul_Tieut 0x0ebc
+#define XK_Hangul_Phieuf 0x0ebd
+#define XK_Hangul_Hieuh 0x0ebe
+
+/* Hangul Vowel Characters */
+#define XK_Hangul_A 0x0ebf
+#define XK_Hangul_AE 0x0ec0
+#define XK_Hangul_YA 0x0ec1
+#define XK_Hangul_YAE 0x0ec2
+#define XK_Hangul_EO 0x0ec3
+#define XK_Hangul_E 0x0ec4
+#define XK_Hangul_YEO 0x0ec5
+#define XK_Hangul_YE 0x0ec6
+#define XK_Hangul_O 0x0ec7
+#define XK_Hangul_WA 0x0ec8
+#define XK_Hangul_WAE 0x0ec9
+#define XK_Hangul_OE 0x0eca
+#define XK_Hangul_YO 0x0ecb
+#define XK_Hangul_U 0x0ecc
+#define XK_Hangul_WEO 0x0ecd
+#define XK_Hangul_WE 0x0ece
+#define XK_Hangul_WI 0x0ecf
+#define XK_Hangul_YU 0x0ed0
+#define XK_Hangul_EU 0x0ed1
+#define XK_Hangul_YI 0x0ed2
+#define XK_Hangul_I 0x0ed3
+
+/* Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_Kiyeog 0x0ed4
+#define XK_Hangul_J_SsangKiyeog 0x0ed5
+#define XK_Hangul_J_KiyeogSios 0x0ed6
+#define XK_Hangul_J_Nieun 0x0ed7
+#define XK_Hangul_J_NieunJieuj 0x0ed8
+#define XK_Hangul_J_NieunHieuh 0x0ed9
+#define XK_Hangul_J_Dikeud 0x0eda
+#define XK_Hangul_J_Rieul 0x0edb
+#define XK_Hangul_J_RieulKiyeog 0x0edc
+#define XK_Hangul_J_RieulMieum 0x0edd
+#define XK_Hangul_J_RieulPieub 0x0ede
+#define XK_Hangul_J_RieulSios 0x0edf
+#define XK_Hangul_J_RieulTieut 0x0ee0
+#define XK_Hangul_J_RieulPhieuf 0x0ee1
+#define XK_Hangul_J_RieulHieuh 0x0ee2
+#define XK_Hangul_J_Mieum 0x0ee3
+#define XK_Hangul_J_Pieub 0x0ee4
+#define XK_Hangul_J_PieubSios 0x0ee5
+#define XK_Hangul_J_Sios 0x0ee6
+#define XK_Hangul_J_SsangSios 0x0ee7
+#define XK_Hangul_J_Ieung 0x0ee8
+#define XK_Hangul_J_Jieuj 0x0ee9
+#define XK_Hangul_J_Cieuc 0x0eea
+#define XK_Hangul_J_Khieuq 0x0eeb
+#define XK_Hangul_J_Tieut 0x0eec
+#define XK_Hangul_J_Phieuf 0x0eed
+#define XK_Hangul_J_Hieuh 0x0eee
+
+/* Ancient Hangul Consonant Characters */
+#define XK_Hangul_RieulYeorinHieuh 0x0eef
+#define XK_Hangul_SunkyeongeumMieum 0x0ef0
+#define XK_Hangul_SunkyeongeumPieub 0x0ef1
+#define XK_Hangul_PanSios 0x0ef2
+#define XK_Hangul_KkogjiDalrinIeung 0x0ef3
+#define XK_Hangul_SunkyeongeumPhieuf 0x0ef4
+#define XK_Hangul_YeorinHieuh 0x0ef5
+
+/* Ancient Hangul Vowel Characters */
+#define XK_Hangul_AraeA 0x0ef6
+#define XK_Hangul_AraeAE 0x0ef7
+
+/* Ancient Hangul syllable-final (JongSeong) Characters */
+#define XK_Hangul_J_PanSios 0x0ef8
+#define XK_Hangul_J_KkogjiDalrinIeung 0x0ef9
+#define XK_Hangul_J_YeorinHieuh 0x0efa
+
+/* Korean currency symbol */
+#define XK_Korean_Won 0x0eff /*(U+20A9 WON SIGN)*/
+
+#endif /* XK_KOREAN */
+
+/*
+ * Armenian
+ */
+
+#ifdef XK_ARMENIAN
+#define XK_Armenian_ligature_ew 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */
+#define XK_Armenian_full_stop 0x1000589 /* U+0589 ARMENIAN FULL STOP */
+#define XK_Armenian_verjaket 0x1000589 /* U+0589 ARMENIAN FULL STOP */
+#define XK_Armenian_separation_mark 0x100055d /* U+055D ARMENIAN COMMA */
+#define XK_Armenian_but 0x100055d /* U+055D ARMENIAN COMMA */
+#define XK_Armenian_hyphen 0x100058a /* U+058A ARMENIAN HYPHEN */
+#define XK_Armenian_yentamna 0x100058a /* U+058A ARMENIAN HYPHEN */
+#define XK_Armenian_exclam 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */
+#define XK_Armenian_amanak 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */
+#define XK_Armenian_accent 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */
+#define XK_Armenian_shesht 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */
+#define XK_Armenian_question 0x100055e /* U+055E ARMENIAN QUESTION MARK */
+#define XK_Armenian_paruyk 0x100055e /* U+055E ARMENIAN QUESTION MARK */
+#define XK_Armenian_AYB 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */
+#define XK_Armenian_ayb 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */
+#define XK_Armenian_BEN 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */
+#define XK_Armenian_ben 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */
+#define XK_Armenian_GIM 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */
+#define XK_Armenian_gim 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */
+#define XK_Armenian_DA 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */
+#define XK_Armenian_da 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */
+#define XK_Armenian_YECH 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */
+#define XK_Armenian_yech 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */
+#define XK_Armenian_ZA 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */
+#define XK_Armenian_za 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */
+#define XK_Armenian_E 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */
+#define XK_Armenian_e 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */
+#define XK_Armenian_AT 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */
+#define XK_Armenian_at 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */
+#define XK_Armenian_TO 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */
+#define XK_Armenian_to 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */
+#define XK_Armenian_ZHE 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */
+#define XK_Armenian_zhe 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */
+#define XK_Armenian_INI 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */
+#define XK_Armenian_ini 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */
+#define XK_Armenian_LYUN 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */
+#define XK_Armenian_lyun 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */
+#define XK_Armenian_KHE 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */
+#define XK_Armenian_khe 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */
+#define XK_Armenian_TSA 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */
+#define XK_Armenian_tsa 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */
+#define XK_Armenian_KEN 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */
+#define XK_Armenian_ken 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */
+#define XK_Armenian_HO 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */
+#define XK_Armenian_ho 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */
+#define XK_Armenian_DZA 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */
+#define XK_Armenian_dza 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */
+#define XK_Armenian_GHAT 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */
+#define XK_Armenian_ghat 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */
+#define XK_Armenian_TCHE 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */
+#define XK_Armenian_tche 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */
+#define XK_Armenian_MEN 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */
+#define XK_Armenian_men 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */
+#define XK_Armenian_HI 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */
+#define XK_Armenian_hi 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */
+#define XK_Armenian_NU 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */
+#define XK_Armenian_nu 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */
+#define XK_Armenian_SHA 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */
+#define XK_Armenian_sha 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */
+#define XK_Armenian_VO 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */
+#define XK_Armenian_vo 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */
+#define XK_Armenian_CHA 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */
+#define XK_Armenian_cha 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */
+#define XK_Armenian_PE 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */
+#define XK_Armenian_pe 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */
+#define XK_Armenian_JE 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */
+#define XK_Armenian_je 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */
+#define XK_Armenian_RA 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */
+#define XK_Armenian_ra 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */
+#define XK_Armenian_SE 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */
+#define XK_Armenian_se 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */
+#define XK_Armenian_VEV 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */
+#define XK_Armenian_vev 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */
+#define XK_Armenian_TYUN 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */
+#define XK_Armenian_tyun 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */
+#define XK_Armenian_RE 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */
+#define XK_Armenian_re 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */
+#define XK_Armenian_TSO 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */
+#define XK_Armenian_tso 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */
+#define XK_Armenian_VYUN 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */
+#define XK_Armenian_vyun 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */
+#define XK_Armenian_PYUR 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */
+#define XK_Armenian_pyur 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */
+#define XK_Armenian_KE 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */
+#define XK_Armenian_ke 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */
+#define XK_Armenian_O 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */
+#define XK_Armenian_o 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */
+#define XK_Armenian_FE 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */
+#define XK_Armenian_fe 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */
+#define XK_Armenian_apostrophe 0x100055a /* U+055A ARMENIAN APOSTROPHE */
+#endif /* XK_ARMENIAN */
+
+/*
+ * Georgian
+ */
+
+#ifdef XK_GEORGIAN
+#define XK_Georgian_an 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */
+#define XK_Georgian_ban 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */
+#define XK_Georgian_gan 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */
+#define XK_Georgian_don 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */
+#define XK_Georgian_en 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */
+#define XK_Georgian_vin 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */
+#define XK_Georgian_zen 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */
+#define XK_Georgian_tan 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */
+#define XK_Georgian_in 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */
+#define XK_Georgian_kan 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */
+#define XK_Georgian_las 0x10010da /* U+10DA GEORGIAN LETTER LAS */
+#define XK_Georgian_man 0x10010db /* U+10DB GEORGIAN LETTER MAN */
+#define XK_Georgian_nar 0x10010dc /* U+10DC GEORGIAN LETTER NAR */
+#define XK_Georgian_on 0x10010dd /* U+10DD GEORGIAN LETTER ON */
+#define XK_Georgian_par 0x10010de /* U+10DE GEORGIAN LETTER PAR */
+#define XK_Georgian_zhar 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */
+#define XK_Georgian_rae 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */
+#define XK_Georgian_san 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */
+#define XK_Georgian_tar 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */
+#define XK_Georgian_un 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */
+#define XK_Georgian_phar 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */
+#define XK_Georgian_khar 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */
+#define XK_Georgian_ghan 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */
+#define XK_Georgian_qar 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */
+#define XK_Georgian_shin 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */
+#define XK_Georgian_chin 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */
+#define XK_Georgian_can 0x10010ea /* U+10EA GEORGIAN LETTER CAN */
+#define XK_Georgian_jil 0x10010eb /* U+10EB GEORGIAN LETTER JIL */
+#define XK_Georgian_cil 0x10010ec /* U+10EC GEORGIAN LETTER CIL */
+#define XK_Georgian_char 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */
+#define XK_Georgian_xan 0x10010ee /* U+10EE GEORGIAN LETTER XAN */
+#define XK_Georgian_jhan 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */
+#define XK_Georgian_hae 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */
+#define XK_Georgian_he 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */
+#define XK_Georgian_hie 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */
+#define XK_Georgian_we 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */
+#define XK_Georgian_har 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */
+#define XK_Georgian_hoe 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */
+#define XK_Georgian_fi 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */
+#endif /* XK_GEORGIAN */
+
+/*
+ * Azeri (and other Turkic or Caucasian languages)
+ */
+
+#ifdef XK_CAUCASUS
+/* latin */
+#define XK_Xabovedot 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */
+#define XK_Ibreve 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */
+#define XK_Zstroke 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */
+#define XK_Gcaron 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */
+#define XK_Ocaron 0x10001d1 /* U+01D2 LATIN CAPITAL LETTER O WITH CARON */
+#define XK_Obarred 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */
+#define XK_xabovedot 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */
+#define XK_ibreve 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */
+#define XK_zstroke 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */
+#define XK_gcaron 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */
+#define XK_ocaron 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */
+#define XK_obarred 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */
+#define XK_SCHWA 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */
+#define XK_schwa 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */
+/* those are not really Caucasus */
+/* For Inupiak */
+#define XK_Lbelowdot 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */
+#define XK_lbelowdot 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */
+#endif /* XK_CAUCASUS */
+
+/*
+ * Vietnamese
+ */
+
+#ifdef XK_VIETNAMESE
+#define XK_Abelowdot 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */
+#define XK_abelowdot 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */
+#define XK_Ahook 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */
+#define XK_ahook 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */
+#define XK_Acircumflexacute 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */
+#define XK_acircumflexacute 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */
+#define XK_Acircumflexgrave 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */
+#define XK_acircumflexgrave 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */
+#define XK_Acircumflexhook 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_acircumflexhook 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_Acircumflextilde 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */
+#define XK_acircumflextilde 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */
+#define XK_Acircumflexbelowdot 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_acircumflexbelowdot 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_Abreveacute 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */
+#define XK_abreveacute 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */
+#define XK_Abrevegrave 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */
+#define XK_abrevegrave 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */
+#define XK_Abrevehook 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */
+#define XK_abrevehook 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */
+#define XK_Abrevetilde 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */
+#define XK_abrevetilde 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */
+#define XK_Abrevebelowdot 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */
+#define XK_abrevebelowdot 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */
+#define XK_Ebelowdot 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */
+#define XK_ebelowdot 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */
+#define XK_Ehook 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */
+#define XK_ehook 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */
+#define XK_Etilde 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */
+#define XK_etilde 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */
+#define XK_Ecircumflexacute 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */
+#define XK_ecircumflexacute 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */
+#define XK_Ecircumflexgrave 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */
+#define XK_ecircumflexgrave 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */
+#define XK_Ecircumflexhook 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_ecircumflexhook 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_Ecircumflextilde 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */
+#define XK_ecircumflextilde 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */
+#define XK_Ecircumflexbelowdot 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_ecircumflexbelowdot 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_Ihook 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */
+#define XK_ihook 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */
+#define XK_Ibelowdot 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */
+#define XK_ibelowdot 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */
+#define XK_Obelowdot 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */
+#define XK_obelowdot 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */
+#define XK_Ohook 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */
+#define XK_ohook 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */
+#define XK_Ocircumflexacute 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */
+#define XK_ocircumflexacute 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */
+#define XK_Ocircumflexgrave 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */
+#define XK_ocircumflexgrave 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */
+#define XK_Ocircumflexhook 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_ocircumflexhook 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */
+#define XK_Ocircumflextilde 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */
+#define XK_ocircumflextilde 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */
+#define XK_Ocircumflexbelowdot 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_ocircumflexbelowdot 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */
+#define XK_Ohornacute 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */
+#define XK_ohornacute 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */
+#define XK_Ohorngrave 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */
+#define XK_ohorngrave 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */
+#define XK_Ohornhook 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */
+#define XK_ohornhook 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */
+#define XK_Ohorntilde 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */
+#define XK_ohorntilde 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */
+#define XK_Ohornbelowdot 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */
+#define XK_ohornbelowdot 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */
+#define XK_Ubelowdot 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */
+#define XK_ubelowdot 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */
+#define XK_Uhook 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */
+#define XK_uhook 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */
+#define XK_Uhornacute 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */
+#define XK_uhornacute 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */
+#define XK_Uhorngrave 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */
+#define XK_uhorngrave 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */
+#define XK_Uhornhook 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */
+#define XK_uhornhook 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */
+#define XK_Uhorntilde 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */
+#define XK_uhorntilde 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */
+#define XK_Uhornbelowdot 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */
+#define XK_uhornbelowdot 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */
+#define XK_Ybelowdot 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */
+#define XK_ybelowdot 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */
+#define XK_Yhook 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */
+#define XK_yhook 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */
+#define XK_Ytilde 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */
+#define XK_ytilde 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */
+#define XK_Ohorn 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */
+#define XK_ohorn 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */
+#define XK_Uhorn 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */
+#define XK_uhorn 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */
+
+#endif /* XK_VIETNAMESE */
+
+#ifdef XK_CURRENCY
+#define XK_EcuSign 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */
+#define XK_ColonSign 0x10020a1 /* U+20A1 COLON SIGN */
+#define XK_CruzeiroSign 0x10020a2 /* U+20A2 CRUZEIRO SIGN */
+#define XK_FFrancSign 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */
+#define XK_LiraSign 0x10020a4 /* U+20A4 LIRA SIGN */
+#define XK_MillSign 0x10020a5 /* U+20A5 MILL SIGN */
+#define XK_NairaSign 0x10020a6 /* U+20A6 NAIRA SIGN */
+#define XK_PesetaSign 0x10020a7 /* U+20A7 PESETA SIGN */
+#define XK_RupeeSign 0x10020a8 /* U+20A8 RUPEE SIGN */
+#define XK_WonSign 0x10020a9 /* U+20A9 WON SIGN */
+#define XK_NewSheqelSign 0x10020aa /* U+20AA NEW SHEQEL SIGN */
+#define XK_DongSign 0x10020ab /* U+20AB DONG SIGN */
+#define XK_EuroSign 0x20ac /* U+20AC EURO SIGN */
+#endif /* XK_CURRENCY */
+
+#ifdef XK_MATHEMATICAL
+/* one, two and three are defined above. */
+#define XK_zerosuperior 0x1002070 /* U+2070 SUPERSCRIPT ZERO */
+#define XK_foursuperior 0x1002074 /* U+2074 SUPERSCRIPT FOUR */
+#define XK_fivesuperior 0x1002075 /* U+2075 SUPERSCRIPT FIVE */
+#define XK_sixsuperior 0x1002076 /* U+2076 SUPERSCRIPT SIX */
+#define XK_sevensuperior 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */
+#define XK_eightsuperior 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */
+#define XK_ninesuperior 0x1002079 /* U+2079 SUPERSCRIPT NINE */
+#define XK_zerosubscript 0x1002080 /* U+2080 SUBSCRIPT ZERO */
+#define XK_onesubscript 0x1002081 /* U+2081 SUBSCRIPT ONE */
+#define XK_twosubscript 0x1002082 /* U+2082 SUBSCRIPT TWO */
+#define XK_threesubscript 0x1002083 /* U+2083 SUBSCRIPT THREE */
+#define XK_foursubscript 0x1002084 /* U+2084 SUBSCRIPT FOUR */
+#define XK_fivesubscript 0x1002085 /* U+2085 SUBSCRIPT FIVE */
+#define XK_sixsubscript 0x1002086 /* U+2086 SUBSCRIPT SIX */
+#define XK_sevensubscript 0x1002087 /* U+2087 SUBSCRIPT SEVEN */
+#define XK_eightsubscript 0x1002088 /* U+2088 SUBSCRIPT EIGHT */
+#define XK_ninesubscript 0x1002089 /* U+2089 SUBSCRIPT NINE */
+#define XK_partdifferential 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */
+#define XK_emptyset 0x1002205 /* U+2205 NULL SET */
+#define XK_elementof 0x1002208 /* U+2208 ELEMENT OF */
+#define XK_notelementof 0x1002209 /* U+2209 NOT AN ELEMENT OF */
+#define XK_containsas 0x100220B /* U+220B CONTAINS AS MEMBER */
+#define XK_squareroot 0x100221A /* U+221A SQUARE ROOT */
+#define XK_cuberoot 0x100221B /* U+221B CUBE ROOT */
+#define XK_fourthroot 0x100221C /* U+221C FOURTH ROOT */
+#define XK_dintegral 0x100222C /* U+222C DOUBLE INTEGRAL */
+#define XK_tintegral 0x100222D /* U+222D TRIPLE INTEGRAL */
+#define XK_because 0x1002235 /* U+2235 BECAUSE */
+#define XK_approxeq 0x1002248 /* U+2245 ALMOST EQUAL TO */
+#define XK_notapproxeq 0x1002247 /* U+2247 NOT ALMOST EQUAL TO */
+#define XK_notidentical 0x1002262 /* U+2262 NOT IDENTICAL TO */
+#define XK_stricteq 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */
+#endif /* XK_MATHEMATICAL */
+
+#ifdef XK_BRAILLE
+#define XK_braille_dot_1 0xfff1
+#define XK_braille_dot_2 0xfff2
+#define XK_braille_dot_3 0xfff3
+#define XK_braille_dot_4 0xfff4
+#define XK_braille_dot_5 0xfff5
+#define XK_braille_dot_6 0xfff6
+#define XK_braille_dot_7 0xfff7
+#define XK_braille_dot_8 0xfff8
+#define XK_braille_dot_9 0xfff9
+#define XK_braille_dot_10 0xfffa
+#define XK_braille_blank 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */
+#define XK_braille_dots_1 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */
+#define XK_braille_dots_2 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */
+#define XK_braille_dots_12 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */
+#define XK_braille_dots_3 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */
+#define XK_braille_dots_13 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */
+#define XK_braille_dots_23 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */
+#define XK_braille_dots_123 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */
+#define XK_braille_dots_4 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */
+#define XK_braille_dots_14 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */
+#define XK_braille_dots_24 0x100280a /* U+280a BRAILLE PATTERN DOTS-24 */
+#define XK_braille_dots_124 0x100280b /* U+280b BRAILLE PATTERN DOTS-124 */
+#define XK_braille_dots_34 0x100280c /* U+280c BRAILLE PATTERN DOTS-34 */
+#define XK_braille_dots_134 0x100280d /* U+280d BRAILLE PATTERN DOTS-134 */
+#define XK_braille_dots_234 0x100280e /* U+280e BRAILLE PATTERN DOTS-234 */
+#define XK_braille_dots_1234 0x100280f /* U+280f BRAILLE PATTERN DOTS-1234 */
+#define XK_braille_dots_5 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */
+#define XK_braille_dots_15 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */
+#define XK_braille_dots_25 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */
+#define XK_braille_dots_125 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */
+#define XK_braille_dots_35 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */
+#define XK_braille_dots_135 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */
+#define XK_braille_dots_235 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */
+#define XK_braille_dots_1235 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */
+#define XK_braille_dots_45 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */
+#define XK_braille_dots_145 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */
+#define XK_braille_dots_245 0x100281a /* U+281a BRAILLE PATTERN DOTS-245 */
+#define XK_braille_dots_1245 0x100281b /* U+281b BRAILLE PATTERN DOTS-1245 */
+#define XK_braille_dots_345 0x100281c /* U+281c BRAILLE PATTERN DOTS-345 */
+#define XK_braille_dots_1345 0x100281d /* U+281d BRAILLE PATTERN DOTS-1345 */
+#define XK_braille_dots_2345 0x100281e /* U+281e BRAILLE PATTERN DOTS-2345 */
+#define XK_braille_dots_12345 0x100281f /* U+281f BRAILLE PATTERN DOTS-12345 */
+#define XK_braille_dots_6 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */
+#define XK_braille_dots_16 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */
+#define XK_braille_dots_26 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */
+#define XK_braille_dots_126 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */
+#define XK_braille_dots_36 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */
+#define XK_braille_dots_136 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */
+#define XK_braille_dots_236 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */
+#define XK_braille_dots_1236 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */
+#define XK_braille_dots_46 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */
+#define XK_braille_dots_146 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */
+#define XK_braille_dots_246 0x100282a /* U+282a BRAILLE PATTERN DOTS-246 */
+#define XK_braille_dots_1246 0x100282b /* U+282b BRAILLE PATTERN DOTS-1246 */
+#define XK_braille_dots_346 0x100282c /* U+282c BRAILLE PATTERN DOTS-346 */
+#define XK_braille_dots_1346 0x100282d /* U+282d BRAILLE PATTERN DOTS-1346 */
+#define XK_braille_dots_2346 0x100282e /* U+282e BRAILLE PATTERN DOTS-2346 */
+#define XK_braille_dots_12346 0x100282f /* U+282f BRAILLE PATTERN DOTS-12346 */
+#define XK_braille_dots_56 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */
+#define XK_braille_dots_156 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */
+#define XK_braille_dots_256 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */
+#define XK_braille_dots_1256 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */
+#define XK_braille_dots_356 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */
+#define XK_braille_dots_1356 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */
+#define XK_braille_dots_2356 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */
+#define XK_braille_dots_12356 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */
+#define XK_braille_dots_456 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */
+#define XK_braille_dots_1456 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */
+#define XK_braille_dots_2456 0x100283a /* U+283a BRAILLE PATTERN DOTS-2456 */
+#define XK_braille_dots_12456 0x100283b /* U+283b BRAILLE PATTERN DOTS-12456 */
+#define XK_braille_dots_3456 0x100283c /* U+283c BRAILLE PATTERN DOTS-3456 */
+#define XK_braille_dots_13456 0x100283d /* U+283d BRAILLE PATTERN DOTS-13456 */
+#define XK_braille_dots_23456 0x100283e /* U+283e BRAILLE PATTERN DOTS-23456 */
+#define XK_braille_dots_123456 0x100283f /* U+283f BRAILLE PATTERN DOTS-123456 */
+#define XK_braille_dots_7 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */
+#define XK_braille_dots_17 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */
+#define XK_braille_dots_27 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */
+#define XK_braille_dots_127 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */
+#define XK_braille_dots_37 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */
+#define XK_braille_dots_137 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */
+#define XK_braille_dots_237 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */
+#define XK_braille_dots_1237 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */
+#define XK_braille_dots_47 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */
+#define XK_braille_dots_147 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */
+#define XK_braille_dots_247 0x100284a /* U+284a BRAILLE PATTERN DOTS-247 */
+#define XK_braille_dots_1247 0x100284b /* U+284b BRAILLE PATTERN DOTS-1247 */
+#define XK_braille_dots_347 0x100284c /* U+284c BRAILLE PATTERN DOTS-347 */
+#define XK_braille_dots_1347 0x100284d /* U+284d BRAILLE PATTERN DOTS-1347 */
+#define XK_braille_dots_2347 0x100284e /* U+284e BRAILLE PATTERN DOTS-2347 */
+#define XK_braille_dots_12347 0x100284f /* U+284f BRAILLE PATTERN DOTS-12347 */
+#define XK_braille_dots_57 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */
+#define XK_braille_dots_157 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */
+#define XK_braille_dots_257 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */
+#define XK_braille_dots_1257 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */
+#define XK_braille_dots_357 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */
+#define XK_braille_dots_1357 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */
+#define XK_braille_dots_2357 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */
+#define XK_braille_dots_12357 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */
+#define XK_braille_dots_457 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */
+#define XK_braille_dots_1457 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */
+#define XK_braille_dots_2457 0x100285a /* U+285a BRAILLE PATTERN DOTS-2457 */
+#define XK_braille_dots_12457 0x100285b /* U+285b BRAILLE PATTERN DOTS-12457 */
+#define XK_braille_dots_3457 0x100285c /* U+285c BRAILLE PATTERN DOTS-3457 */
+#define XK_braille_dots_13457 0x100285d /* U+285d BRAILLE PATTERN DOTS-13457 */
+#define XK_braille_dots_23457 0x100285e /* U+285e BRAILLE PATTERN DOTS-23457 */
+#define XK_braille_dots_123457 0x100285f /* U+285f BRAILLE PATTERN DOTS-123457 */
+#define XK_braille_dots_67 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */
+#define XK_braille_dots_167 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */
+#define XK_braille_dots_267 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */
+#define XK_braille_dots_1267 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */
+#define XK_braille_dots_367 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */
+#define XK_braille_dots_1367 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */
+#define XK_braille_dots_2367 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */
+#define XK_braille_dots_12367 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */
+#define XK_braille_dots_467 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */
+#define XK_braille_dots_1467 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */
+#define XK_braille_dots_2467 0x100286a /* U+286a BRAILLE PATTERN DOTS-2467 */
+#define XK_braille_dots_12467 0x100286b /* U+286b BRAILLE PATTERN DOTS-12467 */
+#define XK_braille_dots_3467 0x100286c /* U+286c BRAILLE PATTERN DOTS-3467 */
+#define XK_braille_dots_13467 0x100286d /* U+286d BRAILLE PATTERN DOTS-13467 */
+#define XK_braille_dots_23467 0x100286e /* U+286e BRAILLE PATTERN DOTS-23467 */
+#define XK_braille_dots_123467 0x100286f /* U+286f BRAILLE PATTERN DOTS-123467 */
+#define XK_braille_dots_567 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */
+#define XK_braille_dots_1567 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */
+#define XK_braille_dots_2567 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */
+#define XK_braille_dots_12567 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */
+#define XK_braille_dots_3567 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */
+#define XK_braille_dots_13567 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */
+#define XK_braille_dots_23567 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */
+#define XK_braille_dots_123567 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */
+#define XK_braille_dots_4567 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */
+#define XK_braille_dots_14567 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */
+#define XK_braille_dots_24567 0x100287a /* U+287a BRAILLE PATTERN DOTS-24567 */
+#define XK_braille_dots_124567 0x100287b /* U+287b BRAILLE PATTERN DOTS-124567 */
+#define XK_braille_dots_34567 0x100287c /* U+287c BRAILLE PATTERN DOTS-34567 */
+#define XK_braille_dots_134567 0x100287d /* U+287d BRAILLE PATTERN DOTS-134567 */
+#define XK_braille_dots_234567 0x100287e /* U+287e BRAILLE PATTERN DOTS-234567 */
+#define XK_braille_dots_1234567 0x100287f /* U+287f BRAILLE PATTERN DOTS-1234567 */
+#define XK_braille_dots_8 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */
+#define XK_braille_dots_18 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */
+#define XK_braille_dots_28 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */
+#define XK_braille_dots_128 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */
+#define XK_braille_dots_38 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */
+#define XK_braille_dots_138 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */
+#define XK_braille_dots_238 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */
+#define XK_braille_dots_1238 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */
+#define XK_braille_dots_48 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */
+#define XK_braille_dots_148 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */
+#define XK_braille_dots_248 0x100288a /* U+288a BRAILLE PATTERN DOTS-248 */
+#define XK_braille_dots_1248 0x100288b /* U+288b BRAILLE PATTERN DOTS-1248 */
+#define XK_braille_dots_348 0x100288c /* U+288c BRAILLE PATTERN DOTS-348 */
+#define XK_braille_dots_1348 0x100288d /* U+288d BRAILLE PATTERN DOTS-1348 */
+#define XK_braille_dots_2348 0x100288e /* U+288e BRAILLE PATTERN DOTS-2348 */
+#define XK_braille_dots_12348 0x100288f /* U+288f BRAILLE PATTERN DOTS-12348 */
+#define XK_braille_dots_58 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */
+#define XK_braille_dots_158 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */
+#define XK_braille_dots_258 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */
+#define XK_braille_dots_1258 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */
+#define XK_braille_dots_358 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */
+#define XK_braille_dots_1358 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */
+#define XK_braille_dots_2358 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */
+#define XK_braille_dots_12358 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */
+#define XK_braille_dots_458 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */
+#define XK_braille_dots_1458 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */
+#define XK_braille_dots_2458 0x100289a /* U+289a BRAILLE PATTERN DOTS-2458 */
+#define XK_braille_dots_12458 0x100289b /* U+289b BRAILLE PATTERN DOTS-12458 */
+#define XK_braille_dots_3458 0x100289c /* U+289c BRAILLE PATTERN DOTS-3458 */
+#define XK_braille_dots_13458 0x100289d /* U+289d BRAILLE PATTERN DOTS-13458 */
+#define XK_braille_dots_23458 0x100289e /* U+289e BRAILLE PATTERN DOTS-23458 */
+#define XK_braille_dots_123458 0x100289f /* U+289f BRAILLE PATTERN DOTS-123458 */
+#define XK_braille_dots_68 0x10028a0 /* U+28a0 BRAILLE PATTERN DOTS-68 */
+#define XK_braille_dots_168 0x10028a1 /* U+28a1 BRAILLE PATTERN DOTS-168 */
+#define XK_braille_dots_268 0x10028a2 /* U+28a2 BRAILLE PATTERN DOTS-268 */
+#define XK_braille_dots_1268 0x10028a3 /* U+28a3 BRAILLE PATTERN DOTS-1268 */
+#define XK_braille_dots_368 0x10028a4 /* U+28a4 BRAILLE PATTERN DOTS-368 */
+#define XK_braille_dots_1368 0x10028a5 /* U+28a5 BRAILLE PATTERN DOTS-1368 */
+#define XK_braille_dots_2368 0x10028a6 /* U+28a6 BRAILLE PATTERN DOTS-2368 */
+#define XK_braille_dots_12368 0x10028a7 /* U+28a7 BRAILLE PATTERN DOTS-12368 */
+#define XK_braille_dots_468 0x10028a8 /* U+28a8 BRAILLE PATTERN DOTS-468 */
+#define XK_braille_dots_1468 0x10028a9 /* U+28a9 BRAILLE PATTERN DOTS-1468 */
+#define XK_braille_dots_2468 0x10028aa /* U+28aa BRAILLE PATTERN DOTS-2468 */
+#define XK_braille_dots_12468 0x10028ab /* U+28ab BRAILLE PATTERN DOTS-12468 */
+#define XK_braille_dots_3468 0x10028ac /* U+28ac BRAILLE PATTERN DOTS-3468 */
+#define XK_braille_dots_13468 0x10028ad /* U+28ad BRAILLE PATTERN DOTS-13468 */
+#define XK_braille_dots_23468 0x10028ae /* U+28ae BRAILLE PATTERN DOTS-23468 */
+#define XK_braille_dots_123468 0x10028af /* U+28af BRAILLE PATTERN DOTS-123468 */
+#define XK_braille_dots_568 0x10028b0 /* U+28b0 BRAILLE PATTERN DOTS-568 */
+#define XK_braille_dots_1568 0x10028b1 /* U+28b1 BRAILLE PATTERN DOTS-1568 */
+#define XK_braille_dots_2568 0x10028b2 /* U+28b2 BRAILLE PATTERN DOTS-2568 */
+#define XK_braille_dots_12568 0x10028b3 /* U+28b3 BRAILLE PATTERN DOTS-12568 */
+#define XK_braille_dots_3568 0x10028b4 /* U+28b4 BRAILLE PATTERN DOTS-3568 */
+#define XK_braille_dots_13568 0x10028b5 /* U+28b5 BRAILLE PATTERN DOTS-13568 */
+#define XK_braille_dots_23568 0x10028b6 /* U+28b6 BRAILLE PATTERN DOTS-23568 */
+#define XK_braille_dots_123568 0x10028b7 /* U+28b7 BRAILLE PATTERN DOTS-123568 */
+#define XK_braille_dots_4568 0x10028b8 /* U+28b8 BRAILLE PATTERN DOTS-4568 */
+#define XK_braille_dots_14568 0x10028b9 /* U+28b9 BRAILLE PATTERN DOTS-14568 */
+#define XK_braille_dots_24568 0x10028ba /* U+28ba BRAILLE PATTERN DOTS-24568 */
+#define XK_braille_dots_124568 0x10028bb /* U+28bb BRAILLE PATTERN DOTS-124568 */
+#define XK_braille_dots_34568 0x10028bc /* U+28bc BRAILLE PATTERN DOTS-34568 */
+#define XK_braille_dots_134568 0x10028bd /* U+28bd BRAILLE PATTERN DOTS-134568 */
+#define XK_braille_dots_234568 0x10028be /* U+28be BRAILLE PATTERN DOTS-234568 */
+#define XK_braille_dots_1234568 0x10028bf /* U+28bf BRAILLE PATTERN DOTS-1234568 */
+#define XK_braille_dots_78 0x10028c0 /* U+28c0 BRAILLE PATTERN DOTS-78 */
+#define XK_braille_dots_178 0x10028c1 /* U+28c1 BRAILLE PATTERN DOTS-178 */
+#define XK_braille_dots_278 0x10028c2 /* U+28c2 BRAILLE PATTERN DOTS-278 */
+#define XK_braille_dots_1278 0x10028c3 /* U+28c3 BRAILLE PATTERN DOTS-1278 */
+#define XK_braille_dots_378 0x10028c4 /* U+28c4 BRAILLE PATTERN DOTS-378 */
+#define XK_braille_dots_1378 0x10028c5 /* U+28c5 BRAILLE PATTERN DOTS-1378 */
+#define XK_braille_dots_2378 0x10028c6 /* U+28c6 BRAILLE PATTERN DOTS-2378 */
+#define XK_braille_dots_12378 0x10028c7 /* U+28c7 BRAILLE PATTERN DOTS-12378 */
+#define XK_braille_dots_478 0x10028c8 /* U+28c8 BRAILLE PATTERN DOTS-478 */
+#define XK_braille_dots_1478 0x10028c9 /* U+28c9 BRAILLE PATTERN DOTS-1478 */
+#define XK_braille_dots_2478 0x10028ca /* U+28ca BRAILLE PATTERN DOTS-2478 */
+#define XK_braille_dots_12478 0x10028cb /* U+28cb BRAILLE PATTERN DOTS-12478 */
+#define XK_braille_dots_3478 0x10028cc /* U+28cc BRAILLE PATTERN DOTS-3478 */
+#define XK_braille_dots_13478 0x10028cd /* U+28cd BRAILLE PATTERN DOTS-13478 */
+#define XK_braille_dots_23478 0x10028ce /* U+28ce BRAILLE PATTERN DOTS-23478 */
+#define XK_braille_dots_123478 0x10028cf /* U+28cf BRAILLE PATTERN DOTS-123478 */
+#define XK_braille_dots_578 0x10028d0 /* U+28d0 BRAILLE PATTERN DOTS-578 */
+#define XK_braille_dots_1578 0x10028d1 /* U+28d1 BRAILLE PATTERN DOTS-1578 */
+#define XK_braille_dots_2578 0x10028d2 /* U+28d2 BRAILLE PATTERN DOTS-2578 */
+#define XK_braille_dots_12578 0x10028d3 /* U+28d3 BRAILLE PATTERN DOTS-12578 */
+#define XK_braille_dots_3578 0x10028d4 /* U+28d4 BRAILLE PATTERN DOTS-3578 */
+#define XK_braille_dots_13578 0x10028d5 /* U+28d5 BRAILLE PATTERN DOTS-13578 */
+#define XK_braille_dots_23578 0x10028d6 /* U+28d6 BRAILLE PATTERN DOTS-23578 */
+#define XK_braille_dots_123578 0x10028d7 /* U+28d7 BRAILLE PATTERN DOTS-123578 */
+#define XK_braille_dots_4578 0x10028d8 /* U+28d8 BRAILLE PATTERN DOTS-4578 */
+#define XK_braille_dots_14578 0x10028d9 /* U+28d9 BRAILLE PATTERN DOTS-14578 */
+#define XK_braille_dots_24578 0x10028da /* U+28da BRAILLE PATTERN DOTS-24578 */
+#define XK_braille_dots_124578 0x10028db /* U+28db BRAILLE PATTERN DOTS-124578 */
+#define XK_braille_dots_34578 0x10028dc /* U+28dc BRAILLE PATTERN DOTS-34578 */
+#define XK_braille_dots_134578 0x10028dd /* U+28dd BRAILLE PATTERN DOTS-134578 */
+#define XK_braille_dots_234578 0x10028de /* U+28de BRAILLE PATTERN DOTS-234578 */
+#define XK_braille_dots_1234578 0x10028df /* U+28df BRAILLE PATTERN DOTS-1234578 */
+#define XK_braille_dots_678 0x10028e0 /* U+28e0 BRAILLE PATTERN DOTS-678 */
+#define XK_braille_dots_1678 0x10028e1 /* U+28e1 BRAILLE PATTERN DOTS-1678 */
+#define XK_braille_dots_2678 0x10028e2 /* U+28e2 BRAILLE PATTERN DOTS-2678 */
+#define XK_braille_dots_12678 0x10028e3 /* U+28e3 BRAILLE PATTERN DOTS-12678 */
+#define XK_braille_dots_3678 0x10028e4 /* U+28e4 BRAILLE PATTERN DOTS-3678 */
+#define XK_braille_dots_13678 0x10028e5 /* U+28e5 BRAILLE PATTERN DOTS-13678 */
+#define XK_braille_dots_23678 0x10028e6 /* U+28e6 BRAILLE PATTERN DOTS-23678 */
+#define XK_braille_dots_123678 0x10028e7 /* U+28e7 BRAILLE PATTERN DOTS-123678 */
+#define XK_braille_dots_4678 0x10028e8 /* U+28e8 BRAILLE PATTERN DOTS-4678 */
+#define XK_braille_dots_14678 0x10028e9 /* U+28e9 BRAILLE PATTERN DOTS-14678 */
+#define XK_braille_dots_24678 0x10028ea /* U+28ea BRAILLE PATTERN DOTS-24678 */
+#define XK_braille_dots_124678 0x10028eb /* U+28eb BRAILLE PATTERN DOTS-124678 */
+#define XK_braille_dots_34678 0x10028ec /* U+28ec BRAILLE PATTERN DOTS-34678 */
+#define XK_braille_dots_134678 0x10028ed /* U+28ed BRAILLE PATTERN DOTS-134678 */
+#define XK_braille_dots_234678 0x10028ee /* U+28ee BRAILLE PATTERN DOTS-234678 */
+#define XK_braille_dots_1234678 0x10028ef /* U+28ef BRAILLE PATTERN DOTS-1234678 */
+#define XK_braille_dots_5678 0x10028f0 /* U+28f0 BRAILLE PATTERN DOTS-5678 */
+#define XK_braille_dots_15678 0x10028f1 /* U+28f1 BRAILLE PATTERN DOTS-15678 */
+#define XK_braille_dots_25678 0x10028f2 /* U+28f2 BRAILLE PATTERN DOTS-25678 */
+#define XK_braille_dots_125678 0x10028f3 /* U+28f3 BRAILLE PATTERN DOTS-125678 */
+#define XK_braille_dots_35678 0x10028f4 /* U+28f4 BRAILLE PATTERN DOTS-35678 */
+#define XK_braille_dots_135678 0x10028f5 /* U+28f5 BRAILLE PATTERN DOTS-135678 */
+#define XK_braille_dots_235678 0x10028f6 /* U+28f6 BRAILLE PATTERN DOTS-235678 */
+#define XK_braille_dots_1235678 0x10028f7 /* U+28f7 BRAILLE PATTERN DOTS-1235678 */
+#define XK_braille_dots_45678 0x10028f8 /* U+28f8 BRAILLE PATTERN DOTS-45678 */
+#define XK_braille_dots_145678 0x10028f9 /* U+28f9 BRAILLE PATTERN DOTS-145678 */
+#define XK_braille_dots_245678 0x10028fa /* U+28fa BRAILLE PATTERN DOTS-245678 */
+#define XK_braille_dots_1245678 0x10028fb /* U+28fb BRAILLE PATTERN DOTS-1245678 */
+#define XK_braille_dots_345678 0x10028fc /* U+28fc BRAILLE PATTERN DOTS-345678 */
+#define XK_braille_dots_1345678 0x10028fd /* U+28fd BRAILLE PATTERN DOTS-1345678 */
+#define XK_braille_dots_2345678 0x10028fe /* U+28fe BRAILLE PATTERN DOTS-2345678 */
+#define XK_braille_dots_12345678 0x10028ff /* U+28ff BRAILLE PATTERN DOTS-12345678 */
+#endif /* XK_BRAILLE */
diff --git a/system/include/emscripten.h b/system/include/emscripten.h
deleted file mode 100644
index 7b135c5a..00000000
--- a/system/include/emscripten.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * This file contains a few useful things for compiling C/C++ code
- * with Emscripten, an LLVM-to-JavaScript compiler.
- *
- * The code can be used permissively under the MIT license.
- *
- * http://emscripten.org
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Interface to the underlying JS engine. This function will
- * eval() the given script.
- */
-extern void emscripten_run_script(const char *script);
-extern int emscripten_run_script_int(const char *script);
-
-/*
- * This macro-looking function will cause Emscripten to
- * generate a comment in the generated code.
- * XXX This is deprecated for now, because it requires us to
- * hold all global vars in memory. We need a better solution.
- */
-//extern void EMSCRIPTEN_COMMENT(const char *text);
-
-/*
- * Profiling tools.
- * INIT must be called first, with the maximum identifier that
- * will be used. BEGIN will add some code that marks
- * the beginning of a section of code whose run time you
- * want to measure. END will finish such a section. Note: If you
- * call begin but not end, you will get invalid data!
- * The profiling data will be written out if you call Profile.dump().
- */
-extern void EMSCRIPTEN_PROFILE_INIT(int max);
-extern void EMSCRIPTEN_PROFILE_BEGIN(int id);
-extern void EMSCRIPTEN_PROFILE_END(int id);
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
new file mode 100644
index 00000000..9bc6c410
--- /dev/null
+++ b/system/include/emscripten/emscripten.h
@@ -0,0 +1,145 @@
+/**
+ * This file contains a few useful things for compiling C/C++ code
+ * with Emscripten, an LLVM-to-JavaScript compiler.
+ *
+ * The code can be used permissively under the MIT license.
+ *
+ * http://emscripten.org
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Forces LLVM to not dead-code-eliminate a function. Note that
+ * closure may still eliminate it at the JS level, for which you
+ * should use EXPORTED_FUNCTIONS (see settings.js).
+ *
+ * Example usage:
+ * void EMSCRIPTEN_KEEPALIVE my_function() { .. }
+ */
+#define EMSCRIPTEN_KEEPALIVE __attribute__((used))
+
+/*
+ * Interface to the underlying JS engine. This function will
+ * eval() the given script.
+ */
+extern void emscripten_run_script(const char *script);
+extern int emscripten_run_script_int(const char *script);
+extern void emscripten_async_run_script(const char *script, int millis);
+
+/*
+ * Set a C function as the main event loop. The JS environment
+ * will call that function at a specified number of frames per
+ * second. Setting 0 or a negative value as the fps will use
+ * the browser's requestAnimationFrame mechanism.
+ *
+ * Pausing and resuming the main loop is useful if your app
+ * needs to perform some synchronous operation, for example
+ * to load a file from the network. It might be wrong to
+ * run the main loop before that finishes (the original
+ * code assumes that), so you can break the code up into
+ * asynchronous callbacks, but you must pause the main
+ * loop until they complete.
+ */
+extern void emscripten_set_main_loop(void (*func)(), int fps);
+extern void emscripten_pause_main_loop();
+extern void emscripten_resume_main_loop();
+extern void emscripten_cancel_main_loop();
+
+/*
+ * Add a function to a queue of events that will execute
+ * before the main loop will continue.
+ */
+#if EMSCRIPTEN
+extern void emscripten_push_main_loop_blocker(void (*func)());
+#else
+inline void emscripten_push_main_loop_blocker(void (*func)()) {
+ func();
+}
+#endif
+
+/*
+ * Call a C function asynchronously, that is, after returning
+ * control to the JS event loop. This is done by a setTimeout.
+ * When building natively this becomes a simple direct call,
+ * after SDL_Delay (you must include SDL.h for that).
+ *
+ * If millis is negative, the browser's requestAnimationFrame
+ * mechanism is used.
+ */
+#if EMSCRIPTEN
+extern void emscripten_async_call(void (*func)(), int millis);
+#else
+inline void emscripten_async_call(void (*func)(), int millis) {
+ SDL_Delay(millis);
+ func();
+}
+#endif
+
+/*
+ * Hide the OS mouse cursor over the canvas. Note that SDL's
+ * SDL_ShowCursor command shows and hides the SDL cursor, not
+ * the OS one. This command is useful to hide the OS cursor
+ * if your app draws its own cursor.
+ */
+void emscripten_hide_mouse();
+
+/*
+ * Resizes the pixel width and height of the <canvas> element
+ * on the Emscripten web page.
+ */
+void emscripten_set_canvas_size(int width, int height);
+
+/*
+ * Returns the highest-precision representation of the
+ * current time that the browser provides. This uses either
+ * Date.now or performance.now. The result is *not* an
+ * absolute time, and is only meaningful in comparison to
+ * other calls to this function. The unit is ms.
+ */
+float emscripten_get_now();
+
+/*
+ * Simple random number generation in [0, 1), maps to Math.random().
+ */
+float emscripten_random();
+
+/*
+ * This macro-looking function will cause Emscripten to
+ * generate a comment in the generated code.
+ * XXX This is deprecated for now, because it requires us to
+ * hold all global vars in memory. We need a better solution.
+ */
+//extern void EMSCRIPTEN_COMMENT(const char *text);
+
+/*
+ * Emscripten file system api
+ */
+
+/*
+ * Load file from url in asynchronous way.
+ * When file is loaded then 'onload' callback will called.
+ * If any error occurred 'onerror' will called.
+ * The callbacks are called with the file as their argument.
+ */
+void emscripten_async_wget(const char* url, const char* file, void (*onload)(const char*), void (*onerror)(const char*));
+
+/*
+ * Profiling tools.
+ * INIT must be called first, with the maximum identifier that
+ * will be used. BEGIN will add some code that marks
+ * the beginning of a section of code whose run time you
+ * want to measure. END will finish such a section. Note: If you
+ * call begin but not end, you will get invalid data!
+ * The profiling data will be written out if you call Profile.dump().
+ */
+extern void EMSCRIPTEN_PROFILE_INIT(int max);
+extern void EMSCRIPTEN_PROFILE_BEGIN(int id);
+extern void EMSCRIPTEN_PROFILE_END(int id);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/system/include/features.h b/system/include/features.h
new file mode 100644
index 00000000..1dd6ea6d
--- /dev/null
+++ b/system/include/features.h
@@ -0,0 +1,3 @@
+
+#include <sys/features.h>
+
diff --git a/system/include/gc.h b/system/include/gc.h
new file mode 100644
index 00000000..996bc9ec
--- /dev/null
+++ b/system/include/gc.h
@@ -0,0 +1,50 @@
+/*
+ * Boehm-compatible GC API
+ */
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __attribute__((used)) __GC_KEEPALIVE__() {
+ // Force inclusion of necessary dlmalloc functions
+ static int times = 1;
+ void *x = malloc(times);
+ free(x);
+ x = calloc(1, times);
+ free(x);
+ x = calloc(times, 1);
+ free(x);
+ times++;
+}
+
+/* Initialize. */
+void GC_INIT();
+
+/* Allocate memory. Cleared to 0 to erase all pointers. */
+void *GC_MALLOC(int bytes);
+
+/* Allocate memory for an object that the user promises will not contain pointers. */
+void *GC_MALLOC_ATOMIC(int bytes);
+
+/* Explicitly deallocate an object. Dangerous as it forces a free and does not check if the object is reffed. */
+void GC_FREE(void *ptr);
+
+/* Register a finalizer. func(ptr, arg) will be called. The old values are saved in old_func, old_arg */
+void GC_REGISTER_FINALIZER_NO_ORDER(void *ptr, void (*func)(void *, void *), void *arg,
+ void *(*old_func)(void *, void *), void *old_arg);
+
+/* Non-Boehm additions */
+
+/* Call this once per frame or such, it will collect if necessary */
+void GC_MAYBE_COLLECT();
+
+/* Forces a GC. Mainly useful for testing, but call it if you know a good time to GC in your app. */
+void GC_FORCE_COLLECT();
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/system/include/libc/stdio.h b/system/include/libc/stdio.h
index 19e460a3..4e14df79 100644
--- a/system/include/libc/stdio.h
+++ b/system/include/libc/stdio.h
@@ -142,6 +142,7 @@ typedef _fpos64_t fpos64_t;
#define TMP_MAX 26
+#if 0 /* XXX Emscripten: do not use impure stuff for std*, it makes comparing to native builds harder */
#ifndef _REENT_ONLY
#define stdin (_REENT->_stdin)
#define stdout (_REENT->_stdout)
@@ -151,6 +152,14 @@ typedef _fpos64_t fpos64_t;
#define stdout (_impure_ptr->_stdout)
#define stderr (_impure_ptr->_stderr)
#endif /* _REENT_ONLY */
+#else
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+#define stdin stdin
+#define stdout stdout
+#define stderr stderr
+#endif
#define _stdin_r(x) ((x)->_stdin)
#define _stdout_r(x) ((x)->_stdout)
diff --git a/system/include/libc/sys/_default_fcntl.h b/system/include/libc/sys/_default_fcntl.h
index 0f2ffb07..188e25c4 100644
--- a/system/include/libc/sys/_default_fcntl.h
+++ b/system/include/libc/sys/_default_fcntl.h
@@ -209,6 +209,11 @@ extern int _open64 _PARAMS ((const char *, int, ...));
#define POSIX_FADV_DONTNEED 135
int posix_fadvise(int fd, off_t offset, off_t len, int advice);
int posix_fallocate(int fd, off_t offset, off_t len);
+#define LOCK_SH 1
+#define LOCK_EX 2
+#define LOCK_UN 4
+#define LOCK_NB 8
+int flock(int fd, int operation);
#ifdef __cplusplus
}
diff --git a/system/include/libc/sys/dirent.h b/system/include/libc/sys/dirent.h
index 1fbe2b21..9dcf34d1 100644
--- a/system/include/libc/sys/dirent.h
+++ b/system/include/libc/sys/dirent.h
@@ -26,6 +26,10 @@ long telldir(DIR *);
DIR *readdir(DIR *);
int closedir(DIR *dirp);
void rewinddir(DIR *dirp);
+int scandir(const char *dirp,
+ struct dirent ***namelist,
+ int (*filter)(const struct dirent *),
+ int (*compar)(const struct dirent **, const struct dirent **));
enum {
DT_UNKNOWN = 0,
diff --git a/system/include/libc/sys/types.h b/system/include/libc/sys/types.h
index 79506f3a..2f887537 100644
--- a/system/include/libc/sys/types.h
+++ b/system/include/libc/sys/types.h
@@ -140,15 +140,8 @@ typedef unsigned long vm_size_t;
#define __BIT_TYPES_DEFINED__
-typedef signed char int8_t;
-typedef unsigned char u_int8_t;
-typedef short int16_t;
-typedef unsigned short u_int16_t;
-typedef int int32_t;
-typedef unsigned int u_int32_t;
-typedef long long int64_t;
-typedef unsigned long long u_int64_t;
-typedef int32_t register_t;
+// XXX Emscripten: removed types which are already defined, get them from stdint
+#include <stdint.h>
#endif /* __MS_types__ */
/*
diff --git a/system/include/libcxx/ios b/system/include/libcxx/ios
index e2f2b6fd..477a51fa 100644
--- a/system/include/libcxx/ios
+++ b/system/include/libcxx/ios
@@ -8,6 +8,12 @@
//
//===----------------------------------------------------------------------===//
+// Emscripten note:
+// __except has been renamed to __exceptXXX in this header to avoid compilation
+// errors on windows using clang version 3.0 (tags/RELEASE_30/final). This can
+// be reverted once emscripten upgrades to clang 3.1:
+// http://comments.gmane.org/gmane.comp.compilers.clang.scm/41578
+
#ifndef _LIBCPP_IOS
#define _LIBCPP_IOS
@@ -317,7 +323,7 @@ public:
_LIBCPP_INLINE_VISIBILITY bool bad() const;
_LIBCPP_INLINE_VISIBILITY iostate exceptions() const;
- _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __except);
+ _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __exceptXXX);
void __set_badbit_and_consider_rethrow();
void __set_failbit_and_consider_rethrow();
@@ -553,9 +559,9 @@ ios_base::exceptions() const
inline _LIBCPP_INLINE_VISIBILITY
void
-ios_base::exceptions(iostate __except)
+ios_base::exceptions(iostate __exceptXXX)
{
- __exceptions_ = __except;
+ __exceptions_ = __exceptXXX;
clear(__rdstate_);
}
@@ -584,7 +590,7 @@ public:
_LIBCPP_ALWAYS_INLINE bool bad() const {return ios_base::bad();}
_LIBCPP_ALWAYS_INLINE iostate exceptions() const {return ios_base::exceptions();}
- _LIBCPP_ALWAYS_INLINE void exceptions(iostate __except) {ios_base::exceptions(__except);}
+ _LIBCPP_ALWAYS_INLINE void exceptions(iostate __exceptXXX) {ios_base::exceptions(__exceptXXX);}
// 27.5.4.1 Constructor/destructor:
_LIBCPP_INLINE_VISIBILITY
diff --git a/system/include/net/if.h b/system/include/net/if.h
index 9a4badf3..dd7884aa 100644
--- a/system/include/net/if.h
+++ b/system/include/net/if.h
@@ -2,6 +2,10 @@
#ifndef _NET_IF_H
#define _NET_IF_H
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -11,6 +15,61 @@ struct if_nameindex {
char *if_name;
};
+#define IFHWADDRLEN 6
+#define IFNAMSIZ 16
+
+struct ifmap {
+ unsigned long int mem_start;
+ unsigned long int mem_end;
+ unsigned short int base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+};
+
+struct ifreq {
+ union {
+ char ifrn_name[IFNAMSIZ];
+ } ifr_ifrn;
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_destaddr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short int ifru_flags;
+ int ifru_ivalue;
+ int ifru_mtu;
+ struct ifmap ifru_map;
+ char ifru_slave[IFNAMSIZ];
+ char ifru_newname[IFNAMSIZ];
+ caddr_t ifru_data;
+ } ifr_ifru;
+};
+#define ifr_name ifr_ifrn.ifrn_name
+#define ifr_addr ifr_ifru.ifru_addr
+#define ifr_destaddr ifr_ifru.ifru_destaddr
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr
+#define ifr_netmask ifr_ifru.ifru_netmask
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr
+#define ifr_flags ifr_ifru.ifru_flags
+#define ifr_ivalue ifr_ifru.ifru_ivalue
+#define ifr_mtu ifr_ifru.ifru_mtu
+#define ifr_map ifr_ifru.ifru_map
+#define ifr_slave ifr_ifru.ifru_slave
+#define ifr_newname ifr_ifru.ifru_newname
+#define ifr_data ifr_ifru.ifru_data
+
+struct ifconf {
+ int ifc_len;
+ union {
+ caddr_t ifcu_buf;
+ struct ifreq* ifcu_req;
+ } ifc_ifcu;
+};
+#define ifc_buf ifc_ifcu.ifcu_buf
+#define ifc_req ifc_ifcu.ifcu_req
+
#define IF_NAMESIZE abort(0);
unsigned if_nametoindex(const char *a);
@@ -18,6 +77,8 @@ char *if_indextoname(unsigned int a, char *b);
struct if_nameindex *if_nameindex();
void if_freenameindex(struct if_nameindex *a);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/system/include/net/netinet/in.h b/system/include/net/netinet/in.h
index 4547696b..9229ca84 100644
--- a/system/include/net/netinet/in.h
+++ b/system/include/net/netinet/in.h
@@ -39,6 +39,11 @@ struct sockaddr_in6 {
int sin6_scope_id;
};
+struct ip_mreq {
+ struct in_addr imr_multiaddr;
+ struct in_addr imr_interface;
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/system/include/net/netinet/tcp.h b/system/include/net/netinet/tcp.h
new file mode 100644
index 00000000..06e8414b
--- /dev/null
+++ b/system/include/net/netinet/tcp.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tcp.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_TCP_H
+#define _NETINET_TCP_H 1
+
+#include <features.h>
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */
+#define TCP_MAXSEG 2 /* Set maximum segment size */
+#define TCP_CORK 3 /* Control sending of partial frames */
+#define TCP_KEEPIDLE 4 /* Start keeplives after this period */
+#define TCP_KEEPINTVL 5 /* Interval between keepalives */
+#define TCP_KEEPCNT 6 /* Number of keepalives before death */
+#define TCP_SYNCNT 7 /* Number of SYN retransmits */
+#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */
+#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */
+#define TCP_INFO 11 /* Information about this connection. */
+#define TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */
+#define TCP_CONGESTION 13 /* Congestion control algorithm. */
+#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */
+
+#ifdef __USE_MISC
+# include <sys/types.h>
+# include <sys/socket.h>
+
+# ifdef __FAVOR_BSD
+typedef u_int32_t tcp_seq;
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr
+ {
+ u_int16_t th_sport; /* source port */
+ u_int16_t th_dport; /* destination port */
+ tcp_seq th_seq; /* sequence number */
+ tcp_seq th_ack; /* acknowledgement number */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t th_x2:4; /* (unused) */
+ u_int8_t th_off:4; /* data offset */
+# endif
+# if __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t th_off:4; /* data offset */
+ u_int8_t th_x2:4; /* (unused) */
+# endif
+ u_int8_t th_flags;
+# define TH_FIN 0x01
+# define TH_SYN 0x02
+# define TH_RST 0x04
+# define TH_PUSH 0x08
+# define TH_ACK 0x10
+# define TH_URG 0x20
+ u_int16_t th_win; /* window */
+ u_int16_t th_sum; /* checksum */
+ u_int16_t th_urp; /* urgent pointer */
+};
+
+# else /* !__FAVOR_BSD */
+struct tcphdr
+ {
+ u_int16_t source;
+ u_int16_t dest;
+ u_int32_t seq;
+ u_int32_t ack_seq;
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int16_t res1:4;
+ u_int16_t doff:4;
+ u_int16_t fin:1;
+ u_int16_t syn:1;
+ u_int16_t rst:1;
+ u_int16_t psh:1;
+ u_int16_t ack:1;
+ u_int16_t urg:1;
+ u_int16_t res2:2;
+# elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int16_t doff:4;
+ u_int16_t res1:4;
+ u_int16_t res2:2;
+ u_int16_t urg:1;
+ u_int16_t ack:1;
+ u_int16_t psh:1;
+ u_int16_t rst:1;
+ u_int16_t syn:1;
+ u_int16_t fin:1;
+# else
+# error "Adjust your <bits/endian.h> defines"
+# endif
+ u_int16_t window;
+ u_int16_t check;
+ u_int16_t urg_ptr;
+};
+# endif /* __FAVOR_BSD */
+
+enum
+{
+ TCP_ESTABLISHED = 1,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_TIME_WAIT,
+ TCP_CLOSE,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_LISTEN,
+ TCP_CLOSING /* now a valid state */
+};
+
+# define TCPOPT_EOL 0
+# define TCPOPT_NOP 1
+# define TCPOPT_MAXSEG 2
+# define TCPOLEN_MAXSEG 4
+# define TCPOPT_WINDOW 3
+# define TCPOLEN_WINDOW 3
+# define TCPOPT_SACK_PERMITTED 4 /* Experimental */
+# define TCPOLEN_SACK_PERMITTED 2
+# define TCPOPT_SACK 5 /* Experimental */
+# define TCPOPT_TIMESTAMP 8
+# define TCPOLEN_TIMESTAMP 10
+# define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
+
+# define TCPOPT_TSTAMP_HDR \
+ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+# define TCP_MSS 512
+
+# define TCP_MAXWIN 65535 /* largest value for (unscaled) window */
+
+# define TCP_MAX_WINSHIFT 14 /* maximum window shift */
+
+# define SOL_TCP 6 /* TCP level */
+
+
+# define TCPI_OPT_TIMESTAMPS 1
+# define TCPI_OPT_SACK 2
+# define TCPI_OPT_WSCALE 4
+# define TCPI_OPT_ECN 8
+
+/* Values for tcpi_state. */
+enum tcp_ca_state
+{
+ TCP_CA_Open = 0,
+ TCP_CA_Disorder = 1,
+ TCP_CA_CWR = 2,
+ TCP_CA_Recovery = 3,
+ TCP_CA_Loss = 4
+};
+
+struct tcp_info
+{
+ u_int8_t tcpi_state;
+ u_int8_t tcpi_ca_state;
+ u_int8_t tcpi_retransmits;
+ u_int8_t tcpi_probes;
+ u_int8_t tcpi_backoff;
+ u_int8_t tcpi_options;
+ u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+
+ u_int32_t tcpi_rto;
+ u_int32_t tcpi_ato;
+ u_int32_t tcpi_snd_mss;
+ u_int32_t tcpi_rcv_mss;
+
+ u_int32_t tcpi_unacked;
+ u_int32_t tcpi_sacked;
+ u_int32_t tcpi_lost;
+ u_int32_t tcpi_retrans;
+ u_int32_t tcpi_fackets;
+
+ /* Times. */
+ u_int32_t tcpi_last_data_sent;
+ u_int32_t tcpi_last_ack_sent; /* Not remembered, sorry. */
+ u_int32_t tcpi_last_data_recv;
+ u_int32_t tcpi_last_ack_recv;
+
+ /* Metrics. */
+ u_int32_t tcpi_pmtu;
+ u_int32_t tcpi_rcv_ssthresh;
+ u_int32_t tcpi_rtt;
+ u_int32_t tcpi_rttvar;
+ u_int32_t tcpi_snd_ssthresh;
+ u_int32_t tcpi_snd_cwnd;
+ u_int32_t tcpi_advmss;
+ u_int32_t tcpi_reordering;
+
+ u_int32_t tcpi_rcv_rtt;
+ u_int32_t tcpi_rcv_space;
+
+ u_int32_t tcpi_total_retrans;
+};
+
+
+/* For TCP_MD5SIG socket option. */
+#define TCP_MD5SIG_MAXKEYLEN 80
+
+struct tcp_md5sig
+{
+ struct sockaddr_storage tcpm_addr; /* Address associated. */
+ u_int16_t __tcpm_pad1; /* Zero. */
+ u_int16_t tcpm_keylen; /* Key length. */
+ u_int32_t __tcpm_pad2; /* Zero. */
+ u_int8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary). */
+};
+
+#endif /* Misc. */
+
+#endif /* netinet/tcp.h */
diff --git a/system/include/netdb.h b/system/include/netdb.h
new file mode 100644
index 00000000..20f876df
--- /dev/null
+++ b/system/include/netdb.h
@@ -0,0 +1,55 @@
+#ifndef _NETDB_H
+#define _NETDB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HOST_NOT_FOUND 1
+#define TRY_AGAIN 2
+#define NO_RECOVERY 3
+#define NO_DATA 4
+
+#define IP_TOS 1
+#define IP_TTL 2
+#define IP_HDRINCL 3
+#define IP_OPTIONS 4
+#define IP_ROUTER_ALERT 5
+#define IP_RECVOPTS 6
+#define IP_RETOPTS 7
+#define IP_PKTINFO 8
+#define IP_PKTOPTIONS 9
+#define IP_MTU_DISCOVER 10
+#define IP_RECVERR 11
+#define IP_RECVTTL 12
+#define IP_RECVTOS 13
+#define IP_MTU 14
+#define IP_FREEBIND 15
+#define IP_IPSEC_POLICY 16
+#define IP_XFRM_POLICY 17
+#define IP_PASSSEC 18
+#define IP_TRANSPARENT 19
+
+typedef int socklen_t;
+
+struct hostent {
+ char* h_name;
+ char** h_aliases;
+ int h_addrtype;
+ int h_length;
+ char** h_addr_list;
+};
+#define h_addr h_addr_list[0]
+
+struct hostent* gethostbyaddr(const void* addr, socklen_t len, int type);
+struct hostent* gethostbyname(const char* name);
+void sethostent(int stayopen);
+void endhostent(void);
+void herror(const char* s);
+const char* hstrerror(int err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/system/include/pty.h b/system/include/pty.h
new file mode 100644
index 00000000..0ad5b6d5
--- /dev/null
+++ b/system/include/pty.h
@@ -0,0 +1,6 @@
+
+#include <sys/termios.h>
+
+int openpty(int *amaster, int *aslave, char *name, struct termios *termp, struct winsize *winp);
+int forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp);
+
diff --git a/system/include/sys/ioctl.h b/system/include/sys/ioctl.h
new file mode 100644
index 00000000..b7ade699
--- /dev/null
+++ b/system/include/sys/ioctl.h
@@ -0,0 +1,20 @@
+#ifndef _IOCTL_H
+#define _IOCTL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SIOCGIFCONF 1 // bogus value
+#define SIOCGIFNETMASK 2 // bogus value
+
+int ioctl(int d, int request, ...);
+
+#define SO_RCVTIMEO 1000
+#define SO_SNDTIMEO 2000
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/system/include/sys/socket.h b/system/include/sys/socket.h
index 2c23ddb7..69bbdcaa 100644
--- a/system/include/sys/socket.h
+++ b/system/include/sys/socket.h
@@ -1,10 +1,14 @@
#ifndef _SYS_SOCKET_H
#define _SYS_SOCKET_H
+#include <netdb.h>
+#include <sys/select.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+// Note that the values of these constants are mostly arbitrary numbers.
#define SOMAXCONN 128
#define PF_INET 2
#define SO_BROADCAST 6
@@ -17,8 +21,10 @@ extern "C" {
#define SO_REUSEADDR 30
#define SO_SNDBUF 40
#define SO_RCVBUF 60
+#define SO_LINGER 70
+#define SO_NOSIGPIPE 80
-typedef int socklen_t;
+#define SHUT_RDWR 1
typedef unsigned int sa_family_t;
#define AF_INET 1
@@ -41,6 +47,7 @@ int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
+int shutdown(int sockfd, int how);
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
ssize_t recv(int s, void *buf, size_t len, int flags);
ssize_t send(int s, const void *buf, size_t len, int flags);
@@ -58,6 +65,11 @@ struct msghdr
int msg_flags;
};
+struct linger {
+ int l_onoff;
+ int l_linger;
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/system/include/sys/socketvar.h b/system/include/sys/socketvar.h
new file mode 100644
index 00000000..58fe99cf
--- /dev/null
+++ b/system/include/sys/socketvar.h
@@ -0,0 +1,3 @@
+
+#include <sys/socket.h>
+
diff --git a/system/include/sys/statvfs.h b/system/include/sys/statvfs.h
index cf0a8c96..192be153 100644
--- a/system/include/sys/statvfs.h
+++ b/system/include/sys/statvfs.h
@@ -20,7 +20,7 @@ struct statvfs {
int f_namemax;
};
-int statvfs(char *path, struct statvfs *s);
+int statvfs(const char *path, struct statvfs *s);
#ifdef __cplusplus
}
diff --git a/system/lib/libcxx/Makefile b/system/lib/libcxx/Makefile
index 01d8dbf3..814921ea 100644
--- a/system/lib/libcxx/Makefile
+++ b/system/lib/libcxx/Makefile
@@ -1,5 +1,4 @@
OBJECTS = \
- locale.bc \
algorithm.bc \
condition_variable.bc \
future.bc \
@@ -13,13 +12,13 @@ OBJECTS = \
debug.bc \
hash.bc \
mutex.bc \
- readme.txt \
string.bc \
thread.bc \
valarray.bc \
chrono.bc \
exception.bc \
ios.bc \
+ locale.bc \
regex.bc \
strstream.bc \
typeinfo.bc
diff --git a/tests/aniso.c b/tests/aniso.c
new file mode 100644
index 00000000..e673e228
--- /dev/null
+++ b/tests/aniso.c
@@ -0,0 +1,210 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+int hasext(const char *exts, const char *ext) // from cube2, zlib licensed
+{
+ int len = strlen(ext);
+ if(len) for(const char *cur = exts; (cur = strstr(cur, ext)); cur += len)
+ {
+ if((cur == exts || cur[-1] == ' ') && (cur[len] == ' ' || !cur[len])) return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 600, 600, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Check extensions
+
+ const char *exts = (const char *)glGetString(GL_EXTENSIONS);
+ assert(hasext(exts, "GL_EXT_texture_filter_anisotropic"));
+
+ GLint aniso;
+ glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
+ printf("Max anisotropy: %d (using that)\n", aniso);
+ assert(aniso >= 4);
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 600, 600 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/600, 0, 0, 0,
+ 0, -2.0/600, 0, 0,
+ 0, 0, -2.0/600, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+
+ // Load the OpenGL texture
+
+ GLuint texture, texture2;
+
+ const int DDS_SIZE = 43920;
+ FILE *dds = fopen("water.dds", "rb");
+ assert(dds);
+ char *ddsdata = (char*)malloc(DDS_SIZE);
+ assert(fread(ddsdata, 1, DDS_SIZE, dds) == DDS_SIZE);
+ fclose(dds);
+
+ {
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ char *curr = ddsdata + 128;
+ int level = 0;
+ int w = 512;
+ int h = 64;
+ while (level < 5) {
+ printf("uploading level %d: %d, %d\n", level, w, h);
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, w, h, 0, w*h, curr);
+ assert(!glGetError());
+ curr += MAX(w, 4)*MAX(h, 4);
+ w /= 2;
+ h /= 2;
+ level++;
+ }
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ }
+ {
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+
+ char *curr = ddsdata + 128;
+ int level = 0;
+ int w = 512;
+ int h = 64;
+ while (level < 5) {
+ printf("uploading level %d: %d, %d\n", level, w, h);
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, w, h, 0, w*h, curr);
+ assert(!glGetError());
+ curr += MAX(w, 4)*MAX(h, 4);
+ w /= 2;
+ h /= 2;
+ level++;
+ }
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+ }
+
+ // Prepare and Render
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ int w = 10;
+ int n = 15;
+ glBindTexture( GL_TEXTURE_2D, texture );
+ for (int x = 0; x < n; x++) {
+ int start = x*w*2;
+ glBegin( GL_TRIANGLES );
+ glTexCoord2i( 1, 0 ); glVertex3f( start , 0, 0 );
+ glTexCoord2i( 0, 0 ); glVertex3f( start+w, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( start-w, 300, 0 );
+ glEnd();
+ }
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ for (int x = 0; x < n; x++) {
+ int start = n*w*2 + x*w*2;
+ glBegin( GL_TRIANGLES );
+ glTexCoord2i( 1, 0 ); glVertex3f( start , 0, 0 );
+ glTexCoord2i( 0, 0 ); glVertex3f( start+w, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( start-w, 300, 0 );
+ glEnd();
+ }
+/*
+ int w = 8;
+ int n = 20;
+ for (int x = 0; x < n; x++) {
+ for (int y = 0; y < n*2; y++) {
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( x*w, y*(w), 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( (x+1)*(w-2*y/n), y*(w), 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( (x+1)*(w-2*y/n), (y+1)*(w), 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( x*w, (y+1)*(w), 0 );
+ glEnd();
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( n*w + x*w, y*(w), 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( n*w + (x+1)*(w-2*y/n), y*(w), 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( n*w + (x+1)*(w-2*y/n), (y+1)*(w), 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( n*w + x*w, (y+1)*(w), 0 );
+ glEnd();
+ }
+ }
+*/
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(2000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/aniso.png b/tests/aniso.png
new file mode 100644
index 00000000..5f5812d2
--- /dev/null
+++ b/tests/aniso.png
Binary files differ
diff --git a/tests/bloom.dds b/tests/bloom.dds
new file mode 100644
index 00000000..ed51ab51
--- /dev/null
+++ b/tests/bloom.dds
Binary files differ
diff --git a/tests/browser_gc.cpp b/tests/browser_gc.cpp
new file mode 100644
index 00000000..75dea10a
--- /dev/null
+++ b/tests/browser_gc.cpp
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <gc.h>
+#include <assert.h>
+#include <emscripten.h>
+
+void *global;
+
+int freed = 0;
+
+void finalizer(void *ptr, void *arg) {
+ printf("finalizing %d (global == %d)\n", (int)arg, ptr == global);
+ freed++;
+ if (ptr == global) global = 0;
+}
+
+int stage = 0;
+float start = 0;
+
+void waiter() {
+ if (stage == 0) { // wait for a while, see no GCing
+ assert(global);
+ if (emscripten_get_now() - start > 2100) {
+ GC_MALLOC(1024*1024*2); // allocate enough to trigger a GC
+ start = emscripten_get_now();
+ stage = 1;
+ printf("stage 1\n");
+ }
+ } else if (stage == 1) {
+ assert(global);
+ if (freed > 0) {
+ GC_FREE(global);
+ stage = 2;
+ start = emscripten_get_now();
+ printf("stage 2\n");
+ }
+ if (emscripten_get_now() - start > 2100) {
+ printf("fail, too much time passed (a)\n");
+ return;
+ }
+ } else if (stage == 2) {
+ if (emscripten_get_now() - start > 2100) { // wait and see that no gc'ing happens yet
+ GC_MALLOC(1024*1024*2); // allocate enough to trigger a GC
+ stage = 3;
+ start = emscripten_get_now();
+ printf("stage 3\n");
+ }
+ } else if (stage == 3) {
+ assert(!global);
+ if (freed == 5) {
+ printf("Ok.\n");
+ int result = 1;
+ REPORT_RESULT();
+ return;
+ }
+ if (emscripten_get_now() - start > 2100) {
+ printf("fail, too much time passed (b)\n");
+ return;
+ }
+ }
+
+ emscripten_async_call(waiter, 100);
+}
+
+int main() {
+ start = emscripten_get_now();
+
+ GC_INIT();
+
+ void *local, *local2, *local3, *local4;
+
+ global = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(global, finalizer, 0, 0, 0);
+ local = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local, finalizer, (void*)1, 0, 0);
+ local2 = GC_MALLOC_ATOMIC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local2, finalizer, (void*)2, 0, 0);
+ local3 = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local3, finalizer, (void*)3, 0, 0);
+ local4 = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local4, finalizer, (void*)4, 0, 0);
+
+ void **globalData = (void**)global;
+ globalData[0] = local;
+ globalData[1] = local2;
+
+ void **localData = (void**)local;
+ localData[0] = local3;
+
+ void **local2Data = (void**)local2;
+ local2Data[0] = local4; // actually ignored, because local2 is atomic, so 4 is freeable
+
+ emscripten_async_call(waiter, 100);
+
+ return 0;
+}
+
diff --git a/tests/browser_harness.html b/tests/browser_harness.html
new file mode 100644
index 00000000..86f3749f
--- /dev/null
+++ b/tests/browser_harness.html
@@ -0,0 +1,29 @@
+<html>
+<head>
+ <title>Emscripten Browser Test Harness</title>
+</head>
+<body>
+<h2><b>Running tests...</b></h2>
+<div id="output"></div>
+<script>
+ var counter = 0;
+ function check() {
+ var request = new XMLHttpRequest();
+ request.open('GET', '/check', false);
+ try {
+ request.send(null);
+ if (request.responseText != 'False') {
+ window.open(request.responseText);
+ document.getElementById('output').innerHTML += 'opened test window ' + (counter++) + '..<br>';
+ }
+ setTimeout(check, 333);
+ } catch(e) {
+ document.write('Tests complete. View log in console.');
+ return;
+ }
+ }
+ check();
+</script>
+</body>
+</html>
+
diff --git a/tests/cases/aliasbitcastdollar.ll b/tests/cases/aliasbitcastdollar.ll
new file mode 100644
index 00000000..1ecf6047
--- /dev/null
+++ b/tests/cases/aliasbitcastdollar.ll
@@ -0,0 +1,27 @@
+; ModuleID = '/tmp/emscripten/tmp/src.cpp.o'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1]
+
+@"other$name" = alias bitcast (void ()* @original to void (i32)*) ; [#uses=1]
+
+; [#uses=2]
+define void @original() {
+entry:
+ %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+; [#uses=1]
+declare i32 @puts(i8*)
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ call void @"other$name"(i32 5)
+ ret i32 0
+}
diff --git a/tests/cases/complexphi.ll b/tests/cases/complexphi.ll
index 6f64af06..fcb7185f 100644
--- a/tests/cases/complexphi.ll
+++ b/tests/cases/complexphi.ll
@@ -3,6 +3,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3
target triple = "i386-pc-linux-gnu"
@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+@_dispatchTable = internal global i64 0
; [#uses=0]
define i32 @main() {
@@ -19,6 +20,9 @@ cond.null:
cond.end: ; preds = %cond.false, %cond.true
%cond = phi { i32, i32 } [ { i32 5, i32 6 }, %entry ], [ zeroinitializer, %cond.null ] ; [#uses=1]
store { i32, i32 } %cond, { i32, i32 }* %comp
+
+ store { i32, i32 } { i32 ptrtoint (i64* @_dispatchTable to i32), i32 0 }, { i32, i32 }* getelementptr inbounds ([1 x i64]* @_dispatchTable, i32 0, i32 0, i32 1), align 4
+
ret i32 0 ; [debug line = 6:13]
}
diff --git a/tests/cases/dash.ll b/tests/cases/dash.ll
new file mode 100644
index 00000000..ed5b01ae
--- /dev/null
+++ b/tests/cases/dash.ll
@@ -0,0 +1,18 @@
+; ModuleID = '/tmp/tmpqfApGD/a.out.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@other-name = alias i32 ()* @main
+
+@.st-r = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1
+
+define i32 @main() {
+entry:
+ %ret-val = alloca i32, align 4
+ store i32 0, i32* %ret-val
+ %aaa = bitcast i32 ()* @other-name to i32
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.st-r, i32 0, i32 0), i32 %aaa)
+ ret i32 %ret-val
+}
+
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/emptystruct.ll b/tests/cases/emptystruct.ll
new file mode 100644
index 00000000..d4165fdd
--- /dev/null
+++ b/tests/cases/emptystruct.ll
@@ -0,0 +1,21 @@
+; ModuleID = 'emptystruct.c'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+%struct.s = type { {}, i32 }
+
+@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1]
+
+define i32 @main() nounwind {
+entry:
+ %z = alloca %struct.s, align 4
+ %0 = bitcast %struct.s* %z to i8*
+ call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 4, i32 4, i1 false)
+ %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ ret i32 0
+}
+
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind
+
+declare i32 @puts(i8*)
+
diff --git a/tests/cases/frem.ll b/tests/cases/frem.ll
new file mode 100644
index 00000000..442cd04c
--- /dev/null
+++ b/tests/cases/frem.ll
@@ -0,0 +1,13 @@
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@.str2 = private constant [6 x i8] c"*%f*\0A\00", align 1 ; [#uses=1]
+
+declare i32 @printf(i8* noalias, ...) nounwind
+
+define i32 @main() {
+entry:
+ %c = frem double 2.5, 1.0
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), double %c)
+ ret i32 0
+}
diff --git a/tests/cases/frem.txt b/tests/cases/frem.txt
new file mode 100644
index 00000000..3a7ecb6a
--- /dev/null
+++ b/tests/cases/frem.txt
@@ -0,0 +1 @@
+*0.500000*
diff --git a/tests/cases/funcptr.ll b/tests/cases/funcptr.ll
new file mode 100644
index 00000000..07e2bf91
--- /dev/null
+++ b/tests/cases/funcptr.ll
@@ -0,0 +1,27 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [17 x i8] c"hello %d world!\0A\00", align 1 ; [#uses=1 type=[17 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %access_virt_barray = bitcast i32 0 to [64 x i16]* (i32*, i32)**
+ store [64 x i16]* (i32*, i32)* @access_virt_barray, [64 x i16]* (i32*, i32)** %access_virt_barray, align 4
+ %wakaptr = bitcast [64 x i16]* (i32*, i32)** %access_virt_barray to i32*
+ %waka = load i32* %wakaptr
+ %waka2 = icmp eq i32 %waka, 0
+ %waka3 = zext i1 %waka2 to i32
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i32 0, i32 0), i32 %waka3) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+define [64 x i16]* @access_virt_barray(i32*, i32) {
+ ret void
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/funcptr.txt b/tests/cases/funcptr.txt
new file mode 100644
index 00000000..1030830d
--- /dev/null
+++ b/tests/cases/funcptr.txt
@@ -0,0 +1 @@
+hello 0 world!
diff --git a/tests/cases/phientryimplicitmoar.ll b/tests/cases/phientryimplicitmoar.ll
new file mode 100644
index 00000000..c83458e6
--- /dev/null
+++ b/tests/cases/phientryimplicitmoar.ll
@@ -0,0 +1,28 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+@.str2 = private unnamed_addr constant [15 x i8] c"hello!!world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+define i32 @main() {
+ %retval = alloca i32, align 4
+ %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str2, i32 0, i32 0))
+ %a12 = zext i1 1 to i32
+ br label %13
+
+; <label>:13 ; preds = %13, %1
+ %a14 = phi i32 [ %a12, %1 ], [ %a15, %13 ]
+ %call0 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0))
+ %a15 = add nsw i32 %a14, 2
+ %a16 = icmp eq i32 %a15, 9
+ br i1 %a16, label %17, label %13
+
+; <label>:17 ; preds = %1
+ %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str2, i32 0, i32 0))
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+
diff --git a/tests/cases/phientryimplicitmoar.txt b/tests/cases/phientryimplicitmoar.txt
new file mode 100644
index 00000000..50e5e9ae
--- /dev/null
+++ b/tests/cases/phientryimplicitmoar.txt
@@ -0,0 +1,6 @@
+hello!!world!
+hello, world!
+hello, world!
+hello, world!
+hello, world!
+hello!!world!
diff --git a/tests/cases/phinonexist.ll b/tests/cases/phinonexist.ll
new file mode 100644
index 00000000..145d2221
--- /dev/null
+++ b/tests/cases/phinonexist.ll
@@ -0,0 +1,25 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+define i32 @main() {
+ %retval = alloca i32, align 4
+ %a12 = zext i1 1 to i32
+ br label %13
+
+; <label>:13 ; preds = %13, %1
+ %a14 = phi i32 [ %a12, %1 ], [ %a15, %135 ]
+ %call0 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0))
+ %a15 = add nsw i32 %a14, 2
+ %a16 = icmp eq i32 %a15, 9
+ br label %17
+
+; <label>:17 ; preds = %1
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+
diff --git a/tests/cases/quotedlabel.ll b/tests/cases/quotedlabel.ll
new file mode 100644
index 00000000..d32e380a
--- /dev/null
+++ b/tests/cases/quotedlabel.ll
@@ -0,0 +1,19 @@
+; ModuleID = '/tmp/emscripten/tmp/src.cpp.o'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1]
+
+; [#uses=1]
+declare i32 @puts(i8*)
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ br label %"finish$$$"
+
+"finish$$$": ; preds = %entry
+ %0 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ ret i32 0
+}
+
diff --git a/tests/cases/subnums.ll b/tests/cases/subnums.ll
new file mode 100644
index 00000000..981a1592
--- /dev/null
+++ b/tests/cases/subnums.ll
@@ -0,0 +1,18 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world! %d\0A\00", align 1 ; [#uses=1 type=[18 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ %sub = sub nsw i32 0, -2147483648
+ store i32 %sub, i32* %retval
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0), i32 %sub) ; [#uses=0 type=i32]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/subnums.txt b/tests/cases/subnums.txt
new file mode 100644
index 00000000..e8831e0b
--- /dev/null
+++ b/tests/cases/subnums.txt
@@ -0,0 +1 @@
+hello, world! -2147483648
diff --git a/tests/cases/uadd_overflow.ll b/tests/cases/uadd_overflow.ll
new file mode 100644
index 00000000..a808b9de
--- /dev/null
+++ b/tests/cases/uadd_overflow.ll
@@ -0,0 +1,25 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str2 = private constant [9 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ %mul7 = bitcast i32 -259741926 to i32
+ %shl10 = shl i32 4014, 16
+ %uadd1 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %mul7, i32 %shl10)
+ %a0 = extractvalue { i32, i1 } %uadd1, 0
+ %a1 = extractvalue { i32, i1 } %uadd1, 1
+ %a2 = zext i1 %a1 to i32
+ call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %a0, i32 %a2) ; [#uses=0]
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+
+declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone
+
diff --git a/tests/cases/uadd_overflow.txt b/tests/cases/uadd_overflow.txt
new file mode 100644
index 00000000..dcda9240
--- /dev/null
+++ b/tests/cases/uadd_overflow.txt
@@ -0,0 +1 @@
+*3319578,1*
diff --git a/tests/cube2hash/Makefile b/tests/cube2hash/Makefile
new file mode 100644
index 00000000..5d0a7a63
--- /dev/null
+++ b/tests/cube2hash/Makefile
@@ -0,0 +1,14 @@
+all: cube2hash.bc
+
+cube2hash.bc: cube2crypto.o tiger.o hashstring.o
+ $(CXX) $^ -o $@
+
+hashstring.o: hashstring.cpp
+ $(CXX) -c $^ -o $@
+
+cube2crypto.o: cube2crypto.c cube2crypto.h
+ $(CC) -c $< -o $@
+
+tiger.o: tiger.c tiger.h
+ $(CC) -c $< -o $@
+
diff --git a/tests/cube2hash/cube2crypto.c b/tests/cube2hash/cube2crypto.c
new file mode 100644
index 00000000..52613318
--- /dev/null
+++ b/tests/cube2hash/cube2crypto.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include "util.h"
+#include "tiger.h"
+#include "cube2crypto.h"
+
+char *cube2crypto_hashstring(char *string)
+{
+ char *result = (char *)malloc(49);
+ union hashval hv;
+
+ tiger_hash((uchar *)string, strlen(string), &hv);
+
+ int i;
+ for(i = 0; i < sizeof(hv.bytes); i++)
+ {
+ uchar c = hv.bytes[i];
+ *(result+(i*2)) = "0123456789ABCDEF"[c&0xF];
+ *(result+(i*2)+1) = "0123456789ABCDEF"[c>>4];
+ }
+ *(result+(i*2)+2) = '\0';
+
+ return result;
+}
diff --git a/tests/cube2hash/cube2crypto.h b/tests/cube2hash/cube2crypto.h
new file mode 100644
index 00000000..90bd06a8
--- /dev/null
+++ b/tests/cube2hash/cube2crypto.h
@@ -0,0 +1,9 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *cube2crypto_hashstring(char *string);
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif \ No newline at end of file
diff --git a/tests/cube2hash/hashstring.cpp b/tests/cube2hash/hashstring.cpp
new file mode 100644
index 00000000..b08d5d5e
--- /dev/null
+++ b/tests/cube2hash/hashstring.cpp
@@ -0,0 +1,28 @@
+#include "cube2crypto.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#define EXIT_FAILURE 1
+#define EXIT_SUCCESS 0
+
+void help()
+{
+ printf("Usage: hashstring <seed>\n");
+}
+
+int main(int argc, char **argv)
+{
+ if(argc != 2 || !argv[1])
+ {
+ help();
+ return EXIT_FAILURE;
+ }
+
+ char *answer = cube2crypto_hashstring(argv[1]);
+
+ printf("hash value: %s\n", answer);
+
+ free(answer);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/cube2hash/readme.txt b/tests/cube2hash/readme.txt
new file mode 100644
index 00000000..6eb129c2
--- /dev/null
+++ b/tests/cube2hash/readme.txt
@@ -0,0 +1,27 @@
+This directory contains zlib code (c) the Cube 2/Sauerbraten project.
+http://sauerbraten.org/
+
+LICENSE
+=======
+
+Sauerbraten game engine source code, any release.
+
+Copyright (C) 2001-2009 Wouter van Oortmerssen, Lee Salzman, Mike Dysart, Robert Pointon, and Quinton Reeves
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+
diff --git a/tests/cube2hash/tiger.c b/tests/cube2hash/tiger.c
new file mode 100644
index 00000000..f8707248
--- /dev/null
+++ b/tests/cube2hash/tiger.c
@@ -0,0 +1,175 @@
+///////////////////////// cryptography /////////////////////////////////
+
+/* Based off the reference implementation of Tiger, a cryptographically
+ * secure 192 bit hash function by Ross Anderson and Eli Biham. More info at:
+ * http://www.cs.technion.ac.il/~biham/Reports/Tiger/
+ */
+
+#define TIGER_PASSES 3
+
+#include "tiger.h"
+#include "util.h"
+
+chunk sboxes[4*256];
+
+#define sb1 (sboxes)
+#define sb2 (sboxes+256)
+#define sb3 (sboxes+256*2)
+#define sb4 (sboxes+256*3)
+
+#define round(a, b, c, x) \
+ c ^= x; \
+ a -= sb1[((c)>>(0*8))&0xFF] ^ sb2[((c)>>(2*8))&0xFF] ^ \
+ sb3[((c)>>(4*8))&0xFF] ^ sb4[((c)>>(6*8))&0xFF] ; \
+ b += sb4[((c)>>(1*8))&0xFF] ^ sb3[((c)>>(3*8))&0xFF] ^ \
+ sb2[((c)>>(5*8))&0xFF] ^ sb1[((c)>>(7*8))&0xFF] ; \
+ b *= mul;
+
+void tiger_compress(const chunk *str, chunk state[3])
+{
+ chunk a, b, c;
+ chunk aa, bb, cc;
+ chunk x0, x1, x2, x3, x4, x5, x6, x7;
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+
+ x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3];
+ x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7];
+
+ aa = a;
+ bb = b;
+ cc = c;
+
+ int pass;
+
+ for(pass = 0; pass < TIGER_PASSES; pass++)
+ {
+ if(pass)
+ {
+ x0 -= x7 ^ 0xA5A5A5A5A5A5A5A5ULL; x1 ^= x0; x2 += x1; x3 -= x2 ^ ((~x1)<<19);
+ x4 ^= x3; x5 += x4; x6 -= x5 ^ ((~x4)>>23); x7 ^= x6;
+ x0 += x7; x1 -= x0 ^ ((~x7)<<19); x2 ^= x1; x3 += x2;
+ x4 -= x3 ^ ((~x2)>>23); x5 ^= x4; x6 += x5; x7 -= x6 ^ 0x0123456789ABCDEFULL;
+ }
+
+ uint mul = !pass ? 5 : (pass==1 ? 7 : 9);
+ round(a, b, c, x0) round(b, c, a, x1) round(c, a, b, x2) round(a, b, c, x3)
+ round(b, c, a, x4) round(c, a, b, x5) round(a, b, c, x6) round(b, c, a, x7)
+
+ chunk tmp = a; a = c; c = b; b = tmp;
+
+ }
+
+ a ^= aa;
+ b -= bb;
+ c += cc;
+
+ state[0] = a;
+ state[1] = b;
+ state[2] = c;
+}
+
+void tiger_gensboxes()
+{
+ const char *str = "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham";
+ chunk state[3] = { 0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL, 0xF096A5B4C3B2E187ULL };
+ uchar temp[64];
+ int i, j, col, sb, pass;
+
+ if(BIGENDIAN)
+ {
+ for(j = 0; j < 64; j++)
+ {
+ temp[j^7] = str[j];
+ }
+ }
+ else
+ {
+ for(j = 0; j < 64; j++)
+ {
+ temp[j] = str[j];
+ }
+ }
+
+ for(i = 0; i < 1024; i++)
+ {
+ for(col = 0; col < 8; col++)
+ {
+ ((uchar *)&sboxes[i])[col] = i&0xFF;
+ }
+ }
+
+ int abc = 2;
+ for(pass = 0; pass < 5; pass++)
+ {
+ for(i = 0; i < 256; i++)
+ {
+ for(sb = 0; sb < 1024; sb += 256)
+ {
+ abc++;
+ if(abc >= 3) { abc = 0; tiger_compress((chunk *)temp, state); }
+ for(col = 0; col < 8; col++)
+ {
+ uchar val = ((uchar *)&sboxes[sb+i])[col];
+ ((uchar *)&sboxes[sb+i])[col] = ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col];
+ ((uchar *)&sboxes[sb + ((uchar *)&state[abc])[col]])[col] = val;
+ }
+ }
+ }
+ }
+}
+
+void tiger_hash(const uchar *str, int length, union hashval *val)
+{
+ static int init = false;
+ if(!init) { tiger_gensboxes(); init = true; }
+
+ uchar temp[64];
+
+ val->chunks[0] = 0x0123456789ABCDEFULL;
+ val->chunks[1] = 0xFEDCBA9876543210ULL;
+ val->chunks[2] = 0xF096A5B4C3B2E187ULL;
+
+ int i, j;
+ for(i = length; i >= 64; i -= 64, str += 64)
+ {
+ if(BIGENDIAN)
+ {
+ for(j = 0; j < 64; j++)
+ {
+ temp[j^7] = str[j];
+ }
+
+ tiger_compress((chunk *)temp, val->chunks);
+ }
+ else
+ {
+ tiger_compress((chunk *)str, val->chunks);
+ }
+ }
+
+ if(BIGENDIAN)
+ {
+ for(j = 0; j < i; j++) temp[j^7] = str[j];
+ temp[j^7] = 0x01;
+ while(++j&7) temp[j^7] = 0;
+ }
+ else
+ {
+ for(j = 0; j < i; j++) temp[j] = str[j];
+ temp[j] = 0x01;
+ while(++j&7) temp[j] = 0;
+ }
+
+ if(j > 56)
+ {
+ while(j < 64) temp[j++] = 0;
+ tiger_compress((chunk *)temp, val->chunks);
+ j = 0;
+ }
+ while(j < 56) temp[j++] = 0;
+ *(chunk *)(temp+56) = (chunk)length<<3;
+ tiger_compress((chunk *)temp, val->chunks);
+}
diff --git a/tests/cube2hash/tiger.h b/tests/cube2hash/tiger.h
new file mode 100644
index 00000000..b0d70797
--- /dev/null
+++ b/tests/cube2hash/tiger.h
@@ -0,0 +1,12 @@
+#ifndef _TIGER_H
+#define _TIGER_H
+
+union hashval
+{
+ unsigned char bytes[3*8];
+ unsigned long long int chunks[3];
+};
+
+void tiger_hash(const unsigned char *str, int length, union hashval *val);
+
+#endif
diff --git a/tests/cube2hash/util.h b/tests/cube2hash/util.h
new file mode 100644
index 00000000..844b8ed0
--- /dev/null
+++ b/tests/cube2hash/util.h
@@ -0,0 +1,22 @@
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define BIGENDIAN 0
+
+#ifndef bool
+#define bool unsigned short int
+#define true 1
+#define false 0
+#endif
+
+typedef unsigned long long int chunk;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+
+#endif
diff --git a/tests/cube2md5.cpp b/tests/cube2md5.cpp
new file mode 100644
index 00000000..d2a638d1
--- /dev/null
+++ b/tests/cube2md5.cpp
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+FILE *file;
+bool getline(char *str, int len) { return fgets(str, len, file)!=NULL; }
+
+int main() {
+ file = fopen("cube2md5.txt", "r");
+ char buf[1024];
+ int tmp;
+ getline(buf, sizeof(buf));
+ if(sscanf(buf, " frame %d", &tmp)==1)
+ {
+ printf("frame %d\n", tmp);
+ for(int numdata = 0; getline(buf, sizeof(buf)) && buf[0]!='}';)
+ {
+ printf("frameline\n");
+ for(char *src = buf, *next = src; numdata < 198; numdata++, src = next)
+ {
+ double x = strtod(src, &next);
+ printf("animdata[%d] = %.8f\n", numdata, x);
+ if(next <= src) break;
+ }
+ }
+ }
+ return 1;
+}
+
diff --git a/tests/cube2md5.ok b/tests/cube2md5.ok
new file mode 100644
index 00000000..13505e73
--- /dev/null
+++ b/tests/cube2md5.ok
@@ -0,0 +1,264 @@
+frame 0
+frameline
+animdata[0] = 0.00000000
+animdata[1] = -0.02213600
+animdata[2] = 0.21368000
+animdata[3] = 0.00000000
+animdata[4] = 0.94635600
+animdata[5] = 0.32312500
+animdata[6] = 0.00000000
+frameline
+animdata[6] = 0.00000000
+animdata[7] = 0.10150600
+animdata[8] = 0.00000000
+animdata[9] = -0.10292100
+animdata[10] = 0.00000000
+animdata[11] = 0.00000000
+animdata[12] = 0.00000000
+frameline
+animdata[12] = 0.00000000
+animdata[13] = 0.11562300
+animdata[14] = 0.00000000
+animdata[15] = -0.13181200
+animdata[16] = 0.00000000
+animdata[17] = 0.00000000
+animdata[18] = 0.00000000
+frameline
+animdata[18] = 0.00000000
+animdata[19] = 0.14716600
+animdata[20] = 0.05224800
+animdata[21] = 0.00000000
+animdata[22] = 0.99503400
+animdata[23] = 0.09954000
+animdata[24] = 0.00000000
+frameline
+animdata[24] = -0.08901200
+animdata[25] = 0.03495200
+animdata[26] = 0.10200100
+animdata[27] = -0.90449900
+animdata[28] = 0.31986300
+animdata[29] = -0.16450100
+animdata[30] = 0.00000000
+frameline
+animdata[30] = 0.00000000
+animdata[31] = 0.03460000
+animdata[32] = 0.00000000
+animdata[33] = -0.33932300
+animdata[34] = -0.17058500
+animdata[35] = -0.05674000
+animdata[36] = 0.00000000
+frameline
+animdata[36] = 0.08901300
+animdata[37] = 0.03495300
+animdata[38] = 0.10200300
+animdata[39] = -0.90678000
+animdata[40] = -0.30414400
+animdata[41] = 0.13180800
+animdata[42] = 0.00000000
+frameline
+animdata[42] = 0.00000000
+animdata[43] = 0.03459800
+animdata[44] = 0.00000000
+animdata[45] = -0.38465600
+animdata[46] = 0.20853500
+animdata[47] = 0.04355200
+animdata[48] = 0.00000000
+frameline
+animdata[48] = 0.05478300
+animdata[49] = 0.08776100
+animdata[50] = 0.00658100
+animdata[51] = -0.04975400
+animdata[52] = -0.00020500
+animdata[53] = -0.00542700
+animdata[54] = 0.00000000
+frameline
+animdata[54] = -0.05362600
+animdata[55] = 0.08775300
+animdata[56] = 0.00662200
+animdata[57] = -0.03224000
+animdata[58] = 0.70633700
+animdata[59] = 0.03805700
+animdata[60] = 0.00000000
+frameline
+animdata[60] = 0.08767800
+animdata[61] = 0.09910000
+animdata[62] = 0.04200400
+animdata[63] = -0.48658300
+animdata[64] = -0.75782800
+animdata[65] = -0.39224400
+animdata[66] = 0.00000000
+frameline
+animdata[66] = 0.00000000
+animdata[67] = 0.08621700
+animdata[68] = 0.00000000
+animdata[69] = -0.13275100
+animdata[70] = -0.25403200
+animdata[71] = 0.42206600
+animdata[72] = 0.00000000
+frameline
+animdata[72] = 0.00010900
+animdata[73] = 0.11343800
+animdata[74] = -0.00046000
+animdata[75] = 0.00424900
+animdata[76] = 0.43245700
+animdata[77] = 0.08065100
+animdata[78] = 0.00000000
+frameline
+animdata[78] = -0.08767700
+animdata[79] = 0.09909800
+animdata[80] = 0.04200500
+animdata[81] = -0.48460700
+animdata[82] = 0.76187500
+animdata[83] = 0.38432000
+animdata[84] = 0.00000000
+frameline
+animdata[84] = 0.00000000
+animdata[85] = 0.08621700
+animdata[86] = 0.00000000
+animdata[87] = -0.09719100
+animdata[88] = 0.28995100
+animdata[89] = -0.44564500
+animdata[90] = 0.00000000
+frameline
+animdata[90] = 0.00021600
+animdata[91] = 0.11610300
+animdata[92] = 0.00060100
+animdata[93] = -0.02305500
+animdata[94] = -0.41085000
+animdata[95] = -0.08651400
+animdata[96] = 0.00000000
+frameline
+animdata[96] = 0.00000000
+animdata[97] = -0.02463200
+animdata[98] = 0.22803300
+animdata[99] = 0.00000000
+animdata[100] = 0.81624500
+animdata[101] = -0.57770600
+animdata[102] = 0.00000000
+frameline
+animdata[102] = 0.06124500
+animdata[103] = 0.07378500
+animdata[104] = 0.01947500
+animdata[105] = -0.49098300
+animdata[106] = -0.18594000
+animdata[107] = 0.01243400
+animdata[108] = 0.00000000
+frameline
+animdata[108] = 0.00000000
+animdata[109] = 0.10644500
+animdata[110] = 0.00000000
+animdata[111] = -0.54092700
+animdata[112] = 0.23666500
+animdata[113] = -0.28196200
+animdata[114] = 0.00000000
+frameline
+animdata[114] = 0.00000000
+animdata[115] = 0.08007200
+animdata[116] = 0.00000000
+animdata[117] = -0.31038200
+animdata[118] = -0.77741400
+animdata[119] = 0.54682500
+animdata[120] = 0.00000000
+frameline
+animdata[120] = 0.00000000
+animdata[121] = 0.05055300
+animdata[122] = 0.00000000
+animdata[123] = 0.09166800
+animdata[124] = -0.20672100
+animdata[125] = -0.07288900
+animdata[126] = 0.00000000
+frameline
+animdata[126] = -0.06124500
+animdata[127] = 0.07378400
+animdata[128] = 0.01947500
+animdata[129] = -0.58758300
+animdata[130] = 0.18610800
+animdata[131] = 0.00950000
+animdata[132] = 0.00000000
+frameline
+animdata[132] = 0.00000000
+animdata[133] = 0.10644600
+animdata[134] = 0.00000000
+animdata[135] = -0.54092800
+animdata[136] = -0.23666300
+animdata[137] = 0.28196400
+animdata[138] = 0.00000000
+frameline
+animdata[138] = 0.00000000
+animdata[139] = 0.08007200
+animdata[140] = 0.00000000
+animdata[141] = -0.28906600
+animdata[142] = 0.74845100
+animdata[143] = -0.59650400
+animdata[144] = 0.00000000
+frameline
+animdata[144] = 0.00000000
+animdata[145] = 0.05055300
+animdata[146] = 0.00000000
+animdata[147] = 0.12786100
+animdata[148] = 0.23079600
+animdata[149] = 0.07114100
+animdata[150] = 0.00000000
+frameline
+animdata[150] = 0.00000000
+animdata[151] = -0.04418300
+animdata[152] = 0.02565600
+animdata[153] = -0.87689900
+animdata[154] = 0.00000000
+animdata[155] = 0.00000000
+animdata[156] = 0.00000000
+frameline
+animdata[156] = 0.00000000
+animdata[157] = 0.04597000
+animdata[158] = 0.00000000
+animdata[159] = 0.14528300
+animdata[160] = 0.00000000
+animdata[161] = 0.00000000
+animdata[162] = 0.00000000
+frameline
+animdata[162] = 0.00000000
+animdata[163] = 0.05919300
+animdata[164] = 0.00000000
+animdata[165] = 0.06151300
+animdata[166] = 0.00000000
+animdata[167] = 0.00000000
+animdata[168] = 0.00000000
+frameline
+animdata[168] = 0.00000000
+animdata[169] = 0.06477600
+animdata[170] = 0.00000000
+animdata[171] = 0.01219600
+animdata[172] = 0.00000000
+animdata[173] = 0.00000000
+animdata[174] = 0.00000000
+frameline
+animdata[174] = 0.00000000
+animdata[175] = 0.06418900
+animdata[176] = 0.00000000
+animdata[177] = -0.01392400
+animdata[178] = 0.00000000
+animdata[179] = 0.00000000
+animdata[180] = 0.00000000
+frameline
+animdata[180] = 0.00000000
+animdata[181] = 0.06595100
+animdata[182] = 0.00000000
+animdata[183] = -0.04015600
+animdata[184] = 0.00000000
+animdata[185] = 0.00000000
+animdata[186] = 0.00000000
+frameline
+animdata[186] = 0.00000000
+animdata[187] = 0.06742100
+animdata[188] = 0.00000000
+animdata[189] = -0.02690900
+animdata[190] = 0.00000000
+animdata[191] = 0.00000000
+animdata[192] = 0.00000000
+frameline
+animdata[192] = 0.00000000
+animdata[193] = 0.06124900
+animdata[194] = 0.00000000
+animdata[195] = -0.01467800
+animdata[196] = 0.00000000
+animdata[197] = 0.00000000
diff --git a/tests/cube2md5.txt b/tests/cube2md5.txt
new file mode 100644
index 00000000..5226b5bf
--- /dev/null
+++ b/tests/cube2md5.txt
@@ -0,0 +1,37 @@
+frame 0 {
+ 0.000000 -0.022136 0.213680 0.000000 0.946356 0.323125
+ 0.000000 0.101506 0.000000 -0.102921 0.000000 0.000000
+ 0.000000 0.115623 0.000000 -0.131812 0.000000 0.000000
+ 0.000000 0.147166 0.052248 0.000000 0.995034 0.099540
+ -0.089012 0.034952 0.102001 -0.904499 0.319863 -0.164501
+ 0.000000 0.034600 0.000000 -0.339323 -0.170585 -0.056740
+ 0.089013 0.034953 0.102003 -0.906780 -0.304144 0.131808
+ 0.000000 0.034598 0.000000 -0.384656 0.208535 0.043552
+ 0.054783 0.087761 0.006581 -0.049754 -0.000205 -0.005427
+ -0.053626 0.087753 0.006622 -0.032240 0.706337 0.038057
+ 0.087678 0.099100 0.042004 -0.486583 -0.757828 -0.392244
+ 0.000000 0.086217 0.000000 -0.132751 -0.254032 0.422066
+ 0.000109 0.113438 -0.000460 0.004249 0.432457 0.080651
+ -0.087677 0.099098 0.042005 -0.484607 0.761875 0.384320
+ 0.000000 0.086217 0.000000 -0.097191 0.289951 -0.445645
+ 0.000216 0.116103 0.000601 -0.023055 -0.410850 -0.086514
+ 0.000000 -0.024632 0.228033 0.000000 0.816245 -0.577706
+ 0.061245 0.073785 0.019475 -0.490983 -0.185940 0.012434
+ 0.000000 0.106445 0.000000 -0.540927 0.236665 -0.281962
+ 0.000000 0.080072 0.000000 -0.310382 -0.777414 0.546825
+ 0.000000 0.050553 0.000000 0.091668 -0.206721 -0.072889
+ -0.061245 0.073784 0.019475 -0.587583 0.186108 0.009500
+ 0.000000 0.106446 0.000000 -0.540928 -0.236663 0.281964
+ 0.000000 0.080072 0.000000 -0.289066 0.748451 -0.596504
+ 0.000000 0.050553 0.000000 0.127861 0.230796 0.071141
+ 0.000000 -0.044183 0.025656 -0.876899 0.000000 0.000000
+ 0.000000 0.045970 0.000000 0.145283 0.000000 0.000000
+ 0.000000 0.059193 0.000000 0.061513 0.000000 0.000000
+ 0.000000 0.064776 0.000000 0.012196 0.000000 0.000000
+ 0.000000 0.064189 0.000000 -0.013924 0.000000 0.000000
+ 0.000000 0.065951 0.000000 -0.040156 0.000000 0.000000
+ 0.000000 0.067421 0.000000 -0.026909 0.000000 0.000000
+ 0.000000 0.061249 0.000000 -0.014678 0.000000 0.000000
+}
+
+
diff --git a/tests/cube_explosion.c b/tests/cube_explosion.c
new file mode 100644
index 00000000..ee990a57
--- /dev/null
+++ b/tests/cube_explosion.c
@@ -0,0 +1,235 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8) + ((y*16) << 16) + 0xff331177;
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ // cubegeom: glFrustum(-0.6435469817188064, 0.1435469817188064, -0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.6435469817188064, -0.48266022190470925, 0.48266022190470925, 0.5400000214576721, 2048);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ // cubegeom glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+ glRotated(0, 0, 1, 0);
+ glRotated(0, -1, 0, 0);
+ glRotated(0, 0, 0, -1);
+ glTranslated(-512,-512,-527);
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ GLint ok;
+
+ const char *vertexShader =
+ "uniform vec4 center, animstate;\n"
+ "uniform vec4 texgenS, texgenT;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 wobble = vec4(gl_Vertex.xyz*(1.0 + 0.5*abs(fract(dot(gl_Vertex.xyz, center.xyz) + animstate.w*0.002) - 0.5)), gl_Vertex.w);\n"
+ " gl_Position = gl_ModelViewProjectionMatrix * wobble;\n"
+ " gl_FrontColor = gl_Color;\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n"
+ " vec2 texgen = vec2(dot(texgenS, gl_Vertex), dot(texgenT, gl_Vertex)); \n"
+ " gl_TexCoord[1].xy = texgen;\n"
+ " gl_TexCoord[2].xy = texgen - animstate.w*0.0005;\n"
+ "}\n";
+ const char *fragmentShader =
+ "uniform sampler2D tex2;\n"
+ "uniform sampler2D tex0, tex1;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec2 dtc = gl_TexCoord[0].xy + texture2D(tex0, gl_TexCoord[2].xy).xy*0.1; \n"
+ " vec4 diffuse = texture2D(tex0, dtc);\n"
+ " vec4 blend = texture2D(tex1, gl_TexCoord[1].xy); \n"
+ " diffuse *= blend.a*4.0; \n"
+ " diffuse.b += 0.5 - blend.a*0.5; \n"
+ " gl_FragColor = diffuse * gl_Color;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ // get active uniform data for 10 uniforms. XXX they include our additions from shader rewriting! XXX
+
+ // gen texture, we already has one
+
+ GLuint arrayBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ GLubyte arrayBufferData[] =
+{0,0,0,128,0,0,0,0,0,0,128,63,0,0,0,0,0,0,128,63,0,0,0,128,0,0,0,0,0,0,128,63,171,170,170,61,0,0,128,63,0,0,0,128,0,0,0,0,0,0,128,63,171,170,42,62,0,0,128,63,0,0,0,128,0,0,0,0,0,0,128,63,0,0,128,62,0,0,128,63,0,0,0,128,0,0,0,128,0,0,128,63,171,170,170,62,0,0,128,63,0,0,0,128,0,0,0,128,0,0,128,63,85,85,213,62,0,0,128,63,0,0,0,128,0,0,0,128,0,0,128,63,0,0,0,63,0,0,128,63,0,0,0,0,0,0,0,128,0,0,128,63,85,85,21,63,0,0,128,63,0,0,0,0,0,0,0,128,0,0,128,63,171,170,42,63,0,0,128,63,0,0,0,0,0,0,0,128,0,0,128,63,0,0,64,63,0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,85,85,85,63,0,0,128,63,0,0,0,0,0,0,0,0,0,0,128,63,171,170,106,63,0,0,128,63,0,0,0,128,0,0,0,0,0,0,128,63,0,0,128,63,0,0,128,63,0,0,0,128,0,0,0,63,215,179,93,63,0,0,0,0,85,85,85,63,0,0,128,190,215,179,221,62,215,179,93,63,171,170,170,61,85,85,85,63,215,179,221,190,0,0,128,62,215,179,93,63,171,170,42,62,85,85,85,63,0,0,0,191,0,48,13,36,215,179,93,63,0,0,128,62,85,85,85,63,215,179,221,190,0,0,128,190,215,179,93,63,171,170,170,62,85,85,85,63,0,0,128,190,215,179,221,190,215,179,93,63,85,85,213,62,85,85,85,63,0,76,163,165,0,0,0,191,215,179,93,63,0,0,0,63,85,85,85,63,0,0,128,62,215,179,221,190,215,179,93,63,85,85,21,63,85,85,85,63,215,179,221,62,0,0,128,190,215,179,93,63,171,170,42,63,85,85,85,63,0,0,0,63,0,200,211,164,215,179,93,63,0,0,64,63,85,85,85,63,215,179,221,62,0,0,128,62,215,179,93,63,85,85,85,63,85,85,85,63,0,0,128,62,215,179,221,62,215,179,93,63,171,170,106,63,85,85,85,63,0,0,0,128,0,0,0,63,215,179,93,63,0,0,128,63,85,85,85,63,0,0,0,128,215,179,93,63,0,0,0,63,0,0,0,0,171,170,42,63,215,179,221,190,0,0,64,63,0,0,0,63,171,170,170,61,171,170,42,63,0,0,64,191,215,179,221,62,0,0,0,63,171,170,42,62,171,170,42,63,215,179,93,191,63,139,116,36,0,0,0,63,0,0,128,62,171,170,42,63,0,0,64,191,215,179,221,190,0,0,0,63,171,170,170,62,171,170,42,63,215,179,221,190,0,0,64,191,0,0,0,63,85,85,213,62,171,170,42,63,83,107,13,166,215,179,93,191,0,0,0,63,0,0,0,63,171,170,42,63,215,179,221,62,0,0,64,191,0,0,0,63,85,85,21,63,171,170,42,63,0,0,64,63,215,179,221,190,0,0,0,63,171,170,42,63,171,170,42,63,215,179,93,63,111,104,55,165,0,0,0,63,0,0,64,63,171,170,42,63,0,0,64,63,215,179,221,62,0,0,0,63,85,85,85,63,171,170,42,63,215,179,221,62,0,0,64,63,0,0,0,63,171,170,106,63,171,170,42,63,0,0,0,128,215,179,93,63,0,0,0,63,0,0,128,63,171,170,42,63,0,0,0,128,0,0,128,63,0,166,17,38,0,0,0,0,0,0,0,63,0,0,0,191,215,179,93,63,0,166,17,38,171,170,170,61,0,0,0,63,215,179,93,191,0,0,0,63,0,166,17,38,171,170,42,62,0,0,0,63,0,0,128,191,0,48,141,36,0,166,17,38,0,0,128,62,0,0,0,63,215,179,93,191,0,0,0,191,0,166,17,38,171,170,170,62,0,0,0,63,0,0,0,191,215,179,93,191,0,166,17,38,85,85,213,62,0,0,0,63,0,76,35,166,0,0,128,191,0,166,17,38,0,0,0,63,0,0,0,63,0,0,0,63,215,179,93,191,0,166,17,38,85,85,21,63,0,0,0,63,215,179,93,63,0,0,0,191,0,166,17,38,171,170,42,63,0,0,0,63,0,0,128,63,0,200,83,165,0,166,17,38,0,0,64,63,0,0,0,63,215,179,93,63,0,0,0,63,0,166,17,38,85,85,85,63,0,0,0,63,0,0,0,63,215,179,93,63,0,166,17,38,171,170,106,63,0,0,0,63,0,0,0,128,0,0,128,63,0,166,17,38,0,0,128,63,0,0,0,63,0,0,0,128,215,179,93,63,0,0,0,191,0,0,0,0,171,170,170,62,215,179,221,190,0,0,64,63,0,0,0,191,171,170,170,61,171,170,170,62,0,0,64,191,215,179,221,62,0,0,0,191,171,170,42,62,171,170,170,62,215,179,93,191,63,139,116,36,0,0,0,191,0,0,128,62,171,170,170,62,0,0,64,191,215,179,221,190,0,0,0,191,171,170,170,62,171,170,170,62,215,179,221,190,0,0,64,191,0,0,0,191,85,85,213,62,171,170,170,62,83,107,13,166,215,179,93,191,0,0,0,191,0,0,0,63,171,170,170,62,215,179,221,62,0,0,64,191,0,0,0,191,85,85,21,63,171,170,170,62,0,0,64,63,215,179,221,190,0,0,0,191,171,170,42,63,171,170,170,62,215,179,93,63,111,104,55,165,0,0,0,191,0,0,64,63,171,170,170,62,0,0,64,63,215,179,221,62,0,0,0,191,85,85,85,63,171,170,170,62,215,179,221,62,0,0,64,63,0,0,0,191,171,170,106,63,171,170,170,62,0,0,0,128,215,179,93,63,0,0,0,191,0,0,128,63,171,170,170,62,0,0,0,128,0,0,0,63,215,179,93,191,0,0,0,0,171,170,42,62,0,0,128,190,215,179,221,62,215,179,93,191,171,170,170,61,171,170,42,62,215,179,221,190,0,0,128,62,215,179,93,191,171,170,42,62,171,170,42,62,0,0,0,191,0,48,13,36,215,179,93,191,0,0,128,62,171,170,42,62,215,179,221,190,0,0,128,190,215,179,93,191,171,170,170,62,171,170,42,62,0,0,128,190,215,179,221,190,215,179,93,191,85,85,213,62,171,170,42,62,0,76,163,165,0,0,0,191,215,179,93,191,0,0,0,63,171,170,42,62,0,0,128,62,215,179,221,190,215,179,93,191,85,85,21,63,171,170,42,62,215,179,221,62,0,0,128,190,215,179,93,191,171,170,42,63,171,170,42,62,0,0,0,63,0,200,211,164,215,179,93,191,0,0,64,63,171,170,42,62,215,179,221,62,0,0,128,62,215,179,93,191,85,85,85,63,171,170,42,62,0,0,128,62,215,179,221,62,215,179,93,191,171,170,106,63,171,170,42,62,0,0,0,128,0,0,0,63,215,179,93,191,0,0,128,63,171,170,42,62,0,0,0,128,0,166,145,38,0,0,128,191,0,0,0,0,0,0,64,37,0,166,17,166,63,69,124,38,0,0,128,191,171,170,170,61,0,0,64,37,63,69,124,166,0,166,17,38,0,0,128,191,171,170,42,62,0,0,64,37,0,166,145,166,122,167,160,11,0,0,128,191,0,0,128,62,0,0,64,37,63,69,124,166,0,166,17,166,0,0,128,191,171,170,170,62,0,0,64,37,0,166,17,166,63,69,124,166,0,0,128,191,85,85,213,62,0,0,64,37,223,207,57,141,0,166,145,166,0,0,128,191,0,0,0,63,0,0,64,37,0,166,17,38,63,69,124,166,0,0,128,191,85,85,21,63,0,0,64,37,63,69,124,38,0,166,17,166,0,0,128,191,171,170,42,63,0,0,64,37,0,166,145,38,55,251,112,140,0,0,128,191,0,0,64,63,0,0,64,37,63,69,124,38,0,166,17,38,0,0,128,191,85,85,85,63,0,0,64,37,0,166,17,38,63,69,124,38,0,0,128,191,171,170,106,63,0,0,64,37,0,0,0,128,0,166,145,38,0,0,128,191,0,0,128,63,0,0,64,37};
+ glBufferData(GL_ARRAY_BUFFER, 1820, arrayBufferData, GL_STATIC_DRAW);
+
+ GLuint elementBuffer;
+ glGenBuffers(1, &elementBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ GLubyte elementBufferData[] =
+{0,0,13,0,1,0,1,0,13,0,14,0,1,0,14,0,2,0,2,0,14,0,15,0,2,0,15,0,3,0,3,0,15,0,16,0,3,0,16,0,4,0,4,0,16,0,17,0,4,0,17,0,5,0,5,0,17,0,18,0,5,0,18,0,6,0,6,0,18,0,19,0,6,0,19,0,7,0,7,0,19,0,20,0,7,0,20,0,8,0,8,0,20,0,21,0,8,0,21,0,9,0,9,0,21,0,22,0,9,0,22,0,10,0,10,0,22,0,23,0,10,0,23,0,11,0,11,0,23,0,24,0,11,0,24,0,12,0,12,0,24,0,25,0,24,0,37,0,25,0,25,0,37,0,38,0,23,0,36,0,24,0,24,0,36,0,37,0,22,0,35,0,23,0,23,0,35,0,36,0,21,0,34,0,22,0,22,0,34,0,35,0,20,0,33,0,21,0,21,0,33,0,34,0,19,0,32,0,20,0,20,0,32,0,33,0,18,0,31,0,19,0,19,0,31,0,32,0,17,0,30,0,18,0,18,0,30,0,31,0,16,0,29,0,17,0,17,0,29,0,30,0,15,0,28,0,16,0,16,0,28,0,29,0,14,0,27,0,15,0,15,0,27,0,28,0,13,0,26,0,14,0,14,0,26,0,27,0,26,0,39,0,27,0,27,0,39,0,40,0,27,0,40,0,28,0,28,0,40,0,41,0,28,0,41,0,29,0,29,0,41,0,42,0,29,0,42,0,30,0,30,0,42,0,43,0,30,0,43,0,31,0,31,0,43,0,44,0,31,0,44,0,32,0,32,0,44,0,45,0,32,0,45,0,33,0,33,0,45,0,46,0,33,0,46,0,34,0,34,0,46,0,47,0,34,0,47,0,35,0,35,0,47,0,48,0,35,0,48,0,36,0,36,0,48,0,49,0,36,0,49,0,37,0,37,0,49,0,50,0,37,0,50,0,38,0,38,0,50,0,51,0,50,0,63,0,51,0,51,0,63,0,64,0,49,0,62,0,50,0,50,0,62,0,63,0,48,0,61,0,49,0,49,0,61,0,62,0,47,0,60,0,48,0,48,0,60,0,61,0,46,0,59,0,47,0,47,0,59,0,60,0,45,0,58,0,46,0,46,0,58,0,59,0,44,0,57,0,45,0,45,0,57,0,58,0,43,0,56,0,44,0,44,0,56,0,57,0,42,0,55,0,43,0,43,0,55,0,56,0,41,0,54,0,42,0,42,0,54,0,55,0,40,0,53,0,41,0,41,0,53,0,54,0,39,0,52,0,40,0,40,0,52,0,53,0,52,0,65,0,53,0,53,0,65,0,66,0,53,0,66,0,54,0,54,0,66,0,67,0,54,0,67,0,55,0,55,0,67,0,68,0,55,0,68,0,56,0,56,0,68,0,69,0,56,0,69,0,57,0,57,0,69,0,70,0,57,0,70,0,58,0,58,0,70,0,71,0,58,0,71,0,59,0,59,0,71,0,72,0,59,0,72,0,60,0,60,0,72,0,73,0,60,0,73,0,61,0,61,0,73,0,74,0,61,0,74,0,62,0,62,0,74,0,75,0,62,0,75,0,63,0,63,0,75,0,76,0,63,0,76,0,64,0,64,0,76,0,77,0,76,0,89,0,77,0,77,0,89,0,90,0,75,0,88,0,76,0,76,0,88,0,89,0,74,0,87,0,75,0,75,0,87,0,88,0,73,0,86,0,74,0,74,0,86,0,87,0,72,0,85,0,73,0,73,0,85,0,86,0,71,0,84,0,72,0,72,0,84,0,85,0,70,0,83,0,71,0,71,0,83,0,84,0,69,0,82,0,70,0,70,0,82,0,83,0,68,0,81,0,69,0,69,0,81,0,82,0,67,0,80,0,68,0,68,0,80,0,81,0,66,0,79,0,67,0,67,0,79,0,80,0,65,0,78,0,66,0,66,0,78,0,79,0};
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, 864, elementBufferData, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // try to confuse the client state tracker
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 20, 0);
+ glTexCoordPointer(2, GL_FLOAT, 20, (void*)12);
+
+ glPushMatrix();
+ glTranslated(484.50579833984375, 589.3919067382812, 528.0055541992188);
+
+ GLint texgenSLocation = glGetUniformLocation(program, "texgenS");
+ assert(texgenSLocation >= 0);
+ GLfloat texgenSData[4] = { 0.31012535095214844, 0.05928778275847435, 0.38769474625587463, 0.5 };
+ glUniform4fv(texgenSLocation, 1, texgenSData);
+
+ GLint texgenTLocation = glGetUniformLocation(program, "texgenT");
+ assert(texgenTLocation >= 0 && texgenTLocation != texgenSLocation);
+ GLfloat texgenTData[4] = { -0.12697559595108032, -0.4524572193622589, 0.17076200246810913, 0.5 };
+ glUniform4fv(texgenTLocation, 1, texgenTData);
+
+ GLint centerLocation = glGetUniformLocation(program, "center");
+ if (centerLocation >= 0) {
+ GLfloat centerData[4] = { 484.50579833984375, 589.3919067382812, 528.0055541992188, 0 };
+ glUniform4fv(centerLocation, 1, centerData);
+ }
+
+ GLint animstateLocation = glGetUniformLocation(program, "animstate");
+ assert(animstateLocation >= 0);
+ GLfloat animstateData[4] = { 1, 55, 51, 10709 };
+ glUniform4fv(animstateLocation, 1, animstateData);
+
+ glRotated(1529.857142857143, 0.5773502588272095, 0.5773502588272095, 0.5773502588272095);
+ glScaled(-55, 55, -55);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture); // XXX this is after setting Pointers, do we miss it? Also, does it not need clientActiveTexture - should we have updated that?
+ glActiveTexture(GL_TEXTURE0);
+ glColor4f(1, 0.158823529411764705, 0.058823529411764705, 1);
+
+ glDrawElements(GL_TRIANGLES, 432, GL_UNSIGNED_SHORT, 0);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom.c b/tests/cubegeom.c
new file mode 100644
index 00000000..ecefb24a
--- /dev/null
+++ b/tests/cubegeom.c
@@ -0,0 +1,295 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_color.c b/tests/cubegeom_color.c
new file mode 100644
index 00000000..7d384324
--- /dev/null
+++ b/tests/cubegeom_color.c
@@ -0,0 +1,295 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 128, 255, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 255, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 196, 128, 255, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 64, 128, 255, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 100, 128, 255, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here
+ " gl_TexCoord[1] = gl_Color;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = (diffuse * lm * 0.2) + gl_TexCoord[1];\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_color2.c b/tests/cubegeom_color2.c
new file mode 100644
index 00000000..5294329d
--- /dev/null
+++ b/tests/cubegeom_color2.c
@@ -0,0 +1,299 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 128, 255, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 255, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 196, 128, 255, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 64, 128, 255, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 100, 128, 255, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here
+ " gl_TexCoord[1] = gl_Color;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = (diffuse * lm * 0.2) + gl_TexCoord[1];\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+
+ // Disable the color attrib, and use a fixed color
+ glDisableClientState(GL_COLOR_ARRAY);
+ glColor3f(1.0, 0.25, 0.33);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_fog.c b/tests/cubegeom_fog.c
new file mode 100644
index 00000000..9c04a55d
--- /dev/null
+++ b/tests/cubegeom_fog.c
@@ -0,0 +1,307 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Fog
+
+ glEnable(GL_FOG);
+ glFogf(GL_FOG_START, 100);
+ glFogf(GL_FOG_END, 2000);
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ GLfloat fogcolor[4] = { 0.9, 0.1, 0.35, 0 };
+ glFogfv(GL_FOG_COLOR, fogcolor);
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ " gl_FogFragCoord = gl_Position.z;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " vec4 color = diffuse * lm;\n"
+ " gl_FragColor.rgb = mix((gl_Fog.color).rgb, color.rgb, clamp((gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale, 0.0, 1.0));\n"
+ //" gl_FragColor.rgb = 0.0001 * color.rgb + ((gl_Fog.color).rgb * (1.0-clamp((gl_FogFragCoord)* 1.0/1000.0, 0.0, 1.0)));\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_mt.c b/tests/cubegeom_mt.c
new file mode 100644
index 00000000..464de7cc
--- /dev/null
+++ b/tests/cubegeom_mt.c
@@ -0,0 +1,300 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8) + ((x*y) << 16);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0x00, 0x00, 0xff, 0x77,
+ 0x00, 0x44, 0xaa, 0x77,
+ 0x44, 0x00, 0xcc, 0x77,
+ 0x00, 0x44, 0x77, 0x77 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 1, 0, 1, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 1, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 1, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 1, 0, 1, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 1, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 1, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 1, 0, 1, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 1, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 1, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 1, 0, 1, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 1, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+
+ glClientActiveTexture(GL_TEXTURE1);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+
+ glClientActiveTexture(GL_TEXTURE0);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal.c b/tests/cubegeom_normal.c
new file mode 100644
index 00000000..d128fef2
--- /dev/null
+++ b/tests/cubegeom_normal.c
@@ -0,0 +1,295 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal_dap.c b/tests/cubegeom_normal_dap.c
new file mode 100644
index 00000000..f811c586
--- /dev/null
+++ b/tests/cubegeom_normal_dap.c
@@ -0,0 +1,291 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[12/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[ 0/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[24/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[36/sizeof(GLushort)]);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal_dap_far.c b/tests/cubegeom_normal_dap_far.c
new file mode 100644
index 00000000..f954b3c7
--- /dev/null
+++ b/tests/cubegeom_normal_dap_far.c
@@ -0,0 +1,289 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // ignorable ones
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ };
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ for (int i = 0; i < 24; i++) {
+ elementData[i] += 16;
+ }
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)&arrayData[0]);
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)&arrayData[16]);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)&arrayData[24]);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)&arrayData[12]);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)&arrayData[28]);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[12/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[ 0/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[24/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[36/sizeof(GLushort)]);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal_dap_far_glda.c b/tests/cubegeom_normal_dap_far_glda.c
new file mode 100644
index 00000000..a4b4975b
--- /dev/null
+++ b/tests/cubegeom_normal_dap_far_glda.c
@@ -0,0 +1,280 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // ignorable ones
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+
+ 0, 0, 10, 0, 0, 0, 40, 0, 0, 0, 10, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 20, 68, 0, 0, 50, 0, 0, 0, 20, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 30, 68, 0, 0, 60, 68, 0, 0, 30, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 40, 0, 0, 0, 70, 68, 0, 0, 40, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 50, 68, 0, 0, 80, 0, 0, 0, 50, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 90, 0, 0, 0, 60, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 100, 68, 0, 0, 70, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 60, 68, 0, 0, 110, 68, 0, 0, 80, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 70, 0, 0, 0, 10, 68, 0, 0, 90, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 80, 68, 0, 0, 20, 68, 0, 0, 100, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 90, 68, 0, 0, 128, 68, 0, 0, 110, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 100, 0, 0, 0, 128, 68, 0, 0, 120, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 110, 68, 0, 0, 55, 68, 0, 0, 5, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 75, 68, 0, 0, 15, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 25, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 55, 68, 0, 0, 128, 68, 0, 0, 55, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ };
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)&arrayData[0]);
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)&arrayData[16]);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)&arrayData[24]);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)&arrayData[12]);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)&arrayData[28]);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawArrays(GL_TRIANGLES, 16, 16);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal_dap_far_glda_quad.c b/tests/cubegeom_normal_dap_far_glda_quad.c
new file mode 100644
index 00000000..aa6383b8
--- /dev/null
+++ b/tests/cubegeom_normal_dap_far_glda_quad.c
@@ -0,0 +1,280 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // ignorable ones
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+
+ 0, 0, 10, 0, 0, 0, 40, 0, 0, 0, 10, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 20, 68, 0, 0, 50, 0, 0, 0, 20, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 30, 68, 0, 0, 60, 68, 0, 0, 30, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 40, 0, 0, 0, 70, 68, 0, 0, 40, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 50, 68, 0, 0, 80, 0, 0, 0, 50, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 90, 0, 0, 0, 60, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 100, 68, 0, 0, 70, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 60, 68, 0, 0, 110, 68, 0, 0, 80, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 70, 0, 0, 0, 10, 68, 0, 0, 90, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 80, 68, 0, 0, 20, 68, 0, 0, 100, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 90, 68, 0, 0, 128, 68, 0, 0, 110, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 100, 0, 0, 0, 128, 68, 0, 0, 120, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 110, 68, 0, 0, 55, 68, 0, 0, 5, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 75, 68, 0, 0, 15, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 25, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 55, 68, 0, 0, 128, 68, 0, 0, 55, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ };
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)&arrayData[0]);
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)&arrayData[16]);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)&arrayData[24]);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)&arrayData[12]);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)&arrayData[28]);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawArrays(GL_QUADS, 16, 12);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_normal_dap_far_range.c b/tests/cubegeom_normal_dap_far_range.c
new file mode 100644
index 00000000..eb54c22a
--- /dev/null
+++ b/tests/cubegeom_normal_dap_far_range.c
@@ -0,0 +1,289 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // ignorable ones
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 94, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 20, 10, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 31, 20, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 42, 30, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 53, 40, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 64, 50, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 75, 60, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 86, 70, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ };
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ for (int i = 0; i < 24; i++) {
+ elementData[i] += 16;
+ }
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)&arrayData[0]);
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)&arrayData[16]);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)&arrayData[24]);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)&arrayData[12]);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)&arrayData[28]);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/10000.0 + (0.001*texgenscroll.xy) + gl_Normal.xy;\n" // added /100 here
+ " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = diffuse * lm;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[12/sizeof(GLushort)]);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)&elementData[ 0/sizeof(GLushort)]);
+ glDrawRangeElements(GL_TRIANGLES, 8+16, 11+16, 6, GL_UNSIGNED_SHORT, (void*)&elementData[24/sizeof(GLushort)]);
+ glDrawRangeElements(GL_TRIANGLES, 12+16, 15+16, 6, GL_UNSIGNED_SHORT, (void*)&elementData[36/sizeof(GLushort)]);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_pre.c b/tests/cubegeom_pre.c
new file mode 100644
index 00000000..8001a2b8
--- /dev/null
+++ b/tests/cubegeom_pre.c
@@ -0,0 +1,307 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ //glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "attribute vec4 a_position;\n"
+ "attribute vec4 a_texCoord0;\n"
+ "uniform mat4 u_modelView;\n"
+ "uniform mat4 u_projection;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = (u_projection * u_modelView * a_position) + vec4(200, 0, 0, 0);\n"
+ " v_texCoord0.xy = a_texCoord0.xy/20.0;\n" // added /20 here
+ "}\n";
+ const char *fragmentShader = "uniform sampler2D diffusemap;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n"
+ " gl_FragColor = diffuse;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with vertex\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with fragment\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_MODELVIEW_MATRIX, data);
+ printf("Modelview: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ GLint modelViewLocation = glGetUniformLocation(program, "u_modelView");
+ assert(modelViewLocation >= 0);
+ glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data);
+ }
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_PROJECTION_MATRIX, data);
+ printf("Projection: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ GLint projectionLocation = glGetUniformLocation(program, "u_projection");
+ assert(projectionLocation >= 0);
+ glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data);
+ }
+
+ glBindAttribLocation(program, 0, "a_position");
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0);
+ glEnableVertexAttribArray(0);
+
+ glBindAttribLocation(program, 1, "a_texCoord0");
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16);
+ glEnableVertexAttribArray(1);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/cubegeom_pre2.c b/tests/cubegeom_pre2.c
new file mode 100644
index 00000000..ae8dcf9f
--- /dev/null
+++ b/tests/cubegeom_pre2.c
@@ -0,0 +1,348 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ //glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+// glEnable(GL_CULL_FACE);
+ // glEnable(GL_DEPTH_TEST);
+
+ //glClear(GL_DEPTH_BUFFER_BIT);
+
+// glEnableClientState(GL_NORMAL_ARRAY);
+ // glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+// glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+// glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+// glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+// glNormalPointer(GL_BYTE, 32, (void*)12);
+// glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform mat4 u_modelView;\n"
+ "uniform mat4 u_projection;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n" // (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex)
+ // (u_projection * u_modelView * a_position)
+ " gl_Position = (u_projection * u_modelView * gl_Vertex) + vec4(200, 0, 0, 0);\n"
+ " v_texCoord0.xy = gl_MultiTexCoord0.xy/20.0;\n" // added /100 here
+ "}\n";
+ const char *fragmentShader = "uniform sampler2D diffusemap;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n"
+ " gl_FragColor = diffuse;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with vertex\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with fragment\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ //GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ //assert(lightmapLocation >= 0);
+ //glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ //GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ //assert(texgenscrollLocation >= 0);
+
+ //GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ //assert(colorparamsLocation >= 0);
+
+ //GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ //glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ //GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ //glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_MODELVIEW_MATRIX, data);
+ printf("Modelview: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ //memset(data, 0, 16*4);
+ GLint modelViewLocation = glGetUniformLocation(program, "u_modelView");
+ assert(modelViewLocation >= 0);
+ glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data);
+ }
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_PROJECTION_MATRIX, data);
+ printf("Projection: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ //memset(data, 0, 16*4);
+ GLint projectionLocation = glGetUniformLocation(program, "u_projection");
+ assert(projectionLocation >= 0);
+ glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data);
+ }
+
+/*
+ glBindAttribLocation(program, 0, "a_position");
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0);
+ glEnableVertexAttribArray(0);
+
+ glBindAttribLocation(program, 1, "v_texCoord0");
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16);
+ glEnableVertexAttribArray(1);
+*/
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ // SDL_Quit();
+
+ return 0;
+}
+
diff --git a/tests/cubegeom_pre3.c b/tests/cubegeom_pre3.c
new file mode 100644
index 00000000..a1f811b6
--- /dev/null
+++ b/tests/cubegeom_pre3.c
@@ -0,0 +1,348 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform mat4 u_modelView;\n"
+ "uniform mat4 u_projection;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n" // (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex)
+ // (u_projection * u_modelView * a_position)
+ " gl_Position = (u_projection * u_modelView * gl_Vertex) + vec4(200, 0, 0, 0);\n"
+ " v_texCoord0.xy = gl_MultiTexCoord0.xy/20.0;\n" // added /100 here
+ "}\n";
+ const char *fragmentShader = "uniform sampler2D diffusemap;\n"
+ "varying vec4 v_texCoord0;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n"
+ " gl_FragColor = diffuse;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with vertex\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ printf("Shader compilation error with fragment\n");
+ GLint infoLen = 0;
+ glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen > 1)
+ {
+ char* infoLog = (char *)malloc(sizeof(char) * infoLen+1);
+ glGetShaderInfoLog(vs, infoLen, NULL, infoLog);
+ printf("Error compiling shader:\n%s\n", infoLog);
+ }
+ }
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ //GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ //assert(lightmapLocation >= 0);
+ //glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ //GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ //assert(texgenscrollLocation >= 0);
+
+ //GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ //assert(colorparamsLocation >= 0);
+
+ //GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ //glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ //GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ //glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_MODELVIEW_MATRIX, data);
+ printf("Modelview: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ //memset(data, 0, 16*4);
+ GLint modelViewLocation = glGetUniformLocation(program, "u_modelView");
+ assert(modelViewLocation >= 0);
+ glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data);
+ }
+ {
+ GLfloat data[16];
+ glGetFloatv(GL_PROJECTION_MATRIX, data);
+ printf("Projection: ");
+ for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]);
+ printf("\n");
+ //memset(data, 0, 16*4);
+ GLint projectionLocation = glGetUniformLocation(program, "u_projection");
+ assert(projectionLocation >= 0);
+ glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data);
+ }
+
+/*
+ glBindAttribLocation(program, 0, "a_position");
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0);
+ glEnableVertexAttribArray(0);
+
+ glBindAttribLocation(program, 1, "v_texCoord0");
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16);
+ glEnableVertexAttribArray(1);
+*/
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ // SDL_Quit();
+
+ return 0;
+}
+
diff --git a/tests/cubegeom_texturematrix.c b/tests/cubegeom_texturematrix.c
new file mode 100644
index 00000000..229bf2a8
--- /dev/null
+++ b/tests/cubegeom_texturematrix.c
@@ -0,0 +1,312 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+
+ glActiveTexture(GL_TEXTURE0); // TODO: try 1
+ glMatrixMode(GL_TEXTURE);
+ GLfloat tm[] = { 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 };
+ glLoadMatrixf(tm);
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 128, 255, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 255, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 196, 128, 255, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 255, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 64, 255, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 64, 128, 255, 128, // 8
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 9
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 10
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 11
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 100, 128, 255, 128, // 12
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 0, 255, 128, // 13
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 128, // 14
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 255, 0, // 15
+
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128,
+ 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128
+ };
+ assert(sizeof(arrayData) == 1408);
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 };
+ assert(sizeof(elementData) == 48);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
+
+ // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B
+ glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound
+ glTexCoordPointer(2, GL_FLOAT, 32, (void*)16);
+ glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build
+ glTexCoordPointer(2, GL_SHORT, 32, (void*)24);
+ glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup
+ glNormalPointer(GL_BYTE, 32, (void*)12);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28);
+
+ glBindTexture(GL_TEXTURE_2D, texture); // diffuse?
+ glActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, texture2); // lightmap?
+ glActiveTexture(GL_TEXTURE0);
+
+ GLint ok;
+
+ const char *vertexShader = "uniform vec4 texgenscroll;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = gl_TextureMatrix[0] * ftransform();\n"
+ " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here
+ " gl_TexCoord[1] = gl_Color;\n"
+ "}\n";
+ const char *fragmentShader = "uniform vec4 colorparams;\n"
+ "uniform sampler2D diffusemap, lightmap;\n"
+ "void main(void)\n"
+ "{\n"
+ " vec4 diffuse = texture2D(diffusemap, gl_TexCoord[0].xy);\n"
+ " vec4 lm = texture2D(lightmap, gl_TexCoord[1].xy);\n"
+ " diffuse *= colorparams;\n"
+ " gl_FragColor = (diffuse * lm * 0.2) + gl_TexCoord[1];\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv ( vs, GL_COMPILE_STATUS, &ok );
+ if ( !ok )
+ {
+ GLint infoLen = 0;
+ glGetShaderiv ( vs, GL_INFO_LOG_LENGTH, &infoLen );
+ if ( infoLen > 1 )
+ {
+ char* infoLog = (char*)malloc (sizeof(char) * infoLen );
+ glGetShaderInfoLog ( vs, infoLen, NULL, infoLog );
+ printf ( "Error compiling shader:\n%s\n", infoLog );
+ free ( infoLog );
+ }
+ glDeleteShader ( vs );
+ return 0;
+ }
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ GLint lightmapLocation = glGetUniformLocation(program, "lightmap");
+ assert(lightmapLocation >= 0);
+ glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit?
+
+ GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap");
+ assert(diffusemapLocation >= 0);
+ glUniform1i(diffusemapLocation, 0);
+
+ GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll");
+ assert(texgenscrollLocation >= 0);
+
+ GLint colorparamsLocation = glGetUniformLocation(program, "colorparams");
+ assert(colorparamsLocation >= 0);
+
+ GLfloat texgenscrollData[] = { 0, 0, 0, 0 };
+ glUniform4fv(texgenscrollLocation, 1, texgenscrollData);
+
+ GLfloat colorparamsData[] = { 2, 2, 2, 1 };
+ glUniform4fv(colorparamsLocation, 1, colorparamsData);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24);
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/emscripten_api_browser.cpp b/tests/emscripten_api_browser.cpp
new file mode 100644
index 00000000..305265e5
--- /dev/null
+++ b/tests/emscripten_api_browser.cpp
@@ -0,0 +1,88 @@
+#include<stdio.h>
+#include<math.h>
+#include<stdlib.h>
+#include<SDL.h>
+#include<emscripten.h>
+#include<assert.h>
+
+int last = 0;
+
+extern "C" {
+
+bool pre1ed = false;
+bool pre2ed = false;
+void pre1() {
+ assert(!pre1ed);
+ assert(!pre2ed);
+ pre1ed = true;
+}
+void pre2() {
+ assert(pre1ed);
+ assert(!pre2ed);
+ pre2ed = true;
+}
+
+bool fived = false;
+void five() {
+ fived = true;
+ emscripten_resume_main_loop();
+}
+
+void mainey() {
+ static int counter = 0;
+ printf("mainey: %d\n", counter++);
+ if (counter == 20) {
+ emscripten_pause_main_loop();
+ emscripten_async_call(five, 1000);
+ } else if (counter == 22) { // very soon after 20, so without pausing we fail
+ assert(fived);
+ emscripten_push_main_loop_blocker(pre1);
+ emscripten_push_main_loop_blocker(pre2);
+ } else if (counter == 23) {
+ assert(pre1ed);
+ assert(pre2ed);
+ printf("Good!\n");
+ int result = 1;
+ REPORT_RESULT();
+ }
+}
+
+void four() {
+ printf("four!\n");
+ emscripten_set_main_loop(mainey, 0);
+}
+
+void __attribute__((used)) third() {
+ int now = SDL_GetTicks();
+ printf("thard! %d\n", now);
+ assert(fabs(now - last - 1000) < 500);
+ emscripten_async_call(four, -1); // triggers requestAnimationFrame
+}
+
+void second() {
+ int now = SDL_GetTicks();
+ printf("sacond! %d\n", now);
+ assert(fabs(now - last - 500) < 250);
+ last = now;
+ emscripten_async_run_script("_third()", 1000);
+}
+
+}
+
+void never() {
+ int result = 0;
+ REPORT_RESULT();
+}
+
+int main() {
+ SDL_Init(0);
+ last = SDL_GetTicks();
+ printf("frist! %d\n", last);
+
+ atexit(never); // should never be called - it is wrong to exit the runtime orderly if we have async calls!
+
+ emscripten_async_call(second, 500);
+
+ return 1;
+}
+
diff --git a/tests/emscripten_fs_api_browser.cpp b/tests/emscripten_fs_api_browser.cpp
new file mode 100644
index 00000000..07469f34
--- /dev/null
+++ b/tests/emscripten_fs_api_browser.cpp
@@ -0,0 +1,69 @@
+#include<stdio.h>
+#include<emscripten.h>
+#include<assert.h>
+#include <string.h>
+
+extern "C" {
+
+int result = 1;
+int get_count = 0;
+
+void wait_wgets() {
+ if (get_count == 2) {
+ emscripten_cancel_main_loop();
+ REPORT_RESULT();
+ }
+}
+
+void onLoaded(const char* file) {
+ if (strcmp(file, "/tmp/test.html")) {
+ result = 0;
+ }
+
+ printf("loaded: %s\n", file);
+
+ if (FILE * f = fopen(file, "r")) {
+ printf("exists: %s\n", file);
+ int c = fgetc (f);
+ if (c == EOF) {
+ printf("file empty: %s\n", file);
+ result = 0;
+ }
+ fclose(f);
+ } else {
+ result = 0;
+ printf("!exists: %s\n", file);
+ }
+
+ get_count++;
+}
+
+void onError(const char* file) {
+ if (strcmp(file, "/tmp/null")) {
+ result = 0;
+ }
+
+ printf("error: %s\n", file);
+ get_count++;
+}
+
+int main() {
+ emscripten_async_wget(
+ "http://localhost:8888/this_is_not_a_file",
+ "/tmp/null",
+ onLoaded,
+ onError);
+
+ emscripten_async_wget(
+ "http://localhost:8888/test.html",
+ "/tmp/test.html",
+ onLoaded,
+ onError);
+
+ emscripten_set_main_loop(wait_wgets, 0);
+
+ return 0;
+}
+
+}
+
diff --git a/tests/env/output.txt b/tests/env/output.txt
index fa342d48..0ec94064 100644
--- a/tests/env/output.txt
+++ b/tests/env/output.txt
@@ -2,7 +2,7 @@ List:
USER=root
PATH=/
PWD=/
-HOME=/
+HOME=/home/emscripten
LANG=en_US.UTF-8
_=./this.program
diff --git a/tests/fcntl/src.c b/tests/fcntl/src.c
index 5b40ec79..c8c71c8a 100644
--- a/tests/fcntl/src.c
+++ b/tests/fcntl/src.c
@@ -45,7 +45,7 @@ int main() {
printf("\n");
errno = 0;
- flock lk;
+ struct flock lk;
lk.l_type = 42;
printf("F_GETLK: %d\n", fcntl(f, F_GETLK, &lk));
printf("errno: %d\n", errno);
diff --git a/tests/float_tex.cpp b/tests/float_tex.cpp
new file mode 100644
index 00000000..475f2bee
--- /dev/null
+++ b/tests/float_tex.cpp
@@ -0,0 +1,136 @@
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+#include <cmath>
+#include <iostream>
+#include <vector>
+extern "C" {
+#include <GL/gl.h>
+#include <GL/glut.h>
+}
+static const char vertex_shader[] =
+ "#ifdef GL_ES\n"
+ "precision highp float;\n"
+ "#endif\n"
+ "attribute float indices;\n"
+ "uniform sampler2D nodeInfo;\n"
+ "varying vec4 color;"
+ "\n"
+ "void main(void)\n"
+ "{\n"
+ " float s = (indices + 0.5) / 512.; \n"
+ " vec4 v = texture2D(nodeInfo, vec2( s, 0.5));\n"
+ " gl_Position = vec4(v.x, v.y, 0.5, 1.);\n"
+ " gl_PointSize = v.z;\n"
+ " color = vec4(0.5 + v.w/2., 0.5 + 0.5 * v.w/2., 0.5, 1);\n"
+ "}\n";
+static const char fragment_shader[] =
+ "#ifdef GL_ES\n"
+ "precision highp float;\n"
+ "#endif\n"
+ "\n"
+ "varying vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " float dst = distance(vec2(0.5, 0.5), gl_PointCoord); \n"
+ " gl_FragColor = color;\n"
+ " if ( dst > 0.3) {"
+ " gl_FragColor = vec4(0., 0., 0.5, 0.2);\n"
+ "}\n"
+ "if ( dst > 0.5) discard;\n"
+ "}";
+struct NodeInfo { //structure that we want to transmit to our shaders
+ float x;
+ float y;
+ float s;
+ float c;
+};
+GLuint nodeTexture; //texture id used to bind
+GLuint nodeSamplerLocation; //shader sampler address
+GLuint indicesAttributeLocation; //shader attribute address
+GLuint indicesVBO; //Vertex Buffer Object Id;
+const int nbNodes = 512;
+NodeInfo * data = new NodeInfo[nbNodes]; //our data that will be transmitted using float texture.
+double alpha = 0; //use to make a simple funny effect;
+static void updateFloatTexture() {
+ int count = 0;
+ for (float x=0; x < nbNodes; ++x ) {
+ data[count].x = 0.2*pow(cos(alpha), 3) + (sin(alpha)*3. + 3.5) * x/nbNodes * cos(alpha + x/nbNodes * 16. * M_PI);
+ data[count].y = 0.2*pow(sin(alpha), 3) + (sin(alpha)*3. + 3.5) * x/nbNodes * sin(alpha + x/nbNodes * 16. * M_PI);
+ data[count].s = (16. + 16. * cos(alpha + x/nbNodes * 32. * M_PI)) + 8.;// * fmod(x/nbNodes + alpha, 1.) + 5.;
+ data[count].c = 0.5 + 0.5 * sin(alpha + x/nbNodes * 32. * M_PI);
+ ++count;
+ }
+ glBindTexture(GL_TEXTURE_2D, nodeTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, nbNodes, 1, 0, GL_RGBA, GL_FLOAT, data);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, NULL);
+ alpha -= 0.001;
+}
+static void glut_draw_callback(void) {
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glClearColor(1., 1., 1., 0.);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glActiveTexture(GL_TEXTURE0);
+ updateFloatTexture(); //we change the texture each time to create the effect (it is just for the test)
+ glBindTexture(GL_TEXTURE_2D, nodeTexture);
+ glUniform1i(nodeSamplerLocation, GL_TEXTURE0);
+ glEnableVertexAttribArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, indicesVBO);
+ glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
+ glDrawArrays(GL_POINTS, 0, nbNodes);
+ glutSwapBuffers();
+}
+GLuint createShader(const char source[], int type) {
+ char msg[512];
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, (const GLchar**)(&source), NULL);
+ glCompileShader(shader);
+ glGetShaderInfoLog(shader, sizeof msg, NULL, msg);
+ std::cout << "Shader info: " << msg << std::endl;
+ return shader;
+}
+static void gl_init(void) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, createShader(vertex_shader , GL_VERTEX_SHADER));
+ glAttachShader(program, createShader(fragment_shader, GL_FRAGMENT_SHADER));
+ glLinkProgram(program);
+ char msg[512];
+ glGetProgramInfoLog(program, sizeof msg, NULL, msg);
+ std::cout << "info: " << msg << std::endl;
+ glUseProgram(program);
+ std::vector<float> elements(nbNodes);
+ int count = 0;
+ for (float x=0; x < nbNodes; ++x ) {
+ elements[count] = count;
+ ++count;
+ }
+ /*Create one texture to store all the needed information */
+ glGenTextures(1, &nodeTexture);
+ /* Store the vertices in a vertex buffer object (VBO) */
+ glGenBuffers(1, &indicesVBO);
+ glBindBuffer(GL_ARRAY_BUFFER, indicesVBO);
+ glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(uint), &elements[0], GL_STATIC_DRAW);
+ /* Get the locations of the uniforms so we can access them */
+ nodeSamplerLocation = glGetUniformLocation(program, "nodeInfo");
+ glBindAttribLocation(program, 0, "indices");
+ //Enable glPoint size in shader, always enable in Open Gl ES 2.
+ glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
+ glEnable(GL_POINT_SPRITE);
+}
+int main(int argc, char *argv[]) {
+ glutInit(&argc, argv);
+ glutInitWindowSize(640, 480);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutCreateWindow("Simple FLOAT Texture Test");
+ /* Set up glut callback functions */
+ glutDisplayFunc(glut_draw_callback );
+ gl_init();
+ glutMainLoop();
+ return 0;
+}
+
+
diff --git a/tests/float_tex.png b/tests/float_tex.png
new file mode 100644
index 00000000..8c3c6502
--- /dev/null
+++ b/tests/float_tex.png
Binary files differ
diff --git a/tests/freetype/main_2.c b/tests/freetype/main_2.c
new file mode 100644
index 00000000..85e5609d
--- /dev/null
+++ b/tests/freetype/main_2.c
@@ -0,0 +1,135 @@
+/* example1.c */
+/* */
+/* This small program shows how to print a rotated string with the */
+/* FreeType 2 library. */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+int WIDTH = 0;
+int HEIGHT = 0;
+
+/* origin is the upper left corner */
+unsigned char *image;
+
+
+/* Replace this function with something useful. */
+
+void
+draw_bitmap( FT_Bitmap* bitmap,
+ FT_Int x,
+ FT_Int y)
+{
+ FT_Int i, j, p, q;
+ FT_Int x_max = x + bitmap->width;
+ FT_Int y_max = y + bitmap->rows;
+
+ for ( i = x, p = 0; i < x_max; i++, p++ )
+ {
+ for ( j = y, q = 0; j < y_max; j++, q++ )
+ {
+ if ( i < 0 || j < 0 ||
+ i >= WIDTH || j >= HEIGHT )
+ continue;
+
+ image[j*WIDTH + i] |= bitmap->buffer[q * bitmap->width + p];
+ }
+ }
+}
+
+
+void
+show_image( void )
+{
+ int i, j;
+ int count = 0;
+
+ for ( i = 0; i < HEIGHT; i++ )
+ {
+ for ( j = 0; j < WIDTH; j++ )
+ {
+ if (image[i*WIDTH + j]) count++;
+ putchar(image[i*WIDTH + j] == 0? ' '
+ : image[i*WIDTH + j] < 128 ? '+'
+ : '*' );
+ }
+ putchar( '\n' );
+ }
+ printf("Non-0s: %d\n", count);
+}
+
+
+int
+main( int argc,
+ char** argv )
+{
+ FT_Library library;
+ FT_Face face;
+
+ FT_GlyphSlot slot;
+ FT_Error error;
+
+ FT_UInt glyphIndex;
+
+ char* filename;
+ char* text;
+
+ int target_height;
+
+ if ( argc != 6 )
+ {
+ fprintf ( stderr, "usage: %s font sample-text width height angle\n", argv[0] );
+ exit( 1 );
+ }
+
+ // Only test the character 'w'
+ text = "w";
+
+ filename = argv[1]; /* first argument */
+ WIDTH = atoi(argv[3]);
+ HEIGHT = atoi(argv[4]);
+ target_height = HEIGHT;
+
+ image = (unsigned char*)malloc(WIDTH*HEIGHT);
+ for (int x = 0; x < WIDTH; x++)
+ for (int y = 0; y < HEIGHT; y++)
+ image[y*WIDTH + x] = 0;
+
+ error = FT_Init_FreeType( &library ); /* initialize library */
+ if (error) printf("Init Error! %d\n", error);
+
+ error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
+ if (error) printf("New_Face Error! %d\n", error);
+
+ /* use 50pt at 100dpi */
+ error = FT_Set_Char_Size( face, 0, 32 * 64, 0, 0 ); /* set character size */
+ if (error) printf("Set_Cshar_Size Error! %d\n", error);
+
+ slot = face->glyph;
+
+ glyphIndex = FT_Get_Char_Index(face, text[0]);
+
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_NO_BITMAP);
+ if(error) printf("FT_Load_Glyph Error! %d\n", error);
+
+ error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
+ if(error) printf("FT_Render_Glyph Error! %d\n", error);
+
+ /* now, draw to our target surface (convert position) */
+ draw_bitmap(&slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top);
+
+ show_image();
+
+ FT_Done_Face(face);
+ FT_Done_FreeType(library);
+ return 0;
+}
+
+/* EOF */ \ No newline at end of file
diff --git a/tests/freetype/main_3.c b/tests/freetype/main_3.c
new file mode 100644
index 00000000..c3941a17
--- /dev/null
+++ b/tests/freetype/main_3.c
@@ -0,0 +1,184 @@
+/* example1.c */
+/* */
+/* This small program shows how to print a rotated string with the */
+/* FreeType 2 library. */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+int WIDTH = 0;
+int HEIGHT = 0;
+
+/* origin is the upper left corner */
+unsigned char *image;
+
+unsigned char pixelData[32 * 32];
+
+/* Replace this function with something useful. */
+void
+draw_bitmap( FT_Bitmap* bitmap,
+ FT_Int x,
+ FT_Int y)
+{
+ FT_Int i, j, p, q;
+ FT_Int x_max = x + bitmap->width;
+ FT_Int y_max = y + bitmap->rows;
+ int xbyte;
+ int xbit;
+ unsigned char* pcur;
+
+ unsigned char* src = bitmap->buffer;
+ unsigned char* dest = pixelData;
+
+ // Note: FT_RENDER_MONO_MODE render characater's one pixel by a single bit,
+ // translate the single bit to a single char for displaying image.
+ for(int _y = 0; _y < bitmap->rows; ++_y)
+ {
+ for(int _x = 0; _x < bitmap->width; ++_x)
+ {
+ xbyte = _x / 8;
+ xbit = _x - xbyte * 8;
+ pcur = dest + _x;
+
+ // test if the pixel bit be set
+ if(src[xbyte] & (0x80 >> xbit))
+ {
+ *pcur = 0xFF;
+ }
+ else
+ {
+ *pcur = 0;
+ }
+ }
+ src += bitmap->pitch;
+ dest += bitmap->width;
+ }
+
+ // display the character to ref txt file
+ for ( i = x, p = 0; i < x_max; i++, p++ )
+ {
+ for ( j = y, q = 0; j < y_max; j++, q++ )
+ {
+ if ( i < 0 || j < 0 ||
+ i >= WIDTH || j >= HEIGHT )
+ continue;
+
+ image[j*WIDTH + i] |= pixelData[q * bitmap->width + p];
+ }
+ }
+}
+
+
+void
+show_image( void )
+{
+ int i, j;
+ int count = 0;
+
+ for ( i = 0; i < HEIGHT; i++ )
+ {
+ for ( j = 0; j < WIDTH; j++ ) {
+ if (image[i*WIDTH + j]) count++;
+ putchar( image[i*WIDTH + j] == 0 ? ' '
+ : image[i*WIDTH + j] < 128 ? '+'
+ : '*');
+ }
+ putchar('\n');
+ }
+ printf("Non-0s: %d\n", count);
+}
+
+
+int
+main( int argc,
+ char** argv )
+{
+ FT_Library library;
+ FT_Face face;
+
+ FT_GlyphSlot slot;
+ FT_Error error;
+ FT_Vector pen; /* untransformed origin */
+
+ char* filename;
+ char* text;
+
+ double angle;
+ int target_height;
+ int n, num_chars;
+ FT_UInt glyphIndex;
+
+ if ( argc != 6 )
+ {
+ fprintf ( stderr, "usage: %s font sample-text width height angle\n", argv[0] );
+ exit( 1 );
+ }
+
+ filename = argv[1]; /* first argument */
+ text = argv[2]; /* second argument */
+ num_chars = strlen( text );
+ WIDTH = atoi(argv[3]);
+ HEIGHT = atoi(argv[4]);
+ angle = ( ((float)atoi(argv[5])) / 360 ) * 3.14159 * 2; /* use 25 degrees */
+ target_height = HEIGHT;
+
+ image = (unsigned char*)malloc(WIDTH*HEIGHT);
+ for (int x = 0; x < WIDTH; x++)
+ for (int y = 0; y < HEIGHT; y++)
+ image[y*WIDTH + x] = 0;
+
+ error = FT_Init_FreeType( &library ); /* initialize library */
+ if (error) printf("Init Error! %d\n", error);
+
+ error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
+ if (error) printf("New_Face Error! %d\n", error);
+
+ /* use 50pt at 100dpi */
+ error = FT_Set_Char_Size( face, 32 * 64, 0,
+ 0, 0 ); /* set character size */
+ if (error) printf("Set_Char_Size Error! %d\n", error);
+
+ slot = face->glyph;
+ pen.x = 0;
+ pen.y = 0;
+ for ( n = 0; n < num_chars; n++ )
+ {
+ /* set transformation */
+ FT_Set_Transform( face, 0, &pen );
+
+ /* load glyph image into the slot (erase previous one) */
+ glyphIndex = FT_Get_Char_Index(face, text[n]);
+
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Glyph(face, glyphIndex, FT_LOAD_DEFAULT);
+ if(error) printf("FT_Load_Glyph Error! %d\n", error);
+
+ error = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
+ if(error) printf("FT_Render_Glyph Error! %d\n", error);
+
+ /* now, draw to our target surface (convert position) */
+ draw_bitmap(&slot->bitmap,
+ slot->bitmap_left,
+ target_height - slot->bitmap_top );
+
+ /* increment pen position */
+ pen.x += slot->advance.x;
+ pen.y += slot->advance.y;
+ }
+
+ show_image();
+
+ FT_Done_Face ( face );
+ FT_Done_FreeType( library );
+
+ return 0;
+}
+
+/* EOF */
diff --git a/tests/freetype/ref_2.txt b/tests/freetype/ref_2.txt
new file mode 100644
index 00000000..c15bb415
--- /dev/null
+++ b/tests/freetype/ref_2.txt
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+****+ +***** +****
+****+ +*****+ +****
++**** ******+ ****+
++**** ******* ****+
++****+ +***+*** +****
+ ****+ +***+***+ +***+
+ +***+ **** ***+ ****+
+ +**** ***+ +*** ****+
+ +**** +***+ +*** +****
+ ****++*** +***++***+
+ +***+**** ***++***+
+ +***+***+ +*******+
+ *******+ +*******
+ ******* +******+
+ +*****+ ******+
+ +*****+ +*****
+ *****+ +*****
+Non-0s: 285
diff --git a/tests/freetype/ref_3.txt b/tests/freetype/ref_3.txt
new file mode 100644
index 00000000..2b121eb7
--- /dev/null
+++ b/tests/freetype/ref_3.txt
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+***** ***** ****
+***** ****** *****
+***** ******* *****
+***** ******* ****
+ ***** ******* ****
+ ***** *** **** *****
+ ***** **** **** ****
+ **** **** **** ****
+ ***** **** **** ****
+ ***** **** ***** ****
+ ***** **** **** ****
+ **** **** **** ****
+ **** **** **** ****
+ ***** *** **** ****
+ **** **** **** ****
+ **** **** **** ****
+ **** **** **** ***
+ ******* ********
+ ******* *******
+ ******* *******
+ ******* ******
+ ***** *****
+Non-0s: 342
diff --git a/tests/freetype/ref_4.txt b/tests/freetype/ref_4.txt
new file mode 100644
index 00000000..e8124c1d
--- /dev/null
+++ b/tests/freetype/ref_4.txt
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ****** ******
+ ********** **********
+ ************ ************
+ ***** ***** ***** *****
+ **** **** **** ****
+ **** *** ****
+ **** **** ****
+ **************** ***********
+ **************** *************
+ **************** **************
+ **** ***** ****
+ **** **** ****
+ **** **** **** *****
+ ***** **** ***** ******
+ ************* ********** *****
+ *********** ********* *****
+ ******* ***** ****
+Non-0s: 332
diff --git a/tests/gears.png b/tests/gears.png
new file mode 100644
index 00000000..ffb855c4
--- /dev/null
+++ b/tests/gears.png
Binary files differ
diff --git a/tests/gl/LICENSE.TXT b/tests/gl/LICENSE.TXT
deleted file mode 100644
index 45e1d8ad..00000000
--- a/tests/gl/LICENSE.TXT
+++ /dev/null
@@ -1,11 +0,0 @@
-THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
-AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
-
-THE ORIGINAL AUTHOR IS KYLE FOLEY.
-
-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
-RESULTING FROM THE USE, MODIFICATION, OR
-REDISTRIBUTION OF THIS SOFTWARE.
diff --git a/tests/gl/sdl_ogl.c b/tests/gl/sdl_ogl.c
deleted file mode 100644
index 6f81c7ff..00000000
--- a/tests/gl/sdl_ogl.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*******************************************************************
- * *
- * Using SDL With OpenGL *
- * *
- * Tutorial by Kyle Foley (sdw) *
- * *
- * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
- * *
- *******************************************************************/
-
-/*
- Combined with opengl.org tutorial #2,
- http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29
-
- Build with
-
- gcc sdl_ogl.c -lSDL -lGL
-
- g++ will fail!
-
- Or, to JS:
-
- ~/Dev/emscripten/tools/emmaken.py sdl_ogl.c -o sdl_ogl.o
- ~/Dev/emscripten/emscripten.py sdl_ogl.o > sdl_ogl.js
-*/
-
-#include "SDL/SDL.h"
-#include "SDL/SDL_opengl.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-char* filetobuf(char *file)
-{
- FILE *fptr;
- long length;
- char *buf;
-
- fptr = fopen(file, "r"); /* Open file for reading */
- if (!fptr) /* Return NULL on failure */
- return NULL;
- fseek(fptr, 0, SEEK_END); /* Seek to the end of the file */
- length = ftell(fptr); /* Find out how many bytes into the file we are */
- buf = (char*)malloc(length+1); /* Allocate a buffer for the entire length of the file and a null terminator */
- fseek(fptr, 0, SEEK_SET); /* Go back to the beginning of the file */
- fread(buf, length, 1, fptr); /* Read the contents of the file in to the buffer */
- fclose(fptr); /* Close the file */
- buf[length] = 0; /* Null terminator */
-
- return buf; /* Return the buffer */
-}
-
-void drawscene()
-{
- int i; /* Simple iterator */
- GLuint vao, vbo[2]; /* Create handles for our Vertex Array Object and two Vertex Buffer Objects */
-
- /* We're going to create a simple diamond made from lines */
- const GLfloat diamond[4][2] = {
- { 0.0, 1.0 }, /* Top point */
- { 1.0, 0.0 }, /* Right point */
- { 0.0, -1.0 }, /* Bottom point */
- { -1.0, 0.0 } }; /* Left point */
-
- const GLfloat colors[4][3] = {
- { 1.0, 0.0, 0.0 }, /* Red */
- { 0.0, 1.0, 0.0 }, /* Green */
- { 0.0, 0.0, 1.0 }, /* Blue */
- { 1.0, 1.0, 1.0 } }; /* White */
-
- /* These pointers will receive the contents of our shader source code files */
- GLchar *vertexsource, *fragmentsource;
-
- /* These are handles used to reference the shaders */
- GLuint vertexshader, fragmentshader;
-
- /* This is a handle to the shader program */
- GLuint shaderprogram;
-
- /* Allocate and assign a Vertex Array Object to our handle */
- glGenVertexArrays(1, &vao);
-
- /* Bind our Vertex Array Object as the current used object */
- glBindVertexArray(vao);
-
- /* Allocate and assign two Vertex Buffer Objects to our handle */
- glGenBuffers(2, vbo);
-
- /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */
- glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
-
- /* Copy the vertex data from diamond to our buffer */
- /* 8 * sizeof(GLfloat) is the size of the diamond array, since it contains 8 GLfloat values */
- glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW);
-
- /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */
- glVertexAttribPointer((GLuint)0, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
- /* Enable attribute index 0 as being used */
- glEnableVertexAttribArray(0);
-
- /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */
- glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
-
- /* Copy the color data from colors to our buffer */
- /* 12 * sizeof(GLfloat) is the size of the colors array, since it contains 12 GLfloat values */
- glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
-
- /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */
- glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
-
- /* Enable attribute index 1 as being used */
- glEnableVertexAttribArray(1);
-
- /* Read our shaders into the appropriate buffers */
- vertexsource = filetobuf("tutorial2.vert");
- fragmentsource = filetobuf("tutorial2.frag");
-
- /* Assign our handles a "name" to new shader objects */
- vertexshader = glCreateShader(GL_VERTEX_SHADER);
- fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
-
- /* Associate the source code buffers with each handle */
- glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
- glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
-
- /* Compile our shader objects */
- glCompileShader(vertexshader);
- glCompileShader(fragmentshader);
-
- /* Assign our program handle a "name" */
- shaderprogram = glCreateProgram();
-
- /* Attach our shaders to our program */
- glAttachShader(shaderprogram, vertexshader);
- glAttachShader(shaderprogram, fragmentshader);
-
- /* Bind attribute index 0 (coordinates) to in_Position and attribute index 1 (color) to in_Color */
- glBindAttribLocation(shaderprogram, 0, "in_Position");
- glBindAttribLocation(shaderprogram, 1, "in_Color");
-
- /* Link our program, and set it as being actively used */
- glLinkProgram(shaderprogram);
- glUseProgram(shaderprogram);
-
- /* Loop our display increasing the number of shown vertexes each time.
- * Start with 2 vertexes (a line) and increase to 3 (a triangle) and 4 (a diamond) */
- for (i=4; i <= 4; i++)
- {
- /* Make our background black */
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */
- glDrawArrays(GL_LINE_LOOP, 0, i);
-
- /* Swap our buffers to make our changes visible */
- SDL_GL_SwapBuffers();
-
- /* Sleep for 2 seconds */
- SDL_Delay(2000);
- }
-
- /* Cleanup all the things we bound and allocated */
- glUseProgram(0);
- glDisableVertexAttribArray(0);
- glDisableVertexAttribArray(1);
- glDetachShader(shaderprogram, vertexshader);
- glDetachShader(shaderprogram, fragmentshader);
- glDeleteProgram(shaderprogram);
- glDeleteShader(vertexshader);
- glDeleteShader(fragmentshader);
- glDeleteBuffers(2, vbo);
- glDeleteVertexArrays(1, &vao);
- free(vertexsource);
- free(fragmentsource);
-}
-
-int main(int argc, char *argv[])
-{
- SDL_Surface *screen;
-
- // Slightly different SDL initialization
- if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
- printf("Unable to initialize SDL: %s\n", SDL_GetError());
- return 1;
- }
-
- SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
-
- screen = SDL_SetVideoMode( 512, 384, 32, SDL_OPENGL); // *changed*
- if ( !screen ) {
- printf("Unable to set video mode: %s\n", SDL_GetError());
- return 1;
- }
-
- drawscene();
-
- SDL_Quit();
-
- return 0;
-}
diff --git a/tests/gl/tutorial2.frag b/tests/gl/tutorial2.frag
deleted file mode 100644
index faa30eaf..00000000
--- a/tests/gl/tutorial2.frag
+++ /dev/null
@@ -1,11 +0,0 @@
-#version 150
-// It was expressed that some drivers required this next line to function properly
-precision highp float;
-
-in vec3 ex_Color;
-out vec4 gl_FragColor;
-
-void main(void) {
- // Pass through our original color with full opacity.
- gl_FragColor = vec4(ex_Color,1.0);
-}
diff --git a/tests/gl/tutorial2.vert b/tests/gl/tutorial2.vert
deleted file mode 100644
index d9de08e3..00000000
--- a/tests/gl/tutorial2.vert
+++ /dev/null
@@ -1,19 +0,0 @@
-#version 150
-// in_Position was bound to attribute index 0 and in_Color was bound to attribute index 1
-in vec2 in_Position;
-in vec3 in_Color;
-
-// We output the ex_Color variable to the next shader in the chain
-out vec3 ex_Color;
-void main(void) {
- // Since we are using flat lines, our input only had two points: x and y.
- // Set the Z coordinate to 0 and W coordinate to 1
-
- gl_Position = vec4(in_Position.x, in_Position.y, 0.0, 1.0);
-
- // GLSL allows shorthand use of vectors too, the following is also valid:
- // gl_Position = vec4(in_Position, 0.0, 1.0);
- // We're simply passing the color through unmodified
-
- ex_Color = in_Color;
-}
diff --git a/tests/gl_matrix_identity.c b/tests/gl_matrix_identity.c
new file mode 100644
index 00000000..98b1c21f
--- /dev/null
+++ b/tests/gl_matrix_identity.c
@@ -0,0 +1,129 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ GLubyte textureData[] = { 0x7f, 0, 0,
+ 0, 0xff, 0,
+ 0x7f, 0, 0,
+ 0, 0xff, 0};
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, textureData );
+
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glClearColor( 0, 0, 0.5, 1.0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ glColor4f(0.8, 0.8, 0.8, 1);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ const int kRowSize = 20;
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ float fbuf[] = {0, 1, 0, 0, 1,
+ 1, 1, 0, 1, 1,
+ 1, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0};
+ glBufferData(GL_ARRAY_BUFFER, sizeof(fbuf) * sizeof(float), fbuf, GL_STATIC_DRAW);
+
+ glTexCoordPointer(2, GL_FLOAT, kRowSize, (GLvoid*)(3*4));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glVertexPointer(3, GL_FLOAT, kRowSize, 0);
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ // END
+
+ SDL_GL_SwapBuffers();
+
+ verify();
+
+#if !EMSCRIPTEN
+ SDL_Delay(1500);
+#endif
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/gl_ps.c b/tests/gl_ps.c
new file mode 100644
index 00000000..81579c1d
--- /dev/null
+++ b/tests/gl_ps.c
@@ -0,0 +1,230 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void shaders() {
+#if USE_GLEW
+ glewInit();
+#endif
+
+ GLint ok;
+
+ const char *vertexShader = "void main(void) \n"
+ "{ \n"
+ " gl_Position = ftransform(); \n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
+ " gl_FrontColor = gl_Color; \n"
+ "} \n";
+ const char *fragmentShader = "uniform sampler2D tex0; \n"
+ "void main(void) \n"
+ "{ \n"
+ " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n"
+ "} \n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ {
+ // Also, check getting the error log
+ const char *fakeVertexShader = "atbute ve4 blarg; ### AAA\n";
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &fakeVertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(!ok);
+ GLint infoLen = 0;
+ glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &infoLen);
+ assert(infoLen > 1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ shaders();
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250,
+ 0, 0, 100, 300,
+ 1, 0, 300, 300,
+ 1, 1, 300, 400,
+ 0, 1, 100, 400 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 12);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/gl_ps.png b/tests/gl_ps.png
new file mode 100644
index 00000000..185f7166
--- /dev/null
+++ b/tests/gl_ps.png
Binary files differ
diff --git a/tests/glbook/CH02_HelloTriangle.png b/tests/glbook/CH02_HelloTriangle.png
new file mode 100644
index 00000000..d6351e2a
--- /dev/null
+++ b/tests/glbook/CH02_HelloTriangle.png
Binary files differ
diff --git a/tests/glbook/CH08_SimpleVertexShader.png b/tests/glbook/CH08_SimpleVertexShader.png
new file mode 100644
index 00000000..84b276fd
--- /dev/null
+++ b/tests/glbook/CH08_SimpleVertexShader.png
Binary files differ
diff --git a/tests/glbook/CH09_SimpleTexture2D.png b/tests/glbook/CH09_SimpleTexture2D.png
new file mode 100644
index 00000000..e33539e9
--- /dev/null
+++ b/tests/glbook/CH09_SimpleTexture2D.png
Binary files differ
diff --git a/tests/glbook/CH09_TextureCubemap.png b/tests/glbook/CH09_TextureCubemap.png
new file mode 100644
index 00000000..b592b047
--- /dev/null
+++ b/tests/glbook/CH09_TextureCubemap.png
Binary files differ
diff --git a/tests/glbook/CH09_TextureWrap.png b/tests/glbook/CH09_TextureWrap.png
new file mode 100644
index 00000000..3367e254
--- /dev/null
+++ b/tests/glbook/CH09_TextureWrap.png
Binary files differ
diff --git a/tests/glbook/CH10_MultiTexture.png b/tests/glbook/CH10_MultiTexture.png
new file mode 100644
index 00000000..8e006eb3
--- /dev/null
+++ b/tests/glbook/CH10_MultiTexture.png
Binary files differ
diff --git a/tests/glbook/CH13_ParticleSystem.png b/tests/glbook/CH13_ParticleSystem.png
new file mode 100644
index 00000000..39b9af0a
--- /dev/null
+++ b/tests/glbook/CH13_ParticleSystem.png
Binary files differ
diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c
new file mode 100644
index 00000000..61bda608
--- /dev/null
+++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c
@@ -0,0 +1,227 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MultiTexture.c
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler locations
+ GLint baseMapLoc;
+ GLint lightMapLoc;
+
+ // Texture handle
+ GLuint baseMapTexId;
+ GLuint lightMapTexId;
+
+ GLuint vertexObject, indexObject;
+
+} UserData;
+
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform sampler2D s_lightMap; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor; \n"
+ " vec4 lightColor; \n"
+ " \n"
+ " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
+ " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
+ " gl_FragColor = baseColor * (lightColor + 0.25); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
+ userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
+
+ // Load the textures
+ userData->baseMapTexId = LoadTexture ( "basemap.tga" );
+ userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
+
+ if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
+ return FALSE;
+
+ GLfloat vVertices[] = { -0.5, 0.5, 0.0, // Position 0
+ 0.0, 0.0, // TexCoord 0
+ -0.5, -0.5, 0.0, // Position 1
+ 0.0, 1.0, // TexCoord 1
+ 0.5, -0.5, 0.0, // Position 2
+ 1.0, 1.0, // TexCoord 2
+ 0.5, 0.5, 0.0, // Position 3
+ 1.0, 0.0 // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData ( GL_ARRAY_BUFFER, 5 * 4 * 4, vVertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indexObject);
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0, 0.0, 0.0, 1.0 );
+
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), 0 );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), 3 * sizeof(GLfloat) );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the base map
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ glUniform1i ( userData->baseMapLoc, 0 );
+
+ // Bind the light map
+ glActiveTexture ( GL_TEXTURE1 );
+ glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ glUniform1i ( userData->lightMapLoc, 1 );
+
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->baseMapTexId );
+ glDeleteTextures ( 1, &userData->lightMapTexId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c
new file mode 100644
index 00000000..5324ad92
--- /dev/null
+++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture_orig.c
@@ -0,0 +1,213 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MultiTexture.c
+//
+// This is an example that draws a quad with a basemap and
+// lightmap to demonstrate multitexturing.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler locations
+ GLint baseMapLoc;
+ GLint lightMapLoc;
+
+ // Texture handle
+ GLuint baseMapTexId;
+ GLuint lightMapTexId;
+
+} UserData;
+
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform sampler2D s_lightMap; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor; \n"
+ " vec4 lightColor; \n"
+ " \n"
+ " baseColor = texture2D( s_baseMap, v_texCoord ); \n"
+ " lightColor = texture2D( s_lightMap, v_texCoord ); \n"
+ " gl_FragColor = baseColor * (lightColor + 0.25); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->baseMapLoc = glGetUniformLocation ( userData->programObject, "s_baseMap" );
+ userData->lightMapLoc = glGetUniformLocation ( userData->programObject, "s_lightMap" );
+
+ // Load the textures
+ userData->baseMapTexId = LoadTexture ( "basemap.tga" );
+ userData->lightMapTexId = LoadTexture ( "lightmap.tga" );
+
+ if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
+ return FALSE;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the base map
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->baseMapTexId );
+
+ // Set the base map sampler to texture unit to 0
+ glUniform1i ( userData->baseMapLoc, 0 );
+
+ // Bind the light map
+ glActiveTexture ( GL_TEXTURE1 );
+ glBindTexture ( GL_TEXTURE_2D, userData->lightMapTexId );
+
+ // Set the light map sampler to texture unit 1
+ glUniform1i ( userData->lightMapLoc, 1 );
+
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->baseMapTexId );
+ glDeleteTextures ( 1, &userData->lightMapTexId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MultiTexture", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_10/MultiTexture/basemap.tga b/tests/glbook/Chapter_10/MultiTexture/basemap.tga
new file mode 100644
index 00000000..8acafae2
--- /dev/null
+++ b/tests/glbook/Chapter_10/MultiTexture/basemap.tga
Binary files differ
diff --git a/tests/glbook/Chapter_10/MultiTexture/lightmap.tga b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga
new file mode 100644
index 00000000..d95b2628
--- /dev/null
+++ b/tests/glbook/Chapter_10/MultiTexture/lightmap.tga
Binary files differ
diff --git a/tests/glbook/Chapter_11/Multisample/Multisample.c b/tests/glbook/Chapter_11/Multisample/Multisample.c
new file mode 100644
index 00000000..fd064c70
--- /dev/null
+++ b/tests/glbook/Chapter_11/Multisample/Multisample.c
@@ -0,0 +1,302 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Multisample.c
+//
+// This example shows various multi-sampling
+// operations.
+//
+#include <stdlib.h>
+#include <stdio.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint colorLoc;
+
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = u_color; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the sampler location
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+
+ // Set the clear color
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Set the stencil clear value
+ glClearStencil ( 0x1 );
+
+ // Set the depth clear value
+ glClearDepthf( 0.75f );
+
+ // Enable the depth and stencil tests
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_STENCIL_TEST );
+
+ return TRUE;
+}
+
+///
+// Initialize the stencil buffer values, and then use those
+// values to control rendering
+//
+void Draw ( ESContext *esContext )
+{
+ int i;
+
+ UserData *userData = esContext->userData;
+
+ GLfloat vVertices[] = {
+ -0.75f, 0.25f, 0.50f, // Quad #0
+ -0.25f, 0.25f, 0.50f,
+ -0.25f, 0.75f, 0.50f,
+ -0.75f, 0.75f, 0.50f,
+ 0.25f, 0.25f, 0.90f, // Quad #1
+ 0.75f, 0.25f, 0.90f,
+ 0.75f, 0.75f, 0.90f,
+ 0.25f, 0.75f, 0.90f,
+ -0.75f, -0.75f, 0.50f, // Quad #2
+ -0.25f, -0.75f, 0.50f,
+ -0.25f, -0.25f, 0.50f,
+ -0.75f, -0.25f, 0.50f,
+ 0.25f, -0.75f, 0.50f, // Quad #3
+ 0.75f, -0.75f, 0.50f,
+ 0.75f, -0.25f, 0.50f,
+ 0.25f, -0.25f, 0.50f,
+ -1.00f, -1.00f, 0.00f, // Big Quad
+ 1.00f, -1.00f, 0.00f,
+ 1.00f, 1.00f, 0.00f,
+ -1.00f, 1.00f, 0.00f
+ };
+
+ GLubyte indices[][6] = {
+ { 0, 1, 2, 0, 2, 3 }, // Quad #0
+ { 4, 5, 6, 4, 6, 7 }, // Quad #1
+ { 8, 9, 10, 8, 10, 11 }, // Quad #2
+ { 12, 13, 14, 12, 14, 15 }, // Quad #3
+ { 16, 17, 18, 16, 18, 19 } // Big Quad
+ };
+
+#define NumTests 4
+ GLfloat colors[NumTests][4] = {
+ { 1.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f },
+ { 1.0f, 1.0f, 0.0f, 0.0f }
+ };
+
+ GLint numStencilBits;
+ GLuint stencilValues[NumTests] = {
+ 0x7, // Result of test 0
+ 0x0, // Result of test 1
+ 0x2, // Result of test 2
+ 0xff // Result of test 3. We need to fill this
+ // value in a run-time
+ };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color, depth, and stencil buffers. At this
+ // point, the stencil buffer will be 0x1 for all pixels
+ glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, vVertices );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+ // Test 0:
+ //
+ // Initialize upper-left region. In this case, the
+ // stencil-buffer values will be replaced because the
+ // stencil test for the rendered pixels will fail the
+ // stencil test, which is
+ //
+ // ref mask stencil mask
+ // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
+ //
+ // The value in the stencil buffer for these pixels will
+ // be 0x7.
+ //
+ glStencilFunc( GL_LESS, 0x7, 0x3 );
+ glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
+
+ // Test 1:
+ //
+ // Initialize the upper-right region. Here, we'll decrement
+ // the stencil-buffer values where the stencil test passes
+ // but the depth test fails. The stencil test is
+ //
+ // ref mask stencil mask
+ // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
+ //
+ // but where the geometry fails the depth test. The
+ // stencil values for these pixels will be 0x0.
+ //
+ glStencilFunc( GL_GREATER, 0x3, 0x3 );
+ glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
+
+ // Test 2:
+ //
+ // Initialize the lower-left region. Here we'll increment
+ // (with saturation) the stencil value where both the
+ // stencil and depth tests pass. The stencil test for
+ // these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
+ //
+ // The stencil values for these pixels will be 0x2.
+ //
+ glStencilFunc( GL_EQUAL, 0x1, 0x3 );
+ glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
+
+ // Test 3:
+ //
+ // Finally, initialize the lower-right region. We'll invert
+ // the stencil value where the stencil tests fails. The
+ // stencil test for these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
+ //
+ // The stencil value here will be set to ~((2^s-1) & 0x1),
+ // (with the 0x1 being from the stencil clear value),
+ // where 's' is the number of bits in the stencil buffer
+ //
+ glStencilFunc( GL_EQUAL, 0x2, 0x1 );
+ glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
+
+ // Since we don't know at compile time how many stecil bits are present,
+ // we'll query, and update the value correct value in the
+ // stencilValues arrays for the fourth tests. We'll use this value
+ // later in rendering.
+ glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
+
+ stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
+
+ // Use the stencil buffer for controlling where rendering will
+ // occur. We diable writing to the stencil buffer so we
+ // can test against them without modifying the values we
+ // generated.
+ glStencilMask( 0x0 );
+
+ for ( i = 0; i < NumTests; ++i )
+ {
+ glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
+ glUniform4fv( userData->colorLoc, 1, colors[i] );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
+ }
+
+ //eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+///
+// Handle keyboard input
+//
+void Key ( ESContext *esContext, unsigned char key, int x, int y)
+{
+ switch ( key )
+ {
+ case 'm':
+ printf( "Saw an 'm'\n" );
+ break;
+
+ case 'a':
+ printf( "Saw an 'a'\n" );
+ break;
+
+ case '1':
+ printf( "Saw a '1'\n" );
+ break;
+
+ case 033: // ASCII Escape Key
+ ShutDown( esContext );
+ exit( 0 );
+ break;
+ }
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Multi-sampling", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterKeyFunc( &esContext, Key );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c
new file mode 100644
index 00000000..b3a0486d
--- /dev/null
+++ b/tests/glbook/Chapter_11/Stencil_Test/Stencil_Test.c
@@ -0,0 +1,273 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Stencil_Test.c
+//
+// This example shows various stencil buffer
+// operations.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint colorLoc;
+
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = u_color; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the sampler location
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+
+ // Set the clear color
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Set the stencil clear value
+ glClearStencil ( 0x1 );
+
+ // Set the depth clear value
+ glClearDepthf( 0.75f );
+
+ // Enable the depth and stencil tests
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_STENCIL_TEST );
+
+ return TRUE;
+}
+
+///
+// Initialize the stencil buffer values, and then use those
+// values to control rendering
+//
+void Draw ( ESContext *esContext )
+{
+ int i;
+
+ UserData *userData = esContext->userData;
+
+ GLfloat vVertices[] = {
+ -0.75f, 0.25f, 0.50f, // Quad #0
+ -0.25f, 0.25f, 0.50f,
+ -0.25f, 0.75f, 0.50f,
+ -0.75f, 0.75f, 0.50f,
+ 0.25f, 0.25f, 0.90f, // Quad #1
+ 0.75f, 0.25f, 0.90f,
+ 0.75f, 0.75f, 0.90f,
+ 0.25f, 0.75f, 0.90f,
+ -0.75f, -0.75f, 0.50f, // Quad #2
+ -0.25f, -0.75f, 0.50f,
+ -0.25f, -0.25f, 0.50f,
+ -0.75f, -0.25f, 0.50f,
+ 0.25f, -0.75f, 0.50f, // Quad #3
+ 0.75f, -0.75f, 0.50f,
+ 0.75f, -0.25f, 0.50f,
+ 0.25f, -0.25f, 0.50f,
+ -1.00f, -1.00f, 0.00f, // Big Quad
+ 1.00f, -1.00f, 0.00f,
+ 1.00f, 1.00f, 0.00f,
+ -1.00f, 1.00f, 0.00f
+ };
+
+ GLubyte indices[][6] = {
+ { 0, 1, 2, 0, 2, 3 }, // Quad #0
+ { 4, 5, 6, 4, 6, 7 }, // Quad #1
+ { 8, 9, 10, 8, 10, 11 }, // Quad #2
+ { 12, 13, 14, 12, 14, 15 }, // Quad #3
+ { 16, 17, 18, 16, 18, 19 } // Big Quad
+ };
+
+#define NumTests 4
+ GLfloat colors[NumTests][4] = {
+ { 1.0f, 0.0f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f, 1.0f },
+ { 0.0f, 0.0f, 1.0f, 1.0f },
+ { 1.0f, 1.0f, 0.0f, 0.0f }
+ };
+
+ GLint numStencilBits;
+ GLuint stencilValues[NumTests] = {
+ 0x7, // Result of test 0
+ 0x0, // Result of test 1
+ 0x2, // Result of test 2
+ 0xff // Result of test 3. We need to fill this
+ // value in a run-time
+ };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color, depth, and stencil buffers. At this
+ // point, the stencil buffer will be 0x1 for all pixels
+ glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, vVertices );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+ // Test 0:
+ //
+ // Initialize upper-left region. In this case, the
+ // stencil-buffer values will be replaced because the
+ // stencil test for the rendered pixels will fail the
+ // stencil test, which is
+ //
+ // ref mask stencil mask
+ // ( 0x7 & 0x3 ) < ( 0x1 & 0x7 )
+ //
+ // The value in the stencil buffer for these pixels will
+ // be 0x7.
+ //
+ glStencilFunc( GL_LESS, 0x7, 0x3 );
+ glStencilOp( GL_REPLACE, GL_DECR, GL_DECR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[0] );
+
+ // Test 1:
+ //
+ // Initialize the upper-right region. Here, we'll decrement
+ // the stencil-buffer values where the stencil test passes
+ // but the depth test fails. The stencil test is
+ //
+ // ref mask stencil mask
+ // ( 0x3 & 0x3 ) > ( 0x1 & 0x3 )
+ //
+ // but where the geometry fails the depth test. The
+ // stencil values for these pixels will be 0x0.
+ //
+ glStencilFunc( GL_GREATER, 0x3, 0x3 );
+ glStencilOp( GL_KEEP, GL_DECR, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[1] );
+
+ // Test 2:
+ //
+ // Initialize the lower-left region. Here we'll increment
+ // (with saturation) the stencil value where both the
+ // stencil and depth tests pass. The stencil test for
+ // these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x1 & 0x3 ) == ( 0x1 & 0x3 )
+ //
+ // The stencil values for these pixels will be 0x2.
+ //
+ glStencilFunc( GL_EQUAL, 0x1, 0x3 );
+ glStencilOp( GL_KEEP, GL_INCR, GL_INCR );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[2] );
+
+ // Test 3:
+ //
+ // Finally, initialize the lower-right region. We'll invert
+ // the stencil value where the stencil tests fails. The
+ // stencil test for these pixels will be
+ //
+ // ref mask stencil mask
+ // ( 0x2 & 0x1 ) == ( 0x1 & 0x1 )
+ //
+ // The stencil value here will be set to ~((2^s-1) & 0x1),
+ // (with the 0x1 being from the stencil clear value),
+ // where 's' is the number of bits in the stencil buffer
+ //
+ glStencilFunc( GL_EQUAL, 0x2, 0x1 );
+ glStencilOp( GL_INVERT, GL_KEEP, GL_KEEP );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[3] );
+
+ // Since we don't know at compile time how many stecil bits are present,
+ // we'll query, and update the value correct value in the
+ // stencilValues arrays for the fourth tests. We'll use this value
+ // later in rendering.
+ glGetIntegerv( GL_STENCIL_BITS, &numStencilBits );
+
+ stencilValues[3] = ~(((1 << numStencilBits) - 1) & 0x1) & 0xff;
+
+ // Use the stencil buffer for controlling where rendering will
+ // occur. We diable writing to the stencil buffer so we
+ // can test against them without modifying the values we
+ // generated.
+ glStencilMask( 0x0 );
+
+ for ( i = 0; i < NumTests; ++i )
+ {
+ glStencilFunc( GL_EQUAL, stencilValues[i], 0xff );
+ glUniform4fv( userData->colorLoc, 1, colors[i] );
+ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices[4] );
+ }
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Stencil Test", 320, 240,
+ ES_WINDOW_RGB | ES_WINDOW_DEPTH | ES_WINDOW_STENCIL );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c
new file mode 100644
index 00000000..f48e871a
--- /dev/null
+++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c
@@ -0,0 +1,310 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ParticleSystem.c
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+#include <stdlib.h>
+#include <math.h>
+#include "esUtil.h"
+
+#define NUM_PARTICLES 2000
+#define PARTICLE_SIZE 7
+
+int randomTemp = 8765;
+float myrandom() {
+ int curr = randomTemp;
+ randomTemp = (1140671485 * randomTemp + 12820163) % 4294967296;
+ return ((float)curr) / 4294967296;
+}
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint lifetimeLoc;
+ GLint startPositionLoc;
+ GLint endPositionLoc;
+
+ // Uniform location
+ GLint timeLoc;
+ GLint colorLoc;
+ GLint centerPositionLoc;
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Particle vertex data
+ GLfloat particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ // Current time
+ float time;
+
+ GLuint vertexObject;
+} UserData;
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ int i;
+
+ GLbyte vShaderStr[] =
+ "uniform float u_time; \n"
+ "uniform vec3 u_centerPosition; \n"
+ "attribute float a_lifetime; \n"
+ "attribute vec3 a_startPosition; \n"
+ "attribute vec3 a_endPosition; \n"
+ "varying float v_lifetime; \n"
+ "void main() \n"
+ "{ \n"
+ " if ( u_time <= a_lifetime ) \n"
+ " { \n"
+ " gl_Position.xyz = a_startPosition + \n"
+ " (u_time * a_endPosition); \n"
+ " gl_Position.xyz += u_centerPosition; \n"
+ " gl_Position.w = 1.0; \n"
+ " } \n"
+ " else \n"
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
+ "}";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "varying float v_lifetime; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor; \n"
+ " texColor = texture2D( s_texture, gl_PointCoord ); \n"
+ " gl_FragColor = vec4( u_color ) * texColor; \n"
+ " gl_FragColor.a *= v_lifetime; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
+ userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
+ userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
+
+ // Get the uniform locations
+ userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
+ userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
+
+ // Fill in particle data array
+ for ( i = 0; i < NUM_PARTICLES; i++ )
+ {
+ GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE];
+
+ // Lifetime of particle
+ (*particleData++) = myrandom();
+
+ // End position of particle
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+
+ // Start position of particle
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ }
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES * PARTICLE_SIZE * 4, userData->particleData, GL_STATIC_DRAW );
+
+ // Initialize time to cause reset on first update
+ userData->time = 1.0f;
+
+ userData->textureId = LoadTexture ( "smoke.tga" );
+ if ( userData->textureId <= 0 )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+///
+// Update time-based variables
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+// deltaTime = 0.1;
+ UserData *userData = esContext->userData;
+
+ userData->time += deltaTime;
+
+ if ( userData->time >= 1.0f )
+ {
+ float centerPos[3];
+ float color[4];
+
+ userData->time = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = myrandom() - 0.5f;
+ centerPos[1] = myrandom() - 0.5f;
+ centerPos[2] = myrandom() - 0.5f;
+
+ glUniform3fv ( userData->centerPositionLoc, 1, &centerPos[0] );
+
+ // Random color
+ color[0] = myrandom() * 0.5 + 0.5f;
+ color[1] = myrandom() * 0.5 + 0.5f;
+ color[2] = myrandom() * 0.5 + 0.5f;
+ color[3] = 1.0;
+
+ glUniform4fv ( userData->colorLoc, 1, &color[0] );
+ }
+
+ // Load uniform time variable
+ glUniform1f ( userData->timeLoc, userData->time );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex attributes
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 0 );
+
+ glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 4 );
+
+ glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ 4 * 4 );
+
+
+ glEnableVertexAttribArray ( userData->lifetimeLoc );
+ glEnableVertexAttribArray ( userData->endPositionLoc );
+ glEnableVertexAttribArray ( userData->startPositionLoc );
+ // Blend particles
+ glEnable ( GL_BLEND );
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+ //glEnable ( GL_TEXTURE_2D );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ Update ( esContext, 133 * 0.001125 );
+
+ glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "ParticleSystem", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+// esRegisterUpdateFunc ( &esContext, Update );
+
+ Draw (&esContext);
+ Draw (&esContext);
+ //esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c
new file mode 100644
index 00000000..378d05a7
--- /dev/null
+++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem_orig.c
@@ -0,0 +1,294 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ParticleSystem.c
+//
+// This is an example that demonstrates rendering a particle system
+// using a vertex shader and point sprites.
+//
+#include <stdlib.h>
+#include <math.h>
+#include "esUtil.h"
+
+#define NUM_PARTICLES 1000
+#define PARTICLE_SIZE 7
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint lifetimeLoc;
+ GLint startPositionLoc;
+ GLint endPositionLoc;
+
+ // Uniform location
+ GLint timeLoc;
+ GLint colorLoc;
+ GLint centerPositionLoc;
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Particle vertex data
+ float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+
+ // Current time
+ float time;
+
+} UserData;
+
+///
+// Load texture from disk
+//
+GLuint LoadTexture ( char *fileName )
+{
+ int width,
+ height;
+ char *buffer = esLoadTGA ( fileName, &width, &height );
+ GLuint texId;
+
+ if ( buffer == NULL )
+ {
+ esLogMessage ( "Error loading (%s) image.\n", fileName );
+ return 0;
+ }
+
+ glGenTextures ( 1, &texId );
+ glBindTexture ( GL_TEXTURE_2D, texId );
+
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ free ( buffer );
+
+ return texId;
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ int i;
+
+ GLbyte vShaderStr[] =
+ "uniform float u_time; \n"
+ "uniform vec3 u_centerPosition; \n"
+ "attribute float a_lifetime; \n"
+ "attribute vec3 a_startPosition; \n"
+ "attribute vec3 a_endPosition; \n"
+ "varying float v_lifetime; \n"
+ "void main() \n"
+ "{ \n"
+ " if ( u_time <= a_lifetime ) \n"
+ " { \n"
+ " gl_Position.xyz = a_startPosition + \n"
+ " (u_time * a_endPosition); \n"
+ " gl_Position.xyz += u_centerPosition; \n"
+ " gl_Position.w = 1.0; \n"
+ " } \n"
+ " else \n"
+ " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
+ " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
+ " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
+ " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
+ "}";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "uniform vec4 u_color; \n"
+ "varying float v_lifetime; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor; \n"
+ " texColor = texture2D( s_texture, gl_PointCoord ); \n"
+ " gl_FragColor = vec4( u_color ) * texColor; \n"
+ " gl_FragColor.a *= v_lifetime; \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
+ userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
+ userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
+
+ // Get the uniform locations
+ userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
+ userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
+ userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+
+ // Fill in particle data array
+ srand ( 0 );
+ for ( i = 0; i < NUM_PARTICLES; i++ )
+ {
+ float *particleData = &userData->particleData[i * PARTICLE_SIZE];
+
+ // Lifetime of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
+
+ // End position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+
+ // Start position of particle
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+ (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
+
+ }
+
+ // Initialize time to cause reset on first update
+ userData->time = 1.0f;
+
+ userData->textureId = LoadTexture ( "smoke.tga" );
+ if ( userData->textureId <= 0 )
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+///
+// Update time-based variables
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+ UserData *userData = esContext->userData;
+
+ userData->time += deltaTime;
+
+ if ( userData->time >= 1.0f )
+ {
+ float centerPos[3];
+ float color[4];
+
+ userData->time = 0.0f;
+
+ // Pick a new start location and color
+ centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+
+ glUniform3fv ( userData->centerPositionLoc, 1, &centerPos[0] );
+
+ // Random color
+ color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
+ color[3] = 0.5;
+
+ glUniform4fv ( userData->colorLoc, 1, &color[0] );
+ }
+
+ // Load uniform time variable
+ glUniform1f ( userData->timeLoc, userData->time );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex attributes
+ glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ userData->particleData );
+
+ glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[1] );
+
+ glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
+ GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
+ &userData->particleData[4] );
+
+
+ glEnableVertexAttribArray ( userData->lifetimeLoc );
+ glEnableVertexAttribArray ( userData->endPositionLoc );
+ glEnableVertexAttribArray ( userData->startPositionLoc );
+ // Blend particles
+ glEnable ( GL_BLEND );
+ glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+ glEnable ( GL_TEXTURE_2D );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
+
+ eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+}
+
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterUpdateFunc ( &esContext, Update );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/smoke.tga b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga
new file mode 100644
index 00000000..06a0705c
--- /dev/null
+++ b/tests/glbook/Chapter_13/ParticleSystem/smoke.tga
Binary files differ
diff --git a/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c
new file mode 100644
index 00000000..af49c13c
--- /dev/null
+++ b/tests/glbook/Chapter_15/Hello_Triangle_KD/Hello_Triangle_KD.c
@@ -0,0 +1,306 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Hello_Triangle_KD.c
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader using OpenKODE.
+//
+#include <KD/kd.h>
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // EGL handles
+ EGLDisplay eglDisplay;
+ EGLContext eglContext;
+ EGLSurface eglSurface;
+
+} UserData;
+
+///
+// Create a shader object, load the shader source, and
+// compile the shader.
+//
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+///
+// Initialize the shader and program object
+//
+int Init ( UserData *userData )
+{
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Bind vPosition to attribute 0
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = kdMalloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ kdLogMessage ( infoLog );
+
+ kdFree ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return FALSE;
+ }
+
+ // Store the program object
+ userData->programObject = programObject;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( UserData *userData )
+{
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // Set the viewport
+ glViewport ( 0, 0, 320, 240 );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex data
+ glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
+ glEnableVertexAttribArray ( 0 );
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+
+ eglSwapBuffers ( userData->eglDisplay, userData->eglSurface );
+}
+
+
+///
+// InitEGLContext()
+//
+// Initialize an EGL rendering context and all associated elements
+//
+EGLBoolean InitEGLContext ( UserData *userData,
+ KDWindow *window,
+ EGLConfig config )
+{
+ EGLContext context;
+ EGLSurface surface;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get native window handle
+ EGLNativeWindowType hWnd;
+ if(kdRealizeWindow(window, &hWnd) != 0)
+ {
+ return EGL_FALSE;
+ }
+ surface = eglCreateWindowSurface(userData->eglDisplay, config, hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(userData->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(userData->eglDisplay, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ userData->eglContext = context;
+ userData->eglSurface = surface;
+
+ return EGL_TRUE;
+}
+
+///
+// kdMain()
+//
+// Main function for OpenKODE application
+//
+KDint kdMain ( KDint argc, const KDchar *const *argv )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, EGL_DONT_CARE,
+ EGL_NONE
+ };
+ EGLint majorVersion,
+ minorVersion;
+ UserData userData;
+ EGLint numConfigs;
+ EGLConfig config;
+ KDWindow *window = KD_NULL;
+
+ userData.eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
+
+ // Initialize EGL
+ if ( !eglInitialize(userData.eglDisplay, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(userData.eglDisplay, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(userData.eglDisplay, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+
+ // Use OpenKODE to create a Window
+ window = kdCreateWindow ( userData.eglDisplay, config, KD_NULL );
+ if( !window )
+ kdExit ( 0 );
+
+ if ( !InitEGLContext ( &userData, window, config ) )
+ kdExit ( 0 );
+
+ if ( !Init ( &userData ) )
+ kdExit ( 0 );
+
+ // Main Loop
+ while ( 1 )
+ {
+ // Wait for an event
+ const KDEvent *evt = kdWaitEvent ( 0 );
+ if ( evt )
+ {
+ // Exit app
+ if ( evt->type == KD_EVENT_WINDOW_CLOSE)
+ break;
+ }
+
+ // Draw frame
+ Draw ( &userData );
+ }
+
+ // EGL clean up
+ eglMakeCurrent ( 0, 0, 0, 0 );
+ eglDestroySurface ( userData.eglDisplay, userData.eglSurface );
+ eglDestroyContext ( userData.eglDisplay, userData.eglContext );
+
+ // Destroy the window
+ kdDestroyWindow(window);
+
+ return 0;
+}
diff --git a/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c
new file mode 100644
index 00000000..5d4e0bd9
--- /dev/null
+++ b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle.c
@@ -0,0 +1,200 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Hello_Triangle.c
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader. The purpose of this
+// example is to demonstrate the basic concepts of
+// OpenGL ES 2.0 rendering.
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+} UserData;
+
+///
+// Create a shader object, load the shader source, and
+// compile the shader.
+//
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Bind vPosition to attribute 0
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ esLogMessage ( "Error linking program:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return GL_FALSE;
+ }
+
+ // Store the program object
+ userData->programObject = programObject;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // No clientside arrays, so do this in a webgl-friendly manner
+ GLuint vertexPosObject;
+ glGenBuffers(1, &vertexPosObject);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
+ glBufferData(GL_ARRAY_BUFFER, 9*4, vVertices, GL_STATIC_DRAW);
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex data
+ glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
+ glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(0);
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+}
diff --git a/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c
new file mode 100644
index 00000000..fd4c506a
--- /dev/null
+++ b/tests/glbook/Chapter_2/Hello_Triangle/Hello_Triangle_orig.c
@@ -0,0 +1,193 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Hello_Triangle.c
+//
+// This is a simple example that draws a single triangle with
+// a minimal vertex/fragment shader. The purpose of this
+// example is to demonstrate the basic concepts of
+// OpenGL ES 2.0 rendering.
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+} UserData;
+
+///
+// Create a shader object, load the shader source, and
+// compile the shader.
+//
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Bind vPosition to attribute 0
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ esLogMessage ( "Error linking program:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return GL_FALSE;
+ }
+
+ // Store the program object
+ userData->programObject = programObject;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex data
+ glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
+ glEnableVertexAttribArray ( 0 );
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+}
diff --git a/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c
new file mode 100644
index 00000000..44380c18
--- /dev/null
+++ b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader.c
@@ -0,0 +1,209 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_VertexShader.c
+//
+// This is a simple example that draws a rotating cube in perspective
+// using a vertex shader to transform the object
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint mvpLoc;
+
+ // Vertex daata
+ GLfloat *vertices;
+ GLushort *indices;
+ int numIndices;
+
+ // Rotation angle
+ GLfloat angle;
+
+ // MVP matrix
+ ESMatrix mvpMatrix;
+
+ GLuint vertPosObject, indicesObject;
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "uniform mat4 u_mvpMatrix; \n"
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_mvpMatrix * a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the uniform locations
+ userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" );
+
+ // Generate the vertex data
+ userData->numIndices = esGenCube( 1.0, &userData->vertices,
+ NULL, NULL, &userData->indices );
+
+ // Starting rotation angle for the cube
+ userData->angle = 45.0f;
+
+ glGenBuffers(1, &userData->vertPosObject);
+ glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject);
+ glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat) * 3, userData->vertices, GL_STATIC_DRAW);
+
+ glGenBuffers(1, &userData->indicesObject);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, userData->numIndices * sizeof(GLushort), userData->indices, GL_STATIC_DRAW);
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+
+///
+// Update MVP matrix based on time
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+ UserData *userData = (UserData*) esContext->userData;
+ ESMatrix perspective;
+ ESMatrix modelview;
+ float aspect;
+
+ // Compute a rotation angle based on time to rotate the cube
+ userData->angle += ( deltaTime * 40.0f );
+ if( userData->angle >= 360.0f )
+ userData->angle -= 360.0f;
+
+ // Compute the window aspect ratio
+ aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;
+
+ // Generate a perspective matrix with a 60 degree FOV
+ esMatrixLoadIdentity( &perspective );
+ esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f );
+
+ // Generate a model view matrix to rotate/translate the cube
+ esMatrixLoadIdentity( &modelview );
+
+ // Translate away from the viewer
+ esTranslate( &modelview, 0.0, 0.0, -2.0 );
+
+ // Rotate the cube
+ esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 );
+
+ // Compute the final MVP by multiplying the
+ // modevleiw and perspective matrices together
+ esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject);
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, 0 );
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+
+ // Load the index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject);
+
+ // Load the MVP matrix
+ glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] );
+
+ // Draw the cube
+ glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_SHORT, 0 );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ if ( userData->vertices != NULL )
+ {
+ free ( userData->vertices );
+ }
+
+ if ( userData->indices != NULL )
+ {
+ free ( userData->indices );
+ }
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free(userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterUpdateFunc ( &esContext, Update );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
+
diff --git a/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c
new file mode 100644
index 00000000..6036bf0c
--- /dev/null
+++ b/tests/glbook/Chapter_8/Simple_VertexShader/Simple_VertexShader_orig.c
@@ -0,0 +1,196 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_VertexShader.c
+//
+// This is a simple example that draws a rotating cube in perspective
+// using a vertex shader to transform the object
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+
+ // Uniform locations
+ GLint mvpLoc;
+
+ // Vertex daata
+ GLfloat *vertices;
+ GLuint *indices;
+ int numIndices;
+
+ // Rotation angle
+ GLfloat angle;
+
+ // MVP matrix
+ ESMatrix mvpMatrix;
+} UserData;
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "uniform mat4 u_mvpMatrix; \n"
+ "attribute vec4 a_position; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_mvpMatrix * a_position; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); \n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+
+ // Get the uniform locations
+ userData->mvpLoc = glGetUniformLocation( userData->programObject, "u_mvpMatrix" );
+
+ // Generate the vertex data
+ userData->numIndices = esGenCube( 1.0, &userData->vertices,
+ NULL, NULL, &userData->indices );
+
+ // Starting rotation angle for the cube
+ userData->angle = 45.0f;
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+
+///
+// Update MVP matrix based on time
+//
+void Update ( ESContext *esContext, float deltaTime )
+{
+ UserData *userData = (UserData*) esContext->userData;
+ ESMatrix perspective;
+ ESMatrix modelview;
+ float aspect;
+
+ // Compute a rotation angle based on time to rotate the cube
+ userData->angle += ( deltaTime * 40.0f );
+ if( userData->angle >= 360.0f )
+ userData->angle -= 360.0f;
+
+ // Compute the window aspect ratio
+ aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;
+
+ // Generate a perspective matrix with a 60 degree FOV
+ esMatrixLoadIdentity( &perspective );
+ esPerspective( &perspective, 60.0f, aspect, 1.0f, 20.0f );
+
+ // Generate a model view matrix to rotate/translate the cube
+ esMatrixLoadIdentity( &modelview );
+
+ // Translate away from the viewer
+ esTranslate( &modelview, 0.0, 0.0, -2.0 );
+
+ // Rotate the cube
+ esRotate( &modelview, userData->angle, 1.0, 0.0, 1.0 );
+
+ // Compute the final MVP by multiplying the
+ // modevleiw and perspective matrices together
+ esMatrixMultiply( &userData->mvpMatrix, &modelview, &perspective );
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 3 * sizeof(GLfloat), userData->vertices );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+
+
+ // Load the MVP matrix
+ glUniformMatrix4fv( userData->mvpLoc, 1, GL_FALSE, (GLfloat*) &userData->mvpMatrix.m[0][0] );
+
+ // Draw the cube
+ glDrawElements ( GL_TRIANGLES, userData->numIndices, GL_UNSIGNED_INT, userData->indices );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ if ( userData->vertices != NULL )
+ {
+ free ( userData->vertices );
+ }
+
+ if ( userData->indices != NULL )
+ {
+ free ( userData->indices );
+ }
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free(userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+ esRegisterUpdateFunc ( &esContext, Update );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
+
diff --git a/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c
new file mode 100644
index 00000000..38ab38a5
--- /dev/null
+++ b/tests/glbook/Chapter_9/MipMap2D/MipMap2D.c
@@ -0,0 +1,348 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// MipMap2D.c
+//
+// This is a simple example that demonstrates generating a mipmap chain
+// and rendering with it
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Offset location
+ GLint offsetLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+} UserData;
+
+
+///
+// From an RGB8 source image, generate the next level mipmap
+//
+GLboolean GenMipMap2D( GLubyte *src, GLubyte **dst, int srcWidth, int srcHeight, int *dstWidth, int *dstHeight )
+{
+ int x,
+ y;
+ int texelSize = 3;
+
+ *dstWidth = srcWidth / 2;
+ if ( *dstWidth <= 0 )
+ *dstWidth = 1;
+
+ *dstHeight = srcHeight / 2;
+ if ( *dstHeight <= 0 )
+ *dstHeight = 1;
+
+ *dst = malloc ( sizeof(GLubyte) * texelSize * (*dstWidth) * (*dstHeight) );
+ if ( *dst == NULL )
+ return GL_FALSE;
+
+ for ( y = 0; y < *dstHeight; y++ )
+ {
+ for( x = 0; x < *dstWidth; x++ )
+ {
+ int srcIndex[4];
+ float r = 0.0f,
+ g = 0.0f,
+ b = 0.0f;
+ int sample;
+
+ // Compute the offsets for 2x2 grid of pixels in previous
+ // image to perform box filter
+ srcIndex[0] =
+ (((y * 2) * srcWidth) + (x * 2)) * texelSize;
+ srcIndex[1] =
+ (((y * 2) * srcWidth) + (x * 2 + 1)) * texelSize;
+ srcIndex[2] =
+ ((((y * 2) + 1) * srcWidth) + (x * 2)) * texelSize;
+ srcIndex[3] =
+ ((((y * 2) + 1) * srcWidth) + (x * 2 + 1)) * texelSize;
+
+ // Sum all pixels
+ for ( sample = 0; sample < 4; sample++ )
+ {
+ r += src[srcIndex[sample]];
+ g += src[srcIndex[sample] + 1];
+ b += src[srcIndex[sample] + 2];
+ }
+
+ // Average results
+ r /= 4.0;
+ g /= 4.0;
+ b /= 4.0;
+
+ // Store resulting pixels
+ (*dst)[ ( y * (*dstWidth) + x ) * texelSize ] = (GLubyte)( r );
+ (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 1] = (GLubyte)( g );
+ (*dst)[ ( y * (*dstWidth) + x ) * texelSize + 2] = (GLubyte)( b );
+ }
+ }
+
+ return GL_TRUE;
+}
+
+///
+// Generate an RGB8 checkerboard image
+//
+GLubyte* GenCheckImage( int width, int height, int checkSize )
+{
+ int x,
+ y;
+ GLubyte *pixels = malloc( width * height * 3 );
+
+ if ( pixels == NULL )
+ return NULL;
+
+ for ( y = 0; y < height; y++ )
+ for ( x = 0; x < width; x++ )
+ {
+ GLubyte rColor = 0;
+ GLubyte bColor = 0;
+
+ if ( ( x / checkSize ) % 2 == 0 )
+ {
+ rColor = 255 * ( ( y / checkSize ) % 2 );
+ bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+ else
+ {
+ bColor = 255 * ( ( y / checkSize ) % 2 );
+ rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+
+ pixels[(y * height + x) * 3] = rColor;
+ pixels[(y * height + x) * 3 + 1] = 0;
+ pixels[(y * height + x) * 3 + 2] = bColor;
+ }
+
+ return pixels;
+}
+
+///
+// Create a mipmapped 2D texture image
+//
+GLuint CreateMipMappedTexture2D( )
+{
+ // Texture object handle
+ GLuint textureId;
+ int width = 256,
+ height = 256;
+ int level;
+ GLubyte *pixels;
+ GLubyte *prevImage;
+ GLubyte *newImage;
+
+ pixels = GenCheckImage( width, height, 8 );
+ if ( pixels == NULL )
+ return 0;
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_2D, textureId );
+
+ // Load mipmap level 0
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
+
+ level = 1;
+ prevImage = &pixels[0];
+
+ while ( width > 1 && height > 1 )
+ {
+ int newWidth,
+ newHeight;
+
+ // Generate the next mipmap level
+ GenMipMap2D( prevImage, &newImage, width, height,
+ &newWidth, &newHeight );
+
+ // Load the mipmap level
+ glTexImage2D( GL_TEXTURE_2D, level, GL_RGB,
+ newWidth, newHeight, 0, GL_RGB,
+ GL_UNSIGNED_BYTE, newImage );
+
+ // Free the previous image
+ free ( prevImage );
+
+ // Set the previous image for the next iteration
+ prevImage = newImage;
+ level++;
+
+ // Half the width and height
+ width = newWidth;
+ height = newHeight;
+ }
+
+ free ( newImage );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ return textureId;
+
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "uniform float u_offset; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " gl_Position.x += u_offset;\n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Get the offset location
+ userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" );
+
+ // Load the texture
+ userData->textureId = CreateMipMappedTexture2D ();
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, 1.5f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, 0.75f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, 0.75f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, 1.5f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ // Draw quad with nearest sampling
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glUniform1f ( userData->offsetLoc, -0.6f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ // Draw quad with trilinear filtering
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ glUniform1f ( userData->offsetLoc, 0.6f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free(esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c
new file mode 100644
index 00000000..5276bda4
--- /dev/null
+++ b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D.c
@@ -0,0 +1,213 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_Texture2D.c
+//
+// This is a simple example that draws a quad with a 2D
+// texture image. The purpose of this example is to demonstrate
+// the basics of 2D texturing
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ GLuint vertexObject, indexObject;
+
+} UserData;
+
+///
+// Create a simple 2x2 texture image with four different colors
+//
+GLuint CreateSimpleTexture2D( )
+{
+ // Texture object handle
+ GLuint textureId;
+
+ // 2x2 Image, 3 bytes per pixel (R, G, B)
+ GLubyte pixels[4 * 3] =
+ {
+ 255, 0, 0, // Red
+ 0, 255, 0, // Green
+ 0, 0, 255, // Blue
+ 255, 255, 0 // Yellow
+ };
+
+ // Use tightly packed data
+ glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_2D, textureId );
+
+ // Load the texture
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ return textureId;
+
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Load the texture
+ userData->textureId = CreateSimpleTexture2D ();
+
+ // Setup the vertex data
+ GLfloat vVertices[] = { -0.5, 0.5, 0.0, // Position 0
+ 0.0, 0.0, // TexCoord 0
+ -0.5, -0.5, 0.0, // Position 1
+ 0.0, 1.0, // TexCoord 1
+ 0.5, -0.5, 0.0, // Position 2
+ 1.0, 1.0, // TexCoord 2
+ 0.5, 0.5, 0.0, // Position 3
+ 1.0, 0.0 // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer(GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indexObject);
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glBufferData ( GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ UserData *userData = esContext->userData;
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer (GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * 4, 0 );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * 4,
+ 3 * 4 );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free(esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c
new file mode 100644
index 00000000..cc465c9a
--- /dev/null
+++ b/tests/glbook/Chapter_9/Simple_Texture2D/Simple_Texture2D_orig.c
@@ -0,0 +1,199 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_Texture2D.c
+//
+// This is a simple example that draws a quad with a 2D
+// texture image. The purpose of this example is to demonstrate
+// the basics of 2D texturing
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+} UserData;
+
+///
+// Create a simple 2x2 texture image with four different colors
+//
+GLuint CreateSimpleTexture2D( )
+{
+ // Texture object handle
+ GLuint textureId;
+
+ // 2x2 Image, 3 bytes per pixel (R, G, B)
+ GLubyte pixels[4 * 3] =
+ {
+ 255, 0, 0, // Red
+ 0, 255, 0, // Green
+ 0, 0, 255, // Blue
+ 255, 255, 0 // Yellow
+ };
+
+ // Use tightly packed data
+ glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_2D, textureId );
+
+ // Load the texture
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ return textureId;
+
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Load the texture
+ userData->textureId = CreateSimpleTexture2D ();
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
+ 0.0f, 0.0f, // TexCoord 0
+ -0.5f, -0.5f, 0.0f, // Position 1
+ 0.0f, 1.0f, // TexCoord 1
+ 0.5f, -0.5f, 0.0f, // Position 2
+ 1.0f, 1.0f, // TexCoord 2
+ 0.5f, 0.5f, 0.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free(esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c
new file mode 100644
index 00000000..9f4a9017
--- /dev/null
+++ b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c
@@ -0,0 +1,244 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_TextureCubemap.c
+//
+// This is a simple example that draws a sphere with a cubemap image applied.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint normalLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Vertex data
+ int numIndices;
+ GLfloat *vertices;
+ GLfloat *normals;
+ GLushort *indices;
+
+ GLuint vertPosObject, vertNormalObject, indicesObject;
+} UserData;
+
+///
+// Create a simple cubemap with a 1x1 face with a different
+// color for each face
+GLuint CreateSimpleTextureCubemap( )
+{
+ GLuint textureId;
+ // Six 1x1 RGB faces
+ GLubyte cubePixels[6][3] =
+ {
+ // Face 0 - Red
+ 255, 0, 0,
+ // Face 1 - Green,
+ 0, 255, 0,
+ // Face 3 - Blue
+ 0, 0, 255,
+ // Face 4 - Yellow
+ 255, 255, 0,
+ // Face 5 - Purple
+ 255, 0, 255,
+ // Face 6 - White
+ 255, 255, 255
+ };
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId );
+
+ // Load the cube face - Positive X
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] );
+
+ // Load the cube face - Negative X
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] );
+
+ // Load the cube face - Positive Y
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] );
+
+ // Load the cube face - Negative Y
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] );
+
+ // Load the cube face - Positive Z
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] );
+
+ // Load the cube face - Negative Z
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ return textureId;
+
+}
+
+#include <stdio.h>
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ //esContext->userData = malloc(sizeof(UserData));
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec3 a_normal; \n"
+ "varying vec3 v_normal; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_normal = a_normal; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec3 v_normal; \n"
+ "uniform samplerCube s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = textureCube( s_texture, v_normal );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" );
+
+ // Get the sampler locations
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Load the texture
+ userData->textureId = CreateSimpleTextureCubemap ();
+
+ // Generate the vertex data
+ userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals,
+ NULL, &userData->indices );
+
+ // Generate the VBOs
+ glGenBuffers(1, &userData->vertPosObject);
+ glBindBuffer(GL_ARRAY_BUFFER, userData->vertPosObject);
+ glBufferData(GL_ARRAY_BUFFER, 21 * 21 * 4 * 3, userData->vertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->vertNormalObject);
+ glBindBuffer(GL_ARRAY_BUFFER, userData->vertNormalObject );
+ glBufferData(GL_ARRAY_BUFFER, 21 * 21 * 4 * 3, userData->normals, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indicesObject);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject );
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * userData->numIndices, userData->indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ glCullFace ( GL_BACK );
+ glEnable ( GL_CULL_FACE );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertPosObject );
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, 0 );
+ // Load the normal
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertNormalObject );
+ glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, 0 );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->normalLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indicesObject );
+ glDrawElements ( GL_TRIANGLES, userData->numIndices,
+ GL_UNSIGNED_SHORT, 0 );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free ( userData->vertices );
+ free ( userData->normals );
+
+ //free ( esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture Cubemap", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c
new file mode 100644
index 00000000..b981d943
--- /dev/null
+++ b/tests/glbook/Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap_orig.c
@@ -0,0 +1,227 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// Simple_TextureCubemap.c
+//
+// This is a simple example that draws a sphere with a cubemap image applied.
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint normalLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ // Vertex data
+ int numIndices;
+ GLfloat *vertices;
+ GLfloat *normals;
+ GLuint *indices;
+
+} UserData;
+
+///
+// Create a simple cubemap with a 1x1 face with a different
+// color for each face
+GLuint CreateSimpleTextureCubemap( )
+{
+ GLuint textureId;
+ // Six 1x1 RGB faces
+ GLubyte cubePixels[6][3] =
+ {
+ // Face 0 - Red
+ 255, 0, 0,
+ // Face 1 - Green,
+ 0, 255, 0,
+ // Face 3 - Blue
+ 0, 0, 255,
+ // Face 4 - Yellow
+ 255, 255, 0,
+ // Face 5 - Purple
+ 255, 0, 255,
+ // Face 6 - White
+ 255, 255, 255
+ };
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_CUBE_MAP, textureId );
+
+ // Load the cube face - Positive X
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[0] );
+
+ // Load the cube face - Negative X
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[1] );
+
+ // Load the cube face - Positive Y
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[2] );
+
+ // Load the cube face - Negative Y
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[3] );
+
+ // Load the cube face - Positive Z
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[4] );
+
+ // Load the cube face - Negative Z
+ glTexImage2D ( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, 1, 1, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, &cubePixels[5] );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri ( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+ return textureId;
+
+}
+
+#include <stdio.h>
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ //esContext->userData = malloc(sizeof(UserData));
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec3 a_normal; \n"
+ "varying vec3 v_normal; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_normal = a_normal; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec3 v_normal; \n"
+ "uniform samplerCube s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = textureCube( s_texture, v_normal );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->normalLoc = glGetAttribLocation ( userData->programObject, "a_normal" );
+
+ // Get the sampler locations
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Load the texture
+ userData->textureId = CreateSimpleTextureCubemap ();
+
+ // Generate the vertex data
+ userData->numIndices = esGenSphere ( 20, 0.75f, &userData->vertices, &userData->normals,
+ NULL, &userData->indices );
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ glCullFace ( GL_BACK );
+ glEnable ( GL_CULL_FACE );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, userData->vertices );
+ // Load the normal
+ glVertexAttribPointer ( userData->normalLoc, 3, GL_FLOAT,
+ GL_FALSE, 0, userData->normals );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->normalLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_CUBE_MAP, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ glDrawElements ( GL_TRIANGLES, userData->numIndices,
+ GL_UNSIGNED_INT, userData->indices );
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free ( userData->vertices );
+ free ( userData->normals );
+
+ //free ( esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "Simple Texture Cubemap", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c
new file mode 100644
index 00000000..30f39444
--- /dev/null
+++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c
@@ -0,0 +1,275 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// TextureWrap.c
+//
+// This is an example that demonstrates the three texture
+// wrap modes available on 2D textures
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Offset location
+ GLint offsetLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+ GLuint vertexObject, indexObject;
+
+} UserData;
+
+///
+// Generate an RGB8 checkerboard image
+//
+GLubyte* GenCheckImage( int width, int height, int checkSize )
+{
+ int x,
+ y;
+ GLubyte *pixels = malloc( width * height * 3 );
+
+ if ( pixels == NULL )
+ return NULL;
+
+ for ( y = 0; y < height; y++ )
+ for ( x = 0; x < width; x++ )
+ {
+ GLubyte rColor = 0;
+ GLubyte bColor = 0;
+
+ if ( ( x / checkSize ) % 2 == 0 )
+ {
+ rColor = 255 * ( ( y / checkSize ) % 2 );
+ bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+ else
+ {
+ bColor = 255 * ( ( y / checkSize ) % 2 );
+ rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+
+ pixels[(y * height + x) * 3] = rColor;
+ pixels[(y * height + x) * 3 + 1] = 0;
+ pixels[(y * height + x) * 3 + 2] = bColor;
+ }
+
+ return pixels;
+}
+
+///
+// Create a mipmapped 2D texture image
+//
+GLuint CreateTexture2D( )
+{
+ // Texture object handle
+ GLuint textureId;
+ int width = 256,
+ height = 256;
+ GLubyte *pixels;
+
+ pixels = GenCheckImage( width, height, 64 );
+ if ( pixels == NULL )
+ return 0;
+
+ // Use tightly packed data
+ glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_2D, textureId );
+
+ // Load mipmap level 0
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ return textureId;
+
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "uniform float u_offset; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " gl_Position.x += u_offset;\n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Get the offset location
+ userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" );
+
+ // Load the texture
+ userData->textureId = CreateTexture2D ();
+
+ // Setup the vertex data
+ GLfloat vVertices[] = { -0.3, 0.3, 0.0, 1.0, // Position 0
+ -1.0, -1.0, // TexCoord 0
+ -0.3, -0.3, 0.0, 1.0, // Position 1
+ -1.0, 2.0, // TexCoord 1
+ 0.3, -0.3, 0.0, 1.0, // Position 2
+ 2.0, 2.0, // TexCoord 2
+ 0.3, 0.3, 0.0, 1.0, // Position 3
+ 2.0, -1.0 // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData ( GL_ARRAY_BUFFER, 6 * 4 * 4, vVertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indexObject);
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0, 0.0, 0.0, 1.0 );
+
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), 0 );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), 4 * sizeof(GLfloat) );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ // Draw quad with repeat wrap mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glUniform1f ( userData->offsetLoc, -0.7f );
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+
+ // Draw quad with clamp to edge wrap mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glUniform1f ( userData->offsetLoc, 0.0f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+
+ // Draw quad with mirrored repeat
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
+ glUniform1f ( userData->offsetLoc, 0.7f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
+
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free ( esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
+
diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c
new file mode 100644
index 00000000..fe22282f
--- /dev/null
+++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap_orig.c
@@ -0,0 +1,257 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// TextureWrap.c
+//
+// This is an example that demonstrates the three texture
+// wrap modes available on 2D textures
+//
+#include <stdlib.h>
+#include "esUtil.h"
+
+typedef struct
+{
+ // Handle to a program object
+ GLuint programObject;
+
+ // Attribute locations
+ GLint positionLoc;
+ GLint texCoordLoc;
+
+ // Sampler location
+ GLint samplerLoc;
+
+ // Offset location
+ GLint offsetLoc;
+
+ // Texture handle
+ GLuint textureId;
+
+} UserData;
+
+///
+// Generate an RGB8 checkerboard image
+//
+GLubyte* GenCheckImage( int width, int height, int checkSize )
+{
+ int x,
+ y;
+ GLubyte *pixels = malloc( width * height * 3 );
+
+ if ( pixels == NULL )
+ return NULL;
+
+ for ( y = 0; y < height; y++ )
+ for ( x = 0; x < width; x++ )
+ {
+ GLubyte rColor = 0;
+ GLubyte bColor = 0;
+
+ if ( ( x / checkSize ) % 2 == 0 )
+ {
+ rColor = 255 * ( ( y / checkSize ) % 2 );
+ bColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+ else
+ {
+ bColor = 255 * ( ( y / checkSize ) % 2 );
+ rColor = 255 * ( 1 - ( ( y / checkSize ) % 2 ) );
+ }
+
+ pixels[(y * height + x) * 3] = rColor;
+ pixels[(y * height + x) * 3 + 1] = 0;
+ pixels[(y * height + x) * 3 + 2] = bColor;
+ }
+
+ return pixels;
+}
+
+///
+// Create a mipmapped 2D texture image
+//
+GLuint CreateTexture2D( )
+{
+ // Texture object handle
+ GLuint textureId;
+ int width = 256,
+ height = 256;
+ GLubyte *pixels;
+
+ pixels = GenCheckImage( width, height, 64 );
+ if ( pixels == NULL )
+ return 0;
+
+ // Generate a texture object
+ glGenTextures ( 1, &textureId );
+
+ // Bind the texture object
+ glBindTexture ( GL_TEXTURE_2D, textureId );
+
+ // Load mipmap level 0
+ glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
+
+ // Set the filtering mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ return textureId;
+
+}
+
+
+///
+// Initialize the shader and program object
+//
+int Init ( ESContext *esContext )
+{
+ esContext->userData = malloc(sizeof(UserData));
+
+ UserData *userData = esContext->userData;
+ GLbyte vShaderStr[] =
+ "uniform float u_offset; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " gl_Position.x += u_offset;\n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
+ "} \n";
+
+ // Load the shaders and get a linked program object
+ userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
+
+ // Get the attribute locations
+ userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
+ userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
+
+ // Get the sampler location
+ userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
+
+ // Get the offset location
+ userData->offsetLoc = glGetUniformLocation( userData->programObject, "u_offset" );
+
+ // Load the texture
+ userData->textureId = CreateTexture2D ();
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+ GLfloat vVertices[] = { -0.3f, 0.3f, 0.0f, 1.0f, // Position 0
+ -1.0f, -1.0f, // TexCoord 0
+ -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
+ -1.0f, 2.0f, // TexCoord 1
+ 0.3f, -0.3f, 0.0f, 1.0f, // Position 2
+ 2.0f, 2.0f, // TexCoord 2
+ 0.3f, 0.3f, 0.0f, 1.0f, // Position 3
+ 2.0f, -1.0f // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ // Set the viewport
+ glViewport ( 0, 0, esContext->width, esContext->height );
+
+ // Clear the color buffer
+ glClear ( GL_COLOR_BUFFER_BIT );
+
+ // Use the program object
+ glUseProgram ( userData->programObject );
+
+ // Load the vertex position
+ glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), vVertices );
+ // Load the texture coordinate
+ glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] );
+
+ glEnableVertexAttribArray ( userData->positionLoc );
+ glEnableVertexAttribArray ( userData->texCoordLoc );
+
+ // Bind the texture
+ glActiveTexture ( GL_TEXTURE0 );
+ glBindTexture ( GL_TEXTURE_2D, userData->textureId );
+
+ // Set the sampler texture unit to 0
+ glUniform1i ( userData->samplerLoc, 0 );
+
+ // Draw quad with repeat wrap mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glUniform1f ( userData->offsetLoc, -0.7f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ // Draw quad with clamp to edge wrap mode
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glUniform1f ( userData->offsetLoc, 0.0f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+ // Draw quad with mirrored repeat
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
+ glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
+ glUniform1f ( userData->offsetLoc, 0.7f );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+
+}
+
+///
+// Cleanup
+//
+void ShutDown ( ESContext *esContext )
+{
+ UserData *userData = esContext->userData;
+
+ // Delete texture object
+ glDeleteTextures ( 1, &userData->textureId );
+
+ // Delete program object
+ glDeleteProgram ( userData->programObject );
+
+ free ( esContext->userData);
+}
+
+int main ( int argc, char *argv[] )
+{
+ ESContext esContext;
+ UserData userData;
+
+ esInitContext ( &esContext );
+ esContext.userData = &userData;
+
+ esCreateWindow ( &esContext, "MipMap 2D", 640, 480, ES_WINDOW_RGB );
+
+ if ( !Init ( &esContext ) )
+ return 0;
+
+ esRegisterDrawFunc ( &esContext, Draw );
+
+ esMainLoop ( &esContext );
+
+ ShutDown ( &esContext );
+}
+
diff --git a/tests/glbook/Common/esShader.c b/tests/glbook/Common/esShader.c
new file mode 100644
index 00000000..4ea2cbcb
--- /dev/null
+++ b/tests/glbook/Common/esShader.c
@@ -0,0 +1,155 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESShader.c
+//
+// Utility functions for loading shaders and creating program objects.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <stdlib.h>
+
+//////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+//
+
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ // Create the shader object
+ shader = glCreateShader ( type );
+
+ if ( shader == 0 )
+ return 0;
+
+ // Load the shader source
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+
+ // Compile the shader
+ glCompileShader ( shader );
+
+ // Check the compile status
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ esLogMessage ( "Error compiling shader:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteShader ( shader );
+ return 0;
+ }
+
+ return shader;
+
+}
+
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc )
+{
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLuint programObject;
+ GLint linked;
+
+ // Load the vertex/fragment shaders
+ vertexShader = esLoadShader ( GL_VERTEX_SHADER, vertShaderSrc );
+ if ( vertexShader == 0 )
+ return 0;
+
+ fragmentShader = esLoadShader ( GL_FRAGMENT_SHADER, fragShaderSrc );
+ if ( fragmentShader == 0 )
+ {
+ glDeleteShader( vertexShader );
+ return 0;
+ }
+
+ // Create the program object
+ programObject = glCreateProgram ( );
+
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+
+ // Link the program
+ glLinkProgram ( programObject );
+
+ // Check the link status
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ esLogMessage ( "Error linking program:\n%s\n", infoLog );
+
+ free ( infoLog );
+ }
+
+ glDeleteProgram ( programObject );
+ return 0;
+ }
+
+ // Free up no longer needed shader resources
+ glDeleteShader ( vertexShader );
+ glDeleteShader ( fragmentShader );
+
+ return programObject;
+} \ No newline at end of file
diff --git a/tests/glbook/Common/esShapes.c b/tests/glbook/Common/esShapes.c
new file mode 100644
index 00000000..6a8ab7ad
--- /dev/null
+++ b/tests/glbook/Common/esShapes.c
@@ -0,0 +1,280 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESShapes.c
+//
+// Utility functions for generating shapes
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+///
+// Defines
+//
+#define ES_PI (3.14159265f)
+
+//////////////////////////////////////////////////////////////////
+//
+// Private Functions
+//
+//
+
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+//
+/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
+/// \param numSlices The number of slices in the sphere
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLE_STRIP
+//
+int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices )
+{
+ int i;
+ int j;
+ int numParallels = numSlices;
+ int numVertices = ( numParallels + 1 ) * ( numSlices + 1 );
+ int numIndices = numParallels * numSlices * 6;
+ float angleStep = (2.0f * ES_PI) / ((float) numSlices);
+
+ // Allocate memory for buffers
+ if ( vertices != NULL )
+ *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices );
+
+ if ( normals != NULL )
+ *normals = malloc ( sizeof(GLfloat) * 3 * numVertices );
+
+ if ( texCoords != NULL )
+ *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices );
+
+ if ( indices != NULL )
+ *indices = malloc ( sizeof(GLushort) * numIndices );
+
+ for ( i = 0; i < numParallels + 1; i++ )
+ {
+ for ( j = 0; j < numSlices + 1; j++ )
+ {
+ int vertex = ( i * (numSlices + 1) + j ) * 3;
+
+ if ( vertices )
+ {
+ (*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) *
+ sinf ( angleStep * (float)j );
+ (*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i );
+ (*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) *
+ cosf ( angleStep * (float)j );
+ }
+
+ if ( normals )
+ {
+ (*normals)[vertex + 0] = (*vertices)[vertex + 0] / radius;
+ (*normals)[vertex + 1] = (*vertices)[vertex + 1] / radius;
+ (*normals)[vertex + 2] = (*vertices)[vertex + 2] / radius;
+ }
+
+ if ( texCoords )
+ {
+ int texIndex = ( i * (numSlices + 1) + j ) * 2;
+ (*texCoords)[texIndex + 0] = (float) j / (float) numSlices;
+ (*texCoords)[texIndex + 1] = ( 1.0f - (float) i ) / (float) (numParallels - 1 );
+ }
+ }
+ }
+
+ // Generate the indices
+ if ( indices != NULL )
+ {
+ GLushort *indexBuf = (*indices);
+ for ( i = 0; i < numParallels ; i++ )
+ {
+ for ( j = 0; j < numSlices; j++ )
+ {
+ *indexBuf++ = i * ( numSlices + 1 ) + j;
+ *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + j;
+ *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
+
+ *indexBuf++ = i * ( numSlices + 1 ) + j;
+ *indexBuf++ = ( i + 1 ) * ( numSlices + 1 ) + ( j + 1 );
+ *indexBuf++ = i * ( numSlices + 1 ) + ( j + 1 );
+ }
+ }
+ }
+
+ return numIndices;
+}
+
+//
+/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLES
+/// \param scale The size of the cube, use 1.0 for a unit cube.
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLE_STRIP
+//
+int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices )
+{
+ int i;
+ int numVertices = 24;
+ int numIndices = 36;
+
+ GLfloat cubeVerts[] =
+ {
+ -0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f,
+ 0.5f, -0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ -0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, -0.5f,
+ -0.5f, -0.5f, -0.5f,
+ -0.5f, 0.5f, -0.5f,
+ 0.5f, 0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f,
+ 0.5f, -0.5f, 0.5f,
+ -0.5f, -0.5f, -0.5f,
+ -0.5f, -0.5f, 0.5f,
+ -0.5f, 0.5f, 0.5f,
+ -0.5f, 0.5f, -0.5f,
+ 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, -0.5f,
+ };
+
+ GLfloat cubeNormals[] =
+ {
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f,
+ -1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ };
+
+ GLfloat cubeTex[] =
+ {
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f,
+ 0.0f, 1.0f,
+ 0.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f,
+ };
+
+ // Allocate memory for buffers
+ if ( vertices != NULL )
+ {
+ *vertices = malloc ( sizeof(GLfloat) * 3 * numVertices );
+ memcpy( *vertices, cubeVerts, sizeof( cubeVerts ) );
+ for ( i = 0; i < numVertices * 3; i++ )
+ {
+ (*vertices)[i] *= scale;
+ }
+ }
+
+ if ( normals != NULL )
+ {
+ *normals = malloc ( sizeof(GLfloat) * 3 * numVertices );
+ memcpy( *normals, cubeNormals, sizeof( cubeNormals ) );
+ }
+
+ if ( texCoords != NULL )
+ {
+ *texCoords = malloc ( sizeof(GLfloat) * 2 * numVertices );
+ memcpy( *texCoords, cubeTex, sizeof( cubeTex ) ) ;
+ }
+
+
+ // Generate the indices
+ if ( indices != NULL )
+ {
+ GLushort cubeIndices[] =
+ {
+ 0, 2, 1,
+ 0, 3, 2,
+ 4, 5, 6,
+ 4, 6, 7,
+ 8, 9, 10,
+ 8, 10, 11,
+ 12, 15, 14,
+ 12, 14, 13,
+ 16, 17, 18,
+ 16, 18, 19,
+ 20, 23, 22,
+ 20, 22, 21
+ };
+
+ *indices = malloc ( sizeof(GLushort) * numIndices );
+ memcpy( *indices, cubeIndices, sizeof( cubeIndices ) );
+ }
+
+ return numIndices;
+}
diff --git a/tests/glbook/Common/esTransform.c b/tests/glbook/Common/esTransform.c
new file mode 100644
index 00000000..5182218c
--- /dev/null
+++ b/tests/glbook/Common/esTransform.c
@@ -0,0 +1,213 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include "esUtil.h"
+#include <math.h>
+#include <string.h>
+
+#define PI 3.1415926535897932384626433832795f
+
+void ESUTIL_API
+esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz)
+{
+ result->m[0][0] *= sx;
+ result->m[0][1] *= sx;
+ result->m[0][2] *= sx;
+ result->m[0][3] *= sx;
+
+ result->m[1][0] *= sy;
+ result->m[1][1] *= sy;
+ result->m[1][2] *= sy;
+ result->m[1][3] *= sy;
+
+ result->m[2][0] *= sz;
+ result->m[2][1] *= sz;
+ result->m[2][2] *= sz;
+ result->m[2][3] *= sz;
+}
+
+void ESUTIL_API
+esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz)
+{
+ result->m[3][0] += (result->m[0][0] * tx + result->m[1][0] * ty + result->m[2][0] * tz);
+ result->m[3][1] += (result->m[0][1] * tx + result->m[1][1] * ty + result->m[2][1] * tz);
+ result->m[3][2] += (result->m[0][2] * tx + result->m[1][2] * ty + result->m[2][2] * tz);
+ result->m[3][3] += (result->m[0][3] * tx + result->m[1][3] * ty + result->m[2][3] * tz);
+}
+
+void ESUTIL_API
+esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat sinAngle, cosAngle;
+ GLfloat mag = sqrtf(x * x + y * y + z * z);
+
+ sinAngle = sinf ( angle * PI / 180.0f );
+ cosAngle = cosf ( angle * PI / 180.0f );
+ if ( mag > 0.0f )
+ {
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
+ GLfloat oneMinusCos;
+ ESMatrix rotMat;
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * sinAngle;
+ ys = y * sinAngle;
+ zs = z * sinAngle;
+ oneMinusCos = 1.0f - cosAngle;
+
+ rotMat.m[0][0] = (oneMinusCos * xx) + cosAngle;
+ rotMat.m[0][1] = (oneMinusCos * xy) - zs;
+ rotMat.m[0][2] = (oneMinusCos * zx) + ys;
+ rotMat.m[0][3] = 0.0F;
+
+ rotMat.m[1][0] = (oneMinusCos * xy) + zs;
+ rotMat.m[1][1] = (oneMinusCos * yy) + cosAngle;
+ rotMat.m[1][2] = (oneMinusCos * yz) - xs;
+ rotMat.m[1][3] = 0.0F;
+
+ rotMat.m[2][0] = (oneMinusCos * zx) - ys;
+ rotMat.m[2][1] = (oneMinusCos * yz) + xs;
+ rotMat.m[2][2] = (oneMinusCos * zz) + cosAngle;
+ rotMat.m[2][3] = 0.0F;
+
+ rotMat.m[3][0] = 0.0F;
+ rotMat.m[3][1] = 0.0F;
+ rotMat.m[3][2] = 0.0F;
+ rotMat.m[3][3] = 1.0F;
+
+ esMatrixMultiply( result, &rotMat, result );
+ }
+}
+
+void ESUTIL_API
+esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix frust;
+
+ if ( (nearZ <= 0.0f) || (farZ <= 0.0f) ||
+ (deltaX <= 0.0f) || (deltaY <= 0.0f) || (deltaZ <= 0.0f) )
+ return;
+
+ frust.m[0][0] = 2.0f * nearZ / deltaX;
+ frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+ frust.m[1][1] = 2.0f * nearZ / deltaY;
+ frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+ frust.m[2][0] = (right + left) / deltaX;
+ frust.m[2][1] = (top + bottom) / deltaY;
+ frust.m[2][2] = -(nearZ + farZ) / deltaZ;
+ frust.m[2][3] = -1.0f;
+
+ frust.m[3][2] = -2.0f * nearZ * farZ / deltaZ;
+ frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+ esMatrixMultiply(result, &frust, result);
+}
+
+
+void ESUTIL_API
+esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ)
+{
+ GLfloat frustumW, frustumH;
+
+ frustumH = tanf( fovy / 360.0f * PI ) * nearZ;
+ frustumW = frustumH * aspect;
+
+ esFrustum( result, -frustumW, frustumW, -frustumH, frustumH, nearZ, farZ );
+}
+
+void ESUTIL_API
+esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ float deltaZ = farZ - nearZ;
+ ESMatrix ortho;
+
+ if ( (deltaX == 0.0f) || (deltaY == 0.0f) || (deltaZ == 0.0f) )
+ return;
+
+ esMatrixLoadIdentity(&ortho);
+ ortho.m[0][0] = 2.0f / deltaX;
+ ortho.m[3][0] = -(right + left) / deltaX;
+ ortho.m[1][1] = 2.0f / deltaY;
+ ortho.m[3][1] = -(top + bottom) / deltaY;
+ ortho.m[2][2] = -2.0f / deltaZ;
+ ortho.m[3][2] = -(nearZ + farZ) / deltaZ;
+
+ esMatrixMultiply(result, &ortho, result);
+}
+
+
+void ESUTIL_API
+esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB)
+{
+ ESMatrix tmp;
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ tmp.m[i][0] = (srcA->m[i][0] * srcB->m[0][0]) +
+ (srcA->m[i][1] * srcB->m[1][0]) +
+ (srcA->m[i][2] * srcB->m[2][0]) +
+ (srcA->m[i][3] * srcB->m[3][0]) ;
+
+ tmp.m[i][1] = (srcA->m[i][0] * srcB->m[0][1]) +
+ (srcA->m[i][1] * srcB->m[1][1]) +
+ (srcA->m[i][2] * srcB->m[2][1]) +
+ (srcA->m[i][3] * srcB->m[3][1]) ;
+
+ tmp.m[i][2] = (srcA->m[i][0] * srcB->m[0][2]) +
+ (srcA->m[i][1] * srcB->m[1][2]) +
+ (srcA->m[i][2] * srcB->m[2][2]) +
+ (srcA->m[i][3] * srcB->m[3][2]) ;
+
+ tmp.m[i][3] = (srcA->m[i][0] * srcB->m[0][3]) +
+ (srcA->m[i][1] * srcB->m[1][3]) +
+ (srcA->m[i][2] * srcB->m[2][3]) +
+ (srcA->m[i][3] * srcB->m[3][3]) ;
+ }
+ memcpy(result, &tmp, sizeof(ESMatrix));
+}
+
+
+void ESUTIL_API
+esMatrixLoadIdentity(ESMatrix *result)
+{
+ memset(result, 0x0, sizeof(ESMatrix));
+ result->m[0][0] = 1.0f;
+ result->m[1][1] = 1.0f;
+ result->m[2][2] = 1.0f;
+ result->m[3][3] = 1.0f;
+}
+
diff --git a/tests/glbook/Common/esUtil.c b/tests/glbook/Common/esUtil.c
new file mode 100644
index 00000000..fa080648
--- /dev/null
+++ b/tests/glbook/Common/esUtil.c
@@ -0,0 +1,420 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+// ESUtil.c
+//
+// A utility library for OpenGL ES. This library provides a
+// basic common framework for the example applications in the
+// OpenGL ES 2.0 Programming Guide.
+//
+
+///
+// Includes
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include "esUtil.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+// X11 related local variables
+static Display *x_display = NULL;
+
+///
+// CreateEGLContext()
+//
+// Creates an EGL rendering context and all associated elements
+//
+EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
+ EGLContext* eglContext, EGLSurface* eglSurface,
+ EGLint attribList[])
+{
+ EGLint numConfigs;
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLDisplay display;
+ EGLContext context;
+ EGLSurface surface;
+ EGLConfig config;
+ EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
+
+ // Get Display
+ display = eglGetDisplay((EGLNativeDisplayType)x_display);
+ if ( display == EGL_NO_DISPLAY )
+ {
+ return EGL_FALSE;
+ }
+
+ // Initialize EGL
+ if ( !eglInitialize(display, &majorVersion, &minorVersion) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Get configs
+ if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Choose config
+ if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a surface
+ surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);
+ if ( surface == EGL_NO_SURFACE )
+ {
+ return EGL_FALSE;
+ }
+
+ // Create a GL context
+ context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );
+ if ( context == EGL_NO_CONTEXT )
+ {
+ return EGL_FALSE;
+ }
+
+ // Make the context current
+ if ( !eglMakeCurrent(display, surface, surface, context) )
+ {
+ return EGL_FALSE;
+ }
+
+ *eglDisplay = display;
+ *eglSurface = surface;
+ *eglContext = context;
+ return EGL_TRUE;
+}
+
+
+///
+// WinCreate()
+//
+// This function initialized the native X11 display and window for EGL
+//
+EGLBoolean WinCreate(ESContext *esContext, const char *title)
+{
+ Window root;
+ XSetWindowAttributes swa;
+ XSetWindowAttributes xattr;
+ Atom wm_state;
+ XWMHints hints;
+ XEvent xev;
+ EGLConfig ecfg;
+ EGLint num_config;
+ Window win;
+
+ /*
+ * X11 native display initialization
+ */
+
+ x_display = XOpenDisplay(NULL);
+ if ( x_display == NULL )
+ {
+ return EGL_FALSE;
+ }
+
+ root = DefaultRootWindow(x_display);
+
+ swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
+ win = XCreateWindow(
+ x_display, root,
+ 0, 0, esContext->width, esContext->height, 0,
+ CopyFromParent, InputOutput,
+ CopyFromParent, CWEventMask,
+ &swa );
+
+ xattr.override_redirect = FALSE;
+ XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
+
+ hints.input = TRUE;
+ hints.flags = InputHint;
+ XSetWMHints(x_display, win, &hints);
+
+ // make the window visible on the screen
+ XMapWindow (x_display, win);
+ XStoreName (x_display, win, title);
+
+ // get identifiers for the provided atom name strings
+ wm_state = XInternAtom (x_display, "_NET_WM_STATE", FALSE);
+
+ memset ( &xev, 0, sizeof(xev) );
+ xev.type = ClientMessage;
+ xev.xclient.window = win;
+ xev.xclient.message_type = wm_state;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = 1;
+ xev.xclient.data.l[1] = FALSE;
+ XSendEvent (
+ x_display,
+ DefaultRootWindow ( x_display ),
+ FALSE,
+ SubstructureNotifyMask,
+ &xev );
+
+ esContext->hWnd = (EGLNativeWindowType) win;
+ return EGL_TRUE;
+}
+
+
+///
+// userInterrupt()
+//
+// Reads from X11 event loop and interrupt program if there is a keypress, or
+// window close action.
+//
+GLboolean userInterrupt(ESContext *esContext)
+{
+ XEvent xev;
+ KeySym key;
+ GLboolean userinterrupt = GL_FALSE;
+ char text;
+
+ // Pump all messages from X server. Keypresses are directed to keyfunc (if defined)
+ while ( XPending ( x_display ) )
+ {
+ XNextEvent( x_display, &xev );
+ if ( xev.type == KeyPress )
+ {
+ if (XLookupString(&xev.xkey,&text,1,&key,0)==1)
+ {
+ if (esContext->keyFunc != NULL)
+ esContext->keyFunc(esContext, text, 0, 0);
+ }
+ }
+ if ( xev.type == DestroyNotify )
+ userinterrupt = GL_TRUE;
+ }
+ return userinterrupt;
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Public Functions
+//
+//
+
+///
+// esInitContext()
+//
+// Initialize ES utility context. This must be called before calling any other
+// functions.
+//
+void ESUTIL_API esInitContext ( ESContext *esContext )
+{
+ if ( esContext != NULL )
+ {
+ memset( esContext, 0, sizeof( ESContext) );
+ }
+}
+
+
+///
+// esCreateWindow()
+//
+// title - name for title bar of window
+// width - width of window to create
+// height - height of window to create
+// flags - bitwise or of window creation flags
+// ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha
+// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+//
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char* title, GLint width, GLint height, GLuint flags )
+{
+ EGLint attribList[] =
+ {
+ EGL_RED_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_BLUE_SIZE, 5,
+ EGL_ALPHA_SIZE, (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
+ EGL_STENCIL_SIZE, (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
+ EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,
+ EGL_NONE
+ };
+
+ if ( esContext == NULL )
+ {
+ return GL_FALSE;
+ }
+
+ esContext->width = width;
+ esContext->height = height;
+
+ if ( !WinCreate ( esContext, title) )
+ {
+ return GL_FALSE;
+ }
+
+
+ if ( !CreateEGLContext ( esContext->hWnd,
+ &esContext->eglDisplay,
+ &esContext->eglContext,
+ &esContext->eglSurface,
+ attribList) )
+ {
+ return GL_FALSE;
+ }
+
+
+ return GL_TRUE;
+}
+
+
+///
+// esMainLoop()
+//
+// Start the main loop for the OpenGL ES application
+//
+
+void ESUTIL_API esMainLoop ( ESContext *esContext )
+{
+ struct timeval t1, t2;
+ struct timezone tz;
+ float deltatime;
+ float totaltime = 0.0f;
+ unsigned int frames = 0;
+
+ gettimeofday ( &t1 , &tz );
+
+ // Just one iteration! while(userInterrupt(esContext) == GL_FALSE)
+ {
+ gettimeofday(&t2, &tz);
+ deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
+ t1 = t2;
+
+ if (esContext->updateFunc != NULL)
+ esContext->updateFunc(esContext, deltatime);
+ if (esContext->drawFunc != NULL)
+ esContext->drawFunc(esContext);
+
+ eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
+
+ totaltime += deltatime;
+ frames++;
+ if (totaltime > 2.0f)
+ {
+ printf("%4d frames rendered in %1.4f seconds -> FPS=%3.4f\n", frames, totaltime, frames/totaltime);
+ totaltime -= 2.0f;
+ frames = 0;
+ }
+ }
+}
+
+
+///
+// esRegisterDrawFunc()
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) )
+{
+ esContext->drawFunc = drawFunc;
+}
+
+
+///
+// esRegisterUpdateFunc()
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) )
+{
+ esContext->updateFunc = updateFunc;
+}
+
+
+///
+// esRegisterKeyFunc()
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) )
+{
+ esContext->keyFunc = keyFunc;
+}
+
+
+///
+// esLogMessage()
+//
+// Log an error message to the debug output for the platform
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... )
+{
+ va_list params;
+ char buf[BUFSIZ];
+
+ va_start ( params, formatStr );
+ vsprintf ( buf, formatStr, params );
+
+ printf ( "%s", buf );
+
+ va_end ( params );
+}
+
+
+///
+// esLoadTGA()
+//
+// Loads a 24-bit TGA image from a file. This is probably the simplest TGA loader ever.
+// Does not support loading of compressed TGAs nor TGAa with alpha channel. But for the
+// sake of the examples, this is sufficient.
+//
+
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height )
+{
+ char *buffer = NULL;
+ FILE *f;
+ unsigned char tgaheader[12];
+ unsigned char attributes[6];
+ unsigned int imagesize;
+
+ f = fopen(fileName, "rb");
+ if(f == NULL) return NULL;
+
+ if(fread(&tgaheader, sizeof(tgaheader), 1, f) == 0)
+ {
+ fclose(f);
+ return NULL;
+ }
+
+ if(fread(attributes, sizeof(attributes), 1, f) == 0)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ *width = attributes[1] * 256 + attributes[0];
+ *height = attributes[3] * 256 + attributes[2];
+ imagesize = attributes[4] / 8 * *width * *height;
+ buffer = malloc(imagesize);
+ if (buffer == NULL)
+ {
+ fclose(f);
+ return 0;
+ }
+
+ if(fread(buffer, 1, imagesize, f) != imagesize)
+ {
+ free(buffer);
+ return NULL;
+ }
+ fclose(f);
+ return buffer;
+}
diff --git a/tests/glbook/Common/esUtil.h b/tests/glbook/Common/esUtil.h
new file mode 100644
index 00000000..c468b430
--- /dev/null
+++ b/tests/glbook/Common/esUtil.h
@@ -0,0 +1,281 @@
+//
+// Book: OpenGL(R) ES 2.0 Programming Guide
+// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10: 0321502795
+// ISBN-13: 9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs: http://safari.informit.com/9780321563835
+// http://www.opengles-book.com
+//
+
+//
+/// \file ESUtil.h
+/// \brief A utility library for OpenGL ES. This library provides a
+/// basic common framework for the example applications in the
+/// OpenGL ES 2.0 Programming Guide.
+//
+#ifndef ESUTIL_H
+#define ESUTIL_H
+
+///
+// Includes
+//
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+
+#ifdef __cplusplus
+
+extern "C" {
+#endif
+
+
+///
+// Macros
+//
+#define ESUTIL_API
+#define ESCALLBACK
+
+
+/// esCreateWindow flag - RGB color buffer
+#define ES_WINDOW_RGB 0
+/// esCreateWindow flag - ALPHA color buffer
+#define ES_WINDOW_ALPHA 1
+/// esCreateWindow flag - depth buffer
+#define ES_WINDOW_DEPTH 2
+/// esCreateWindow flag - stencil buffer
+#define ES_WINDOW_STENCIL 4
+/// esCreateWindow flat - multi-sample buffer
+#define ES_WINDOW_MULTISAMPLE 8
+
+
+///
+// Types
+//
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+typedef struct
+{
+ GLfloat m[4][4];
+} ESMatrix;
+
+typedef struct _escontext
+{
+ /// Put your user data here...
+ void* userData;
+
+ /// Window width
+ GLint width;
+
+ /// Window height
+ GLint height;
+
+ /// Window handle
+ EGLNativeWindowType hWnd;
+
+ /// EGL display
+ EGLDisplay eglDisplay;
+
+ /// EGL context
+ EGLContext eglContext;
+
+ /// EGL surface
+ EGLSurface eglSurface;
+
+ /// Callbacks
+ void (ESCALLBACK *drawFunc) ( struct _escontext * );
+ void (ESCALLBACK *keyFunc) ( struct _escontext *, unsigned char, int, int );
+ void (ESCALLBACK *updateFunc) ( struct _escontext *, float deltaTime );
+} ESContext;
+
+
+///
+// Public Functions
+//
+
+//
+///
+/// \brief Initialize ES framework context. This must be called before calling any other functions.
+/// \param esContext Application context
+//
+void ESUTIL_API esInitContext ( ESContext *esContext );
+
+//
+/// \brief Create a window with the specified parameters
+/// \param esContext Application context
+/// \param title Name for title bar of window
+/// \param width Width in pixels of window to create
+/// \param height Height in pixels of window to create
+/// \param flags Bitfield for the window creation flags
+/// ES_WINDOW_RGB - specifies that the color buffer should have R,G,B channels
+/// ES_WINDOW_ALPHA - specifies that the color buffer should have alpha
+/// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
+/// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
+/// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
+/// \return GL_TRUE if window creation is succesful, GL_FALSE otherwise
+GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags );
+
+//
+/// \brief Start the main loop for the OpenGL ES application
+/// \param esContext Application context
+//
+void ESUTIL_API esMainLoop ( ESContext *esContext );
+
+//
+/// \brief Register a draw callback function to be used to render each frame
+/// \param esContext Application context
+/// \param drawFunc Draw callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) ( ESContext* ) );
+
+//
+/// \brief Register an update callback function to be used to update on each time step
+/// \param esContext Application context
+/// \param updateFunc Update callback function that will be used to render the scene
+//
+void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) );
+
+//
+/// \brief Register an keyboard input processing callback function
+/// \param esContext Application context
+/// \param keyFunc Key callback function for application processing of keyboard input
+//
+void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,
+ void (ESCALLBACK *drawFunc) ( ESContext*, unsigned char, int, int ) );
+//
+/// \brief Log a message to the debug output for the platform
+/// \param formatStr Format string for error log.
+//
+void ESUTIL_API esLogMessage ( const char *formatStr, ... );
+
+//
+///
+/// \brief Load a shader, check for compile errors, print error messages to output log
+/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
+/// \param shaderSrc Shader source string
+/// \return A new shader object on success, 0 on failure
+//
+GLuint ESUTIL_API esLoadShader ( GLenum type, const char *shaderSrc );
+
+//
+///
+/// \brief Load a vertex and fragment shader, create a program object, link program.
+/// Errors output to log.
+/// \param vertShaderSrc Vertex shader source code
+/// \param fragShaderSrc Fragment shader source code
+/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
+//
+GLuint ESUTIL_API esLoadProgram ( const char *vertShaderSrc, const char *fragShaderSrc );
+
+
+//
+/// \brief Generates geometry for a sphere. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLE_STRIP
+/// \param numSlices The number of slices in the sphere
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLE_STRIP
+//
+int ESUTIL_API esGenSphere ( int numSlices, float radius, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices );
+
+//
+/// \brief Generates geometry for a cube. Allocates memory for the vertex data and stores
+/// the results in the arrays. Generate index list for a TRIANGLES
+/// \param scale The size of the cube, use 1.0 for a unit cube.
+/// \param vertices If not NULL, will contain array of float3 positions
+/// \param normals If not NULL, will contain array of float3 normals
+/// \param texCoords If not NULL, will contain array of float2 texCoords
+/// \param indices If not NULL, will contain the array of indices for the triangle strip
+/// \return The number of indices required for rendering the buffers (the number of indices stored in the indices array
+/// if it is not NULL ) as a GL_TRIANGLES
+//
+int ESUTIL_API esGenCube ( float scale, GLfloat **vertices, GLfloat **normals,
+ GLfloat **texCoords, GLushort **indices );
+
+//
+/// \brief Loads a 24-bit TGA image from a file
+/// \param fileName Name of the file on disk
+/// \param width Width of loaded image in pixels
+/// \param height Height of loaded image in pixels
+/// \return Pointer to loaded image. NULL on failure.
+//
+char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height );
+
+
+//
+/// \brief multiply matrix specified by result with a scaling matrix and return new matrix in result
+/// \param result Specifies the input matrix. Scaled matrix is returned in result.
+/// \param sx, sy, sz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esScale(ESMatrix *result, GLfloat sx, GLfloat sy, GLfloat sz);
+
+//
+/// \brief multiply matrix specified by result with a translation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Translated matrix is returned in result.
+/// \param tx, ty, tz Scale factors along the x, y and z axes respectively
+//
+void ESUTIL_API esTranslate(ESMatrix *result, GLfloat tx, GLfloat ty, GLfloat tz);
+
+//
+/// \brief multiply matrix specified by result with a rotation matrix and return new matrix in result
+/// \param result Specifies the input matrix. Rotated matrix is returned in result.
+/// \param angle Specifies the angle of rotation, in degrees.
+/// \param x, y, z Specify the x, y and z coordinates of a vector, respectively
+//
+void ESUTIL_API esRotate(ESMatrix *result, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+
+//
+// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. Both distances must be positive.
+//
+void ESUTIL_API esFrustum(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param fovy Field of view y angle in degrees
+/// \param aspect Aspect ratio of screen
+/// \param nearZ Near plane distance
+/// \param farZ Far plane distance
+//
+void ESUTIL_API esPerspective(ESMatrix *result, float fovy, float aspect, float nearZ, float farZ);
+
+//
+/// \brief multiply matrix specified by result with a perspective matrix and return new matrix in result
+/// \param result Specifies the input matrix. new matrix is returned in result.
+/// \param left, right Coordinates for the left and right vertical clipping planes
+/// \param bottom, top Coordinates for the bottom and top horizontal clipping planes
+/// \param nearZ, farZ Distances to the near and far depth clipping planes. These values are negative if plane is behind the viewer
+//
+void ESUTIL_API esOrtho(ESMatrix *result, float left, float right, float bottom, float top, float nearZ, float farZ);
+
+//
+/// \brief perform the following operation - result matrix = srcA matrix * srcB matrix
+/// \param result Returns multiplied matrix
+/// \param srcA, srcB Input matrices to be multiplied
+//
+void ESUTIL_API esMatrixMultiply(ESMatrix *result, ESMatrix *srcA, ESMatrix *srcB);
+
+//
+//// \brief return an indentity matrix
+//// \param result returns identity matrix
+//
+void ESUTIL_API esMatrixLoadIdentity(ESMatrix *result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ESUTIL_H
diff --git a/tests/glbook/Makefile b/tests/glbook/Makefile
new file mode 100644
index 00000000..62cffedf
--- /dev/null
+++ b/tests/glbook/Makefile
@@ -0,0 +1,60 @@
+# Straight forward Makefile to compile all examples in a row
+
+INCDIR=-I./Common
+LIBS=-lGLESv2 -lEGL -lm -lX11
+
+COMMONSRC=./Common/esShader.c \
+ ./Common/esTransform.c \
+ ./Common/esShapes.c \
+ ./Common/esUtil.c
+COMMONHRD=esUtil.h
+
+CH02SRC=./Chapter_2/Hello_Triangle/Hello_Triangle.c
+CH08SRC=./Chapter_8/Simple_VertexShader/Simple_VertexShader.c
+CH09SRC1=./Chapter_9/Simple_Texture2D/Simple_Texture2D.c
+CH09SRC2=./Chapter_9/MipMap2D/MipMap2D.c
+CH09SRC3=./Chapter_9/Simple_TextureCubemap/Simple_TextureCubemap.c
+CH09SRC4=./Chapter_9/TextureWrap/TextureWrap.c
+CH10SRC=./Chapter_10/MultiTexture/MultiTexture.c
+CH11SRC=./Chapter_11/Multisample/Multisample.c
+CH11SRC2=./Chapter_11/Stencil_Test/Stencil_Test.c
+CH13SRC2=./Chapter_13/ParticleSystem/ParticleSystem.c
+
+default: all
+
+all: ./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc \
+ ./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc \
+ ./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc \
+ ./Chapter_9/MipMap2D/CH09_MipMap2D.bc \
+ ./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc \
+ ./Chapter_9/TextureWrap/CH09_TextureWrap.bc \
+ ./Chapter_10/MultiTexture/CH10_MultiTexture.bc \
+ ./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc
+# ./Chapter_11/Multisample/CH11_Multisample.bc \
+# ./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc \
+
+clean:
+ find . -name "CH??_*" | xargs rm -f
+
+./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc: ${COMMONSRC} ${COMMONHDR} ${CH02SRC}
+ $(CC) ${COMMONSRC} ${CH02SRC} -o $@ ${INCDIR} ${LIBS}
+./Chapter_8/Simple_VertexShader/CH08_SimpleVertexShader.bc: ${COMMONSRC} ${COMMONHDR} ${CH08SRC}
+ $(CC) ${COMMONSRC} ${CH08SRC} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC1}
+ $(CC) ${COMMONSRC} ${CH09SRC1} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_9/MipMap2D/CH09_MipMap2D.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC2}
+ $(CC) ${COMMONSRC} ${CH09SRC2} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC3}
+ $(CC) ${COMMONSRC} ${CH09SRC3} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_9/TextureWrap/CH09_TextureWrap.bc: ${COMMONSRC} ${COMMONHDR} ${CH09SRC4}
+ $(CC) ${COMMONSRC} ${CH09SRC4} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_10/MultiTexture/CH10_MultiTexture.bc: ${COMMONSRC} ${COMMONHDR} ${CH10SRC}
+ $(CC) ${COMMONSRC} ${CH10SRC} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_11/Multisample/CH11_Multisample.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC}
+ $(CC) ${COMMONSRC} ${CH11SRC} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc: ${COMMONSRC} ${COMMONHDR} ${CH11SRC2}
+ $(CC) ${COMMONSRC} ${CH11SRC2} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_13/Noise3D/CH13_Noise3D.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC1}
+ $(CC) ${COMMONSRC} ${CH13SRC1} -o ./$@ ${INCDIR} ${LIBS}
+./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc: ${COMMONSRC} ${COMMONHDR} ${CH13SRC2}
+ $(CC) ${COMMONSRC} ${CH13SRC2} -o ./$@ ${INCDIR} ${LIBS}
diff --git a/tests/glbook/README.linux b/tests/glbook/README.linux
new file mode 100644
index 00000000..7b76357b
--- /dev/null
+++ b/tests/glbook/README.linux
@@ -0,0 +1,32 @@
+OpenGL ES 2.0 Programming Guide - Example code for Linux/X11 environment
+
+Adaptation code for Linux/X11 environment for the examples of the book
+OpenGL ES 2.0 Programming Guide written by Jarkko Vatjus-Anttila. All
+original example code has remained unmodified. Adaptation changes are
+in esUtil.c|h files, which encapsulates all X11 specific internals from
+the application layer.
+
+Prerequisites for building the source is a valid GCC toolchain (4.5.2
+4.6.1 are tested) and properly setup X11 & GLESv2 & EGL environment.
+Mesa project offers such setup, and version 7.11 has been tested with
+software rendering. Also native GLESv2 renderer has been tested using
+NVidia Tegra2 setup. More details about the tested environments are
+below:
+
+The code has been tested with three configurations
+- ATI Radeon HD 3200 graphics with Mesa 7.11-0ubuntu3, Ubuntu 11.10
+- NVidia Quadro FX 2800M/PCI/SSE2 with Mesa 7.11-0ubuntu3, Ubuntu 11.10
+- NVidia Tegra 2, native EGL/GLESv2 drivers, Ubuntu 10.10
+
+Native GLESv2 on Tegra2 renders all the test cases correctly. However,
+Mesa 7.11 has problems with the Chapter 13 particle test, which at least
+with the mentioned test setups create only a black screen.
+
+Compiling the examples should be as easy as running "make" in the root
+linux directory.
+
+31st Oct 2011 - Jarkko Vatjus-Anttila <jvatjusanttila@gmail.com>
+
+Website: http://code.google.com/p/opengles-book-samples/
+License: MIT
+
diff --git a/tests/glshaderinfo.cpp b/tests/glshaderinfo.cpp
new file mode 100644
index 00000000..8ec393a8
--- /dev/null
+++ b/tests/glshaderinfo.cpp
@@ -0,0 +1,52 @@
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#define _GNU_SOURCE
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <Glut/glut.h>
+#else
+#include <GL/gl.h>
+#include <GL/glut.h>
+#endif
+
+#include <assert.h>
+#include <emscripten.h>
+
+int main(int argc, char *argv[])
+{
+ /* Initialize the window */
+ glutInit(&argc, argv);
+ glutInitWindowSize(300, 300);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+
+ glutCreateWindow("es2gears");
+
+ GLint shaderCompiler;
+ glGetIntegerv(GL_SHADER_COMPILER, &shaderCompiler);
+
+ GLint numShaderBinaryFormats;
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &numShaderBinaryFormats);
+
+ printf("%d,%d\n", shaderCompiler, numShaderBinaryFormats);
+
+ if (!shaderCompiler && numShaderBinaryFormats == 0) {
+ printf("In current environment, the GLES2 implementation IS NOT standard conforming! "
+ "GL_SHADER_COMPILER == GL_FALSE and GL_NUM_SHADER_BINARY_FORMATS == 0! "
+ "In GLES2 spec, either compiling shaders or binary shaders must be supported! (Section 2.10 - Vertex Shaders)\n");
+ int result = 0;
+ REPORT_RESULT();
+ } else {
+ assert(numShaderBinaryFormats == 0);
+ int result = 1;
+ REPORT_RESULT();
+ }
+ return 0;
+}
diff --git a/tests/hello_world_gles.c b/tests/hello_world_gles.c
index 4f2cb45c..78595a49 100644
--- a/tests/hello_world_gles.c
+++ b/tests/hello_world_gles.c
@@ -1,16 +1,16 @@
/*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -23,7 +23,7 @@
* Ported to GLES2.
* Kristian Høgsberg <krh@bitplanet.net>
* May 3, 2010
- *
+ *
* Improve GLES2 port:
* * Refactor gear drawing.
* * Use correct normals for surfaces.
@@ -46,17 +46,28 @@
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <Glut/glut.h>
+#else
#include <GL/gl.h>
#include <GL/glut.h>
-
-#ifndef HAVE_BUILTIN_SINCOS
-#include "sincos.h"
#endif
#define STRIPS_PER_TOOTH 7
#define VERTICES_PER_TOOTH 34
#define GEAR_VERTEX_STRIDE 6
+#ifndef HAVE_BUILTIN_SINCOS
+#define sincos _sincos
+static void
+sincos (double a, double *s, double *c)
+{
+ *s = sin (a);
+ *c = cos (a);
+}
+#endif
+
/**
* Struct describing the vertices in triangle strip
*/
@@ -102,15 +113,15 @@ static GLfloat ProjectionMatrix[16];
/** The direction of the directional light for the scene */
static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0};
-/**
+/**
* Fills a gear vertex.
- *
+ *
* @param v the vertex to fill
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coortinate
- * @param n pointer to the normal table
- *
+ * @param n pointer to the normal table
+ *
* @return the operation error code
*/
static GearVertex *
@@ -128,13 +139,13 @@ vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3])
/**
* Create a gear wheel.
- *
+ *
* @param inner_radius radius of hole at center
* @param outer_radius radius at center of teeth
* @param width width of gear
* @param teeth number of teeth
* @param tooth_depth depth of tooth
- *
+ *
* @return pointer to the constructed struct gear
*/
static struct gear *
@@ -278,11 +289,11 @@ create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
return gear;
}
-/**
+/**
* Multiplies two 4x4 matrices.
- *
+ *
* The result is stored in matrix m.
- *
+ *
* @param m the first matrix to multiply
* @param n the second matrix to multiply
*/
@@ -305,9 +316,9 @@ multiply(GLfloat *m, const GLfloat *n)
memcpy(m, &tmp, sizeof tmp);
}
-/**
+/**
* Rotates a 4x4 matrix.
- *
+ *
* @param[in,out] m the matrix to rotate
* @param angle the angle to rotate
* @param x the x component of the direction to rotate to
@@ -322,7 +333,7 @@ rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
sincos(angle, &s, &c);
GLfloat r[16] = {
x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
- x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
+ x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
0, 0, 0, 1
};
@@ -331,9 +342,9 @@ rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
}
-/**
+/**
* Translates a 4x4 matrix.
- *
+ *
* @param[in,out] m the matrix to translate
* @param x the x component of the direction to translate to
* @param y the y component of the direction to translate to
@@ -347,9 +358,9 @@ translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
multiply(m, t);
}
-/**
+/**
* Creates an identity 4x4 matrix.
- *
+ *
* @param m the matrix make an identity matrix
*/
static void
@@ -365,12 +376,12 @@ identity(GLfloat *m)
memcpy(m, t, sizeof(t));
}
-/**
+/**
* Transposes a 4x4 matrix.
*
* @param m the matrix to transpose
*/
-static void
+static void
transpose(GLfloat *m)
{
GLfloat t[16] = {
@@ -409,9 +420,9 @@ invert(GLfloat *m)
multiply(m, t);
}
-/**
+/**
* Calculate a perspective projection transformation.
- *
+ *
* @param m the matrix to save the transformation in
* @param fovy the field of view in the y direction
* @param aspect the view aspect ratio
@@ -474,7 +485,7 @@ draw_gear(struct gear *gear, GLfloat *transform,
glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE,
model_view_projection);
- /*
+ /*
* Create and set the NormalMatrix. It's the inverse transpose of the
* ModelView matrix.
*/
@@ -509,7 +520,7 @@ draw_gear(struct gear *gear, GLfloat *transform,
glDisableVertexAttribArray(0);
}
-/**
+/**
* Draws the gears.
*/
static void
@@ -538,9 +549,9 @@ gears_draw(void)
glutSwapBuffers();
}
-/**
+/**
* Handles a new window size or exposure.
- *
+ *
* @param width the window width
* @param height the window height
*/
@@ -554,9 +565,9 @@ gears_reshape(int width, int height)
glViewport(0, 0, (GLint) width, (GLint) height);
}
-/**
+/**
* Handles special glut events.
- *
+ *
* @param special the event to handle.
*/
static void
@@ -575,6 +586,9 @@ gears_special(int special, int crap, int morecrap)
case GLUT_KEY_DOWN:
view_rot[0] -= 5.0;
break;
+ case GLUT_KEY_F11:
+ glutFullScreen();
+ break;
}
}
@@ -715,7 +729,7 @@ main(int argc, char *argv[])
glutCreateWindow("es2gears");
/* Set up glut callback functions */
- gears_idle();
+ glutIdleFunc (gears_idle);
glutReshapeFunc(gears_reshape);
glutDisplayFunc(gears_draw);
glutSpecialFunc(gears_special);
diff --git a/tests/hello_world_gles_deriv.c b/tests/hello_world_gles_deriv.c
new file mode 100644
index 00000000..2e0f0664
--- /dev/null
+++ b/tests/hello_world_gles_deriv.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Ported to GLES2.
+ * Kristian Høgsberg <krh@bitplanet.net>
+ * May 3, 2010
+ *
+ * Improve GLES2 port:
+ * * Refactor gear drawing.
+ * * Use correct normals for surfaces.
+ * * Improve shader.
+ * * Use perspective projection transformation.
+ * * Add FPS count.
+ * * Add comments.
+ * Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ * Jul 13, 2010
+ */
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#define _GNU_SOURCE
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include <GL/glut.h>
+
+#ifndef HAVE_BUILTIN_SINCOS
+#include "sincos.h"
+#endif
+
+#define STRIPS_PER_TOOTH 7
+#define VERTICES_PER_TOOTH 34
+#define GEAR_VERTEX_STRIDE 6
+
+/**
+ * Struct describing the vertices in triangle strip
+ */
+struct vertex_strip {
+ /** The first vertex in the strip */
+ GLint first;
+ /** The number of consecutive vertices in the strip after the first */
+ GLint count;
+};
+
+/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
+typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
+
+/**
+ * Struct representing a gear.
+ */
+struct gear {
+ /** The array of vertices comprising the gear */
+ GearVertex *vertices;
+ /** The number of vertices comprising the gear */
+ int nvertices;
+ /** The array of triangle strips comprising the gear */
+ struct vertex_strip *strips;
+ /** The number of triangle strips comprising the gear */
+ int nstrips;
+ /** The Vertex Buffer Object holding the vertices in the graphics card */
+ GLuint vbo;
+};
+
+/** The view rotation [x, y, z] */
+static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 };
+/** The gears */
+static struct gear *gear1, *gear2, *gear3;
+/** The current gear rotation angle */
+static GLfloat angle = 0.0;
+/** The location of the shader uniforms */
+static GLuint ModelViewProjectionMatrix_location,
+ NormalMatrix_location,
+ LightSourcePosition_location,
+ MaterialColor_location;
+/** The projection matrix */
+static GLfloat ProjectionMatrix[16];
+/** The direction of the directional light for the scene */
+static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0};
+
+/**
+ * Fills a gear vertex.
+ *
+ * @param v the vertex to fill
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param z the z coortinate
+ * @param n pointer to the normal table
+ *
+ * @return the operation error code
+ */
+static GearVertex *
+vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3])
+{
+ v[0][0] = x;
+ v[0][1] = y;
+ v[0][2] = z;
+ v[0][3] = n[0];
+ v[0][4] = n[1];
+ v[0][5] = n[2];
+
+ return v + 1;
+}
+
+/**
+ * Create a gear wheel.
+ *
+ * @param inner_radius radius of hole at center
+ * @param outer_radius radius at center of teeth
+ * @param width width of gear
+ * @param teeth number of teeth
+ * @param tooth_depth depth of tooth
+ *
+ * @return pointer to the constructed struct gear
+ */
+static struct gear *
+create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLfloat r0, r1, r2;
+ GLfloat da;
+ GearVertex *v;
+ struct gear *gear;
+ double s[5], c[5];
+ GLfloat normal[3];
+ int cur_strip = 0;
+ int i;
+
+ /* Allocate memory for the gear */
+ gear = malloc(sizeof *gear);
+ if (gear == NULL)
+ return NULL;
+
+ /* Calculate the radii used in the gear */
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ /* Allocate memory for the triangle strip information */
+ gear->nstrips = STRIPS_PER_TOOTH * teeth;
+ gear->strips = calloc(gear->nstrips, sizeof (*gear->strips));
+
+ /* Allocate memory for the vertices */
+ gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
+ v = gear->vertices;
+
+ for (i = 0; i < teeth; i++) {
+ /* Calculate needed sin/cos for varius angles */
+ sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]);
+ sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
+ sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
+ sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
+ sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
+
+ /* A set of macros for making the creation of the gears easier */
+#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] }
+#define SET_NORMAL(x, y, z) do { \
+ normal[0] = (x); normal[1] = (y); normal[2] = (z); \
+} while(0)
+
+#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
+
+#define START_STRIP do { \
+ gear->strips[cur_strip].first = v - gear->vertices; \
+} while(0);
+
+#define END_STRIP do { \
+ int _tmp = (v - gear->vertices); \
+ gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \
+ cur_strip++; \
+} while (0)
+
+#define QUAD_WITH_NORMAL(p1, p2) do { \
+ SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \
+ v = GEAR_VERT(v, (p1), -1); \
+ v = GEAR_VERT(v, (p1), 1); \
+ v = GEAR_VERT(v, (p2), -1); \
+ v = GEAR_VERT(v, (p2), 1); \
+} while(0)
+
+ struct point {
+ GLfloat x;
+ GLfloat y;
+ };
+
+ /* Create the 7 points (only x,y coords) used to draw a tooth */
+ struct point p[7] = {
+ GEAR_POINT(r2, 1), // 0
+ GEAR_POINT(r2, 2), // 1
+ GEAR_POINT(r1, 0), // 2
+ GEAR_POINT(r1, 3), // 3
+ GEAR_POINT(r0, 0), // 4
+ GEAR_POINT(r1, 4), // 5
+ GEAR_POINT(r0, 4), // 6
+ };
+
+ /* Front face */
+ START_STRIP;
+ SET_NORMAL(0, 0, 1.0);
+ v = GEAR_VERT(v, 0, +1);
+ v = GEAR_VERT(v, 1, +1);
+ v = GEAR_VERT(v, 2, +1);
+ v = GEAR_VERT(v, 3, +1);
+ v = GEAR_VERT(v, 4, +1);
+ v = GEAR_VERT(v, 5, +1);
+ v = GEAR_VERT(v, 6, +1);
+ END_STRIP;
+
+ /* Inner face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(4, 6);
+ END_STRIP;
+
+ /* Back face */
+ START_STRIP;
+ SET_NORMAL(0, 0, -1.0);
+ v = GEAR_VERT(v, 6, -1);
+ v = GEAR_VERT(v, 5, -1);
+ v = GEAR_VERT(v, 4, -1);
+ v = GEAR_VERT(v, 3, -1);
+ v = GEAR_VERT(v, 2, -1);
+ v = GEAR_VERT(v, 1, -1);
+ v = GEAR_VERT(v, 0, -1);
+ END_STRIP;
+
+ /* Outer face */
+ START_STRIP;
+ QUAD_WITH_NORMAL(0, 2);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(1, 0);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(3, 1);
+ END_STRIP;
+
+ START_STRIP;
+ QUAD_WITH_NORMAL(5, 3);
+ END_STRIP;
+ }
+
+ gear->nvertices = (v - gear->vertices);
+
+ /* Store the vertices in a vertex buffer object (VBO) */
+ glGenBuffers(1, &gear->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+ glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex),
+ gear->vertices, GL_STATIC_DRAW);
+
+ return gear;
+}
+
+/**
+ * Multiplies two 4x4 matrices.
+ *
+ * The result is stored in matrix m.
+ *
+ * @param m the first matrix to multiply
+ * @param n the second matrix to multiply
+ */
+static void
+multiply(GLfloat *m, const GLfloat *n)
+{
+ GLfloat tmp[16];
+ const GLfloat *row, *column;
+ div_t d;
+ int i, j;
+
+ for (i = 0; i < 16; i++) {
+ tmp[i] = 0;
+ d = div(i, 4);
+ row = n + d.quot * 4;
+ column = m + d.rem;
+ for (j = 0; j < 4; j++)
+ tmp[i] += row[j] * column[j * 4];
+ }
+ memcpy(m, &tmp, sizeof tmp);
+}
+
+/**
+ * Rotates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to rotate
+ * @param angle the angle to rotate
+ * @param x the x component of the direction to rotate to
+ * @param y the y component of the direction to rotate to
+ * @param z the z component of the direction to rotate to
+ */
+static void
+rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+ double s, c;
+
+ sincos(angle, &s, &c);
+ GLfloat r[16] = {
+ x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
+ x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
+ x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
+ 0, 0, 0, 1
+ };
+
+ multiply(m, r);
+}
+
+
+/**
+ * Translates a 4x4 matrix.
+ *
+ * @param[in,out] m the matrix to translate
+ * @param x the x component of the direction to translate to
+ * @param y the y component of the direction to translate to
+ * @param z the z component of the direction to translate to
+ */
+static void
+translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
+
+ multiply(m, t);
+}
+
+/**
+ * Creates an identity 4x4 matrix.
+ *
+ * @param m the matrix make an identity matrix
+ */
+static void
+identity(GLfloat *m)
+{
+ GLfloat t[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Transposes a 4x4 matrix.
+ *
+ * @param m the matrix to transpose
+ */
+static void
+transpose(GLfloat *m)
+{
+ GLfloat t[16] = {
+ m[0], m[4], m[8], m[12],
+ m[1], m[5], m[9], m[13],
+ m[2], m[6], m[10], m[14],
+ m[3], m[7], m[11], m[15]};
+
+ memcpy(m, t, sizeof(t));
+}
+
+/**
+ * Inverts a 4x4 matrix.
+ *
+ * This function can currently handle only pure translation-rotation matrices.
+ * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
+ * for an explanation.
+ */
+static void
+invert(GLfloat *m)
+{
+ GLfloat t[16];
+ identity(t);
+
+ // Extract and invert the translation part 't'. The inverse of a
+ // translation matrix can be calculated by negating the translation
+ // coordinates.
+ t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];
+
+ // Invert the rotation part 'r'. The inverse of a rotation matrix is
+ // equal to its transpose.
+ m[12] = m[13] = m[14] = 0;
+ transpose(m);
+
+ // inv(m) = inv(r) * inv(t)
+ multiply(m, t);
+}
+
+/**
+ * Calculate a perspective projection transformation.
+ *
+ * @param m the matrix to save the transformation in
+ * @param fovy the field of view in the y direction
+ * @param aspect the view aspect ratio
+ * @param zNear the near clipping plane
+ * @param zFar the far clipping plane
+ */
+void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+ GLfloat tmp[16];
+ identity(tmp);
+
+ double sine, cosine, cotangent, deltaZ;
+ GLfloat radians = fovy / 2 * M_PI / 180;
+
+ deltaZ = zFar - zNear;
+ sincos(radians, &sine, &cosine);
+
+ if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
+ return;
+
+ cotangent = cosine / sine;
+
+ tmp[0] = cotangent / aspect;
+ tmp[5] = cotangent;
+ tmp[10] = -(zFar + zNear) / deltaZ;
+ tmp[11] = -1;
+ tmp[14] = -2 * zNear * zFar / deltaZ;
+ tmp[15] = 0;
+
+ memcpy(m, tmp, sizeof(tmp));
+}
+
+/**
+ * Draws a gear.
+ *
+ * @param gear the gear to draw
+ * @param transform the current transformation matrix
+ * @param x the x position to draw the gear at
+ * @param y the y position to draw the gear at
+ * @param angle the rotation angle of the gear
+ * @param color the color of the gear
+ */
+static void
+draw_gear(struct gear *gear, GLfloat *transform,
+ GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4])
+{
+ GLfloat model_view[16];
+ GLfloat normal_matrix[16];
+ GLfloat model_view_projection[16];
+
+ /* Translate and rotate the gear */
+ memcpy(model_view, transform, sizeof (model_view));
+ translate(model_view, x, y, 0);
+ rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1);
+
+ /* Create and set the ModelViewProjectionMatrix */
+ memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection));
+ multiply(model_view_projection, model_view);
+
+ glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE,
+ model_view_projection);
+
+ /*
+ * Create and set the NormalMatrix. It's the inverse transpose of the
+ * ModelView matrix.
+ */
+ memcpy(normal_matrix, model_view, sizeof (normal_matrix));
+ invert(normal_matrix);
+ transpose(normal_matrix);
+ glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix);
+
+ /* Set the gear color */
+ glUniform4fv(MaterialColor_location, 1, color);
+
+ /* Set the vertex buffer object to use */
+ glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+
+ /* Set up the position of the attributes in the vertex buffer object */
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), NULL);
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+ 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
+
+ /* Enable the attributes */
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+
+ /* Draw the triangle strips that comprise the gear */
+ int n;
+ for (n = 0; n < gear->nstrips; n++)
+ glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count);
+
+ /* Disable the attributes */
+ glDisableVertexAttribArray(1);
+ glDisableVertexAttribArray(0);
+}
+
+/**
+ * Draws the gears.
+ */
+static void
+gears_draw(void)
+{
+ const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+ GLfloat transform[16];
+ identity(transform);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* Translate and rotate the view */
+ translate(transform, 0, 0, -20);
+ rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0);
+ rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0);
+ rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1);
+
+ /* Draw the gears */
+ draw_gear(gear1, transform, -3.0, -2.0, angle, red);
+ draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green);
+ draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue);
+
+ glutSwapBuffers();
+}
+
+/**
+ * Handles a new window size or exposure.
+ *
+ * @param width the window width
+ * @param height the window height
+ */
+static void
+gears_reshape(int width, int height)
+{
+ /* Update the projection matrix */
+ perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0);
+
+ /* Set the viewport */
+ glViewport(0, 0, (GLint) width, (GLint) height);
+}
+
+/**
+ * Handles special glut events.
+ *
+ * @param special the event to handle.
+ */
+static void
+gears_special(int special, int crap, int morecrap)
+{
+ switch (special) {
+ case GLUT_KEY_LEFT:
+ view_rot[1] += 5.0;
+ break;
+ case GLUT_KEY_RIGHT:
+ view_rot[1] -= 5.0;
+ break;
+ case GLUT_KEY_UP:
+ view_rot[0] += 5.0;
+ break;
+ case GLUT_KEY_DOWN:
+ view_rot[0] -= 5.0;
+ break;
+ }
+}
+
+static void
+gears_idle(void)
+{
+ static int frames = 0;
+ static double tRot0 = -1.0, tRate0 = -1.0;
+ double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+
+ if (tRot0 < 0.0)
+ tRot0 = t;
+ dt = t - tRot0;
+ tRot0 = t;
+
+ /* advance rotation for next frame */
+ angle += 70.0 * dt; /* 70 degrees per second */
+ if (angle > 3600.0)
+ angle -= 3600.0;
+
+ glutPostRedisplay();
+ frames++;
+
+ if (tRate0 < 0.0)
+ tRate0 = t;
+ if (t - tRate0 >= 5.0) {
+ GLfloat seconds = t - tRate0;
+ GLfloat fps = frames / seconds;
+ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+ fps);
+ tRate0 = t;
+ frames = 0;
+ }
+}
+
+static const char vertex_shader[] =
+"attribute vec3 position;\n"
+"attribute vec3 normal;\n"
+"\n"
+"uniform mat4 ModelViewProjectionMatrix;\n"
+"uniform mat4 NormalMatrix;\n"
+"uniform vec4 LightSourcePosition;\n"
+"uniform vec4 MaterialColor;\n"
+"\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" // Transform the normal to eye coordinates\n"
+" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n"
+"\n"
+" // The LightSourcePosition is actually its direction for directional light\n"
+" vec3 L = normalize(LightSourcePosition.xyz);\n"
+"\n"
+" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n"
+" // to get the actual color that we will use to draw this vertex with\n"
+" float diffuse = max(dot(N, L), 0.0);\n"
+" Color = diffuse * MaterialColor;\n"
+"\n"
+" // Transform the position to clip coordinates\n"
+" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n"
+"}";
+
+static const char fragment_shader[] =
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"varying vec4 Color;\n"
+"\n"
+"void main(void)\n"
+"{\n"
+" vec2 d = dFdx(Color.xy);\n"
+" gl_FragColor = Color;\n"
+"}";
+
+static void
+gears_init(void)
+{
+ GLuint v, f, program;
+ const char *p;
+ char msg[512];
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ /* Compile the vertex shader */
+ p = vertex_shader;
+ v = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(v, 1, &p, NULL);
+ glCompileShader(v);
+ glGetShaderInfoLog(v, sizeof msg, NULL, msg);
+ printf("vertex shader info: %s\n", msg);
+
+ /* Compile the fragment shader */
+ p = fragment_shader;
+ f = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(f, 1, &p, NULL);
+ glCompileShader(f);
+ glGetShaderInfoLog(f, sizeof msg, NULL, msg);
+ printf("fragment shader info: %s\n", msg);
+
+ /* Create and link the shader program */
+ program = glCreateProgram();
+ glAttachShader(program, v);
+ glAttachShader(program, f);
+ glBindAttribLocation(program, 0, "position");
+ glBindAttribLocation(program, 1, "normal");
+
+ glLinkProgram(program);
+ glGetProgramInfoLog(program, sizeof msg, NULL, msg);
+ printf("info: %s\n", msg);
+
+ /* Enable the shaders */
+ glUseProgram(program);
+
+ /* Get the locations of the uniforms so we can access them */
+ ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
+ NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix");
+ LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition");
+ MaterialColor_location = glGetUniformLocation(program, "MaterialColor");
+
+ /* Set the LightSourcePosition uniform which is constant throught the program */
+ glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition);
+
+ /* make the gears */
+ gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
+ gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7);
+ gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7);
+}
+
+int
+main(int argc, char *argv[])
+{
+ /* Initialize the window */
+ glutInit(&argc, argv);
+ glutInitWindowSize(300, 300);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+
+ glutCreateWindow("es2gears");
+
+ /* Set up glut callback functions */
+ gears_idle();
+ glutReshapeFunc(gears_reshape);
+ glutDisplayFunc(gears_draw);
+ glutSpecialFunc(gears_special);
+
+ /* Initialize the gears */
+ gears_init();
+
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/tests/hello_world_gles_shell.html b/tests/hello_world_gles_shell.html
index d3429e3a..343ddb64 100644
--- a/tests/hello_world_gles_shell.html
+++ b/tests/hello_world_gles_shell.html
@@ -36,7 +36,7 @@
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8888/report_gl_result?' + result, true);
xhr.send();
- setTimeout(function() { _glutDisplayFunc = function(){} }, 2000); // Stop rendering after a while
+ setTimeout(function() { window.close() }, 1000);
}
function doTest() {
var firstImage = Module.canvas.toDataURL();
diff --git a/tests/hello_world_sdl.cpp b/tests/hello_world_sdl.cpp
index 35aec303..b6401995 100644
--- a/tests/hello_world_sdl.cpp
+++ b/tests/hello_world_sdl.cpp
@@ -14,13 +14,13 @@ int main() {
*((char*)screen->pixels + i*256*4 + j*4 + 0) = i;
*((char*)screen->pixels + i*256*4 + j*4 + 1) = j;
*((char*)screen->pixels + i*256*4 + j*4 + 2) = 255-i;
- *((char*)screen->pixels + i*256*4 + j*4 + 3) = 255;
+ *((char*)screen->pixels + i*256*4 + j*4 + 3) = (i+j)%255; // actually ignored, since this is to the screen
}
}
if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
SDL_Flip(screen);
- printf("you should see a colored cube.\n");
+ printf("you should see a smoothly-colored square - no sharp lines but the square borders!\n");
printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |\"| quote: |'| less-than, greater-than, html-like tags: |<cheez></cheez>|\nanother line.\n");
SDL_Quit();
diff --git a/tests/htmltest.png b/tests/htmltest.png
new file mode 100644
index 00000000..980245ee
--- /dev/null
+++ b/tests/htmltest.png
Binary files differ
diff --git a/tests/i64_precise.txt b/tests/i64_precise.txt
new file mode 100644
index 00000000..69f1f306
--- /dev/null
+++ b/tests/i64_precise.txt
@@ -0,0 +1,128 @@
+unsigned 0: 0,5,5,18446744073709551611,0,0,0,0,0
+unsigned 1: 0,35,35,18446744073709551581,0,0,0,0,0
+unsigned 2: 1,195,196,18446744073709551422,195,0,195,1,0
+unsigned 3: 3,1020,1023,18446744073709550599,3060,0,340,3,0
+unsigned 4: 6,5195,5201,18446744073709546427,31170,0,865,6,5
+unsigned 5: 12,26165,26177,18446744073709525463,313980,0,2180,12,5
+unsigned 6: 25,131205,131230,18446744073709420436,3280125,0,5248,25,5
+unsigned 7: 51,656790,656841,18446744073708894877,33496290,0,12878,51,12
+unsigned 8: 102,3285485,3285587,18446744073706266233,335119470,0,32210,102,65
+unsigned 9: 204,16430495,16430699,18446744073693121325,3351820980,0,80541,204,131
+unsigned 10: 409,82158615,82159024,18446744073627393410,33602873535,0,200876,409,331
+unsigned 11: 819,410805360,410806179,18446744073298747075,336449589840,0,501593,819,693
+unsigned 12: 1638,2054051375,2054053013,18446744071655501879,3364536152250,0,1253999,1638,1013
+unsigned 13: 3276,10270306025,10270309301,18446744063439248867,33645522537900,0,3135014,3276,161
+unsigned 14: 6553,51351628425,51351634978,18446744022357929744,336507221069025,0,7836354,6553,663
+unsigned 15: 13107,256758338730,256758351837,18446743816951225993,3365331545734110,0,19589405,13107,7395
+unsigned 16: 26214,1283792086865,1283792113079,18446742789917490965,33653325765079110,0,48973528,26214,23873
+unsigned 17: 52428,6418961220755,6418961273183,18446737654748383289,336533298881743140,0,122433837,52428,14519
+unsigned 18: 104857,32094807676635,32094807781492,18446711978901979838,3365365248548916195,0,306081689,104857,13162
+unsigned 19: 209715,160474041528900,160474041738615,18446583599668232431,15207069545523711884,0,765200589,209715,6765
+unsigned 20: 419430,802370213935955,802370214355385,18445941703496035091,4496745504385676562,0,1913001487,419430,243545
+unsigned 21: 838860,4011851082262685,4011851083101545,18442732222628127791,8073977451737544988,0,4782503733,838860,798305
+unsigned 22: 1677721,20059255436479245,20059255438156966,18426684818274750092,6972899699173253061,0,11956252223,1677721,655462
+unsigned 23: 3355443,100296277232727870,100296277236083313,18346447796480179189,14489229932752165722,0,29890621665,3355443,1255275
+unsigned 24: 6710886,501481386264302645,501481386271013531,17945262687451959857,15765766351451925278,0,74726554178,6710886,2920937
+unsigned 25: 13421772,2507406931522839815,2507406931536261587,15939337142200133573,10086413084431357332,0,186816385461,13421772,1182923
+unsigned 26: 26843545,12537034658016852255,12537034658043695800,5909709415719542906,2731509698427185799,0,467040946269,26843545,2368650
+unsigned 27: 53687091,7344941069760912792,7344941069814599883,11101803004002325915,16256528535618547016,0,136810189059,53687091,23175423
+unsigned 28: 107374182,18277961276705625079,18277961276812999261,168782797111300719,15164270991448465002,0,170226780183,107374182,62189773
+unsigned 29: 214748364,17602830091911144401,17602830092125892765,843913982013155579,4760510224565868172,0,81969565513,214748364,203573669
+unsigned 30: 429496729,14227174171159966481,14227174171589463210,4219569902979081864,9259055794720517673,0,33125221242,429496729,319649063
+unsigned 31: 858993459,15795638647556079442,15795638648415072901,2651105427012465633,8773778578690814806,0,18388543570,858993459,389570812
+unsigned 32: 1717986918,5191216968711994521,5191216970429981439,13255527106715544013,2882763035818302198,0,3021685971,1717986918,229867143
+unsigned 33: 3435973836,7509340821390028539,7509340824826002375,10937403255755496913,3002188606886016004,0,2185505821,3435973836,2008329183
+unsigned 34: 6871947673,653216062610254563,653216069482202236,17793528017971244726,1160311421120597163,0,95055447,6871947673,4792629732
+unsigned 35: 13743895347,3266080519209703020,3266080532953598367,15180663568243743943,7490496812310051716,0,237638634,13743895347,3109667022
+unsigned 36: 27487790694,16330403008365375515,16330403035853166209,2116341092831966795,8496689265331596482,0,594096600,27487790694,15548335115
+unsigned 37: 54975581388,7865039571622391941,7865039626597973329,10581704557062741063,3801217959335798268,0,143064236,54975581388,21692352373
+unsigned 38: 109951162777,2431711359960298133,2431711469911460910,16015032823700416260,10929097356750440461,0,22116285,109951162777,107902774688
+unsigned 39: 219902325555,12158560098336373990,12158560318238699545,6288184195275503181,3390366976150811602,0,55290729,219902325555,209605094395
+unsigned 40: 439804651110,5452574867622981757,5452575307427632867,12994169645891220969,4388876164940275662,0,12397719,439804651110,388268163667
+unsigned 41: 879609302220,8816143458544890479,8816144338154192699,9630601494773963357,18063307631679153268,0,10022794,879609302220,621910087799
+unsigned 42: 1759218604441,7187255533584415783,7187257292803020224,11259490299343740274,10731539484643328591,0,4085481,1759218604441,1350294194662
+unsigned 43: 3518437208883,17489586370770660544,17489589889207869427,957161221376099955,6745745258281429568,0,4970839,3518437208883,1473803897707
+unsigned 44: 7036874417766,13661061112131362751,13661068149005780517,4785689998452606631,1049124659338985498,0,1941353,7036874417766,3850578085353
+unsigned 45: 14073748835532,12965284445760691897,12965298519509527429,5481473701697695251,3112351931422336876,0,921238,14073748835532,12216012863281
+unsigned 46: 28147497671065,9486612220139870617,9486640367637541682,8960160001067352064,11094552886493166961,0,337032,28147497671065,4785065491537
+unsigned 47: 56294995342131,10540417378210381818,10540473673205723949,7906382990494511929,3425601976498736334,0,187235,56294995342131,23925326484033
+unsigned 48: 112589990684262,15810287593493069793,15810400183483754055,2636569070207166085,4740441117117290918,0,140423,112589990684262,63331636946967
+unsigned 49: 225179981368524,5267839372347670371,5268064552329038895,13179129881343249769,3129072874530825956,0,23393,225179981368524,204068193788439
+unsigned 50: 450359962737049,7899208187469855979,7899658547432593028,10547986246202432686,9662536335886195571,0,17539,450359962737049,344801024753568
+unsigned 51: 900719925474099,2616063588812288148,2616964308737762247,15831581204822737567,18056837904917260668,0,2904,900719925474099,372925235504652
+unsigned 52: 1801439850948198,13107339541825663715,13109140981676611913,5341205971734836099,3467025862604273778,0,7276,1801439850948198,63186326575067
+unsigned 53: 3602879701896396,10250508683528109677,10254111563230006073,8199838269883338335,8794376607022815964,0,2845,3602879701896396,315931632863057
+unsigned 54: 7205759403792793,14467141661278337053,14474347420682129846,3986808171835007356,17354123729136361045,0,2007,7205759403792793,5182537866201502
+unsigned 55: 14411518807585587,17211648867376814222,17226060386184399809,1249506725140322981,17050849970911342154,0,1194,14411518807585587,4295411119623344
+unsigned 56: 28823037615171174,12703613606273432261,12732436643888603435,5771953505051290529,11664739411905079422,0,440,28823037615171174,21477055598115701
+unsigned 57: 57646075230342348,9042526938693641687,9100173013923984035,9461863210246252277,16227931067794422612,0,156,57646075230342348,49739202760235399
+unsigned 58: 115292150460684697,10048528802959375663,10163820953420060360,8513507421210860650,10457660234102286359,0,87,115292150460684697,18111712879807024
+unsigned 59: 230584300921369395,16807920381198316008,17038504682119685403,1869407993432605003,16929834404840843576,0,72,230584300921369395,205850714859719568
+unsigned 60: 461168601842738790,17170154638794455431,17631323240637194221,1737758036757834975,7428164801607120330,0,37,461168601842738790,106916370613120201
+unsigned 61: 922337203685477580,7452110880706682785,8374448084392160365,11916970396688346411,17096741387571593292,0,8,922337203685477580,73413251222862145
+unsigned 62: 1844674407370955161,9590438292969086497,11435112700340041658,10700980188111420280,7158457875815234233,0,5,1844674407370955161,367066256114310692
+unsigned 63: 3689348814741910323,11058703317426329250,14748052132168239573,11077389571025132689,16235003410224285766,0,2,3689348814741910323,3680005687942508604
+signed 0: 0,5,5,-5,0,0,0,0,0
+signed 1: 0,-35,-35,35,0,0,0,0,0
+signed 2: -1,-155,-156,154,155,0,155,-1,0
+signed 3: -2,740,738,-742,-1480,0,-370,-2,0
+signed 4: -4,3770,3766,-3774,-15080,0,-942,-4,2
+signed 5: -9,-18990,-18999,18981,170910,0,2110,-9,0
+signed 6: -18,-94675,-94693,94657,1704150,0,5259,-18,-13
+signed 7: 36,472825,472861,-472789,17021700,0,13134,36,1
+signed 8: -97,2365585,2365488,-2365682,-229461745,0,-24387,-97,46
+signed 9: -138,-11830000,-11830138,11829862,1632540000,0,85724,-138,-88
+signed 10: -295,-59145570,-59145865,59145275,17447943150,0,200493,-295,-135
+signed 11: -584,295719085,295718501,-295719669,-172699945640,0,-506368,-584,173
+signed 12: -1170,1478612985,1478611815,-1478614155,-1729977192450,0,-1263771,-1170,915
+signed 13: -2340,-7393100035,-7393102375,7393097695,17299854081900,0,3159444,-2340,-1075
+signed 14: 4681,-36965429955,-36965425274,36965434636,-173035177619355,0,-7896908,4681,-3607
+signed 15: -12483,184826962530,184826950047,-184826975013,-2307194973261990,0,-14806293,-12483,7011
+signed 16: -17684,924135077915,924135060231,-924135095599,-16342404717848860,0,-52258260,-17684,8075
+signed 17: -37796,-4620675956515,-4620675994311,4620675918719,174643068452440940,0,122253041,-37796,-18879
+signed 18: -74782,-23103378660835,-23103378735617,23103378586053,1727716863014562970,0,308943043,-74782,-19209
+signed 19: -149835,115516891056645,115516890906810,-115516891206480,1138270702237148041,0,-770960663,-149835,116040
+signed 20: -299580,577584459776930,577584459477350,-577584460076510,-7012055796586724856,0,-1927980705,-299580,173030
+signed 21: 599190,-2887922307872510,-2887922307273320,2887922308471700,3579775274568585004,0,-4819710455,599190,-341060
+signed 22: -1597831,-14439611515395080,-14439611516992911,14439611513797249,-4817928955413000136,0,9037007991,-1597831,-127559
+signed 23: -2263592,72198057543021515,72198057540757923,-72198057545285107,-7239720930239415736,0,-31895349313,-2263592,909219
+signed 24: -4837874,360990287787675695,360990287782837821,-360990287792513569,1520893864324420754,0,-74617546423,-4837874,4050993
+signed 25: -9572186,-1804951439081961265,-1804951439091533451,1804951439072389079,-284040605827480006,0,188562094288,-9572186,-7687697
+signed 26: -19178892,-9024757195122122935,-9024757195141301827,9024757195102944043,3158545232664844052,0,470556755579,-19178892,-2084467
+signed 27: -38346278,8230297827616317263,8230297827577970985,-8230297827654663541,-2447170876606408634,0,-214630943519,-38346278,34444981
+signed 28: 76696392,4258000991812928973,4258000991889625365,-4258000991736232581,-4010249384068861784,0,55517617984,76696392,5815245
+signed 29: -204522434,-2843260888422929769,-2843260888627452203,2843260888218407335,-3330061828535700334,0,13901951159,-204522434,-35128763
+signed 30: -289739796,4230439635940999721,4230439635651259925,-4230439636230739517,-8819265314490703668,0,-14600823547,-289739796,1223309
+signed 31: -619247950,-2705454115284166249,-2705454115903414199,2705454114664918299,4237355741738226942,0,4368935117,-619247950,-398906099
+signed 32: -1225239782,4919473515667317101,4919473514442077319,-4919473516892556883,8469738706080185362,0,-4015110828,-1225239782,62757605
+signed 33: -2454898270,-6150623541450507939,-6150623543905406209,6150623538995609669,-6720592984569904678,0,2505449458,-2454898270,-1433870279
+signed 34: -4908323638,6140370513791418107,6140370508883094469,-6140370518699741745,-2321546656369961458,0,-1251011743,-4908323638,4208937073
+signed 35: 9817138243,6191635431204939047,6191635441022077290,-6191635421387800804,1329921992230270261,0,630696571,9817138243,4311874294
+signed 36: -26178871659,-5935310598711333102,-5935310624890204761,5935310572532461443,-1523401759741279878,0,226721406,-26178871659,-8689300548
+signed 37: -37086693937,-7216935710162846787,-7216935747249540724,7216935673076152850,4375670093386346195,0,194596361,-37086693937,-28501883530
+signed 38: -79263737669,808810785560934332,808810706297196663,-808810864824672001,1308775974572414548,0,-10204045,-79263737669,39518263227
+signed 39: -156830692073,-4044056280265052755,-4044056437095744828,4044056123434360682,3200853909245289355,0,25786127,-156830692073,-136972781484
+signed 40: -314226978567,-1773532614211033644,-1773532928438012211,1773532299984055077,149458714710412084,0,5644113,-314226978567,-39530307573
+signed 41: -628265425661,8867653647073783295,8867653018808357634,-8867654275339208956,1335113139221865725,0,-14114502,-628265425661,40050747473
+signed 42: 1256593695147,7444798936855240458,7444800193448935605,-7444797680261545311,194995390784062894,0,5924587,1256593695147,266305361169
+signed 43: -3350895572451,-330556800290685833,-330560151186258284,330553449395113382,-3084978225808244869,0,98647,-3350895572451,-1004755112036
+signed 44: -4747096823988,-1652712795001069340,-1652717542097893328,1652708047904245352,888305014260137904,0,348152,-4747096823988,-1541535999164
+signed 45: -10145758421614,8263411788629022480,8263401642870600866,-8263421934387444094,1433933448381331232,0,-814469,-10145758421614,6072735489514
+signed 46: -20074328585350,4423871910654789418,4423851836326204068,-4423891984983374768,1087756533121529860,0,-220374,-20074328585350,11822986868518
+signed 47: -40221053256659,-3673218795363245364,-3673259016416502023,3673178574309988705,-3788250272949359140,0,91325,-40221053256659,-31106698862189
+signed 48: -80417974484665,81856366510594781,81775948536110116,-81936784485079446,3556652555309224011,0,-1017,-80417974484665,71286459690476
+signed 49: 160843992978882,-411694492447657140,-411533648454678258,411855336440636022,8646015829301599128,0,-2559,160843992978882,-94714414698102
+signed 50: -428914633273835,-2052038742739178170,-2052467657372452005,2051609828105904335,4194688249318378174,0,4784,-428914633273835,-111137157151530
+signed 51: -607628393470471,-8195664785915717831,-8196272414309188302,8195057157522247360,245300141642486641,0,13487,-607628393470471,-580643179475454
+signed 52: -1298657077966675,-4065355925989985798,-4066654583067952473,4064057268912019123,1136007313742779890,0,3130,-1298657077966675,-559271954293048
+signed 53: -2569514058924772,1841492845356505789,1838923331297581017,-1844062359415430561,6068344375485822380,0,-716,-2569514058924772,1720779166369037
+signed 54: -5148294816852404,-9162055424674236611,-9167203719491089015,9156907129857384207,-6087205165210098660,0,1779,-5148294816852404,-3238945493809895
+signed 55: -10293500734037188,8762386464941522003,8752092964207484815,-8772679965675559191,8399093139116719220,0,-851,-10293500734037188,2617340275875015
+signed 56: 20588031101296916,7227264643807960523,7247852674909257439,-7206676612706663607,-3352533841896882468,0,351,20588031101296916,865727252743007
+signed 57: -54901073059050929,-66351167506463323,-121252240565514252,11450094447412394,1896642381847523307,0,1,-54901073059050929,-11450094447412394
+signed 58: -77776434364220271,834890677930987460,757114243566767189,-912667112295207731,-3500275542106939900,0,-10,-77776434364220271,57126334288784750
+signed 59: -166228105979734405,-6667874979350953385,-6834103085330687790,6501646873371218980,-4513011972483376691,0,40,-166228105979734405,-18750740161577185
+signed 60: -328897799542370857,8487580243799899162,8158682444257528305,-8816478043342270019,-905439778191045674,0,-25,-328897799542370857,265135255240627737
+signed 61: -658981736557107698,3017604953772543563,2358623217215435865,-3676586690329651261,-378165734266082790,0,-4,-658981736557107698,381678007544112771
+signed 62: -1317568093956760068,-2041941969204984387,-3359510063161744455,724373875248224319,-7186442770938425588,0,1,-1317568093956760068,-724373875248224319
+signed 63: 2635267980966005246,7574178278953946467,-8237297813789599903,-4938910297987941221,1110862422097806138,0,2,2635267980966005246,2303642317021935975
diff --git a/tests/msvc10/README.txt b/tests/msvc10/README.txt
new file mode 100644
index 00000000..49a2a478
--- /dev/null
+++ b/tests/msvc10/README.txt
@@ -0,0 +1,5 @@
+This folder contains Visual Studio 2010 project files for Emscripten tests.
+
+Building the solution requires the vs-tool plugin, which enables Emscripten builds to be invoked from within Visual Studio.
+
+Find the vs-tool plugin from here https://github.com/juj/vs-tool
diff --git a/tests/msvc10/dlmalloc_test.vcxproj b/tests/msvc10/dlmalloc_test.vcxproj
new file mode 100644
index 00000000..087ff17f
--- /dev/null
+++ b/tests/msvc10/dlmalloc_test.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A44C4C27-F173-47D0-8626-59A21D86AC1E}</ProjectGuid>
+ <RootNamespace>dlmalloc_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dlmalloc_test.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/emscripten_api_browser.vcxproj b/tests/msvc10/emscripten_api_browser.vcxproj
new file mode 100644
index 00000000..9f4a05fd
--- /dev/null
+++ b/tests/msvc10/emscripten_api_browser.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{65E0ED61-A813-4AEB-8DB0-A58657858EE2}</ProjectGuid>
+ <RootNamespace>emscripten_api_browser</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\emscripten_api_browser.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/fannkuch.vcxproj b/tests/msvc10/fannkuch.vcxproj
new file mode 100644
index 00000000..9b325ea3
--- /dev/null
+++ b/tests/msvc10/fannkuch.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C29BBEE3-02D1-459A-B8BA-832A3439F12D}</ProjectGuid>
+ <RootNamespace>fannkuch</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\fannkuch.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/fasta.vcxproj b/tests/msvc10/fasta.vcxproj
new file mode 100644
index 00000000..d0c10027
--- /dev/null
+++ b/tests/msvc10/fasta.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DDB7FF8E-EC42-4406-832C-F2B043D8760E}</ProjectGuid>
+ <RootNamespace>fasta</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\fasta.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/files.vcxproj b/tests/msvc10/files.vcxproj
new file mode 100644
index 00000000..cba0f3a0
--- /dev/null
+++ b/tests/msvc10/files.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BE6A123E-9729-44A3-976F-3C06A3724894}</ProjectGuid>
+ <RootNamespace>files</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\files.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_10_MultiTexture.vcxproj b/tests/msvc10/glbook_10_MultiTexture.vcxproj
new file mode 100644
index 00000000..b59fda0a
--- /dev/null
+++ b/tests/msvc10/glbook_10_MultiTexture.vcxproj
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}</ProjectGuid>
+ <RootNamespace>glbook_10_MultiTexture</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <None Include="..\glbook\Chapter_10\MultiTexture\basemap.tga" />
+ <None Include="..\glbook\Chapter_10\MultiTexture\lightmap.tga" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_10\MultiTexture\MultiTexture.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_11_Multisample.vcxproj b/tests/msvc10/glbook_11_Multisample.vcxproj
new file mode 100644
index 00000000..ae5170be
--- /dev/null
+++ b/tests/msvc10/glbook_11_Multisample.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AD9E59DF-1628-4081-8672-212A7103FAAD}</ProjectGuid>
+ <RootNamespace>glbook_11_Multisample</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_11\Multisample\Multisample.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_11_Stencil_Test.vcxproj b/tests/msvc10/glbook_11_Stencil_Test.vcxproj
new file mode 100644
index 00000000..d72d7fa6
--- /dev/null
+++ b/tests/msvc10/glbook_11_Stencil_Test.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2D60F3E0-B83A-4442-94D3-AB4B2F068476}</ProjectGuid>
+ <RootNamespace>glbook_11_Stencil_Test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_11\Stencil_Test\Stencil_Test.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_13_ParticleSystem.vcxproj b/tests/msvc10/glbook_13_ParticleSystem.vcxproj
new file mode 100644
index 00000000..458d76fa
--- /dev/null
+++ b/tests/msvc10/glbook_13_ParticleSystem.vcxproj
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3E62931D-2795-4BD1-8AA7-55F5440AD293}</ProjectGuid>
+ <RootNamespace>glbook_13_ParticleSystem</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_13\ParticleSystem\ParticleSystem.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\glbook\Chapter_13\ParticleSystem\smoke.tga" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj b/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
new file mode 100644
index 00000000..654164b3
--- /dev/null
+++ b/tests/msvc10/glbook_15_Hello_Triangle_KD.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A971FFED-3417-452B-B488-6D4F9F257847}</ProjectGuid>
+ <RootNamespace>glbook_15_Hello_Triangle_KD</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_15\Hello_Triangle_KD\Hello_Triangle_KD.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_2_Hello_Triangle.vcxproj b/tests/msvc10/glbook_2_Hello_Triangle.vcxproj
new file mode 100644
index 00000000..b992294d
--- /dev/null
+++ b/tests/msvc10/glbook_2_Hello_Triangle.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_2\Hello_Triangle\Hello_Triangle.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FA655211-CC00-4827-BBCB-B8749BB7671D}</ProjectGuid>
+ <RootNamespace>glbook_2_Hello_Triangle</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj b/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj
new file mode 100644
index 00000000..fb01c1da
--- /dev/null
+++ b/tests/msvc10/glbook_8_Simple_VertexShader.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}</ProjectGuid>
+ <RootNamespace>glbook_8_Simple_VertexShader</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_8\Simple_VertexShader\Simple_VertexShader.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_9_MipMap2D.vcxproj b/tests/msvc10/glbook_9_MipMap2D.vcxproj
new file mode 100644
index 00000000..1d747d1d
--- /dev/null
+++ b/tests/msvc10/glbook_9_MipMap2D.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}</ProjectGuid>
+ <RootNamespace>glbook_9_MipMap2D</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_9\MipMap2D\MipMap2D.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj b/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj
new file mode 100644
index 00000000..d9232e5d
--- /dev/null
+++ b/tests/msvc10/glbook_9_Simple_Texture2D.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A7C445F9-FCE6-48D5-9343-734071A59185}</ProjectGuid>
+ <RootNamespace>glbook_9_Simple_Texture2D</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_9\Simple_Texture2D\Simple_Texture2D.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj b/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj
new file mode 100644
index 00000000..c5c6ee1b
--- /dev/null
+++ b/tests/msvc10/glbook_9_Simple_TextureCubemap.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}</ProjectGuid>
+ <RootNamespace>glbook_9_Simple_TextureCubemap</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_9\Simple_TextureCubemap\Simple_TextureCubemap.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/glbook_9_TextureWrap.vcxproj b/tests/msvc10/glbook_9_TextureWrap.vcxproj
new file mode 100644
index 00000000..6cfbb0c8
--- /dev/null
+++ b/tests/msvc10/glbook_9_TextureWrap.vcxproj
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{982D6A44-9080-4A89-911E-BC1E495267D1}</ProjectGuid>
+ <RootNamespace>glbook_9_TextureWrap</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>$(SolutionDir)../glbook/Common</AdditionalIncludeDirectories>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\glbook\Chapter_9\TextureWrap\TextureWrap.c" />
+ <ClCompile Include="..\glbook\Common\esShader.c" />
+ <ClCompile Include="..\glbook\Common\esShapes.c" />
+ <ClCompile Include="..\glbook\Common\esTransform.c" />
+ <ClCompile Include="..\glbook\Common\esUtil.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\glbook\Common\esUtil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hashtest.vcxproj b/tests/msvc10/hashtest.vcxproj
new file mode 100644
index 00000000..fe0ca2ab
--- /dev/null
+++ b/tests/msvc10/hashtest.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{61D7F11F-25EE-4C2C-9D73-8601F68B055E}</ProjectGuid>
+ <RootNamespace>hashtest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hashtest.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_libcxx.vcxproj b/tests/msvc10/hello_libcxx.vcxproj
new file mode 100644
index 00000000..8bd201e5
--- /dev/null
+++ b/tests/msvc10/hello_libcxx.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}</ProjectGuid>
+ <RootNamespace>hello_libcxx</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_libcxx.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_malloc.vcxproj b/tests/msvc10/hello_malloc.vcxproj
new file mode 100644
index 00000000..6340257a
--- /dev/null
+++ b/tests/msvc10/hello_malloc.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DFBD530C-9163-4558-B607-2A226BCC8DC0}</ProjectGuid>
+ <RootNamespace>hello_malloc</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_malloc.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_c.vcxproj b/tests/msvc10/hello_world_c.vcxproj
new file mode 100644
index 00000000..be79a7b8
--- /dev/null
+++ b/tests/msvc10/hello_world_c.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{660E83C1-82AC-487C-BF5E-CFB6B82196BC}</ProjectGuid>
+ <RootNamespace>hello_world_c</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_cpp.vcxproj b/tests/msvc10/hello_world_cpp.vcxproj
new file mode 100644
index 00000000..31ff3034
--- /dev/null
+++ b/tests/msvc10/hello_world_cpp.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}</ProjectGuid>
+ <RootNamespace>hello_world_cpp</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_file.vcxproj b/tests/msvc10/hello_world_file.vcxproj
new file mode 100644
index 00000000..f076aba8
--- /dev/null
+++ b/tests/msvc10/hello_world_file.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}</ProjectGuid>
+ <RootNamespace>hello_world_file</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world_file.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_gles.vcxproj b/tests/msvc10/hello_world_gles.vcxproj
new file mode 100644
index 00000000..371a5115
--- /dev/null
+++ b/tests/msvc10/hello_world_gles.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world_gles.c" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}</ProjectGuid>
+ <RootNamespace>hello_world_gles</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_loop.vcxproj b/tests/msvc10/hello_world_loop.vcxproj
new file mode 100644
index 00000000..96d5b697
--- /dev/null
+++ b/tests/msvc10/hello_world_loop.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DB3B6C01-8CF9-4397-843E-403D5063F2DE}</ProjectGuid>
+ <RootNamespace>hello_world_loop</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world_loop.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_loop_malloc.vcxproj b/tests/msvc10/hello_world_loop_malloc.vcxproj
new file mode 100644
index 00000000..3302c42d
--- /dev/null
+++ b/tests/msvc10/hello_world_loop_malloc.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5C72F8EA-B852-49F6-A979-DE5011957BC7}</ProjectGuid>
+ <RootNamespace>hello_world_loop_malloc</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world_loop_malloc.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/hello_world_sdl.vcxproj b/tests/msvc10/hello_world_sdl.vcxproj
new file mode 100644
index 00000000..4b5ef9e3
--- /dev/null
+++ b/tests/msvc10/hello_world_sdl.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}</ProjectGuid>
+ <RootNamespace>hello_world_sdl</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\hello_world_sdl.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/new.vcxproj b/tests/msvc10/new.vcxproj
new file mode 100644
index 00000000..11ad95ae
--- /dev/null
+++ b/tests/msvc10/new.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5190107D-91B3-4EF8-82CB-08381DD19ABB}</ProjectGuid>
+ <RootNamespace>new</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\new.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/raytrace.vcxproj b/tests/msvc10/raytrace.vcxproj
new file mode 100644
index 00000000..9084d044
--- /dev/null
+++ b/tests/msvc10/raytrace.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}</ProjectGuid>
+ <RootNamespace>raytrace</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\raytrace.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_audio.vcxproj b/tests/msvc10/sdl_audio.vcxproj
new file mode 100644
index 00000000..80a48d90
--- /dev/null
+++ b/tests/msvc10/sdl_audio.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F28A1DE1-5949-4AF5-8901-A37871C2514E}</ProjectGuid>
+ <RootNamespace>sdl_audio</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_audio.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_canvas.vcxproj b/tests/msvc10/sdl_canvas.vcxproj
new file mode 100644
index 00000000..42215b38
--- /dev/null
+++ b/tests/msvc10/sdl_canvas.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_canvas.c" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}</ProjectGuid>
+ <RootNamespace>sdl_canvas</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_gl_read.vcxproj b/tests/msvc10/sdl_gl_read.vcxproj
new file mode 100644
index 00000000..de6233c1
--- /dev/null
+++ b/tests/msvc10/sdl_gl_read.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}</ProjectGuid>
+ <RootNamespace>sdl_gl_read</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_gl_read.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_image.vcxproj b/tests/msvc10/sdl_image.vcxproj
new file mode 100644
index 00000000..631ea5cd
--- /dev/null
+++ b/tests/msvc10/sdl_image.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{5CE874BD-2F32-4579-B682-4B74E5764F13}</ProjectGuid>
+ <RootNamespace>sdl_image</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_image.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_key.vcxproj b/tests/msvc10/sdl_key.vcxproj
new file mode 100644
index 00000000..3840256a
--- /dev/null
+++ b/tests/msvc10/sdl_key.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{1C5338A3-7020-4086-AE99-BC79EA3D42C1}</ProjectGuid>
+ <RootNamespace>sdl_key</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_key.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_mouse.vcxproj b/tests/msvc10/sdl_mouse.vcxproj
new file mode 100644
index 00000000..7d582eb3
--- /dev/null
+++ b/tests/msvc10/sdl_mouse.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{D3295E36-57BB-4C42-92D8-2AA150024256}</ProjectGuid>
+ <RootNamespace>sdl_mouse</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_mouse.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/sdl_ogl.vcxproj b/tests/msvc10/sdl_ogl.vcxproj
new file mode 100644
index 00000000..b96eac4d
--- /dev/null
+++ b/tests/msvc10/sdl_ogl.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}</ProjectGuid>
+ <RootNamespace>sdl_ogl</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\sdl_ogl.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/skinning_test_no_simd.vcxproj b/tests/msvc10/skinning_test_no_simd.vcxproj
new file mode 100644
index 00000000..b15dc996
--- /dev/null
+++ b/tests/msvc10/skinning_test_no_simd.vcxproj
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{678A07B3-3A25-40E4-8A36-7A399056188A}</ProjectGuid>
+ <RootNamespace>skinning_test_no_simd</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\skinning_test_no_simd.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/tests_msvc10.sln b/tests/msvc10/tests_msvc10.sln
new file mode 100644
index 00000000..67333016
--- /dev/null
+++ b/tests/msvc10/tests_msvc10.sln
@@ -0,0 +1,286 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_gles", "hello_world_gles.vcxproj", "{6A41CB2E-0022-47E1-89C5-FB2B558BEB91}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fannkuch", "fannkuch.vcxproj", "{C29BBEE3-02D1-459A-B8BA-832A3439F12D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fasta", "fasta.vcxproj", "{DDB7FF8E-EC42-4406-832C-F2B043D8760E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_9_Simple_Texture2D", "glbook_9_Simple_Texture2D.vcxproj", "{A7C445F9-FCE6-48D5-9343-734071A59185}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_9_Simple_TextureCubemap", "glbook_9_Simple_TextureCubemap.vcxproj", "{C5500D5B-9489-4109-A6E4-CF8F7E1518E7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_9_TextureWrap", "glbook_9_TextureWrap.vcxproj", "{982D6A44-9080-4A89-911E-BC1E495267D1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_10_MultiTexture", "glbook_10_MultiTexture.vcxproj", "{A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_11_Multisample", "glbook_11_Multisample.vcxproj", "{AD9E59DF-1628-4081-8672-212A7103FAAD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_11_Stencil_Test", "glbook_11_Stencil_Test.vcxproj", "{2D60F3E0-B83A-4442-94D3-AB4B2F068476}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_13_ParticleSystem", "glbook_13_ParticleSystem.vcxproj", "{3E62931D-2795-4BD1-8AA7-55F5440AD293}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_15_Hello_Triangle_KD", "glbook_15_Hello_Triangle_KD.vcxproj", "{A971FFED-3417-452B-B488-6D4F9F257847}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_8_Simple_VertexShader", "glbook_8_Simple_VertexShader.vcxproj", "{2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_9_MipMap2D", "glbook_9_MipMap2D.vcxproj", "{9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raytrace", "raytrace.vcxproj", "{2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_c", "hello_world_c.vcxproj", "{660E83C1-82AC-487C-BF5E-CFB6B82196BC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_cpp", "hello_world_cpp.vcxproj", "{5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_file", "hello_world_file.vcxproj", "{EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_malloc", "hello_malloc.vcxproj", "{DFBD530C-9163-4558-B607-2A226BCC8DC0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_libcxx", "hello_libcxx.vcxproj", "{19DB739D-7EEB-4B99-BB6D-C12F086B5F24}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_loop", "hello_world_loop.vcxproj", "{DB3B6C01-8CF9-4397-843E-403D5063F2DE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_loop_malloc", "hello_world_loop_malloc.vcxproj", "{5C72F8EA-B852-49F6-A979-DE5011957BC7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello_world_sdl", "hello_world_sdl.vcxproj", "{DA2F2979-2902-42BC-B8DA-6B18FE2AF444}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlmalloc_test", "dlmalloc_test.vcxproj", "{A44C4C27-F173-47D0-8626-59A21D86AC1E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emscripten_api_browser", "emscripten_api_browser.vcxproj", "{65E0ED61-A813-4AEB-8DB0-A58657858EE2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "files", "files.vcxproj", "{BE6A123E-9729-44A3-976F-3C06A3724894}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hashtest", "hashtest.vcxproj", "{61D7F11F-25EE-4C2C-9D73-8601F68B055E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "new", "new.vcxproj", "{5190107D-91B3-4EF8-82CB-08381DD19ABB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_audio", "sdl_audio.vcxproj", "{F28A1DE1-5949-4AF5-8901-A37871C2514E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_canvas", "sdl_canvas.vcxproj", "{CE360D01-4362-4FE4-A77E-8EF6E3F623CF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_gl_read", "sdl_gl_read.vcxproj", "{3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_image", "sdl_image.vcxproj", "{5CE874BD-2F32-4579-B682-4B74E5764F13}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_key", "sdl_key.vcxproj", "{1C5338A3-7020-4086-AE99-BC79EA3D42C1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_mouse", "sdl_mouse.vcxproj", "{D3295E36-57BB-4C42-92D8-2AA150024256}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdl_ogl", "sdl_ogl.vcxproj", "{670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "skinning_test_no_simd", "skinning_test_no_simd.vcxproj", "{678A07B3-3A25-40E4-8A36-7A399056188A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "twopart", "twopart.vcxproj", "{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glbook_2_Hello_Triangle", "glbook_2_Hello_Triangle.vcxproj", "{FA655211-CC00-4827-BBCB-B8749BB7671D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gles", "gles", "{9DCFC12B-65CB-4965-9F16-C63B467E2E9E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdl", "sdl", "{70A8D326-5CBD-4C8A-BE84-39B0528C2479}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{8E55380B-7067-47FF-8B6B-6D656B8D8CC3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "README", "README", "{AFB0F421-9B24-495D-B961-EA94780F36E5}"
+ ProjectSection(SolutionItems) = preProject
+ README.txt = README.txt
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Emscripten = Debug|Emscripten
+ Release|Emscripten = Release|Emscripten
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {A7C445F9-FCE6-48D5-9343-734071A59185}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7}.Release|Emscripten.Build.0 = Release|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {982D6A44-9080-4A89-911E-BC1E495267D1}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {AD9E59DF-1628-4081-8672-212A7103FAAD}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476}.Release|Emscripten.Build.0 = Release|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A971FFED-3417-452B-B488-6D4F9F257847}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {A971FFED-3417-452B-B488-6D4F9F257847}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A971FFED-3417-452B-B488-6D4F9F257847}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {A971FFED-3417-452B-B488-6D4F9F257847}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8}.Release|Emscripten.Build.0 = Release|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D}.Release|Emscripten.Build.0 = Release|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0}.Release|Emscripten.Build.0 = Release|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7}.Release|Emscripten.Build.0 = Release|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444}.Release|Emscripten.Build.0 = Release|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {BE6A123E-9729-44A3-976F-3C06A3724894}.Release|Emscripten.Build.0 = Release|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5190107D-91B3-4EF8-82CB-08381DD19ABB}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {5190107D-91B3-4EF8-82CB-08381DD19ABB}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5190107D-91B3-4EF8-82CB-08381DD19ABB}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {5190107D-91B3-4EF8-82CB-08381DD19ABB}.Release|Emscripten.Build.0 = Release|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E}.Release|Emscripten.Build.0 = Release|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF}.Release|Emscripten.Build.0 = Release|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0}.Release|Emscripten.Build.0 = Release|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {5CE874BD-2F32-4579-B682-4B74E5764F13}.Release|Emscripten.Build.0 = Release|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1}.Release|Emscripten.Build.0 = Release|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {D3295E36-57BB-4C42-92D8-2AA150024256}.Release|Emscripten.Build.0 = Release|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {678A07B3-3A25-40E4-8A36-7A399056188A}.Release|Emscripten.Build.0 = Release|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2}.Release|Emscripten.Build.0 = Release|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Emscripten.ActiveCfg = Debug|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Debug|Emscripten.Build.0 = Debug|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Emscripten.ActiveCfg = Release|Emscripten
+ {FA655211-CC00-4827-BBCB-B8749BB7671D}.Release|Emscripten.Build.0 = Release|Emscripten
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {A7C445F9-FCE6-48D5-9343-734071A59185} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {C5500D5B-9489-4109-A6E4-CF8F7E1518E7} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {982D6A44-9080-4A89-911E-BC1E495267D1} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {A2D564BE-34DE-43DC-B8F9-605CEF4BFC4B} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {AD9E59DF-1628-4081-8672-212A7103FAAD} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {2D60F3E0-B83A-4442-94D3-AB4B2F068476} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {3E62931D-2795-4BD1-8AA7-55F5440AD293} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {A971FFED-3417-452B-B488-6D4F9F257847} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {2FD5F24F-8B73-4C62-81D6-B6B866E5EC5E} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {9EB49BEC-C7A0-4AEE-AF19-AACB057DE08B} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {FA655211-CC00-4827-BBCB-B8749BB7671D} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {6A41CB2E-0022-47E1-89C5-FB2B558BEB91} = {9DCFC12B-65CB-4965-9F16-C63B467E2E9E}
+ {DDB7FF8E-EC42-4406-832C-F2B043D8760E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {2F3AD7E0-AA5D-4639-8F6A-53BDBD88EBD8} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {660E83C1-82AC-487C-BF5E-CFB6B82196BC} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {5970CDD4-FB0A-4E66-B7C9-DAD9E580628D} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {EB0B52B6-0177-4CEE-955D-3C7F052E5F5B} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {DFBD530C-9163-4558-B607-2A226BCC8DC0} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {19DB739D-7EEB-4B99-BB6D-C12F086B5F24} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {DB3B6C01-8CF9-4397-843E-403D5063F2DE} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {5C72F8EA-B852-49F6-A979-DE5011957BC7} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {A44C4C27-F173-47D0-8626-59A21D86AC1E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {65E0ED61-A813-4AEB-8DB0-A58657858EE2} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {BE6A123E-9729-44A3-976F-3C06A3724894} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {61D7F11F-25EE-4C2C-9D73-8601F68B055E} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {5190107D-91B3-4EF8-82CB-08381DD19ABB} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {678A07B3-3A25-40E4-8A36-7A399056188A} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {C896D890-9132-4A2D-8BA8-0EB6888FEAC2} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {C29BBEE3-02D1-459A-B8BA-832A3439F12D} = {8E55380B-7067-47FF-8B6B-6D656B8D8CC3}
+ {F28A1DE1-5949-4AF5-8901-A37871C2514E} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {CE360D01-4362-4FE4-A77E-8EF6E3F623CF} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {3EA4E5F5-67B6-4F83-95D7-E041FFF787B0} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {5CE874BD-2F32-4579-B682-4B74E5764F13} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {1C5338A3-7020-4086-AE99-BC79EA3D42C1} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {D3295E36-57BB-4C42-92D8-2AA150024256} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {670EA36B-AD2B-4BFC-8DD3-AE024736AFB2} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ {DA2F2979-2902-42BC-B8DA-6B18FE2AF444} = {70A8D326-5CBD-4C8A-BE84-39B0528C2479}
+ EndGlobalSection
+EndGlobal
diff --git a/tests/msvc10/tests_msvc10.vcxproj b/tests/msvc10/tests_msvc10.vcxproj
new file mode 100644
index 00000000..bb69b0e6
--- /dev/null
+++ b/tests/msvc10/tests_msvc10.vcxproj
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6FB6B535-11C3-4011-B06B-74ACD387DFCC}</ProjectGuid>
+ <RootNamespace>tests_msvc10</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/msvc10/twopart.vcxproj b/tests/msvc10/twopart.vcxproj
new file mode 100644
index 00000000..7d299984
--- /dev/null
+++ b/tests/msvc10/twopart.vcxproj
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Emscripten">
+ <Configuration>Debug</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Emscripten">
+ <Configuration>Release</Configuration>
+ <Platform>Emscripten</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{C896D890-9132-4A2D-8BA8-0EB6888FEAC2}</ProjectGuid>
+ <RootNamespace>twopart</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <PlatformToolset>emcc</PlatformToolset>
+ <ConfigurationType>HTMLPage</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Emscripten'">
+ <IntDir>$(Platform)\$(ProjectName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\twopart_main.cpp" />
+ <ClCompile Include="..\twopart_side.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/tests/pre_run_deps.cpp b/tests/pre_run_deps.cpp
new file mode 100644
index 00000000..41c06972
--- /dev/null
+++ b/tests/pre_run_deps.cpp
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <emscripten.h>
+
+int main() {
+ printf("main() called.\n");
+ int result = emscripten_run_script_int("Module.okk");
+ REPORT_RESULT();
+ return 1;
+}
+
diff --git a/tests/python/ccproxy.py b/tests/python/ccproxy.py
index 853b30f4..82750096 100644
--- a/tests/python/ccproxy.py
+++ b/tests/python/ccproxy.py
@@ -85,4 +85,4 @@ with open('ccproxy.log', 'a') as f:
print "Running:", call, newargs
-os.execvp(call, [call] + newargs)
+subprocess.call([call] + newargs)
diff --git a/tests/runner.py b/tests/runner.py
index 9dc7ab32..d10a7c40 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -14,9 +14,39 @@ will use 4 processes. To install nose do something like
'''
from subprocess import Popen, PIPE, STDOUT
-import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing
+import os, unittest, tempfile, shutil, time, inspect, sys, math, glob, tempfile, re, difflib, webbrowser, hashlib, threading, platform, BaseHTTPServer, multiprocessing, functools
+if len(sys.argv) == 1:
+ print '''
+==============================================================================
+Running the main part of the test suite. Don't forget to run the other parts!
+
+ sanity - tests for first run, etc., modifies ~/.emscripten
+ benchmark - run before and after each set of changes before pushing to
+ master, verify no regressions
+ browser - runs pages in a web browser
+
+To run one of those parts, do something like
+
+ python tests/runner.py sanity
+
+To run a specific set of tests, you can do things like
+
+ python tests/runner.py o1
+
+(that runs the o1 (-O1) tests). You can run individual tests with
+
+ python tests/runner.py test_hello_world
+
+Combinations work too, for example
+
+ python tests/runner.py browser.test_sdl_image
+==============================================================================
+
+'''
+ time.sleep(2)
+
# Setup
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -49,7 +79,7 @@ class RunnerCore(unittest.TestCase):
if not self.save_dir:
dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
else:
- dirname = EMSCRIPTEN_TEMP_DIR
+ dirname = CANONICAL_TEMP_DIR
if not os.path.exists(dirname):
os.makedirs(dirname)
self.working_dir = dirname
@@ -63,6 +93,8 @@ class RunnerCore(unittest.TestCase):
shutil.copy(os.path.join(self.get_dir(), name),
os.path.join(TEMP_DIR, self.id().replace('__main__.', '').replace('.test_', '.')+'.'+suff))
if not self.save_dir:
+ # rmtree() fails on Windows if the current working directory is inside the tree.
+ os.chdir(os.path.join(self.get_dir(), '..'))
shutil.rmtree(self.get_dir())
def skip(self, why):
@@ -135,7 +167,7 @@ class RunnerCore(unittest.TestCase):
transform = open(transform_filename, 'w')
transform.write('''
import sys
-sys.path += ['%s']
+sys.path += [%r]
''' % path_from_root(''))
transform.write(post1)
transform.write('''
@@ -163,6 +195,9 @@ process(sys.argv[1])
additional_files = final_additional_files
else:
# copy whole directory, and use a specific main .cpp file
+ # (rmtree() fails on Windows if the current working directory is inside the tree.)
+ if os.getcwd().startswith(os.path.abspath(dirname)):
+ os.chdir(os.path.join(dirname, '..'))
shutil.rmtree(dirname)
shutil.copytree(src, dirname)
shutil.move(os.path.join(dirname, main_file), filename)
@@ -224,12 +259,14 @@ process(sys.argv[1])
def run_native(self, filename, args):
Popen([filename+'.native'] + args, stdout=PIPE).communicate()[0]
- def assertIdentical(self, x, y):
- if x != y:
- raise Exception("Expected to have '%s' == '%s', diff:\n\n%s" % (
- limit_size(x), limit_size(y),
- limit_size(''.join([a.rstrip()+'\n' for a in difflib.unified_diff(x.split('\n'), y.split('\n'), fromfile='expected', tofile='actual')]))
- ))
+ def assertIdentical(self, values, y):
+ if type(values) not in [list, tuple]: values = [values]
+ for x in values:
+ if x == y: return # success
+ raise Exception("Expected to have '%s' == '%s', diff:\n\n%s" % (
+ limit_size(values[0]), limit_size(y),
+ limit_size(''.join([a.rstrip()+'\n' for a in difflib.unified_diff(x.split('\n'), y.split('\n'), fromfile='expected', tofile='actual')]))
+ ))
def assertContained(self, values, string, additional_info=''):
if type(values) not in [list, tuple]: values = [values]
@@ -253,7 +290,13 @@ process(sys.argv[1])
library_cache = {}
- def get_library(self, name, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True):
+ def get_build_dir(self):
+ ret = os.path.join(self.get_dir(), 'building')
+ if not os.path.exists(ret):
+ os.makedirs(ret)
+ return ret
+
+ def get_library(self, name, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True):
build_dir = self.get_build_dir()
output_dir = self.get_dir()
@@ -275,12 +318,20 @@ process(sys.argv[1])
return Building.build_library(name, build_dir, output_dir, generated_libs, configure, configure_args, make, make_args, self.library_cache, cache_name,
copy_project=True)
+ def clear(self):
+ for name in os.listdir(self.get_dir()):
+ try_delete(name)
+ emcc_debug = os.environ.get('EMCC_DEBUG')
+ if emcc_debug:
+ for name in os.listdir(EMSCRIPTEN_TEMP_DIR):
+ try_delete(os.path.join(EMSCRIPTEN_TEMP_DIR, name))
+
###################################################################################################
sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv)
-if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
+if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv):
# Tests
print "Running Emscripten tests..."
@@ -306,7 +357,6 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines)
if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and settings.py and the paths therein.' % EM_CONFIG)
for engine in js_engines:
- engine = filter(lambda arg: arg != '-n', engine) # SpiderMonkey issue 716255
js_output = self.run_generated_code(engine, filename + '.o.js', args)
if output_nicerizer is not None:
js_output = output_nicerizer(js_output)
@@ -569,13 +619,13 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv):
return 0;
}
'''
- self.do_run(src, '*1311918518731868200\n' +
+ self.do_run(src, '*1311918518731868041\n' +
'0,0,0,1,1\n' +
'1,0,1,0,1*\n' +
'*245127260211081*\n' +
'*245127260209443*\n' +
- '*18446744073709552000*\n' +
- '*576460752303423500*\n' +
+ '*18446744073709551615*\n' +
+ '*576460752303423487*\n' +
'm1: 127\n' +
'*123*\n' +
'*127*\n' +
@@ -801,6 +851,155 @@ m_divisor is 1091269979
'''
self.do_run(src, 'testu64a is 14746250828952703000\n')
+ def test_i64_precise(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <inttypes.h>
+ #include <stdio.h>
+
+ int main() {
+ uint64_t x = 0, y = 0;
+ for (int i = 0; i < 64; i++) {
+ x += 1ULL << i;
+ y += x;
+ x /= 3;
+ y *= 5;
+ printf("unsigned %d: %llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu\n", i, x, y, x+y, x-y, x*y, y ? x/y : 0, x ? y/x : 0, y ? x%y : 0, x ? y%x : 0);
+ }
+ int64_t x2 = 0, y2 = 0;
+ for (int i = 0; i < 64; i++) {
+ x2 += 1LL << i;
+ y2 += x2;
+ x2 /= 3 * (i % 7 ? -1 : 1);
+ y2 *= 5 * (i % 2 ? -1 : 1);
+ printf("signed %d: %lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld\n", i, x2, y2, x2+y2, x2-y2, x2*y2, y2 ? x2/y2 : 0, x2 ? y2/x2 : 0, y2 ? x2%y2 : 0, x2 ? y2%x2 : 0);
+ }
+ return 0;
+ }
+ '''
+ self.do_run(src, open(path_from_root('tests', 'i64_precise.txt')).read())
+
+ # Verify that without precision, we do not include the precision code
+ Settings.PRECISE_I64_MATH = 0
+ self.do_run(src, 'unsigned')
+ code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
+ assert 'goog.math.Long' not in code and 'jsbn' not in code, 'i64 precise math should not have been included if not asked for'
+
+ # Verify that even if we ask for precision, if it is not needed it is not included
+ Settings.PRECISE_I64_MATH = 1
+ src = '''
+ #include <inttypes.h>
+ #include <stdio.h>
+
+ int main(int argc, char **argv) {
+ uint64_t x = 2125299906845564, y = 1225891506842664;
+ if (argc == 12) {
+ x = x >> 1;
+ y = y >> 1;
+ }
+ x = x & 12ULL;
+ y = y | 12ULL;
+ x = x ^ y;
+ x <<= 2;
+ y >>= 3;
+ printf("*%llu, %llu*\\n", x, y);
+ }
+ '''
+ self.do_run(src, '*4903566027370624, 153236438355333*')
+ code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
+ assert 'goog.math.Long' not in code and 'jsbn' not in code, 'i64 precise math should not have been included if not actually used'
+
+ def test_i64_zextneg(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdint.h>
+ #include <stdio.h>
+
+ int main(int argc, char *argv[])
+ {
+ uint8_t byte = 0x80;
+ uint16_t two = byte;
+ uint32_t four = byte;
+ uint64_t eight = byte;
+
+ printf("value: %d,%d,%d,%lld.\n", byte, two, four, eight);
+
+ return 0;
+ }
+ '''
+ self.do_run(src, 'value: 128,128,128,128.')
+
+ def test_i64_7z(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdint.h>
+ #include <stdio.h>
+ uint64_t a, b;
+ int main(int argc, char *argv[])
+ {
+ a = argc;
+ b = argv[1][0];
+ if (a > a + b || a > a + b + 1) {
+ printf("one %lld, %lld", a, b);
+ return 0;
+ }
+ printf("zero %lld, %lld", a, b);
+ return 0;
+ }
+ '''
+ self.do_run(src, 'zero 2, 104', ['hallo'])
+
+ def test_i16_emcc_intrinsic(self):
+ Settings.CORRECT_SIGNS = 1 # Relevant to this test
+
+ src = r'''
+ #include <stdio.h>
+
+ int test(unsigned short a, unsigned short b) {
+ unsigned short result = a;
+ result += b;
+ if (result < b) printf("C!");
+ return result;
+ }
+
+ int main(void) {
+ printf(",%d,", test(0, 0));
+ printf(",%d,", test(1, 1));
+ printf(",%d,", test(65535, 1));
+ printf(",%d,", test(1, 65535));
+ printf(",%d,", test(32768, 32767));
+ printf(",%d,", test(32768, 32768));
+ return 0;
+ }
+ '''
+ self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,')
+
+ def test_sha1(self):
+ if self.emcc_args == None: return self.skip('needs ta2')
+
+ self.do_run(open(path_from_root('tests', 'sha1.c')).read(), 'SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6')
+
+ def test_cube2md5(self):
+ if self.emcc_args == None: return self.skip('needs emcc')
+ self.emcc_args += ['--embed-file', 'cube2md5.txt']
+ shutil.copyfile(path_from_root('tests', 'cube2md5.txt'), os.path.join(self.get_dir(), 'cube2md5.txt'))
+ self.do_run(open(path_from_root('tests', 'cube2md5.cpp')).read(), open(path_from_root('tests', 'cube2md5.ok')).read())
+
+ def test_cube2hash(self):
+ # A good test of i64 math
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
+ self.do_run('', 'Usage: hashstring <seed>',
+ libraries=self.get_library('cube2hash', ['cube2hash.bc'], configure=None),
+ includes=[path_from_root('tests', 'cube2hash')])
+
+ for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
+ ('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
+ ('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
+ self.do_run('', 'hash value: ' + output, [text], no_build=True)
+
def test_unaligned(self):
if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1')
@@ -1011,6 +1210,35 @@ m_divisor is 1091269979
'''
self.do_run(src, '*1,10,10.5,1,1.2340,0.00*')
+ def test_globaldoubles(self):
+ src = r'''
+ #include <stdlib.h>
+ #include <stdio.h>
+
+ double testVu, testVv, testWu, testWv;
+
+ void Test(double _testVu, double _testVv, double _testWu, double _testWv)
+ {
+ testVu = _testVu;
+ testVv = _testVv;
+ testWu = _testWu;
+ testWv = _testWv;
+ printf("BUG?\n");
+ printf("Display: Vu=%f Vv=%f Wu=%f Wv=%f\n", testVu, testVv, testWu, testWv);
+ }
+
+ int main(void)
+ {
+ double v1 = 465.1;
+ double v2 = 465.2;
+ double v3 = 160.3;
+ double v4 = 111.4;
+ Test(v1, v2, v3, v4);
+ return 0;
+ }
+ '''
+ self.do_run(src, 'BUG?\nDisplay: Vu=465.100000 Vv=465.200000 Wu=160.300000 Wv=111.400000')
+
def test_math(self):
src = '''
#include <stdio.h>
@@ -1221,6 +1449,48 @@ m_divisor is 1091269979
'''
self.do_run(src, '4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\n', ['wowie', 'too', '74'])
+ def test_strndup(self):
+ src = '''
+ //---------------
+ //- http://pubs.opengroup.org/onlinepubs/9699919799/functions/strndup.html
+ //---------------
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+
+ int main(int argc, char **argv) {
+ const char* source = "strndup - duplicate a specific number of bytes from a string";
+
+ char* strdup_val = strndup(source, 0);
+ printf("1:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 7);
+ printf("2:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 1000);
+ printf("3:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 60);
+ printf("4:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, 19);
+ printf("5:%s\\n", strdup_val);
+ free(strdup_val);
+
+ strdup_val = strndup(source, -1);
+ printf("6:%s\\n", strdup_val);
+ free(strdup_val);
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '1:\n2:strndup\n3:strndup - duplicate a specific number of bytes from a string\n4:strndup - duplicate a specific number of bytes from a string\n5:strndup - duplicate\n6:\n')
+
def test_errar(self):
src = r'''
#include <stdio.h>
@@ -1510,6 +1780,9 @@ m_divisor is 1091269979
if self.emcc_args is None:
if Building.LLVM_OPTS: return self.skip('optimizing bitcode before emcc can confuse libcxx inclusion')
self.emcc_args = [] # libc++ auto-inclusion is only done if we use emcc
+ else:
+ if '-O2' in self.emcc_args:
+ self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
src = '''
#include <stdio.h>
@@ -1590,6 +1863,8 @@ m_divisor is 1091269979
def test_uncaught_exception(self):
if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc')
+ if '-O2' in self.emcc_args:
+ self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage
Settings.EXCEPTION_DEBUG = 0 # Messes up expected output.
Settings.DISABLE_EXCEPTION_CATCHING = 0
@@ -1693,6 +1968,18 @@ m_divisor is 1091269979
'''
self.do_run(src, '*51,87,78,550,100,78,550*')
+ def test_isdigit_l(self):
+ if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc')
+
+ src = '''
+ #include <iostream>
+ int main() {
+ using namespace std;
+ use_facet<num_put<char> >(cout.getloc()).put(cout, cout, '0', 3.14159265);
+ }
+ '''
+ self.do_run(src, '3.14159')
+
def test_polymorph(self):
src = '''
#include <stdio.h>
@@ -1867,75 +2154,81 @@ m_divisor is 1091269979
'''
self.do_run(src, 'z:1*', force_c=True)
- if self.emcc_args is not None: # too slow in other modes
- # We should not blow up the stack with numerous allocas
+ def test_alloca_stack(self):
+ if self.emcc_args is None: return # too slow in other modes
- src = '''
- #include <stdio.h>
- #include <stdlib.h>
+ # We should not blow up the stack with numerous allocas
+ src = '''
+ #include <stdio.h>
+ #include <stdlib.h>
- func(int i) {
- char *pc = (char *)alloca(100);
- *pc = i;
- (*pc)++;
- return (*pc) % 10;
- }
- int main() {
- int total = 0;
- for (int i = 0; i < 1024*1024; i++)
- total += func(i);
- printf("ok:%d*\\n", total);
- return 0;
- }
- '''
- self.do_run(src, 'ok:-32768*', force_c=True)
+ func(int i) {
+ char *pc = (char *)alloca(100);
+ *pc = i;
+ (*pc)++;
+ return (*pc) % 10;
+ }
+ int main() {
+ int total = 0;
+ for (int i = 0; i < 1024*1024; i++)
+ total += func(i);
+ printf("ok:%d*\\n", total);
+ return 0;
+ }
+ '''
+ self.do_run(src, 'ok:-32768*', force_c=True)
- # We should also not blow up the stack with byval arguments
- src = r'''
- #include<stdio.h>
- struct vec {
- int x, y, z;
- vec(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {}
- static vec add(vec a, vec b) {
- return vec(a.x+b.x, a.y+b.y, a.z+b.z);
- }
- };
- int main() {
- int total = 0;
- for (int i = 0; i < 1000; i++) {
- for (int j = 0; j < 1000; j++) {
- vec c(i+i%10, j*2, i%255);
- vec d(j*2, j%255, i%120);
- vec f = vec::add(c, d);
- total += (f.x + f.y + f.z) % 100;
- total %= 10240;
- }
+ def test_stack_byval(self):
+ if self.emcc_args is None: return # too slow in other modes
+
+ # We should also not blow up the stack with byval arguments
+ src = r'''
+ #include<stdio.h>
+ struct vec {
+ int x, y, z;
+ vec(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {}
+ static vec add(vec a, vec b) {
+ return vec(a.x+b.x, a.y+b.y, a.z+b.z);
+ }
+ };
+ int main() {
+ int total = 0;
+ for (int i = 0; i < 1000; i++) {
+ for (int j = 0; j < 1000; j++) {
+ vec c(i+i%10, j*2, i%255);
+ vec d(j*2, j%255, i%120);
+ vec f = vec::add(c, d);
+ total += (f.x + f.y + f.z) % 100;
+ total %= 10240;
}
- printf("sum:%d*\n", total);
- return 1;
}
- '''
- self.do_run(src, 'sum:9780*')
+ printf("sum:%d*\n", total);
+ return 1;
+ }
+ '''
+ self.do_run(src, 'sum:9780*')
- # We should not blow up the stack with numerous varargs
+ def test_stack_varargs(self):
+ if self.emcc_args is None: return # too slow in other modes
- src = r'''
- #include <stdio.h>
- #include <stdlib.h>
+ # We should not blow up the stack with numerous varargs
+ src = r'''
+ #include <stdio.h>
+ #include <stdlib.h>
- void func(int i) {
- printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
- i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
- }
- int main() {
- for (int i = 0; i < 1024; i++)
- func(i);
- printf("ok!\n");
- return 0;
- }
- '''
- Settings.TOTAL_STACK = 1024
- self.do_run(src, 'ok!')
+ void func(int i) {
+ printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i);
+ }
+ int main() {
+ for (int i = 0; i < 1024; i++)
+ func(i);
+ printf("ok!\n");
+ return 0;
+ }
+ '''
+ Settings.TOTAL_STACK = 1024
+ self.do_run(src, 'ok!')
def test_array2(self):
src = '''
@@ -2185,10 +2478,15 @@ m_divisor is 1091269979
#include <stdio.h>
#include "emscripten.h"
+ extern "C" {
+ void EMSCRIPTEN_KEEPALIVE save_me_aimee() { printf("mann\n"); }
+ }
+
int main() {
// EMSCRIPTEN_COMMENT("hello from the source");
emscripten_run_script("Module.print('hello world' + '!')");
printf("*%d*\n", emscripten_run_script_int("5*20"));
+ emscripten_run_script("_save_me_aimee()");
return 0;
}
'''
@@ -2199,7 +2497,19 @@ def process(filename):
# TODO: restore this (see comment in emscripten.h) assert '// hello from the source' in src
'''
- self.do_run(src, 'hello world!\n*100*', post_build=check)
+ self.do_run(src, 'hello world!\n*100*\nmann\n', post_build=check)
+
+ def test_inlinejs(self):
+ src = r'''
+ #include <stdio.h>
+
+ int main() {
+ asm("Module.print('Inline JS is very cool')");
+ return 0;
+ }
+ '''
+
+ self.do_run(src, 'Inline JS is very cool')
def test_memorygrowth(self):
# With typed arrays in particular, it is dangerous to use more memory than TOTAL_MEMORY,
@@ -2489,6 +2799,8 @@ def process(filename):
# part 2: make sure we warn about mixing c and c++ calling conventions here
+ if not (self.emcc_args is None or self.emcc_args == []): return # Optimized code is missing the warning comments
+
header = r'''
struct point
{
@@ -2541,17 +2853,11 @@ def process(filename):
all_name = os.path.join(self.get_dir(), 'all.bc')
Building.link([supp_name + '.o', main_name + '.o'], all_name)
- try:
- # This will fail! See explanation near the warning we check for, in the compiler source code
- self.do_ll_run(all_name, 'pre: 54,2\ndump: 55,3\ndump: 55,3\npost: 54,2')
- except Exception, e:
- # Check for warning in the generated code
- generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- if self.emcc_args is None or self.emcc_args == []: # Optimized code is missing the warning comments
- assert 'Casting a function pointer type to another with a different number of arguments.' in generated, 'Missing expected warning'
- assert 'void (i32, i32)* ==> void (%struct.point.0*)*' in generated, 'Missing expected warning details'
- return
- raise Exception('We should not have gotten to here!')
+ # This will fail! See explanation near the warning we check for, in the compiler source code
+ output = Popen(['python', EMCC, all_name], stderr=PIPE).communicate()
+ # Check for warning in the generated code
+ generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
+ assert 'Casting a function pointer type to another with a different number of arguments' in output[1], 'Missing expected warning'
def test_stdlibs(self):
if Settings.USE_TYPED_ARRAYS == 2:
@@ -2653,6 +2959,45 @@ def process(filename):
extra_emscripten_args=['-H', 'libc/time.h'])
#extra_emscripten_args=['-H', 'libc/fcntl.h,libc/sys/unistd.h,poll.h,libc/math.h,libc/langinfo.h,libc/time.h'])
+ def test_intentional_fault(self):
+ # Some programs intentionally segfault themselves, we should compile that into a throw
+ src = r'''
+ int main () {
+ *(volatile char *)0 = 0;
+ return 0;
+ }
+ '''
+ self.do_run(src, 'fault on write to 0')
+
+ def test_trickystring(self):
+ src = r'''
+ #include <stdio.h>
+
+ typedef struct
+ {
+ int (*f)(void *);
+ void *d;
+ char s[16];
+ } LMEXFunctionStruct;
+
+ int f(void *user)
+ {
+ return 0;
+ }
+
+ static LMEXFunctionStruct const a[] =
+ {
+ {f, (void *)(int)'a', "aa"}
+ };
+
+ int main()
+ {
+ printf("ok\n");
+ return a[0].f(a[0].d);
+ }
+ '''
+ self.do_run(src, 'ok\n')
+
def test_statics(self):
# static initializers save i16 but load i8 for some reason
if Settings.SAFE_HEAP:
@@ -3395,9 +3740,14 @@ def process(filename):
printf("%g\n", strtod("0", &endptr));
printf("%g\n", strtod("0.", &endptr));
printf("%g\n", strtod("0.0", &endptr));
+ printf("%g\n", strtod("-0.0", &endptr));
printf("%g\n", strtod("1", &endptr));
printf("%g\n", strtod("1.", &endptr));
printf("%g\n", strtod("1.0", &endptr));
+ printf("%g\n", strtod("z1.0", &endptr));
+ printf("%g\n", strtod("0.5", &endptr));
+ printf("%g\n", strtod(".5", &endptr));
+ printf("%g\n", strtod(".a5", &endptr));
printf("%g\n", strtod("123", &endptr));
printf("%g\n", strtod("123.456", &endptr));
printf("%g\n", strtod("-123.456", &endptr));
@@ -3419,9 +3769,14 @@ def process(filename):
0
0
0
+ 0
1
1
1
+ 0
+ 0.5
+ 0.5
+ 0
123
123.456
-123.456
@@ -3437,6 +3792,7 @@ def process(filename):
'''
self.do_run(src, re.sub(r'\n\s+', '\n', expected))
+ self.do_run(src.replace('strtod', 'strtold'), re.sub(r'\n\s+', '\n', expected)) # XXX add real support for long double
def test_strtok(self):
src = r'''
@@ -3501,6 +3857,22 @@ at function.:blag
src = open(path_from_root('tests', 'parseInt', 'src.c'), 'r').read()
expected = open(path_from_root('tests', 'parseInt', 'output.txt'), 'r').read()
self.do_run(src, expected)
+
+ def test_transtrcase(self):
+ src = '''
+ #include <stdio.h>
+ #include <string.h>
+ int main() {
+ char szToupr[] = "hello, ";
+ char szTolwr[] = "EMSCRIPTEN";
+ strupr(szToupr);
+ strlwr(szTolwr);
+ printf(szToupr);
+ printf(szTolwr);
+ return 0;
+ }
+ '''
+ self.do_run(src, 'HELLO, emscripten')
def test_printf(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('i64 mode 1 requires ta2')
@@ -3601,12 +3973,38 @@ at function.:blag
sscanf("-3.03", "%f", &a);
printf("%.4f\n", a);
+ char buffy[100];
+ sscanf("cheez some thing moar 123\nyet more\n", "cheez %s", buffy);
+ printf("|%s|\n", buffy);
+ sscanf("cheez something\nmoar 123\nyet more\n", "cheez %s", buffy);
+ printf("|%s|\n", buffy);
+ sscanf("cheez somethingmoar\tyet more\n", "cheez %s", buffy);
+ printf("|%s|\n", buffy);
+
+ int numverts = -1;
+ printf("%d\n", sscanf(" numverts 1499\n", " numverts %d", &numverts)); // white space is the same, even if tab vs space
+ printf("%d\n", numverts);
+
+ int index;
+ float u, v;
+ short start, count;
+ printf("%d\n", sscanf(" vert 87 ( 0.481565 0.059481 ) 0 1\n", " vert %d ( %f %f ) %hu %hu", &index, &u, &v, &start, &count));
+ printf("%d,%.6f,%.6f,%hu,%hu\n", index, u, v, start, count);
+
+ int neg, neg2, neg3 = 0;
+ printf("%d\n", sscanf("-123 -765 -34-6", "%d %u %d", &neg, &neg2, &neg3));
+ printf("%d,%u,%d\n", neg, neg2, neg3);
+
return 0;
}
'''
- self.do_run(src, 'en-us : 2\nen-r : 99\nen : 3\n1.234567, 0.000000\n-3.0300')
+ self.do_run(src, 'en-us : 2\nen-r : 99\nen : 3\n1.234567, 0.000000\n-3.0300\n|some|\n|something|\n|somethingmoar|\n' +
+ '1\n1499\n' +
+ '5\n87,0.481565,0.059481,0,1\n' +
+ '3\n-123,4294966531,-34\n')
- # Part 2: doubles
+ def test_sscanf_2(self):
+ # doubles
if Settings.USE_TYPED_ARRAYS == 2:
for ftype in ['float', 'double']:
src = r'''
@@ -3675,9 +4073,11 @@ Pass: 0.000012 0.000012''')
def process(filename):
src = \'\'\'
var Module = {
+ 'noFSInit': true,
'preRun': function() {
- FS.createDataFile('/', 'somefile.binary', [100, 200, 50, 25, 10, 77, 123], true, false); // 200 becomes -56, since signed chars are used in memory
FS.createLazyFile('/', 'test.file', 'test.file', true, false);
+ // Test FS_* exporting
+ Module['FS_createDataFile']('/', 'somefile.binary', [100, 200, 50, 25, 10, 77, 123], true, false); // 200 becomes -56, since signed chars are used in memory
var test_files_input = 'hi there!';
var test_files_input_index = 0;
FS.init(function() {
@@ -3727,6 +4127,20 @@ def process(filename):
'''
self.do_run(src, 'isatty? 0,0,1\ngot: 35\ngot: 45\ngot: 25\ngot: 15\n', post_build=post)
+ def test_fgetc_unsigned(self):
+ if self.emcc_args is None: return self.skip('requires emcc')
+ src = r'''
+ #include <stdio.h>
+ int main() {
+ FILE *file = fopen("file_with_byte_234.txt", "rb");
+ int c = fgetc(file);
+ printf("*%d\n", c);
+ }
+ '''
+ open('file_with_byte_234.txt', 'wb').write('\xea')
+ self.emcc_args += ['--embed-file', 'file_with_byte_234.txt']
+ self.do_run(src, '*234\n')
+
def test_folders(self):
add_pre_run = '''
def process(filename):
@@ -4418,6 +4832,43 @@ def process(filename):
self.do_run(src, '*15,15*\n*15,10*\n*6,10*\n*10,0*\n*7,1*')
+ def test_phiundef(self):
+ src = r'''
+#include <stdlib.h>
+#include <stdio.h>
+
+static int state;
+
+struct my_struct {
+ union {
+ struct {
+ unsigned char a;
+ unsigned char b;
+ } c;
+ unsigned int d;
+ } e;
+ unsigned int f;
+};
+
+int main(int argc, char **argv) {
+ struct my_struct r;
+
+ state = 0;
+
+ for (int i=0;i<argc+10;i++)
+ {
+ if (state % 2 == 0)
+ r.e.c.a = 3;
+ else
+ printf("%d\n", r.e.c.a);
+ state++;
+ }
+ return 0;
+}
+ '''
+
+ self.do_run(src, '3\n3\n3\n3\n3\n')
+
# libc++ tests
def test_iostream(self):
@@ -4518,7 +4969,7 @@ def process(filename):
# emcc should build in dlmalloc automatically, and do all the sign correction etc. for it
try_delete(os.path.join(self.get_dir(), 'src.cpp.o.js'))
- output = Popen([EMCC, path_from_root('tests', 'dlmalloc_test.c'),
+ output = Popen(['python', EMCC, path_from_root('tests', 'dlmalloc_test.c'),
'-o', os.path.join(self.get_dir(), 'src.cpp.o.js')], stdout=PIPE, stderr=self.stderr_redirect).communicate()
self.do_run('x', '*1,0*', ['200', '1'], no_build=True)
@@ -4643,6 +5094,8 @@ def process(filename):
# print opt, "FAIL"
def test_lua(self):
+ if self.emcc_args is None and Building.LLVM_OPTS: return self.skip('llvm 3.1 and safe llvm opts break lua')
+
try:
os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1'
@@ -4663,12 +5116,6 @@ def process(filename):
finally:
del os.environ['EMCC_LEAVE_INPUTS_RAW']
- def get_build_dir(self):
- ret = os.path.join(self.get_dir(), 'building')
- if not os.path.exists(ret):
- os.makedirs(ret)
- return ret
-
def get_freetype(self):
Settings.INIT_STACK = 1 # TODO: Investigate why this is necessary
@@ -4691,6 +5138,10 @@ def process(filename):
)
open(filename, 'w').write(src)
'''
+
+ # Not needed for js, but useful for debugging
+ shutil.copyfile(path_from_root('tests', 'freetype', 'LiberationSansBold.ttf'), os.path.join(self.get_dir(), 'font.ttf'))
+
# Main
self.do_run(open(path_from_root('tests', 'freetype', 'main.c'), 'r').read(),
open(path_from_root('tests', 'freetype', 'ref.txt'), 'r').read(),
@@ -4700,6 +5151,29 @@ def process(filename):
post_build=post)
#build_ll_hook=self.do_autodebug)
+ # github issue 324
+ print '[issue 324]'
+ self.do_run(open(path_from_root('tests', 'freetype', 'main_2.c'), 'r').read(),
+ open(path_from_root('tests', 'freetype', 'ref_2.txt'), 'r').read(),
+ ['font.ttf', 'w', '32', '32', '25'],
+ libraries=self.get_freetype(),
+ includes=[path_from_root('tests', 'freetype', 'include')],
+ post_build=post)
+
+ print '[issue 324 case 2]'
+ self.do_run(open(path_from_root('tests', 'freetype', 'main_3.c'), 'r').read(),
+ open(path_from_root('tests', 'freetype', 'ref_3.txt'), 'r').read(),
+ ['font.ttf', 'W', '32', '32', '0'],
+ libraries=self.get_freetype(),
+ includes=[path_from_root('tests', 'freetype', 'include')],
+ post_build=post)
+
+ print '[issue 324 case 3]'
+ self.do_run('',
+ open(path_from_root('tests', 'freetype', 'ref_4.txt'), 'r').read(),
+ ['font.ttf', 'ea', '40', '32', '0'],
+ no_build=True)
+
def test_sqlite(self):
# gcc -O3 -I/home/alon/Dev/emscripten/tests/sqlite -ldl src.c
if self.emcc_args is None: return self.skip('Very slow without ta2, and we would also need to include dlmalloc manually without emcc')
@@ -4719,7 +5193,7 @@ def process(filename):
self.do_run(r'''
#define SQLITE_DISABLE_LFS
#define LONGDOUBLE_TYPE double
- #define SQLITE_INT64_TYPE int
+ #define SQLITE_INT64_TYPE long long int
#define SQLITE_THREADSAFE 0
''' + open(path_from_root('tests', 'sqlite', 'sqlite3.c'), 'r').read() +
open(path_from_root('tests', 'sqlite', 'benchmark.c'), 'r').read(),
@@ -5066,7 +5540,7 @@ Block 0: ''', post_build=post1)
void KEEPALIVE print_int(int x) { printf("%d\n", x); }
void KEEPALIVE print_float(float x) { printf("%.2f\n", x); }
void KEEPALIVE print_string(char *x) { printf("%s\n", x); }
- int KEEPALIVE multi(int x, float y, int z, char *str) { puts(str); return (x+y)*z; }
+ int KEEPALIVE multi(int x, float y, int z, char *str) { if (x) puts(str); return (x+y)*z; }
int * KEEPALIVE pointer(int *in) { printf("%d\n", *in); static int ret = 21; return &ret; }
}
@@ -5091,22 +5565,28 @@ def process(filename):
'postRun': function() {
Module.print('*');
var ret;
- ret = ccall('get_int', 'number'); Module.print([typeof ret, ret]);
+ ret = Module['ccall']('get_int', 'number'); Module.print([typeof ret, ret]);
ret = ccall('get_float', 'number'); Module.print([typeof ret, ret.toFixed(2)]);
ret = ccall('get_string', 'string'); Module.print([typeof ret, ret]);
ret = ccall('print_int', null, ['number'], [12]); Module.print(typeof ret);
ret = ccall('print_float', null, ['number'], [14.56]); Module.print(typeof ret);
ret = ccall('print_string', null, ['string'], ["cheez"]); Module.print(typeof ret);
+ ret = ccall('print_string', null, ['array'], [[97, 114, 114, 45, 97, 121, 0]]); Module.print(typeof ret);
ret = ccall('multi', 'number', ['number', 'number', 'number', 'string'], [2, 1.4, 3, 'more']); Module.print([typeof ret, ret]);
var p = ccall('malloc', 'pointer', ['number'], [4]);
setValue(p, 650, 'i32');
ret = ccall('pointer', 'pointer', ['pointer'], [p]); Module.print([typeof ret, getValue(ret, 'i32')]);
Module.print('*');
// part 2: cwrap
- var multi = cwrap('multi', 'number', ['number', 'number', 'number', 'string']);
+ var multi = Module['cwrap']('multi', 'number', ['number', 'number', 'number', 'string']);
Module.print(multi(2, 1.4, 3, 'atr'));
Module.print(multi(8, 5.4, 4, 'bret'));
Module.print('*');
+ // part 3: avoid stack explosion
+ for (var i = 0; i < TOTAL_STACK/60; i++) {
+ ccall('multi', 'number', ['number', 'number', 'number', 'string'], [0, 0, 0, '123456789012345678901234567890123456789012345678901234567890']);
+ }
+ Module.print('stack is ok.');
}
};
\'\'\' + open(filename, 'r').read()
@@ -5115,7 +5595,7 @@ def process(filename):
Settings.EXPORTED_FUNCTIONS = ['_get_int', '_get_float', '_get_string', '_print_int', '_print_float', '_print_string', '_multi', '_pointer', '_malloc']
- self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\n', post_build=post)
+ self.do_run(src, '*\nnumber,5\nnumber,3.14\nstring,hello world\n12\nundefined\n14.56\nundefined\ncheez\nundefined\narr-ay\nundefined\nmore\nnumber,10\n650\nnumber,21\n*\natr\n10\nbret\n53\n*\nstack is ok.\n', post_build=post)
def test_scriptaclass(self):
header_filename = os.path.join(self.get_dir(), 'header.h')
@@ -5178,6 +5658,7 @@ def process(filename):
int value;
public:
Parent(int val);
+ Parent(Parent *p, Parent *q); // overload constructor
int getVal() { return value; }; // inline should work just fine here, unlike Way 1 before
void mulVal(int mul);
};
@@ -5207,7 +5688,7 @@ def process(filename):
open(header_filename, 'w').write(header)
basename = os.path.join(self.get_dir(), 'bindingtest')
- output = Popen([BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
+ output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
#print output
assert 'Traceback' not in output, 'Failure in binding generation: ' + output
@@ -5215,6 +5696,7 @@ def process(filename):
#include "header.h"
Parent::Parent(int val) : value(val) { printf("Parent:%d\\n", val); }
+ Parent::Parent(Parent *p, Parent *q) : value(p->value + q->value) { printf("Parent:%d\\n", value); }
void Parent::mulVal(int mul) { value *= mul; }
#include "bindingtest.cpp"
@@ -5379,7 +5861,7 @@ Child2:9
open(header_filename, 'w').write(header)
basename = os.path.join(self.get_dir(), 'bindingtest')
- output = Popen([BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
+ output = Popen(['python', BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0]
#print output
assert 'Traceback' not in output, 'Failure in binding generation: ' + output
@@ -5840,6 +6322,120 @@ def process(filename):
'''
self.do_run(src, 'hello, world!\ncleanup\nExit Status: 118')
+ def test_gc(self):
+ if self.emcc_args == None: return self.skip('needs ta2')
+
+ Settings.GC_SUPPORT = 1
+
+ src = r'''
+ #include <stdio.h>
+ #include <gc.h>
+ #include <assert.h>
+
+ void *global;
+
+ void finalizer(void *ptr, void *arg) {
+ printf("finalizing %d (global == %d)\n", (int)arg, ptr == global);
+ }
+
+ void finalizer2(void *ptr, void *arg) {
+ printf("finalizing2 %d (global == %d)\n", (int)arg, ptr == global);
+ }
+
+ int main() {
+ GC_INIT();
+
+ void *local, *local2, *local3, *local4;
+
+ // Hold on to global, drop locals
+
+ global = GC_MALLOC(1024); // rooted since in a static allocation
+ GC_REGISTER_FINALIZER_NO_ORDER(global, finalizer, 0, 0, 0);
+ printf("alloc %p\n", global);
+
+ local = GC_MALLOC(1024); // not rooted since stack is not scanned
+ GC_REGISTER_FINALIZER_NO_ORDER(local, finalizer, (void*)1, 0, 0);
+ printf("alloc %p\n", local);
+
+ assert((char*)local - (char*)global >= 1024 || (char*)global - (char*)local >= 1024);
+
+ local2 = GC_MALLOC(1024); // no finalizer
+ printf("alloc %p\n", local2);
+
+ local3 = GC_MALLOC(1024); // with finalizable2
+ GC_REGISTER_FINALIZER_NO_ORDER(local3, finalizer2, (void*)2, 0, 0);
+ printf("alloc %p\n", local);
+
+ local4 = GC_MALLOC(1024); // yet another
+ GC_REGISTER_FINALIZER_NO_ORDER(local4, finalizer2, (void*)3, 0, 0);
+ printf("alloc %p\n", local);
+
+ printf("basic test\n");
+
+ GC_FORCE_COLLECT();
+
+ printf("*\n");
+
+ GC_FREE(global); // force free will actually work
+
+ // scanning inside objects
+
+ global = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(global, finalizer, 0, 0, 0);
+ local = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local, finalizer, (void*)1, 0, 0);
+ local2 = GC_MALLOC_ATOMIC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local2, finalizer, (void*)2, 0, 0);
+ local3 = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local3, finalizer, (void*)3, 0, 0);
+ local4 = GC_MALLOC(12);
+ GC_REGISTER_FINALIZER_NO_ORDER(local4, finalizer, (void*)4, 0, 0);
+
+ void **globalData = (void**)global;
+ globalData[0] = local;
+ globalData[1] = local2;
+
+ void **localData = (void**)local;
+ localData[0] = local3;
+
+ void **local2Data = (void**)local2;
+ local2Data[0] = local4; // actually ignored, because local2 is atomic, so 4 is freeable
+
+ printf("object scan test test\n");
+
+ GC_FORCE_COLLECT();
+
+ printf("*\n");
+
+ GC_FREE(global); // force free will actually work
+
+ printf("*\n");
+
+ GC_FORCE_COLLECT();
+
+ printf(".\n");
+
+ global = 0;
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''basic test
+finalizing 1 (global == 0)
+finalizing2 2 (global == 0)
+finalizing2 3 (global == 0)
+*
+finalizing 0 (global == 1)
+object scan test test
+finalizing 4 (global == 0)
+*
+finalizing 0 (global == 1)
+*
+finalizing 1 (global == 0)
+finalizing 2 (global == 0)
+finalizing 3 (global == 0)
+.
+''')
# Generate tests for everything
def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None):
@@ -5890,6 +6486,7 @@ class %s(T):
Settings.CATCH_EXIT_CODE = 0
Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2)
Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0
+ Settings.PRECISE_I64_MATH = 0
Building.pick_llvm_opts(3)
@@ -5923,29 +6520,25 @@ TT = %s
del T # T is just a shape for the specific subclasses, we don't test it itself
class other(RunnerCore):
- def clear(self):
- for name in os.listdir(self.get_dir()):
- try_delete(name)
- emcc_debug = os.environ.get('EMCC_DEBUG')
- if emcc_debug:
- for name in os.listdir(EMSCRIPTEN_TEMP_DIR):
- try_delete(os.path.join(EMSCRIPTEN_TEMP_DIR, name))
-
def test_emcc(self):
for compiler in [EMCC, EMXX]:
shortcompiler = os.path.basename(compiler)
suffix = '.c' if compiler == EMCC else '.cpp'
# --version
- output = Popen([compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate()
self.assertContained('''emcc (Emscripten GCC-like replacement) 2.0
-Copyright (C) 2011 the Emscripten authors.
+Copyright (C) 2012 the Emscripten authors.
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-''', output[0], output[1])
+''', output[0].replace('\r', ''), output[1].replace('\r', ''))
+
+ # -v, without input files
+ output = Popen(['python', compiler, '-v'], stdout=PIPE, stderr=PIPE).communicate()
+ self.assertContained('''clang version''', output[1].replace('\r', ''), output[1].replace('\r', ''))
# --help
- output = Popen([compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate()
self.assertContained('''%s [options] file...
Most normal gcc/g++ options will work, for example:
@@ -5954,11 +6547,11 @@ Most normal gcc/g++ options will work, for example:
Options that are modified or new in %s include:
-O0 No optimizations (default)
-''' % (shortcompiler, shortcompiler), output[0], output[1])
+''' % (shortcompiler, shortcompiler), output[0].replace('\r', ''), output[1].replace('\r', ''))
# emcc src.cpp ==> writes a.out.js
self.clear()
- output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)], stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('a.out.js'), '\n'.join(output)
self.assertContained('hello, world!', run_js('a.out.js'))
@@ -5966,7 +6559,7 @@ Options that are modified or new in %s include:
# properly report source code errors, and stop there
self.clear()
assert not os.path.exists('a.out.js')
- output = Popen([compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world_error' + suffix)], stdout=PIPE, stderr=PIPE).communicate()
assert not os.path.exists('a.out.js'), 'compilation failed, so no output file is expected'
assert len(output[0]) == 0, output[0]
self.assertNotContained('IOError', output[1]) # no python stack
@@ -5974,36 +6567,36 @@ Options that are modified or new in %s include:
self.assertContained('error: invalid preprocessing directive', output[1])
self.assertContained("error: use of undeclared identifier 'cheez", output[1])
self.assertContained('2 errors generated', output[1])
- assert output[1].split('2 errors generated.')[1].replace('\n', '') == 'emcc: compiler frontend failed to generate LLVM bitcode, halting'
+ assert output[1].split('2 errors generated.')[1].replace('\r', '').replace('\n', '') == 'emcc: compiler frontend failed to generate LLVM bitcode, halting'
# emcc src.cpp -c and emcc src.cpp -o src.[o|bc] ==> should give a .bc file
# regression check: -o js should create "js", with bitcode content
for args in [['-c'], ['-o', 'src.o'], ['-o', 'src.bc'], ['-o', 'src.so'], ['-o', 'js']]:
target = args[1] if len(args) == 2 else 'hello_world.o'
self.clear()
- Popen([compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate()
+ Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix)] + args, stdout=PIPE, stderr=PIPE).communicate()
syms = Building.llvm_nm(target)
assert len(syms.defs) == 1 and 'main' in syms.defs, 'Failed to generate valid bitcode'
if target == 'js': # make sure emcc can recognize the target as a bitcode file
shutil.move(target, target + '.bc')
target += '.bc'
- output = Popen([compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate()
+ output = Popen(['python', compiler, target, '-o', target + '.js'], stdout = PIPE, stderr = PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists(target + '.js'), 'Expected %s to exist since args are %s : %s' % (target + '.js', str(args), '\n'.join(output))
self.assertContained('hello, world!', run_js(target + '.js'))
# handle singleton archives
self.clear()
- Popen([compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate()
+ Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix), '-o', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate()
Popen([LLVM_AR, 'r', 'a.a', 'a.bc'], stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists('a.a')
- output = Popen([compiler, 'a.a']).communicate()
+ output = Popen(['python', compiler, 'a.a']).communicate()
assert os.path.exists('a.out.js'), output
self.assertContained('hello, world!', run_js('a.out.js'))
# emcc src.ll ==> generates .js
self.clear()
- output = Popen([compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world.ll')], stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('a.out.js'), '\n'.join(output)
self.assertContained('hello, world!', run_js('a.out.js'))
@@ -6015,7 +6608,7 @@ Options that are modified or new in %s include:
os.mkdir('b_dir')
for path in [os.path.abspath(os.path.join('..', 'file1.js')), os.path.join('b_dir', 'file2.js')]:
self.clear()
- output = Popen([compiler, path_from_root('tests', 'hello_world.ll'), '-o', path], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world.ll'), '-o', path], stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists(path), path + ' does not exist; ' + '\n'.join(output)
self.assertContained('hello, world!', run_js(path))
finally:
@@ -6029,7 +6622,7 @@ Options that are modified or new in %s include:
# very speed-sensitive. So we do not implement it in JS in library.js, instead we compile it from source
for source, has_malloc in [('hello_world' + suffix, False), ('hello_malloc.cpp', True)]:
self.clear()
- output = Popen([compiler, path_from_root('tests', source)], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', source)], stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists('a.out.js'), '\n'.join(output)
self.assertContained('hello, world!', run_js('a.out.js'))
generated = open('a.out.js').read()
@@ -6055,14 +6648,14 @@ Options that are modified or new in %s include:
]:
#print params, opt_level, bc_params, closure
self.clear()
- output = Popen([compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params,
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params,
stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
if bc_params is not None:
if '-O1' in params and 'something.bc' in params:
assert 'warning: -Ox flags ignored, since not generating JavaScript' in output[1]
assert os.path.exists('something.bc'), output[1]
- output = Popen([compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists('something.js'), output[1]
assert ('Warning: Applying some potentially unsafe optimizations!' in output[1]) == (opt_level >= 3), 'unsafe warning should appear in opt >= 3'
self.assertContained('hello, world!', run_js('something.js'))
@@ -6083,11 +6676,11 @@ Options that are modified or new in %s include:
assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0'
assert 'var $i;' in generated or 'var $i_01;' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on'
if opt_level >= 1:
- assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + $storemerge4 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($storemerge4 / 2 | 0)]' in generated or 'HEAP8[$vla1 + $i_04 / 2 | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 | 0)]' in generated or 'HEAP8[$1 + $i_01 / 2 | 0]' in generated or 'HEAP8[$1 + ($i_01 / 2 | 0)]' in generated, 'eliminator should create compound expressions, and fewer one-time vars'
+ assert 'HEAP8[HEAP32[' in generated or 'HEAP8[$vla1 + (($storemerge4 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + (($storemerge4 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + (($i_04 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$vla1 + ($i_04 / 2 & -1)]' in generated or 'HEAP8[$1 + (($i_01 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$1 + (($i_01 | 0) / 2 & -1) | 0]' in generated or 'HEAP8[$1 + ($i_01 / 2 & -1)]' in generated, 'eliminator should create compound expressions, and fewer one-time vars'
assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts'
assert ('function _malloc(bytes) {' in generated) == (not has_malloc), 'If malloc is needed, it should be there, if not not'
assert 'function _main() {' in generated, 'Should be unminified, including whitespace'
- assert 'function _dump' in generated, 'No inlining by default'
+ assert ('-O3' in (params+(bc_params or []))) or'function _dump' in generated, 'No inlining by default'
# emcc -s RELOOP=1 src.cpp ==> should pass -s to emscripten.py. --typed-arrays is a convenient alias for -s USE_TYPED_ARRAYS
for params, test, text in [
@@ -6103,7 +6696,7 @@ Options that are modified or new in %s include:
(['--llvm-opts', '1'], lambda generated: '_puts(' in generated, 'llvm opts requested'),
]:
self.clear()
- output = Popen([compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world_loop.cpp'), '-o', 'a.out.js'] + params, stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('a.out.js'), '\n'.join(output)
self.assertContained('hello, world!', run_js('a.out.js'))
@@ -6112,7 +6705,7 @@ Options that are modified or new in %s include:
# Compiling two source files into a final JS.
for args, target in [([], 'a.out.js'), (['-o', 'combined.js'], 'combined.js')]:
self.clear()
- output = Popen([compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp')] + args,
+ output = Popen(['python', compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp')] + args,
stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists(target), '\n'.join(output)
@@ -6120,7 +6713,7 @@ Options that are modified or new in %s include:
# Compiling two files with -c will generate separate .bc files
self.clear()
- output = Popen([compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp'), '-c'] + args,
+ output = Popen(['python', compiler, path_from_root('tests', 'twopart_main.cpp'), path_from_root('tests', 'twopart_side.cpp'), '-c'] + args,
stdout=PIPE, stderr=PIPE).communicate()
if '-o' in args:
# specifying -o and -c is an error
@@ -6132,24 +6725,24 @@ Options that are modified or new in %s include:
assert not os.path.exists(target), 'We should only have created bitcode here: ' + '\n'.join(output)
# Compiling one of them alone is expected to fail
- output = Popen([compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists(target), '\n'.join(output)
#print '\n'.join(output)
self.assertContained('is not a function', run_js(target, stderr=STDOUT))
try_delete(target)
# Combining those bc files into js should work
- output = Popen([compiler, 'twopart_main.o', 'twopart_side.o'] + args, stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, 'twopart_main.o', 'twopart_side.o'] + args, stdout=PIPE, stderr=PIPE).communicate()
assert os.path.exists(target), '\n'.join(output)
self.assertContained('side got: hello from main, over', run_js(target))
# Combining bc files into another bc should also work
try_delete(target)
assert not os.path.exists(target)
- output = Popen([compiler, 'twopart_main.o', 'twopart_side.o', '-o', 'combined.bc'] + args, stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, 'twopart_main.o', 'twopart_side.o', '-o', 'combined.bc'] + args, stdout=PIPE, stderr=PIPE).communicate()
syms = Building.llvm_nm('combined.bc')
assert len(syms.defs) == 2 and 'main' in syms.defs, 'Failed to generate valid bitcode'
- output = Popen([compiler, 'combined.bc', '-o', 'combined.bc.js'], stdout = PIPE, stderr = PIPE).communicate()
+ output = Popen(['python', compiler, 'combined.bc', '-o', 'combined.bc.js'], stdout = PIPE, stderr = PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('combined.bc.js'), 'Expected %s to exist' % ('combined.bc.js')
self.assertContained('side got: hello from main, over', run_js('combined.bc.js'))
@@ -6165,36 +6758,603 @@ f.write('transformed!')
f.close()
''')
trans_file.close()
- output = Popen([compiler, path_from_root('tests', 'hello_world' + suffix), '--js-transform', 'python t.py'], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', compiler, path_from_root('tests', 'hello_world' + suffix), '--js-transform', 'python t.py'], stdout=PIPE, stderr=PIPE).communicate()
assert open('a.out.js').read() == 'transformed!', 'Transformed output must be as expected'
# TODO: Add in files test a clear example of using disablePermissions, and link to it from the wiki
# TODO: test normal project linking, static and dynamic: get_library should not need to be told what to link!
# TODO: deprecate llvm optimizations, dlmalloc, etc. in emscripten.py.
+ def test_catch_undef(self):
+ open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
+ #include <vector>
+ #include <stdio.h>
+
+ class Test {
+ public:
+ std::vector<int> vector;
+ };
+
+ Test globalInstance;
+
+ int main() {
+ printf("hello, world!\n");
+ return 1;
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-fcatch-undefined-behavior']).communicate()
+ self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_l_link(self):
+ # Linking with -lLIBNAME and -L/DIRNAME should work
+
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ extern void printey();
+ int main() {
+ printey();
+ return 0;
+ }
+ ''')
+
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'libdir'));
+ except:
+ pass
+
+ open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
+ #include <stdio.h>
+ void printey() {
+ printf("hello from lib\\n");
+ }
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-c']).communicate()
+ shutil.move(os.path.join(self.get_dir(), 'libfile.o'), os.path.join(self.get_dir(), 'libdir', 'libfile.so'))
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile']).communicate()
+ self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs'
+
+ def test_local_link(self):
+ # Linking a local library directly, like /usr/lib/libsomething.so, cannot work of course since it
+ # doesn't contain bitcode. However, when we see that we should look for a bitcode file for that
+ # library in the -L paths and system/lib
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ extern void printey();
+ int main() {
+ printey();
+ return 0;
+ }
+ ''')
+
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'subdir'));
+ except:
+ pass
+ open(os.path.join(self.get_dir(), 'subdir', 'libfile.so'), 'w').write('this is not llvm bitcode!')
+
+ open(os.path.join(self.get_dir(), 'libfile.cpp'), 'w').write('''
+ #include <stdio.h>
+ void printey() {
+ printf("hello from lib\\n");
+ }
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'libfile.cpp'), '-o', 'libfile.so']).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.']).communicate()
+ self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_js_libraries(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ extern "C" {
+ extern void printey();
+ extern int calcey(int x, int y);
+ }
+ int main() {
+ printey();
+ printf("*%d*\\n", calcey(10, 22));
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'mylib1.js'), 'w').write('''
+ mergeInto(LibraryManager.library, {
+ printey: function() {
+ Module.print('hello from lib!');
+ }
+ });
+ ''')
+ open(os.path.join(self.get_dir(), 'mylib2.js'), 'w').write('''
+ mergeInto(LibraryManager.library, {
+ calcey: function(x, y) {
+ return x + y;
+ }
+ });
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--js-library', os.path.join(self.get_dir(), 'mylib1.js'),
+ '--js-library', os.path.join(self.get_dir(), 'mylib2.js')]).communicate()
+ self.assertContained('hello from lib!\n*32*\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_identical_basenames(self):
+ # Issue 287: files in different dirs but with the same basename get confused as the same,
+ # causing multiply defined symbol errors
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'foo'));
+ except:
+ pass
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'bar'));
+ except:
+ pass
+ open(os.path.join(self.get_dir(), 'foo', 'main.cpp'), 'w').write('''
+ extern void printey();
+ int main() {
+ printey();
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'bar', 'main.cpp'), 'w').write('''
+ #include<stdio.h>
+ void printey() { printf("hello there\\n"); }
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.cpp'), os.path.join(self.get_dir(), 'bar', 'main.cpp')]).communicate()
+ self.assertContained('hello there', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ # ditto with first creating .o files
+ try_delete(os.path.join(self.get_dir(), 'a.out.js'))
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.cpp'), '-o', os.path.join(self.get_dir(), 'foo', 'main.o')]).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'bar', 'main.cpp'), '-o', os.path.join(self.get_dir(), 'bar', 'main.o')]).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo', 'main.o'), os.path.join(self.get_dir(), 'bar', 'main.o')]).communicate()
+ self.assertContained('hello there', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_remove_duplicates(self):
+ # can happen with .a files. we do a best-effort, removing dupes
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include<stdio.h>
+ void printey() { printf("bye bye\\n"); }
+ int main() {
+ printey();
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'side.cpp'), 'w').write('''
+ #include<stdio.h>
+ void printey() { printf("bye bye\\n"); }
+ ''')
+
+ # without --remove-duplicates, we fail
+ err = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'side.cpp')], stderr=PIPE).communicate()[1]
+ assert not os.path.exists('a.out.js')
+ assert 'multiply' in err
+
+ # with it, we succeed
+ err = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'side.cpp'), '--remove-duplicates'], stderr=PIPE).communicate()[1]
+ self.assertContained('bye bye', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_embed_file(self):
+ open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''hello from a file with lots of data and stuff in it thank you very much''')
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ int main() {
+ FILE *f = fopen("somefile.txt", "r");
+ char buf[100];
+ fread(buf, 1, 20, f);
+ buf[20] = 0;
+ fclose(f);
+ printf("|%s|\n", buf);
+ return 0;
+ }
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt']).communicate()
+ self.assertContained('|hello from a file wi|', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ # preload twice, should not err
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt', '--embed-file', 'somefile.txt']).communicate()
+ self.assertContained('|hello from a file wi|', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_multidynamic_link(self):
+ # Linking the same dynamic library in will error, normally, since we statically link it, causing dupe symbols
+ # A workaround is to use --ignore-dynamic-linking, see emcc --help for details
+
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ extern void printey();
+ extern void printother();
+ int main() {
+ printf("*");
+ printey();
+ printf("\n");
+ printother();
+ printf("\n");
+ printf("*");
+ return 0;
+ }
+ ''')
+
+ try:
+ os.makedirs(os.path.join(self.get_dir(), 'libdir'));
+ except:
+ pass
+
+ open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
+ #include <stdio.h>
+ void printey() {
+ printf("hello from lib");
+ }
+ ''')
+
+ open(os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), 'w').write('''
+ #include <stdio.h>
+ extern void printey();
+ void printother() {
+ printf("|");
+ printey();
+ printf("|");
+ }
+ ''')
+
+ # This lets us link the same dynamic lib twice. We will need to link it in manually at the end.
+ compiler = ['python', EMCC, '--ignore-dynamic-linking']
+
+ # Build libfile normally into an .so
+ Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-o', os.path.join(self.get_dir(), 'libdir', 'libfile.so')]).communicate()
+ # Build libother and dynamically link it to libfile - but add --ignore-dynamic-linking
+ Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-o', os.path.join(self.get_dir(), 'libdir', 'libother.so')]).communicate()
+ # Build the main file, linking in both the libs
+ Popen(compiler + [os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother', '-c']).communicate()
+
+ # The normal build system is over. We need to do an additional step to link in the dynamic libraries, since we ignored them before
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.o'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother']).communicate()
+
+ self.assertContained('*hello from lib\n|hello from lib|\n*', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_js_link(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from main\\n");
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'before.js'), 'w').write('''
+ var MESSAGE = 'hello from js';
+ if (typeof Module != 'undefined') throw 'This code should run before anything else!';
+ ''')
+ open(os.path.join(self.get_dir(), 'after.js'), 'w').write('''
+ Module.print(MESSAGE);
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'before.js', '--post-js', 'after.js']).communicate()
+ self.assertContained('hello from main\nhello from js\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_sdl_endianness(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+ #include <SDL/SDL.h>
+
+ int main() {
+ printf("%d, %d, %d\n", SDL_BYTEORDER, SDL_LIL_ENDIAN, SDL_BIG_ENDIAN);
+ return 0;
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')]).communicate()
+ self.assertContained('1234, 1234, 4321\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_warn_undefined(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ extern "C" {
+ void something();
+ }
+
+ int main() {
+ something();
+ return 0;
+ }
+ ''')
+ output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-s', 'WARN_ON_UNDEFINED_SYMBOLS=1'], stderr=PIPE).communicate()
+ self.assertContained('Unresolved symbol: _something\n', output[1])
+
+ output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')], stderr=PIPE).communicate()
+ self.assertNotContained('Unresolved symbol: _something\n', output[1])
+
+ def test_prepost(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from main\\n");
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var Module = {
+ preRun: function() { Module.print('pre-run') },
+ postRun: function() { Module.print('post-run') }
+ };
+ ''')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js']).communicate()
+ self.assertContained('pre-run\nhello from main\npost-run\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ # never run, so no preRun or postRun
+ src = open(os.path.join(self.get_dir(), 'a.out.js')).read().replace('// {{PRE_RUN_ADDITIONS}}', 'addRunDependency()')
+ open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src)
+ self.assertNotContained('pre-run\nhello from main\npost-run\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ # noInitialRun prevents run
+ for no_initial_run in [0, 1]:
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')]).communicate()
+ src = 'var Module = { noInitialRun: %d };\n' % no_initial_run + open(os.path.join(self.get_dir(), 'a.out.js')).read()
+ open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src)
+ assert ('hello from main' in run_js(os.path.join(self.get_dir(), 'a.out.js'))) != no_initial_run, 'only run if no noInitialRun'
+
+ if no_initial_run:
+ # Calling main later should still work, filesystem etc. must be set up.
+ src = open(os.path.join(self.get_dir(), 'a.out.js')).read() + '\n_main();\n';
+ open(os.path.join(self.get_dir(), 'a.out.js'), 'w').write(src)
+ assert 'hello from main' in run_js(os.path.join(self.get_dir(), 'a.out.js')), 'main should print when called manually'
+
+ def test_prepost2(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from main\\n");
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var Module = {
+ preRun: function() { Module.print('pre-run') },
+ };
+ ''')
+ open(os.path.join(self.get_dir(), 'pre2.js'), 'w').write('''
+ Module.postRun = function() { Module.print('post-run') };
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js', '--pre-js', 'pre2.js']).communicate()
+ self.assertContained('pre-run\nhello from main\npost-run\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_prepre(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from main\\n");
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ var Module = {
+ preRun: [function() { Module.print('pre-run') }],
+ };
+ ''')
+ open(os.path.join(self.get_dir(), 'pre2.js'), 'w').write('''
+ Module.preRun.push(function() { Module.print('prepre') });
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js', '--pre-js', 'pre2.js']).communicate()
+ self.assertContained('prepre\npre-run\nhello from main\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
+ def test_eliminator(self):
+ expected = open(path_from_root('tools', 'eliminator', 'eliminator-test-output.js')).read()
+ output = Popen([NODE_JS, COFFEESCRIPT, VARIABLE_ELIMINATOR, path_from_root('tools', 'eliminator', 'eliminator-test.js')], stdout=PIPE).communicate()[0]
+ self.assertIdentical(expected, output)
+
+ def test_fix_closure(self):
+ input = path_from_root('tests', 'test-fix-closure.js')
+ expected = path_from_root('tests', 'test-fix-closure.out.js')
+ Popen(['python', path_from_root('tools', 'fix_closure.py'), input, 'out.js']).communicate(input)
+ output = open('out.js').read()
+ assert '0,zzz_Q_39fa,0' in output
+ assert 'function(a,c)' not in output # should be uninlined, so it gets a name
+ assert run_js(input) == run_js('out.js')
+
+ def test_js_optimizer(self):
+ for input, expected, passes in [
+ (path_from_root('tools', 'test-js-optimizer.js'), open(path_from_root('tools', 'test-js-optimizer-output.js')).read(),
+ ['hoistMultiples', 'loopOptimizer', 'unGlobalize', 'removeAssignsToUndefined', 'simplifyExpressionsPre', 'simplifyExpressionsPost']),
+ (path_from_root('tools', 'test-js-optimizer-t2c.js'), open(path_from_root('tools', 'test-js-optimizer-t2c-output.js')).read(),
+ ['simplifyExpressionsPre', 'optimizeShiftsConservative']),
+ (path_from_root('tools', 'test-js-optimizer-t2.js'), open(path_from_root('tools', 'test-js-optimizer-t2-output.js')).read(),
+ ['simplifyExpressionsPre', 'optimizeShiftsAggressive']),
+ (path_from_root('tools', 'test-js-optimizer-regs.js'), open(path_from_root('tools', 'test-js-optimizer-regs-output.js')).read(),
+ ['registerize']),
+ ]:
+ output = Popen([NODE_JS, JS_OPTIMIZER, input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0]
+ self.assertIdentical(expected, output.replace('\n\n', '\n'))
+
+ def test_m_mm(self):
+ open(os.path.join(self.get_dir(), 'foo.c'), 'w').write('''#include <emscripten.h>''')
+ for opt in ['M', 'MM']:
+ output, err = Popen(['python', EMCC, os.path.join(self.get_dir(), 'foo.c'), '-' + opt], stdout=PIPE, stderr=PIPE).communicate()
+ assert 'foo.o: ' in output, '-%s failed to produce the right output: %s' % (opt, output)
+ assert 'error' not in err, 'Unexpected stderr: ' + err
+
+ def test_scons(self): # also incidentally tests c++11 integration in llvm 3.1
+ try_delete(os.path.join(self.get_dir(), 'test'))
+ shutil.copytree(path_from_root('tests', 'scons'), os.path.join(self.get_dir(), 'test'))
+ shutil.copytree(path_from_root('tools', 'scons', 'site_scons'), os.path.join(self.get_dir(), 'test', 'site_scons'))
+ os.chdir(os.path.join(self.get_dir(), 'test'))
+ Popen(['scons']).communicate()
+ output = run_js('scons_integration.js')
+ assert 'If you see this - the world is all right!' in output
+
+ def test_llvm_nativizer(self):
+ # avoid impure_ptr problems etc.
+ shutil.copyfile(path_from_root('tests', 'files.cpp'), os.path.join(self.get_dir(), 'files.cpp'))
+ open(os.path.join(self.get_dir(), 'somefile.binary'), 'w').write('''waka waka############################''')
+ open(os.path.join(self.get_dir(), 'test.file'), 'w').write('''ay file..............,,,,,,,,,,,,,,''')
+ open(os.path.join(self.get_dir(), 'stdin'), 'w').write('''inter-active''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'files.cpp'), '-c']).communicate()
+ Popen(['python', path_from_root('tools', 'nativize_llvm.py'), os.path.join(self.get_dir(), 'files.o')]).communicate(input)[0]
+ output = Popen([os.path.join(self.get_dir(), 'files.o.run')], stdin=open(os.path.join(self.get_dir(), 'stdin')), stdout=PIPE, stderr=PIPE).communicate()
+ self.assertIdentical('''size: 37
+data: 119,97,107,97,32,119,97,107,97,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35
+loop: 119 97 107 97 32 119 97 107 97 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35
+input:inter-active
+texto
+$
+5 : 10,30,20,11,88
+other=ay file...
+seeked= file.
+seeked=e...
+seeked=,,.
+fscanfed: 10 - hello
+''', output[0])
+ self.assertIdentical('texte\n', output[1])
+
+ def test_emconfig(self):
+ output = Popen(['python', EMCONFIG, 'LLVM_ROOT'], stdout=PIPE, stderr=PIPE).communicate()[0]
+ assert output == LLVM_ROOT + "\n"
+ invalid = 'Usage: em-config VAR_NAME\n'
+ # Don't accept variables that do not exist
+ output = Popen(['python', EMCONFIG, 'VAR_WHICH_DOES_NOT_EXIST'], stdout=PIPE, stderr=PIPE).communicate()[0]
+ assert output == invalid
+ # Don't accept no arguments
+ output = Popen(['python', EMCONFIG], stdout=PIPE, stderr=PIPE).communicate()[0]
+ assert output == invalid
+ # Don't accept more than one variable
+ output = Popen(['python', EMCONFIG, 'LLVM_ROOT', 'EMCC'], stdout=PIPE, stderr=PIPE).communicate()[0]
+ assert output == invalid
+ # Don't accept arbitrary python code
+ output = Popen(['python', EMCONFIG, 'sys.argv[1]'], stdout=PIPE, stderr=PIPE).communicate()[0]
+ assert output == invalid
+
+ def test_link_s(self):
+ # -s OPT=VALUE can conflict with -s as a linker option. We warn and ignore
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ extern "C" {
+ void something();
+ }
+
+ int main() {
+ something();
+ return 0;
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'supp.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ extern "C" {
+ void something() {
+ printf("yello\n");
+ }
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'main.o']).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'supp.cpp'), '-o', 'supp.o']).communicate()
+
+ output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.o'), '-s', os.path.join(self.get_dir(), 'supp.o'), '-s', 'SAFE_HEAP=1'], stderr=PIPE).communicate()
+ self.assertContained('emcc: warning: treating -s as linker option', output[1])
+ output = run_js('a.out.js')
+ assert 'yello' in output, 'code works'
+ code = open('a.out.js').read()
+ assert 'SAFE_HEAP' in code, 'valid -s option had an effect'
+
+ def test_crunch(self):
+ # crunch should not be run if a .crn exists that is more recent than the .dds
+ shutil.copyfile(path_from_root('tests', 'ship.dds'), 'ship.dds')
+ time.sleep(0.1)
+ Popen(['python', FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ assert os.stat('test.data').st_size < 0.25*os.stat('ship.dds').st_size, 'Compressed should be much smaller than dds'
+ crunch_time = os.stat('ship.crn').st_mtime
+ dds_time = os.stat('ship.dds').st_mtime
+ assert crunch_time > dds_time, 'Crunch is more recent'
+ # run again, should not recrunch!
+ time.sleep(0.1)
+ Popen(['python', FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ assert crunch_time == os.stat('ship.crn').st_mtime, 'Crunch is unchanged'
+ # update dds, so should recrunch
+ time.sleep(0.1)
+ os.utime('ship.dds', None)
+ Popen(['python', FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
+ assert crunch_time < os.stat('ship.crn').st_mtime, 'Crunch was changed'
+
+elif 'browser' in str(sys.argv):
+ # Browser tests.
+
+ # Run a server and a web page. When a test runs, we tell the server about it,
+ # which tells the web page, which then opens a window with the test. Doing
+ # it this way then allows the page to close() itself when done.
+
+ def harness_server_func(q):
+ class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ def do_GET(s):
+ s.send_response(200)
+ s.send_header("Content-type", "text/html")
+ s.end_headers()
+ if s.path == '/run_harness':
+ s.wfile.write(open(path_from_root('tests', 'browser_harness.html')).read())
+ else:
+ result = 'False'
+ if not q.empty():
+ result = q.get()
+ s.wfile.write(result)
+ s.wfile.close()
+ httpd = BaseHTTPServer.HTTPServer(('localhost', 9999), TestServerHandler)
+ httpd.serve_forever() # test runner will kill us
+
+ def server_func(dir, q):
+ class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ def do_GET(s):
+ if 'report_' in s.path:
+ q.put(s.path)
+ else:
+ filename = s.path[1:]
+ if os.path.exists(filename):
+ s.send_response(200)
+ s.send_header("Content-type", "text/html")
+ s.end_headers()
+ s.wfile.write(open(filename).read())
+ s.wfile.close()
+ else:
+ s.send_response(500)
+ s.send_header("Content-type", "text/html")
+ s.end_headers()
+ os.chdir(dir)
+ httpd = BaseHTTPServer.HTTPServer(('localhost', 8888), TestServerHandler)
+ httpd.serve_forever() # test runner will kill us
+
+ class browser(RunnerCore):
+ def __init__(self, *args, **kwargs):
+ super(browser, self).__init__(*args, **kwargs)
+
+ if hasattr(browser, 'harness_server'): return
+ browser.harness_queue = multiprocessing.Queue()
+ browser.harness_server = multiprocessing.Process(target=harness_server_func, args=(browser.harness_queue,))
+ browser.harness_server.start()
+ print '[Browser harness server on process %d]' % browser.harness_server.pid
+ webbrowser.open_new('http://localhost:9999/run_harness')
+
+ def __del__(self):
+ if not hasattr(browser, 'harness_server'): return
+
+ browser.harness_server.terminate()
+ delattr(browser, 'harness_server')
+ print '[Browser harness server terminated]'
+ # On Windows, shutil.rmtree() in tearDown() raises this exception if we do not wait a bit:
+ # WindowsError: [Error 32] The process cannot access the file because it is being used by another process.
+ time.sleep(0.1)
+
def run_browser(self, html_file, message, expectedResult=None):
if expectedResult is not None:
try:
- def server_func(q):
- class TestServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- def do_GET(s):
- q.put(s.path)
- httpd = BaseHTTPServer.HTTPServer(('localhost', 8888), TestServerHandler)
- httpd.serve_forever() # test runner will kill us
queue = multiprocessing.Queue()
- server = multiprocessing.Process(target=server_func, args=(queue,))
+ server = multiprocessing.Process(target=functools.partial(server_func, self.get_dir()), args=(queue,))
server.start()
- webbrowser.open_new(os.path.abspath(html_file))
+ browser.harness_queue.put('http://localhost:8888/' + html_file)
output = '[no http server activity]'
start = time.time()
- while time.time() - start < 5:
+ while time.time() - start < 60:
if not queue.empty():
output = queue.get()
break
time.sleep(0.1)
+
self.assertIdentical(expectedResult, output)
finally:
server.terminate()
+ time.sleep(0.1) # see comment about Windows above
else:
webbrowser.open_new(os.path.abspath(html_file))
print 'A web browser window should have opened a page containing the results of a part of this test.'
@@ -6203,13 +7363,6 @@ f.close()
time.sleep(5)
print '(moving on..)'
- def test_emcc_html(self):
- # test HTML generation.
- output = Popen([EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.html'], stdout=PIPE, stderr=PIPE).communicate()
- assert len(output[0]) == 0, output[0]
- assert os.path.exists('something.html'), output
- self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.')
-
def with_report_result(self, code):
return code.replace('REPORT_RESULT();', '''
char output[1000];
@@ -6218,9 +7371,81 @@ f.close()
"xhr.open('GET', 'http://localhost:8888/report_result?%d');"
"xhr.send();", result);
emscripten_run_script(output);
+ emscripten_run_script("setTimeout(function() { window.close() }, 1000)");
''')
- def test_emcc_compression(self):
+ def reftest(self, expected):
+ basename = os.path.basename(expected)
+ shutil.copyfile(expected, os.path.join(self.get_dir(), basename))
+ open(os.path.join(self.get_dir(), 'reftest.js'), 'w').write('''
+ function doReftest() {
+ if (doReftest.done) return;
+ doReftest.done = true;
+ var img = new Image();
+ img.onload = function() {
+ assert(img.width == Module.canvas.width, 'Invalid width: ' + Module.canvas.width + ', should be ' + img.width);
+ assert(img.height == Module.canvas.height, 'Invalid height: ' + Module.canvas.height + ', should be ' + img.height);
+
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ var expected = ctx.getImageData(0, 0, img.width, img.height).data;
+
+ var actualUrl = Module.canvas.toDataURL();
+ var actualImage = new Image();
+ actualImage.onload = function() {
+ var actualCanvas = document.createElement('canvas');
+ actualCanvas.width = actualImage.width;
+ actualCanvas.height = actualImage.height;
+ var actualCtx = actualCanvas.getContext('2d');
+ actualCtx.drawImage(actualImage, 0, 0);
+ var actual = actualCtx.getImageData(0, 0, actualImage.width, actualImage.height).data;
+
+ var total = 0;
+ for (var x = 0; x < img.width; x++) {
+ for (var y = 0; y < img.height; y++) {
+ total += Math.abs(expected[y*img.width*4 + x*4 + 0] - actual[y*img.width*4 + x*4 + 0]);
+ total += Math.abs(expected[y*img.width*4 + x*4 + 1] - actual[y*img.width*4 + x*4 + 1]);
+ total += Math.abs(expected[y*img.width*4 + x*4 + 2] - actual[y*img.width*4 + x*4 + 2]);
+ }
+ }
+ var wrong = Math.floor(total / (img.width*img.height*3)); // floor, to allow some margin of error for antialiasing
+
+ xhr = new XMLHttpRequest();
+ xhr.open('GET', 'http://localhost:8888/report_result?' + wrong);
+ xhr.send();
+ setTimeout(function() { window.close() }, 1000);
+ };
+ actualImage.src = actualUrl;
+ }
+ img.src = '%s';
+ };
+ Module['postRun'] = doReftest;
+ Module['preRun'].push(function() {
+ setTimeout(doReftest, 1000); // if run() throws an exception and postRun is not called, this will kick in
+ });
+''' % basename)
+
+ def test_html(self):
+ # test HTML generation.
+ self.reftest(path_from_root('tests', 'htmltest.png'))
+ output = Popen(['python', EMCC, path_from_root('tests', 'hello_world_sdl.cpp'), '-o', 'something.html', '--pre-js', 'reftest.js']).communicate()
+ self.run_browser('something.html', 'You should see "hello, world!" and a colored cube.', '/report_result?0')
+
+ def build_native_lzma(self):
+ lzma_native = path_from_root('third_party', 'lzma.js', 'lzma-native')
+ if os.path.isfile(lzma_native) and os.access(lzma_native, os.X_OK): return
+
+ cwd = os.getcwd()
+ try:
+ os.chdir(path_from_root('third_party', 'lzma.js'))
+ Popen(['sh', './doit.sh']).communicate()
+ finally:
+ os.chdir(cwd)
+
+ def test_compression(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
#include <stdio.h>
#include <emscripten.h>
@@ -6232,7 +7457,8 @@ f.close()
}
'''))
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html',
+ self.build_native_lzma()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html',
'--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'),
path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'),
'LZMA.decompress')]).communicate()
@@ -6242,35 +7468,56 @@ f.close()
shutil.move(os.path.join(self.get_dir(), 'page.js'), 'page.js.renamedsoitcannotbefound');
self.run_browser('page.html', '', '/report_result?1')
- def test_emcc_preload_file(self):
+ def test_preload_file(self):
open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''load me right before running the code please''')
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
- #include <stdio.h>
- #include <string.h>
- #include <emscripten.h>
- int main() {
- FILE *f = fopen("somefile.txt", "r");
- char buf[100];
- fread(buf, 1, 20, f);
- buf[20] = 0;
- fclose(f);
- printf("|%s|\n", buf);
+ def make_main(path):
+ print path
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
+ #include <stdio.h>
+ #include <string.h>
+ #include <emscripten.h>
+ int main() {
+ FILE *f = fopen("%s", "r");
+ char buf[100];
+ fread(buf, 1, 20, f);
+ buf[20] = 0;
+ fclose(f);
+ printf("|%%s|\n", buf);
- int result = !strcmp("load me right before", buf);
- REPORT_RESULT();
- return 0;
- }
- '''))
+ int result = !strcmp("load me right before", buf);
+ REPORT_RESULT();
+ return 0;
+ }
+ ''' % path))
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '-o', 'page.html']).communicate()
+ make_main('somefile.txt')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'somefile.txt', '-o', 'page.html']).communicate()
self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
- def test_emcc_multifile(self):
+ # By absolute path
+
+ make_main(os.path.join(self.get_dir(), 'somefile.txt'))
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', os.path.join(self.get_dir(), 'somefile.txt'), '-o', 'page.html']).communicate()
+ self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+
+ # With FS.preloadFile
+
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ Module.preRun = function() {
+ FS.createPreloadedFile('/', 'someotherfile.txt', 'somefile.txt', true, false);
+ };
+ ''')
+ make_main('someotherfile.txt')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'pre.js', '-o', 'page.html']).communicate()
+ self.run_browser('page.html', 'You should see |load me right before|.', '/report_result?1')
+
+ def test_multifile(self):
# a few files inside a directory
- if not os.path.exists(os.path.join(self.get_dir(), 'subdirr')):
- os.makedirs(os.path.join(self.get_dir(), 'subdirr'));
+ self.clear()
+ os.makedirs(os.path.join(self.get_dir(), 'subdirr'));
+ os.makedirs(os.path.join(self.get_dir(), 'subdirr', 'moar'));
open(os.path.join(self.get_dir(), 'subdirr', 'data1.txt'), 'w').write('''1214141516171819''')
- open(os.path.join(self.get_dir(), 'subdirr', 'data2.txt'), 'w').write('''3.14159265358979''')
+ open(os.path.join(self.get_dir(), 'subdirr', 'moar', 'data2.txt'), 'w').write('''3.14159265358979''')
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
#include <stdio.h>
#include <string.h>
@@ -6285,7 +7532,7 @@ f.close()
printf("|%s|\n", buf);
int result = !strcmp("1214141516171819", buf);
- FILE *f2 = fopen("subdirr/data2.txt", "r");
+ FILE *f2 = fopen("subdirr/moar/data2.txt", "r");
fread(buf, 1, 16, f2);
buf[16] = 0;
fclose(f2);
@@ -6298,17 +7545,18 @@ f.close()
'''))
# by individual files
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr/data1.txt', '--preload-file', 'subdirr/data2.txt', '-o', 'page.html']).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr/data1.txt', '--preload-file', 'subdirr/moar/data2.txt', '-o', 'page.html']).communicate()
self.run_browser('page.html', 'You should see two cool numbers', '/report_result?1')
-
os.remove('page.html')
- # by directory
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr', '-o', 'page.html']).communicate()
+ # by directory, and remove files to make sure
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--preload-file', 'subdirr', '-o', 'page.html']).communicate()
+ shutil.rmtree(os.path.join(self.get_dir(), 'subdirr'))
self.run_browser('page.html', 'You should see two cool numbers', '/report_result?1')
- def test_emcc_compressed_file(self):
+ def test_compressed_file(self):
open(os.path.join(self.get_dir(), 'datafile.txt'), 'w').write('compress this please' + (2000*'.'))
+ open(os.path.join(self.get_dir(), 'datafile2.txt'), 'w').write('moar' + (100*'!'))
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(self.with_report_result(r'''
#include <stdio.h>
#include <string.h>
@@ -6321,52 +7569,202 @@ f.close()
fclose(f);
printf("file says: |%s|\n", buf);
int result = !strcmp("compress this please", buf);
+ FILE *f2 = fopen("datafile2.txt", "r");
+ fread(buf, 1, 5, f2);
+ buf[5] = 0;
+ fclose(f2);
+ result = result && !strcmp("moar!", buf);
+ printf("file 2 says: |%s|\n", buf);
REPORT_RESULT();
return 0;
}
'''))
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html', '--preload-file', 'datafile.txt',
+ self.build_native_lzma()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-o', 'page.html', '--preload-file', 'datafile.txt', '--preload-file', 'datafile2.txt',
'--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'),
path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'),
'LZMA.decompress')]).communicate()
assert os.path.exists(os.path.join(self.get_dir(), 'datafile.txt')), 'must be data file'
- assert os.path.exists(os.path.join(self.get_dir(), 'datafile.txt.compress')), 'must be data file in compressed form'
+ assert os.path.exists(os.path.join(self.get_dir(), 'page.data.compress')), 'must be data file in compressed form'
assert os.stat(os.path.join(self.get_dir(), 'page.js')).st_size != os.stat(os.path.join(self.get_dir(), 'page.js.compress')).st_size, 'compressed file must be different'
shutil.move(os.path.join(self.get_dir(), 'datafile.txt'), 'datafile.txt.renamedsoitcannotbefound');
self.run_browser('page.html', '', '/report_result?1')
- def test_emcc_sdl_image(self):
- # load an image file, get pixel data
+ def test_sdl_image(self):
+ # load an image file, get pixel data. Also O2 coverage for --preload-file
shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpg'))
open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read()))
- Popen([EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '--preload-file', 'screenshot.jpg', '-o', 'page.html']).communicate()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-O2', '--preload-file', 'screenshot.jpg', '-o', 'page.html']).communicate()
self.run_browser('page.html', '', '/report_result?600')
- def test_emcc_sdl_image_compressed(self):
- for image, worth_compressing, width, height in [(path_from_root('tests', 'screenshot2.png'), True, 300, 225),
- (path_from_root('tests', 'screenshot.jpg'), False, 600, 450)]:
+ def test_sdl_image_compressed(self):
+ for image, width in [(path_from_root('tests', 'screenshot2.png'), 300),
+ (path_from_root('tests', 'screenshot.jpg'), 600)]:
self.clear()
- print image, worth_compressing
+ print image
basename = os.path.basename(image)
shutil.copyfile(image, os.path.join(self.get_dir(), basename))
- open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read()).replace('screenshot.jpg', basename).replace('600', str(width)).replace('450', str(height)))
+ open(os.path.join(self.get_dir(), 'sdl_image.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image.c')).read()).replace('screenshot.jpg', basename))
- Popen([EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '--preload-file', basename, '-o', 'page.html',
+ self.build_native_lzma()
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '--preload-file', basename, '-o', 'page.html',
'--compression', '%s,%s,%s' % (path_from_root('third_party', 'lzma.js', 'lzma-native'),
path_from_root('third_party', 'lzma.js', 'lzma-decoder.js'),
'LZMA.decompress')]).communicate()
- assert ('.compress' in open('page.js').read()) == worth_compressing, 'do not compress image if not worth it'
- assert os.path.exists(basename + '.compress') == worth_compressing, 'remove .compress if not compressing'
- if worth_compressing:
- shutil.move(os.path.join(self.get_dir(), basename), basename + '.renamedsoitcannotbefound');
+ shutil.move(os.path.join(self.get_dir(), basename), basename + '.renamedsoitcannotbefound');
self.run_browser('page.html', '', '/report_result?' + str(width))
- def test_emcc_worker(self):
+ def test_sdl_canvas(self):
+ open(os.path.join(self.get_dir(), 'sdl_canvas.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas.c')).read()))
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_canvas.c'), '-o', 'page.html']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
+ def test_sdl_key(self):
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ Module.postRun = function() {
+ function doOne() {
+ _one();
+ setTimeout(doOne, 1000/60);
+ }
+ setTimeout(doOne, 1000/60);
+ }
+
+ function simulateKeyEvent(c) {
+ var event = document.createEvent("KeyboardEvent");
+ event.initKeyEvent("keydown", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ dispatchEvent(event);
+ var event2 = document.createEvent("KeyboardEvent");
+ event2.initKeyEvent("keyup", true, true, window,
+ 0, 0, 0, 0,
+ c, c);
+ dispatchEvent(event2);
+ }
+ ''')
+ open(os.path.join(self.get_dir(), 'sdl_key.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_key.c')).read()))
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_key.c'), '-o', 'page.html', '--pre-js', 'pre.js']).communicate()
+ self.run_browser('page.html', '', '/report_result?510510')
+
+ def test_sdl_mouse(self):
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ function simulateMouseEvent(x, y, button) {
+ var event = document.createEvent("MouseEvents");
+ if (button >= 0) {
+ var event1 = document.createEvent("MouseEvents");
+ event1.initMouseEvent('mousedown', true, true, window,
+ 1, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y,
+ 0, 0, 0, 0,
+ button, null);
+ Module['canvas'].dispatchEvent(event1);
+ var event2 = document.createEvent("MouseEvents");
+ event2.initMouseEvent('mouseup', true, true, window,
+ 1, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y,
+ 0, 0, 0, 0,
+ button, null);
+ Module['canvas'].dispatchEvent(event2);
+ } else {
+ var event1 = document.createEvent("MouseEvents");
+ event1.initMouseEvent('mousemove', true, true, window,
+ 0, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y,
+ 0, 0, 0, 0,
+ 0, null);
+ Module['canvas'].dispatchEvent(event1);
+ }
+ }
+ window['simulateMouseEvent'] = simulateMouseEvent;
+ ''')
+ open(os.path.join(self.get_dir(), 'sdl_mouse.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_mouse.c')).read()))
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_mouse.c'), '-O2', '--minify', '0', '-o', 'page.html', '--pre-js', 'pre.js']).communicate()
+ self.run_browser('page.html', '', '/report_result?740')
+
+ def test_sdl_audio(self):
+ shutil.copyfile(path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg'))
+ shutil.copyfile(path_from_root('tests', 'sounds', 'alarmcreatemiltaryfoot_1.wav'), os.path.join(self.get_dir(), 'sound2.wav'))
+ open(os.path.join(self.get_dir(), 'sdl_audio.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio.c')).read()))
+
+ # use closure to check for a possible bug with closure minifying away newer Audio() attributes
+ Popen(['python', EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio.c'), '--preload-file', 'sound.ogg', '--preload-file', 'sound2.wav', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play", "_play2"]']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
+ def test_sdl_audio_quickload(self):
+ open(os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_audio_quickload.c')).read()))
+
+ # use closure to check for a possible bug with closure minifying away newer Audio() attributes
+ Popen(['python', EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_quickload.c'), '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play"]']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
+ def test_sdl_gl_read(self):
+ # SDL, OpenGL, readPixels
+ open(os.path.join(self.get_dir(), 'sdl_gl_read.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_gl_read.c')).read()))
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_gl_read.c'), '-o', 'something.html']).communicate()
+ self.run_browser('something.html', '.', '/report_result?1')
+
+ def test_sdl_ogl(self):
+ # SDL, OpenGL, textures, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-gray-purple.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_ogl.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0')
+
+ def test_sdl_ogl_defaultmatrixmode(self):
+ # SDL, OpenGL, textures, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-gray-purple.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_ogl_defaultMatrixMode.c'), '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0')
+
+ def test_sdl_ogl_p(self):
+ # Immediate mode with pointers
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-gray.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_ogl_p.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0')
+
+ def test_sdl_fog_simple(self):
+ # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-fog-simple.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_fog_simple.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+
+ def test_sdl_fog_negative(self):
+ # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-fog-negative.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_fog_negative.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+
+ def test_sdl_fog_density(self):
+ # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-fog-density.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_fog_density.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+
+ def test_sdl_fog_exp2(self):
+ # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-fog-exp2.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_fog_exp2.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+
+ def test_sdl_fog_linear(self):
+ # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.reftest(path_from_root('tests', 'screenshot-fog-linear.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_fog_linear.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate()
+ self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+
+ def test_worker(self):
# Test running in a web worker
- output = Popen([EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate()
+ output = Popen(['python', EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate()
assert len(output[0]) == 0, output[0]
assert os.path.exists('worker.js'), output
self.assertContained('you should not see this text when in a worker!', run_js('worker.js')) # code should run standalone
@@ -6374,186 +7772,210 @@ f.close()
html_file.write('''
<html>
<body>
+ Worker Test
<script>
var worker = new Worker('worker.js');
worker.onmessage = function(event) {
- document.write("<hr>Called back by the worker: " + event.data + "<br><hr>");
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'http://localhost:8888/report_result?' + event.data);
+ xhr.send();
+ setTimeout(function() { window.close() }, 1000);
};
</script>
</body>
</html>
''')
html_file.close()
- self.run_browser('main.html', 'You should see that the worker was called, and said "hello from worker!"')
+ self.run_browser('main.html', 'You should see that the worker was called, and said "hello from worker!"', '/report_result?hello%20from%20worker!')
+
+ def test_glgears(self):
+ self.reftest(path_from_root('tests', 'gears.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html',
+ '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate()
+ self.run_browser('something.html', 'You should see animating gears.', '/report_result?0')
- def test_emcc_gl(self):
- # test the OpenGL ES implementation
- output = Popen([EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html',
+ def test_glgears_animation(self):
+ Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html',
'-DHAVE_BUILTIN_SINCOS',
- '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')],
- stdout=PIPE, stderr=PIPE).communicate()
- assert len(output[0]) == 0, output[0]
- assert os.path.exists('something.html'), output
+ '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate()
self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true')
- def test_emcc_gl_fail(self):
+ def test_glgears_bad(self):
# Make sure that OpenGL ES is not available if typed arrays are not used
- output = Popen([EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html',
+ Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html',
'-DHAVE_BUILTIN_SINCOS',
'-s', 'USE_TYPED_ARRAYS=0',
- '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')],
- stdout=PIPE, stderr=PIPE).communicate()
- assert len(output[0]) == 0, output[0]
- assert os.path.exists('something.html'), output
+ '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate()
self.run_browser('something.html', 'You should not see animating gears.', '/report_gl_result?false')
- def test_emcc_l_link(self):
- # Linking with -lLIBNAME and -L/DIRNAME should work
+ def test_glgears_deriv(self):
+ self.reftest(path_from_root('tests', 'gears.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html',
+ '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate()
+ self.run_browser('something.html', 'You should see animating gears.', '/report_result?0')
+ src = open('something.html').read()
+ assert 'gl-matrix' not in src, 'Should not include glMatrix when not needed'
+
+ def test_glbook(self):
+ programs = self.get_library('glbook', [
+ os.path.join('Chapter_2', 'Hello_Triangle', 'CH02_HelloTriangle.bc'),
+ os.path.join('Chapter_8', 'Simple_VertexShader', 'CH08_SimpleVertexShader.bc'),
+ os.path.join('Chapter_9', 'Simple_Texture2D', 'CH09_SimpleTexture2D.bc'),
+ os.path.join('Chapter_9', 'Simple_TextureCubemap', 'CH09_TextureCubemap.bc'),
+ os.path.join('Chapter_9', 'TextureWrap', 'CH09_TextureWrap.bc'),
+ os.path.join('Chapter_10', 'MultiTexture', 'CH10_MultiTexture.bc'),
+ os.path.join('Chapter_13', 'ParticleSystem', 'CH13_ParticleSystem.bc'),
+ ], configure=None)
+ for program in programs:
+ print program
+ basename = os.path.basename(program)
+ args = []
+ if basename == 'CH10_MultiTexture.bc':
+ shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'basemap.tga'), os.path.join(self.get_dir(), 'basemap.tga'))
+ shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'lightmap.tga'), os.path.join(self.get_dir(), 'lightmap.tga'))
+ args = ['--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga']
+ elif basename == 'CH13_ParticleSystem.bc':
+ shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_13', 'ParticleSystem', 'smoke.tga'), os.path.join(self.get_dir(), 'smoke.tga'))
+ args = ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage
+
+ self.reftest(path_from_root('tests', 'glbook', basename.replace('.bc', '.png')))
+ Popen(['python', EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js'] + args).communicate()
+ self.run_browser('program.html', '', '/report_result?0')
+
+ def btest(self, filename, expected=None, reference=None, reference_slack=0, args=[]): # TODO: use in all other tests
+ if not reference:
+ open(os.path.join(self.get_dir(), filename), 'w').write(self.with_report_result(open(path_from_root('tests', filename)).read()))
+ else:
+ expected = [str(i) for i in range(0, reference_slack+1)]
+ shutil.copyfile(path_from_root('tests', filename), os.path.join(self.get_dir(), filename))
+ self.reftest(path_from_root('tests', reference))
+ args = args + ['--pre-js', 'reftest.js']
+ Popen(['python', EMCC, os.path.join(self.get_dir(), filename), '-o', 'test.html'] + args).communicate()
+ if type(expected) is str: expected = [expected]
+ self.run_browser('test.html', '.', ['/report_result?' + e for e in expected])
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
- extern void printey();
- int main() {
- printey();
- return 0;
- }
- ''')
+ def test_emscripten_api(self):
+ self.btest('emscripten_api_browser.cpp', '1')
- try:
- os.makedirs(os.path.join(self.get_dir(), 'libdir'));
- except:
- pass
+ def test_emscripten_fs_api(self):
+ self.btest('emscripten_fs_api_browser.cpp', '1')
- open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
- #include <stdio.h>
- void printey() {
- printf("hello from lib\\n");
- }
- ''')
+ def test_gc(self):
+ self.btest('browser_gc.cpp', '1')
- Popen([EMCC, os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-c'], stdout=PIPE, stderr=STDOUT).communicate()
- shutil.move(os.path.join(self.get_dir(), 'libfile.o'), os.path.join(self.get_dir(), 'libdir', 'libfile.so'))
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile'], stdout=PIPE, stderr=STDOUT).communicate()
- self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_glshaderinfo(self):
+ self.btest('glshaderinfo.cpp', '1')
- def test_emcc_embed_file(self):
- open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''hello from a file with lots of data and stuff in it thank you very much''')
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
- #include <stdio.h>
- int main() {
- FILE *f = fopen("somefile.txt", "r");
- char buf[100];
- fread(buf, 1, 20, f);
- buf[20] = 0;
- fclose(f);
- printf("|%s|\n", buf);
- return 0;
- }
- ''')
+ def test_sdlglshader(self):
+ self.btest('sdlglshader.c', reference='sdlglshader.png', args=['--closure', '1'])
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'somefile.txt']).communicate()
- self.assertContained('|hello from a file wi|', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_gl_ps(self):
+ # pointers and a shader
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'])
- def test_emcc_multidynamic_link(self):
- # Linking the same dynamic library in will error, normally, since we statically link it, causing dupe symbols
- # A workaround is to use --ignore-dynamic-linking, see emcc --help for details
+ def test_matrix_identity(self):
+ self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'])
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
- #include <stdio.h>
- extern void printey();
- extern void printother();
- int main() {
- printf("*");
- printey();
- printf("\n");
- printother();
- printf("\n");
- printf("*");
- return 0;
- }
- ''')
+ def test_cubegeom_pre(self):
+ self.btest('cubegeom_pre.c', expected='-1472804742')
- try:
- os.makedirs(os.path.join(self.get_dir(), 'libdir'));
- except:
- pass
+ def test_cubegeom_pre2(self):
+ self.btest('cubegeom_pre2.c', expected='-1472804742', args=['-s', 'GL_DEBUG=1']) # some coverage for GL_DEBUG not breaking the build
- open(os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), 'w').write('''
- #include <stdio.h>
- void printey() {
- printf("hello from lib");
- }
- ''')
+ def test_cubegeom_pre3(self):
+ self.btest('cubegeom_pre3.c', expected='-1472804742')
- open(os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), 'w').write('''
- #include <stdio.h>
- extern void printey();
- void printother() {
- printf("|");
- printey();
- printf("|");
- }
- ''')
+ def test_cubegeom(self):
+ self.btest('cubegeom.c', expected=['188641320', '1522377227'])
- # This lets us link the same dynamic lib twice. We will need to link it in manually at the end.
- compiler = [EMCC, '--ignore-dynamic-linking']
+ def test_cubegeom_color(self):
+ self.btest('cubegeom_color.c', expected='588472350')
- # Build libfile normally into an .so
- Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libfile.cpp'), '-o', os.path.join(self.get_dir(), 'libdir', 'libfile.so')]).communicate()
- # Build libother and dynamically link it to libfile - but add --ignore-dynamic-linking
- Popen(compiler + [os.path.join(self.get_dir(), 'libdir', 'libother.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-o', os.path.join(self.get_dir(), 'libdir', 'libother.so')]).communicate()
- # Build the main file, linking in both the libs
- Popen(compiler + [os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother', '-c']).communicate()
+ def test_cubegeom_normal(self):
+ self.btest('cubegeom_normal.c', expected='752917084')
- # The normal build system is over. We need to do an additional step to link in the dynamic libraries, since we ignored them before
- Popen([EMCC, os.path.join(self.get_dir(), 'main.o'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile', '-lother']).communicate()
+ def test_cubegeom_normal_dap(self): # draw is given a direct pointer to clientside memory, no element array buffer
+ self.btest('cubegeom_normal_dap.c', expected='752917084')
- self.assertContained('*hello from lib\n|hello from lib|\n*', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_cubegeom_normal_dap_far(self): # indices do nto start from 0
+ self.btest('cubegeom_normal_dap_far.c', expected='752917084')
- def test_emcc_js_link(self):
- open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
- #include <stdio.h>
- int main() {
- printf("hello from main\\n");
- return 0;
- }
- ''')
- open(os.path.join(self.get_dir(), 'before.js'), 'w').write('''
- var MESSAGE = 'hello from js';
- if (typeof Module != 'undefined') throw 'This code should run before anything else!';
- ''')
- open(os.path.join(self.get_dir(), 'after.js'), 'w').write('''
- Module.print(MESSAGE);
- ''')
+ def test_cubegeom_normal_dap_far_range(self): # glDrawRangeElements
+ self.btest('cubegeom_normal_dap_far_range.c', expected='752917084')
- Popen([EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--pre-js', 'before.js', '--post-js', 'after.js']).communicate()
- self.assertContained('hello from main\nhello from js\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_cubegeom_normal_dap_far_glda(self): # use glDrawArrays
+ self.btest('cubegeom_normal_dap_far_glda.c', expected='-218745386')
- def test_eliminator(self):
- input = open(path_from_root('tools', 'eliminator', 'eliminator-test.js')).read()
- expected = open(path_from_root('tools', 'eliminator', 'eliminator-test-output.js')).read()
- output = Popen([NODE_JS, COFFEESCRIPT, VARIABLE_ELIMINATOR], stdin=PIPE, stdout=PIPE).communicate(input)[0]
- self.assertIdentical(expected, output)
+ def test_cubegeom_normal_dap_far_glda_quad(self): # with quad
+ self.btest('cubegeom_normal_dap_far_glda_quad.c', expected='1757386625')
- def test_fix_closure(self):
- input = path_from_root('tests', 'test-fix-closure.js')
- expected = path_from_root('tests', 'test-fix-closure.out.js')
- Popen(['python', path_from_root('tools', 'fix_closure.py'), input, 'out.js']).communicate(input)
- output = open('out.js').read()
- assert '0,zzz_Q_39fa,0' in output
- assert 'function(a,c)' not in output # should be uninlined, so it gets a name
- assert run_js(input) == run_js('out.js')
+ def test_cubegeom_mt(self):
+ self.btest('cubegeom_mt.c', expected='-457159152') # multitexture
- def test_js_optimizer(self):
- for input, expected, passes in [
- (path_from_root('tools', 'test-js-optimizer.js'), open(path_from_root('tools', 'test-js-optimizer-output.js')).read(),
- ['hoistMultiples', 'loopOptimizer', 'unGlobalize', 'removeAssignsToUndefined', 'simplifyExpressionsPre', 'simplifyExpressionsPost']),
- (path_from_root('tools', 'test-js-optimizer-t2c.js'), open(path_from_root('tools', 'test-js-optimizer-t2c-output.js')).read(),
- ['simplifyExpressionsPre', 'optimizeShiftsConservative']),
- (path_from_root('tools', 'test-js-optimizer-t2.js'), open(path_from_root('tools', 'test-js-optimizer-t2-output.js')).read(),
- ['simplifyExpressionsPre', 'optimizeShiftsAggressive']),
- ]:
- output = Popen([NODE_JS, JS_OPTIMIZER, input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0]
- self.assertIdentical(expected, output.replace('\n\n', '\n'))
+ def test_cubegeom_color2(self):
+ self.btest('cubegeom_color2.c', expected='1121999515')
+
+ def test_cubegeom_texturematrix(self):
+ self.btest('cubegeom_texturematrix.c', expected='1297500583')
+
+ def test_cubegeom_fog(self):
+ self.btest('cubegeom_fog.c', expected='1617140399')
+
+ def test_cube_explosion(self):
+ self.btest('cube_explosion.c', expected='667220544')
+
+ def test_sdl_canvas_palette(self):
+ self.btest('sdl_canvas_palette.c', reference='sdl_canvas_palette.png')
+
+ def test_sdl_maprgba(self):
+ self.btest('sdl_maprgba.c', reference='sdl_maprgba.png', reference_slack=3)
+
+ def zzztest_sdl_canvas_palette_2(self): # XXX disabled until we have proper automation
+ open(os.path.join(self.get_dir(), 'sdl_canvas_palette_2.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas_palette_2.c')).read()))
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('Module[\'preRun\'] = function() { SDL.defaults.copyOnLock = false }')
+
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'sdl_canvas_palette_2.c'), '-o', 'page.html', '--pre-js', 'pre.js']).communicate()
+ self.run_browser('page.html', '')
+
+ def test_s3tc(self):
+ shutil.copyfile(path_from_root('tests', 'screenshot.dds'), os.path.join(self.get_dir(), 'screenshot.dds'))
+ self.btest('s3tc.c', reference='s3tc.png', args=['--preload-file', 'screenshot.dds'])
+
+ def test_s3tc_crunch(self):
+ shutil.copyfile(path_from_root('tests', 'ship.dds'), 'ship.dds')
+ shutil.copyfile(path_from_root('tests', 'bloom.dds'), 'bloom.dds')
+ shutil.copyfile(path_from_root('tests', 'water.dds'), 'water.dds')
+ Popen(['python', FILE_PACKAGER, 'test.data', '--pre-run', '--crunch', '--preload', 'ship.dds', 'bloom.dds', 'water.dds'], stdout=open('pre.js', 'w')).communicate()
+ assert os.stat('test.data').st_size < 0.5*(os.stat('ship.dds').st_size+os.stat('bloom.dds').st_size+os.stat('water.dds').st_size), 'Compressed should be smaller than dds'
+ shutil.move('ship.dds', 'ship.donotfindme.dds') # make sure we load from the compressed
+ shutil.move('bloom.dds', 'bloom.donotfindme.dds') # make sure we load from the compressed
+ shutil.move('water.dds', 'water.donotfindme.dds') # make sure we load from the compressed
+ self.btest('s3tc_crunch.c', reference='s3tc_crunch.png', args=['--pre-js', 'pre.js'])
+
+ def test_aniso(self):
+ shutil.copyfile(path_from_root('tests', 'water.dds'), 'water.dds')
+ self.btest('aniso.c', reference='aniso.png', reference_slack=2, args=['--preload-file', 'water.dds'])
+
+ def test_tex_nonbyte(self):
+ self.btest('tex_nonbyte.c', reference='tex_nonbyte.png')
+
+ def test_float_tex(self):
+ self.btest('float_tex.cpp', reference='float_tex.png')
+
+ def test_pre_run_deps(self):
+ # Adding a dependency in preRun will delay run
+ open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
+ Module.preRun = function() {
+ addRunDependency();
+ Module.print('preRun called, added a dependency...');
+ setTimeout(function() {
+ Module.okk = 10;
+ removeRunDependency()
+ }, 2000);
+ };
+ ''')
+ self.btest('pre_run_deps.cpp', expected='10', args=['--pre-js', 'pre.js'])
elif 'benchmark' in str(sys.argv):
# Benchmarks. Run them with argument |benchmark|. To run a specific test, do
@@ -6649,11 +8071,10 @@ elif 'benchmark' in str(sys.argv):
final_filename = os.path.join(dirname, 'src.js')
try_delete(final_filename)
- output = Popen([EMCC, filename, '-O3',
- '-s', 'INLINING_LIMIT=0',
+ output = Popen(['python', EMCC, filename, '-O3',
'-s', 'TOTAL_MEMORY=100*1024*1024', '-s', 'FAST_MEMORY=10*1024*1024',
'-o', final_filename] + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate()
- assert os.path.exists(final_filename), 'Failed to compile file: ' + '\n'.join(output)
+ assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0]
# Run JS
global total_times, tests_done
@@ -6904,6 +8325,8 @@ elif 'sanity' in str(sys.argv):
def do(self, command):
if type(command) is not list:
command = [command]
+ if command[0] == EMCC:
+ command = ['python'] + command
return Popen(command, stdout=PIPE, stderr=STDOUT).communicate()[0]
@@ -6937,7 +8360,7 @@ elif 'sanity' in str(sys.argv):
self.assertContained('Please edit that file and change the paths to fit your system', output)
self.assertContained('make sure LLVM_ROOT and NODE_JS are correct', output)
self.assertContained('This command will now exit. When you are done editing those paths, re-run it.', output)
- assert output.replace('\n', '').endswith('===='), 'We should have stopped: ' + output
+ assert output.split()[-1].endswith('===='), 'We should have stopped: ' + output
assert (open(CONFIG_FILE).read() == open(path_from_root('settings.py')).read()), 'Settings should be copied from settings.py'
# Second run, with bad EM_CONFIG
@@ -7018,6 +8441,24 @@ elif 'sanity' in str(sys.argv):
assert mtime(SANITY_FILE) >= mtime(CONFIG_FILE)
self.assertNotContained(SANITY_FAIL_MESSAGE, output)
+ # emcc should be configurable directly from EM_CONFIG without any config file
+ restore()
+ config = open(CONFIG_FILE, 'r').read()
+ os.environ['EM_CONFIG'] = config
+ wipe()
+ dirname = tempfile.mkdtemp(prefix='emscripten_test_' + self.__class__.__name__ + '_', dir=TEMP_DIR)
+ open(os.path.join(dirname, 'main.cpp'), 'w').write('''
+ #include <stdio.h>
+ int main() {
+ printf("hello from emcc with no config file\\n");
+ return 0;
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(dirname, 'main.cpp'), '-o', os.path.join(dirname, 'a.out.js')]).communicate()
+ self.assertContained('hello from emcc with no config file', run_js(os.path.join(dirname, 'a.out.js')))
+ del os.environ['EM_CONFIG']
+ shutil.rmtree(dirname)
+
def test_emcc_caching(self):
INCLUDING_MESSAGE = 'emcc: including X'
BUILDING_MESSAGE = 'emcc: building X for cache'
@@ -7041,8 +8482,8 @@ elif 'sanity' in str(sys.argv):
assert not os.path.exists(EMCC_CACHE)
try_delete('a.out.js')
- basebc_name = os.path.join(EMSCRIPTEN_TEMP_DIR, 'emcc-0-basebc.bc')
- dcebc_name = os.path.join(EMSCRIPTEN_TEMP_DIR, 'emcc-1-dce.bc')
+ basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc')
+ dcebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-dce.bc')
# Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time
for filename, libname in [('hello_malloc.cpp', 'dlmalloc'), ('hello_libcxx.cpp', 'libcxx')]:
@@ -7060,9 +8501,10 @@ elif 'sanity' in str(sys.argv):
assert os.path.exists(EMCC_CACHE)
assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc'))
if libname == 'libcxx':
- assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 4000000, 'libc++ is big'
- assert os.stat(basebc_name).st_size > 4000000, 'libc++ is indeed big'
- assert os.stat(dcebc_name).st_size < 2000000, 'Dead code elimination must remove most of libc++'
+ print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size
+ assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 2000000, 'libc++ is big'
+ assert os.stat(basebc_name).st_size > 2000000, 'libc++ is indeed big'
+ assert os.stat(dcebc_name).st_size < 1500000, 'Dead code elimination must remove most of libc++'
finally:
if emcc_debug:
os.environ['EMCC_DEBUG'] = emcc_debug
diff --git a/tests/s3tc.c b/tests/s3tc.c
new file mode 100644
index 00000000..c2736feb
--- /dev/null
+++ b/tests/s3tc.c
@@ -0,0 +1,158 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int hasext(const char *exts, const char *ext) // from cube2, zlib licensed
+{
+ int len = strlen(ext);
+ if(len) for(const char *cur = exts; (cur = strstr(cur, ext)); cur += len)
+ {
+ if((cur == exts || cur[-1] == ' ') && (cur[len] == ' ' || !cur[len])) return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Check extensions
+
+ const char *exts = (const char *)glGetString(GL_EXTENSIONS);
+ assert(hasext(exts, "GL_ARB_texture_compression"));
+ assert(hasext(exts, "GL_EXT_texture_compression_s3tc"));
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+
+ // Load the OpenGL texture
+
+ GLuint texture;
+
+ #define DDS_SIZE 262272
+ FILE *dds = fopen("screenshot.dds", "rb");
+ char *ddsdata = (char*)malloc(512*512*4);//DDS_SIZE);
+ assert(fread(ddsdata, 1, DDS_SIZE, dds) == DDS_SIZE);
+ fclose(dds);
+
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 512, 512, 0, DDS_SIZE-128, ddsdata+128);
+ assert(!glGetError());
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+
+ // Prepare and Render
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 8);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ // Render the last item using oldschool glBegin etc
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(1500);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/s3tc.png b/tests/s3tc.png
new file mode 100644
index 00000000..893ab397
--- /dev/null
+++ b/tests/s3tc.png
Binary files differ
diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c
new file mode 100644
index 00000000..57974109
--- /dev/null
+++ b/tests/s3tc_crunch.c
@@ -0,0 +1,210 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int hasext(const char *exts, const char *ext) // from cube2, zlib licensed
+{
+ int len = strlen(ext);
+ if(len) for(const char *cur = exts; (cur = strstr(cur, ext)); cur += len)
+ {
+ if((cur == exts || cur[-1] == ' ') && (cur[len] == ' ' || !cur[len])) return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Check extensions
+
+ const char *exts = (const char *)glGetString(GL_EXTENSIONS);
+ assert(hasext(exts, "GL_ARB_texture_compression"));
+ assert(hasext(exts, "GL_EXT_texture_compression_s3tc"));
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+
+ // Load the OpenGL textures
+
+ GLuint texture;
+
+ {
+ const int DDS_SIZE = 65664;
+ FILE *dds = fopen("ship.dds", "rb");
+ assert(dds);
+ char *ddsdata = (char*)malloc(DDS_SIZE);
+ assert(fread(ddsdata, 1, DDS_SIZE, dds) == DDS_SIZE);
+ fclose(dds);
+
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 256, 256, 0, DDS_SIZE-128, ddsdata+128);
+ assert(!glGetError());
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ }
+
+ // second texture
+
+ GLuint texture2;
+
+ {
+ const int DDS_SIZE = 32896;
+ FILE *dds = fopen("bloom.dds", "rb");
+ assert(dds);
+ char *ddsdata = (char*)malloc(DDS_SIZE);
+ assert(fread(ddsdata, 1, DDS_SIZE, dds) == DDS_SIZE);
+ fclose(dds);
+
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 256, 256, 0, DDS_SIZE-128, ddsdata+128);
+ assert(!glGetError());
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ }
+
+ // third, a non-square texture with mipmaps
+
+ GLuint texture3;
+
+ {
+ const int DDS_SIZE = 43920;
+ FILE *dds = fopen("water.dds", "rb");
+ assert(dds);
+ char *ddsdata = (char*)malloc(DDS_SIZE);
+ assert(fread(ddsdata, 1, DDS_SIZE, dds) == DDS_SIZE);
+ fclose(dds);
+
+ glGenTextures( 1, &texture3 );
+ glBindTexture( GL_TEXTURE_2D, texture3 );
+
+ assert(!glGetError());
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 512, 64, 0, 512*64, ddsdata+128);
+ assert(!glGetError());
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ }
+
+ // Prepare and Render
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 4);
+
+ glBindTexture( GL_TEXTURE_2D, texture3 );
+ glDrawArrays(GL_QUADS, 4, 4);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ // Render the last item using oldschool glBegin etc
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(1500);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/s3tc_crunch.png b/tests/s3tc_crunch.png
new file mode 100644
index 00000000..383d4c5b
--- /dev/null
+++ b/tests/s3tc_crunch.png
Binary files differ
diff --git a/tests/scons/SConstruct b/tests/scons/SConstruct
new file mode 100644
index 00000000..facdff0a
--- /dev/null
+++ b/tests/scons/SConstruct
@@ -0,0 +1,5 @@
+env = Environment()
+env.Tool('emscripten')
+env.Append(CXXFLAGS='-std=c++11')
+env.Program('scons_integration', ['integration.cpp', 'other.c'])
+
diff --git a/tests/scons/integration.cpp b/tests/scons/integration.cpp
new file mode 100644
index 00000000..c3d2031a
--- /dev/null
+++ b/tests/scons/integration.cpp
@@ -0,0 +1,14 @@
+
+#include <string>
+#include <iostream>
+
+int main() {
+ std::string output("If you see this - the world is all right!");
+
+ auto func = [=](std::string text) -> int {
+ std::cout << text << std::endl;
+ return 5;
+ };
+
+ return func(output);
+}
diff --git a/tests/scons/other.c b/tests/scons/other.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/scons/other.c
diff --git a/tests/screenshot-fog-density.png b/tests/screenshot-fog-density.png
new file mode 100644
index 00000000..cd1f6f1b
--- /dev/null
+++ b/tests/screenshot-fog-density.png
Binary files differ
diff --git a/tests/screenshot-fog-exp2.png b/tests/screenshot-fog-exp2.png
new file mode 100644
index 00000000..cd5e6a63
--- /dev/null
+++ b/tests/screenshot-fog-exp2.png
Binary files differ
diff --git a/tests/screenshot-fog-linear.png b/tests/screenshot-fog-linear.png
new file mode 100644
index 00000000..57534566
--- /dev/null
+++ b/tests/screenshot-fog-linear.png
Binary files differ
diff --git a/tests/screenshot-fog-negative.png b/tests/screenshot-fog-negative.png
new file mode 100644
index 00000000..5b18a201
--- /dev/null
+++ b/tests/screenshot-fog-negative.png
Binary files differ
diff --git a/tests/screenshot-fog-simple.png b/tests/screenshot-fog-simple.png
new file mode 100644
index 00000000..527768fc
--- /dev/null
+++ b/tests/screenshot-fog-simple.png
Binary files differ
diff --git a/tests/screenshot-gray-purple.png b/tests/screenshot-gray-purple.png
new file mode 100644
index 00000000..514b29a1
--- /dev/null
+++ b/tests/screenshot-gray-purple.png
Binary files differ
diff --git a/tests/screenshot-gray.png b/tests/screenshot-gray.png
new file mode 100644
index 00000000..16e45a7a
--- /dev/null
+++ b/tests/screenshot-gray.png
Binary files differ
diff --git a/tests/screenshot.dds b/tests/screenshot.dds
new file mode 100644
index 00000000..de31ea11
--- /dev/null
+++ b/tests/screenshot.dds
Binary files differ
diff --git a/tests/screenshot.png b/tests/screenshot.png
new file mode 100644
index 00000000..44cf844a
--- /dev/null
+++ b/tests/screenshot.png
Binary files differ
diff --git a/tests/sdl_audio.c b/tests/sdl_audio.c
new file mode 100644
index 00000000..938df3c4
--- /dev/null
+++ b/tests/sdl_audio.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_mixer.h>
+#include <assert.h>
+#include <emscripten.h>
+
+Mix_Chunk *sound, *sound2;
+
+void play2();
+
+void play() {
+ int channel = Mix_PlayChannel(-1, sound, 1);
+ assert(channel == 0);
+
+ emscripten_run_script("setTimeout(Module['_play2'], 500)");
+}
+
+void done(int channel) {
+ assert(channel == 1);
+
+ int result = 1;
+ REPORT_RESULT();
+}
+
+void play2() {
+ Mix_ChannelFinished(done);
+
+ int channel2 = Mix_PlayChannel(-1, sound2, 1);
+ assert(channel2 == 1);
+}
+
+int main(int argc, char **argv) {
+ SDL_Init(SDL_INIT_AUDIO);
+
+ int ret = Mix_OpenAudio(0, 0, 0, 0); // we ignore all these..
+ assert(ret == 0);
+
+ sound = Mix_LoadWAV("sound.ogg");
+ assert(sound);
+ sound2 = Mix_LoadWAV("sound2.wav");
+ assert(sound);
+
+ play();
+ if (argc == 12121) play2(); // keep it alive
+
+ emscripten_run_script("element = document.createElement('input');"
+ "element.setAttribute('type', 'button');"
+ "element.setAttribute('value', 'replay!');"
+ "element.setAttribute('onclick', 'Module[\"_play\"]()');"
+ "document.body.appendChild(element);");
+
+ printf("you should hear two sounds. press the button to replay!\n");
+
+ return 0;
+}
+
diff --git a/tests/sdl_audio_quickload.c b/tests/sdl_audio_quickload.c
new file mode 100644
index 00000000..1525d048
--- /dev/null
+++ b/tests/sdl_audio_quickload.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_mixer.h>
+#include <assert.h>
+#include <limits.h>
+#include <emscripten.h>
+
+Mix_Chunk *sound;
+
+void play() {
+ int channel = Mix_PlayChannel(-1, sound, 1);
+ assert(channel == 0);
+
+ int result = 1;
+ REPORT_RESULT();
+}
+
+int main(int argc, char **argv) {
+ SDL_Init(SDL_INIT_AUDIO);
+
+ int ret = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
+ assert(ret == 0);
+
+ Uint16* buffer = (Uint16*)malloc(10*44100*sizeof(Uint16));
+ for (Uint32 i = 0; i < 10*44100; ++i) {
+ buffer[i] = (i * 5) % UINT32_MAX;
+ }
+ sound = Mix_QuickLoad_RAW((Uint8*) buffer, 10*44100*sizeof(Uint16));
+ assert(sound);
+
+ play();
+
+ emscripten_run_script("element = document.createElement('input');"
+ "element.setAttribute('type', 'button');"
+ "element.setAttribute('value', 'replay!');"
+ "element.setAttribute('onclick', 'Module[\"_play\"]()');"
+ "document.body.appendChild(element);");
+
+ printf("you should one sounds. press the button to replay!\n");
+
+ return 0;
+}
+
diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c
new file mode 100644
index 00000000..ab1340a8
--- /dev/null
+++ b/tests/sdl_canvas.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <emscripten.h>
+
+int main() {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ printf("Init: %d\n", TTF_Init());
+
+ TTF_Font *font = TTF_OpenFont("myfont.ttf", 40);
+ printf("Font: %p\n", font);
+
+ SDL_Color color = { 0xff, 0x99, 0x00, 0xff };
+
+ SDL_Surface *text = TTF_RenderText_Solid(font, "hello orange world", color);
+
+ SDL_Color color2 = { 0xbb, 0, 0xff, 0xff };
+ SDL_Surface *text2 = TTF_RenderText_Solid(font, "a second line, purple", color2);
+
+ // render
+ SDL_Rect dest = { 0, 50, 0, 0 };
+ SDL_BlitSurface (text, NULL, screen, NULL);
+ dest.y = 100;
+ SDL_BlitSurface (text2, NULL, screen, &dest);
+
+ // fill stuff
+ SDL_Rect rect = { 200, 200, 175, 125 };
+ SDL_FillRect(screen, &rect, 0x2222ffff);
+
+ SDL_Flip(screen);
+
+ SDL_LockSurface(screen);
+ int sum = 0;
+ for (int i = 0; i < screen->h; i++) {
+ sum += *((char*)screen->pixels + i*screen->w*4 + i*4 + 0);
+ }
+ printf("Sum: %d\n", sum);
+
+ printf("you should see two lines of text in different colors and a blue rectangle\n");
+
+ SDL_Quit();
+
+ int result = sum > 3000 && sum < 5000; // varies a little on different browsers, font differences?
+ REPORT_RESULT();
+
+ return 0;
+}
+
diff --git a/tests/sdl_canvas_palette.c b/tests/sdl_canvas_palette.c
new file mode 100644
index 00000000..316aa44a
--- /dev/null
+++ b/tests/sdl_canvas_palette.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <emscripten.h>
+
+int main() {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 400, 8, SDL_HWSURFACE | SDL_HWPALETTE);
+
+ //initialize sdl palette
+ //with red green and blue
+ //colors
+ SDL_Color pal[3];
+ pal[0].r = 255;
+ pal[0].g = 0;
+ pal[0].b = 0;
+ pal[0].unused = 0;
+
+ pal[1].r = 0;
+ pal[1].g = 255;
+ pal[1].b = 0;
+ pal[1].unused = 0;
+
+ pal[2].r = 0;
+ pal[2].g = 0;
+ pal[2].b = 255;
+ pal[2].unused = 0;
+
+ SDL_SetColors(screen, pal, 0, 3);
+
+ SDL_FillRect(screen, NULL, 0);
+
+ {
+ SDL_Rect rect = { 300, 0, 300, 200 };
+ SDL_FillRect(screen, &rect, 1);
+ }
+
+ {
+ SDL_Rect rect = { 0, 200, 600, 200 };
+ SDL_FillRect(screen, &rect, 2);
+ }
+
+ //changing green color
+ //to yellow
+ pal[1].r = 255;
+ SDL_SetColors(screen, pal, 1, 1);
+
+ {
+ SDL_Rect rect = { 300, 200, 300, 200 };
+ SDL_FillRect(screen, &rect, 1);
+ }
+
+ printf("you should see red, blue and yellow rectangles\n");
+
+ SDL_Quit();
+
+ return 0;
+}
+
diff --git a/tests/sdl_canvas_palette.png b/tests/sdl_canvas_palette.png
new file mode 100644
index 00000000..a52844b6
--- /dev/null
+++ b/tests/sdl_canvas_palette.png
Binary files differ
diff --git a/tests/sdl_canvas_palette_2.c b/tests/sdl_canvas_palette_2.c
new file mode 100644
index 00000000..db051b2b
--- /dev/null
+++ b/tests/sdl_canvas_palette_2.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <emscripten.h>
+
+static const int COLOR_COUNT = 32;
+
+static SDL_Surface *screen;
+static SDL_Color pal[COLOR_COUNT +1];
+
+void initializePalette() {
+ //initialize sdl palette
+ //with red green and blue
+ //colors
+ pal[0].r = 0;
+ pal[0].g = 0;
+ pal[0].b = 0;
+ pal[0].unused = 0;
+
+ for (int i=1; i< 1 + COLOR_COUNT; i++) {
+ pal[i].r = 255 / COLOR_COUNT * i;
+ pal[i].g = 0;
+ pal[i].b = 0;
+ pal[i].unused = 0;
+ }
+
+ SDL_SetColors(screen, pal, 0, 1 + COLOR_COUNT);
+}
+
+void animatePalette() {
+ SDL_Color temporary;
+ temporary = pal[1];
+ for (int i=2; i< 1 + COLOR_COUNT; i++) {
+ pal[i-1] = pal[i];
+ }
+ pal[COLOR_COUNT] = temporary;
+
+ SDL_SetColors(screen, pal, 1, COLOR_COUNT);
+
+ //refreshing
+ SDL_LockSurface(screen);
+ SDL_UnlockSurface(screen);
+
+ printf("yet another cycle\n");
+}
+
+int main() {
+ SDL_Init(SDL_INIT_VIDEO);
+ screen = SDL_SetVideoMode(600, 400, 8, SDL_HWSURFACE | SDL_HWPALETTE);
+
+ //test empty pallete
+ SDL_LockSurface(screen);
+ SDL_UnlockSurface(screen);
+
+ initializePalette();
+
+ //palette is red yellow blue
+ SDL_LockSurface(screen);
+ int size = screen->h * screen->pitch;
+ char *color = screen->pixels;
+ int divider = size / COLOR_COUNT;
+ int i = 0;
+ while (i < size) {
+ *color = 1 + (i / divider); //red
+ color++;
+ i++;
+ }
+ SDL_UnlockSurface(screen);
+
+ //Animation
+ printf("you should see red gradient animation\n");
+ emscripten_set_main_loop(animatePalette, 0);
+
+ SDL_Quit();
+
+ return 0;
+}
+
diff --git a/tests/sdl_fog_density.c b/tests/sdl_fog_density.c
new file mode 100644
index 00000000..95773419
--- /dev/null
+++ b/tests/sdl_fog_density.c
@@ -0,0 +1,183 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1000, 1000 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glEnable(GL_FOG);
+ GLfloat fogColor[] = { 1.0, 0.5, 0.5, 0.05 };
+ glFogfv(GL_FOG_COLOR, fogColor);
+ glFogf(GL_FOG_DENSITY, 0.2);
+
+ assert(glIsEnabled(GL_FOG));
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 10 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 10 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 10 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 10 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 5 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 6 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 7 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 8 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 5 );
+ glVertex3f( 300, 410, 50 );
+ glVertex3f( 300, 480, 100 );
+ glVertex3f( 10, 470, 5 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 10 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 10 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 10 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 10 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(30000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_fog_exp2.c b/tests/sdl_fog_exp2.c
new file mode 100644
index 00000000..a09a5e3d
--- /dev/null
+++ b/tests/sdl_fog_exp2.c
@@ -0,0 +1,184 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1000, 1000 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glEnable(GL_FOG);
+ GLfloat fogColor[] = { 1.0, 0.5, 0.5, 0.05 };
+ glFogfv(GL_FOG_COLOR, fogColor);
+ glFogf(GL_FOG_DENSITY, 0.2);
+ glFogi(GL_FOG_MODE, GL_EXP2);
+
+ assert(glIsEnabled(GL_FOG));
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 10 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 10 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 10 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 10 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 5 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 6 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 7 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 8 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 5 );
+ glVertex3f( 300, 410, 50 );
+ glVertex3f( 300, 480, 100 );
+ glVertex3f( 10, 470, 5 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 10 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 10 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 10 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 10 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(30000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_fog_linear.c b/tests/sdl_fog_linear.c
new file mode 100644
index 00000000..8fc18b7c
--- /dev/null
+++ b/tests/sdl_fog_linear.c
@@ -0,0 +1,185 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1000, 1000 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glEnable(GL_FOG);
+ GLfloat fogColor[] = { 1.0, 0.5, 0.5, 0.05 };
+ glFogfv(GL_FOG_COLOR, fogColor);
+ glFogi(GL_FOG_START, 8);
+ glFogi(GL_FOG_END, 13);
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+
+ assert(glIsEnabled(GL_FOG));
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 10 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 10 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 10 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 10 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 5 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 6 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 7 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 8 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 5 );
+ glVertex3f( 300, 410, 50 );
+ glVertex3f( 300, 480, 100 );
+ glVertex3f( 10, 470, 5 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 10 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 10 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 10 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 10 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(30000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_fog_negative.c b/tests/sdl_fog_negative.c
new file mode 100644
index 00000000..2d589a47
--- /dev/null
+++ b/tests/sdl_fog_negative.c
@@ -0,0 +1,182 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1000, 1000 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glEnable(GL_FOG);
+ GLfloat fogColor[] = { 1.0, 0.5, 0.5, 0.05 };
+ glFogfv(GL_FOG_COLOR, fogColor);
+
+ assert(glIsEnabled(GL_FOG));
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, -1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, -1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, -1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, -1 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, -5 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, -6 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, -7 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, -8 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, -1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, -1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, -1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, -1 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, -5 );
+ glVertex3f( 300, 410, -50 );
+ glVertex3f( 300, 480, -100 );
+ glVertex3f( 10, 470, -5 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, -10 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, -10 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, -10 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, -10 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(30000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_fog_simple.c b/tests/sdl_fog_simple.c
new file mode 100644
index 00000000..be023593
--- /dev/null
+++ b/tests/sdl_fog_simple.c
@@ -0,0 +1,182 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1000, 1000 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glEnable(GL_FOG);
+ GLfloat fogColor[] = { 1.0, 0.5, 0.5, 0.05 };
+ glFogfv(GL_FOG_COLOR, fogColor);
+
+ assert(glIsEnabled(GL_FOG));
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 10 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 10 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 10 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 10 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 5 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 6 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 7 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 8 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 1 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 1 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 1 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 5 );
+ glVertex3f( 300, 410, 50 );
+ glVertex3f( 300, 480, 100 );
+ glVertex3f( 10, 470, 5 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 10 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 10 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 10 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 10 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(30000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_gl_read.c b/tests/sdl_gl_read.c
new file mode 100644
index 00000000..552eb8c0
--- /dev/null
+++ b/tests/sdl_gl_read.c
@@ -0,0 +1,155 @@
+// Built from glbook/hello triange and sdl_ogl, see details there
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+GLuint programObject;
+int width = 512;
+int height = 256;
+
+GLuint LoadShader ( GLenum type, const char *shaderSrc )
+{
+ GLuint shader;
+ GLint compiled;
+
+ shader = glCreateShader ( type );
+ if ( shader == 0 )
+ return 0;
+
+ glShaderSource ( shader, 1, &shaderSrc, NULL );
+ glCompileShader ( shader );
+ glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
+ if ( !compiled )
+ {
+ GLint infoLen = 0;
+ glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+ glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );
+ printf ( "Error compiling shader:\n%s\n", infoLog );
+ free ( infoLog );
+ }
+ glDeleteShader ( shader );
+ return 0;
+ }
+ return shader;
+}
+
+int Init ()
+{
+ GLbyte vShaderStr[] =
+ "attribute vec4 vPosition; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = vPosition; \n"
+ "} \n";
+
+ GLbyte fShaderStr[] =
+ "precision mediump float;\n"\
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4 ( 0.0, 0.0, 1.0, 1.0 );\n"
+ "} \n";
+
+ GLuint vertexShader;
+ GLuint fragmentShader;
+ GLint linked;
+
+ vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
+ fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );
+
+ programObject = glCreateProgram ( );
+ if ( programObject == 0 )
+ return 0;
+
+ glAttachShader ( programObject, vertexShader );
+ glAttachShader ( programObject, fragmentShader );
+ glBindAttribLocation ( programObject, 0, "vPosition" );
+ glLinkProgram ( programObject );
+ glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
+ if ( !linked )
+ {
+ GLint infoLen = 0;
+ glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
+ if ( infoLen > 1 )
+ {
+ char* infoLog = malloc (sizeof(char) * infoLen );
+ glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
+ printf ( "Error linking program:\n%s\n", infoLog );
+ free ( infoLog );
+ }
+ glDeleteProgram ( programObject );
+ return GL_FALSE;
+ }
+
+ glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ return GL_TRUE;
+}
+
+///
+// Draw a triangle using the shader pair created in Init()
+//
+void Draw ()
+{
+ GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f };
+
+ // No clientside arrays, so do this in a webgl-friendly manner
+ GLuint vertexPosObject;
+ glGenBuffers(1, &vertexPosObject);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
+ glBufferData(GL_ARRAY_BUFFER, 9*4, vVertices, GL_STATIC_DRAW);
+
+ glViewport ( 0, 0, width, height );
+ glClear ( GL_COLOR_BUFFER_BIT );
+ glUseProgram ( programObject );
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
+ glVertexAttribPointer(0 /* ? */, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(0);
+
+ glDrawArrays ( GL_TRIANGLES, 0, 3 );
+}
+
+void Verify() {
+ unsigned char *data = malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ // Should see some blue, and nothing else
+ int seen = 0;
+ int ok = 1;
+ for (int x = 0; x < width*height; x++) {
+ seen = seen || data[x*4+2] != 0;
+ ok = ok && (data[x*4+0] == 0);
+ ok = ok && (data[x*4+1] == 0);
+ }
+ int result = seen && ok;
+ REPORT_RESULT();
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ screen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
+ if (!screen) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ Init();
+ Draw();
+ Verify();
+
+ return 0;
+}
+
diff --git a/tests/sdl_image.c b/tests/sdl_image.c
index 3f55374f..9d8c36f2 100644
--- a/tests/sdl_image.c
+++ b/tests/sdl_image.c
@@ -1,31 +1,43 @@
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
+#include <assert.h>
#include <emscripten.h>
-int main() {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_SWSURFACE);
-
- if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen);
-
- SDL_Surface *image = IMG_Load("screenshot.jpg");
+int testImage(SDL_Surface* screen, const char* fileName) {
+ SDL_Surface *image = IMG_Load(fileName);
if (!image)
{
printf("IMG_Load: %s\n", IMG_GetError());
- return 1;
+ return 0;
}
+ assert(image->format->BitsPerPixel == 32);
+ assert(image->format->BytesPerPixel == 4);
+ assert(image->pitch == 4*image->w);
+ int result = image->w;
+
SDL_BlitSurface (image, NULL, screen, NULL);
SDL_FreeSurface (image);
- if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
- SDL_Flip(screen);
+ return result;
+}
+
+int main() {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_SWSURFACE);
+
+ int result = 0;
+ result = testImage(screen, "screenshot.jpg"); // relative path
+ assert(result != 0);
+ result |= testImage(screen, "/screenshot.jpg"); // absolute path
+ assert(result != 0);
+
+ SDL_Flip(screen);
printf("you should see an image.\n");
SDL_Quit();
- int result = image->w;
REPORT_RESULT();
return 0;
diff --git a/tests/sdl_key.c b/tests/sdl_key.c
new file mode 100644
index 00000000..19b0a3d6
--- /dev/null
+++ b/tests/sdl_key.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <emscripten.h>
+
+int result = 1;
+
+void one() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch(event.type) {
+ case SDL_KEYDOWN:
+ break;
+ case SDL_KEYUP:
+ switch (event.key.keysym.sym) {
+ case SDLK_RIGHT: printf("right\n"); result *= 2; break;
+ case SDLK_LEFT: printf("left\n"); result *= 3; break;
+ case SDLK_DOWN: printf("down\n"); result *= 5; break;
+ case SDLK_UP: printf("up\n"); result *= 7; break;
+ case SDLK_SPACE: printf("space\n"); result *= 11; break;
+ case SDLK_a: printf("a\n"); result *= 13; break;
+ default: {
+ if (event.key.keysym.scancode == SDL_SCANCODE_B) {
+ printf("b scancode\n"); result *= 17; break;
+ }
+ printf("unknown key: sym %d scancode %d\n", event.key.keysym.sym, event.key.keysym.scancode);
+ REPORT_RESULT();
+ emscripten_run_script("throw 'done'"); // comment this out to leave event handling active. Use the following to log DOM keys:
+ // addEventListener('keyup', function(event) { console.log(event.keyCode) }, true)
+ }
+ }
+ break;
+ default: /* Report an unhandled event */
+ printf("I don't know what this event is!\n");
+ }
+ }
+}
+
+int main(int argc, char **argv) {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ emscripten_run_script("simulateKeyEvent(38)"); // up
+ emscripten_run_script("simulateKeyEvent(40)"); // down
+ emscripten_run_script("simulateKeyEvent(37)"); // left
+ emscripten_run_script("simulateKeyEvent(39)"); // right
+ emscripten_run_script("simulateKeyEvent(32)"); // space
+ emscripten_run_script("simulateKeyEvent(65)"); // a
+ emscripten_run_script("simulateKeyEvent(66)"); // b
+ emscripten_run_script("simulateKeyEvent(100)"); // trigger the end
+
+ if (argc == 1337) one(); // keep it alive
+
+ return 0;
+}
+
diff --git a/tests/sdl_maprgba.c b/tests/sdl_maprgba.c
new file mode 100644
index 00000000..c87c7524
--- /dev/null
+++ b/tests/sdl_maprgba.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <emscripten.h>
+
+int main() {
+ Uint32 c;
+ SDL_Rect rect = {0,0,300,450};
+
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ c = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00); // OPAQUE RED
+ SDL_FillRect(screen, &rect, c);
+ rect.x = 300;
+ c = SDL_MapRGB(screen->format, 0x7f, 0x7f, 0x00); // OPAQUE MUSTARD
+ SDL_FillRect(screen, &rect, c);
+ rect.x = 150;
+ rect.y = 112;
+ rect.w = 300;
+ rect.h = 225;
+ c = SDL_MapRGBA(screen->format, 0xff, 0xff, 0xff, 0xff); // OPAQUE WHITE
+ SDL_FillRect(screen, &rect, c);
+ c = SDL_MapRGBA(screen->format, 0x00, 0x00, 0x00, 0x00); // TRANSPARENT BLACK
+ SDL_FillRect(screen, &rect, c);
+ SDL_UpdateRect(screen, 0, 0, 600, 450);
+
+ printf("The left half should be red and the right half mustard.\n");
+ printf("There should be a white rectangle in the center.\n");
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_maprgba.png b/tests/sdl_maprgba.png
new file mode 100644
index 00000000..4f64c7cd
--- /dev/null
+++ b/tests/sdl_maprgba.png
Binary files differ
diff --git a/tests/sdl_mouse.c b/tests/sdl_mouse.c
new file mode 100644
index 00000000..0c10198a
--- /dev/null
+++ b/tests/sdl_mouse.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_ttf.h>
+#include <assert.h>
+#include <emscripten.h>
+
+int result = 1;
+
+void one() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch(event.type) {
+ case SDL_MOUSEMOTION: {
+ SDL_MouseMotionEvent *m = (SDL_MouseMotionEvent*)&event;
+ assert(m->state == 0);
+ int x, y;
+ SDL_GetMouseState(&x, &y);
+ assert(x == m->x && y == m->y);
+ printf("motion: %d,%d %d,%d\n", m->x, m->y, m->xrel, m->yrel);
+ result += 2 * (m->x + m->y + m->xrel + m->yrel);
+ break;
+ }
+ case SDL_MOUSEBUTTONDOWN: {
+ SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event;
+ if (m->button == 2) {
+ REPORT_RESULT();
+ emscripten_run_script("throw 'done'");
+ }
+ printf("button down: %d,%d %d,%d\n", m->button, m->state, m->x, m->y);
+ result += 3 * (m->button + m->state + m->x + m->y);
+ break;
+ }
+ case SDL_MOUSEBUTTONUP: {
+ SDL_MouseButtonEvent *m = (SDL_MouseButtonEvent*)&event;
+ printf("button up: %d,%d %d,%d\n", m->button, m->state, m->x, m->y);
+ result += 5 * (m->button + m->state + m->x + m->y);
+ // Remove another click we want to ignore
+ assert(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONDOWN) == 1);
+ assert(SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEBUTTONUP, SDL_MOUSEBUTTONUP) == 1);
+ break;
+ }
+ }
+ }
+}
+
+void main_2();
+
+int main() {
+ SDL_Init(SDL_INIT_VIDEO);
+ SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE);
+
+ SDL_Rect rect = { 0, 0, 600, 450 };
+ SDL_FillRect(screen, &rect, 0x2244ffff);
+
+ emscripten_async_call(main_2, 3000); // avoid startup delays and intermittent errors
+
+ return 0;
+}
+
+void main_2() {
+ emscripten_run_script("window.simulateMouseEvent(10, 20, -1)"); // move from 0,0 to 10,20
+ emscripten_run_script("window.simulateMouseEvent(10, 20, 0)"); // click
+ emscripten_run_script("window.simulateMouseEvent(10, 20, 0)"); // click some more, but this one should be ignored through PeepEvent
+ emscripten_run_script("window.simulateMouseEvent(30, 77, -1)"); // move some more
+ emscripten_run_script("window.simulateMouseEvent(30, 77, 1)"); // trigger the end
+
+ emscripten_set_main_loop(one, 0);
+}
+
diff --git a/tests/sdl_ogl.c b/tests/sdl_ogl.c
new file mode 100644
index 00000000..6b6a5b4a
--- /dev/null
+++ b/tests/sdl_ogl.c
@@ -0,0 +1,175 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1, 1 );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 0 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 0 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 0 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 0 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 0 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 0 );
+ glVertex3f( 300, 410, 0 );
+ glVertex3f( 300, 480, 0 );
+ glVertex3f( 10, 470, 0 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 0 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 0 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 0 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 0 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_ogl_defaultMatrixMode.c b/tests/sdl_ogl_defaultMatrixMode.c
new file mode 100644
index 00000000..0da0a326
--- /dev/null
+++ b/tests/sdl_ogl_defaultMatrixMode.c
@@ -0,0 +1,176 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ // GL_MODELVIEW should be the default...
+ //glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix(); // just for testing
+ glLoadIdentity();
+
+ glOrtho( 0, 640, 480, 0, -1, 1 );
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ glBegin( GL_QUADS );
+ glTexCoord2i( 0, 0 ); glVertex3f( 10, 10, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 10, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 128, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 10, 128, 0 );
+
+ glTexCoord2f( 0, 0.5 ); glVertex3f( 410, 10, 0 );
+ glTexCoord2f( 1, 0.5 ); glVertex3f( 600, 10, 0 );
+ glTexCoord2f( 1, 1 ); glVertex3f( 630, 200, 0 );
+ glTexCoord2f( 0.5, 1 ); glVertex3f( 310, 250, 0 );
+ glEnd();
+
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glEnd();
+
+#if !EMSCRIPTEN
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ glColor3ub(90, 255, 255);
+ glBegin( GL_QUADS );
+ glVertex3f( 10, 410, 0 );
+ glVertex3f( 300, 410, 0 );
+ glVertex3f( 300, 480, 0 );
+ glVertex3f( 10, 470, 0 );
+ glEnd();
+
+ glBegin( GL_QUADS );
+ glColor3f(1.0, 0, 1.0); glVertex3f( 410, 410, 0 );
+ glColor3f(0, 1.0, 0); glVertex3f( 600, 410, 0 );
+ glColor3f(0, 0, 1.0); glVertex3f( 600, 480, 0 );
+ glColor3f(1.0, 1.0, 1.0); glVertex3f( 410, 470, 0 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c
new file mode 100644
index 00000000..949aaa44
--- /dev/null
+++ b/tests/sdl_ogl_p.c
@@ -0,0 +1,166 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 8);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ // Render the last item using oldschool glBegin etc
+ glBegin( GL_TRIANGLE_STRIP );
+ glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
+ glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
+ glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
+ glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/sdlglshader.c b/tests/sdlglshader.c
new file mode 100644
index 00000000..a096ef20
--- /dev/null
+++ b/tests/sdlglshader.c
@@ -0,0 +1,153 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_opengl.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+// GL_ARB_shading_language_100, GL_ARB_shader_objects, GL_ARB_fragment_shader, GL_ARB_vertex_shader
+PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject_ = NULL;
+PFNGLDELETEOBJECTARBPROC glDeleteObject_ = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject_ = NULL;
+PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject_ = NULL;
+PFNGLSHADERSOURCEARBPROC glShaderSource_ = NULL;
+PFNGLCOMPILESHADERARBPROC glCompileShader_ = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv_ = NULL;
+PFNGLATTACHOBJECTARBPROC glAttachObject_ = NULL;
+PFNGLGETINFOLOGARBPROC glGetInfoLog_ = NULL;
+PFNGLLINKPROGRAMARBPROC glLinkProgram_ = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation_ = NULL;
+PFNGLUNIFORM1FARBPROC glUniform1f_ = NULL;
+PFNGLUNIFORM2FARBPROC glUniform2f_ = NULL;
+PFNGLUNIFORM3FARBPROC glUniform3f_ = NULL;
+PFNGLUNIFORM4FARBPROC glUniform4f_ = NULL;
+PFNGLUNIFORM1FVARBPROC glUniform1fv_ = NULL;
+PFNGLUNIFORM2FVARBPROC glUniform2fv_ = NULL;
+PFNGLUNIFORM3FVARBPROC glUniform3fv_ = NULL;
+PFNGLUNIFORM4FVARBPROC glUniform4fv_ = NULL;
+PFNGLUNIFORM1IARBPROC glUniform1i_ = NULL;
+PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocation_ = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniform_ = NULL;
+
+void initARB() {
+ glCreateProgramObject_ = (PFNGLCREATEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glCreateProgramObjectARB");
+ glDeleteObject_ = (PFNGLDELETEOBJECTARBPROC) SDL_GL_GetProcAddress("glDeleteObjectARB");
+ glUseProgramObject_ = (PFNGLUSEPROGRAMOBJECTARBPROC) SDL_GL_GetProcAddress("glUseProgramObjectARB");
+ glCreateShaderObject_ = (PFNGLCREATESHADEROBJECTARBPROC) SDL_GL_GetProcAddress("glCreateShaderObjectARB");
+ glShaderSource_ = (PFNGLSHADERSOURCEARBPROC) SDL_GL_GetProcAddress("glShaderSourceARB");
+ glCompileShader_ = (PFNGLCOMPILESHADERARBPROC) SDL_GL_GetProcAddress("glCompileShaderARB");
+ glGetObjectParameteriv_ = (PFNGLGETOBJECTPARAMETERIVARBPROC) SDL_GL_GetProcAddress("glGetObjectParameterivARB");
+ glAttachObject_ = (PFNGLATTACHOBJECTARBPROC) SDL_GL_GetProcAddress("glAttachObjectARB");
+ glGetInfoLog_ = (PFNGLGETINFOLOGARBPROC) SDL_GL_GetProcAddress("glGetInfoLogARB");
+ glLinkProgram_ = (PFNGLLINKPROGRAMARBPROC) SDL_GL_GetProcAddress("glLinkProgramARB");
+ glGetUniformLocation_ = (PFNGLGETUNIFORMLOCATIONARBPROC) SDL_GL_GetProcAddress("glGetUniformLocationARB");
+ glUniform1f_ = (PFNGLUNIFORM1FARBPROC) SDL_GL_GetProcAddress("glUniform1fARB");
+ glUniform2f_ = (PFNGLUNIFORM2FARBPROC) SDL_GL_GetProcAddress("glUniform2fARB");
+ glUniform3f_ = (PFNGLUNIFORM3FARBPROC) SDL_GL_GetProcAddress("glUniform3fARB");
+ glUniform4f_ = (PFNGLUNIFORM4FARBPROC) SDL_GL_GetProcAddress("glUniform4fARB");
+ glUniform1fv_ = (PFNGLUNIFORM1FVARBPROC) SDL_GL_GetProcAddress("glUniform1fvARB");
+ glUniform2fv_ = (PFNGLUNIFORM2FVARBPROC) SDL_GL_GetProcAddress("glUniform2fvARB");
+ glUniform3fv_ = (PFNGLUNIFORM3FVARBPROC) SDL_GL_GetProcAddress("glUniform3fvARB");
+ glUniform4fv_ = (PFNGLUNIFORM4FVARBPROC) SDL_GL_GetProcAddress("glUniform4fvARB");
+ glUniform1i_ = (PFNGLUNIFORM1IARBPROC) SDL_GL_GetProcAddress("glUniform1iARB");
+ glBindAttribLocation_ = (PFNGLBINDATTRIBLOCATIONARBPROC) SDL_GL_GetProcAddress("glBindAttribLocationARB");
+ glGetActiveUniform_ = (PFNGLGETACTIVEUNIFORMARBPROC) SDL_GL_GetProcAddress("glGetActiveUniformARB");
+}
+
+void setShaders() {
+ GLuint v, f, p;
+ GLint ok;
+
+ const char *vv = "void main() \n"
+ "{ \n"
+ " gl_Position = ftransform() + vec4(0.1, -0.25, 0, 0); \n"
+ "}";
+ const char *ff = "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(gl_FragCoord.y/480.0, gl_FragCoord.x/640.0, 0.66, 1.0); \n"
+ "}";
+
+ v = glCreateShaderObject_(GL_VERTEX_SHADER);
+ f = glCreateShaderObject_(GL_FRAGMENT_SHADER);
+
+ glShaderSource_(v, 1, &vv,NULL);
+ glShaderSource_(f, 1, &ff,NULL);
+
+ glCompileShader_(v);
+ glGetObjectParameteriv_(v, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
+ assert(ok);
+
+ glCompileShader_(f);
+ glGetObjectParameteriv_(f, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
+ assert(ok);
+
+ p = glCreateProgramObject_();
+ glAttachObject_(p,f);
+ glAttachObject_(p,v);
+
+ glLinkProgram_(p);
+ glGetObjectParameteriv_(p, GL_OBJECT_LINK_STATUS_ARB, &ok);
+ assert(ok);
+
+ glUseProgramObject_(p);
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ assert(SDL_Init(SDL_INIT_VIDEO) == 0);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL );
+ assert(screen);
+
+ glClearColor(0, 0, 0, 0);
+ glViewport(0, 0, 640, 480);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, 640, 480, 0, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ initARB();
+ setShaders();
+
+ glColor3f(0, 1, 1); // is overridden by the shader, useful for debugging native builds
+ glBegin( GL_TRIANGLES );
+ glTexCoord2i(0, 0); glVertex3f( 10, 10, 0);
+ glTexCoord2i(1, 0); glVertex3f( 300, 10, 0);
+ glTexCoord2i(1, 1); glVertex3f( 300, 328, 0);
+ glEnd();
+
+ glColor3f(1, 1, 0); // is overridden by the shader, useful for debugging native builds
+ glBegin( GL_TRIANGLES );
+ glTexCoord2f(0, 0.5); glVertex3f(410, 10, 0);
+ glTexCoord2f(1, 0.5); glVertex3f(600, 10, 0);
+ glTexCoord2f(1, 1 ); glVertex3f(630, 400, 0);
+ glEnd();
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ SDL_Delay(3000);
+#endif
+
+ SDL_Quit();
+ return 0;
+}
+
diff --git a/tests/sdlglshader.png b/tests/sdlglshader.png
new file mode 100644
index 00000000..5e52a617
--- /dev/null
+++ b/tests/sdlglshader.png
Binary files differ
diff --git a/tests/sha1.c b/tests/sha1.c
new file mode 100644
index 00000000..034939b5
--- /dev/null
+++ b/tests/sha1.c
@@ -0,0 +1,241 @@
+
+/* from valgrind tests */
+
+/* ================ sha1.c ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h> /* for u_int*_t */
+
+/* ================ sha1.h ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+typedef struct {
+ u_int32_t state[5];
+ u_int32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+/* ================ end of sha1.h ================ */
+#include <endian.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
+{
+u_int32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ u_int32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1]; /* use array to appear as a pointer */
+ memcpy(block, buffer, 64);
+#else
+ /* The following had better never be used because it causes the
+ * pointer-to-const buffer to be cast into a pointer to non-const.
+ * And the result is written through. I threw a "const" in, hoping
+ * this will cause a diagnostic.
+ */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+ memset(block, '\0', sizeof(block));
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len)
+{
+u_int32_t i;
+u_int32_t j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1]++;
+ context->count[1] += (len>>29);
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0 /* untested "improvement" by DHR */
+ /* Convert context->count to a sequence of bytes
+ * in finalcount. Second element first, but
+ * big-endian order within element.
+ * But we do it all backwards.
+ */
+ unsigned char *fcp = &finalcount[8];
+
+ for (i = 0; i < 2; i++)
+ {
+ u_int32_t t = context->count[i];
+ int j;
+
+ for (j = 0; j < 4; t >>= 8, j++)
+ *--fcp = (unsigned char) t;
+ }
+#else
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+#endif
+ c = 0200;
+ SHA1Update(context, &c, 1);
+ while ((context->count[0] & 504) != 448) {
+ c = 0000;
+ SHA1Update(context, &c, 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ memset(context, '\0', sizeof(*context));
+ memset(&finalcount, '\0', sizeof(finalcount));
+}
+/* ================ end of sha1.c ================ */
+
+#define BUFSIZE 4096
+
+int
+main(int argc, char **argv)
+{
+ SHA1_CTX ctx;
+ unsigned char hash[20], buf[BUFSIZE];
+ int i;
+
+ for(i=0;i<BUFSIZE;i++)
+ buf[i] = i;
+
+ SHA1Init(&ctx);
+ for(i=0;i<1000;i++)
+ SHA1Update(&ctx, buf, BUFSIZE);
+ SHA1Final(hash, &ctx);
+
+ printf("SHA1=");
+ for(i=0;i<20;i++)
+ printf("%02x", hash[i]);
+ printf("\n");
+ return 0;
+}
+
diff --git a/tests/ship.dds b/tests/ship.dds
new file mode 100644
index 00000000..dd7b04e9
--- /dev/null
+++ b/tests/ship.dds
Binary files differ
diff --git a/tests/sounds/LICENSE.txt b/tests/sounds/LICENSE.txt
new file mode 100644
index 00000000..1525d517
--- /dev/null
+++ b/tests/sounds/LICENSE.txt
@@ -0,0 +1,19 @@
+The files in this directory are Copyright (C) 2009 Wildfire Games.
+
+These files are licensed under the Creative Commons Attribution-Share Alike 3.0
+(CC-by-sa) license, available at http://creativecommons.org/licenses/by-sa/3.0/
+
+Briefly, this means:
+
+* You may use, modify and distribute these files, for commercial and
+ non-commercial purposes.
+
+* If you distribute one of these files, you must include attribution (e.g.
+ in the credits screen of a game or a video, or in a text file accompanying
+ the files). The attribution must include:
+ * A link to http://creativecommons.org/licenses/by-sa/3.0/
+ * The name "Wildfire Games" as the original author
+ * A link to http://www.wildfiregames.com/
+
+* If you distribute one of these files, you must release it (and any
+ modifications you have made to it) under the CC-by-sa license. \ No newline at end of file
diff --git a/tests/sounds/alarmcreatemiltaryfoot_1.wav b/tests/sounds/alarmcreatemiltaryfoot_1.wav
new file mode 100644
index 00000000..2de6314a
--- /dev/null
+++ b/tests/sounds/alarmcreatemiltaryfoot_1.wav
Binary files differ
diff --git a/tests/sounds/alarmvictory_1.ogg b/tests/sounds/alarmvictory_1.ogg
new file mode 100644
index 00000000..cadb1539
--- /dev/null
+++ b/tests/sounds/alarmvictory_1.ogg
Binary files differ
diff --git a/tests/sqlite/benchmark.c b/tests/sqlite/benchmark.c
index c1385525..802abab1 100644
--- a/tests/sqlite/benchmark.c
+++ b/tests/sqlite/benchmark.c
@@ -21,6 +21,7 @@ int test(){
"INSERT INTO t2 VALUES(1,13153,'thirteen thousand one hundred fifty three');",
"INSERT INTO t2 VALUES(1,987,'some other number');",
"SELECT count(*) FROM t2;",
+ "SELECT datetime('2012-04-16 12:35:57', '+1 days');",
"SELECT a, b, c FROM t2;",
NULL
};
diff --git a/tests/sqlite/benchmark.txt b/tests/sqlite/benchmark.txt
index 472221df..622493b3 100644
--- a/tests/sqlite/benchmark.txt
+++ b/tests/sqlite/benchmark.txt
@@ -1,5 +1,7 @@
count(*) = 2
+datetime('2012-04-16 12:35:57', '+1 days') = 2012-04-17 12:35:57
+
a = 1
b = 13153
c = thirteen thousand one hundred fifty three
diff --git a/tests/tex_nonbyte.c b/tests/tex_nonbyte.c
new file mode 100644
index 00000000..8f2ec162
--- /dev/null
+++ b/tests/tex_nonbyte.c
@@ -0,0 +1,206 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void shaders() {
+#if USE_GLEW
+ glewInit();
+#endif
+
+ GLint ok;
+
+ const char *vertexShader = "void main(void) \n"
+ "{ \n"
+ " gl_Position = ftransform(); \n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
+ " gl_FrontColor = gl_Color; \n"
+ "} \n";
+ const char *fragmentShader = "uniform sampler2D tex0; \n"
+ "void main(void) \n"
+ "{ \n"
+ " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n"
+ "} \n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+
+ glUseProgram(program);
+
+ {
+ // Also, check getting the error log
+ const char *fakeVertexShader = "atbute ve4 blarg; ### AAA\n";
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &fakeVertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(!ok);
+ GLint infoLen = 0;
+ glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &infoLen);
+ assert(infoLen > 1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ int w = 256, h = 256;
+ GLushort *pixels = (GLushort*)malloc(w*h*2);
+ for (int x = 0; x < w; x++)
+ for (int y = 0; y < h; y++)
+ pixels[w*y + x] = ((x*32)/w) | ((((w-x)*(h-y)*64)/(w*h)) << 5) | (((y*32)/h) << 11);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels );
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ shaders();
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250,
+ 0, 0, 100, 300,
+ 1, 0, 300, 300,
+ 1, 1, 300, 400,
+ 0, 1, 100, 400 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 12);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
+
diff --git a/tests/tex_nonbyte.png b/tests/tex_nonbyte.png
new file mode 100644
index 00000000..8e542417
--- /dev/null
+++ b/tests/tex_nonbyte.png
Binary files differ
diff --git a/tests/water.dds b/tests/water.dds
new file mode 100644
index 00000000..2a78a859
--- /dev/null
+++ b/tests/water.dds
Binary files differ
diff --git a/third_party/lzma.js/doit.sh b/third_party/lzma.js/doit.sh
index a8071534..1f530651 100755
--- a/third_party/lzma.js/doit.sh
+++ b/third_party/lzma.js/doit.sh
@@ -1,5 +1,7 @@
cd lzip
+export CXX=`../../../em-config LLVM_ROOT`/clang++
+
echo "native"
make clean
DECODER_ONLY=0 make lzip -j 4 # native build
@@ -9,25 +11,25 @@ exit # just build natively, that's it
echo "bitcode full (encoder+decoder)"
make clean
-DECODER_ONLY=0 ~/Dev/emscripten/emmake make lzip -j 4
+DECODER_ONLY=0 ../../../emmake make lzip -j 4
mv lzip lzip-full.bc
echo "bitcode decoder only"
make clean
-DECODER_ONLY=1 ~/Dev/emscripten/emmake make lzip -j 4
+DECODER_ONLY=1 ../../../emmake make lzip -j 4
mv lzip lzip-decoder.bc
cd ..
echo "javascript full"
-~/Dev/emscripten/emcc -O2 lzip/lzip-full.bc -o lzma-full.raw.js
+../../emcc -O2 lzip/lzip-full.bc -o lzma-full.raw.js
# -s INLINING_LIMIT=0
cat pre.js > lzma-full.js
cat lzma-full.raw.js >> lzma-full.js
cat post.js >> lzma-full.js
echo "javascript decoder"
-~/Dev/emscripten/emcc -O2 lzip/lzip-decoder.bc -o lzma-decoder.raw.js
+../../emcc -O2 lzip/lzip-decoder.bc -o lzma-decoder.raw.js
# -s INLINING_LIMIT=0
cat pre.js > lzma-decoder.js
cat lzma-decoder.raw.js >> lzma-decoder.js
diff --git a/tools/autodebugger.py b/tools/autodebugger.py
index 65ddc641..3631548c 100644
--- a/tools/autodebugger.py
+++ b/tools/autodebugger.py
@@ -11,17 +11,22 @@ Warning: You probably want to compile with SKIP_STACK_IN_SMALL=0! Otherwise
import os, sys, re
ALLOW_POINTERS = False
+ALLOW_MISC = True
MEMCPY = False
+NO_DLMALLOC = True
POSTAMBLE = '''
@.emscripten.autodebug.str = private constant [10 x i8] c"AD:%d,%d\\0A\\00", align 1 ; [#uses=1]
@.emscripten.autodebug.str.f = private constant [11 x i8] c"AD:%d,%lf\\0A\\00", align 1 ; [#uses=1]
+@.emscripten.autodebug.str.64 = private constant [13 x i8] c"AD:%d,%d,%d\\0A\\00", align 1 ; [#uses=1]
; [#uses=1]
define void @emscripten_autodebug_i64(i32 %line, i64 %value) {
entry:
- %0 = sitofp i64 %value to double ; [#uses=1]
- %1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.emscripten.autodebug.str.f, i32 0, i32 0), i32 %line, double %0) ; [#uses=0]
+ %0 = trunc i64 %value to i32
+ %1 = lshr i64 %value, 32
+ %2 = trunc i64 %1 to i32
+ %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([13 x i8]* @.emscripten.autodebug.str.64, i32 0, i32 0), i32 %line, i32 %0, i32 %2) ; [#uses=0]
br label %return
return: ; preds = %entry
@@ -202,6 +207,7 @@ for.end: ; preds = %for.body, %entry
lines_added = 0
lines = data.split('\n')
in_func = False
+added_entry = False
for i in range(len(lines)):
if MEMCPY:
if not lines[i].startswith('declare void'):
@@ -211,34 +217,56 @@ for i in range(len(lines)):
pre = ''
if lines[i].startswith('define '):
in_func = True
+ if NO_DLMALLOC and ('@malloc(' in lines[i] or '@free(' in lines[i] or '@sys_alloc(' in lines[i] or '@segment_holding(' in lines[i] or '@init_top(' in lines[i] or '@add_segment(' in lines[i] or '@tmalloc_small(' in lines[i]):
+ in_func = False
+ if in_func:
+ added_entry = False
elif lines[i].startswith('}'):
in_func = False
- elif in_func and ' = alloca' not in lines[i] and lines[i].startswith(' '):
+ elif in_func and not added_entry and ' = alloca' not in lines[i] and lines[i].startswith(' '):
# This is a good place to mark entry to this function
- in_func = False
+ added_entry = True
index = i+1+lines_added
pre = ' call void @emscripten_autodebug_i32(i32 -1, i32 %d)' % index
- elif lines[i].startswith(' ret '):
+ elif in_func and lines[i].startswith(' ret '):
# This is a good place to mark entry to this function
index = i+1+lines_added
pre = ' call void @emscripten_autodebug_i32(i32 -2, i32 %d)' % index
- m = re.match(' store (?P<type>i64|i32|i16|i8|float|double|%?[\w\.\*]+) (?P<var>%?[\w.+_]+), .*', lines[i])
- if m:
- index = i+1+lines_added
- if m.group('type') in ['i8', 'i16', 'i32', 'i64', 'float', 'double']:
- lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %s)' % (m.group('type'), index, m.group('type'), m.group('var'))
+ if in_func:
+ m = re.match(' store (?P<type>i64|i32|i16|i8|float|double|%?[\w\.\*]+) (?P<var>%?[\w.+_]+), .*', lines[i])
+ if m:
+ index = i+1+lines_added
+ if m.group('type') in ['i8', 'i16', 'i32', 'i64', 'float', 'double']:
+ lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %s)' % (m.group('type'), index, m.group('type'), m.group('var'))
+ lines_added += 1
+ elif ALLOW_POINTERS and m.group('type').endswith('*') and m.group('type').count('*') == 1:
+ lines[i] += '\n %%ead.%d = ptrtoint %s %s to i32' % (index, m.group('type'), m.group('var'))
+ lines[i] += '\n call void @emscripten_autodebug_i32(i32 %d, i32 %%ead.%d)' % (index, index)
+ lines_added += 2
+ continue
+ m = re.match(' %(?P<var>[\w_.]+) = load (?P<type>i64|i32|i16|i8|float|double+)\* [^(].*.*', lines[i])
+ if m:
+ index = i+1+lines_added
+ lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var'))
lines_added += 1
- elif ALLOW_POINTERS and m.group('type').endswith('*') and m.group('type').count('*') == 1:
- lines[i] += '\n %%ead.%d = ptrtoint %s %s to i32' % (index, m.group('type'), m.group('var'))
- lines[i] += '\n call void @emscripten_autodebug_i32(i32 %d, i32 %%ead.%d)' % (index, index)
- lines_added += 2
- continue
- m = re.match(' %(?P<var>[\w_.]+) = load (?P<type>i64|i32|i16|i8|float|double+)\* [^(].*.*', lines[i])
- if m:
- index = i+1+lines_added
- lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var'))
- lines_added += 1
+ continue
+ if ALLOW_MISC:
+ m = re.match(' %(?P<var>[\w_.]+) = (call|mul|add) (nsw )?(?P<type>i64|i32|i16|i8|float|double+) .*', lines[i])
+ if m:
+ index = i+1+lines_added
+ lines[i] += '\n call void @emscripten_autodebug_%s(i32 %d, %s %%%s)' % (m.group('type'), index, m.group('type'), m.group('var'))
+ lines_added += 1
+ continue
+ m = re.match(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i])
+ if m:
+ index = i+1+lines_added
+ lines[i] += '\n %%adpretemp%d = bitcast i8* %%%s to i64*' % (index, m.group('src')) + \
+ '\n %%adtemp%d = load i64* %%adpretemp%d, align %s' % (index, index, m.group('align')) + \
+ '\n call void @emscripten_autodebug_%s(i32 %d, %s %%adtemp%d)' % ('i64', index, 'i64', index)
+ lines_added += 3
+ continue
+
finally:
if len(pre) > 0:
lines[i] = pre + '\n' + lines[i]
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 3fbff13d..0c7c814f 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -671,25 +671,22 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
has_string_convs = False
- # We can assume that NULL is passed for null pointers, so object arguments can always
- # have .ptr done on them
- justargs_fixed = justargs(args)[:]
- for i in range(len(args)):
- arg = args[i]
- clean = clean_type(arg['type'])
- if clean in classes:
- justargs_fixed[i] += '.ptr'
- elif arg['type'].replace(' ', '').endswith('char*'):
- justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')'
- has_string_convs = True
-
calls = ''
- if has_string_convs:
- calls += 'var stack = Runtime.stackSave();\n';
- calls += 'try {\n'
#print 'js loopin', params, '|', len(args)#, args
for args in params:
+ # We can assume that NULL is passed for null pointers, so object arguments can always
+ # have .ptr done on them
+ justargs_fixed = justargs(args)[:]
+ for i in range(len(args)):
+ arg = args[i]
+ clean = clean_type(arg['type'])
+ if clean in classes:
+ justargs_fixed[i] += '.ptr'
+ elif arg['type'].replace(' ', '').endswith('char*'):
+ justargs_fixed[i] = 'ensureString(' + justargs_fixed[i] + ')'
+ has_string_convs = True
+
i = len(args)
if args != params[0]:
calls += ' else '
@@ -715,7 +712,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
calls += '\n'
if has_string_convs:
- calls += '} finally { Runtime.stackRestore(stack) }\n';
+ calls = 'var stack = Runtime.stackSave();\ntry {\n' + calls + '} finally { Runtime.stackRestore(stack) }\n';
print 'Maekin:', classname, generating_classname, mname, mname_suffixed
if constructor:
diff --git a/tools/bisect_pair.py b/tools/bisect_pair.py
index 3b880b28..8eea0d61 100644
--- a/tools/bisect_pair.py
+++ b/tools/bisect_pair.py
@@ -47,14 +47,12 @@ if len(curr) > 0:
chunks.append(curr)
# Bisect both sides of the span, until we have a single chunk
-low = 0
high = len(chunks)
print 'beginning bisection, %d chunks' % high
-while high-low > 2:
- mid = (low + high)/2
- print ' current status: %d - %d - %d' % (low, mid, high)
+for mid in range(high):
+ print ' current: %d' % mid
# Take chunks from the middle and on. This is important because the eliminator removes variables, so starting from the beginning will add errors
curr_diff = '\n'.join(map(lambda parts: '\n'.join(parts), chunks[mid:])) + '\n'
difff = open('diff.diff', 'w')
@@ -64,11 +62,11 @@ while high-low > 2:
Popen(['patch', 'middle', 'diff.diff'], stdout=PIPE, stderr=PIPE).communicate()
result = run_js('middle', stderr=PIPE)
if result == left_result:
- high = mid+1
- else:
- low = mid
+ print 'found where it starts to work: %d' % mid
+ found = mid
+ break
-critical = '\n'.join(chunks[low]) + '\n'
+critical = '\n'.join(chunks[found-1]) + '\n'
c = open('critical.diff', 'w')
c.write(critical)
@@ -76,8 +74,8 @@ c.close()
print 'sanity check'
shutil.copy('middle', 'middle2')
Popen(['patch', 'middle2', 'critical.diff'], stdout=PIPE, stderr=PIPE).communicate()
-assert run_js('middle', stderr=PIPE) == left_result
-assert run_js('middle2', stderr=PIPE) != left_result
+assert run_js('middle', stderr=PIPE) == left_result, 'middle was expected %s' % left_result
+assert run_js('middle2', stderr=PIPE) != left_result, 'middle2 was expected NOT %s' % left_result
print 'middle is like left, middle2 is like right, critical.diff is the difference that matters,'
print critical
diff --git a/tools/clean_webconsole.py b/tools/clean_webconsole.py
new file mode 100644
index 00000000..43694179
--- /dev/null
+++ b/tools/clean_webconsole.py
@@ -0,0 +1,34 @@
+'''
+Removes timestamp and line info from a webgl log
+'''
+
+import os, sys, re
+
+__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+def path_from_root(*pathelems):
+ return os.path.join(__rootpath__, *pathelems)
+
+def nice(x):
+ return '0x' + ('0' * (len(x)-6)) + x[2:].upper()
+
+repdata = open(path_from_root('system', 'include', 'GL', 'gl.h')).readlines() + ['\n'] + \
+ open(path_from_root('system', 'include', 'GL', 'glext.h')).readlines()
+reps = {}
+for rep in repdata:
+ rep = rep.replace('\t', ' ').replace('\n', '')
+ parts = filter(lambda part: part != '', rep.split(' '))
+ if len(parts) == 3 and parts[0] == '#define':
+ reps[nice(parts[2])] = '%s (%s)' % (parts[1], parts[2])
+
+lines = sys.stdin.read().split('\n')
+
+for line in lines:
+ if line.startswith('['):
+ line = line[15:]
+ line = line.split(' @ ')[0]
+ line = re.sub('(0x[\dabcdef]+)', lambda hexx: reps[nice(hexx.group(0))] if nice(hexx.group(0)) in reps else nice(hexx.group(0)), line)
+ print line
+
+#for i in range(100):
+# print
+
diff --git a/tools/crunch-worker.js b/tools/crunch-worker.js
new file mode 100644
index 00000000..5c48d009
--- /dev/null
+++ b/tools/crunch-worker.js
@@ -0,0 +1,124 @@
+// From Brandon Jones' awesome WebGL texture utils,
+// https://github.com/toji/webgl-texture-utils
+// which in turn based off of Evan Parker's cool work,
+// http://www-cs-students.stanford.edu/~eparker/files/crunch/decode_test.html
+//
+// This combines crunch-worker.js and crn_decomp.js. Minor changes
+// to make it work that way, and to return all levels in one array
+
+ /*
+ * Copyright (c) 2012 Brandon Jones
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+ // Taken from crnlib.h
+ var cCRNFmtInvalid = -1;
+
+ var cCRNFmtDXT1 = 0;
+ var cCRNFmtDXT3 = 1;
+ var cCRNFmtDXT5 = 2;
+
+ // Various DXT5 derivatives
+ var cCRNFmtDXT5_CCxY = 3; // Luma-chroma
+ var cCRNFmtDXT5_xGxR = 4; // Swizzled 2-component
+ var cCRNFmtDXT5_xGBR = 5; // Swizzled 3-component
+ var cCRNFmtDXT5_AGBR = 6; // Swizzled 4-component
+
+ // ATI 3DC and X360 DXN
+ var cCRNFmtDXN_XY = 7;
+ var cCRNFmtDXN_YX = 8;
+
+ // DXT5 alpha blocks only
+ var cCRNFmtDXT5A = 9;
+
+ function arrayBufferCopy(src, dst, dstByteOffset, numBytes) {
+ dst.set(src.subarray(0, numBytes), dstByteOffset);
+ }
+
+ function deCrunch(bytes, filename) {
+ var srcSize = bytes.length;
+ var src = Module._malloc(srcSize),
+ format, internalFormat, dst, dstSize,
+ width, height, levels, dxtData, rgb565Data, i;
+
+ arrayBufferCopy(bytes, Module.HEAPU8, src, srcSize);
+
+ format = Module._crn_get_dxt_format(src, srcSize);
+
+ if(format != cCRNFmtDXT1 && format != cCRNFmtDXT3 && format != cCRNFmtDXT5) {
+ throw "Unsupported image format " + format + " for " + filename;
+ }
+ width = Module._crn_get_width(src, srcSize);
+ height = Module._crn_get_height(src, srcSize);
+ levels = Module._crn_get_levels(src, srcSize);
+ dstSize = Module._crn_get_uncompressed_size(src, srcSize, 0);
+ dst = Module._malloc(dstSize);
+
+ var totalSize = 0;
+ var bytesPerPixel = format == cCRNFmtDXT1 ? 0.5 : 1;
+ for(i = 0; i < levels; ++i) {
+ totalSize += width * height * bytesPerPixel;
+ width *= 0.5;
+ height *= 0.5;
+ width = Math.max(width, 4);
+ height = Math.max(height, 4);
+ }
+
+ width = Module._crn_get_width(src, srcSize);
+ height = Module._crn_get_height(src, srcSize);
+
+ var ret = new Uint8Array(totalSize);
+ var retIndex = 0;
+
+ for(i = 0; i < levels; ++i) {
+ if(i) {
+ dstSize = Module._crn_get_uncompressed_size(src, srcSize, i);
+ }
+ Module._crn_decompress(src, srcSize, dst, dstSize, i);
+ ret.set(Module.HEAPU8.subarray(dst, dst+dstSize), retIndex);
+ retIndex += dstSize;
+
+ width *= 0.5;
+ height *= 0.5;
+ }
+
+ Module._free(src);
+ Module._free(dst);
+
+ return ret;
+ }
+
+ //===
+function a(b){throw b}var aa=void 0,l=!0,pa=null,n=!1,za=[],Da="object"===typeof process,Ea="object"===typeof window,Fa="function"===typeof importScripts,Ja=!Ea&&!Da&&!Fa;if(Da){print=(function(b){process.stdout.write(b+"\n")});printErr=(function(b){process.stderr.write(b+"\n")});var Ma=require("fs");read=(function(b){var c=Ma.readFileSync(b).toString();!c&&"/"!=b[0]&&(b=__dirname.split("/").slice(0,-1).join("/")+"/src/"+b,c=Ma.readFileSync(b).toString());return c});load=(function(b){Na(read(b))});za=process.argv.slice(2)}else{Ja?(this.read||(this.read=(function(b){snarf(b)})),"undefined"!=typeof scriptArgs?za=scriptArgs:"undefined"!=typeof arguments&&(za=arguments)):Ea?(this.print=printErr=(function(b){console.log(b)}),this.read=(function(b){var c=new XMLHttpRequest;c.open("GET",b,n);c.send(pa);return c.responseText}),this.arguments&&(za=arguments)):Fa?this.load=importScripts:a("Unknown runtime environment. Where are we?")}function Na(b){eval.call(pa,b)}"undefined"==typeof load&&"undefined"!=typeof read&&(this.load=(function(b){Na(read(b))}));"undefined"===typeof printErr&&(this.printErr=(function(){}));"undefined"===typeof print&&(this.print=printErr);try{this.Module=Module}catch(Qa){this.Module=Module={}}Module.arguments||(Module.arguments=za);Module.print&&(print=Module.print);function Wa(b){if(Xa==1){return 1}var c={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+b];if(!c){if(b[b.length-1]=="*"){c=Xa}else{if(b[0]=="i"){b=parseInt(b.substr(1));Ya(b%8==0);c=b/8}}}return c}function cb(b){var c=q;q=q+b;q=q+3>>2<<2;return c}function db(b){var c=eb;eb=eb+b;eb=eb+3>>2<<2;if(eb>=fb){for(;fb<=eb;){fb=2*fb+4095>>12<<12}var b=v,d=new ArrayBuffer(fb);v=new Int8Array(d);gb=new Int16Array(d);y=new Int32Array(d);z=new Uint8Array(d);A=new Uint16Array(d);C=new Uint32Array(d);lb=new Float32Array(d);mb=new Float64Array(d);v.set(b)}return c}var Xa=4,ub={},vb;function wb(b){print(b+":\n"+Error().stack);a("Assertion: "+b)}function Ya(b,c){b||wb("Assertion failed: "+c)}var Mb=this;Module.ccall=(function(b,c,d,e){try{var g=eval("_"+b)}catch(h){try{g=Mb.Module["_"+b]}catch(j){}}Ya(g,"Cannot call unknown function "+b+" (perhaps LLVM optimizations or closure removed it?)");var i=0,b=e?e.map((function(b){if(d[i++]=="string"){var c=q;cb(b.length+1);Nb(b,c);b=c}return b})):[];return(function(b,c){return c=="string"?Vb(b):b})(g.apply(pa,b),c)});function Wb(b,c,d){d=d||"i8";d[d.length-1]==="*"&&(d="i32");switch(d){case"i1":v[b]=c;break;case"i8":v[b]=c;break;case"i16":gb[b>>1]=c;break;case"i32":y[b>>2]=c;break;case"i64":y[b>>2]=c;break;case"float":lb[b>>2]=c;break;case"double":Yb[0]=c;y[b>>2]=Zb[0];y[b+4>>2]=Zb[1];break;default:wb("invalid type for setValue: "+d)}}Module.setValue=Wb;Module.getValue=(function(b,c){c=c||"i8";c[c.length-1]==="*"&&(c="i32");switch(c){case"i1":return v[b];case"i8":return v[b];case"i16":return gb[b>>1];case"i32":return y[b>>2];case"i64":return y[b>>2];case"float":return lb[b>>2];case"double":return Zb[0]=y[b>>2],Zb[1]=y[b+4>>2],Yb[0];default:wb("invalid type for setValue: "+c)}return pa});var $b=1,D=2;Module.ALLOC_NORMAL=0;Module.ALLOC_STACK=$b;Module.ALLOC_STATIC=D;function G(b,c,d){var e,g;if(typeof b==="number"){e=l;g=b}else{e=n;g=b.length}var h=typeof c==="string"?c:pa,d=[ac,cb,db][d===aa?D:d](Math.max(g,h?1:c.length));if(e){bc(d,0,g);return d}e=0;for(var j;e<g;){var i=b[e];typeof i==="function"&&(i=ub.xa(i));j=h||c[e];if(j===0){e++}else{j=="i64"&&(j="i32");Wb(d+e,i,j);e=e+Wa(j)}}return d}Module.allocate=G;function Vb(b,c){for(var d=typeof c=="undefined",e="",g=0,h,j=String.fromCharCode(0);;){h=String.fromCharCode(z[b+g]);if(d&&h==j){break}e=e+h;g=g+1;if(!d&&g==c){break}}return e}Module.Pointer_stringify=Vb;Module.Array_stringify=(function(b){for(var c="",d=0;d<b.length;d++){c=c+String.fromCharCode(b[d])}return c});var dc,ec=4096,v,z,gb,A,y,C,lb,mb,q,fc,eb,hc=Module.TOTAL_STACK||5242880,fb=Module.TOTAL_MEMORY||10485760;Ya(!!Int32Array&&!!Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"Cannot fallback to non-typed array case: Code is too specialized");var ic=new ArrayBuffer(fb);v=new Int8Array(ic);gb=new Int16Array(ic);y=new Int32Array(ic);z=new Uint8Array(ic);A=new Uint16Array(ic);C=new Uint32Array(ic);lb=new Float32Array(ic);mb=new Float64Array(ic);y[0]=255;Ya(255===z[0]&&0===z[3],"Typed arrays 2 must be run on a little-endian system");var kc=jc("(null)");eb=kc.length;for(var lc=0;lc<kc.length;lc++){v[lc]=kc[lc]}Module.HEAP=aa;Module.HEAP8=v;Module.HEAP16=gb;Module.HEAP32=y;Module.HEAPU8=z;Module.HEAPU16=A;Module.HEAPU32=C;Module.HEAPF32=lb;Module.HEAPF64=mb;fc=(q=4*Math.ceil(eb/4))+hc;var mc=8*Math.ceil(fc/8);v.subarray(mc);var Zb=y.subarray(mc>>2);lb.subarray(mc>>2);var Yb=mb.subarray(mc>>3);fc=mc+8;eb=fc+4095>>12<<12;function nc(b){for(;b.length>0;){var c=b.shift(),d=c.r;typeof d==="number"&&(d=dc[d]);d(c.da===aa?pa:c.da)}}var pc=[],qc=[];function rc(b,c){return Array.prototype.slice.call(v.subarray(b,b+c))}Module.Array_copy=rc;Module.TypedArray_copy=(function(b,c){for(var d=new Uint8Array(c),e=0;e<c;++e){d[e]=v[b+e]}return d.buffer});function sc(b){for(var c=0;v[b+c];){c++}return c}Module.String_len=sc;function tc(b,c){var d=sc(b);c&&d++;var e=rc(b,d);c&&(e[d-1]=0);return e}Module.String_copy=tc;function jc(b,c){for(var d=[],e=0;e<b.length;){var g=b.charCodeAt(e);g>255&&(g=g&255);d.push(g);e=e+1}c||d.push(0);return d}Module.intArrayFromString=jc;Module.intArrayToString=(function(b){for(var c=[],d=0;d<b.length;d++){var e=b[d];e>255&&(e=e&255);c.push(String.fromCharCode(e))}return c.join("")});function Nb(b,c,d){for(var e=0;e<b.length;){var g=b.charCodeAt(e);g>255&&(g=g&255);v[c+e]=g;e=e+1}d||(v[c+e]=0)}Module.writeStringToMemory=Nb;var M=[];function uc(b,c){return b>=0?b:c<=32?2*Math.abs(1<<c-1)+b:Math.pow(2,c)+b}function vc(b,c){if(b<=0){return b}var d=c<=32?Math.abs(1<<c-1):Math.pow(2,c-1);if(b>=d&&(c<=32||b>d)){b=-2*d+b}return b}function wc(b){b=b-1|0;b=b>>>16|b;b=b>>>8|b;b=b>>>4|b;b=b>>>2|b;return(b>>>1|b)+1|0}function xc(b,c){var d=M.O|0,e=q;q=q+512;for(var g=e|0,d=(vb=q,q=q+12,y[vb>>2]=d,y[vb+4>>2]=c,y[vb+8>>2]=b,vb),d=yc(M.G|0,d),h=d.length,j=0;j<h;j++){v[g+j]=d[j]}v[g+j]=0;h=(vb=q,q=q+1,q=q+3>>2<<2,y[vb>>2]=0,vb);d=y[zc>>2];j=yc(g,h);g=q;h=G(j,"i8",$b);j=j.length*1;if(j!=0&&Dc(d,h,j)==-1&&Ec[d]){Ec[d].error=l}q=g;q=e}function Fc(b,c,d,e,g){var h,j,i=q;q=q+4;var f=b+4|0;j=(b+8|0)>>2;C[f>>2]>>>0>C[j]>>>0&&xc(M.H|0,2121);Math.floor(2147418112/(e>>>0))>>>0>c>>>0||xc(M.T|0,2122);var k=C[j],o=k>>>0<c>>>0;do{if(o){var m=d?((c|0)==0?0:(c-1&c|0)==0)?c:wc(c):c;(m|0)!=0&m>>>0>k>>>0||xc(M.Y|0,2131);var t=m*e|0;if((g|0)==0){h=b|0;var s,w=y[h>>2],u=t,r=i;s=q;q=q+4;if((w&7|0)==0){if(u>>>0>2147418112){xc(M.m|0,2500);r=0}else{y[s>>2]=u;w=dc[y[Gc>>2]](w,u,s,1,y[Hc>>2]);(r|0)!=0&&(y[r>>2]=y[s>>2]);(w&7|0)!=0&&xc(M.n|0,2552);r=w}}else{xc(M.J|0,2500);r=0}q=s;s=r;if((s|0)==0){m=0;break}y[h>>2]=s}else{s=Ic(t,i);if((s|0)==0){m=0;break}h=(b|0)>>2;dc[g](s,y[h],y[f>>2]);r=y[h];(r|0)!=0&&Jc(r);y[h]=s}h=C[i>>2];y[j]=h>>>0>t>>>0?Math.floor((h>>>0)/(e>>>0)):m}m=1}while(0);q=i;return m}Fc.X=1;function Ic(b,c){var d=q;q=q+4;var e=b+3&-4,e=(e|0)==0?4:e;if(e>>>0>2147418112){xc(M.m|0,2500);e=0}else{y[d>>2]=e;var g=dc[y[Gc>>2]](0,e,d,1,y[Hc>>2]),h=C[d>>2];(c|0)!=0&&(y[c>>2]=h);if((g|0)==0|h>>>0<e>>>0){xc(M.I|0,2500);e=0}else{(g&7|0)!=0&&xc(M.n|0,2527);e=g}}q=d;return e}function Jc(b){if((b|0)!=0){if((b&7|0)==0){dc[y[Gc>>2]](b,0,0,1,y[Hc>>2])}else{xc(M.K|0,2500)}}}function Kc(b,c,d,e){var g,h,j,i,f=b>>2,k=q;q=q+200;var o;i=k>>2;var m=k+64;j=m>>2;var t=k+132,s=(c|0)==0|e>>>0>11;a:do{if(s){var w=0}else{y[f]=c;bc(m,0,68);for(var u=0;;){var r=z[d+u|0];if(r<<24>>24!=0){var x=((r&255)<<2)+m|0;y[x>>2]=y[x>>2]+1|0}var p=u+1|0;if((p|0)==(c|0)){var B=1,I=-1,S=0,Q=0,H=0;break}u=p}for(;;){var J=C[(B<<2>>2)+j];if((J|0)==0){y[((B-1<<2)+28>>2)+f]=0;var K=H,E=Q,da=S,N=I}else{var ka=I>>>0<B>>>0?I:B,ba=S>>>0>B>>>0?S:B,ra=B-1|0;y[(ra<<2>>2)+i]=H;var ia=J+H|0,fa=16-B|0;y[((ra<<2)+28>>2)+f]=(ia-1<<fa|(1<<fa)-1)+1|0;y[((ra<<2)+96>>2)+f]=Q;y[t+(B<<2)>>2]=Q;K=ia;E=J+Q|0;da=ba;N=ka}var Ga=B+1|0;if((Ga|0)==17){break}B=Ga;I=N;S=da;Q=E;H=K<<1}y[f+1]=E;h=(b+172|0)>>2;if(E>>>0>C[h]>>>0){var ta=((E|0)==0?0:(E-1&E|0)==0)?E:c>>>0<wc(E)>>>0?c:wc(E);y[h]=ta;var la=b+176|0,Aa=y[la>>2];if((Aa|0)==0){var xa=ta}else{Lc(Aa);xa=y[h]}var Y,ma=(xa|0)==0?1:xa,ga=Ic((ma<<1)+8|0,0);if((ga|0)==0){var ua=0}else{var Ba=ga+8|0;y[ga+4>>2]=ma;y[ga>>2]=ma^-1;ua=Ba}Y=ua;y[la>>2]=Y;if((Y|0)==0){w=0;break}var Ca=la}else{Ca=b+176|0}var va=b+24|0;v[va]=N&255;v[b+25|0]=da&255;for(var Z=0;;){var sa=z[d+Z|0],T=sa&255;if(sa<<24>>24!=0){(y[(T<<2>>2)+j]|0)==0&&xc(M.Z|0,2274);var ea=(T<<2)+t|0,W=C[ea>>2];y[ea>>2]=W+1|0;W>>>0<E>>>0||xc(M.$|0,2278);gb[y[Ca>>2]+(W<<1)>>1]=Z&65535}var ya=Z+1|0;if((ya|0)==(c|0)){break}Z=ya}var L=z[va],O=(L&255)>>>0<e>>>0?e:0,qa=b+8|0;y[qa>>2]=O;var na=(O|0)!=0;if(na){var U=1<<O,P=b+164|0,F=U>>>0>C[P>>2]>>>0;do{if(F){y[P>>2]=U;var oa=b+168|0,wa=y[oa>>2];(wa|0)!=0&&Mc(wa);var ca,V=(U|0)==0?1:U,ja=Ic((V<<2)+8|0,0);if((ja|0)==0){var Oa=0}else{var hb=ja+8|0;y[ja+4>>2]=V;y[ja>>2]=V^-1;Oa=hb}ca=Oa;y[oa>>2]=ca;if((ca|0)==0){w=0;break a}bc(ca,-1,U<<2);if((O|0)==0){o=26}else{Ra=oa;o=34}}else{var Ha=b+168|0;bc(y[Ha>>2],-1,U<<2);var Ra=Ha;o=34}}while(0);b:do{if(o==34){for(var Za=1;;){var Ob=(y[(Za<<2>>2)+j]|0)==0;c:do{if(!Ob){var xb=O-Za|0,Pb=1<<xb,yb=Za-1|0,ha=C[(yb<<2>>2)+i],Ka,La=b,ib=Za;(ib|0)!=0&ib>>>0<17||xc(M.W|0,1954);var zb=y[La+(ib-1<<2)+28>>2];Ka=(zb|0)==0?-1:(zb-1|0)>>>((16-ib|0)>>>0);if(ha>>>0<=Ka>>>0){for(var Qb=y[((yb<<2)+96>>2)+f]-ha|0,Rb=Za<<16,$a=ha;;){var Sb=A[y[Ca>>2]+(Qb+$a<<1)>>1]&65535;(z[d+Sb|0]&255|0)!=(Za|0)&&xc(M.aa|0,2320);for(var Tb=$a<<xb,cc=Sb|Rb,Ab=0;;){var bb=Ab+Tb|0;bb>>>0<U>>>0||xc(M.ba|0,2326);var ab=C[Ra>>2];if((y[ab+(bb<<2)>>2]|0)==-1){var Ia=ab}else{xc(M.ca|0,2328);Ia=y[Ra>>2]}y[Ia+(bb<<2)>>2]=cc;var Bb=Ab+1|0;if(Bb>>>0>=Pb>>>0){break}Ab=Bb}var Cb=$a+1|0;if(Cb>>>0>Ka>>>0){break c}$a=Cb}}}}while(0);var Db=Za+1|0;if(Db>>>0>O>>>0){break b}Za=Db}}}while(0);var ob=v[va]}else{ob=L}var pb=b+96|0;y[pb>>2]=y[pb>>2]-y[i]|0;var Eb=b+100|0;y[Eb>>2]=y[Eb>>2]-y[i+1]|0;var Fb=b+104|0;y[Fb>>2]=y[Fb>>2]-y[i+2]|0;var qb=b+108|0;y[qb>>2]=y[qb>>2]-y[i+3]|0;var jb=b+112|0;y[jb>>2]=y[jb>>2]-y[i+4]|0;var rb=b+116|0;y[rb>>2]=y[rb>>2]-y[i+5]|0;var Sa=b+120|0;y[Sa>>2]=y[Sa>>2]-y[i+6]|0;var Pa=b+124|0;y[Pa>>2]=y[Pa>>2]-y[i+7]|0;var sb=b+128|0;y[sb>>2]=y[sb>>2]-y[i+8]|0;var Ta=b+132|0;y[Ta>>2]=y[Ta>>2]-y[i+9]|0;var Gb=b+136|0;y[Gb>>2]=y[Gb>>2]-y[i+10]|0;var Hb=b+140|0;y[Hb>>2]=y[Hb>>2]-y[i+11]|0;var Ib=b+144|0;y[Ib>>2]=y[Ib>>2]-y[i+12]|0;var tb=b+148|0;y[tb>>2]=y[tb>>2]-y[i+13]|0;var Jb=b+152|0;y[Jb>>2]=y[Jb>>2]-y[i+14]|0;var Kb=b+156|0;y[Kb>>2]=y[Kb>>2]-y[i+15]|0;var Lb=b+16|0;y[Lb>>2]=0;g=(b+20|0)>>2;y[g]=ob&255;b:do{if(na){for(var kb=O;;){if((kb|0)==0){break b}var Ua=kb-1|0;if((y[(kb<<2>>2)+j]|0)!=0){break}kb=Ua}y[Lb>>2]=y[((Ua<<2)+28>>2)+f];for(var Ub=O+1|0,Va=y[g]=Ub;;){if(Va>>>0>da>>>0){break b}if((y[(Va<<2>>2)+j]|0)!=0){break}Va=Va+1|0}y[g]=Va}}while(0);y[f+23]=-1;y[f+40]=1048575;y[f+3]=32-y[qa>>2]|0;w=1}}while(0);q=k;return w}Kc.X=1;function Lc(b){var c;if((b|0)!=0){c=y[b-4>>2];b=b-8|0;c=(c|0)==0?4:(c|0)==(y[b>>2]^-1|0)?5:4;c==4&&xc(M.p|0,645);Jc(b)}}function Mc(b){var c;if((b|0)!=0){c=y[b-4>>2];b=b-8|0;c=(c|0)==0?4:(c|0)==(y[b>>2]^-1|0)?5:4;c==4&&xc(M.p|0,645);Jc(b)}}function Nc(b){return(z[b|0]&255)<<8|z[b+1|0]&255}function Oc(b){return(z[b+1|0]&255)<<16|(z[b|0]&255)<<24|z[b+3|0]&255|(z[b+2|0]&255)<<8}function Pc(b){return z[b|0]&255}function Qc(b){return z[b+2|0]&255|(z[b|0]&255)<<16|(z[b+1|0]&255)<<8}function Rc(b,c){if(b==0&&c==0||b==9&&c==0){var d=4}else{if(b==1&&c==0||b==2&&c==0||b==7&&c==0||b==8&&c==0||b==3&&c==0||b==4&&c==0||b==5&&c==0||b==6&&c==0){d=8}else{xc(M.M|0,2664);d=0}}return d}function Sc(b,c){return(b|0)==0|c>>>0<74?0:(Nc(b)|0)!=18552?0:Nc(b+2|0)>>>0<74?0:Oc(b+6|0)>>>0>c>>>0?0:b}function Tc(b,c,d){var e=d>>2;if((b|0)==0|c>>>0<74|(d|0)==0){e=0}else{if((y[e]|0)!=40){e=0}else{b=Sc(b,c);if((b|0)==0){e=0}else{y[e+1]=Nc(b+12|0);y[e+2]=Nc(b+14|0);y[e+3]=Pc(b+16|0);y[e+4]=Pc(b+17|0);c=b+18|0;d=d+32|0;y[d>>2]=Pc(c);y[d+4>>2]=0;d=Pc(c);y[e+5]=(d|0)==0?8:(d|0)==9?8:16;y[e+6]=Oc(b+25|0);y[e+7]=Oc(b+29|0);e=1}}}return e}Tc.X=1;function Uc(b){y[b>>2]=0;var c=b+4|0;y[c>>2]=0;y[c+4>>2]=0;y[c+8>>2]=0;v[c+12|0]=0;y[b+20>>2]=0}function Vc(b){var c=y[b+20>>2];if((c|0)!=0&&(c|0)!=0){Wc(c);Jc(c)}Xc(b+4|0)}function Xc(b){var c=b|0,d=y[c>>2];if((d|0)!=0){var e=b+4|0;Jc(d);y[c>>2]=0;y[e>>2]=0;y[b+8>>2]=0}v[b+12|0]=0}function Yc(b,c){var d;d=(b+4|0)>>2;var e=C[d],g=(e|0)==(c|0);do{if(g){var h=1}else{if(e>>>0<=c>>>0){if(C[b+8>>2]>>>0<c>>>0){h=b;if(Fc(h,c,(e+1|0)==(c|0),1,0)){h=1}else{v[h+12|0]=1;h=0}if(!h){h=0;break}h=y[d]}else{h=e}bc(y[b>>2]+h|0,0,c-h|0)}y[d]=c;h=1}}while(0);return h}function Zc(b,c){C[b+4>>2]>>>0>c>>>0||xc(M.g|0,904);return y[b>>2]+c|0}function $c(b){var c=b+4|0,d=y[c+4>>2];(d|0)!=0&d>>>0<8193||xc(M.N|0,2998);var e=b|0;y[e>>2]=d;var g=b+20|0,h=C[g>>2];if((h|0)==0){d=Ic(180,0);if((d|0)==0){d=0}else{if((d|0)==0){d=0}else{y[d+164>>2]=0;y[d+168>>2]=0;y[d+172>>2]=0;y[d+176>>2]=0}}g=y[g>>2]=d;e=y[e>>2]}else{g=h;e=d}var c=Zc(c,0),b=C[b>>2],j;if(b>>>0>16){d=b>>>0>1;a:do{if(d){for(var i=0,h=b;;){i=i+1|0;if(h>>>0<=3){j=i;break a}h=h>>>1}}else{j=0}}while(0);j=(j|0)==32?32:(1<<j>>>0<b>>>0&1)+j|0;j=((j+1|0)>>>0<11?j+1|0:11)&255}else{j=0}return Kc(g,e,c,j)}function ad(b,c){if((c|0)==0){var d=0}else{if(c>>>0>16){var d=bd(b,c-16|0),e=bd(b,16),d=d<<16|e}else{d=bd(b,c)}}return d}function R(b,c){var d,e,g,h;g=C[c+20>>2]>>2;e=(b+20|0)>>2;var j=C[e];if((j|0)<24){d=(b+4|0)>>2;var i=C[d],f=C[b+8>>2];h=i>>>0<f>>>0;if((j|0)<16){if(h){h=i+1|0;i=(z[i]&255)<<8}else{h=i;i=0}if(h>>>0<f>>>0){f=h+1|0;h=z[h]&255}else{f=h;h=0}y[d]=f;y[e]=j+16|0;d=b+16|0;j=(h|i)<<16-j|y[d>>2]}else{if(h){y[d]=i+1|0;i=z[i]&255}else{i=0}y[e]=j+8|0;d=b+16|0;j=i<<24-j|y[d>>2]}y[d>>2]=j}else{j=y[b+16>>2]}d=b+16|0;i=(j>>>16)+1|0;f=i>>>0>C[g+4]>>>0;do{if(f){h=C[g+5];var k=h-1|0,o=i>>>0>C[((k<<2)+28>>2)+g]>>>0;a:do{if(o){for(var m=h;;){var t=m+1|0;if(i>>>0<=C[((m<<2)+28>>2)+g]>>>0){var s=t,w=m;break a}m=t}}else{s=h;w=k}}while(0);h=(j>>>((32-s|0)>>>0))+y[((w<<2)+96>>2)+g]|0;if(h>>>0<C[c>>2]>>>0){r=s;x=A[y[g+44]+(h<<1)>>1]&65535;h=22}else{xc(M.o|0,3267);var u=0;h=23}}else{r=C[y[g+42]+(j>>>((32-y[g+2]|0)>>>0)<<2)>>2];(r|0)==-1&&xc(M.R|0,3245);x=r&65535;r=r>>>16;h=c+4|0;k=x;C[h+4>>2]>>>0>k>>>0||xc(M.g|0,903);if((z[y[h>>2]+k|0]&255|0)==(r|0)){var r=r,x=x}else{xc(M.S|0,3249)}h=22}}while(0);if(h==22){y[d>>2]=y[d>>2]<<r;y[e]=y[e]-r|0;u=x}return u}R.X=1;function cd(b,c,d){if((d|0)==0){b=0}else{y[b>>2]=c;y[b+4>>2]=c;y[b+12>>2]=d;y[b+8>>2]=c+d|0;y[b+16>>2]=0;y[b+20>>2]=0;b=1}return b}function bd(b,c){var d;c>>>0<33||xc(M.P|0,3191);d=(b+20|0)>>2;var e=C[d],g=(e|0)<(c|0);a:do{if(g){for(var h=b+4|0,j=b+8|0,i=b+16|0,f=e;;){var k=y[h>>2];if((k|0)==(y[j>>2]|0)){k=0}else{y[h>>2]=k+1|0;k=z[k]&255}f=f+8|0;y[d]=f;if((f|0)>=33){xc(M.Q|0,3200);f=y[d]}k=k<<32-f|y[i>>2];y[i>>2]=k;if((f|0)>=(c|0)){var o=f,m=k;break a}}}else{o=e;m=y[b+16>>2]}}while(0);y[b+16>>2]=m<<c;y[d]=o-c|0;return m>>>((32-c|0)>>>0)}bd.X=1;function dd(b,c){var d,e=q;q=q+24;a:do{for(var g=0,h=8192;;){h=h>>>1;g=g+1|0;if((h|0)==0){d=g;break a}}}while(0);d=ad(b,d);g=(d|0)==0;do{if(g){h=c;y[h>>2]=0;Xc(h+4|0);var h=h+20|0,j=y[h>>2];if((j|0)!=0){if((j|0)!=0){Wc(j);Jc(j)}y[h>>2]=0}h=1}else{h=c+4|0;if(Yc(h,d)){j=Zc(h,0);bc(j,0,d);j=ad(b,5);if((j|0)==0|j>>>0>21){h=0}else{Uc(e);var i=e+4|0,f=Yc(i,21);a:do{if(f){for(var k=0;;){var o=ad(b,3),m=Zc(i,z[M.C+k|0]&255);v[m]=o&255;k=k+1|0;if((k|0)==(j|0)){break}}if($c(e)){k=0;b:for(;;){for(var m=k>>>0<d>>>0,o=d-k|0,t=(k|0)==0,s=k-1|0;;){if(!m){if((k|0)!=(d|0)){p=0;break a}p=$c(c);break a}var w=R(b,e);if(w>>>0<17){o=Zc(h,k);v[o]=w&255;k=k+1|0;continue b}if((w|0)==17){m=ad(b,3)+3|0;if(m>>>0>o>>>0){p=0;break a}k=m+k|0;continue b}else{if((w|0)==18){m=ad(b,7)+11|0;if(m>>>0>o>>>0){p=0;break a}k=m+k|0;continue b}else{if((w-19|0)>>>0>=2){xc(M.o|0,3141);p=0;break a}w=(w|0)==19?ad(b,2)+3|0:ad(b,6)+7|0;if(t|w>>>0>o>>>0){p=0;break a}var u=Zc(h,s),u=z[u];if(u<<24>>24==0){p=0;break a}var r=w+k|0;if(k>>>0<r>>>0){var x=k;break}}}}for(;;){o=Zc(h,x);m=x+1|0;v[o]=u;if((m|0)==(r|0)){k=r;continue b}x=m}}}else{var p=0}}else{p=0}}while(0);Vc(e);h=p}}else{h=0}}}while(0);q=e;return h}dd.X=1;function ed(b,c,d,e,g,h,j){var i=b+88|0,f=C[i>>2],k=((Nc(f+12|0)>>>(j>>>0)>>>0>1?Nc(f+12|0)>>>(j>>>0):1)+3|0)>>>2,j=((Nc(f+14|0)>>>(j>>>0)>>>0>1?Nc(f+14|0)>>>(j>>>0):1)+3|0)>>>2,f=Pc(f+18|0),f=((f|0)==0?8:(f|0)==9?8:16)*k|0;if((h|0)==0){var o=f,h=5}else{if(f>>>0<=h>>>0&(h&3|0)==0){o=h;h=5}else{var m=0,h=12}}if(h==5){if((o*j|0)>>>0>g>>>0){m=0}else{g=(k+1|0)>>>1;m=(j+1|0)>>>1;if(cd(b+92|0,c,d)){c=Pc(y[i>>2]+18|0);if((c|0)==0){fd(b,e,0,o,k,j,g,m);m=1}else{if((c|0)==2||(c|0)==3||(c|0)==5||(c|0)==6||(c|0)==4){gd(b,e,0,o,k,j,g,m);m=1}else{if((c|0)==9){hd(b,e,0,o,k,j,g,m);m=1}else{if((c|0)==7||(c|0)==8){id(b,e,0,o,k,j,g,m);m=1}else{m=0}}}}}else{m=0}}}return m}ed.X=1;Module._crn_get_width=(function(b,c){var d=q;q=q+40;jd(d);Tc(b,c,d);var e=y[d+4>>2];q=d;return e});Module._crn_get_height=(function(b,c){var d=q;q=q+40;jd(d);Tc(b,c,d);var e=y[d+8>>2];q=d;return e});Module._crn_get_levels=(function(b,c){var d=q;q=q+40;jd(d);Tc(b,c,d);var e=y[d+12>>2];q=d;return e});Module._crn_get_dxt_format=(function(b,c){var d=q;q=q+40;jd(d);Tc(b,c,d);var e=y[(d+32|0)>>2];q=d;return e});Module._crn_get_uncompressed_size=(function(b,c,d){var e=q;q=q+40;jd(e);Tc(b,c,e);b=((C[e+4>>2]>>>(d>>>0))+3|0)>>>2;d=((C[e+8>>2]>>>(d>>>0))+3|0)>>>2;c=e+32|0;c=Rc(y[c>>2],y[c+4>>2])<<1&536870910;q=e;return b*c*d|0});Module._crn_decompress=(function(b,c,d,e,g){var h=q;q=q+44;var j=h+40;jd(h);Tc(b,c,h);var i=((C[h+4>>2]>>>(g>>>0))+3|0)>>>2,f=h+32|0,f=Rc(y[f>>2],y[f+4>>2])<<1&536870910,i=i*f|0,k;if((b|0)==0|c>>>0<62){k=0}else{f=Ic(300,0);if((f|0)==0){f=0}else{if((f|0)==0){f=0}else{y[f>>2]=519686845;y[f+4>>2]=0;y[f+8>>2]=0;y[f+88>>2]=0;var o=(f+92|0)>>2;y[o]=0;y[o+1]=0;y[o+2]=0;y[o+3]=0;y[o+4]=0;y[o+5]=0;Uc(f+116|0);Uc(f+140|0);Uc(f+164|0);Uc(f+188|0);Uc(f+212|0);kd(f+236|0);kd(f+252|0);ld(f+268|0);ld(f+284|0)}}if((f|0)==0){k=0}else{o=Sc(b,c);y[f+88>>2]=o;if((o|0)==0){k=0}else{y[f+4>>2]=b;y[f+8>>2]=c;var c=f+92|0,o=y[f+4>>2],b=(f+88|0)>>2,m=y[b],o=cd(c,o+Qc(m+67|0)|0,Nc(m+65|0));do{if(o){if(dd(c,f+116|0)){m=y[b];if((Nc(m+39|0)|0)==0){if((Nc(m+55|0)|0)==0){m=0;break}}else{if(!dd(c,f+140|0)){m=0;break}if(!dd(c,f+188|0)){m=0;break}m=y[b]}if((Nc(m+55|0)|0)!=0){if(!dd(c,f+164|0)){m=0;break}if(!dd(c,f+212|0)){m=0;break}}m=1}else{m=0}}else{m=0}}while(0);if(m){b=f+88|0;c=y[b>>2];if((Nc(c+39|0)|0)==0){k=c;b=5}else{if(md(f)){if(nd(f)){k=y[b>>2];b=5}else{t=0;b=9}}else{var t=0,b=9}}do{if(b==5){if((Nc(k+55|0)|0)!=0){if(!od(f)){t=0;break}if(!pd(f)){t=0;break}}t=1}}while(0);k=t}else{k=0}}if(k){k=f}else{if((f|0)!=0){qd(f);Jc(f)}k=0}}}j=j|0;y[j>>2]=d;if(!((k|0)==0|(j|0)==0|e>>>0<8|g>>>0>15)&&(y[k>>2]|0)==519686845){t=C[k+88>>2];d=Oc((g<<2)+t+70|0);f=y[k+8>>2];b=g+1|0;t=b>>>0<Pc(t+16|0)>>>0?Oc((b<<2)+t+70|0):f;t>>>0>d>>>0||xc(M.U|0,3705);ed(k,y[k+4>>2]+d|0,t-d|0,j,e,i,g)}if((k|0)!=0&&(y[k>>2]|0)==519686845&&(k|0)!=0){qd(k);Jc(k)}q=h});function ld(b){y[b>>2]=0;y[b+4>>2]=0;y[b+8>>2]=0;v[b+12|0]=0}function kd(b){y[b>>2]=0;y[b+4>>2]=0;y[b+8>>2]=0;v[b+12|0]=0}function jd(b){y[b>>2]=40}function rd(b){var c=b|0,d=y[c>>2];if((d|0)!=0){var e=b+4|0;Jc(d);y[c>>2]=0;y[e>>2]=0;y[b+8>>2]=0}v[b+12|0]=0}function sd(b){var c=b|0,d=y[c>>2];if((d|0)!=0){var e=b+4|0;Jc(d);y[c>>2]=0;y[e>>2]=0;y[b+8>>2]=0}v[b+12|0]=0}function Wc(b){var c=y[b+168>>2];(c|0)!=0&&Mc(c);b=y[b+176>>2];(b|0)!=0&&Lc(b)}function fd(b,c,d,e,g,h,j,i){var f,k,o,m,t,s=q;q=q+24;t=s>>2;var w=s+4;m=w>>2;var d=s+8>>2,u=b+236|0,r=y[u+4>>2],x=b+252|0,p=y[x+4>>2];y[t]=0;y[m]=0;var B=Pc(y[b+88>>2]+17|0),I=e>>>2,S=(B|0)==0;a:do{if(!S){for(var Q=(i|0)==0,H=i-1|0,J=(h&1|0)!=0,K=e<<1,E=b+92|0,da=b+116|0,N=b+188|0,ka=I+1|0,ba=I+2|0,ra=I+3|0,ia=j-1|0,fa=b+140|0,Ga=ia<<4,ta=(g&1|0)!=0,la=0,Aa=1;;){b:do{if(Q){var xa=Aa}else{for(var Y=y[c+(la<<2)>>2],ma=0,ga=Aa;;){if((ma&1|0)==0){var ua=Y,Ba=16,Ca=1,va=j,Z=0}else{ua=Y+Ga|0;Ba=-16;va=Ca=-1;Z=ia}var sa=(ma|0)==(H|0),T=sa&J,ea=(Z|0)==(va|0);c:do{if(ea){var W=ga}else{var ya=sa&J^1,L=ga,O=ua;o=O>>2;for(var qa=Z;;){var na=(L|0)==1?R(E,da)|512:L,L=na&7,na=na>>>3;k=z[M.f+L|0]&255;for(var U=0,P=y[t];;){var F=R(E,fa);y[t]=P+F|0;td(s,r);P=C[t];F=ud(u,P);y[(U<<2>>2)+d]=y[F>>2];U=U+1|0;if(U>>>0>=k>>>0){break}}U=(qa|0)==(ia|0)&ta;k=O>>2;P=T|U;d:do{if(P){for(F=0;;){var oa=F*e|0;f=oa>>2;var wa=O+oa|0,ca=(F|0)==0|ya,V=F<<1,ja=R(E,N);y[m]=y[m]+ja|0;td(w,p);if(U){if(ca){y[wa>>2]=y[((z[(L<<2)+vd+V|0]&255)<<2>>2)+d];V=ud(x,y[m]);y[f+(o+1)]=y[V>>2]}f=R(E,N);y[m]=y[m]+f|0;td(w,p)}else{if(ca){y[wa>>2]=y[((z[(L<<2)+vd+V|0]&255)<<2>>2)+d];wa=ud(x,y[m]);y[f+(o+1)]=y[wa>>2];oa=oa+(O+8)|0;wa=R(E,N);y[m]=y[m]+wa|0;td(w,p);y[oa>>2]=y[((z[(L<<2)+vd+(V|1)|0]&255)<<2>>2)+d];V=ud(x,y[m]);y[f+(o+3)]=y[V>>2]}else{f=R(E,N);y[m]=y[m]+f|0;td(w,p)}}F=F+1|0;if((F|0)==2){break d}}}else{y[k]=y[((z[(L<<2)+vd|0]&255)<<2>>2)+d];F=R(E,N);y[m]=y[m]+F|0;td(w,p);F=ud(x,y[m]);y[o+1]=y[F>>2];y[o+2]=y[((z[(L<<2)+vd+1|0]&255)<<2>>2)+d];F=R(E,N);y[m]=y[m]+F|0;td(w,p);F=ud(x,y[m]);y[o+3]=y[F>>2];y[(I<<2>>2)+k]=y[((z[(L<<2)+vd+2|0]&255)<<2>>2)+d];F=R(E,N);y[m]=y[m]+F|0;td(w,p);F=ud(x,y[m]);y[(ka<<2>>2)+k]=y[F>>2];y[(ba<<2>>2)+k]=y[((z[(L<<2)+vd+3|0]&255)<<2>>2)+d];F=R(E,N);y[m]=y[m]+F|0;td(w,p);F=ud(x,y[m]);y[(ra<<2>>2)+k]=y[F>>2]}}while(0);qa=qa+Ca|0;if((qa|0)==(va|0)){W=na;break c}L=na;O=O+Ba|0;o=O>>2}}}while(0);o=ma+1|0;if((o|0)==(i|0)){xa=W;break b}Y=Y+K|0;ma=o;ga=W}}}while(0);la=la+1|0;if((la|0)==(B|0)){break a}Aa=xa}}}while(0);q=s;return 1}fd.X=1;function qd(b){y[b>>2]=0;sd(b+284|0);sd(b+268|0);rd(b+252|0);rd(b+236|0);var c=b+188|0;Vc(b+212|0);Vc(c);c=b+140|0;Vc(b+164|0);Vc(c);Vc(b+116|0)}qd.X=1;function td(b,c){var d=y[b>>2],e=d-c|0,g=e>>31;y[b>>2]=g&d|e&(g^-1)}function gd(b,c,d,e,g,h,j,i){var f,k,o,m,t,s,w,u,r=q;q=q+48;u=r>>2;var x=r+4;w=x>>2;var p=r+8;s=p>>2;var B=r+12;t=B>>2;m=r+16>>2;var d=r+32>>2,I=b+236|0,S=y[I+4>>2],Q=b+252|0,H=y[Q+4>>2],J=b+268|0,K=y[J+4>>2],E=y[b+88>>2],da=Nc(E+63|0);y[u]=0;y[w]=0;y[s]=0;y[t]=0;var E=Pc(E+17|0),N=(E|0)==0;a:do{if(!N){for(var ka=(i|0)==0,ba=i-1|0,ra=(h&1|0)==0,ia=e<<1,fa=b+92|0,Ga=b+116|0,ta=b+212|0,la=b+188|0,Aa=b+284|0,xa=b+140|0,Y=b+164|0,ma=j-1|0,ga=ma<<5,ua=(g&1|0)!=0,Ba=0,Ca=1;;){b:do{if(ka){var va=Ca}else{for(var Z=y[c+(Ba<<2)>>2],sa=0,T=Ca;;){if((sa&1|0)==0){var ea=Z,W=32,ya=1,L=j,O=0}else{ea=Z+ga|0;W=-32;L=ya=-1;O=ma}var qa=ra|(sa|0)!=(ba|0),na=(O|0)==(L|0);c:do{if(na){var U=T}else{for(var P=T,F=ea,oa=O;;){var wa=(P|0)==1?R(fa,Ga)|512:P,P=wa&7,wa=wa>>>3;o=z[M.f+P|0]&255;for(var ca=0,V=y[s];;){var ja=R(fa,Y);y[s]=V+ja|0;td(p,K);V=C[s];ja=wd(J,V);y[(ca<<2>>2)+d]=A[ja>>1]&65535;ca=ca+1|0;if(ca>>>0>=o>>>0){break}}ca=0;for(V=y[u];;){ja=R(fa,xa);y[u]=V+ja|0;td(r,S);V=C[u];ja=ud(I,V);y[(ca<<2>>2)+m]=y[ja>>2];ca=ca+1|0;if(ca>>>0>=o>>>0){break}}ca=(oa|0)==(ma|0)&ua;V=F;o=V>>2;for(ja=0;;){var Oa=(ja|0)==0|qa;f=ja<<1;k=R(fa,ta);y[t]=y[t]+k|0;td(B,da);k=R(fa,la);y[w]=y[w]+k|0;td(x,H);if(Oa){var hb=V,Ha=z[(P<<2)+vd+f|0]&255;k=wd(Aa,y[t]*3|0)>>1;y[hb>>2]=(A[k]&65535)<<16|y[(Ha<<2>>2)+d];y[o+1]=(A[k+2]&65535)<<16|A[k+1]&65535;y[o+2]=y[(Ha<<2>>2)+m];k=ud(Q,y[w]);y[o+3]=y[k>>2]}k=R(fa,ta);y[t]=y[t]+k|0;td(B,da);k=R(fa,la);y[w]=y[w]+k|0;td(x,H);if(!(ca|Oa^1)){Oa=V+16|0;k=z[(P<<2)+vd+(f|1)|0]&255;f=wd(Aa,y[t]*3|0)>>1;y[Oa>>2]=(A[f]&65535)<<16|y[(k<<2>>2)+d];y[o+5]=(A[f+2]&65535)<<16|A[f+1]&65535;y[o+6]=y[(k<<2>>2)+m];f=ud(Q,y[w]);y[o+7]=y[f>>2]}ja=ja+1|0;if((ja|0)==2){break}V=V+e|0;o=V>>2}oa=oa+ya|0;if((oa|0)==(L|0)){U=wa;break c}P=wa;F=F+W|0}}}while(0);sa=sa+1|0;if((sa|0)==(i|0)){va=U;break b}Z=Z+ia|0;T=U}}}while(0);Ba=Ba+1|0;if((Ba|0)==(E|0)){break a}Ca=va}}}while(0);q=r;return 1}gd.X=1;function hd(b,c,d,e,g,h,j,i){var f,k,o,m,t,s=q;q=q+24;t=s>>2;var w=s+4;m=w>>2;var d=s+8>>2,u=b+268|0,r=y[u+4>>2],x=y[b+88>>2],p=Nc(x+63|0);y[t]=0;y[m]=0;var x=Pc(x+17|0),B=(x|0)==0;a:do{if(!B){for(var I=(i|0)==0,S=i-1|0,Q=(h&1|0)==0,H=e<<1,J=b+92|0,K=b+116|0,E=(g&1|0)==0,da=b+164|0,N=b+212|0,ka=b+284|0,ba=j-1|0,ra=ba<<4,ia=0,fa=1;;){b:do{if(I){var Ga=fa}else{for(var ta=y[c+(ia<<2)>>2],la=0,Aa=fa;;){if((la&1|0)==0){var xa=ta,Y=16,ma=1,ga=j,ua=0}else{xa=ta+ra|0;Y=-16;ga=ma=-1;ua=ba}var Ba=Q|(la|0)!=(S|0),Ca=(ua|0)==(ga|0);c:do{if(Ca){var va=Aa}else{for(var Z=Aa,sa=xa,T=ua;;){var ea=(Z|0)==1?R(J,K)|512:Z,Z=ea&7,ea=ea>>>3,W=z[M.f+Z|0]&255,ya=E|(T|0)!=(ba|0);f=0;for(k=y[t];;){var L=R(J,da);y[t]=k+L|0;td(s,r);k=C[t];L=wd(u,k);y[(f<<2>>2)+d]=A[L>>1]&65535;f=f+1|0;if(f>>>0>=W>>>0){var O=sa;o=O>>2;var qa=0;break}}for(;;){W=O;k=(qa|0)==0|Ba;f=qa<<1;L=R(J,N);y[m]=y[m]+L|0;td(w,p);if(ya){if(k){L=z[(Z<<2)+vd+f|0]&255;k=wd(ka,y[m]*3|0)>>1;y[W>>2]=(A[k]&65535)<<16|y[(L<<2>>2)+d];y[o+1]=(A[k+2]&65535)<<16|A[k+1]&65535;W=O+8|0;k=R(J,N);y[m]=y[m]+k|0;td(w,p);k=z[(Z<<2)+vd+(f|1)|0]&255;f=wd(ka,y[m]*3|0)>>1;y[W>>2]=(A[f]&65535)<<16|y[(k<<2>>2)+d];y[o+3]=(A[f+2]&65535)<<16|A[f+1]&65535}else{W=R(J,N);y[m]=y[m]+W|0;td(w,p)}}else{if(k){k=z[(Z<<2)+vd+f|0]&255;f=wd(ka,y[m]*3|0)>>1;y[W>>2]=(A[f]&65535)<<16|y[(k<<2>>2)+d];y[o+1]=(A[f+2]&65535)<<16|A[f+1]&65535}W=R(J,N);y[m]=y[m]+W|0;td(w,p)}W=qa+1|0;if((W|0)==2){break}O=O+e|0;o=O>>2;qa=W}T=T+ma|0;if((T|0)==(ga|0)){va=ea;break c}Z=ea;sa=sa+Y|0}}}while(0);la=la+1|0;if((la|0)==(i|0)){Ga=va;break b}ta=ta+H|0;Aa=va}}}while(0);ia=ia+1|0;if((ia|0)==(x|0)){break a}fa=Ga}}}while(0);q=s;return 1}hd.X=1;function id(b,c,d,e,g,h,j,i){var f,k,o,m,t,s,w,u,r,x=q;q=q+48;r=x>>2;var p=x+4;u=p>>2;var B=x+8;w=B>>2;var I=x+12;s=I>>2;t=x+16>>2;var d=x+32>>2,S=b+268|0,Q=y[S+4>>2],H=y[b+88>>2],J=Nc(H+63|0);y[r]=0;y[u]=0;y[w]=0;y[s]=0;var H=Pc(H+17|0),K=(H|0)==0;a:do{if(!K){for(var E=(i|0)==0,da=i-1|0,N=(h&1|0)==0,ka=e<<1,ba=b+92|0,ra=b+116|0,ia=b+212|0,fa=b+284|0,Ga=b+164|0,ta=j-1|0,la=ta<<5,Aa=(g&1|0)!=0,xa=0,Y=1;;){b:do{if(E){var ma=Y}else{for(var ga=y[c+(xa<<2)>>2],ua=0,Ba=Y;;){if((ua&1|0)==0){var Ca=ga,va=32,Z=1,sa=j,T=0}else{Ca=ga+la|0;va=-32;sa=Z=-1;T=ta}var ea=N|(ua|0)!=(da|0),W=(T|0)==(sa|0);c:do{if(W){var ya=Ba}else{for(var L=Ba,O=Ca,qa=T;;){var na=(L|0)==1?R(ba,ra)|512:L,L=na&7,na=na>>>3;m=z[M.f+L|0]&255;for(var U=0,P=y[r];;){var F=R(ba,Ga);y[r]=P+F|0;td(x,Q);P=C[r];F=wd(S,P);y[(U<<2>>2)+t]=A[F>>1]&65535;U=U+1|0;if(U>>>0>=m>>>0){break}}U=0;for(P=y[w];;){F=R(ba,Ga);y[w]=P+F|0;td(B,Q);P=C[w];F=wd(S,P);y[(U<<2>>2)+d]=A[F>>1]&65535;U=U+1|0;if(U>>>0>=m>>>0){break}}U=(qa|0)==(ta|0)&Aa;P=O;m=P>>2;for(F=0;;){var oa=(F|0)==0|ea;f=F<<1;k=R(ba,ia);y[u]=y[u]+k|0;td(p,J);k=R(ba,ia);y[s]=y[s]+k|0;td(I,J);if(oa){var wa=P,ca=z[(L<<2)+vd+f|0]&255;o=wd(fa,y[u]*3|0)>>1;k=wd(fa,y[s]*3|0)>>1;y[wa>>2]=(A[o]&65535)<<16|y[(ca<<2>>2)+t];y[m+1]=(A[o+2]&65535)<<16|A[o+1]&65535;y[m+2]=(A[k]&65535)<<16|y[(ca<<2>>2)+d];y[m+3]=(A[k+2]&65535)<<16|A[k+1]&65535}k=R(ba,ia);y[u]=y[u]+k|0;td(p,J);k=R(ba,ia);y[s]=y[s]+k|0;td(I,J);if(!(U|oa^1)){oa=P+16|0;o=z[(L<<2)+vd+(f|1)|0]&255;k=wd(fa,y[u]*3|0)>>1;f=wd(fa,y[s]*3|0)>>1;y[oa>>2]=(A[k]&65535)<<16|y[(o<<2>>2)+t];y[m+5]=(A[k+2]&65535)<<16|A[k+1]&65535;y[m+6]=(A[f]&65535)<<16|y[(o<<2>>2)+d];y[m+7]=(A[f+2]&65535)<<16|A[f+1]&65535}F=F+1|0;if((F|0)==2){break}P=P+e|0;m=P>>2}qa=qa+Z|0;if((qa|0)==(sa|0)){ya=na;break c}L=na;O=O+va|0}}}while(0);ua=ua+1|0;if((ua|0)==(i|0)){ma=ya;break b}ga=ga+ka|0;Ba=ya}}}while(0);xa=xa+1|0;if((xa|0)==(H|0)){break a}Y=ma}}}while(0);q=x;return 1}id.X=1;function wd(b,c){C[b+4>>2]>>>0>c>>>0||xc(M.g|0,904);return(c<<1)+y[b>>2]|0}function ud(b,c){C[b+4>>2]>>>0>c>>>0||xc(M.g|0,904);return(c<<2)+y[b>>2]|0}function xd(b,c){var d;d=(b+4|0)>>2;var e=C[d],g=(e|0)==(c|0);do{if(g){var h=1}else{if(e>>>0<=c>>>0){if(C[b+8>>2]>>>0<c>>>0){h=b;if(Fc(h,c,(e+1|0)==(c|0),2,0)){h=1}else{v[h+12|0]=1;h=0}if(!h){h=0;break}h=y[d]}else{h=e}bc((h<<1)+y[b>>2]|0,0,(c-h|0)<<1)}y[d]=c;h=1}}while(0);return h}function yd(b,c){var d;d=(b+4|0)>>2;var e=C[d],g=(e|0)==(c|0);do{if(g){var h=1}else{if(e>>>0<=c>>>0){if(C[b+8>>2]>>>0<c>>>0){h=b;if(Fc(h,c,(e+1|0)==(c|0),4,0)){h=1}else{v[h+12|0]=1;h=0}if(!h){h=0;break}h=y[d]}else{h=e}bc((h<<2)+y[b>>2]|0,0,(c-h|0)<<2)}y[d]=c;h=1}}while(0);return h}function md(b){var c=q;q=q+48;var d,e=b+88|0,g=Nc(y[e>>2]+39|0),h=b+236|0,j=yd(h,g);do{if(j){var i=b+92|0,f=y[e>>2];if(cd(i,y[b+4>>2]+Qc(f+33|0)|0,Qc(f+36|0))){f=c|0;Uc(f);var k=c+24|0;Uc(k);for(var o=0;;){if(o>>>0>=2){d=9;break}if(!dd(i,c+o*24|0)){var m=0;d=11;break}o=o+1|0}a:do{if(d==9){var t=ud(h,0);if((g|0)==0){m=1}else{for(var s=o=0,w=0,u=0,r=0,x=0,p=0;;){var x=R(i,f)+x&31,r=R(i,k)+r&63,u=R(i,f)+u&31,B=R(i,f)+w|0,w=B&31,s=R(i,k)+s&63,o=R(i,f)+o&31;y[t>>2]=r<<5|x<<11|u|B<<27|s<<21|o<<16;p=p+1|0;if((p|0)==(g|0)){m=1;break a}t=t+4|0}}}}while(0);Vc(k);Vc(f);i=m}else{i=0}}else{i=0}}while(0);q=c;return i}md.X=1;function nd(b){var c=q;q=q+480;var d=c+24,e=c+220,g=c+416,h=y[b+88>>2],j=Nc(h+47|0),i=b+92|0;if(cd(i,y[b+4>>2]+Qc(h+41|0)|0,Qc(h+44|0))){Uc(c);h=dd(i,c);a:do{if(h){for(var f=-3,k=-3,o=0;;){y[d+(o<<2)>>2]=f;y[e+(o<<2)>>2]=k;var f=f+1|0,m=(f|0)>3,k=(m&1)+k|0,o=o+1|0;if((o|0)==49){break}f=m?-3:f}bc(g,0,64);k=b+252|0;if(yd(k,j)){var t=ud(k,0);if((j|0)==0){ba=1}else{for(var k=g|0,o=g+4|0,f=g+8|0,m=g+12|0,s=g+16|0,w=g+20|0,u=g+24|0,r=g+28|0,x=g+32|0,p=g+36|0,B=g+40|0,I=g+44|0,S=g+48|0,Q=g+52|0,H=g+56|0,J=g+60|0,K=0;;){for(var E=0;;){var da=R(i,c),N=E<<1,ka=(N<<2)+g|0;y[ka>>2]=y[ka>>2]+y[d+(da<<2)>>2]&3;N=((N|1)<<2)+g|0;y[N>>2]=y[N>>2]+y[e+(da<<2)>>2]&3;E=E+1|0;if((E|0)==8){break}}y[t>>2]=(z[M.b+y[o>>2]|0]&255)<<2|z[M.b+y[k>>2]|0]&255|(z[M.b+y[f>>2]|0]&255)<<4|(z[M.b+y[m>>2]|0]&255)<<6|(z[M.b+y[s>>2]|0]&255)<<8|(z[M.b+y[w>>2]|0]&255)<<10|(z[M.b+y[u>>2]|0]&255)<<12|(z[M.b+y[r>>2]|0]&255)<<14|(z[M.b+y[x>>2]|0]&255)<<16|(z[M.b+y[p>>2]|0]&255)<<18|(z[M.b+y[B>>2]|0]&255)<<20|(z[M.b+y[I>>2]|0]&255)<<22|(z[M.b+y[S>>2]|0]&255)<<24|(z[M.b+y[Q>>2]|0]&255)<<26|(z[M.b+y[H>>2]|0]&255)<<28|(z[M.b+y[J>>2]|0]&255)<<30;K=K+1|0;if((K|0)==(j|0)){ba=1;break a}t=t+4|0}}}else{var ba=0}}else{ba=0}}while(0);Vc(c);b=ba}else{b=0}q=c;return b}nd.X=1;function od(b){var c=q;q=q+24;var d=y[b+88>>2],e=Nc(d+55|0),g=b+92|0;if(cd(g,y[b+4>>2]+Qc(d+49|0)|0,Qc(d+52|0))){Uc(c);d=dd(g,c);a:do{if(d){var h=b+268|0;if(xd(h,e)){h=wd(h,0);if((e|0)==0){m=1}else{for(var j=0,i=0,f=0;;){var k=R(g,c),o=R(g,c),j=k+j&255,i=o+i&255;gb[h>>1]=(i<<8|j)&65535;f=f+1|0;if((f|0)==(e|0)){m=1;break a}h=h+2|0}}}else{var m=0}}else{m=0}}while(0);Vc(c);b=m}else{b=0}q=c;return b}od.X=1;function pd(b){var c,d=q;q=q+1888;var e=d+24,g=d+924,h=d+1824,j=y[b+88>>2],i=Nc(j+63|0),f=b+92|0;if(cd(f,y[b+4>>2]+Qc(j+57|0)|0,Qc(j+60|0))){Uc(d);j=dd(f,d);a:do{if(j){for(var k=-7,o=-7,m=0;;){y[e+(m<<2)>>2]=k;y[g+(m<<2)>>2]=o;var k=k+1|0,t=(k|0)>7,o=(t&1)+o|0,m=m+1|0;if((m|0)==225){break}k=t?-7:k}bc(h,0,64);o=b+284|0;if(xd(o,i*3|0)){c=wd(o,0);if((i|0)==0){ra=1}else{var o=h|0,m=h+4|0,k=h+8|0,t=h+12|0,s=h+16|0,w=h+20|0,u=h+24|0,r=h+28|0,x=h+32|0,p=h+36|0,B=h+40|0,I=h+44|0,S=h+48|0,Q=h+52|0,H=h+56|0,J=h+60|0,K=c;c=K>>1;for(var E=0;;){for(var da=0;;){var N=R(f,d),ka=da<<1,ba=(ka<<2)+h|0;y[ba>>2]=y[ba>>2]+y[e+(N<<2)>>2]&7;ka=((ka|1)<<2)+h|0;y[ka>>2]=y[ka>>2]+y[g+(N<<2)>>2]&7;da=da+1|0;if((da|0)==8){break}}gb[c]=(z[M.a+y[m>>2]|0]&255)<<3|z[M.a+y[o>>2]|0]&255|(z[M.a+y[k>>2]|0]&255)<<6|(z[M.a+y[t>>2]|0]&255)<<9|(z[M.a+y[s>>2]|0]&255)<<12|(z[M.a+y[w>>2]|0]&255)<<15;gb[c+1]=(z[M.a+y[u>>2]|0]&255)<<2|(z[M.a+y[w>>2]|0]&255)>>>1|(z[M.a+y[r>>2]|0]&255)<<5|(z[M.a+y[x>>2]|0]&255)<<8|(z[M.a+y[p>>2]|0]&255)<<11|(z[M.a+y[B>>2]|0]&255)<<14;gb[c+2]=(z[M.a+y[I>>2]|0]&255)<<1|(z[M.a+y[B>>2]|0]&255)>>>2|(z[M.a+y[S>>2]|0]&255)<<4|(z[M.a+y[Q>>2]|0]&255)<<7|(z[M.a+y[H>>2]|0]&255)<<10|(z[M.a+y[J>>2]|0]&255)<<13;E=E+1|0;if((E|0)==(i|0)){ra=1;break a}K=K+6|0;c=K>>1}}}else{var ra=0}}else{ra=0}}while(0);Vc(d);b=ra}else{b=0}q=d;return b}pd.X=1;function ac(b){if(b>>>0<245){var c=b>>>0<11?16:b+11&-8,d=c>>>3,b=C[X>>2],e=b>>>(d>>>0);if((e&3|0)!=0){var g=(e&1^1)+d|0,c=g<<1,d=(c<<2)+X+40|0,h=(c+2<<2)+X+40|0,e=C[h>>2],c=e+8|0,j=C[c>>2];if((d|0)==(j|0)){y[X>>2]=b&(1<<g^-1)}else{if(j>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[h>>2]=j;y[j+12>>2]=d}b=g<<3;y[e+4>>2]=b|3;b=e+(b|4)|0;y[b>>2]=y[b>>2]|1;g=c;b=38}else{if(c>>>0>C[X+8>>2]>>>0){if((e|0)!=0){var g=2<<d,g=e<<d&(g|-g),d=(g&-g)-1|0,g=d>>>12&16,e=d>>>(g>>>0),d=e>>>5&8,h=e>>>(d>>>0),e=h>>>2&4,j=h>>>(e>>>0),h=j>>>1&2,j=j>>>(h>>>0),i=j>>>1&1,d=(d|g|e|h|i)+(j>>>(i>>>0))|0,g=d<<1,h=(g<<2)+X+40|0,j=(g+2<<2)+X+40|0,e=C[j>>2],g=e+8|0,i=C[g>>2];if((h|0)==(i|0)){y[X>>2]=b&(1<<d^-1)}else{if(i>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[j>>2]=i;y[i+12>>2]=h}h=d<<3;b=h-c|0;y[e+4>>2]=c|3;d=e+c|0;y[e+(c|4)>>2]=b|1;y[e+h>>2]=b;i=C[X+8>>2];if((i|0)!=0){c=y[X+20>>2];h=i>>>2&1073741822;e=(h<<2)+X+40|0;j=C[X>>2];i=1<<(i>>>3);if((j&i|0)==0){y[X>>2]=j|i;j=e;h=(h+2<<2)+X+40|0}else{h=(h+2<<2)+X+40|0;j=C[h>>2];if(j>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}}y[h>>2]=c;y[j+12>>2]=c;y[(c+8|0)>>2]=j;y[(c+12|0)>>2]=e}y[X+8>>2]=b;y[X+20>>2]=d;b=38}else{if((y[X+4>>2]|0)==0){f=c;b=30}else{b=zd(c);if((b|0)==0){f=c;b=30}else{g=b;b=38}}}}else{var f=c,b=30}}}else{if(b>>>0>4294967231){f=-1;b=30}else{b=b+11&-8;if((y[X+4>>2]|0)==0){f=b;b=30}else{c=Ad(b);if((c|0)==0){f=b;b=30}else{g=c;b=38}}}}if(b==30){c=C[X+8>>2];if(f>>>0>c>>>0){b=C[X+12>>2];if(f>>>0<b>>>0){b=b-f|0;y[X+12>>2]=b;c=C[X+24>>2];y[X+24>>2]=c+f|0;y[f+(c+4)>>2]=b|1;y[c+4>>2]=f|3;g=c+8|0}else{g=Bd(f)}}else{g=c-f|0;b=C[X+20>>2];if(g>>>0>15){y[X+20>>2]=b+f|0;y[X+8>>2]=g;y[f+(b+4)>>2]=g|1;y[b+c>>2]=g;y[b+4>>2]=f|3}else{y[X+8>>2]=0;y[X+20>>2]=0;y[b+4>>2]=c|3;f=c+(b+4)|0;y[f>>2]=y[f>>2]|1}g=b+8|0}}return g}Module._malloc=ac;ac.X=1;function zd(b){var c,d,e=y[X+4>>2],g=(e&-e)-1|0,e=g>>>12&16,h=g>>>(e>>>0),g=h>>>5&8;d=h>>>(g>>>0);var h=d>>>2&4,j=d>>>(h>>>0);d=j>>>1&2;var j=j>>>(d>>>0),i=j>>>1&1,e=g=C[X+((g|e|h|d|i)+(j>>>(i>>>0))<<2)+304>>2];d=e>>2;g=(y[g+4>>2]&-8)-b|0;a:for(;;){for(h=e;;){j=y[h+16>>2];if((j|0)==0){h=y[h+20>>2];if((h|0)==0){break a}}else{h=j}j=(y[h+4>>2]&-8)-b|0;if(j>>>0<g>>>0){e=h;d=e>>2;g=j;continue a}}}var j=e,f=C[X+16>>2],i=j>>>0<f>>>0;do{if(!i){var k=j+b|0,h=k;if(j>>>0<k>>>0){var i=C[d+6],k=C[d+3],o=(k|0)==(e|0);do{if(o){c=e+20|0;var m=y[c>>2];if((m|0)==0){c=e+16|0;m=y[c>>2];if((m|0)==0){m=0;c=m>>2;break}}for(;;){var t=m+20|0,s=y[t>>2];if((s|0)==0){t=m+16|0;s=C[t>>2];if((s|0)==0){break}}c=t;m=s}if(c>>>0<f>>>0){$();a("Reached an unreachable!")}y[c>>2]=0}else{c=C[d+2];if(c>>>0<f>>>0){$();a("Reached an unreachable!")}y[c+12>>2]=k;y[k+8>>2]=c;m=k}c=m>>2}while(0);f=(i|0)==0;a:do{if(!f){k=e+28|0;o=(y[k>>2]<<2)+X+304|0;t=(e|0)==(y[o>>2]|0);do{if(t){y[o>>2]=m;if((m|0)!=0){break}y[X+4>>2]=y[X+4>>2]&(1<<y[k>>2]^-1);break a}if(i>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}s=i+16|0;(y[s>>2]|0)==(e|0)?y[s>>2]=m:y[i+20>>2]=m;if((m|0)==0){break a}}while(0);if(m>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+6]=i;k=C[d+4];if((k|0)!=0){if(k>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+4]=k;y[k+24>>2]=m}k=C[d+5];if((k|0)!=0){if(k>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+5]=k;y[k+24>>2]=m}}}while(0);if(g>>>0<16){b=g+b|0;y[d+1]=b|3;b=b+(j+4)|0;y[b>>2]=y[b>>2]|1}else{y[d+1]=b|3;y[b+(j+4)>>2]=g|1;y[j+g+b>>2]=g;f=C[X+8>>2];if((f|0)!=0){b=C[X+20>>2];j=f>>>2&1073741822;d=(j<<2)+X+40|0;i=C[X>>2];f=1<<(f>>>3);if((i&f|0)==0){y[X>>2]=i|f;i=d;j=(j+2<<2)+X+40|0}else{j=(j+2<<2)+X+40|0;i=C[j>>2];if(i>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}}y[j>>2]=b;y[i+12>>2]=b;y[b+8>>2]=i;y[b+12>>2]=d}y[X+8>>2]=g;y[X+20>>2]=h}return e+8|0}}}while(0);$();a("Reached an unreachable!")}zd.X=1;function Bd(b){var c,d;(y[Cd>>2]|0)==0&&Dd();var e=(y[X+440>>2]&4|0)==0;do{if(e){d=y[X+24>>2];if((d|0)==0){d=6}else{d=Ed(d);if((d|0)==0){d=6}else{var g=y[Cd+8>>2],g=b+47-y[X+12>>2]+g&-g;if(g>>>0<2147483647){var h=Fd(g);if((h|0)==(y[d>>2]+y[d+4>>2]|0)){var j=h,i=g;c=h;d=13}else{var f=h,k=g;d=15}}else{d=14}}}if(d==6){d=Fd(0);if((d|0)==-1){d=14}else{var g=y[Cd+8>>2],g=g+(b+47)&-g,h=d,o=y[Cd+4>>2],m=o-1|0,g=(m&h|0)==0?g:g-h+(m+h&-o)|0;if(g>>>0<2147483647){h=Fd(g);if((h|0)==(d|0)){j=d;i=g;c=h;d=13}else{f=h;k=g;d=15}}else{d=14}}}if(d==13){if((j|0)!=-1){var t=i,s=j;d=26;break}f=c;k=i}else{if(d==14){y[X+440>>2]=y[X+440>>2]|4;d=23;break}}d=-k|0;if((f|0)!=-1&k>>>0<2147483647){if(k>>>0<(b+48|0)>>>0){g=y[Cd+8>>2];g=b+47-k+g&-g;if(g>>>0<2147483647){if((Fd(g)|0)==-1){Fd(d);d=22}else{w=g+k|0;d=21}}else{w=k;d=21}}else{var w=k;d=21}}else{w=k;d=21}if(d==21&&(f|0)!=-1){t=w;s=f;d=26;break}y[X+440>>2]=y[X+440>>2]|4}d=23}while(0);if(d==23){e=y[Cd+8>>2];e=e+(b+47)&-e;if(e>>>0<2147483647){e=Fd(e);j=Fd(0);if((j|0)!=-1&(e|0)!=-1&e>>>0<j>>>0){j=j-e|0;if(j>>>0<=(b+40|0)>>>0|(e|0)==-1){d=49}else{t=j;s=e;d=26}}else{d=49}}else{d=49}}a:do{if(d==26){e=y[X+432>>2]+t|0;y[X+432>>2]=e;e>>>0>C[X+436>>2]>>>0&&(y[X+436>>2]=e);e=C[X+24>>2];j=(e|0)==0;b:do{if(j){i=C[X+16>>2];(i|0)==0|s>>>0<i>>>0&&(y[X+16>>2]=s);y[X+444>>2]=s;y[X+448>>2]=t;y[X+456>>2]=0;y[X+36>>2]=y[Cd>>2];y[X+32>>2]=-1;for(i=0;;){c=i<<1;f=(c<<2)+X+40|0;y[X+(c+3<<2)+40>>2]=f;y[X+(c+2<<2)+40>>2]=f;i=i+1|0;if((i|0)==32){break}}Gd(s,t-40|0)}else{f=X+444|0;for(c=f>>2;;){if((f|0)==0){break}i=C[c];f=f+4|0;k=C[f>>2];w=i+k|0;if((s|0)==(w|0)){if((y[c+3]&8|0)!=0){break}c=e;if(!(c>>>0>=i>>>0&c>>>0<w>>>0)){break}y[f>>2]=k+t|0;Gd(y[X+24>>2],y[X+12>>2]+t|0);break b}f=y[c+2];c=f>>2}s>>>0<C[X+16>>2]>>>0&&(y[X+16>>2]=s);c=s+t|0;for(f=X+444|0;;){if((f|0)==0){break}k=f|0;i=C[k>>2];if((i|0)==(c|0)){if((y[f+12>>2]&8|0)!=0){break}y[k>>2]=s;var u=f+4|0;y[u>>2]=y[u>>2]+t|0;u=Hd(s,i,b);d=50;break a}f=y[f+8>>2]}Id(s,t)}}while(0);e=C[X+12>>2];if(e>>>0>b>>>0){u=e-b|0;y[X+12>>2]=u;j=e=C[X+24>>2];y[X+24>>2]=j+b|0;y[b+(j+4)>>2]=u|1;y[e+4>>2]=b|3;u=e+8|0;d=50}else{d=49}}}while(0);if(d==49){y[Jd>>2]=12;u=0}return u}Bd.X=1;function Ad(b){var c,d,e,g,h,j=b>>2,i=-b|0,f=b>>>8;if((f|0)==0){var k=0}else{if(b>>>0>16777215){k=31}else{var o=(f+1048320|0)>>>16&8,m=f<<o,t=(m+520192|0)>>>16&4,s=m<<t,w=(s+245760|0)>>>16&2,u=14-(t|o|w)+(s<<w>>>15)|0,k=b>>>((u+7|0)>>>0)&1|u<<1}}var r=C[X+(k<<2)+304>>2],x=(r|0)==0;a:do{if(x){var p=0,B=i,I=0}else{var S=(k|0)==31?0:25-(k>>>1)|0,Q=0,H=i,J=r;h=J>>2;for(var K=b<<S,E=0;;){var da=y[h+1]&-8,N=da-b|0;if(N>>>0<H>>>0){if((da|0)==(b|0)){p=J;B=N;I=J;break a}var ka=J,ba=N}else{ka=Q;ba=H}var ra=C[h+5],ia=C[((K>>>31<<2)+16>>2)+h],fa=(ra|0)==0|(ra|0)==(ia|0)?E:ra;if((ia|0)==0){p=ka;B=ba;I=fa;break a}Q=ka;H=ba;J=ia;h=J>>2;K=K<<1;E=fa}}}while(0);if((I|0)==0&(p|0)==0){var Ga=2<<k,ta=y[X+4>>2]&(Ga|-Ga);if((ta|0)==0){var la=I}else{var Aa=(ta&-ta)-1|0,xa=Aa>>>12&16,Y=Aa>>>(xa>>>0),ma=Y>>>5&8,ga=Y>>>(ma>>>0),ua=ga>>>2&4,Ba=ga>>>(ua>>>0),Ca=Ba>>>1&2,va=Ba>>>(Ca>>>0),Z=va>>>1&1,la=y[X+((ma|xa|ua|Ca|Z)+(va>>>(Z>>>0))<<2)+304>>2]}}else{la=I}var sa=(la|0)==0;a:do{if(sa){var T=B,ea=p;g=ea>>2}else{var W=la;e=W>>2;for(var ya=B,L=p;;){var O=(y[e+1]&-8)-b|0,qa=O>>>0<ya>>>0,na=qa?O:ya,U=qa?W:L,P=C[e+4];if((P|0)!=0){W=P}else{var F=C[e+5];if((F|0)==0){T=na;ea=U;g=ea>>2;break a}W=F}e=W>>2;ya=na;L=U}}}while(0);var oa=(ea|0)==0;a:do{if(oa){var wa=0}else{if(T>>>0<(y[X+8>>2]-b|0)>>>0){var ca=ea;d=ca>>2;var V=C[X+16>>2],ja=ca>>>0<V>>>0;do{if(!ja){var Oa=ca+b|0,hb=Oa;if(ca>>>0<Oa>>>0){var Ha=C[g+6],Ra=C[g+3],Za=(Ra|0)==(ea|0);do{if(Za){var Ob=ea+20|0,xb=y[Ob>>2];if((xb|0)==0){var Pb=ea+16|0,yb=y[Pb>>2];if((yb|0)==0){var ha=0;c=ha>>2;break}var Ka=Pb,La=yb}else{Ka=Ob;La=xb}for(;;){var ib=La+20|0,zb=y[ib>>2];if((zb|0)!=0){Ka=ib;La=zb}else{var Qb=La+16|0,Rb=C[Qb>>2];if((Rb|0)==0){break}Ka=Qb;La=Rb}}if(Ka>>>0<V>>>0){$();a("Reached an unreachable!")}y[Ka>>2]=0;ha=La}else{var $a=C[g+2];if($a>>>0<V>>>0){$();a("Reached an unreachable!")}y[$a+12>>2]=Ra;y[Ra+8>>2]=$a;ha=Ra}c=ha>>2}while(0);var Sb=(Ha|0)==0;b:do{if(!Sb){var Tb=ea+28|0,cc=(y[Tb>>2]<<2)+X+304|0,Ab=(ea|0)==(y[cc>>2]|0);do{if(Ab){y[cc>>2]=ha;if((ha|0)!=0){break}y[X+4>>2]=y[X+4>>2]&(1<<y[Tb>>2]^-1);break b}if(Ha>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}var bb=Ha+16|0;(y[bb>>2]|0)==(ea|0)?y[bb>>2]=ha:y[Ha+20>>2]=ha;if((ha|0)==0){break b}}while(0);if(ha>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+6]=Ha;var ab=C[g+4];if((ab|0)!=0){if(ab>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+4]=ab;y[ab+24>>2]=ha}var Ia=C[g+5];if((Ia|0)!=0){if(Ia>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+5]=Ia;y[Ia+24>>2]=ha}}}while(0);var Bb=T>>>0<16;b:do{if(Bb){var Cb=T+b|0;y[g+1]=Cb|3;var Db=Cb+(ca+4)|0;y[Db>>2]=y[Db>>2]|1}else{y[g+1]=b|3;y[j+(d+1)]=T|1;y[(T>>2)+d+j]=T;if(T>>>0<256){var ob=T>>>2&1073741822,pb=(ob<<2)+X+40|0,Eb=C[X>>2],Fb=1<<(T>>>3);if((Eb&Fb|0)==0){y[X>>2]=Eb|Fb;var qb=pb,jb=(ob+2<<2)+X+40|0}else{var rb=(ob+2<<2)+X+40|0,Sa=C[rb>>2];if(Sa>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}qb=Sa;jb=rb}y[jb>>2]=hb;y[qb+12>>2]=hb;y[j+(d+2)]=qb;y[j+(d+3)]=pb}else{var Pa=Oa,sb=T>>>8;if((sb|0)==0){var Ta=0}else{if(T>>>0>16777215){Ta=31}else{var Gb=(sb+1048320|0)>>>16&8,Hb=sb<<Gb,Ib=(Hb+520192|0)>>>16&4,tb=Hb<<Ib,Jb=(tb+245760|0)>>>16&2,Kb=14-(Ib|Gb|Jb)+(tb<<Jb>>>15)|0,Ta=T>>>((Kb+7|0)>>>0)&1|Kb<<1}}var Lb=(Ta<<2)+X+304|0;y[j+(d+7)]=Ta;var kb=b+(ca+16)|0;y[j+(d+5)]=0;y[kb>>2]=0;var Ua=y[X+4>>2],Ub=1<<Ta;if((Ua&Ub|0)==0){y[X+4>>2]=Ua|Ub;y[Lb>>2]=Pa;y[j+(d+6)]=Lb;y[j+(d+3)]=Pa;y[j+(d+2)]=Pa}else{for(var Va=T<<((Ta|0)==31?0:25-(Ta>>>1)|0),nb=y[Lb>>2];;){if((y[nb+4>>2]&-8|0)==(T|0)){var Ac=nb+8|0,Xb=C[Ac>>2],oc=C[X+16>>2],Bc=nb>>>0<oc>>>0;do{if(!Bc&&Xb>>>0>=oc>>>0){y[Xb+12>>2]=Pa;y[Ac>>2]=Pa;y[j+(d+2)]=Xb;y[j+(d+3)]=nb;y[j+(d+6)]=0;break b}}while(0);$();a("Reached an unreachable!")}var gc=(Va>>>31<<2)+nb+16|0,Cc=C[gc>>2];if((Cc|0)==0){if(gc>>>0>=C[X+16>>2]>>>0){y[gc>>2]=Pa;y[j+(d+6)]=nb;y[j+(d+3)]=Pa;y[j+(d+2)]=Pa;break b}$();a("Reached an unreachable!")}Va=Va<<1;nb=Cc}}}}}while(0);wa=ea+8|0;break a}}}while(0);$();a("Reached an unreachable!")}wa=0}}while(0);return wa}Ad.X=1;function Kd(b){var c;(y[Cd>>2]|0)==0&&Dd();var d=b>>>0<4294967232;a:do{if(d){var e=C[X+24>>2];if((e|0)!=0){var g=C[X+12>>2],h=g>>>0>(b+40|0)>>>0;do{if(h){var j=C[Cd+8>>2],i=(Math.floor(((-40-b-1+g+j|0)>>>0)/(j>>>0))-1)*j|0,f=Ed(e);if((y[f+12>>2]&8|0)==0){var k=Fd(0);c=(f+4|0)>>2;if((k|0)==(y[f>>2]+y[c]|0)){i=Fd(-(i>>>0>2147483646?-2147483648-j|0:i)|0);j=Fd(0);if((i|0)!=-1&j>>>0<k>>>0){i=k-j|0;if((k|0)!=(j|0)){y[c]=y[c]-i|0;y[X+432>>2]=y[X+432>>2]-i|0;Gd(y[X+24>>2],y[X+12>>2]-i|0);c=(k|0)!=(j|0);break a}}}}}}while(0);C[X+12>>2]>>>0>C[X+28>>2]>>>0&&(y[X+28>>2]=-1)}}c=0}while(0);return c&1}Kd.X=1;function Ld(b){var c,d,e,g,h,j,i=b>>2,f,k=(b|0)==0;a:do{if(!k){var o=b-8|0,m=o,t=C[X+16>>2],s=o>>>0<t>>>0;b:do{if(!s){var w=C[b-4>>2],u=w&3;if((u|0)!=1){var r=w&-8;j=r>>2;var x=b+(r-8)|0,p=x,B=(w&1|0)==0;c:do{if(B){var I=C[o>>2];if((u|0)==0){break a}var S=-8-I|0;h=S>>2;var Q=b+S|0,H=Q,J=I+r|0;if(Q>>>0<t>>>0){break b}if((H|0)==(y[X+20>>2]|0)){g=(b+(r-4)|0)>>2;if((y[g]&3|0)!=3){var K=H;e=K>>2;var E=J;break}y[X+8>>2]=J;y[g]=y[g]&-2;y[h+(i+1)]=J|1;y[x>>2]=J;break a}if(I>>>0<256){var da=C[h+(i+2)],N=C[h+(i+3)];if((da|0)==(N|0)){y[X>>2]=y[X>>2]&(1<<(I>>>3)^-1);K=H;e=K>>2;E=J}else{var ka=((I>>>2&1073741822)<<2)+X+40|0,ba=(da|0)!=(ka|0)&da>>>0<t>>>0;do{if(!ba&&(N|0)==(ka|0)|N>>>0>=t>>>0){y[da+12>>2]=N;y[N+8>>2]=da;K=H;e=K>>2;E=J;break c}}while(0);$();a("Reached an unreachable!")}}else{var ra=Q,ia=C[h+(i+6)],fa=C[h+(i+3)],Ga=(fa|0)==(ra|0);do{if(Ga){var ta=S+(b+20)|0,la=y[ta>>2];if((la|0)==0){var Aa=S+(b+16)|0,xa=y[Aa>>2];if((xa|0)==0){var Y=0;d=Y>>2;break}var ma=Aa,ga=xa}else{ma=ta;ga=la;f=21}for(;;){var ua=ga+20|0,Ba=y[ua>>2];if((Ba|0)!=0){ma=ua;ga=Ba}else{var Ca=ga+16|0,va=C[Ca>>2];if((va|0)==0){break}ma=Ca;ga=va}}if(ma>>>0<t>>>0){$();a("Reached an unreachable!")}y[ma>>2]=0;Y=ga}else{var Z=C[h+(i+2)];if(Z>>>0<t>>>0){$();a("Reached an unreachable!")}y[Z+12>>2]=fa;y[fa+8>>2]=Z;Y=fa}d=Y>>2}while(0);if((ia|0)!=0){var sa=S+(b+28)|0,T=(y[sa>>2]<<2)+X+304|0,ea=(ra|0)==(y[T>>2]|0);do{if(ea){y[T>>2]=Y;if((Y|0)!=0){break}y[X+4>>2]=y[X+4>>2]&(1<<y[sa>>2]^-1);K=H;e=K>>2;E=J;break c}if(ia>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}var W=ia+16|0;(y[W>>2]|0)==(ra|0)?y[W>>2]=Y:y[ia+20>>2]=Y;if((Y|0)==0){K=H;e=K>>2;E=J;break c}}while(0);if(Y>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[d+6]=ia;var ya=C[h+(i+4)];if((ya|0)!=0){if(ya>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[d+4]=ya;y[ya+24>>2]=Y}var L=C[h+(i+5)];if((L|0)!=0){if(L>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[d+5]=L;y[L+24>>2]=Y}}K=H;e=K>>2;E=J}}else{K=m;e=K>>2;E=r}}while(0);var O=K;if(O>>>0<x>>>0){var qa=b+(r-4)|0,na=C[qa>>2];if((na&1|0)!=0){var U=(na&2|0)==0;do{if(U){if((p|0)==(y[X+24>>2]|0)){var P=y[X+12>>2]+E|0;y[X+12>>2]=P;y[X+24>>2]=K;y[e+1]=P|1;if((K|0)==(y[X+20>>2]|0)){y[X+20>>2]=0;y[X+8>>2]=0}if(P>>>0<=C[X+28>>2]>>>0){break a}Kd(0);break a}if((p|0)==(y[X+20>>2]|0)){var F=y[X+8>>2]+E|0;y[X+8>>2]=F;y[X+20>>2]=K;y[e+1]=F|1;y[(O+F|0)>>2]=F;break a}var oa=(na&-8)+E|0,wa=na>>>3,ca=na>>>0<256;c:do{if(ca){var V=C[i+j],ja=C[((r|4)>>2)+i];if((V|0)==(ja|0)){y[X>>2]=y[X>>2]&(1<<wa^-1)}else{var Oa=((na>>>2&1073741822)<<2)+X+40|0;f=(V|0)==(Oa|0)?63:V>>>0<C[X+16>>2]>>>0?66:63;do{if(f==63&&!((ja|0)!=(Oa|0)&&ja>>>0<C[X+16>>2]>>>0)){y[V+12>>2]=ja;y[ja+8>>2]=V;break c}}while(0);$();a("Reached an unreachable!")}}else{var hb=x,Ha=C[j+(i+4)],Ra=C[((r|4)>>2)+i],Za=(Ra|0)==(hb|0);do{if(Za){var Ob=r+(b+12)|0,xb=y[Ob>>2];if((xb|0)==0){var Pb=r+(b+8)|0,yb=y[Pb>>2];if((yb|0)==0){var ha=0;c=ha>>2;break}var Ka=Pb,La=yb}else{Ka=Ob;La=xb;f=73}for(;;){var ib=La+20|0,zb=y[ib>>2];if((zb|0)!=0){Ka=ib;La=zb}else{var Qb=La+16|0,Rb=C[Qb>>2];if((Rb|0)==0){break}Ka=Qb;La=Rb}}if(Ka>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[Ka>>2]=0;ha=La}else{var $a=C[i+j];if($a>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[$a+12>>2]=Ra;y[Ra+8>>2]=$a;ha=Ra}c=ha>>2}while(0);if((Ha|0)!=0){var Sb=r+(b+20)|0,Tb=(y[Sb>>2]<<2)+X+304|0,cc=(hb|0)==(y[Tb>>2]|0);do{if(cc){y[Tb>>2]=ha;if((ha|0)!=0){break}y[X+4>>2]=y[X+4>>2]&(1<<y[Sb>>2]^-1);break c}if(Ha>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}var Ab=Ha+16|0;(y[Ab>>2]|0)==(hb|0)?y[Ab>>2]=ha:y[Ha+20>>2]=ha;if((ha|0)==0){break c}}while(0);if(ha>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+6]=Ha;var bb=C[j+(i+2)];if((bb|0)!=0){if(bb>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+4]=bb;y[bb+24>>2]=ha}var ab=C[j+(i+3)];if((ab|0)!=0){if(ab>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[c+5]=ab;y[ab+24>>2]=ha}}}}while(0);y[e+1]=oa|1;y[O+oa>>2]=oa;if((K|0)!=(y[X+20>>2]|0)){var Ia=oa}else{y[X+8>>2]=oa;break a}}else{y[qa>>2]=na&-2;y[e+1]=E|1;Ia=y[O+E>>2]=E}}while(0);if(Ia>>>0<256){var Bb=Ia>>>2&1073741822,Cb=(Bb<<2)+X+40|0,Db=C[X>>2],ob=1<<(Ia>>>3);if((Db&ob|0)==0){y[X>>2]=Db|ob;var pb=Cb,Eb=(Bb+2<<2)+X+40|0}else{var Fb=(Bb+2<<2)+X+40|0,qb=C[Fb>>2];if(qb>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}pb=qb;Eb=Fb}y[Eb>>2]=K;y[pb+12>>2]=K;y[e+2]=pb;y[e+3]=Cb;break a}var jb=K,rb=Ia>>>8;if((rb|0)==0){var Sa=0}else{if(Ia>>>0>16777215){Sa=31}else{var Pa=(rb+1048320|0)>>>16&8,sb=rb<<Pa,Ta=(sb+520192|0)>>>16&4,Gb=sb<<Ta,Hb=(Gb+245760|0)>>>16&2,Ib=14-(Ta|Pa|Hb)+(Gb<<Hb>>>15)|0,Sa=Ia>>>((Ib+7|0)>>>0)&1|Ib<<1}}var tb=(Sa<<2)+X+304|0;y[e+7]=Sa;y[e+5]=0;y[e+4]=0;var Jb=y[X+4>>2],Kb=1<<Sa,Lb=(Jb&Kb|0)==0;c:do{if(Lb){y[X+4>>2]=Jb|Kb;y[tb>>2]=jb;y[e+6]=tb;y[e+3]=K;y[e+2]=K}else{for(var kb=Ia<<((Sa|0)==31?0:25-(Sa>>>1)|0),Ua=y[tb>>2];;){if((y[Ua+4>>2]&-8|0)==(Ia|0)){var Ub=Ua+8|0,Va=C[Ub>>2],nb=C[X+16>>2],Ac=Ua>>>0<nb>>>0;do{if(!Ac&&Va>>>0>=nb>>>0){y[Va+12>>2]=jb;y[Ub>>2]=jb;y[e+2]=Va;y[e+3]=Ua;y[e+6]=0;break c}}while(0);$();a("Reached an unreachable!")}var Xb=(kb>>>31<<2)+Ua+16|0,oc=C[Xb>>2];if((oc|0)==0){if(Xb>>>0>=C[X+16>>2]>>>0){y[Xb>>2]=jb;y[e+6]=Ua;y[e+3]=K;y[e+2]=K;break c}$();a("Reached an unreachable!")}kb=kb<<1;Ua=oc}}}while(0);var Bc=y[X+32>>2]-1|0;y[X+32>>2]=Bc;if((Bc|0)!=0){break a}var gc=y[X+452>>2],Cc=(gc|0)==0;c:do{if(!Cc){for(var Td=gc;;){var Ud=y[Td+8>>2];if((Ud|0)==0){break c}Td=Ud}}}while(0);y[X+32>>2]=-1;break a}}}}}while(0);$();a("Reached an unreachable!")}}while(0)}Module._free=Ld;Ld.X=1;function Md(b,c){var d,e,g,h=c>>>0>4294967231;a:do{if(h){y[Jd>>2]=12;var j=0}else{g=d=b-8|0;e=(b-4|0)>>2;var i=C[e],f=i&-8,k=f-8|0,o=b+k|0,m=d>>>0<C[X+16>>2]>>>0;do{if(!m){var t=i&3;if((t|0)!=1&(k|0)>-8){d=(b+(f-4)|0)>>2;if((y[d]&1|0)!=0){h=c>>>0<11?16:c+11&-8;if((t|0)==0){var s=0,w,i=y[g+4>>2]&-8;w=h>>>0<256?0:i>>>0>=(h+4|0)>>>0&&(i-h|0)>>>0<=y[Cd+8>>2]<<1>>>0?g:0;g=17}else{if(f>>>0<h>>>0){if((o|0)!=(y[X+24>>2]|0)){g=21}else{d=y[X+12>>2]+f|0;if(d>>>0>h>>>0){s=d-h|0;w=b+(h-8)|0;y[e]=h|i&1|2;y[b+(h-4)>>2]=s|1;y[X+24>>2]=w;y[X+12>>2]=s;s=0;w=g;g=17}else{g=21}}}else{s=f-h|0;if(s>>>0>15){y[e]=h|i&1|2;y[b+(h-4)>>2]=s|3;y[d]=y[d]|1;s=b+h|0}else{s=0}w=g;g=17}}do{if(g==17&&(w|0)!=0){(s|0)!=0&&Ld(s);j=w+8|0;break a}}while(0);g=ac(c);if((g|0)==0){j=0;break a}e=f-((y[e]&3|0)==0?8:4)|0;f=g;i=b;e=e>>>0<c>>>0?e:c;if(e>=20&&i%2==f%2){if(i%4==f%4){for(e=i+e;i%4;){v[f++]=v[i++]}i=i>>2;f=f>>2;for(s=e>>2;i<s;){y[f++]=y[i++]}i=i<<2;for(f=f<<2;i<e;){v[f++]=v[i++]}}else{e=i+e;i%2&&(v[f++]=v[i++]);i=i>>1;f=f>>1;for(s=e>>1;i<s;){gb[f++]=gb[i++]}i=i<<1;f=f<<1;i<e&&(v[f++]=v[i++])}}else{for(;e--;){v[f++]=v[i++]}}Ld(b);j=g;break a}}}}while(0);$();a("Reached an unreachable!")}}while(0);return j}Md.X=1;function Dd(){if((y[Cd>>2]|0)==0){var b=Nd();if((b-1&b|0)==0){y[Cd+8>>2]=b;y[Cd+4>>2]=b;y[Cd+12>>2]=-1;y[Cd+16>>2]=2097152;y[Cd+20>>2]=0;y[X+440>>2]=0;y[Cd>>2]=Math.floor(Date.now()/1e3)&-16^1431655768}else{$();a("Reached an unreachable!")}}}function Od(b){if((b|0)==0){b=0}else{var b=y[b-4>>2],c=b&3,b=(c|0)==1?0:(b&-8)-((c|0)==0?8:4)|0}return b}function Ed(b){var c,d=X+444|0;for(c=d>>2;;){var e=C[c];if(e>>>0<=b>>>0&&(e+y[c+1]|0)>>>0>b>>>0){var g=d;break}c=C[c+2];if((c|0)==0){g=0;break}d=c;c=d>>2}return g}function Gd(b,c){var d=b+8|0,d=(d&7|0)==0?0:-d&7,e=c-d|0;y[X+24>>2]=b+d|0;y[X+12>>2]=e;y[d+(b+4)>>2]=e|1;y[c+(b+4)>>2]=40;y[X+28>>2]=y[Cd+16>>2]}function Hd(b,c,d){var e,g,h,j=c>>2,i=b>>2,f,k=b+8|0,k=(k&7|0)==0?0:-k&7;g=c+8|0;var o=(g&7|0)==0?0:-g&7;h=o>>2;var m=c+o|0,t=k+d|0;g=t>>2;var s=b+t|0,w=m-(b+k)-d|0;y[(k+4>>2)+i]=d|3;d=(m|0)==(y[X+24>>2]|0);a:do{if(d){var u=y[X+12>>2]+w|0;y[X+12>>2]=u;y[X+24>>2]=s;y[g+(i+1)]=u|1}else{if((m|0)==(y[X+20>>2]|0)){u=y[X+8>>2]+w|0;y[X+8>>2]=u;y[X+20>>2]=s;y[g+(i+1)]=u|1;y[(b+u+t|0)>>2]=u}else{var r=C[h+(j+1)];if((r&3|0)==1){var u=r&-8,x=r>>>3,p=r>>>0<256;b:do{if(p){var B=C[((o|8)>>2)+j],I=C[h+(j+3)];if((B|0)==(I|0)){y[X>>2]=y[X>>2]&(1<<x^-1)}else{var S=((r>>>2&1073741822)<<2)+X+40|0;f=(B|0)==(S|0)?15:B>>>0<C[X+16>>2]>>>0?18:15;do{if(f==15&&!((I|0)!=(S|0)&&I>>>0<C[X+16>>2]>>>0)){y[B+12>>2]=I;y[I+8>>2]=B;break b}}while(0);$();a("Reached an unreachable!")}}else{f=m;B=C[((o|24)>>2)+j];I=C[h+(j+3)];S=(I|0)==(f|0);do{if(S){e=o|16;var Q=e+(c+4)|0,H=y[Q>>2];if((H|0)==0){e=c+e|0;H=y[e>>2];if((H|0)==0){H=0;e=H>>2;break}}else{e=Q}for(;;){var Q=H+20|0,J=y[Q>>2];if((J|0)==0){Q=H+16|0;J=C[Q>>2];if((J|0)==0){break}}e=Q;H=J}if(e>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[e>>2]=0}else{e=C[((o|8)>>2)+j];if(e>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[e+12>>2]=I;y[I+8>>2]=e;H=I}e=H>>2}while(0);if((B|0)!=0){I=o+(c+28)|0;S=(y[I>>2]<<2)+X+304|0;Q=(f|0)==(y[S>>2]|0);do{if(Q){y[S>>2]=H;if((H|0)!=0){break}y[X+4>>2]=y[X+4>>2]&(1<<y[I>>2]^-1);break b}if(B>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}J=B+16|0;(y[J>>2]|0)==(f|0)?y[J>>2]=H:y[B+20>>2]=H;if((H|0)==0){break b}}while(0);if(H>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[e+6]=B;f=o|16;B=C[(f>>2)+j];if((B|0)!=0){if(B>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[e+4]=B;y[B+24>>2]=H}f=C[(f+4>>2)+j];if((f|0)!=0){if(f>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}y[e+5]=f;y[f+24>>2]=H}}}}while(0);r=c+(u|o)|0;u=u+w|0}else{r=m;u=w}r=r+4|0;y[r>>2]=y[r>>2]&-2;y[g+(i+1)]=u|1;y[(u>>2)+i+g]=u;if(u>>>0<256){x=u>>>2&1073741822;r=(x<<2)+X+40|0;p=C[X>>2];u=1<<(u>>>3);if((p&u|0)==0){y[X>>2]=p|u;u=r;x=(x+2<<2)+X+40|0}else{x=(x+2<<2)+X+40|0;u=C[x>>2];if(u>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}}y[x>>2]=s;y[u+12>>2]=s;y[g+(i+2)]=u;y[g+(i+3)]=r}else{r=s;p=u>>>8;if((p|0)==0){x=0}else{if(u>>>0>16777215){x=31}else{x=(p+1048320|0)>>>16&8;f=p<<x;p=(f+520192|0)>>>16&4;f=f<<p;B=(f+245760|0)>>>16&2;x=14-(p|x|B)+(f<<B>>>15)|0;x=u>>>((x+7|0)>>>0)&1|x<<1}}p=(x<<2)+X+304|0;y[g+(i+7)]=x;f=t+(b+16)|0;y[g+(i+5)]=0;y[f>>2]=0;f=y[X+4>>2];B=1<<x;if((f&B|0)==0){y[X+4>>2]=f|B;y[p>>2]=r;y[g+(i+6)]=p;y[g+(i+3)]=r;y[g+(i+2)]=r}else{x=u<<((x|0)==31?0:25-(x>>>1)|0);for(p=y[p>>2];;){if((y[p+4>>2]&-8|0)==(u|0)){f=p+8|0;B=C[f>>2];I=C[X+16>>2];S=p>>>0<I>>>0;do{if(!S&&B>>>0>=I>>>0){y[B+12>>2]=r;y[f>>2]=r;y[g+(i+2)]=B;y[g+(i+3)]=p;y[g+(i+6)]=0;break a}}while(0);$();a("Reached an unreachable!")}f=(x>>>31<<2)+p+16|0;B=C[f>>2];if((B|0)==0){if(f>>>0>=C[X+16>>2]>>>0){y[f>>2]=r;y[g+(i+6)]=p;y[g+(i+3)]=r;y[g+(i+2)]=r;break a}$();a("Reached an unreachable!")}x=x<<1;p=B}}}}}}while(0);return b+(k|8)|0}Hd.X=1;function Id(b,c){var d,e,g=C[X+24>>2];e=g>>2;var h=Ed(g),j=y[h>>2];d=y[h+4>>2];var h=j+d|0,i=j+(d-39)|0,j=j+(d-47)+((i&7|0)==0?0:-i&7)|0,j=j>>>0<(g+16|0)>>>0?g:j,i=j+8|0;d=i>>2;Gd(b,c-40|0);y[(j+4|0)>>2]=27;y[d]=y[X+444>>2];y[d+1]=y[X+448>>2];y[d+2]=y[X+452>>2];y[d+3]=y[X+456>>2];y[X+444>>2]=b;y[X+448>>2]=c;y[X+456>>2]=0;y[X+452>>2]=i;d=j+28|0;y[d>>2]=7;i=(j+32|0)>>>0<h>>>0;a:do{if(i){for(var f=d;;){var k=f+4|0;y[k>>2]=7;if((f+8|0)>>>0>=h>>>0){break a}f=k}}}while(0);h=(j|0)==(g|0);a:do{if(!h){d=j-g|0;i=g+d|0;f=d+(g+4)|0;y[f>>2]=y[f>>2]&-2;y[e+1]=d|1;y[i>>2]=d;if(d>>>0<256){f=d>>>2&1073741822;i=(f<<2)+X+40|0;k=C[X>>2];d=1<<(d>>>3);if((k&d|0)==0){y[X>>2]=k|d;d=i;f=(f+2<<2)+X+40|0}else{f=(f+2<<2)+X+40|0;d=C[f>>2];if(d>>>0<C[X+16>>2]>>>0){$();a("Reached an unreachable!")}}y[f>>2]=g;y[d+12>>2]=g;y[e+2]=d;y[e+3]=i}else{i=g;k=d>>>8;if((k|0)==0){f=0}else{if(d>>>0>16777215){f=31}else{var f=(k+1048320|0)>>>16&8,o=k<<f,k=(o+520192|0)>>>16&4,o=o<<k,m=(o+245760|0)>>>16&2,f=14-(k|f|m)+(o<<m>>>15)|0,f=d>>>((f+7|0)>>>0)&1|f<<1}}k=(f<<2)+X+304|0;y[e+7]=f;y[e+5]=0;y[e+4]=0;o=y[X+4>>2];m=1<<f;if((o&m|0)==0){y[X+4>>2]=o|m;y[k>>2]=i;y[e+6]=k;y[e+3]=g;y[e+2]=g}else{f=d<<((f|0)==31?0:25-(f>>>1)|0);for(k=y[k>>2];;){if((y[k+4>>2]&-8|0)==(d|0)){var o=k+8|0,m=C[o>>2],t=C[X+16>>2],s=k>>>0<t>>>0;do{if(!s&&m>>>0>=t>>>0){y[m+12>>2]=i;y[o>>2]=i;y[e+2]=m;y[e+3]=k;y[e+6]=0;break a}}while(0);$();a("Reached an unreachable!")}o=(f>>>31<<2)+k+16|0;m=C[o>>2];if((m|0)==0){if(o>>>0>=C[X+16>>2]>>>0){y[o>>2]=i;y[e+6]=k;y[e+3]=g;y[e+2]=g;break a}$();a("Reached an unreachable!")}f=f<<1;k=m}}}}}while(0)}Id.X=1;function yc(b,c){function d(b){var d;if(b==="double"){d=(Zb[0]=y[c+g>>2],Zb[1]=y[c+g+4>>2],Yb[0])}else{if(b=="i64"){d=[y[c+g>>2],y[c+g+4>>2]]}else{b="i32";d=y[c+g>>2]}}g=g+Math.max(Wa(b),Xa);return d}for(var e=b,g=0,h=[],j,i;;){var f=e;j=v[e];if(j===0){break}i=v[e+1];if(j==37){var k=n,o=n,m=n,t=n;a:for(;;){switch(i){case 43:k=l;break;case 45:o=l;break;case 35:m=l;break;case 48:if(t){break a}else{t=l;break};default:break a}e++;i=v[e+1]}var s=0;if(i==42){s=d("i32");e++;i=v[e+1]}else{for(;i>=48&&i<=57;){s=s*10+(i-48);e++;i=v[e+1]}}var w=n;if(i==46){var u=0,w=l;e++;i=v[e+1];if(i==42){u=d("i32");e++}else{for(;;){i=v[e+1];if(i<48||i>57){break}u=u*10+(i-48);e++}}i=v[e+1]}else{u=6}var r;switch(String.fromCharCode(i)){case"h":i=v[e+2];if(i==104){e++;r=1}else{r=2}break;case"l":i=v[e+2];if(i==108){e++;r=8}else{r=4}break;case"L":case"q":case"j":r=8;break;case"z":case"t":case"I":r=4;break;default:r=pa}r&&e++;i=v[e+1];if(["d","i","u","o","x","X","p"].indexOf(String.fromCharCode(i))!=-1){f=i==100||i==105;r=r||4;j=d("i"+r*8);r==8&&(j=i==117?(j[0]>>>0)+(j[1]>>>0)*4294967296:(j[0]>>>0)+(j[1]|0)*4294967296);r<=4&&(j=(f?vc:uc)(j&Math.pow(256,r)-1,r*8));var x=Math.abs(j),p,f="";if(i==100||i==105){p=vc(j,8*r).toString(10)}else{if(i==117){p=uc(j,8*r).toString(10);j=Math.abs(j)}else{if(i==111){p=(m?"0":"")+x.toString(8)}else{if(i==120||i==88){f=m?"0x":"";if(j<0){j=-j;p=(x-1).toString(16);m=[];for(x=0;x<p.length;x++){m.push((15-parseInt(p[x],16)).toString(16))}for(p=m.join("");p.length<r*2;){p="f"+p}}else{p=x.toString(16)}if(i==88){f=f.toUpperCase();p=p.toUpperCase()}}else{if(i==112){if(x===0){p="(nil)"}else{f="0x";p=x.toString(16)}}}}}}if(w){for(;p.length<u;){p="0"+p}}for(k&&(f=j<0?"-"+f:"+"+f);f.length+p.length<s;){o?p=p+" ":t?p="0"+p:f=" "+f}p=f+p;p.split("").forEach((function(b){h.push(b.charCodeAt(0))}))}else{if(["f","F","e","E","g","G"].indexOf(String.fromCharCode(i))!=-1){j=d("double");if(isNaN(j)){p="nan";t=n}else{if(isFinite(j)){w=n;r=Math.min(u,20);if(i==103||i==71){w=l;u=u||1;r=parseInt(j.toExponential(r).split("e")[1],10);if(u>r&&r>=-4){i=(i==103?"f":"F").charCodeAt(0);u=u-(r+1)}else{i=(i==103?"e":"E").charCodeAt(0);u--}r=Math.min(u,20)}if(i==101||i==69){p=j.toExponential(r);/[eE][-+]\d$/.test(p)&&(p=p.slice(0,-1)+"0"+p.slice(-1))}else{if(i==102||i==70){p=j.toFixed(r)}}f=p.split("e");if(w&&!m){for(;f[0].length>1&&f[0].indexOf(".")!=-1&&(f[0].slice(-1)=="0"||f[0].slice(-1)==".");){f[0]=f[0].slice(0,-1)}}else{for(m&&p.indexOf(".")==-1&&(f[0]=f[0]+".");u>r++;){f[0]=f[0]+"0"}}p=f[0]+(f.length>1?"e"+f[1]:"");i==69&&(p=p.toUpperCase());k&&j>=0&&(p="+"+p)}else{p=(j<0?"-":"")+"inf";t=n}}for(;p.length<s;){p=o?p+" ":t&&(p[0]=="-"||p[0]=="+")?p[0]+"0"+p.slice(1):(t?"0":" ")+p}i<97&&(p=p.toUpperCase());p.split("").forEach((function(b){h.push(b.charCodeAt(0))}))}else{if(i==115){if(k=d("i8*")){k=tc(k);w&&k.length>u&&(k=k.slice(0,u))}else{k=jc("(null)",l)}if(!o){for(;k.length<s--;){h.push(32)}}h=h.concat(k);if(o){for(;k.length<s--;){h.push(32)}}}else{if(i==99){for(o&&h.push(d("i8"));--s>0;){h.push(32)}o||h.push(d("i8"))}else{if(i==110){o=d("i32*");y[o>>2]=h.length}else{if(i==37){h.push(j)}else{for(x=f;x<e+2;x++){h.push(v[x])}}}}}}}e=e+2}else{h.push(j);e=e+1}}return h}var Pd=13,Qd=9,Rd=22,Sd=5,Vd=21,Wd=6;function Xd(b){Jd||(Jd=G([0],"i32",D));y[Jd>>2]=b}var Jd,Yd=0,zc=0,Zd=0,$d=2,Ec=[pa],ae=l;function be(b,c){if(typeof b!=="string"){return pa}c===aa&&(c="/");b&&b[0]=="/"&&(c="");for(var d=(c+"/"+b).split("/").reverse(),e=[""];d.length;){var g=d.pop();g==""||g=="."||(g==".."?e.length>1&&e.pop():e.push(g))}return e.length==1?"/":e.join("/")}function ce(b,c,d){var e={ga:n,l:n,error:0,name:pa,path:pa,object:pa,v:n,z:pa,w:pa},b=be(b);if(b=="/"){e.ga=l;e.l=e.v=l;e.name="/";e.path=e.z="/";e.object=e.w=de}else{if(b!==pa){for(var d=d||0,b=b.slice(1).split("/"),g=de,h=[""];b.length;){if(b.length==1&&g.d){e.v=l;e.z=h.length==1?"/":h.join("/");e.w=g;e.name=b[0]}var j=b.shift();if(g.d){if(g.A){if(!g.c.hasOwnProperty(j)){e.error=2;break}}else{e.error=Pd;break}}else{e.error=20;break}g=g.c[j];if(g.link&&!(c&&b.length==0)){if(d>40){e.error=40;break}e=be(g.link,h.join("/"));return ce([e].concat(b).join("/"),c,d+1)}h.push(j);if(b.length==0){e.l=l;e.path=h.join("/");e.object=g}}}}return e}function ee(b){fe();b=ce(b,aa);if(b.l){return b.object}Xd(b.error);return pa}function ge(b,c,d,e,g){b||(b="/");typeof b==="string"&&(b=ee(b));if(!b){Xd(Pd);a(Error("Parent path must exist."))}if(!b.d){Xd(20);a(Error("Parent must be a folder."))}if(!b.write&&!ae){Xd(Pd);a(Error("Parent folder must be writeable."))}if(!c||c=="."||c==".."){Xd(2);a(Error("Name must not be empty."))}if(b.c.hasOwnProperty(c)){Xd(17);a(Error("Can't overwrite object."))}b.c[c]={A:e===aa?l:e,write:g===aa?n:g,timestamp:Date.now(),fa:$d++};for(var h in d){d.hasOwnProperty(h)&&(b.c[c][h]=d[h])}return b.c[c]}function he(b,c){return ge(b,c,{d:l,h:n,c:{}},l,l)}function ie(){var b="dev/shm/tmp",c=ee("/");c===pa&&a(Error("Invalid parent."));for(b=b.split("/").reverse();b.length;){var d=b.pop();if(d){c.c.hasOwnProperty(d)||he(c,d);c=c.c[d]}}}function je(b,c,d,e){!d&&!e&&a(Error("A device must have at least one callback defined."));var g={h:l,input:d,e:e};g.d=n;return ge(b,c,g,Boolean(d),Boolean(e))}function fe(){de||(de={A:l,write:l,d:l,h:n,timestamp:Date.now(),fa:1,c:{}})}function ke(){var b,c,d;function e(b){if(b===pa||b===10){c.j(c.buffer.join(""));c.buffer=[]}else{c.buffer.push(String.fromCharCode(b))}}Ya(!le,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");le=l;fe();b=b||Module.stdin;c=c||Module.stdout;d=d||Module.stderr;var g=l,h=l,j=l;if(!b){g=n;b=(function(){if(!b.k||!b.k.length){var c;typeof window!="undefined"&&typeof window.prompt=="function"?c=window.prompt("Input: "):typeof readline=="function"&&(c=readline());c||(c="");b.k=jc(c+"\n",l)}return b.k.shift()})}if(!c){h=n;c=e}if(!c.j){c.j=print}if(!c.buffer){c.buffer=[]}if(!d){j=n;d=e}if(!d.j){d.j=print}if(!d.buffer){d.buffer=[]}he("/","tmp");var i=he("/","dev"),f=je(i,"stdin",b),k=je(i,"stdout",pa,c);d=je(i,"stderr",pa,d);je(i,"tty",b,c);Ec[1]={path:"/dev/stdin",object:f,position:0,t:l,i:n,s:n,u:!g,error:n,q:n,B:[]};Ec[2]={path:"/dev/stdout",object:k,position:0,t:n,i:l,s:n,u:!h,error:n,q:n,B:[]};Ec[3]={path:"/dev/stderr",object:d,position:0,t:n,i:l,s:n,u:!j,error:n,q:n,B:[]};Yd=G([1],"void*",D);zc=G([2],"void*",D);Zd=G([3],"void*",D);ie();Ec[Yd]=Ec[1];Ec[zc]=Ec[2];Ec[Zd]=Ec[3];G([G([0,0,0,0,Yd,0,0,0,zc,0,0,0,Zd,0,0,0],"void*",D)],"void*",D)}var le,de;function Dc(b,c,d){var e=Ec[b];if(e){if(e.i){if(d<0){Xd(Rd);return-1}if(e.object.h){if(e.object.e){for(var g=0;g<d;g++){try{e.object.e(v[c+g])}catch(h){Xd(Sd);return-1}}e.object.timestamp=Date.now();return g}Xd(Wd);return-1}g=e.position;b=Ec[b];if(!b||b.object.h){Xd(Qd);c=-1}else{if(b.i){if(b.object.d){Xd(Vd);c=-1}else{if(d<0||g<0){Xd(Rd);c=-1}else{for(var j=b.object.c;j.length<g;){j.push(0)}for(var i=0;i<d;i++){j[g+i]=z[c+i]}b.object.timestamp=Date.now();c=i}}}else{Xd(Pd);c=-1}}if(c!=-1){e.position=e.position+c}return c}Xd(Pd);return-1}Xd(Qd);return-1}function bc(b,c,d){if(d>=20){for(d=b+d;b%4;){v[b++]=c}c<0&&(c=c+256);for(var b=b>>2,e=d>>2,g=c|c<<8|c<<16|c<<24;b<e;){y[b++]=g}for(b=b<<2;b<d;){v[b++]=c}}else{for(;d--;){v[b++]=c}}}function $(){a("ABORT: undefined, at "+Error().stack)}function Nd(){switch(8){case 8:return ec;case 54:case 56:case 21:case 61:case 63:case 22:case 67:case 23:case 24:case 25:case 26:case 27:case 69:case 28:case 101:case 70:case 71:case 29:case 30:case 199:case 75:case 76:case 32:case 43:case 44:case 80:case 46:case 47:case 45:case 48:case 49:case 42:case 82:case 33:case 7:case 108:case 109:case 107:case 112:case 119:case 121:return 200809;case 13:case 104:case 94:case 95:case 34:case 35:case 77:case 81:case 83:case 84:case 85:case 86:case 87:case 88:case 89:case 90:case 91:case 94:case 95:case 110:case 111:case 113:case 114:case 115:case 116:case 117:case 118:case 120:case 40:case 16:case 79:case 19:return-1;case 92:case 93:case 5:case 72:case 6:case 74:case 92:case 93:case 96:case 97:case 98:case 99:case 102:case 103:case 105:return 1;case 38:case 66:case 50:case 51:case 4:return 1024;case 15:case 64:case 41:return 32;case 55:case 37:case 17:return 2147483647;case 18:case 1:return 47839;case 59:case 57:return 99;case 68:case 58:return 2048;case 0:return 2097152;case 3:return 65536;case 14:return 32768;case 73:return 32767;case 39:return 16384;case 60:return 1e3;case 106:return 700;case 52:return 256;case 62:return 255;case 2:return 100;case 65:return 64;case 36:return 20;case 100:return 16;case 20:return 6;case 53:return 4}Xd(Rd);return-1}function Fd(b){if(!me){eb=eb+4095>>12<<12;me=l}var c=eb;b!=0&&db(b);return c}var me;pc.unshift({r:(function(){ae=n;le||ke()})});qc.push({r:(function(){if(le){Ec[2]&&Ec[2].object.e.buffer.length>0&&Ec[2].object.e(10);Ec[3]&&Ec[3].object.e.buffer.length>0&&Ec[3].object.e(10)}})});Xd(0);G(12,"void*",D);Module.ea=(function(b){function c(){for(var b=0;b<3;b++){e.push(0)}}var d=b.length+1,e=[G(jc("/bin/this.program"),"i8",D)];c();for(var g=0;g<d-1;g=g+1){e.push(G(jc(b[g]),"i8",D));c()}e.push(0);e=G(e,"i32",D);return _main(d,e,0)});var Gc,Hc,vd,X,Cd,ne,oe,pe,qe,re;M.G=G([37,115,40,37,117,41,58,32,65,115,115,101,114,116,105,111,110,32,102,97,105,108,117,114,101,58,32,34,37,115,34,10,0],"i8",D);M.H=G([109,95,115,105,122,101,32,60,61,32,109,95,99,97,112,97,99,105,116,121,0],"i8",D);M.O=G([46,47,99,114,110,95,100,101,99,111,109,112,46,104,0],"i8",D);M.T=G([109,105,110,95,110,101,119,95,99,97,112,97,99,105,116,121,32,60,32,40,48,120,55,70,70,70,48,48,48,48,85,32,47,32,101,108,101,109,101,110,116,95,115,105,122,101,41,0],"i8",D);M.Y=G([110,101,119,95,99,97,112,97,99,105,116,121,32,38,38,32,40,110,101,119,95,99,97,112,97,99,105,116,121,32,62,32,109,95,99,97,112,97,99,105,116,121,41,0],"i8",D);M.Z=G([110,117,109,95,99,111,100,101,115,91,99,93,0],"i8",D);M.$=G([115,111,114,116,101,100,95,112,111,115,32,60,32,116,111,116,97,108,95,117,115,101,100,95,115,121,109,115,0],"i8",D);M.aa=G([112,67,111,100,101,115,105,122,101,115,91,115,121,109,95,105,110,100,101,120,93,32,61,61,32,99,111,100,101,115,105,122,101,0],"i8",D);M.ba=G([116,32,60,32,40,49,85,32,60,60,32,116,97,98,108,101,95,98,105,116,115,41,0],"i8",D);M.ca=G([109,95,108,111,111,107,117,112,91,116,93,32,61,61,32,99,85,73,78,84,51,50,95,77,65,88,0],"i8",D);Gc=G([2],["i8* (i8*, i32, i32*, i1, i8*)*",0,0,0,0],D);G([4],["i32 (i8*, i8*)*",0,0,0,0],D);Hc=G(1,"i8*",D);M.m=G([99,114,110,100,95,109,97,108,108,111,99,58,32,115,105,122,101,32,116,111,111,32,98,105,103,0],"i8",D);M.I=G([99,114,110,100,95,109,97,108,108,111,99,58,32,111,117,116,32,111,102,32,109,101,109,111,114,121,0],"i8",D);M.n=G([40,40,117,105,110,116,51,50,41,112,95,110,101,119,32,38,32,40,67,82,78,68,95,77,73,78,95,65,76,76,79,67,95,65,76,73,71,78,77,69,78,84,32,45,32,49,41,41,32,61,61,32,48,0],"i8",D);M.J=G([99,114,110,100,95,114,101,97,108,108,111,99,58,32,98,97,100,32,112,116,114,0],"i8",D);M.K=G([99,114,110,100,95,102,114,101,101,58,32,98,97,100,32,112,116,114,0],"i8",D);M.ma=G([99,114,110,100,95,109,115,105,122,101,58,32,98,97,100,32,112,116,114,0],"i8",D);G([1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,256,0,0,0,512,0,0,0,1024,0,0,0,2048,0,0,0,4096,0,0,0,8192,0,0,0,16384,0,0,0,32768,0,0,0,65536,0,0,0,131072,0,0,0,262144,0,0,0,524288,0,0,0,1048576,0,0,0,2097152,0,0,0,4194304,0,0,0,8388608,0,0,0,16777216,0,0,0,33554432,0,0,0,67108864,0,0,0,134217728,0,0,0,268435456,0,0,0,536870912,0,0,0,1073741824,0,0,0,-2147483648,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0],D);M.M=G([102,97,108,115,101,0],"i8",D);M.na=G([99,114,110,100,95,118,97,108,105,100,97,116,101,95,102,105,108,101,40,38,110,101,119,95,104,101,97,100,101,114,44,32,97,99,116,117,97,108,95,98,97,115,101,95,100,97,116,97,95,115,105,122,101,44,32,78,85,76,76,41,0],"i8",D);M.oa=G([40,116,111,116,97,108,95,115,121,109,115,32,62,61,32,49,41,32,38,38,32,40,116,111,116,97,108,95,115,121,109,115,32,60,61,32,112,114,101,102,105,120,95,99,111,100,105,110,103,58,58,99,77,97,120,83,117,112,112,111,114,116,101,100,83,121,109,115,41,32,38,38,32,40,99,111,100,101,95,115,105,122,101,95,108,105,109,105,116,32,62,61,32,49,41,0],"i8",D);M.N=G([40,116,111,116,97,108,95,115,121,109,115,32,62,61,32,49,41,32,38,38,32,40,116,111,116,97,108,95,115,121,109,115,32,60,61,32,112,114,101,102,105,120,95,99,111,100,105,110,103,58,58,99,77,97,120,83,117,112,112,111,114,116,101,100,83,121,109,115,41,0],"i8",D);M.C=G([17,18,19,20,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,16],"i8",D);M.o=G([48,0],"i8",D);M.P=G([110,117,109,95,98,105,116,115,32,60,61,32,51,50,85,0],"i8",D);M.Q=G([109,95,98,105,116,95,99,111,117,110,116,32,60,61,32,99,66,105,116,66,117,102,83,105,122,101,0],"i8",D);M.R=G([116,32,33,61,32,99,85,73,78,84,51,50,95,77,65,88,0],"i8",D);M.S=G([109,111,100,101,108,46,109,95,99,111,100,101,95,115,105,122,101,115,91,115,121,109,93,32,61,61,32,108,101,110,0],"i8",D);G([1,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,3,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,7,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,3,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,6,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,7,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,8,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0],D);G([0,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,3,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,8,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,7,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0,8,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0],D);M.ha=G([0,3,1,2],"i8",D);M.b=G([0,2,3,1],"i8",D);M.ia=G([0,7,1,2,3,4,5,6],"i8",D);M.a=G([0,2,3,4,5,6,7,1],"i8",D);M.ja=G([1,0,5,4,3,2,6,7],"i8",D);M.ka=G([1,0,7,6,5,4,3,2],"i8",D);M.qa=G([105,110,100,101,120,32,60,32,50,0],"i8",D);M.ra=G([40,108,111,32,60,61,32,48,120,70,70,70,70,85,41,32,38,38,32,40,104,105,32,60,61,32,48,120,70,70,70,70,85,41,0],"i8",D);M.sa=G([40,120,32,60,32,99,68,88,84,66,108,111,99,107,83,105,122,101,41,32,38,38,32,40,121,32,60,32,99,68,88,84,66,108,111,99,107,83,105,122,101,41,0],"i8",D);M.ta=G([118,97,108,117,101,32,60,61,32,48,120,70,70,0],"i8",D);M.ua=G([118,97,108,117,101,32,60,61,32,48,120,70,0],"i8",D);M.va=G([40,108,111,32,60,61,32,48,120,70,70,41,32,38,38,32,40,104,105,32,60,61,32,48,120,70,70,41,0],"i8",D);M.g=G([105,32,60,32,109,95,115,105,122,101,0],"i8",D);M.p=G([110,117,109,32,38,38,32,40,110,117,109,32,61,61,32,126,110,117,109,95,99,104,101,99,107,41,0],"i8",D);M.f=G([1,2,2,3,3,3,3,4],"i8",D);vd=G([0,0,0,0,0,0,1,1,0,1,0,1,0,0,1,2,1,2,0,0,0,1,0,2,1,0,2,0,0,1,2,3],"i8",D);M.U=G([110,101,120,116,95,108,101,118,101,108,95,111,102,115,32,62,32,99,117,114,95,108,101,118,101,108,95,111,102,115,0],"i8",D);M.W=G([40,108,101,110,32,62,61,32,49,41,32,38,38,32,40,108,101,110,32,60,61,32,99,77,97,120,69,120,112,101,99,116,101,100,67,111,100,101,83,105,122,101,41,0],"i8",D);X=G(468,["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0,"*",0,0,0,"i32",0,0,0],D);Cd=G(24,"i32",D);M.wa=G([109,97,120,32,115,121,115,116,101,109,32,98,121,116,101,115,32,61,32,37,49,48,108,117,10,0],"i8",D);M.la=G([115,121,115,116,101,109,32,98,121,116,101,115,32,32,32,32,32,61,32,37,49,48,108,117,10,0],"i8",D);M.pa=G([105,110,32,117,115,101,32,98,121,116,101,115,32,32,32,32,32,61,32,37,49,48,108,117,10,0],"i8",D);G([0],"i8",D);G(1,"void ()*",D);ne=G([0,0,0,0,0,0,0,0,6,0,0,0,8,0,0,0,10,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],D);G(1,"void*",D);M.V=G([115,116,100,58,58,98,97,100,95,97,108,108,111,99,0],"i8",D);oe=G([0,0,0,0,0,0,0,0,12,0,0,0,14,0,0,0,16,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],D);G(1,"void*",D);M.L=G([98,97,100,95,97,114,114,97,121,95,110,101,119,95,108,101,110,103,116,104,0],"i8",D);M.F=G([83,116,57,98,97,100,95,97,108,108,111,99,0],"i8",D);qe=G(12,"*",D);M.D=G([83,116,50,48,98,97,100,95,97,114,114,97,121,95,110,101,119,95,108,101,110,103,116,104,0],"i8",D);re=G(12,"*",D);y[ne+4>>2]=qe;y[oe+4>>2]=re;pe=G([2,0,0,0,0],["i8*",0,0,0,0],D);y[qe>>2]=pe+8|0;y[qe+4>>2]=M.F|0;y[qe+8>>2]=aa;y[re>>2]=pe+8|0;y[re+4>>2]=M.D|0;y[re+8>>2]=qe;dc=[0,0,(function(b,c,d,e){if((b|0)==0){b=ac(c);(d|0)!=0&&(y[d>>2]=(b|0)==0?0:Od(b));d=b}else{if((c|0)==0){Ld(b);(d|0)!=0&&(y[d>>2]=0);d=0}else{var g=(b|0)==0?ac(c):Md(b,c),h=(g|0)!=0,j=h?g:b;if(h|e^1){b=j}else{g=(b|0)==0?ac(c):Md(b,c);(g|0)==0?g=0:b=g}(d|0)!=0&&(y[d>>2]=Od(b));d=g}}return d}),0,(function(b){return(b|0)==0?0:Od(b)}),0,(function(b){aa(b|0)}),0,(function(b){aa(b|0);(b|0)!=0&&Ld(b)}),0,(function(){return M.V|0}),0,(function(b){aa(b|0)}),0,(function(b){aa(b|0);(b|0)!=0&&Ld(b)}),0,(function(){return M.L|0}),0];Module.FUNCTION_TABLE=dc;function se(b){b=b||Module.arguments;nc(pc);var c=pa;if(Module._main){c=Module.ea(b);Module.noExitRuntime||nc(qc)}return c}Module.run=se;Module.preRun&&Module.preRun();Module.noInitialRun||se();Module.postRun&&Module.postRun()
+
+ //===
+
+onmessage = function(msg) {
+ var start = Date.now();
+ var data = deCrunch(new Uint8Array(msg.data.data), msg.data.filename);
+ postMessage({
+ filename: msg.data.filename,
+ data: data,
+ callbackID: msg.data.callbackID,
+ time: Date.now() - start
+ });
+};
+
diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js
index aac21e87..fd8036bf 100644
--- a/tools/eliminator/eliminator-test-output.js
+++ b/tools/eliminator/eliminator-test-output.js
@@ -126,4 +126,2724 @@ function llvm3_1() {
run($j_0 / 2);
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1"]
+function _inflate($strm, $flush) {
+ var __stackBase__ = STACKTOP;
+ STACKTOP += 4;
+ var __label__;
+ var $hbuf = __stackBase__;
+ var $cmp = ($strm | 0) == 0;
+ $_$2 : do {
+ if ($cmp) {
+ var $retval_0 = -2;
+ } else {
+ var $0 = HEAPU32[($strm + 28 | 0) >> 2];
+ if (($0 | 0) == 0) {
+ var $retval_0 = -2;
+ break;
+ }
+ var $next_out = $strm + 12 | 0;
+ var $1 = HEAP32[$next_out >> 2];
+ if (($1 | 0) == 0) {
+ var $retval_0 = -2;
+ break;
+ }
+ var $next_in = $strm | 0;
+ var $2 = HEAP32[$next_in >> 2];
+ if (($2 | 0) == 0) {
+ if (!((HEAP32[($strm + 4 | 0) >> 2] | 0) == 0)) {
+ var $retval_0 = -2;
+ break;
+ }
+ }
+ var $4 = $0;
+ var $mode = $0 | 0;
+ var $5 = HEAP32[$mode >> 2];
+ if (($5 | 0) == 11) {
+ HEAP32[$mode >> 2] = 12;
+ var $8 = HEAP32[$next_out >> 2];
+ var $7 = HEAP32[$next_in >> 2];
+ var $6 = 12;
+ } else {
+ var $8 = $1;
+ var $7 = $2;
+ var $6 = $5;
+ }
+ var $6;
+ var $7;
+ var $8;
+ var $avail_out = $strm + 16 | 0;
+ var $9 = HEAP32[$avail_out >> 2];
+ var $avail_in15 = $strm + 4 | 0;
+ var $10 = HEAPU32[$avail_in15 >> 2];
+ var $11 = $0 + 56 | 0;
+ var $13 = $0 + 60 | 0;
+ var $15 = $0 + 8 | 0;
+ var $16 = $0 + 24 | 0;
+ var $arrayidx = $hbuf | 0;
+ var $arrayidx40 = $hbuf + 1 | 0;
+ var $17 = $0 + 16 | 0;
+ var $18 = $0 + 32 | 0;
+ var $msg = $strm + 24 | 0;
+ var $19 = $0 + 36 | 0;
+ var $20 = $0 + 20 | 0;
+ var $adler = $strm + 48 | 0;
+ var $21 = $0 + 64 | 0;
+ var $22 = $0 + 12 | 0;
+ var $23 = ($flush - 5 | 0) >>> 0 < 2;
+ var $24 = $0 + 4 | 0;
+ var $cmp660 = ($flush | 0) == 6;
+ var $25 = $0 + 7108 | 0;
+ var $26 = $0 + 84 | 0;
+ var $27 = $0 + 76 | 0;
+ var $28 = $0 + 72 | 0;
+ var $29 = $0 + 7112 | 0;
+ var $30 = $0 + 68 | 0;
+ var $31 = $0 + 44 | 0;
+ var $32 = $0 + 7104 | 0;
+ var $33 = $0 + 48 | 0;
+ var $34 = $0 + 52 | 0;
+ var $35 = $0 + 40 | 0;
+ var $total_out = $strm + 20 | 0;
+ var $36 = $0 + 28 | 0;
+ var $arrayidx199 = $hbuf + 2 | 0;
+ var $arrayidx202 = $hbuf + 3 | 0;
+ var $37 = $0 + 96 | 0;
+ var $38 = $0 + 100 | 0;
+ var $39 = $0 + 92 | 0;
+ var $40 = $0 + 104 | 0;
+ var $lens = $0 + 112 | 0;
+ var $41 = $lens;
+ var $next861 = $0 + 108 | 0;
+ var $42 = $next861;
+ var $43 = $next861 | 0;
+ var $arraydecay860_c = $0 + 1328 | 0;
+ var $44 = $0 + 76 | 0;
+ var $arraydecay864 = $lens;
+ var $arraydecay867 = $0 + 752 | 0;
+ var $45 = $0 + 624 | 0;
+ var $46 = $0 + 80 | 0;
+ var $47 = $0 + 88 | 0;
+ var $48 = $0 + 80 | 0;
+ var $ret_0 = 0;
+ var $next_0 = $7;
+ var $put_0 = $8;
+ var $have_0 = $10;
+ var $left_0 = $9;
+ var $hold_0 = HEAP32[$11 >> 2];
+ var $bits_0 = HEAP32[$13 >> 2];
+ var $out_0 = $9;
+ var $49 = $6;
+ $_$12 : while (1) {
+ var $49;
+ var $out_0;
+ var $bits_0;
+ var $hold_0;
+ var $left_0;
+ var $have_0;
+ var $put_0;
+ var $next_0;
+ var $ret_0;
+ $_$14 : do {
+ if (($49 | 0) == 0) {
+ var $50 = HEAPU32[$15 >> 2];
+ if (($50 | 0) == 0) {
+ HEAP32[$mode >> 2] = 12;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_0;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_0;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_0;
+ var $bits_0_be = $bits_0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $next_1 = $next_0;
+ var $have_1 = $have_0;
+ var $hold_1 = $hold_0;
+ var $bits_1 = $bits_0;
+ while (1) {
+ var $bits_1;
+ var $hold_1;
+ var $have_1;
+ var $next_1;
+ if (!($bits_1 >>> 0 < 16)) {
+ break;
+ }
+ if (($have_1 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_1;
+ var $have_58 = 0;
+ var $hold_54 = $hold_1;
+ var $bits_54 = $bits_1;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add = ((HEAPU8[$next_1] & 255) << $bits_1) + $hold_1 | 0;
+ var $next_1 = $next_1 + 1 | 0;
+ var $have_1 = $have_1 - 1 | 0;
+ var $hold_1 = $add;
+ var $bits_1 = $bits_1 + 8 | 0;
+ }
+ if (($50 & 2 | 0) != 0 & ($hold_1 | 0) == 35615) {
+ var $call = _crc32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call;
+ HEAP8[$arrayidx] = 31;
+ HEAP8[$arrayidx40] = -117;
+ var $52 = HEAP32[$16 >> 2];
+ var $call42 = _crc32($52, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call42;
+ HEAP32[$mode >> 2] = 1;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = 0;
+ var $bits_0_be = 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$17 >> 2] = 0;
+ var $53 = HEAP32[$18 >> 2];
+ if (($53 | 0) == 0) {
+ var $54 = $50;
+ } else {
+ var $done = $53 + 48 | 0;
+ HEAP32[$done >> 2] = -1;
+ var $54 = HEAP32[$15 >> 2];
+ }
+ var $54;
+ var $tobool56 = ($54 & 1 | 0) == 0;
+ do {
+ if (!$tobool56) {
+ if (!((((($hold_1 << 8 & 65280) + ($hold_1 >>> 8) | 0) >>> 0) % 31 | 0) == 0)) {
+ break;
+ }
+ if (($hold_1 & 15 | 0) == 8) {
+ var $shr74 = $hold_1 >>> 4;
+ var $sub = $bits_1 - 4 | 0;
+ var $add77 = ($shr74 & 15) + 8 | 0;
+ var $55 = HEAPU32[$19 >> 2];
+ var $cmp78 = ($55 | 0) == 0;
+ do {
+ if (!$cmp78) {
+ if (!($add77 >>> 0 > $55 >>> 0)) {
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str3100 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr74;
+ var $bits_0_be = $sub;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ HEAP32[$19 >> 2] = $add77;
+ } while (0);
+ HEAP32[$20 >> 2] = 1 << $add77;
+ var $call91 = _adler32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call91;
+ HEAP32[$adler >> 2] = $call91;
+ HEAP32[$mode >> 2] = $hold_1 >>> 12 & 2 ^ 11;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = 0;
+ var $bits_0_be = 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str299 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_1;
+ var $bits_0_be = $bits_1;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ } while (0);
+ HEAP32[$msg >> 2] = STRING_TABLE.__str198 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_1;
+ var $bits_0_be = $bits_1;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 1) {
+ var $next_2 = $next_0;
+ var $have_2 = $have_0;
+ var $hold_2 = $hold_0;
+ var $bits_2 = $bits_0;
+ while (1) {
+ var $bits_2;
+ var $hold_2;
+ var $have_2;
+ var $next_2;
+ if (!($bits_2 >>> 0 < 16)) {
+ break;
+ }
+ if (($have_2 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_2;
+ var $have_58 = 0;
+ var $hold_54 = $hold_2;
+ var $bits_54 = $bits_2;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add113 = ((HEAPU8[$next_2] & 255) << $bits_2) + $hold_2 | 0;
+ var $next_2 = $next_2 + 1 | 0;
+ var $have_2 = $have_2 - 1 | 0;
+ var $hold_2 = $add113;
+ var $bits_2 = $bits_2 + 8 | 0;
+ }
+ HEAP32[$17 >> 2] = $hold_2;
+ if (!(($hold_2 & 255 | 0) == 8)) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str299 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_2;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_2;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_2;
+ var $bits_0_be = $bits_2;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ if (($hold_2 & 57344 | 0) == 0) {
+ var $59 = HEAPU32[$18 >> 2];
+ if (($59 | 0) == 0) {
+ var $60 = $hold_2;
+ } else {
+ HEAP32[($59 | 0) >> 2] = $hold_2 >>> 8 & 1;
+ var $60 = HEAP32[$17 >> 2];
+ }
+ var $60;
+ if (!(($60 & 512 | 0) == 0)) {
+ HEAP8[$arrayidx] = $hold_2 & 255;
+ HEAP8[$arrayidx40] = $hold_2 >>> 8 & 255;
+ var $61 = HEAP32[$16 >> 2];
+ var $call154 = _crc32($61, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call154;
+ }
+ HEAP32[$mode >> 2] = 2;
+ var $next_3 = $next_2;
+ var $have_3 = $have_2;
+ var $hold_3 = 0;
+ var $bits_3 = 0;
+ __label__ = 44;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str4101 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_2;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_2;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_2;
+ var $bits_0_be = $bits_2;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 2) {
+ var $next_3 = $next_0;
+ var $have_3 = $have_0;
+ var $hold_3 = $hold_0;
+ var $bits_3 = $bits_0;
+ __label__ = 44;
+ } else if (($49 | 0) == 3) {
+ var $next_4 = $next_0;
+ var $have_4 = $have_0;
+ var $hold_4 = $hold_0;
+ var $bits_4 = $bits_0;
+ __label__ = 52;
+ } else if (($49 | 0) == 4) {
+ var $next_5 = $next_0;
+ var $have_5 = $have_0;
+ var $hold_5 = $hold_0;
+ var $bits_5 = $bits_0;
+ __label__ = 60;
+ } else if (($49 | 0) == 5) {
+ var $next_8 = $next_0;
+ var $have_8 = $have_0;
+ var $hold_8 = $hold_0;
+ var $bits_8 = $bits_0;
+ __label__ = 71;
+ } else if (($49 | 0) == 6) {
+ var $next_11 = $next_0;
+ var $have_11 = $have_0;
+ var $hold_9 = $hold_0;
+ var $bits_9 = $bits_0;
+ var $89 = HEAP32[$17 >> 2];
+ __label__ = 81;
+ break;
+ } else if (($49 | 0) == 7) {
+ var $next_13 = $next_0;
+ var $have_13 = $have_0;
+ var $hold_10 = $hold_0;
+ var $bits_10 = $bits_0;
+ __label__ = 94;
+ } else if (($49 | 0) == 8) {
+ var $next_15 = $next_0;
+ var $have_15 = $have_0;
+ var $hold_11 = $hold_0;
+ var $bits_11 = $bits_0;
+ __label__ = 107;
+ } else if (($49 | 0) == 9) {
+ var $next_18 = $next_0;
+ var $have_18 = $have_0;
+ var $hold_14 = $hold_0;
+ var $bits_14 = $bits_0;
+ while (1) {
+ var $bits_14;
+ var $hold_14;
+ var $have_18;
+ var $next_18;
+ if (!($bits_14 >>> 0 < 32)) {
+ break;
+ }
+ if (($have_18 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_18;
+ var $have_58 = 0;
+ var $hold_54 = $hold_14;
+ var $bits_54 = $bits_14;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add564 = ((HEAPU8[$next_18] & 255) << $bits_14) + $hold_14 | 0;
+ var $next_18 = $next_18 + 1 | 0;
+ var $have_18 = $have_18 - 1 | 0;
+ var $hold_14 = $add564;
+ var $bits_14 = $bits_14 + 8 | 0;
+ }
+ var $add581 = _llvm_bswap_i32($hold_14);
+ HEAP32[$16 >> 2] = $add581;
+ HEAP32[$adler >> 2] = $add581;
+ HEAP32[$mode >> 2] = 10;
+ var $next_19 = $next_18;
+ var $have_19 = $have_18;
+ var $hold_15 = 0;
+ var $bits_15 = 0;
+ __label__ = 120;
+ break;
+ } else if (($49 | 0) == 10) {
+ var $next_19 = $next_0;
+ var $have_19 = $have_0;
+ var $hold_15 = $hold_0;
+ var $bits_15 = $bits_0;
+ __label__ = 120;
+ } else if (($49 | 0) == 11) {
+ var $next_20 = $next_0;
+ var $have_20 = $have_0;
+ var $hold_16 = $hold_0;
+ var $bits_16 = $bits_0;
+ __label__ = 123;
+ } else if (($49 | 0) == 12) {
+ var $next_21 = $next_0;
+ var $have_21 = $have_0;
+ var $hold_17 = $hold_0;
+ var $bits_17 = $bits_0;
+ __label__ = 124;
+ } else if (($49 | 0) == 13) {
+ var $and681 = $bits_0 & 7;
+ var $next_23 = $next_0;
+ var $have_23 = $have_0;
+ var $hold_19 = $hold_0 >>> ($and681 >>> 0);
+ var $bits_19 = $bits_0 - $and681 | 0;
+ while (1) {
+ var $bits_19;
+ var $hold_19;
+ var $have_23;
+ var $next_23;
+ if (!($bits_19 >>> 0 < 32)) {
+ break;
+ }
+ if (($have_23 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_23;
+ var $have_58 = 0;
+ var $hold_54 = $hold_19;
+ var $bits_54 = $bits_19;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add701 = ((HEAPU8[$next_23] & 255) << $bits_19) + $hold_19 | 0;
+ var $next_23 = $next_23 + 1 | 0;
+ var $have_23 = $have_23 - 1 | 0;
+ var $hold_19 = $add701;
+ var $bits_19 = $bits_19 + 8 | 0;
+ }
+ var $and708 = $hold_19 & 65535;
+ if (!(($and708 | 0) == ($hold_19 >>> 16 ^ 65535 | 0))) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str7104 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_23;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_23;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_19;
+ var $bits_0_be = $bits_19;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$21 >> 2] = $and708;
+ HEAP32[$mode >> 2] = 14;
+ if ($cmp660) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_23;
+ var $have_58 = $have_23;
+ var $hold_54 = 0;
+ var $bits_54 = 0;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_24 = $next_23;
+ var $have_24 = $have_23;
+ var $hold_20 = 0;
+ var $bits_20 = 0;
+ __label__ = 143;
+ break;
+ } else if (($49 | 0) == 14) {
+ var $next_24 = $next_0;
+ var $have_24 = $have_0;
+ var $hold_20 = $hold_0;
+ var $bits_20 = $bits_0;
+ __label__ = 143;
+ } else if (($49 | 0) == 15) {
+ var $next_25 = $next_0;
+ var $have_25 = $have_0;
+ var $hold_21 = $hold_0;
+ var $bits_21 = $bits_0;
+ __label__ = 144;
+ } else if (($49 | 0) == 16) {
+ var $next_26 = $next_0;
+ var $have_26 = $have_0;
+ var $hold_22 = $hold_0;
+ var $bits_22 = $bits_0;
+ while (1) {
+ var $bits_22;
+ var $hold_22;
+ var $have_26;
+ var $next_26;
+ if (!($bits_22 >>> 0 < 14)) {
+ break;
+ }
+ if (($have_26 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_26;
+ var $have_58 = 0;
+ var $hold_54 = $hold_22;
+ var $bits_54 = $bits_22;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add767 = ((HEAPU8[$next_26] & 255) << $bits_22) + $hold_22 | 0;
+ var $next_26 = $next_26 + 1 | 0;
+ var $have_26 = $have_26 - 1 | 0;
+ var $hold_22 = $add767;
+ var $bits_22 = $bits_22 + 8 | 0;
+ }
+ var $add775 = ($hold_22 & 31) + 257 | 0;
+ HEAP32[$37 >> 2] = $add775;
+ var $add782 = ($hold_22 >>> 5 & 31) + 1 | 0;
+ HEAP32[$38 >> 2] = $add782;
+ HEAP32[$39 >> 2] = ($hold_22 >>> 10 & 15) + 4 | 0;
+ var $shr791 = $hold_22 >>> 14;
+ var $sub792 = $bits_22 - 14 | 0;
+ if ($add775 >>> 0 > 286 | $add782 >>> 0 > 30) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str8105 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_26;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_26;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr791;
+ var $bits_0_be = $sub792;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$40 >> 2] = 0;
+ HEAP32[$mode >> 2] = 17;
+ var $next_27 = $next_26;
+ var $have_27 = $have_26;
+ var $hold_23 = $shr791;
+ var $bits_23 = $sub792;
+ __label__ = 154;
+ break;
+ } else if (($49 | 0) == 17) {
+ var $next_27 = $next_0;
+ var $have_27 = $have_0;
+ var $hold_23 = $hold_0;
+ var $bits_23 = $bits_0;
+ __label__ = 154;
+ } else if (($49 | 0) == 18) {
+ var $ret_1_ph = $ret_0;
+ var $next_29_ph = $next_0;
+ var $have_29_ph = $have_0;
+ var $hold_25_ph = $hold_0;
+ var $bits_25_ph = $bits_0;
+ __label__ = 164;
+ } else if (($49 | 0) == 19) {
+ var $ret_2 = $ret_0;
+ var $next_37 = $next_0;
+ var $have_37 = $have_0;
+ var $hold_33 = $hold_0;
+ var $bits_33 = $bits_0;
+ __label__ = 205;
+ } else if (($49 | 0) == 20) {
+ var $ret_3 = $ret_0;
+ var $next_38 = $next_0;
+ var $have_38 = $have_0;
+ var $hold_34 = $hold_0;
+ var $bits_34 = $bits_0;
+ __label__ = 206;
+ } else if (($49 | 0) == 21) {
+ var $ret_4 = $ret_0;
+ var $next_42 = $next_0;
+ var $have_42 = $have_0;
+ var $hold_38 = $hold_0;
+ var $bits_38 = $bits_0;
+ var $156 = HEAP32[$28 >> 2];
+ __label__ = 227;
+ break;
+ } else if (($49 | 0) == 22) {
+ var $ret_5_ph = $ret_0;
+ var $next_45_ph = $next_0;
+ var $have_45_ph = $have_0;
+ var $hold_41_ph = $hold_0;
+ var $bits_41_ph = $bits_0;
+ __label__ = 234;
+ } else if (($49 | 0) == 23) {
+ var $ret_6 = $ret_0;
+ var $next_48 = $next_0;
+ var $have_48 = $have_0;
+ var $hold_44 = $hold_0;
+ var $bits_44 = $bits_0;
+ var $167 = HEAP32[$28 >> 2];
+ __label__ = 248;
+ break;
+ } else if (($49 | 0) == 24) {
+ var $ret_7 = $ret_0;
+ var $next_51 = $next_0;
+ var $have_51 = $have_0;
+ var $hold_47 = $hold_0;
+ var $bits_47 = $bits_0;
+ __label__ = 254;
+ } else if (($49 | 0) == 25) {
+ if (($left_0 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ HEAP8[$put_0] = HEAP32[$21 >> 2] & 255;
+ HEAP32[$mode >> 2] = 20;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_0;
+ var $put_0_be = $put_0 + 1 | 0;
+ var $have_0_be = $have_0;
+ var $left_0_be = $left_0 - 1 | 0;
+ var $hold_0_be = $hold_0;
+ var $bits_0_be = $bits_0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 26) {
+ var $tobool1626 = (HEAP32[$15 >> 2] | 0) == 0;
+ do {
+ if (!$tobool1626) {
+ var $next_52 = $next_0;
+ var $have_52 = $have_0;
+ var $hold_48 = $hold_0;
+ var $bits_48 = $bits_0;
+ while (1) {
+ var $bits_48;
+ var $hold_48;
+ var $have_52;
+ var $next_52;
+ if (!($bits_48 >>> 0 < 32)) {
+ break;
+ }
+ if (($have_52 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_52;
+ var $have_58 = 0;
+ var $hold_54 = $hold_48;
+ var $bits_54 = $bits_48;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1642 = ((HEAPU8[$next_52] & 255) << $bits_48) + $hold_48 | 0;
+ var $next_52 = $next_52 + 1 | 0;
+ var $have_52 = $have_52 - 1 | 0;
+ var $hold_48 = $add1642;
+ var $bits_48 = $bits_48 + 8 | 0;
+ }
+ var $sub1649 = $out_0 - $left_0 | 0;
+ var $add1650 = HEAP32[$total_out >> 2] + $sub1649 | 0;
+ HEAP32[$total_out >> 2] = $add1650;
+ var $add1651 = HEAP32[$36 >> 2] + $sub1649 | 0;
+ HEAP32[$36 >> 2] = $add1651;
+ if (!(($out_0 | 0) == ($left_0 | 0))) {
+ var $192 = HEAP32[$16 >> 2];
+ var $add_ptr1659 = $put_0 + (-$sub1649 | 0) | 0;
+ if ((HEAP32[$17 >> 2] | 0) == 0) {
+ var $call1665 = _adler32($192, $add_ptr1659, $sub1649);
+ var $cond1667 = $call1665;
+ } else {
+ var $call1660 = _crc32($192, $add_ptr1659, $sub1649);
+ var $cond1667 = $call1660;
+ }
+ var $cond1667;
+ HEAP32[$16 >> 2] = $cond1667;
+ HEAP32[$adler >> 2] = $cond1667;
+ }
+ if ((HEAP32[$17 >> 2] | 0) == 0) {
+ var $add1685 = _llvm_bswap_i32($hold_48);
+ var $cond1687 = $add1685;
+ } else {
+ var $cond1687 = $hold_48;
+ }
+ var $cond1687;
+ if (($cond1687 | 0) == (HEAP32[$16 >> 2] | 0)) {
+ var $next_53 = $next_52;
+ var $have_53 = $have_52;
+ var $hold_49 = 0;
+ var $bits_49 = 0;
+ var $out_1 = $left_0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str17114 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_52;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_52;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_48;
+ var $bits_0_be = $bits_48;
+ var $out_0_be = $left_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ var $next_53 = $next_0;
+ var $have_53 = $have_0;
+ var $hold_49 = $hold_0;
+ var $bits_49 = $bits_0;
+ var $out_1 = $out_0;
+ } while (0);
+ var $out_1;
+ var $bits_49;
+ var $hold_49;
+ var $have_53;
+ var $next_53;
+ HEAP32[$mode >> 2] = 27;
+ var $next_54 = $next_53;
+ var $have_54 = $have_53;
+ var $hold_50 = $hold_49;
+ var $bits_50 = $bits_49;
+ var $out_2 = $out_1;
+ __label__ = 286;
+ break;
+ } else if (($49 | 0) == 27) {
+ var $next_54 = $next_0;
+ var $have_54 = $have_0;
+ var $hold_50 = $hold_0;
+ var $bits_50 = $bits_0;
+ var $out_2 = $out_0;
+ __label__ = 286;
+ } else if (($49 | 0) == 28) {
+ var $ret_8 = 1;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($49 | 0) == 29) {
+ var $ret_8 = -3;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($49 | 0) == 30) {
+ var $retval_0 = -4;
+ break $_$2;
+ } else {
+ var $retval_0 = -2;
+ break $_$2;
+ }
+ } while (0);
+ $_$106 : do {
+ if (__label__ == 44) {
+ while (1) {
+ var $bits_3;
+ var $hold_3;
+ var $have_3;
+ var $next_3;
+ if (!($bits_3 >>> 0 < 32)) {
+ break;
+ }
+ if (($have_3 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_3;
+ var $have_58 = 0;
+ var $hold_54 = $hold_3;
+ var $bits_54 = $bits_3;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add176 = ((HEAPU8[$next_3] & 255) << $bits_3) + $hold_3 | 0;
+ var $next_3 = $next_3 + 1 | 0;
+ var $have_3 = $have_3 - 1 | 0;
+ var $hold_3 = $add176;
+ var $bits_3 = $bits_3 + 8 | 0;
+ }
+ var $63 = HEAP32[$18 >> 2];
+ if (!(($63 | 0) == 0)) {
+ var $time = $63 + 4 | 0;
+ HEAP32[$time >> 2] = $hold_3;
+ }
+ if (!((HEAP32[$17 >> 2] & 512 | 0) == 0)) {
+ HEAP8[$arrayidx] = $hold_3 & 255;
+ HEAP8[$arrayidx40] = $hold_3 >>> 8 & 255;
+ HEAP8[$arrayidx199] = $hold_3 >>> 16 & 255;
+ HEAP8[$arrayidx202] = $hold_3 >>> 24 & 255;
+ var $65 = HEAP32[$16 >> 2];
+ var $call205 = _crc32($65, $arrayidx, 4);
+ HEAP32[$16 >> 2] = $call205;
+ }
+ HEAP32[$mode >> 2] = 3;
+ var $next_4 = $next_3;
+ var $have_4 = $have_3;
+ var $hold_4 = 0;
+ var $bits_4 = 0;
+ __label__ = 52;
+ break;
+ } else if (__label__ == 120) {
+ var $bits_15;
+ var $hold_15;
+ var $have_19;
+ var $next_19;
+ if ((HEAP32[$22 >> 2] | 0) == 0) {
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_19;
+ HEAP32[$avail_in15 >> 2] = $have_19;
+ HEAP32[$11 >> 2] = $hold_15;
+ HEAP32[$13 >> 2] = $bits_15;
+ var $retval_0 = 2;
+ break $_$2;
+ }
+ var $call602 = _adler32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call602;
+ HEAP32[$adler >> 2] = $call602;
+ HEAP32[$mode >> 2] = 11;
+ var $next_20 = $next_19;
+ var $have_20 = $have_19;
+ var $hold_16 = $hold_15;
+ var $bits_16 = $bits_15;
+ __label__ = 123;
+ break;
+ } else if (__label__ == 143) {
+ var $bits_20;
+ var $hold_20;
+ var $have_24;
+ var $next_24;
+ HEAP32[$mode >> 2] = 15;
+ var $next_25 = $next_24;
+ var $have_25 = $have_24;
+ var $hold_21 = $hold_20;
+ var $bits_21 = $bits_20;
+ __label__ = 144;
+ break;
+ } else if (__label__ == 154) {
+ while (1) {
+ var $bits_23;
+ var $hold_23;
+ var $have_27;
+ var $next_27;
+ var $122 = HEAPU32[$40 >> 2];
+ if (!($122 >>> 0 < HEAPU32[$39 >> 2] >>> 0)) {
+ break;
+ }
+ var $next_28 = $next_27;
+ var $have_28 = $have_27;
+ var $hold_24 = $hold_23;
+ var $bits_24 = $bits_23;
+ while (1) {
+ var $bits_24;
+ var $hold_24;
+ var $have_28;
+ var $next_28;
+ if (!($bits_24 >>> 0 < 3)) {
+ break;
+ }
+ if (($have_28 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_28;
+ var $have_58 = 0;
+ var $hold_54 = $hold_24;
+ var $bits_54 = $bits_24;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add829 = ((HEAPU8[$next_28] & 255) << $bits_24) + $hold_24 | 0;
+ var $next_28 = $next_28 + 1 | 0;
+ var $have_28 = $have_28 - 1 | 0;
+ var $hold_24 = $add829;
+ var $bits_24 = $bits_24 + 8 | 0;
+ }
+ HEAP32[$40 >> 2] = $122 + 1 | 0;
+ HEAP16[($41 + ((HEAPU16[(_inflate_order + ($122 << 1) | 0) >> 1] & 65535) << 1) | 0) >> 1] = $hold_24 & 65535 & 7;
+ var $next_27 = $next_28;
+ var $have_27 = $have_28;
+ var $hold_23 = $hold_24 >>> 3;
+ var $bits_23 = $bits_24 - 3 | 0;
+ }
+ var $cmp850111 = $122 >>> 0 < 19;
+ $_$131 : do {
+ if ($cmp850111) {
+ var $126 = $122;
+ while (1) {
+ var $126;
+ HEAP32[$40 >> 2] = $126 + 1 | 0;
+ HEAP16[($41 + ((HEAPU16[(_inflate_order + ($126 << 1) | 0) >> 1] & 65535) << 1) | 0) >> 1] = 0;
+ var $_pr = HEAPU32[$40 >> 2];
+ if (!($_pr >>> 0 < 19)) {
+ break $_$131;
+ }
+ var $126 = $_pr;
+ }
+ }
+ } while (0);
+ HEAP32[$43 >> 2] = $arraydecay860_c;
+ HEAP32[$44 >> 2] = $arraydecay860_c;
+ HEAP32[$26 >> 2] = 7;
+ var $call868 = _inflate_table(0, $arraydecay864, 19, $42, $26, $arraydecay867);
+ if (($call868 | 0) == 0) {
+ HEAP32[$40 >> 2] = 0;
+ HEAP32[$mode >> 2] = 18;
+ var $ret_1_ph = 0;
+ var $next_29_ph = $next_27;
+ var $have_29_ph = $have_27;
+ var $hold_25_ph = $hold_23;
+ var $bits_25_ph = $bits_23;
+ __label__ = 164;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str9106 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call868;
+ var $next_0_be = $next_27;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_27;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_23;
+ var $bits_0_be = $bits_23;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 286) {
+ var $out_2;
+ var $bits_50;
+ var $hold_50;
+ var $have_54;
+ var $next_54;
+ var $tobool1702 = (HEAP32[$15 >> 2] | 0) == 0;
+ do {
+ if (!$tobool1702) {
+ if ((HEAP32[$17 >> 2] | 0) == 0) {
+ var $next_56 = $next_54;
+ var $have_56 = $have_54;
+ var $hold_52 = $hold_50;
+ var $bits_52 = $bits_50;
+ break;
+ }
+ var $next_55 = $next_54;
+ var $have_55 = $have_54;
+ var $hold_51 = $hold_50;
+ var $bits_51 = $bits_50;
+ while (1) {
+ var $bits_51;
+ var $hold_51;
+ var $have_55;
+ var $next_55;
+ if (!($bits_51 >>> 0 < 32)) {
+ break;
+ }
+ if (($have_55 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_55;
+ var $have_58 = 0;
+ var $hold_54 = $hold_51;
+ var $bits_54 = $bits_51;
+ var $out_4 = $out_2;
+ break $_$12;
+ }
+ var $add1721 = ((HEAPU8[$next_55] & 255) << $bits_51) + $hold_51 | 0;
+ var $next_55 = $next_55 + 1 | 0;
+ var $have_55 = $have_55 - 1 | 0;
+ var $hold_51 = $add1721;
+ var $bits_51 = $bits_51 + 8 | 0;
+ }
+ if (($hold_51 | 0) == (HEAP32[$36 >> 2] | 0)) {
+ var $next_56 = $next_55;
+ var $have_56 = $have_55;
+ var $hold_52 = 0;
+ var $bits_52 = 0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str18115 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_55;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_55;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_51;
+ var $bits_0_be = $bits_51;
+ var $out_0_be = $out_2;
+ __label__ = 268;
+ break $_$106;
+ }
+ var $next_56 = $next_54;
+ var $have_56 = $have_54;
+ var $hold_52 = $hold_50;
+ var $bits_52 = $bits_50;
+ } while (0);
+ var $bits_52;
+ var $hold_52;
+ var $have_56;
+ var $next_56;
+ HEAP32[$mode >> 2] = 28;
+ var $ret_8 = 1;
+ var $next_58 = $next_56;
+ var $have_58 = $have_56;
+ var $hold_54 = $hold_52;
+ var $bits_54 = $bits_52;
+ var $out_4 = $out_2;
+ break $_$12;
+ }
+ } while (0);
+ $_$148 : do {
+ if (__label__ == 52) {
+ while (1) {
+ var $bits_4;
+ var $hold_4;
+ var $have_4;
+ var $next_4;
+ if (!($bits_4 >>> 0 < 16)) {
+ break;
+ }
+ if (($have_4 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_4;
+ var $have_58 = 0;
+ var $hold_54 = $hold_4;
+ var $bits_54 = $bits_4;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add227 = ((HEAPU8[$next_4] & 255) << $bits_4) + $hold_4 | 0;
+ var $next_4 = $next_4 + 1 | 0;
+ var $have_4 = $have_4 - 1 | 0;
+ var $hold_4 = $add227;
+ var $bits_4 = $bits_4 + 8 | 0;
+ }
+ var $67 = HEAP32[$18 >> 2];
+ if (!(($67 | 0) == 0)) {
+ var $xflags = $67 + 8 | 0;
+ HEAP32[$xflags >> 2] = $hold_4 & 255;
+ var $os = HEAP32[$18 >> 2] + 12 | 0;
+ HEAP32[$os >> 2] = $hold_4 >>> 8;
+ }
+ if (!((HEAP32[$17 >> 2] & 512 | 0) == 0)) {
+ HEAP8[$arrayidx] = $hold_4 & 255;
+ HEAP8[$arrayidx40] = $hold_4 >>> 8 & 255;
+ var $70 = HEAP32[$16 >> 2];
+ var $call253 = _crc32($70, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call253;
+ }
+ HEAP32[$mode >> 2] = 4;
+ var $next_5 = $next_4;
+ var $have_5 = $have_4;
+ var $hold_5 = 0;
+ var $bits_5 = 0;
+ __label__ = 60;
+ break;
+ } else if (__label__ == 123) {
+ var $bits_16;
+ var $hold_16;
+ var $have_20;
+ var $next_20;
+ if ($23) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_20;
+ var $have_58 = $have_20;
+ var $hold_54 = $hold_16;
+ var $bits_54 = $bits_16;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_21 = $next_20;
+ var $have_21 = $have_20;
+ var $hold_17 = $hold_16;
+ var $bits_17 = $bits_16;
+ __label__ = 124;
+ break;
+ } else if (__label__ == 144) {
+ var $bits_21;
+ var $hold_21;
+ var $have_25;
+ var $next_25;
+ var $119 = HEAPU32[$21 >> 2];
+ if (($119 | 0) == 0) {
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_25;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_25;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_21;
+ var $bits_0_be = $bits_21;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $copy_3 = $119 >>> 0 > $have_25 >>> 0 ? $have_25 : $119;
+ var $copy_4 = $copy_3 >>> 0 > $left_0 >>> 0 ? $left_0 : $copy_3;
+ if (($copy_4 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_25;
+ var $have_58 = $have_25;
+ var $hold_54 = $hold_21;
+ var $bits_54 = $bits_21;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ _memcpy($put_0, $next_25, $copy_4, 1);
+ var $sub744 = $have_25 - $copy_4 | 0;
+ var $add_ptr745 = $next_25 + $copy_4 | 0;
+ var $sub746 = $left_0 - $copy_4 | 0;
+ var $add_ptr747 = $put_0 + $copy_4 | 0;
+ var $sub749 = HEAP32[$21 >> 2] - $copy_4 | 0;
+ HEAP32[$21 >> 2] = $sub749;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $add_ptr745;
+ var $put_0_be = $add_ptr747;
+ var $have_0_be = $sub744;
+ var $left_0_be = $sub746;
+ var $hold_0_be = $hold_21;
+ var $bits_0_be = $bits_21;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 164) {
+ var $bits_25_ph;
+ var $hold_25_ph;
+ var $have_29_ph;
+ var $next_29_ph;
+ var $ret_1_ph;
+ var $next_29 = $next_29_ph;
+ var $have_29 = $have_29_ph;
+ var $hold_25 = $hold_25_ph;
+ var $bits_25 = $bits_25_ph;
+ $_$167 : while (1) {
+ var $bits_25;
+ var $hold_25;
+ var $have_29;
+ var $next_29;
+ var $128 = HEAPU32[$40 >> 2];
+ var $129 = HEAPU32[$37 >> 2];
+ var $add881 = HEAP32[$38 >> 2] + $129 | 0;
+ if ($128 >>> 0 < $add881 >>> 0) {
+ var $sub888 = (1 << HEAP32[$26 >> 2]) - 1 | 0;
+ var $132 = HEAPU32[$27 >> 2];
+ var $next_30 = $next_29;
+ var $have_30 = $have_29;
+ var $hold_26 = $hold_25;
+ var $bits_26 = $bits_25;
+ while (1) {
+ var $bits_26;
+ var $hold_26;
+ var $have_30;
+ var $next_30;
+ var $and889 = $sub888 & $hold_26;
+ var $conv893 = HEAPU8[$132 + ($and889 << 2) + 1 | 0] & 255;
+ if (!($conv893 >>> 0 > $bits_26 >>> 0)) {
+ break;
+ }
+ if (($have_30 | 0) == 0) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_30;
+ var $have_58 = 0;
+ var $hold_54 = $hold_26;
+ var $bits_54 = $bits_26;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add907 = ((HEAPU8[$next_30] & 255) << $bits_26) + $hold_26 | 0;
+ var $next_30 = $next_30 + 1 | 0;
+ var $have_30 = $have_30 - 1 | 0;
+ var $hold_26 = $add907;
+ var $bits_26 = $bits_26 + 8 | 0;
+ }
+ var $tmp26 = HEAPU16[($132 + ($and889 << 2) + 2 | 0) >> 1];
+ if (($tmp26 & 65535) < 16) {
+ var $next_31 = $next_30;
+ var $have_31 = $have_30;
+ var $hold_27 = $hold_26;
+ var $bits_27 = $bits_26;
+ while (1) {
+ var $bits_27;
+ var $hold_27;
+ var $have_31;
+ var $next_31;
+ if (!($bits_27 >>> 0 < $conv893 >>> 0)) {
+ break;
+ }
+ if (($have_31 | 0) == 0) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_31;
+ var $have_58 = 0;
+ var $hold_54 = $hold_27;
+ var $bits_54 = $bits_27;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add931 = ((HEAPU8[$next_31] & 255) << $bits_27) + $hold_27 | 0;
+ var $next_31 = $next_31 + 1 | 0;
+ var $have_31 = $have_31 - 1 | 0;
+ var $hold_27 = $add931;
+ var $bits_27 = $bits_27 + 8 | 0;
+ }
+ var $shr941 = $hold_27 >>> ($conv893 >>> 0);
+ var $sub944 = $bits_27 - $conv893 | 0;
+ HEAP32[$40 >> 2] = $128 + 1 | 0;
+ HEAP16[($41 + ($128 << 1) | 0) >> 1] = $tmp26;
+ var $next_29 = $next_31;
+ var $have_29 = $have_31;
+ var $hold_25 = $shr941;
+ var $bits_25 = $sub944;
+ } else {
+ if ($tmp26 << 16 >> 16 == 16) {
+ var $add962 = $conv893 + 2 | 0;
+ var $next_32 = $next_30;
+ var $have_32 = $have_30;
+ var $hold_28 = $hold_26;
+ var $bits_28 = $bits_26;
+ while (1) {
+ var $bits_28;
+ var $hold_28;
+ var $have_32;
+ var $next_32;
+ if (!($bits_28 >>> 0 < $add962 >>> 0)) {
+ break;
+ }
+ if (($have_32 | 0) == 0) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_32;
+ var $have_58 = 0;
+ var $hold_54 = $hold_28;
+ var $bits_54 = $bits_28;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add975 = ((HEAPU8[$next_32] & 255) << $bits_28) + $hold_28 | 0;
+ var $next_32 = $next_32 + 1 | 0;
+ var $have_32 = $have_32 - 1 | 0;
+ var $hold_28 = $add975;
+ var $bits_28 = $bits_28 + 8 | 0;
+ }
+ var $shr985 = $hold_28 >>> ($conv893 >>> 0);
+ var $sub988 = $bits_28 - $conv893 | 0;
+ if (($128 | 0) == 0) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str10107 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_32;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_32;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr985;
+ var $bits_0_be = $sub988;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $len_0 = HEAP16[($41 + (($128 - 1 | 0) << 1) | 0) >> 1];
+ var $next_35 = $next_32;
+ var $have_35 = $have_32;
+ var $hold_31 = $shr985 >>> 2;
+ var $bits_31 = $sub988 - 2 | 0;
+ var $copy_5 = ($shr985 & 3) + 3 | 0;
+ } else if ($tmp26 << 16 >> 16 == 17) {
+ var $add1020 = $conv893 + 3 | 0;
+ var $next_33 = $next_30;
+ var $have_33 = $have_30;
+ var $hold_29 = $hold_26;
+ var $bits_29 = $bits_26;
+ while (1) {
+ var $bits_29;
+ var $hold_29;
+ var $have_33;
+ var $next_33;
+ if (!($bits_29 >>> 0 < $add1020 >>> 0)) {
+ break;
+ }
+ if (($have_33 | 0) == 0) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_33;
+ var $have_58 = 0;
+ var $hold_54 = $hold_29;
+ var $bits_54 = $bits_29;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1033 = ((HEAPU8[$next_33] & 255) << $bits_29) + $hold_29 | 0;
+ var $next_33 = $next_33 + 1 | 0;
+ var $have_33 = $have_33 - 1 | 0;
+ var $hold_29 = $add1033;
+ var $bits_29 = $bits_29 + 8 | 0;
+ }
+ var $shr1043 = $hold_29 >>> ($conv893 >>> 0);
+ var $len_0 = 0;
+ var $next_35 = $next_33;
+ var $have_35 = $have_33;
+ var $hold_31 = $shr1043 >>> 3;
+ var $bits_31 = (-3 - $conv893 | 0) + $bits_29 | 0;
+ var $copy_5 = ($shr1043 & 7) + 3 | 0;
+ } else {
+ var $add1061 = $conv893 + 7 | 0;
+ var $next_34 = $next_30;
+ var $have_34 = $have_30;
+ var $hold_30 = $hold_26;
+ var $bits_30 = $bits_26;
+ while (1) {
+ var $bits_30;
+ var $hold_30;
+ var $have_34;
+ var $next_34;
+ if (!($bits_30 >>> 0 < $add1061 >>> 0)) {
+ break;
+ }
+ if (($have_34 | 0) == 0) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_34;
+ var $have_58 = 0;
+ var $hold_54 = $hold_30;
+ var $bits_54 = $bits_30;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1074 = ((HEAPU8[$next_34] & 255) << $bits_30) + $hold_30 | 0;
+ var $next_34 = $next_34 + 1 | 0;
+ var $have_34 = $have_34 - 1 | 0;
+ var $hold_30 = $add1074;
+ var $bits_30 = $bits_30 + 8 | 0;
+ }
+ var $shr1084 = $hold_30 >>> ($conv893 >>> 0);
+ var $len_0 = 0;
+ var $next_35 = $next_34;
+ var $have_35 = $have_34;
+ var $hold_31 = $shr1084 >>> 7;
+ var $bits_31 = (-7 - $conv893 | 0) + $bits_30 | 0;
+ var $copy_5 = ($shr1084 & 127) + 11 | 0;
+ }
+ var $copy_5;
+ var $bits_31;
+ var $hold_31;
+ var $have_35;
+ var $next_35;
+ var $len_0;
+ if (($128 + $copy_5 | 0) >>> 0 > $add881 >>> 0) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str10107 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_35;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_35;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_31;
+ var $bits_0_be = $bits_31;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $copy_6127 = $copy_5;
+ var $139 = $128;
+ while (1) {
+ var $139;
+ var $copy_6127;
+ var $dec1111 = $copy_6127 - 1 | 0;
+ HEAP32[$40 >> 2] = $139 + 1 | 0;
+ HEAP16[($41 + ($139 << 1) | 0) >> 1] = $len_0;
+ if (($dec1111 | 0) == 0) {
+ var $next_29 = $next_35;
+ var $have_29 = $have_35;
+ var $hold_25 = $hold_31;
+ var $bits_25 = $bits_31;
+ continue $_$167;
+ }
+ var $copy_6127 = $dec1111;
+ var $139 = HEAP32[$40 >> 2];
+ }
+ }
+ } else {
+ if ((HEAP32[$mode >> 2] | 0) == 29) {
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ if (HEAP16[$45 >> 1] << 16 >> 16 == 0) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str11108 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ HEAP32[$43 >> 2] = $arraydecay860_c;
+ HEAP32[$44 >> 2] = $arraydecay860_c;
+ HEAP32[$26 >> 2] = 9;
+ var $call1149 = _inflate_table(1, $arraydecay864, $129, $42, $26, $arraydecay867);
+ if (!(($call1149 | 0) == 0)) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str12109 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call1149;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $_c = HEAP32[$42 >> 2];
+ HEAP32[$46 >> 2] = $_c;
+ HEAP32[$47 >> 2] = 6;
+ var $add_ptr1159 = $arraydecay864 + (HEAP32[$37 >> 2] << 1) | 0;
+ var $143 = HEAP32[$38 >> 2];
+ var $call1165 = _inflate_table(2, $add_ptr1159, $143, $42, $47, $arraydecay867);
+ if (!(($call1165 | 0) == 0)) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str13110 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call1165;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ HEAP32[$mode >> 2] = 19;
+ if ($cmp660) {
+ var $ret_8 = 0;
+ var $next_58 = $next_29;
+ var $have_58 = $have_29;
+ var $hold_54 = $hold_25;
+ var $bits_54 = $bits_25;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $ret_2 = 0;
+ var $next_37 = $next_29;
+ var $have_37 = $have_29;
+ var $hold_33 = $hold_25;
+ var $bits_33 = $bits_25;
+ __label__ = 205;
+ break $_$148;
+ }
+ }
+ }
+ } while (0);
+ do {
+ if (__label__ == 60) {
+ var $bits_5;
+ var $hold_5;
+ var $have_5;
+ var $next_5;
+ var $71 = HEAPU32[$17 >> 2];
+ var $tobool263 = ($71 & 1024 | 0) == 0;
+ do {
+ if ($tobool263) {
+ var $76 = HEAP32[$18 >> 2];
+ if (($76 | 0) == 0) {
+ var $next_7 = $next_5;
+ var $have_7 = $have_5;
+ var $hold_7 = $hold_5;
+ var $bits_7 = $bits_5;
+ break;
+ }
+ var $extra = $76 + 16 | 0;
+ HEAP32[$extra >> 2] = 0;
+ var $next_7 = $next_5;
+ var $have_7 = $have_5;
+ var $hold_7 = $hold_5;
+ var $bits_7 = $bits_5;
+ } else {
+ var $next_6 = $next_5;
+ var $have_6 = $have_5;
+ var $hold_6 = $hold_5;
+ var $bits_6 = $bits_5;
+ while (1) {
+ var $bits_6;
+ var $hold_6;
+ var $have_6;
+ var $next_6;
+ if (!($bits_6 >>> 0 < 16)) {
+ break;
+ }
+ if (($have_6 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_6;
+ var $have_58 = 0;
+ var $hold_54 = $hold_6;
+ var $bits_54 = $bits_6;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add279 = ((HEAPU8[$next_6] & 255) << $bits_6) + $hold_6 | 0;
+ var $next_6 = $next_6 + 1 | 0;
+ var $have_6 = $have_6 - 1 | 0;
+ var $hold_6 = $add279;
+ var $bits_6 = $bits_6 + 8 | 0;
+ }
+ HEAP32[$21 >> 2] = $hold_6;
+ var $73 = HEAP32[$18 >> 2];
+ if (($73 | 0) == 0) {
+ var $74 = $71;
+ } else {
+ var $extra_len = $73 + 20 | 0;
+ HEAP32[$extra_len >> 2] = $hold_6;
+ var $74 = HEAP32[$17 >> 2];
+ }
+ var $74;
+ if (($74 & 512 | 0) == 0) {
+ var $next_7 = $next_6;
+ var $have_7 = $have_6;
+ var $hold_7 = 0;
+ var $bits_7 = 0;
+ break;
+ }
+ HEAP8[$arrayidx] = $hold_6 & 255;
+ HEAP8[$arrayidx40] = $hold_6 >>> 8 & 255;
+ var $75 = HEAP32[$16 >> 2];
+ var $call302 = _crc32($75, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call302;
+ var $next_7 = $next_6;
+ var $have_7 = $have_6;
+ var $hold_7 = 0;
+ var $bits_7 = 0;
+ }
+ } while (0);
+ var $bits_7;
+ var $hold_7;
+ var $have_7;
+ var $next_7;
+ HEAP32[$mode >> 2] = 5;
+ var $next_8 = $next_7;
+ var $have_8 = $have_7;
+ var $hold_8 = $hold_7;
+ var $bits_8 = $bits_7;
+ __label__ = 71;
+ break;
+ } else if (__label__ == 124) {
+ var $bits_17;
+ var $hold_17;
+ var $have_21;
+ var $next_21;
+ if ((HEAP32[$24 >> 2] | 0) == 0) {
+ var $next_22 = $next_21;
+ var $have_22 = $have_21;
+ var $hold_18 = $hold_17;
+ var $bits_18 = $bits_17;
+ while (1) {
+ var $bits_18;
+ var $hold_18;
+ var $have_22;
+ var $next_22;
+ if (!($bits_18 >>> 0 < 3)) {
+ break;
+ }
+ if (($have_22 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_22;
+ var $have_58 = 0;
+ var $hold_54 = $hold_18;
+ var $bits_54 = $bits_18;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add641 = ((HEAPU8[$next_22] & 255) << $bits_18) + $hold_18 | 0;
+ var $next_22 = $next_22 + 1 | 0;
+ var $have_22 = $have_22 - 1 | 0;
+ var $hold_18 = $add641;
+ var $bits_18 = $bits_18 + 8 | 0;
+ }
+ HEAP32[$24 >> 2] = $hold_18 & 1;
+ var $and655 = $hold_18 >>> 1 & 3;
+ do {
+ if (($and655 | 0) == 0) {
+ HEAP32[$mode >> 2] = 13;
+ } else if (($and655 | 0) == 1) {
+ _fixedtables($4);
+ HEAP32[$mode >> 2] = 19;
+ if (!$cmp660) {
+ break;
+ }
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_22;
+ var $have_58 = $have_22;
+ var $hold_54 = $hold_18 >>> 3;
+ var $bits_54 = $bits_18 - 3 | 0;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($and655 | 0) == 2) {
+ HEAP32[$mode >> 2] = 16;
+ } else if (($and655 | 0) == 3) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str6103 | 0;
+ HEAP32[$mode >> 2] = 29;
+ }
+ } while (0);
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_22;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_22;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_18 >>> 3;
+ var $bits_0_be = $bits_18 - 3 | 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $and619 = $bits_17 & 7;
+ HEAP32[$mode >> 2] = 26;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_21;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_21;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_17 >>> ($and619 >>> 0);
+ var $bits_0_be = $bits_17 - $and619 | 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 205) {
+ var $bits_33;
+ var $hold_33;
+ var $have_37;
+ var $next_37;
+ var $ret_2;
+ HEAP32[$mode >> 2] = 20;
+ var $ret_3 = $ret_2;
+ var $next_38 = $next_37;
+ var $have_38 = $have_37;
+ var $hold_34 = $hold_33;
+ var $bits_34 = $bits_33;
+ __label__ = 206;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 71) {
+ var $bits_8;
+ var $hold_8;
+ var $have_8;
+ var $next_8;
+ var $77 = HEAPU32[$17 >> 2];
+ if (($77 & 1024 | 0) == 0) {
+ var $next_10 = $next_8;
+ var $have_10 = $have_8;
+ var $88 = $77;
+ } else {
+ var $78 = HEAPU32[$21 >> 2];
+ var $copy_0 = $78 >>> 0 > $have_8 >>> 0 ? $have_8 : $78;
+ if (($copy_0 | 0) == 0) {
+ var $next_9 = $next_8;
+ var $have_9 = $have_8;
+ var $87 = $78;
+ var $86 = $77;
+ } else {
+ var $79 = HEAPU32[$18 >> 2];
+ var $cmp330 = ($79 | 0) == 0;
+ do {
+ if ($cmp330) {
+ var $83 = $77;
+ } else {
+ var $80 = HEAP32[($79 + 16 | 0) >> 2];
+ if (($80 | 0) == 0) {
+ var $83 = $77;
+ break;
+ }
+ var $sub341 = HEAP32[($79 + 20 | 0) >> 2] - $78 | 0;
+ var $add_ptr = $80 + $sub341 | 0;
+ var $82 = HEAPU32[($79 + 24 | 0) >> 2];
+ var $cond351 = ($sub341 + $copy_0 | 0) >>> 0 > $82 >>> 0 ? $82 - $sub341 | 0 : $copy_0;
+ _memcpy($add_ptr, $next_8, $cond351, 1);
+ var $83 = HEAP32[$17 >> 2];
+ }
+ } while (0);
+ var $83;
+ if (!(($83 & 512 | 0) == 0)) {
+ var $84 = HEAP32[$16 >> 2];
+ var $call358 = _crc32($84, $next_8, $copy_0);
+ HEAP32[$16 >> 2] = $call358;
+ }
+ var $sub361 = $have_8 - $copy_0 | 0;
+ var $add_ptr362 = $next_8 + $copy_0 | 0;
+ var $sub364 = HEAP32[$21 >> 2] - $copy_0 | 0;
+ HEAP32[$21 >> 2] = $sub364;
+ var $next_9 = $add_ptr362;
+ var $have_9 = $sub361;
+ var $87 = $sub364;
+ var $86 = $83;
+ }
+ var $86;
+ var $87;
+ var $have_9;
+ var $next_9;
+ if (!(($87 | 0) == 0)) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_9;
+ var $have_58 = $have_9;
+ var $hold_54 = $hold_8;
+ var $bits_54 = $bits_8;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_10 = $next_9;
+ var $have_10 = $have_9;
+ var $88 = $86;
+ }
+ var $88;
+ var $have_10;
+ var $next_10;
+ HEAP32[$21 >> 2] = 0;
+ HEAP32[$mode >> 2] = 6;
+ var $next_11 = $next_10;
+ var $have_11 = $have_10;
+ var $hold_9 = $hold_8;
+ var $bits_9 = $bits_8;
+ var $89 = $88;
+ __label__ = 81;
+ break;
+ } else if (__label__ == 206) {
+ var $bits_34;
+ var $hold_34;
+ var $have_38;
+ var $next_38;
+ var $ret_3;
+ if ($have_38 >>> 0 > 5 & $left_0 >>> 0 > 257) {
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_38;
+ HEAP32[$avail_in15 >> 2] = $have_38;
+ HEAP32[$11 >> 2] = $hold_34;
+ HEAP32[$13 >> 2] = $bits_34;
+ _inflate_fast($strm, $out_0);
+ var $144 = HEAP32[$next_out >> 2];
+ var $145 = HEAP32[$avail_out >> 2];
+ var $146 = HEAP32[$next_in >> 2];
+ var $147 = HEAP32[$avail_in15 >> 2];
+ var $148 = HEAP32[$11 >> 2];
+ var $149 = HEAP32[$13 >> 2];
+ if (!((HEAP32[$mode >> 2] | 0) == 11)) {
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $146;
+ var $put_0_be = $144;
+ var $have_0_be = $147;
+ var $left_0_be = $145;
+ var $hold_0_be = $148;
+ var $bits_0_be = $149;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$25 >> 2] = -1;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $146;
+ var $put_0_be = $144;
+ var $have_0_be = $147;
+ var $left_0_be = $145;
+ var $hold_0_be = $148;
+ var $bits_0_be = $149;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$25 >> 2] = 0;
+ var $sub1213 = (1 << HEAP32[$26 >> 2]) - 1 | 0;
+ var $152 = HEAPU32[$27 >> 2];
+ var $next_39 = $next_38;
+ var $have_39 = $have_38;
+ var $hold_35 = $hold_34;
+ var $bits_35 = $bits_34;
+ while (1) {
+ var $bits_35;
+ var $hold_35;
+ var $have_39;
+ var $next_39;
+ var $and1214 = $sub1213 & $hold_35;
+ var $tmp22 = HEAPU8[$152 + ($and1214 << 2) + 1 | 0];
+ var $conv1218 = $tmp22 & 255;
+ if (!($conv1218 >>> 0 > $bits_35 >>> 0)) {
+ break;
+ }
+ if (($have_39 | 0) == 0) {
+ var $ret_8 = $ret_3;
+ var $next_58 = $next_39;
+ var $have_58 = 0;
+ var $hold_54 = $hold_35;
+ var $bits_54 = $bits_35;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1232 = ((HEAPU8[$next_39] & 255) << $bits_35) + $hold_35 | 0;
+ var $next_39 = $next_39 + 1 | 0;
+ var $have_39 = $have_39 - 1 | 0;
+ var $hold_35 = $add1232;
+ var $bits_35 = $bits_35 + 8 | 0;
+ }
+ var $tmp21 = HEAPU8[$152 + ($and1214 << 2) | 0];
+ var $tmp23 = HEAPU16[($152 + ($and1214 << 2) + 2 | 0) >> 1];
+ var $conv1237 = $tmp21 & 255;
+ var $tobool1238 = $tmp21 << 24 >> 24 == 0;
+ do {
+ if ($tobool1238) {
+ var $next_41 = $next_39;
+ var $have_41 = $have_39;
+ var $hold_37 = $hold_35;
+ var $bits_37 = $bits_35;
+ var $here_09_0 = 0;
+ var $here_110_0 = $tmp22;
+ var $here_211_0 = $tmp23;
+ var $155 = 0;
+ } else {
+ if (!(($conv1237 & 240 | 0) == 0)) {
+ var $next_41 = $next_39;
+ var $have_41 = $have_39;
+ var $hold_37 = $hold_35;
+ var $bits_37 = $bits_35;
+ var $here_09_0 = $tmp21;
+ var $here_110_0 = $tmp22;
+ var $here_211_0 = $tmp23;
+ var $155 = 0;
+ break;
+ }
+ var $conv1248 = $tmp23 & 65535;
+ var $sub1255 = (1 << ($conv1218 + $conv1237 | 0)) - 1 | 0;
+ var $next_40 = $next_39;
+ var $have_40 = $have_39;
+ var $hold_36 = $hold_35;
+ var $bits_36 = $bits_35;
+ while (1) {
+ var $bits_36;
+ var $hold_36;
+ var $have_40;
+ var $next_40;
+ var $add1260 = (($hold_36 & $sub1255) >>> ($conv1218 >>> 0)) + $conv1248 | 0;
+ var $tmp19 = HEAPU8[$152 + ($add1260 << 2) + 1 | 0];
+ if (!((($tmp19 & 255) + $conv1218 | 0) >>> 0 > $bits_36 >>> 0)) {
+ break;
+ }
+ if (($have_40 | 0) == 0) {
+ var $ret_8 = $ret_3;
+ var $next_58 = $next_40;
+ var $have_58 = 0;
+ var $hold_54 = $hold_36;
+ var $bits_54 = $bits_36;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1281 = ((HEAPU8[$next_40] & 255) << $bits_36) + $hold_36 | 0;
+ var $next_40 = $next_40 + 1 | 0;
+ var $have_40 = $have_40 - 1 | 0;
+ var $hold_36 = $add1281;
+ var $bits_36 = $bits_36 + 8 | 0;
+ }
+ var $tmp20 = HEAP16[($152 + ($add1260 << 2) + 2 | 0) >> 1];
+ var $tmp18 = HEAP8[$152 + ($add1260 << 2) | 0];
+ var $shr1289 = $hold_36 >>> ($conv1218 >>> 0);
+ var $sub1292 = $bits_36 - $conv1218 | 0;
+ HEAP32[$25 >> 2] = $conv1218;
+ var $next_41 = $next_40;
+ var $have_41 = $have_40;
+ var $hold_37 = $shr1289;
+ var $bits_37 = $sub1292;
+ var $here_09_0 = $tmp18;
+ var $here_110_0 = $tmp19;
+ var $here_211_0 = $tmp20;
+ var $155 = $conv1218;
+ }
+ } while (0);
+ var $155;
+ var $here_211_0;
+ var $here_110_0;
+ var $here_09_0;
+ var $bits_37;
+ var $hold_37;
+ var $have_41;
+ var $next_41;
+ var $conv1302 = $here_110_0 & 255;
+ var $shr1303 = $hold_37 >>> ($conv1302 >>> 0);
+ var $sub1306 = $bits_37 - $conv1302 | 0;
+ HEAP32[$25 >> 2] = $155 + $conv1302 | 0;
+ HEAP32[$21 >> 2] = $here_211_0 & 65535;
+ var $conv1317 = $here_09_0 & 255;
+ if ($here_09_0 << 24 >> 24 == 0) {
+ HEAP32[$mode >> 2] = 25;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ if (!(($conv1317 & 32 | 0) == 0)) {
+ HEAP32[$25 >> 2] = -1;
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ if (($conv1317 & 64 | 0) == 0) {
+ var $and1341 = $conv1317 & 15;
+ HEAP32[$28 >> 2] = $and1341;
+ HEAP32[$mode >> 2] = 21;
+ var $ret_4 = $ret_3;
+ var $next_42 = $next_41;
+ var $have_42 = $have_41;
+ var $hold_38 = $shr1303;
+ var $bits_38 = $sub1306;
+ var $156 = $and1341;
+ __label__ = 227;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str2171 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 81) {
+ var $89;
+ var $bits_9;
+ var $hold_9;
+ var $have_11;
+ var $next_11;
+ var $tobool376 = ($89 & 2048 | 0) == 0;
+ do {
+ if ($tobool376) {
+ var $98 = HEAP32[$18 >> 2];
+ if (($98 | 0) == 0) {
+ var $next_12 = $next_11;
+ var $have_12 = $have_11;
+ break;
+ }
+ var $name428 = $98 + 28 | 0;
+ HEAP32[$name428 >> 2] = 0;
+ var $next_12 = $next_11;
+ var $have_12 = $have_11;
+ } else {
+ if (($have_11 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_11;
+ var $have_58 = 0;
+ var $hold_54 = $hold_9;
+ var $bits_54 = $bits_9;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $copy_1 = 0;
+ while (1) {
+ var $copy_1;
+ var $inc = $copy_1 + 1 | 0;
+ var $90 = HEAP8[$next_11 + $copy_1 | 0];
+ var $91 = HEAP32[$18 >> 2];
+ var $cmp386 = ($91 | 0) == 0;
+ do {
+ if (!$cmp386) {
+ var $name = $91 + 28 | 0;
+ if ((HEAP32[$name >> 2] | 0) == 0) {
+ break;
+ }
+ var $93 = HEAPU32[$21 >> 2];
+ if (!($93 >>> 0 < HEAPU32[($91 + 32 | 0) >> 2] >>> 0)) {
+ break;
+ }
+ HEAP32[$21 >> 2] = $93 + 1 | 0;
+ HEAP8[HEAP32[$name >> 2] + $93 | 0] = $90;
+ }
+ } while (0);
+ var $tobool405 = $90 << 24 >> 24 != 0;
+ if (!($tobool405 & $inc >>> 0 < $have_11 >>> 0)) {
+ break;
+ }
+ var $copy_1 = $inc;
+ }
+ if (!((HEAP32[$17 >> 2] & 512 | 0) == 0)) {
+ var $97 = HEAP32[$16 >> 2];
+ var $call414 = _crc32($97, $next_11, $inc);
+ HEAP32[$16 >> 2] = $call414;
+ }
+ var $sub417 = $have_11 - $inc | 0;
+ var $add_ptr418 = $next_11 + $inc | 0;
+ if ($tobool405) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $add_ptr418;
+ var $have_58 = $sub417;
+ var $hold_54 = $hold_9;
+ var $bits_54 = $bits_9;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_12 = $add_ptr418;
+ var $have_12 = $sub417;
+ }
+ } while (0);
+ var $have_12;
+ var $next_12;
+ HEAP32[$21 >> 2] = 0;
+ HEAP32[$mode >> 2] = 7;
+ var $next_13 = $next_12;
+ var $have_13 = $have_12;
+ var $hold_10 = $hold_9;
+ var $bits_10 = $bits_9;
+ __label__ = 94;
+ break;
+ } else if (__label__ == 227) {
+ var $156;
+ var $bits_38;
+ var $hold_38;
+ var $have_42;
+ var $next_42;
+ var $ret_4;
+ if (($156 | 0) == 0) {
+ var $next_44 = $next_42;
+ var $have_44 = $have_42;
+ var $hold_40 = $hold_38;
+ var $bits_40 = $bits_38;
+ var $160 = HEAP32[$21 >> 2];
+ } else {
+ var $next_43 = $next_42;
+ var $have_43 = $have_42;
+ var $hold_39 = $hold_38;
+ var $bits_39 = $bits_38;
+ while (1) {
+ var $bits_39;
+ var $hold_39;
+ var $have_43;
+ var $next_43;
+ if (!($bits_39 >>> 0 < $156 >>> 0)) {
+ break;
+ }
+ if (($have_43 | 0) == 0) {
+ var $ret_8 = $ret_4;
+ var $next_58 = $next_43;
+ var $have_58 = 0;
+ var $hold_54 = $hold_39;
+ var $bits_54 = $bits_39;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1363 = ((HEAPU8[$next_43] & 255) << $bits_39) + $hold_39 | 0;
+ var $next_43 = $next_43 + 1 | 0;
+ var $have_43 = $have_43 - 1 | 0;
+ var $hold_39 = $add1363;
+ var $bits_39 = $bits_39 + 8 | 0;
+ }
+ var $add1375 = HEAP32[$21 >> 2] + (((1 << $156) - 1 | 0) & $hold_39) | 0;
+ HEAP32[$21 >> 2] = $add1375;
+ var $add1385 = HEAP32[$25 >> 2] + $156 | 0;
+ HEAP32[$25 >> 2] = $add1385;
+ var $next_44 = $next_43;
+ var $have_44 = $have_43;
+ var $hold_40 = $hold_39 >>> ($156 >>> 0);
+ var $bits_40 = $bits_39 - $156 | 0;
+ var $160 = $add1375;
+ }
+ var $160;
+ var $bits_40;
+ var $hold_40;
+ var $have_44;
+ var $next_44;
+ HEAP32[$29 >> 2] = $160;
+ HEAP32[$mode >> 2] = 22;
+ var $ret_5_ph = $ret_4;
+ var $next_45_ph = $next_44;
+ var $have_45_ph = $have_44;
+ var $hold_41_ph = $hold_40;
+ var $bits_41_ph = $bits_40;
+ __label__ = 234;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 94) {
+ var $bits_10;
+ var $hold_10;
+ var $have_13;
+ var $next_13;
+ var $tobool436 = (HEAP32[$17 >> 2] & 4096 | 0) == 0;
+ do {
+ if ($tobool436) {
+ var $108 = HEAP32[$18 >> 2];
+ if (($108 | 0) == 0) {
+ var $next_14 = $next_13;
+ var $have_14 = $have_13;
+ break;
+ }
+ var $comment492 = $108 + 36 | 0;
+ HEAP32[$comment492 >> 2] = 0;
+ var $next_14 = $next_13;
+ var $have_14 = $have_13;
+ } else {
+ if (($have_13 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_13;
+ var $have_58 = 0;
+ var $hold_54 = $hold_10;
+ var $bits_54 = $bits_10;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $copy_2 = 0;
+ while (1) {
+ var $copy_2;
+ var $inc443 = $copy_2 + 1 | 0;
+ var $100 = HEAP8[$next_13 + $copy_2 | 0];
+ var $101 = HEAP32[$18 >> 2];
+ var $cmp447 = ($101 | 0) == 0;
+ do {
+ if (!$cmp447) {
+ var $comment = $101 + 36 | 0;
+ if ((HEAP32[$comment >> 2] | 0) == 0) {
+ break;
+ }
+ var $103 = HEAPU32[$21 >> 2];
+ if (!($103 >>> 0 < HEAPU32[($101 + 40 | 0) >> 2] >>> 0)) {
+ break;
+ }
+ HEAP32[$21 >> 2] = $103 + 1 | 0;
+ HEAP8[HEAP32[$comment >> 2] + $103 | 0] = $100;
+ }
+ } while (0);
+ var $tobool467 = $100 << 24 >> 24 != 0;
+ if (!($tobool467 & $inc443 >>> 0 < $have_13 >>> 0)) {
+ break;
+ }
+ var $copy_2 = $inc443;
+ }
+ if (!((HEAP32[$17 >> 2] & 512 | 0) == 0)) {
+ var $107 = HEAP32[$16 >> 2];
+ var $call478 = _crc32($107, $next_13, $inc443);
+ HEAP32[$16 >> 2] = $call478;
+ }
+ var $sub481 = $have_13 - $inc443 | 0;
+ var $add_ptr482 = $next_13 + $inc443 | 0;
+ if ($tobool467) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $add_ptr482;
+ var $have_58 = $sub481;
+ var $hold_54 = $hold_10;
+ var $bits_54 = $bits_10;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_14 = $add_ptr482;
+ var $have_14 = $sub481;
+ }
+ } while (0);
+ var $have_14;
+ var $next_14;
+ HEAP32[$mode >> 2] = 8;
+ var $next_15 = $next_14;
+ var $have_15 = $have_14;
+ var $hold_11 = $hold_10;
+ var $bits_11 = $bits_10;
+ __label__ = 107;
+ break;
+ } else if (__label__ == 234) {
+ var $bits_41_ph;
+ var $hold_41_ph;
+ var $have_45_ph;
+ var $next_45_ph;
+ var $ret_5_ph;
+ var $sub1393 = (1 << HEAP32[$47 >> 2]) - 1 | 0;
+ var $162 = HEAPU32[$48 >> 2];
+ var $next_45 = $next_45_ph;
+ var $have_45 = $have_45_ph;
+ var $hold_41 = $hold_41_ph;
+ var $bits_41 = $bits_41_ph;
+ while (1) {
+ var $bits_41;
+ var $hold_41;
+ var $have_45;
+ var $next_45;
+ var $and1394 = $sub1393 & $hold_41;
+ var $tmp16 = HEAPU8[$162 + ($and1394 << 2) + 1 | 0];
+ var $conv1398 = $tmp16 & 255;
+ if (!($conv1398 >>> 0 > $bits_41 >>> 0)) {
+ break;
+ }
+ if (($have_45 | 0) == 0) {
+ var $ret_8 = $ret_5_ph;
+ var $next_58 = $next_45;
+ var $have_58 = 0;
+ var $hold_54 = $hold_41;
+ var $bits_54 = $bits_41;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1412 = ((HEAPU8[$next_45] & 255) << $bits_41) + $hold_41 | 0;
+ var $next_45 = $next_45 + 1 | 0;
+ var $have_45 = $have_45 - 1 | 0;
+ var $hold_41 = $add1412;
+ var $bits_41 = $bits_41 + 8 | 0;
+ }
+ var $tmp15 = HEAPU8[$162 + ($and1394 << 2) | 0];
+ var $tmp17 = HEAPU16[($162 + ($and1394 << 2) + 2 | 0) >> 1];
+ var $conv1418 = $tmp15 & 255;
+ if (($conv1418 & 240 | 0) == 0) {
+ var $conv1425 = $tmp17 & 65535;
+ var $sub1432 = (1 << ($conv1398 + $conv1418 | 0)) - 1 | 0;
+ var $next_46 = $next_45;
+ var $have_46 = $have_45;
+ var $hold_42 = $hold_41;
+ var $bits_42 = $bits_41;
+ while (1) {
+ var $bits_42;
+ var $hold_42;
+ var $have_46;
+ var $next_46;
+ var $add1437 = (($hold_42 & $sub1432) >>> ($conv1398 >>> 0)) + $conv1425 | 0;
+ var $tmp13 = HEAPU8[$162 + ($add1437 << 2) + 1 | 0];
+ if (!((($tmp13 & 255) + $conv1398 | 0) >>> 0 > $bits_42 >>> 0)) {
+ break;
+ }
+ if (($have_46 | 0) == 0) {
+ var $ret_8 = $ret_5_ph;
+ var $next_58 = $next_46;
+ var $have_58 = 0;
+ var $hold_54 = $hold_42;
+ var $bits_54 = $bits_42;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1458 = ((HEAPU8[$next_46] & 255) << $bits_42) + $hold_42 | 0;
+ var $next_46 = $next_46 + 1 | 0;
+ var $have_46 = $have_46 - 1 | 0;
+ var $hold_42 = $add1458;
+ var $bits_42 = $bits_42 + 8 | 0;
+ }
+ var $tmp14 = HEAP16[($162 + ($add1437 << 2) + 2 | 0) >> 1];
+ var $tmp12 = HEAP8[$162 + ($add1437 << 2) | 0];
+ var $shr1466 = $hold_42 >>> ($conv1398 >>> 0);
+ var $sub1469 = $bits_42 - $conv1398 | 0;
+ var $add1475 = HEAP32[$25 >> 2] + $conv1398 | 0;
+ HEAP32[$25 >> 2] = $add1475;
+ var $next_47 = $next_46;
+ var $have_47 = $have_46;
+ var $hold_43 = $shr1466;
+ var $bits_43 = $sub1469;
+ var $here_09_1 = $tmp12;
+ var $here_110_1 = $tmp13;
+ var $here_211_1 = $tmp14;
+ var $166 = $add1475;
+ } else {
+ var $next_47 = $next_45;
+ var $have_47 = $have_45;
+ var $hold_43 = $hold_41;
+ var $bits_43 = $bits_41;
+ var $here_09_1 = $tmp15;
+ var $here_110_1 = $tmp16;
+ var $here_211_1 = $tmp17;
+ var $166 = HEAP32[$25 >> 2];
+ }
+ var $166;
+ var $here_211_1;
+ var $here_110_1;
+ var $here_09_1;
+ var $bits_43;
+ var $hold_43;
+ var $have_47;
+ var $next_47;
+ var $conv1479 = $here_110_1 & 255;
+ var $shr1480 = $hold_43 >>> ($conv1479 >>> 0);
+ var $sub1483 = $bits_43 - $conv1479 | 0;
+ HEAP32[$25 >> 2] = $166 + $conv1479 | 0;
+ var $conv1491 = $here_09_1 & 255;
+ if (($conv1491 & 64 | 0) == 0) {
+ HEAP32[$30 >> 2] = $here_211_1 & 65535;
+ var $and1502 = $conv1491 & 15;
+ HEAP32[$28 >> 2] = $and1502;
+ HEAP32[$mode >> 2] = 23;
+ var $ret_6 = $ret_5_ph;
+ var $next_48 = $next_47;
+ var $have_48 = $have_47;
+ var $hold_44 = $shr1480;
+ var $bits_44 = $sub1483;
+ var $167 = $and1502;
+ __label__ = 248;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str1170 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_5_ph;
+ var $next_0_be = $next_47;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_47;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1480;
+ var $bits_0_be = $sub1483;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ } while (0);
+ $_$359 : do {
+ if (__label__ == 107) {
+ var $bits_11;
+ var $hold_11;
+ var $have_15;
+ var $next_15;
+ var $109 = HEAPU32[$17 >> 2];
+ var $tobool499 = ($109 & 512 | 0) == 0;
+ do {
+ if (!$tobool499) {
+ var $next_16 = $next_15;
+ var $have_16 = $have_15;
+ var $hold_12 = $hold_11;
+ var $bits_12 = $bits_11;
+ while (1) {
+ var $bits_12;
+ var $hold_12;
+ var $have_16;
+ var $next_16;
+ if (!($bits_12 >>> 0 < 16)) {
+ break;
+ }
+ if (($have_16 | 0) == 0) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_16;
+ var $have_58 = 0;
+ var $hold_54 = $hold_12;
+ var $bits_54 = $bits_12;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add515 = ((HEAPU8[$next_16] & 255) << $bits_12) + $hold_12 | 0;
+ var $next_16 = $next_16 + 1 | 0;
+ var $have_16 = $have_16 - 1 | 0;
+ var $hold_12 = $add515;
+ var $bits_12 = $bits_12 + 8 | 0;
+ }
+ if (($hold_12 | 0) == (HEAP32[$16 >> 2] & 65535 | 0)) {
+ var $next_17 = $next_16;
+ var $have_17 = $have_16;
+ var $hold_13 = 0;
+ var $bits_13 = 0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str5102 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_16;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_16;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_12;
+ var $bits_0_be = $bits_12;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$359;
+ }
+ var $next_17 = $next_15;
+ var $have_17 = $have_15;
+ var $hold_13 = $hold_11;
+ var $bits_13 = $bits_11;
+ } while (0);
+ var $bits_13;
+ var $hold_13;
+ var $have_17;
+ var $next_17;
+ var $112 = HEAPU32[$18 >> 2];
+ if (!(($112 | 0) == 0)) {
+ HEAP32[($112 + 44 | 0) >> 2] = $109 >>> 9 & 1;
+ var $done543 = HEAP32[$18 >> 2] + 48 | 0;
+ HEAP32[$done543 >> 2] = 1;
+ }
+ var $call545 = _crc32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call545;
+ HEAP32[$adler >> 2] = $call545;
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_17;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_17;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_13;
+ var $bits_0_be = $bits_13;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 248) {
+ var $167;
+ var $bits_44;
+ var $hold_44;
+ var $have_48;
+ var $next_48;
+ var $ret_6;
+ if (($167 | 0) == 0) {
+ var $next_50 = $next_48;
+ var $have_50 = $have_48;
+ var $hold_46 = $hold_44;
+ var $bits_46 = $bits_44;
+ } else {
+ var $next_49 = $next_48;
+ var $have_49 = $have_48;
+ var $hold_45 = $hold_44;
+ var $bits_45 = $bits_44;
+ while (1) {
+ var $bits_45;
+ var $hold_45;
+ var $have_49;
+ var $next_49;
+ if (!($bits_45 >>> 0 < $167 >>> 0)) {
+ break;
+ }
+ if (($have_49 | 0) == 0) {
+ var $ret_8 = $ret_6;
+ var $next_58 = $next_49;
+ var $have_58 = 0;
+ var $hold_54 = $hold_45;
+ var $bits_54 = $bits_45;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $add1524 = ((HEAPU8[$next_49] & 255) << $bits_45) + $hold_45 | 0;
+ var $next_49 = $next_49 + 1 | 0;
+ var $have_49 = $have_49 - 1 | 0;
+ var $hold_45 = $add1524;
+ var $bits_45 = $bits_45 + 8 | 0;
+ }
+ var $add1536 = HEAP32[$30 >> 2] + (((1 << $167) - 1 | 0) & $hold_45) | 0;
+ HEAP32[$30 >> 2] = $add1536;
+ var $add1546 = HEAP32[$25 >> 2] + $167 | 0;
+ HEAP32[$25 >> 2] = $add1546;
+ var $next_50 = $next_49;
+ var $have_50 = $have_49;
+ var $hold_46 = $hold_45 >>> ($167 >>> 0);
+ var $bits_46 = $bits_45 - $167 | 0;
+ }
+ var $bits_46;
+ var $hold_46;
+ var $have_50;
+ var $next_50;
+ HEAP32[$mode >> 2] = 24;
+ var $ret_7 = $ret_6;
+ var $next_51 = $next_50;
+ var $have_51 = $have_50;
+ var $hold_47 = $hold_46;
+ var $bits_47 = $bits_46;
+ __label__ = 254;
+ break;
+ }
+ } while (0);
+ $_$380 : do {
+ if (__label__ == 254) {
+ var $bits_47;
+ var $hold_47;
+ var $have_51;
+ var $next_51;
+ var $ret_7;
+ if (($left_0 | 0) == 0) {
+ var $ret_8 = $ret_7;
+ var $next_58 = $next_51;
+ var $have_58 = $have_51;
+ var $hold_54 = $hold_47;
+ var $bits_54 = $bits_47;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $sub1554 = $out_0 - $left_0 | 0;
+ var $171 = HEAPU32[$30 >> 2];
+ var $cmp1556 = $171 >>> 0 > $sub1554 >>> 0;
+ do {
+ if ($cmp1556) {
+ var $sub1560 = $171 - $sub1554 | 0;
+ var $cmp1561 = $sub1560 >>> 0 > HEAPU32[$31 >> 2] >>> 0;
+ do {
+ if ($cmp1561) {
+ if ((HEAP32[$32 >> 2] | 0) == 0) {
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str169 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_51;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ break $_$380;
+ }
+ } while (0);
+ var $174 = HEAPU32[$33 >> 2];
+ if ($sub1560 >>> 0 > $174 >>> 0) {
+ var $sub1574 = $sub1560 - $174 | 0;
+ var $from_0 = HEAP32[$34 >> 2] + (HEAP32[$35 >> 2] - $sub1574 | 0) | 0;
+ var $copy_7 = $sub1574;
+ } else {
+ var $from_0 = HEAP32[$34 >> 2] + ($174 - $sub1560 | 0) | 0;
+ var $copy_7 = $sub1560;
+ }
+ var $copy_7;
+ var $from_0;
+ var $178 = HEAPU32[$21 >> 2];
+ if (!($copy_7 >>> 0 > $178 >>> 0)) {
+ var $from_1 = $from_0;
+ var $copy_8 = $copy_7;
+ var $180 = $178;
+ break;
+ }
+ var $from_1 = $from_0;
+ var $copy_8 = $178;
+ var $180 = $178;
+ } else {
+ var $179 = HEAP32[$21 >> 2];
+ var $from_1 = $put_0 + (-$171 | 0) | 0;
+ var $copy_8 = $179;
+ var $180 = $179;
+ }
+ } while (0);
+ var $180;
+ var $copy_8;
+ var $from_1;
+ var $copy_9 = $copy_8 >>> 0 > $left_0 >>> 0 ? $left_0 : $copy_8;
+ HEAP32[$21 >> 2] = $180 - $copy_9 | 0;
+ var $181 = $copy_8 ^ -1;
+ var $182 = $left_0 ^ -1;
+ var $umax = $181 >>> 0 > $182 >>> 0 ? $181 : $182;
+ var $from_2 = $from_1;
+ var $put_1 = $put_0;
+ var $copy_10 = $copy_9;
+ while (1) {
+ var $copy_10;
+ var $put_1;
+ var $from_2;
+ var $184 = HEAP8[$from_2];
+ HEAP8[$put_1] = $184;
+ var $dec1605 = $copy_10 - 1 | 0;
+ if (($dec1605 | 0) == 0) {
+ break;
+ }
+ var $from_2 = $from_2 + 1 | 0;
+ var $put_1 = $put_1 + 1 | 0;
+ var $copy_10 = $dec1605;
+ }
+ var $sub1598 = $left_0 - $copy_9 | 0;
+ var $scevgep632 = $put_0 + ($umax ^ -1) | 0;
+ if (!((HEAP32[$21 >> 2] | 0) == 0)) {
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $scevgep632;
+ var $have_0_be = $have_51;
+ var $left_0_be = $sub1598;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ break;
+ }
+ HEAP32[$mode >> 2] = 20;
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $scevgep632;
+ var $have_0_be = $have_51;
+ var $left_0_be = $sub1598;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ }
+ } while (0);
+ var $out_0_be;
+ var $bits_0_be;
+ var $hold_0_be;
+ var $left_0_be;
+ var $have_0_be;
+ var $put_0_be;
+ var $next_0_be;
+ var $ret_0_be;
+ var $ret_0 = $ret_0_be;
+ var $next_0 = $next_0_be;
+ var $put_0 = $put_0_be;
+ var $have_0 = $have_0_be;
+ var $left_0 = $left_0_be;
+ var $hold_0 = $hold_0_be;
+ var $bits_0 = $bits_0_be;
+ var $out_0 = $out_0_be;
+ var $49 = HEAP32[$mode >> 2];
+ }
+ var $out_4;
+ var $bits_54;
+ var $hold_54;
+ var $have_58;
+ var $next_58;
+ var $ret_8;
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_58;
+ HEAP32[$avail_in15 >> 2] = $have_58;
+ HEAP32[$11 >> 2] = $hold_54;
+ HEAP32[$13 >> 2] = $bits_54;
+ var $tobool1755 = (HEAP32[$35 >> 2] | 0) == 0;
+ do {
+ if ($tobool1755) {
+ if (!(HEAPU32[$mode >> 2] >>> 0 < 26)) {
+ __label__ = 300;
+ break;
+ }
+ if (($out_4 | 0) == (HEAP32[$avail_out >> 2] | 0)) {
+ __label__ = 300;
+ break;
+ }
+ __label__ = 298;
+ break;
+ } else {
+ __label__ = 298;
+ }
+ } while (0);
+ do {
+ if (__label__ == 298) {
+ var $call1765 = _updatewindow($strm, $out_4);
+ if (($call1765 | 0) == 0) {
+ break;
+ }
+ HEAP32[$mode >> 2] = 30;
+ var $retval_0 = -4;
+ break $_$2;
+ }
+ } while (0);
+ var $202 = HEAPU32[$avail_in15 >> 2];
+ var $203 = HEAPU32[$avail_out >> 2];
+ var $sub1774 = $out_4 - $203 | 0;
+ var $total_in = $strm + 8 | 0;
+ var $add1775 = ($10 - $202 | 0) + HEAP32[$total_in >> 2] | 0;
+ HEAP32[$total_in >> 2] = $add1775;
+ var $add1777 = HEAP32[$total_out >> 2] + $sub1774 | 0;
+ HEAP32[$total_out >> 2] = $add1777;
+ var $add1779 = HEAP32[$36 >> 2] + $sub1774 | 0;
+ HEAP32[$36 >> 2] = $add1779;
+ var $tobool1783 = ($out_4 | 0) == ($203 | 0);
+ if (!((HEAP32[$15 >> 2] | 0) == 0 | $tobool1783)) {
+ var $209 = HEAP32[$16 >> 2];
+ var $add_ptr1791 = HEAP32[$next_out >> 2] + (-$sub1774 | 0) | 0;
+ if ((HEAP32[$17 >> 2] | 0) == 0) {
+ var $call1798 = _adler32($209, $add_ptr1791, $sub1774);
+ var $cond1800 = $call1798;
+ } else {
+ var $call1792 = _crc32($209, $add_ptr1791, $sub1774);
+ var $cond1800 = $call1792;
+ }
+ var $cond1800;
+ HEAP32[$16 >> 2] = $cond1800;
+ HEAP32[$adler >> 2] = $cond1800;
+ }
+ var $cond1807 = (HEAP32[$24 >> 2] | 0) != 0 ? 64 : 0;
+ var $213 = HEAP32[$mode >> 2];
+ var $cond1812 = ($213 | 0) == 11 ? 128 : 0;
+ if (($213 | 0) == 19) {
+ var $214 = 256;
+ } else {
+ var $phitmp = ($213 | 0) == 14 ? 256 : 0;
+ var $214 = $phitmp;
+ }
+ var $214;
+ var $add1821 = (($cond1807 + HEAP32[$13 >> 2] | 0) + $cond1812 | 0) + $214 | 0;
+ HEAP32[($strm + 44 | 0) >> 2] = $add1821;
+ var $ret_9 = (($10 | 0) == ($202 | 0) & $tobool1783 | ($flush | 0) == 4) & ($ret_8 | 0) == 0 ? -5 : $ret_8;
+ var $retval_0 = $ret_9;
+ }
+ } while (0);
+ var $retval_0;
+ STACKTOP = __stackBase__;
+ return $retval_0;
+ return null;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate"]
diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js
index 55f74d67..a2d62a25 100644
--- a/tools/eliminator/eliminator-test.js
+++ b/tools/eliminator/eliminator-test.js
@@ -140,4 +140,3304 @@ function llvm3_1() {
run($j_0 / 2);
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1"]
+function _inflate($strm, $flush) {
+ var __stackBase__ = STACKTOP;
+ STACKTOP += 4;
+ var __label__;
+ var $hbuf = __stackBase__;
+ var $cmp = ($strm | 0) == 0;
+ $_$2 : do {
+ if ($cmp) {
+ var $retval_0 = -2;
+ } else {
+ var $state1 = $strm + 28 | 0;
+ var $0 = HEAPU32[$state1 >> 2];
+ var $cmp2 = ($0 | 0) == 0;
+ if ($cmp2) {
+ var $retval_0 = -2;
+ break;
+ }
+ var $next_out = $strm + 12 | 0;
+ var $1 = HEAP32[$next_out >> 2];
+ var $cmp4 = ($1 | 0) == 0;
+ if ($cmp4) {
+ var $retval_0 = -2;
+ break;
+ }
+ var $next_in = $strm | 0;
+ var $2 = HEAP32[$next_in >> 2];
+ var $cmp6 = ($2 | 0) == 0;
+ if ($cmp6) {
+ var $avail_in = $strm + 4 | 0;
+ var $3 = HEAP32[$avail_in >> 2];
+ var $cmp7 = ($3 | 0) == 0;
+ if (!$cmp7) {
+ var $retval_0 = -2;
+ break;
+ }
+ }
+ var $4 = $0;
+ var $mode = $0 | 0;
+ var $5 = HEAP32[$mode >> 2];
+ var $cmp9 = ($5 | 0) == 11;
+ if ($cmp9) {
+ HEAP32[$mode >> 2] = 12;
+ var $_pre = HEAP32[$next_out >> 2];
+ var $_pre882 = HEAP32[$next_in >> 2];
+ var $8 = $_pre;
+ var $7 = $_pre882;
+ var $6 = 12;
+ } else {
+ var $8 = $1;
+ var $7 = $2;
+ var $6 = $5;
+ }
+ var $6;
+ var $7;
+ var $8;
+ var $avail_out = $strm + 16 | 0;
+ var $9 = HEAP32[$avail_out >> 2];
+ var $avail_in15 = $strm + 4 | 0;
+ var $10 = HEAPU32[$avail_in15 >> 2];
+ var $11 = $0 + 56 | 0;
+ var $12 = HEAP32[$11 >> 2];
+ var $13 = $0 + 60 | 0;
+ var $14 = HEAP32[$13 >> 2];
+ var $15 = $0 + 8 | 0;
+ var $16 = $0 + 24 | 0;
+ var $arrayidx = $hbuf | 0;
+ var $arrayidx40 = $hbuf + 1 | 0;
+ var $17 = $0 + 16 | 0;
+ var $head = $0 + 32 | 0;
+ var $18 = $head;
+ var $msg = $strm + 24 | 0;
+ var $19 = $0 + 36 | 0;
+ var $20 = $0 + 20 | 0;
+ var $adler = $strm + 48 | 0;
+ var $21 = $0 + 64 | 0;
+ var $22 = $0 + 12 | 0;
+ var $flush_off = $flush - 5 | 0;
+ var $23 = $flush_off >>> 0 < 2;
+ var $24 = $0 + 4 | 0;
+ var $cmp660 = ($flush | 0) == 6;
+ var $25 = $0 + 7108 | 0;
+ var $26 = $0 + 84 | 0;
+ var $lencode1215 = $0 + 76 | 0;
+ var $27 = $lencode1215;
+ var $28 = $0 + 72 | 0;
+ var $29 = $0 + 7112 | 0;
+ var $30 = $0 + 68 | 0;
+ var $31 = $0 + 44 | 0;
+ var $32 = $0 + 7104 | 0;
+ var $33 = $0 + 48 | 0;
+ var $window = $0 + 52 | 0;
+ var $34 = $window;
+ var $35 = $0 + 40 | 0;
+ var $total_out = $strm + 20 | 0;
+ var $36 = $0 + 28 | 0;
+ var $arrayidx199 = $hbuf + 2 | 0;
+ var $arrayidx202 = $hbuf + 3 | 0;
+ var $37 = $0 + 96 | 0;
+ var $38 = $0 + 100 | 0;
+ var $39 = $0 + 92 | 0;
+ var $40 = $0 + 104 | 0;
+ var $lens = $0 + 112 | 0;
+ var $41 = $lens;
+ var $codes = $0 + 1328 | 0;
+ var $next861 = $0 + 108 | 0;
+ var $42 = $next861;
+ var $43 = $next861 | 0;
+ var $arraydecay860_c = $codes;
+ var $44 = $0 + 76 | 0;
+ var $arraydecay864 = $lens;
+ var $work = $0 + 752 | 0;
+ var $arraydecay867 = $work;
+ var $arrayidx1128 = $0 + 624 | 0;
+ var $45 = $arrayidx1128;
+ var $46 = $0 + 80 | 0;
+ var $47 = $0 + 88 | 0;
+ var $distcode1395 = $0 + 80 | 0;
+ var $48 = $distcode1395;
+ var $ret_0 = 0;
+ var $next_0 = $7;
+ var $put_0 = $8;
+ var $have_0 = $10;
+ var $left_0 = $9;
+ var $hold_0 = $12;
+ var $bits_0 = $14;
+ var $out_0 = $9;
+ var $49 = $6;
+ $_$12 : while (1) {
+ var $49;
+ var $out_0;
+ var $bits_0;
+ var $hold_0;
+ var $left_0;
+ var $have_0;
+ var $put_0;
+ var $next_0;
+ var $ret_0;
+ $_$14 : do {
+ if (($49 | 0) == 0) {
+ var $50 = HEAPU32[$15 >> 2];
+ var $cmp19 = ($50 | 0) == 0;
+ if ($cmp19) {
+ HEAP32[$mode >> 2] = 12;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_0;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_0;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_0;
+ var $bits_0_be = $bits_0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $next_1 = $next_0;
+ var $have_1 = $have_0;
+ var $hold_1 = $hold_0;
+ var $bits_1 = $bits_0;
+ while (1) {
+ var $bits_1;
+ var $hold_1;
+ var $have_1;
+ var $next_1;
+ var $cmp24 = $bits_1 >>> 0 < 16;
+ if (!$cmp24) {
+ break;
+ }
+ var $cmp26 = ($have_1 | 0) == 0;
+ if ($cmp26) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_1;
+ var $have_58 = 0;
+ var $hold_54 = $hold_1;
+ var $bits_54 = $bits_1;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ // XXX first chunk with a difference (no impact)
+ var $dec = $have_1 - 1 | 0;
+ var $incdec_ptr = $next_1 + 1 | 0;
+ var $51 = HEAPU8[$next_1];
+ var $conv = $51 & 255;
+ var $shl = $conv << $bits_1;
+ var $add = $shl + $hold_1 | 0;
+ var $add29 = $bits_1 + 8 | 0;
+ var $next_1 = $incdec_ptr;
+ var $have_1 = $dec;
+ var $hold_1 = $add;
+ var $bits_1 = $add29;
+ }
+ var $and = $50 & 2;
+ var $tobool = ($and | 0) != 0;
+ var $cmp34 = ($hold_1 | 0) == 35615;
+ var $or_cond = $tobool & $cmp34;
+ if ($or_cond) {
+ var $call = _crc32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call;
+ HEAP8[$arrayidx] = 31;
+ HEAP8[$arrayidx40] = -117;
+ var $52 = HEAP32[$16 >> 2];
+ var $call42 = _crc32($52, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call42;
+ HEAP32[$mode >> 2] = 1;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = 0;
+ var $bits_0_be = 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$17 >> 2] = 0;
+ var $53 = HEAP32[$18 >> 2];
+ var $cmp49 = ($53 | 0) == 0;
+ if ($cmp49) {
+ var $54 = $50;
+ } else {
+ var $done = $53 + 48 | 0;
+ HEAP32[$done >> 2] = -1;
+ var $_pre884 = HEAP32[$15 >> 2];
+ var $54 = $_pre884;
+ }
+ var $54;
+ var $and55 = $54 & 1;
+ var $tobool56 = ($and55 | 0) == 0;
+ do {
+ if (!$tobool56) {
+ var $and58 = $hold_1 << 8;
+ var $shl59 = $and58 & 65280;
+ var $shr60 = $hold_1 >>> 8;
+ var $add61 = $shl59 + $shr60 | 0;
+ var $rem = ($add61 >>> 0) % 31;
+ var $tobool62 = ($rem | 0) == 0;
+ if (!$tobool62) {
+ break;
+ }
+ var $and66 = $hold_1 & 15;
+ var $cmp67 = ($and66 | 0) == 8;
+ if ($cmp67) {
+ var $shr74 = $hold_1 >>> 4;
+ var $sub = $bits_1 - 4 | 0;
+ var $and76 = $shr74 & 15;
+ var $add77 = $and76 + 8 | 0;
+ var $55 = HEAPU32[$19 >> 2];
+ var $cmp78 = ($55 | 0) == 0;
+ do {
+ if (!$cmp78) {
+ var $cmp83 = $add77 >>> 0 > $55 >>> 0;
+ if (!$cmp83) {
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str3100 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr74;
+ var $bits_0_be = $sub;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ HEAP32[$19 >> 2] = $add77;
+ } while (0);
+ var $shl90 = 1 << $add77;
+ HEAP32[$20 >> 2] = $shl90;
+ var $call91 = _adler32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call91;
+ HEAP32[$adler >> 2] = $call91;
+ var $and93 = $hold_1 >>> 12;
+ var $56 = $and93 & 2;
+ var $57 = $56 ^ 11;
+ HEAP32[$mode >> 2] = $57;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = 0;
+ var $bits_0_be = 0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str299 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_1;
+ var $bits_0_be = $bits_1;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ } while (0);
+ HEAP32[$msg >> 2] = STRING_TABLE.__str198 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_1;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_1;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_1;
+ var $bits_0_be = $bits_1;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 1) {
+ var $next_2 = $next_0;
+ var $have_2 = $have_0;
+ var $hold_2 = $hold_0;
+ var $bits_2 = $bits_0;
+ while (1) {
+ var $bits_2;
+ var $hold_2;
+ var $have_2;
+ var $next_2;
+ var $cmp101 = $bits_2 >>> 0 < 16;
+ if (!$cmp101) {
+ break;
+ }
+ var $cmp105 = ($have_2 | 0) == 0;
+ if ($cmp105) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_2;
+ var $have_58 = 0;
+ var $hold_54 = $hold_2;
+ var $bits_54 = $bits_2;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec109 = $have_2 - 1 | 0;
+ var $incdec_ptr110 = $next_2 + 1 | 0;
+ var $58 = HEAPU8[$next_2];
+ var $conv111 = $58 & 255;
+ var $shl112 = $conv111 << $bits_2;
+ var $add113 = $shl112 + $hold_2 | 0;
+ var $add114 = $bits_2 + 8 | 0;
+ var $next_2 = $incdec_ptr110;
+ var $have_2 = $dec109;
+ var $hold_2 = $add113;
+ var $bits_2 = $add114;
+ }
+ HEAP32[$17 >> 2] = $hold_2;
+ var $and120 = $hold_2 & 255;
+ var $cmp121 = ($and120 | 0) == 8;
+ if (!$cmp121) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str299 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_2;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_2;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_2;
+ var $bits_0_be = $bits_2;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $and128 = $hold_2 & 57344;
+ var $tobool129 = ($and128 | 0) == 0;
+ if ($tobool129) {
+ var $59 = HEAPU32[$18 >> 2];
+ var $cmp135 = ($59 | 0) == 0;
+ if ($cmp135) {
+ var $60 = $hold_2;
+ } else {
+ var $shr138 = $hold_2 >>> 8;
+ var $and139 = $shr138 & 1;
+ var $text = $59 | 0;
+ HEAP32[$text >> 2] = $and139;
+ var $_pre887 = HEAP32[$17 >> 2];
+ var $60 = $_pre887;
+ }
+ var $60;
+ var $and143 = $60 & 512;
+ var $tobool144 = ($and143 | 0) == 0;
+ if (!$tobool144) {
+ var $conv147 = $hold_2 & 255;
+ HEAP8[$arrayidx] = $conv147;
+ var $shr149 = $hold_2 >>> 8;
+ var $conv150 = $shr149 & 255;
+ HEAP8[$arrayidx40] = $conv150;
+ var $61 = HEAP32[$16 >> 2];
+ var $call154 = _crc32($61, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call154;
+ }
+ HEAP32[$mode >> 2] = 2;
+ var $next_3 = $next_2;
+ var $have_3 = $have_2;
+ var $hold_3 = 0;
+ var $bits_3 = 0;
+ __label__ = 44;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str4101 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_2;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_2;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_2;
+ var $bits_0_be = $bits_2;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 2) {
+ var $next_3 = $next_0;
+ var $have_3 = $have_0;
+ var $hold_3 = $hold_0;
+ var $bits_3 = $bits_0;
+ __label__ = 44;
+ } else if (($49 | 0) == 3) {
+ var $next_4 = $next_0;
+ var $have_4 = $have_0;
+ var $hold_4 = $hold_0;
+ var $bits_4 = $bits_0;
+ __label__ = 52;
+ } else if (($49 | 0) == 4) {
+ var $next_5 = $next_0;
+ var $have_5 = $have_0;
+ var $hold_5 = $hold_0;
+ var $bits_5 = $bits_0;
+ __label__ = 60;
+ } else if (($49 | 0) == 5) {
+ var $next_8 = $next_0;
+ var $have_8 = $have_0;
+ var $hold_8 = $hold_0;
+ var $bits_8 = $bits_0;
+ __label__ = 71;
+ } else if (($49 | 0) == 6) {
+ var $_pre888 = HEAP32[$17 >> 2];
+ var $next_11 = $next_0;
+ var $have_11 = $have_0;
+ var $hold_9 = $hold_0;
+ var $bits_9 = $bits_0;
+ var $89 = $_pre888;
+ __label__ = 81;
+ break;
+ } else if (($49 | 0) == 7) {
+ var $next_13 = $next_0;
+ var $have_13 = $have_0;
+ var $hold_10 = $hold_0;
+ var $bits_10 = $bits_0;
+ __label__ = 94;
+ } else if (($49 | 0) == 8) {
+ var $next_15 = $next_0;
+ var $have_15 = $have_0;
+ var $hold_11 = $hold_0;
+ var $bits_11 = $bits_0;
+ __label__ = 107;
+ } else if (($49 | 0) == 9) {
+ var $next_18 = $next_0;
+ var $have_18 = $have_0;
+ var $hold_14 = $hold_0;
+ var $bits_14 = $bits_0;
+ while (1) {
+ var $bits_14;
+ var $hold_14;
+ var $have_18;
+ var $next_18;
+ var $cmp552 = $bits_14 >>> 0 < 32;
+ if (!$cmp552) {
+ break;
+ }
+ var $cmp556 = ($have_18 | 0) == 0;
+ if ($cmp556) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_18;
+ var $have_58 = 0;
+ var $hold_54 = $hold_14;
+ var $bits_54 = $bits_14;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec560 = $have_18 - 1 | 0;
+ var $incdec_ptr561 = $next_18 + 1 | 0;
+ var $114 = HEAPU8[$next_18];
+ var $conv562 = $114 & 255;
+ var $shl563 = $conv562 << $bits_14;
+ var $add564 = $shl563 + $hold_14 | 0;
+ var $add565 = $bits_14 + 8 | 0;
+ var $next_18 = $incdec_ptr561;
+ var $have_18 = $dec560;
+ var $hold_14 = $add564;
+ var $bits_14 = $add565;
+ }
+ var $add581 = _llvm_bswap_i32($hold_14);
+ HEAP32[$16 >> 2] = $add581;
+ HEAP32[$adler >> 2] = $add581;
+ HEAP32[$mode >> 2] = 10;
+ var $next_19 = $next_18;
+ var $have_19 = $have_18;
+ var $hold_15 = 0;
+ var $bits_15 = 0;
+ __label__ = 120;
+ break;
+ } else if (($49 | 0) == 10) {
+ var $next_19 = $next_0;
+ var $have_19 = $have_0;
+ var $hold_15 = $hold_0;
+ var $bits_15 = $bits_0;
+ __label__ = 120;
+ } else if (($49 | 0) == 11) {
+ var $next_20 = $next_0;
+ var $have_20 = $have_0;
+ var $hold_16 = $hold_0;
+ var $bits_16 = $bits_0;
+ __label__ = 123;
+ } else if (($49 | 0) == 12) {
+ var $next_21 = $next_0;
+ var $have_21 = $have_0;
+ var $hold_17 = $hold_0;
+ var $bits_17 = $bits_0;
+ __label__ = 124;
+ } else if (($49 | 0) == 13) {
+ var $and681 = $bits_0 & 7;
+ var $shr682 = $hold_0 >>> ($and681 >>> 0);
+ var $sub684 = $bits_0 - $and681 | 0;
+ var $next_23 = $next_0;
+ var $have_23 = $have_0;
+ var $hold_19 = $shr682;
+ var $bits_19 = $sub684;
+ while (1) {
+ var $bits_19;
+ var $hold_19;
+ var $have_23;
+ var $next_23;
+ var $cmp689 = $bits_19 >>> 0 < 32;
+ if (!$cmp689) {
+ break;
+ }
+ var $cmp693 = ($have_23 | 0) == 0;
+ if ($cmp693) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_23;
+ var $have_58 = 0;
+ var $hold_54 = $hold_19;
+ var $bits_54 = $bits_19;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec697 = $have_23 - 1 | 0;
+ var $incdec_ptr698 = $next_23 + 1 | 0;
+ var $118 = HEAPU8[$next_23];
+ var $conv699 = $118 & 255;
+ var $shl700 = $conv699 << $bits_19;
+ var $add701 = $shl700 + $hold_19 | 0;
+ var $add702 = $bits_19 + 8 | 0;
+ var $next_23 = $incdec_ptr698;
+ var $have_23 = $dec697;
+ var $hold_19 = $add701;
+ var $bits_19 = $add702;
+ }
+ var $and708 = $hold_19 & 65535;
+ var $shr709 = $hold_19 >>> 16;
+ var $xor = $shr709 ^ 65535;
+ var $cmp710 = ($and708 | 0) == ($xor | 0);
+ if (!$cmp710) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str7104 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_23;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_23;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_19;
+ var $bits_0_be = $bits_19;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$21 >> 2] = $and708;
+ HEAP32[$mode >> 2] = 14;
+ if ($cmp660) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_23;
+ var $have_58 = $have_23;
+ var $hold_54 = 0;
+ var $bits_54 = 0;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_24 = $next_23;
+ var $have_24 = $have_23;
+ var $hold_20 = 0;
+ var $bits_20 = 0;
+ __label__ = 143;
+ break;
+ } else if (($49 | 0) == 14) {
+ var $next_24 = $next_0;
+ var $have_24 = $have_0;
+ var $hold_20 = $hold_0;
+ var $bits_20 = $bits_0;
+ __label__ = 143;
+ } else if (($49 | 0) == 15) {
+ var $next_25 = $next_0;
+ var $have_25 = $have_0;
+ var $hold_21 = $hold_0;
+ var $bits_21 = $bits_0;
+ __label__ = 144;
+ } else if (($49 | 0) == 16) {
+ var $next_26 = $next_0;
+ var $have_26 = $have_0;
+ var $hold_22 = $hold_0;
+ var $bits_22 = $bits_0;
+ while (1) {
+ var $bits_22;
+ var $hold_22;
+ var $have_26;
+ var $next_26;
+ var $cmp755 = $bits_22 >>> 0 < 14;
+ if (!$cmp755) {
+ break;
+ }
+ var $cmp759 = ($have_26 | 0) == 0;
+ if ($cmp759) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_26;
+ var $have_58 = 0;
+ var $hold_54 = $hold_22;
+ var $bits_54 = $bits_22;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec763 = $have_26 - 1 | 0;
+ var $incdec_ptr764 = $next_26 + 1 | 0;
+ var $121 = HEAPU8[$next_26];
+ var $conv765 = $121 & 255;
+ var $shl766 = $conv765 << $bits_22;
+ var $add767 = $shl766 + $hold_22 | 0;
+ var $add768 = $bits_22 + 8 | 0;
+ var $next_26 = $incdec_ptr764;
+ var $have_26 = $dec763;
+ var $hold_22 = $add767;
+ var $bits_22 = $add768;
+ }
+ var $and774 = $hold_22 & 31;
+ var $add775 = $and774 + 257 | 0;
+ HEAP32[$37 >> 2] = $add775;
+ var $shr777 = $hold_22 >>> 5;
+ var $and781 = $shr777 & 31;
+ var $add782 = $and781 + 1 | 0;
+ HEAP32[$38 >> 2] = $add782;
+ var $shr784 = $hold_22 >>> 10;
+ var $and788 = $shr784 & 15;
+ var $add789 = $and788 + 4 | 0;
+ HEAP32[$39 >> 2] = $add789;
+ var $shr791 = $hold_22 >>> 14;
+ var $sub792 = $bits_22 - 14 | 0;
+ var $cmp796 = $add775 >>> 0 > 286;
+ var $cmp800 = $add782 >>> 0 > 30;
+ var $or_cond894 = $cmp796 | $cmp800;
+ if ($or_cond894) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str8105 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_26;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_26;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr791;
+ var $bits_0_be = $sub792;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$40 >> 2] = 0;
+ HEAP32[$mode >> 2] = 17;
+ var $next_27 = $next_26;
+ var $have_27 = $have_26;
+ var $hold_23 = $shr791;
+ var $bits_23 = $sub792;
+ __label__ = 154;
+ break;
+ } else if (($49 | 0) == 17) {
+ var $next_27 = $next_0;
+ var $have_27 = $have_0;
+ var $hold_23 = $hold_0;
+ var $bits_23 = $bits_0;
+ __label__ = 154;
+ } else if (($49 | 0) == 18) {
+ var $ret_1_ph = $ret_0;
+ var $next_29_ph = $next_0;
+ var $have_29_ph = $have_0;
+ var $hold_25_ph = $hold_0;
+ var $bits_25_ph = $bits_0;
+ __label__ = 164;
+ } else if (($49 | 0) == 19) {
+ var $ret_2 = $ret_0;
+ var $next_37 = $next_0;
+ var $have_37 = $have_0;
+ var $hold_33 = $hold_0;
+ var $bits_33 = $bits_0;
+ __label__ = 205;
+ } else if (($49 | 0) == 20) {
+ var $ret_3 = $ret_0;
+ var $next_38 = $next_0;
+ var $have_38 = $have_0;
+ var $hold_34 = $hold_0;
+ var $bits_34 = $bits_0;
+ __label__ = 206;
+ } else if (($49 | 0) == 21) {
+ var $_pre889 = HEAP32[$28 >> 2];
+ var $ret_4 = $ret_0;
+ var $next_42 = $next_0;
+ var $have_42 = $have_0;
+ var $hold_38 = $hold_0;
+ var $bits_38 = $bits_0;
+ var $156 = $_pre889;
+ __label__ = 227;
+ break;
+ } else if (($49 | 0) == 22) {
+ var $ret_5_ph = $ret_0;
+ var $next_45_ph = $next_0;
+ var $have_45_ph = $have_0;
+ var $hold_41_ph = $hold_0;
+ var $bits_41_ph = $bits_0;
+ __label__ = 234;
+ } else if (($49 | 0) == 23) {
+ var $_pre891 = HEAP32[$28 >> 2];
+ var $ret_6 = $ret_0;
+ var $next_48 = $next_0;
+ var $have_48 = $have_0;
+ var $hold_44 = $hold_0;
+ var $bits_44 = $bits_0;
+ var $167 = $_pre891;
+ __label__ = 248;
+ break;
+ } else if (($49 | 0) == 24) {
+ var $ret_7 = $ret_0;
+ var $next_51 = $next_0;
+ var $have_51 = $have_0;
+ var $hold_47 = $hold_0;
+ var $bits_47 = $bits_0;
+ __label__ = 254;
+ } else if (($49 | 0) == 25) {
+ var $cmp1615 = ($left_0 | 0) == 0;
+ if ($cmp1615) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $186 = HEAP32[$21 >> 2];
+ var $conv1620 = $186 & 255;
+ var $incdec_ptr1621 = $put_0 + 1 | 0;
+ HEAP8[$put_0] = $conv1620;
+ var $dec1622 = $left_0 - 1 | 0;
+ HEAP32[$mode >> 2] = 20;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_0;
+ var $put_0_be = $incdec_ptr1621;
+ var $have_0_be = $have_0;
+ var $left_0_be = $dec1622;
+ var $hold_0_be = $hold_0;
+ var $bits_0_be = $bits_0;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (($49 | 0) == 26) {
+ var $187 = HEAP32[$15 >> 2];
+ var $tobool1626 = ($187 | 0) == 0;
+ do {
+ if (!$tobool1626) {
+ var $next_52 = $next_0;
+ var $have_52 = $have_0;
+ var $hold_48 = $hold_0;
+ var $bits_48 = $bits_0;
+ while (1) {
+ var $bits_48;
+ var $hold_48;
+ var $have_52;
+ var $next_52;
+ var $cmp1630 = $bits_48 >>> 0 < 32;
+ if (!$cmp1630) {
+ break;
+ }
+ var $cmp1634 = ($have_52 | 0) == 0;
+ if ($cmp1634) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_52;
+ var $have_58 = 0;
+ var $hold_54 = $hold_48;
+ var $bits_54 = $bits_48;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1638 = $have_52 - 1 | 0;
+ var $incdec_ptr1639 = $next_52 + 1 | 0;
+ var $188 = HEAPU8[$next_52];
+ var $conv1640 = $188 & 255;
+ var $shl1641 = $conv1640 << $bits_48;
+ var $add1642 = $shl1641 + $hold_48 | 0;
+ var $add1643 = $bits_48 + 8 | 0;
+ var $next_52 = $incdec_ptr1639;
+ var $have_52 = $dec1638;
+ var $hold_48 = $add1642;
+ var $bits_48 = $add1643;
+ }
+ var $sub1649 = $out_0 - $left_0 | 0;
+ var $189 = HEAP32[$total_out >> 2];
+ var $add1650 = $189 + $sub1649 | 0;
+ HEAP32[$total_out >> 2] = $add1650;
+ var $190 = HEAP32[$36 >> 2];
+ var $add1651 = $190 + $sub1649 | 0;
+ HEAP32[$36 >> 2] = $add1651;
+ var $tobool1652 = ($out_0 | 0) == ($left_0 | 0);
+ if (!$tobool1652) {
+ var $191 = HEAP32[$17 >> 2];
+ var $tobool1655 = ($191 | 0) == 0;
+ var $192 = HEAP32[$16 >> 2];
+ var $idx_neg1658 = -$sub1649 | 0;
+ var $add_ptr1659 = $put_0 + $idx_neg1658 | 0;
+ if ($tobool1655) {
+ var $call1665 = _adler32($192, $add_ptr1659, $sub1649);
+ var $cond1667 = $call1665;
+ } else {
+ var $call1660 = _crc32($192, $add_ptr1659, $sub1649);
+ var $cond1667 = $call1660;
+ }
+ var $cond1667;
+ HEAP32[$16 >> 2] = $cond1667;
+ HEAP32[$adler >> 2] = $cond1667;
+ }
+ var $193 = HEAP32[$17 >> 2];
+ var $tobool1672 = ($193 | 0) == 0;
+ if ($tobool1672) {
+ var $add1685 = _llvm_bswap_i32($hold_48);
+ var $cond1687 = $add1685;
+ } else {
+ var $cond1687 = $hold_48;
+ }
+ var $cond1687;
+ var $194 = HEAP32[$16 >> 2];
+ var $cmp1689 = ($cond1687 | 0) == ($194 | 0);
+ if ($cmp1689) {
+ var $next_53 = $next_52;
+ var $have_53 = $have_52;
+ var $hold_49 = 0;
+ var $bits_49 = 0;
+ var $out_1 = $left_0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str17114 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_52;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_52;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_48;
+ var $bits_0_be = $bits_48;
+ var $out_0_be = $left_0;
+ __label__ = 268;
+ break $_$14;
+ }
+ var $next_53 = $next_0;
+ var $have_53 = $have_0;
+ var $hold_49 = $hold_0;
+ var $bits_49 = $bits_0;
+ var $out_1 = $out_0;
+ } while (0);
+ var $out_1;
+ var $bits_49;
+ var $hold_49;
+ var $have_53;
+ var $next_53;
+ HEAP32[$mode >> 2] = 27;
+ var $next_54 = $next_53;
+ var $have_54 = $have_53;
+ var $hold_50 = $hold_49;
+ var $bits_50 = $bits_49;
+ var $out_2 = $out_1;
+ __label__ = 286;
+ break;
+ } else if (($49 | 0) == 27) {
+ var $next_54 = $next_0;
+ var $have_54 = $have_0;
+ var $hold_50 = $hold_0;
+ var $bits_50 = $bits_0;
+ var $out_2 = $out_0;
+ __label__ = 286;
+ } else if (($49 | 0) == 28) {
+ var $ret_8 = 1;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($49 | 0) == 29) {
+ var $ret_8 = -3;
+ var $next_58 = $next_0;
+ var $have_58 = $have_0;
+ var $hold_54 = $hold_0;
+ var $bits_54 = $bits_0;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($49 | 0) == 30) {
+ var $retval_0 = -4;
+ break $_$2;
+ } else {
+ var $retval_0 = -2;
+ break $_$2;
+ }
+ } while (0);
+ $_$106 : do {
+ if (__label__ == 44) {
+ while (1) {
+ var $bits_3;
+ var $hold_3;
+ var $have_3;
+ var $next_3;
+ var $cmp164 = $bits_3 >>> 0 < 32;
+ if (!$cmp164) {
+ break;
+ }
+ var $cmp168 = ($have_3 | 0) == 0;
+ if ($cmp168) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_3;
+ var $have_58 = 0;
+ var $hold_54 = $hold_3;
+ var $bits_54 = $bits_3;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec172 = $have_3 - 1 | 0;
+ var $incdec_ptr173 = $next_3 + 1 | 0;
+ var $62 = HEAPU8[$next_3];
+ var $conv174 = $62 & 255;
+ var $shl175 = $conv174 << $bits_3;
+ var $add176 = $shl175 + $hold_3 | 0;
+ var $add177 = $bits_3 + 8 | 0;
+ var $next_3 = $incdec_ptr173;
+ var $have_3 = $dec172;
+ var $hold_3 = $add176;
+ var $bits_3 = $add177;
+ }
+ var $63 = HEAP32[$18 >> 2];
+ var $cmp182 = ($63 | 0) == 0;
+ if (!$cmp182) {
+ var $time = $63 + 4 | 0;
+ HEAP32[$time >> 2] = $hold_3;
+ }
+ var $64 = HEAP32[$17 >> 2];
+ var $and188 = $64 & 512;
+ var $tobool189 = ($and188 | 0) == 0;
+ if (!$tobool189) {
+ var $conv192 = $hold_3 & 255;
+ HEAP8[$arrayidx] = $conv192;
+ var $shr194 = $hold_3 >>> 8;
+ var $conv195 = $shr194 & 255;
+ HEAP8[$arrayidx40] = $conv195;
+ var $shr197 = $hold_3 >>> 16;
+ var $conv198 = $shr197 & 255;
+ HEAP8[$arrayidx199] = $conv198;
+ var $shr200 = $hold_3 >>> 24;
+ var $conv201 = $shr200 & 255;
+ HEAP8[$arrayidx202] = $conv201;
+ var $65 = HEAP32[$16 >> 2];
+ var $call205 = _crc32($65, $arrayidx, 4);
+ HEAP32[$16 >> 2] = $call205;
+ }
+ HEAP32[$mode >> 2] = 3;
+ var $next_4 = $next_3;
+ var $have_4 = $have_3;
+ var $hold_4 = 0;
+ var $bits_4 = 0;
+ __label__ = 52;
+ break;
+ } else if (__label__ == 120) {
+ var $bits_15;
+ var $hold_15;
+ var $have_19;
+ var $next_19;
+ var $115 = HEAP32[$22 >> 2];
+ var $cmp589 = ($115 | 0) == 0;
+ if ($cmp589) {
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_19;
+ HEAP32[$avail_in15 >> 2] = $have_19;
+ HEAP32[$11 >> 2] = $hold_15;
+ HEAP32[$13 >> 2] = $bits_15;
+ var $retval_0 = 2;
+ break $_$2;
+ }
+ var $call602 = _adler32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call602;
+ HEAP32[$adler >> 2] = $call602;
+ HEAP32[$mode >> 2] = 11;
+ var $next_20 = $next_19;
+ var $have_20 = $have_19;
+ var $hold_16 = $hold_15;
+ var $bits_16 = $bits_15;
+ __label__ = 123;
+ break;
+ } else if (__label__ == 143) {
+ var $bits_20;
+ var $hold_20;
+ var $have_24;
+ var $next_24;
+ HEAP32[$mode >> 2] = 15;
+ var $next_25 = $next_24;
+ var $have_25 = $have_24;
+ var $hold_21 = $hold_20;
+ var $bits_21 = $bits_20;
+ __label__ = 144;
+ break;
+ } else if (__label__ == 154) {
+ while (1) {
+ var $bits_23;
+ var $hold_23;
+ var $have_27;
+ var $next_27;
+ var $122 = HEAPU32[$40 >> 2];
+ var $123 = HEAPU32[$39 >> 2];
+ var $cmp812 = $122 >>> 0 < $123 >>> 0;
+ if (!$cmp812) {
+ break;
+ }
+ var $next_28 = $next_27;
+ var $have_28 = $have_27;
+ var $hold_24 = $hold_23;
+ var $bits_24 = $bits_23;
+ while (1) {
+ var $bits_24;
+ var $hold_24;
+ var $have_28;
+ var $next_28;
+ var $cmp817 = $bits_24 >>> 0 < 3;
+ if (!$cmp817) {
+ break;
+ }
+ var $cmp821 = ($have_28 | 0) == 0;
+ if ($cmp821) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_28;
+ var $have_58 = 0;
+ var $hold_54 = $hold_24;
+ var $bits_54 = $bits_24;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec825 = $have_28 - 1 | 0;
+ var $incdec_ptr826 = $next_28 + 1 | 0;
+ var $124 = HEAPU8[$next_28];
+ var $conv827 = $124 & 255;
+ var $shl828 = $conv827 << $bits_24;
+ var $add829 = $shl828 + $hold_24 | 0;
+ var $add830 = $bits_24 + 8 | 0;
+ var $next_28 = $incdec_ptr826;
+ var $have_28 = $dec825;
+ var $hold_24 = $add829;
+ var $bits_24 = $add830;
+ }
+ var $hold_24_tr = $hold_24 & 65535;
+ var $conv837 = $hold_24_tr & 7;
+ var $inc839 = $122 + 1 | 0;
+ HEAP32[$40 >> 2] = $inc839;
+ var $arrayidx840 = _inflate_order + ($122 << 1) | 0;
+ var $125 = HEAPU16[$arrayidx840 >> 1];
+ var $idxprom = $125 & 65535;
+ var $arrayidx841 = $41 + ($idxprom << 1) | 0;
+ HEAP16[$arrayidx841 >> 1] = $conv837;
+ var $shr843 = $hold_24 >>> 3;
+ var $sub844 = $bits_24 - 3 | 0;
+ var $next_27 = $next_28;
+ var $have_27 = $have_28;
+ var $hold_23 = $shr843;
+ var $bits_23 = $sub844;
+ }
+ var $cmp850111 = $122 >>> 0 < 19;
+ $_$131 : do {
+ if ($cmp850111) {
+ var $126 = $122;
+ while (1) {
+ var $126;
+ var $inc854 = $126 + 1 | 0;
+ HEAP32[$40 >> 2] = $inc854;
+ var $arrayidx855 = _inflate_order + ($126 << 1) | 0;
+ var $127 = HEAPU16[$arrayidx855 >> 1];
+ var $idxprom856 = $127 & 65535;
+ var $arrayidx858 = $41 + ($idxprom856 << 1) | 0;
+ HEAP16[$arrayidx858 >> 1] = 0;
+ var $_pr = HEAPU32[$40 >> 2];
+ var $cmp850 = $_pr >>> 0 < 19;
+ if (!$cmp850) {
+ break $_$131;
+ }
+ var $126 = $_pr;
+ }
+ }
+ } while (0);
+ HEAP32[$43 >> 2] = $arraydecay860_c;
+ HEAP32[$44 >> 2] = $arraydecay860_c;
+ HEAP32[$26 >> 2] = 7;
+ var $call868 = _inflate_table(0, $arraydecay864, 19, $42, $26, $arraydecay867);
+ var $tobool869 = ($call868 | 0) == 0;
+ if ($tobool869) {
+ HEAP32[$40 >> 2] = 0;
+ HEAP32[$mode >> 2] = 18;
+ var $ret_1_ph = 0;
+ var $next_29_ph = $next_27;
+ var $have_29_ph = $have_27;
+ var $hold_25_ph = $hold_23;
+ var $bits_25_ph = $bits_23;
+ __label__ = 164;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str9106 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call868;
+ var $next_0_be = $next_27;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_27;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_23;
+ var $bits_0_be = $bits_23;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 286) {
+ var $out_2;
+ var $bits_50;
+ var $hold_50;
+ var $have_54;
+ var $next_54;
+ var $195 = HEAP32[$15 >> 2];
+ var $tobool1702 = ($195 | 0) == 0;
+ do {
+ if (!$tobool1702) {
+ var $196 = HEAP32[$17 >> 2];
+ var $tobool1705 = ($196 | 0) == 0;
+ if ($tobool1705) {
+ var $next_56 = $next_54;
+ var $have_56 = $have_54;
+ var $hold_52 = $hold_50;
+ var $bits_52 = $bits_50;
+ break;
+ }
+ var $next_55 = $next_54;
+ var $have_55 = $have_54;
+ var $hold_51 = $hold_50;
+ var $bits_51 = $bits_50;
+ while (1) {
+ var $bits_51;
+ var $hold_51;
+ var $have_55;
+ var $next_55;
+ var $cmp1709 = $bits_51 >>> 0 < 32;
+ if (!$cmp1709) {
+ break;
+ }
+ var $cmp1713 = ($have_55 | 0) == 0;
+ if ($cmp1713) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_55;
+ var $have_58 = 0;
+ var $hold_54 = $hold_51;
+ var $bits_54 = $bits_51;
+ var $out_4 = $out_2;
+ break $_$12;
+ }
+ var $dec1717 = $have_55 - 1 | 0;
+ var $incdec_ptr1718 = $next_55 + 1 | 0;
+ var $197 = HEAPU8[$next_55];
+ var $conv1719 = $197 & 255;
+ var $shl1720 = $conv1719 << $bits_51;
+ var $add1721 = $shl1720 + $hold_51 | 0;
+ var $add1722 = $bits_51 + 8 | 0;
+ var $next_55 = $incdec_ptr1718;
+ var $have_55 = $dec1717;
+ var $hold_51 = $add1721;
+ var $bits_51 = $add1722;
+ }
+ var $198 = HEAP32[$36 >> 2];
+ var $cmp1729 = ($hold_51 | 0) == ($198 | 0);
+ if ($cmp1729) {
+ var $next_56 = $next_55;
+ var $have_56 = $have_55;
+ var $hold_52 = 0;
+ var $bits_52 = 0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str18115 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_55;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_55;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_51;
+ var $bits_0_be = $bits_51;
+ var $out_0_be = $out_2;
+ __label__ = 268;
+ break $_$106;
+ }
+ var $next_56 = $next_54;
+ var $have_56 = $have_54;
+ var $hold_52 = $hold_50;
+ var $bits_52 = $bits_50;
+ } while (0);
+ var $bits_52;
+ var $hold_52;
+ var $have_56;
+ var $next_56;
+ HEAP32[$mode >> 2] = 28;
+ var $ret_8 = 1;
+ var $next_58 = $next_56;
+ var $have_58 = $have_56;
+ var $hold_54 = $hold_52;
+ var $bits_54 = $bits_52;
+ var $out_4 = $out_2;
+ break $_$12;
+ }
+ } while (0);
+ $_$148 : do {
+ if (__label__ == 52) {
+ while (1) {
+ var $bits_4;
+ var $hold_4;
+ var $have_4;
+ var $next_4;
+ var $cmp215 = $bits_4 >>> 0 < 16;
+ if (!$cmp215) {
+ break;
+ }
+ var $cmp219 = ($have_4 | 0) == 0;
+ if ($cmp219) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_4;
+ var $have_58 = 0;
+ var $hold_54 = $hold_4;
+ var $bits_54 = $bits_4;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec223 = $have_4 - 1 | 0;
+ var $incdec_ptr224 = $next_4 + 1 | 0;
+ var $66 = HEAPU8[$next_4];
+ var $conv225 = $66 & 255;
+ var $shl226 = $conv225 << $bits_4;
+ var $add227 = $shl226 + $hold_4 | 0;
+ var $add228 = $bits_4 + 8 | 0;
+ var $next_4 = $incdec_ptr224;
+ var $have_4 = $dec223;
+ var $hold_4 = $add227;
+ var $bits_4 = $add228;
+ }
+ var $67 = HEAP32[$18 >> 2];
+ var $cmp233 = ($67 | 0) == 0;
+ if (!$cmp233) {
+ var $and236 = $hold_4 & 255;
+ var $xflags = $67 + 8 | 0;
+ HEAP32[$xflags >> 2] = $and236;
+ var $shr238 = $hold_4 >>> 8;
+ var $68 = HEAP32[$18 >> 2];
+ var $os = $68 + 12 | 0;
+ HEAP32[$os >> 2] = $shr238;
+ }
+ var $69 = HEAP32[$17 >> 2];
+ var $and242 = $69 & 512;
+ var $tobool243 = ($and242 | 0) == 0;
+ if (!$tobool243) {
+ var $conv246 = $hold_4 & 255;
+ HEAP8[$arrayidx] = $conv246;
+ var $shr248 = $hold_4 >>> 8;
+ var $conv249 = $shr248 & 255;
+ HEAP8[$arrayidx40] = $conv249;
+ var $70 = HEAP32[$16 >> 2];
+ var $call253 = _crc32($70, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call253;
+ }
+ HEAP32[$mode >> 2] = 4;
+ var $next_5 = $next_4;
+ var $have_5 = $have_4;
+ var $hold_5 = 0;
+ var $bits_5 = 0;
+ __label__ = 60;
+ break;
+ } else if (__label__ == 123) {
+ var $bits_16;
+ var $hold_16;
+ var $have_20;
+ var $next_20;
+ if ($23) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_20;
+ var $have_58 = $have_20;
+ var $hold_54 = $hold_16;
+ var $bits_54 = $bits_16;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_21 = $next_20;
+ var $have_21 = $have_20;
+ var $hold_17 = $hold_16;
+ var $bits_17 = $bits_16;
+ __label__ = 124;
+ break;
+ } else if (__label__ == 144) {
+ var $bits_21;
+ var $hold_21;
+ var $have_25;
+ var $next_25;
+ var $119 = HEAPU32[$21 >> 2];
+ var $tobool730 = ($119 | 0) == 0;
+ if ($tobool730) {
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_25;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_25;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_21;
+ var $bits_0_be = $bits_21;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $cmp732 = $119 >>> 0 > $have_25 >>> 0;
+ var $copy_3 = $cmp732 ? $have_25 : $119;
+ var $cmp736 = $copy_3 >>> 0 > $left_0 >>> 0;
+ var $copy_4 = $cmp736 ? $left_0 : $copy_3;
+ var $cmp740 = ($copy_4 | 0) == 0;
+ if ($cmp740) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_25;
+ var $have_58 = $have_25;
+ var $hold_54 = $hold_21;
+ var $bits_54 = $bits_21;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ _memcpy($put_0, $next_25, $copy_4, 1);
+ var $sub744 = $have_25 - $copy_4 | 0;
+ var $add_ptr745 = $next_25 + $copy_4 | 0;
+ var $sub746 = $left_0 - $copy_4 | 0;
+ var $add_ptr747 = $put_0 + $copy_4 | 0;
+ var $120 = HEAP32[$21 >> 2];
+ var $sub749 = $120 - $copy_4 | 0;
+ HEAP32[$21 >> 2] = $sub749;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $add_ptr745;
+ var $put_0_be = $add_ptr747;
+ var $have_0_be = $sub744;
+ var $left_0_be = $sub746;
+ var $hold_0_be = $hold_21;
+ var $bits_0_be = $bits_21;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 164) {
+ var $bits_25_ph;
+ var $hold_25_ph;
+ var $have_29_ph;
+ var $next_29_ph;
+ var $ret_1_ph;
+ var $next_29 = $next_29_ph;
+ var $have_29 = $have_29_ph;
+ var $hold_25 = $hold_25_ph;
+ var $bits_25 = $bits_25_ph;
+ $_$167 : while (1) {
+ var $bits_25;
+ var $hold_25;
+ var $have_29;
+ var $next_29;
+ var $128 = HEAPU32[$40 >> 2];
+ var $129 = HEAPU32[$37 >> 2];
+ var $130 = HEAP32[$38 >> 2];
+ var $add881 = $130 + $129 | 0;
+ var $cmp882 = $128 >>> 0 < $add881 >>> 0;
+ if ($cmp882) {
+ var $131 = HEAP32[$26 >> 2];
+ var $shl887 = 1 << $131;
+ var $sub888 = $shl887 - 1 | 0;
+ var $132 = HEAPU32[$27 >> 2];
+ var $next_30 = $next_29;
+ var $have_30 = $have_29;
+ var $hold_26 = $hold_25;
+ var $bits_26 = $bits_25;
+ while (1) {
+ var $bits_26;
+ var $hold_26;
+ var $have_30;
+ var $next_30;
+ var $and889 = $sub888 & $hold_26;
+ var $arrayidx891_1 = $132 + ($and889 << 2) + 1 | 0;
+ var $tmp25 = HEAPU8[$arrayidx891_1];
+ var $conv893 = $tmp25 & 255;
+ var $cmp894 = $conv893 >>> 0 > $bits_26 >>> 0;
+ if (!$cmp894) {
+ break;
+ }
+ var $cmp899 = ($have_30 | 0) == 0;
+ if ($cmp899) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_30;
+ var $have_58 = 0;
+ var $hold_54 = $hold_26;
+ var $bits_54 = $bits_26;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec903 = $have_30 - 1 | 0;
+ var $incdec_ptr904 = $next_30 + 1 | 0;
+ var $133 = HEAPU8[$next_30];
+ var $conv905 = $133 & 255;
+ var $shl906 = $conv905 << $bits_26;
+ var $add907 = $shl906 + $hold_26 | 0;
+ var $add908 = $bits_26 + 8 | 0;
+ var $next_30 = $incdec_ptr904;
+ var $have_30 = $dec903;
+ var $hold_26 = $add907;
+ var $bits_26 = $add908;
+ }
+ var $arrayidx891_2 = $132 + ($and889 << 2) + 2 | 0;
+ var $tmp26 = HEAPU16[$arrayidx891_2 >> 1];
+ var $cmp912 = ($tmp26 & 65535) < 16;
+ if ($cmp912) {
+ var $next_31 = $next_30;
+ var $have_31 = $have_30;
+ var $hold_27 = $hold_26;
+ var $bits_27 = $bits_26;
+ while (1) {
+ var $bits_27;
+ var $hold_27;
+ var $have_31;
+ var $next_31;
+ var $cmp919 = $bits_27 >>> 0 < $conv893 >>> 0;
+ if (!$cmp919) {
+ break;
+ }
+ var $cmp923 = ($have_31 | 0) == 0;
+ if ($cmp923) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_31;
+ var $have_58 = 0;
+ var $hold_54 = $hold_27;
+ var $bits_54 = $bits_27;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec927 = $have_31 - 1 | 0;
+ var $incdec_ptr928 = $next_31 + 1 | 0;
+ var $134 = HEAPU8[$next_31];
+ var $conv929 = $134 & 255;
+ var $shl930 = $conv929 << $bits_27;
+ var $add931 = $shl930 + $hold_27 | 0;
+ var $add932 = $bits_27 + 8 | 0;
+ var $next_31 = $incdec_ptr928;
+ var $have_31 = $dec927;
+ var $hold_27 = $add931;
+ var $bits_27 = $add932;
+ }
+ var $shr941 = $hold_27 >>> ($conv893 >>> 0);
+ var $sub944 = $bits_27 - $conv893 | 0;
+ var $inc949 = $128 + 1 | 0;
+ HEAP32[$40 >> 2] = $inc949;
+ var $arrayidx951 = $41 + ($128 << 1) | 0;
+ HEAP16[$arrayidx951 >> 1] = $tmp26;
+ var $next_29 = $next_31;
+ var $have_29 = $have_31;
+ var $hold_25 = $shr941;
+ var $bits_25 = $sub944;
+ } else {
+ if ($tmp26 << 16 >> 16 == 16) {
+ var $add962 = $conv893 + 2 | 0;
+ var $next_32 = $next_30;
+ var $have_32 = $have_30;
+ var $hold_28 = $hold_26;
+ var $bits_28 = $bits_26;
+ while (1) {
+ var $bits_28;
+ var $hold_28;
+ var $have_32;
+ var $next_32;
+ var $cmp963 = $bits_28 >>> 0 < $add962 >>> 0;
+ if (!$cmp963) {
+ break;
+ }
+ var $cmp967 = ($have_32 | 0) == 0;
+ if ($cmp967) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_32;
+ var $have_58 = 0;
+ var $hold_54 = $hold_28;
+ var $bits_54 = $bits_28;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec971 = $have_32 - 1 | 0;
+ var $incdec_ptr972 = $next_32 + 1 | 0;
+ var $135 = HEAPU8[$next_32];
+ var $conv973 = $135 & 255;
+ var $shl974 = $conv973 << $bits_28;
+ var $add975 = $shl974 + $hold_28 | 0;
+ var $add976 = $bits_28 + 8 | 0;
+ var $next_32 = $incdec_ptr972;
+ var $have_32 = $dec971;
+ var $hold_28 = $add975;
+ var $bits_28 = $add976;
+ }
+ var $shr985 = $hold_28 >>> ($conv893 >>> 0);
+ var $sub988 = $bits_28 - $conv893 | 0;
+ var $cmp992 = ($128 | 0) == 0;
+ if ($cmp992) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str10107 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_32;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_32;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr985;
+ var $bits_0_be = $sub988;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $sub999 = $128 - 1 | 0;
+ var $arrayidx1001 = $41 + ($sub999 << 1) | 0;
+ var $136 = HEAP16[$arrayidx1001 >> 1];
+ var $and1003 = $shr985 & 3;
+ var $add1004 = $and1003 + 3 | 0;
+ var $shr1006 = $shr985 >>> 2;
+ var $sub1007 = $sub988 - 2 | 0;
+ var $len_0 = $136;
+ var $next_35 = $next_32;
+ var $have_35 = $have_32;
+ var $hold_31 = $shr1006;
+ var $bits_31 = $sub1007;
+ var $copy_5 = $add1004;
+ } else if ($tmp26 << 16 >> 16 == 17) {
+ var $add1020 = $conv893 + 3 | 0;
+ var $next_33 = $next_30;
+ var $have_33 = $have_30;
+ var $hold_29 = $hold_26;
+ var $bits_29 = $bits_26;
+ while (1) {
+ var $bits_29;
+ var $hold_29;
+ var $have_33;
+ var $next_33;
+ var $cmp1021 = $bits_29 >>> 0 < $add1020 >>> 0;
+ if (!$cmp1021) {
+ break;
+ }
+ var $cmp1025 = ($have_33 | 0) == 0;
+ if ($cmp1025) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_33;
+ var $have_58 = 0;
+ var $hold_54 = $hold_29;
+ var $bits_54 = $bits_29;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1029 = $have_33 - 1 | 0;
+ var $incdec_ptr1030 = $next_33 + 1 | 0;
+ var $137 = HEAPU8[$next_33];
+ var $conv1031 = $137 & 255;
+ var $shl1032 = $conv1031 << $bits_29;
+ var $add1033 = $shl1032 + $hold_29 | 0;
+ var $add1034 = $bits_29 + 8 | 0;
+ var $next_33 = $incdec_ptr1030;
+ var $have_33 = $dec1029;
+ var $hold_29 = $add1033;
+ var $bits_29 = $add1034;
+ }
+ var $shr1043 = $hold_29 >>> ($conv893 >>> 0);
+ var $and1049 = $shr1043 & 7;
+ var $add1050 = $and1049 + 3 | 0;
+ var $shr1052 = $shr1043 >>> 3;
+ var $sub1046 = -3 - $conv893 | 0;
+ var $sub1053 = $sub1046 + $bits_29 | 0;
+ var $len_0 = 0;
+ var $next_35 = $next_33;
+ var $have_35 = $have_33;
+ var $hold_31 = $shr1052;
+ var $bits_31 = $sub1053;
+ var $copy_5 = $add1050;
+ } else {
+ var $add1061 = $conv893 + 7 | 0;
+ var $next_34 = $next_30;
+ var $have_34 = $have_30;
+ var $hold_30 = $hold_26;
+ var $bits_30 = $bits_26;
+ while (1) {
+ var $bits_30;
+ var $hold_30;
+ var $have_34;
+ var $next_34;
+ var $cmp1062 = $bits_30 >>> 0 < $add1061 >>> 0;
+ if (!$cmp1062) {
+ break;
+ }
+ var $cmp1066 = ($have_34 | 0) == 0;
+ if ($cmp1066) {
+ var $ret_8 = $ret_1_ph;
+ var $next_58 = $next_34;
+ var $have_58 = 0;
+ var $hold_54 = $hold_30;
+ var $bits_54 = $bits_30;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1070 = $have_34 - 1 | 0;
+ var $incdec_ptr1071 = $next_34 + 1 | 0;
+ var $138 = HEAPU8[$next_34];
+ var $conv1072 = $138 & 255;
+ var $shl1073 = $conv1072 << $bits_30;
+ var $add1074 = $shl1073 + $hold_30 | 0;
+ var $add1075 = $bits_30 + 8 | 0;
+ var $next_34 = $incdec_ptr1071;
+ var $have_34 = $dec1070;
+ var $hold_30 = $add1074;
+ var $bits_30 = $add1075;
+ }
+ var $shr1084 = $hold_30 >>> ($conv893 >>> 0);
+ var $and1090 = $shr1084 & 127;
+ var $add1091 = $and1090 + 11 | 0;
+ var $shr1093 = $shr1084 >>> 7;
+ var $sub1087 = -7 - $conv893 | 0;
+ var $sub1094 = $sub1087 + $bits_30 | 0;
+ var $len_0 = 0;
+ var $next_35 = $next_34;
+ var $have_35 = $have_34;
+ var $hold_31 = $shr1093;
+ var $bits_31 = $sub1094;
+ var $copy_5 = $add1091;
+ }
+ var $copy_5;
+ var $bits_31;
+ var $hold_31;
+ var $have_35;
+ var $next_35;
+ var $len_0;
+ var $add1100 = $128 + $copy_5 | 0;
+ var $cmp1104 = $add1100 >>> 0 > $add881 >>> 0;
+ if ($cmp1104) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str10107 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_35;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_35;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_31;
+ var $bits_0_be = $bits_31;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $copy_6127 = $copy_5;
+ var $139 = $128;
+ while (1) {
+ var $139;
+ var $copy_6127;
+ var $dec1111 = $copy_6127 - 1 | 0;
+ var $inc1116 = $139 + 1 | 0;
+ HEAP32[$40 >> 2] = $inc1116;
+ var $arrayidx1118 = $41 + ($139 << 1) | 0;
+ HEAP16[$arrayidx1118 >> 1] = $len_0;
+ var $tobool1112 = ($dec1111 | 0) == 0;
+ if ($tobool1112) {
+ var $next_29 = $next_35;
+ var $have_29 = $have_35;
+ var $hold_25 = $hold_31;
+ var $bits_25 = $bits_31;
+ continue $_$167;
+ }
+ var $_pre892 = HEAP32[$40 >> 2];
+ var $copy_6127 = $dec1111;
+ var $139 = $_pre892;
+ }
+ }
+ } else {
+ var $_pr38 = HEAP32[$mode >> 2];
+ var $cmp1123 = ($_pr38 | 0) == 29;
+ if ($cmp1123) {
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $140 = HEAP16[$45 >> 1];
+ var $cmp1130 = $140 << 16 >> 16 == 0;
+ if ($cmp1130) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str11108 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_1_ph;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ HEAP32[$43 >> 2] = $arraydecay860_c;
+ HEAP32[$44 >> 2] = $arraydecay860_c;
+ HEAP32[$26 >> 2] = 9;
+ var $call1149 = _inflate_table(1, $arraydecay864, $129, $42, $26, $arraydecay867);
+ var $tobool1150 = ($call1149 | 0) == 0;
+ if (!$tobool1150) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str12109 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call1149;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ var $141 = HEAP32[$42 >> 2];
+ var $_c = $141;
+ HEAP32[$46 >> 2] = $_c;
+ HEAP32[$47 >> 2] = 6;
+ var $142 = HEAP32[$37 >> 2];
+ var $add_ptr1159 = $arraydecay864 + ($142 << 1) | 0;
+ var $143 = HEAP32[$38 >> 2];
+ var $call1165 = _inflate_table(2, $add_ptr1159, $143, $42, $47, $arraydecay867);
+ var $tobool1166 = ($call1165 | 0) == 0;
+ if (!$tobool1166) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str13110 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $call1165;
+ var $next_0_be = $next_29;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_29;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_25;
+ var $bits_0_be = $bits_25;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$148;
+ }
+ HEAP32[$mode >> 2] = 19;
+ if ($cmp660) {
+ var $ret_8 = 0;
+ var $next_58 = $next_29;
+ var $have_58 = $have_29;
+ var $hold_54 = $hold_25;
+ var $bits_54 = $bits_25;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $ret_2 = 0;
+ var $next_37 = $next_29;
+ var $have_37 = $have_29;
+ var $hold_33 = $hold_25;
+ var $bits_33 = $bits_25;
+ __label__ = 205;
+ break $_$148;
+ }
+ }
+ }
+ } while (0);
+ do {
+ if (__label__ == 60) {
+ var $bits_5;
+ var $hold_5;
+ var $have_5;
+ var $next_5;
+ var $71 = HEAPU32[$17 >> 2];
+ var $and262 = $71 & 1024;
+ var $tobool263 = ($and262 | 0) == 0;
+ do {
+ if ($tobool263) {
+ var $76 = HEAP32[$18 >> 2];
+ var $cmp310 = ($76 | 0) == 0;
+ if ($cmp310) {
+ var $next_7 = $next_5;
+ var $have_7 = $have_5;
+ var $hold_7 = $hold_5;
+ var $bits_7 = $bits_5;
+ break;
+ }
+ var $extra = $76 + 16 | 0;
+ HEAP32[$extra >> 2] = 0;
+ var $next_7 = $next_5;
+ var $have_7 = $have_5;
+ var $hold_7 = $hold_5;
+ var $bits_7 = $bits_5;
+ } else {
+ var $next_6 = $next_5;
+ var $have_6 = $have_5;
+ var $hold_6 = $hold_5;
+ var $bits_6 = $bits_5;
+ while (1) {
+ var $bits_6;
+ var $hold_6;
+ var $have_6;
+ var $next_6;
+ var $cmp267 = $bits_6 >>> 0 < 16;
+ if (!$cmp267) {
+ break;
+ }
+ var $cmp271 = ($have_6 | 0) == 0;
+ if ($cmp271) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_6;
+ var $have_58 = 0;
+ var $hold_54 = $hold_6;
+ var $bits_54 = $bits_6;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec275 = $have_6 - 1 | 0;
+ var $incdec_ptr276 = $next_6 + 1 | 0;
+ var $72 = HEAPU8[$next_6];
+ var $conv277 = $72 & 255;
+ var $shl278 = $conv277 << $bits_6;
+ var $add279 = $shl278 + $hold_6 | 0;
+ var $add280 = $bits_6 + 8 | 0;
+ var $next_6 = $incdec_ptr276;
+ var $have_6 = $dec275;
+ var $hold_6 = $add279;
+ var $bits_6 = $add280;
+ }
+ HEAP32[$21 >> 2] = $hold_6;
+ var $73 = HEAP32[$18 >> 2];
+ var $cmp285 = ($73 | 0) == 0;
+ if ($cmp285) {
+ var $74 = $71;
+ } else {
+ var $extra_len = $73 + 20 | 0;
+ HEAP32[$extra_len >> 2] = $hold_6;
+ var $_pre885 = HEAP32[$17 >> 2];
+ var $74 = $_pre885;
+ }
+ var $74;
+ var $and291 = $74 & 512;
+ var $tobool292 = ($and291 | 0) == 0;
+ if ($tobool292) {
+ var $next_7 = $next_6;
+ var $have_7 = $have_6;
+ var $hold_7 = 0;
+ var $bits_7 = 0;
+ break;
+ }
+ var $conv295 = $hold_6 & 255;
+ HEAP8[$arrayidx] = $conv295;
+ var $shr297 = $hold_6 >>> 8;
+ var $conv298 = $shr297 & 255;
+ HEAP8[$arrayidx40] = $conv298;
+ var $75 = HEAP32[$16 >> 2];
+ var $call302 = _crc32($75, $arrayidx, 2);
+ HEAP32[$16 >> 2] = $call302;
+ var $next_7 = $next_6;
+ var $have_7 = $have_6;
+ var $hold_7 = 0;
+ var $bits_7 = 0;
+ }
+ } while (0);
+ var $bits_7;
+ var $hold_7;
+ var $have_7;
+ var $next_7;
+ HEAP32[$mode >> 2] = 5;
+ var $next_8 = $next_7;
+ var $have_8 = $have_7;
+ var $hold_8 = $hold_7;
+ var $bits_8 = $bits_7;
+ __label__ = 71;
+ break;
+ } else if (__label__ == 124) {
+ var $bits_17;
+ var $hold_17;
+ var $have_21;
+ var $next_21;
+ var $116 = HEAP32[$24 >> 2];
+ var $tobool616 = ($116 | 0) == 0;
+ if ($tobool616) {
+ var $next_22 = $next_21;
+ var $have_22 = $have_21;
+ var $hold_18 = $hold_17;
+ var $bits_18 = $bits_17;
+ while (1) {
+ var $bits_18;
+ var $hold_18;
+ var $have_22;
+ var $next_22;
+ var $cmp629 = $bits_18 >>> 0 < 3;
+ if (!$cmp629) {
+ break;
+ }
+ var $cmp633 = ($have_22 | 0) == 0;
+ if ($cmp633) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_22;
+ var $have_58 = 0;
+ var $hold_54 = $hold_18;
+ var $bits_54 = $bits_18;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec637 = $have_22 - 1 | 0;
+ var $incdec_ptr638 = $next_22 + 1 | 0;
+ var $117 = HEAPU8[$next_22];
+ var $conv639 = $117 & 255;
+ var $shl640 = $conv639 << $bits_18;
+ var $add641 = $shl640 + $hold_18 | 0;
+ var $add642 = $bits_18 + 8 | 0;
+ var $next_22 = $incdec_ptr638;
+ var $have_22 = $dec637;
+ var $hold_18 = $add641;
+ var $bits_18 = $add642;
+ }
+ var $and648 = $hold_18 & 1;
+ HEAP32[$24 >> 2] = $and648;
+ var $shr651 = $hold_18 >>> 1;
+ var $and655 = $shr651 & 3;
+ do {
+ if (($and655 | 0) == 0) {
+ HEAP32[$mode >> 2] = 13;
+ } else if (($and655 | 0) == 1) {
+ _fixedtables($4);
+ HEAP32[$mode >> 2] = 19;
+ if (!$cmp660) {
+ break;
+ }
+ var $shr664 = $hold_18 >>> 3;
+ var $sub665 = $bits_18 - 3 | 0;
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_22;
+ var $have_58 = $have_22;
+ var $hold_54 = $shr664;
+ var $bits_54 = $sub665;
+ var $out_4 = $out_0;
+ break $_$12;
+ } else if (($and655 | 0) == 2) {
+ HEAP32[$mode >> 2] = 16;
+ } else if (($and655 | 0) == 3) {
+ HEAP32[$msg >> 2] = STRING_TABLE.__str6103 | 0;
+ HEAP32[$mode >> 2] = 29;
+ }
+ } while (0);
+ var $shr675 = $hold_18 >>> 3;
+ var $sub676 = $bits_18 - 3 | 0;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_22;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_22;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr675;
+ var $bits_0_be = $sub676;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $and619 = $bits_17 & 7;
+ var $shr620 = $hold_17 >>> ($and619 >>> 0);
+ var $sub622 = $bits_17 - $and619 | 0;
+ HEAP32[$mode >> 2] = 26;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_21;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_21;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr620;
+ var $bits_0_be = $sub622;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 205) {
+ var $bits_33;
+ var $hold_33;
+ var $have_37;
+ var $next_37;
+ var $ret_2;
+ HEAP32[$mode >> 2] = 20;
+ var $ret_3 = $ret_2;
+ var $next_38 = $next_37;
+ var $have_38 = $have_37;
+ var $hold_34 = $hold_33;
+ var $bits_34 = $bits_33;
+ __label__ = 206;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 71) {
+ var $bits_8;
+ var $hold_8;
+ var $have_8;
+ var $next_8;
+ var $77 = HEAPU32[$17 >> 2];
+ var $and319 = $77 & 1024;
+ var $tobool320 = ($and319 | 0) == 0;
+ if ($tobool320) {
+ var $next_10 = $next_8;
+ var $have_10 = $have_8;
+ var $88 = $77;
+ } else {
+ var $78 = HEAPU32[$21 >> 2];
+ var $cmp323 = $78 >>> 0 > $have_8 >>> 0;
+ var $copy_0 = $cmp323 ? $have_8 : $78;
+ var $tobool327 = ($copy_0 | 0) == 0;
+ if ($tobool327) {
+ var $next_9 = $next_8;
+ var $have_9 = $have_8;
+ var $87 = $78;
+ var $86 = $77;
+ } else {
+ var $79 = HEAPU32[$18 >> 2];
+ var $cmp330 = ($79 | 0) == 0;
+ do {
+ if ($cmp330) {
+ var $83 = $77;
+ } else {
+ var $extra334 = $79 + 16 | 0;
+ var $80 = HEAP32[$extra334 >> 2];
+ var $cmp335 = ($80 | 0) == 0;
+ if ($cmp335) {
+ var $83 = $77;
+ break;
+ }
+ var $extra_len339 = $79 + 20 | 0;
+ var $81 = HEAP32[$extra_len339 >> 2];
+ var $sub341 = $81 - $78 | 0;
+ var $add_ptr = $80 + $sub341 | 0;
+ var $add344 = $sub341 + $copy_0 | 0;
+ var $extra_max = $79 + 24 | 0;
+ var $82 = HEAPU32[$extra_max >> 2];
+ var $cmp346 = $add344 >>> 0 > $82 >>> 0;
+ var $sub350 = $82 - $sub341 | 0;
+ var $cond351 = $cmp346 ? $sub350 : $copy_0;
+ _memcpy($add_ptr, $next_8, $cond351, 1);
+ var $_pre886 = HEAP32[$17 >> 2];
+ var $83 = $_pre886;
+ }
+ } while (0);
+ var $83;
+ var $and354 = $83 & 512;
+ var $tobool355 = ($and354 | 0) == 0;
+ if (!$tobool355) {
+ var $84 = HEAP32[$16 >> 2];
+ var $call358 = _crc32($84, $next_8, $copy_0);
+ HEAP32[$16 >> 2] = $call358;
+ }
+ var $sub361 = $have_8 - $copy_0 | 0;
+ var $add_ptr362 = $next_8 + $copy_0 | 0;
+ var $85 = HEAP32[$21 >> 2];
+ var $sub364 = $85 - $copy_0 | 0;
+ HEAP32[$21 >> 2] = $sub364;
+ var $next_9 = $add_ptr362;
+ var $have_9 = $sub361;
+ var $87 = $sub364;
+ var $86 = $83;
+ }
+ var $86;
+ var $87;
+ var $have_9;
+ var $next_9;
+ var $tobool367 = ($87 | 0) == 0;
+ if (!$tobool367) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_9;
+ var $have_58 = $have_9;
+ var $hold_54 = $hold_8;
+ var $bits_54 = $bits_8;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_10 = $next_9;
+ var $have_10 = $have_9;
+ var $88 = $86;
+ }
+ var $88;
+ var $have_10;
+ var $next_10;
+ HEAP32[$21 >> 2] = 0;
+ HEAP32[$mode >> 2] = 6;
+ var $next_11 = $next_10;
+ var $have_11 = $have_10;
+ var $hold_9 = $hold_8;
+ var $bits_9 = $bits_8;
+ var $89 = $88;
+ __label__ = 81;
+ break;
+ } else if (__label__ == 206) {
+ var $bits_34;
+ var $hold_34;
+ var $have_38;
+ var $next_38;
+ var $ret_3;
+ var $cmp1179 = $have_38 >>> 0 > 5;
+ var $cmp1182 = $left_0 >>> 0 > 257;
+ var $or_cond33 = $cmp1179 & $cmp1182;
+ if ($or_cond33) {
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_38;
+ HEAP32[$avail_in15 >> 2] = $have_38;
+ HEAP32[$11 >> 2] = $hold_34;
+ HEAP32[$13 >> 2] = $bits_34;
+ _inflate_fast($strm, $out_0);
+ var $144 = HEAP32[$next_out >> 2];
+ var $145 = HEAP32[$avail_out >> 2];
+ var $146 = HEAP32[$next_in >> 2];
+ var $147 = HEAP32[$avail_in15 >> 2];
+ var $148 = HEAP32[$11 >> 2];
+ var $149 = HEAP32[$13 >> 2];
+ var $150 = HEAP32[$mode >> 2];
+ var $cmp1204 = ($150 | 0) == 11;
+ if (!$cmp1204) {
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $146;
+ var $put_0_be = $144;
+ var $have_0_be = $147;
+ var $left_0_be = $145;
+ var $hold_0_be = $148;
+ var $bits_0_be = $149;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$25 >> 2] = -1;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $146;
+ var $put_0_be = $144;
+ var $have_0_be = $147;
+ var $left_0_be = $145;
+ var $hold_0_be = $148;
+ var $bits_0_be = $149;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ HEAP32[$25 >> 2] = 0;
+ var $151 = HEAP32[$26 >> 2];
+ var $shl1212 = 1 << $151;
+ var $sub1213 = $shl1212 - 1 | 0;
+ var $152 = HEAPU32[$27 >> 2];
+ var $next_39 = $next_38;
+ var $have_39 = $have_38;
+ var $hold_35 = $hold_34;
+ var $bits_35 = $bits_34;
+ while (1) {
+ var $bits_35;
+ var $hold_35;
+ var $have_39;
+ var $next_39;
+ var $and1214 = $sub1213 & $hold_35;
+ var $arrayidx1216_1 = $152 + ($and1214 << 2) + 1 | 0;
+ var $tmp22 = HEAPU8[$arrayidx1216_1];
+ var $conv1218 = $tmp22 & 255;
+ var $cmp1219 = $conv1218 >>> 0 > $bits_35 >>> 0;
+ if (!$cmp1219) {
+ break;
+ }
+ var $cmp1224 = ($have_39 | 0) == 0;
+ if ($cmp1224) {
+ var $ret_8 = $ret_3;
+ var $next_58 = $next_39;
+ var $have_58 = 0;
+ var $hold_54 = $hold_35;
+ var $bits_54 = $bits_35;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1228 = $have_39 - 1 | 0;
+ var $incdec_ptr1229 = $next_39 + 1 | 0;
+ var $153 = HEAPU8[$next_39];
+ var $conv1230 = $153 & 255;
+ var $shl1231 = $conv1230 << $bits_35;
+ var $add1232 = $shl1231 + $hold_35 | 0;
+ var $add1233 = $bits_35 + 8 | 0;
+ var $next_39 = $incdec_ptr1229;
+ var $have_39 = $dec1228;
+ var $hold_35 = $add1232;
+ var $bits_35 = $add1233;
+ }
+ var $arrayidx1216_0 = $152 + ($and1214 << 2) | 0;
+ var $tmp21 = HEAPU8[$arrayidx1216_0];
+ var $arrayidx1216_2 = $152 + ($and1214 << 2) + 2 | 0;
+ var $tmp23 = HEAPU16[$arrayidx1216_2 >> 1];
+ var $conv1237 = $tmp21 & 255;
+ var $tobool1238 = $tmp21 << 24 >> 24 == 0;
+ do {
+ if ($tobool1238) {
+ var $next_41 = $next_39;
+ var $have_41 = $have_39;
+ var $hold_37 = $hold_35;
+ var $bits_37 = $bits_35;
+ var $here_09_0 = 0;
+ var $here_110_0 = $tmp22;
+ var $here_211_0 = $tmp23;
+ var $155 = 0;
+ } else {
+ var $and1242 = $conv1237 & 240;
+ var $cmp1243 = ($and1242 | 0) == 0;
+ if (!$cmp1243) {
+ var $next_41 = $next_39;
+ var $have_41 = $have_39;
+ var $hold_37 = $hold_35;
+ var $bits_37 = $bits_35;
+ var $here_09_0 = $tmp21;
+ var $here_110_0 = $tmp22;
+ var $here_211_0 = $tmp23;
+ var $155 = 0;
+ break;
+ }
+ var $conv1248 = $tmp23 & 65535;
+ var $add1253 = $conv1218 + $conv1237 | 0;
+ var $shl1254 = 1 << $add1253;
+ var $sub1255 = $shl1254 - 1 | 0;
+ var $next_40 = $next_39;
+ var $have_40 = $have_39;
+ var $hold_36 = $hold_35;
+ var $bits_36 = $bits_35;
+ while (1) {
+ var $bits_36;
+ var $hold_36;
+ var $have_40;
+ var $next_40;
+ var $and1256 = $hold_36 & $sub1255;
+ var $shr1259 = $and1256 >>> ($conv1218 >>> 0);
+ var $add1260 = $shr1259 + $conv1248 | 0;
+ var $arrayidx1262_1 = $152 + ($add1260 << 2) + 1 | 0;
+ var $tmp19 = HEAPU8[$arrayidx1262_1];
+ var $conv1266 = $tmp19 & 255;
+ var $add1267 = $conv1266 + $conv1218 | 0;
+ var $cmp1268 = $add1267 >>> 0 > $bits_36 >>> 0;
+ if (!$cmp1268) {
+ break;
+ }
+ var $cmp1273 = ($have_40 | 0) == 0;
+ if ($cmp1273) {
+ var $ret_8 = $ret_3;
+ var $next_58 = $next_40;
+ var $have_58 = 0;
+ var $hold_54 = $hold_36;
+ var $bits_54 = $bits_36;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1277 = $have_40 - 1 | 0;
+ var $incdec_ptr1278 = $next_40 + 1 | 0;
+ var $154 = HEAPU8[$next_40];
+ var $conv1279 = $154 & 255;
+ var $shl1280 = $conv1279 << $bits_36;
+ var $add1281 = $shl1280 + $hold_36 | 0;
+ var $add1282 = $bits_36 + 8 | 0;
+ var $next_40 = $incdec_ptr1278;
+ var $have_40 = $dec1277;
+ var $hold_36 = $add1281;
+ var $bits_36 = $add1282;
+ }
+ var $arrayidx1262_2 = $152 + ($add1260 << 2) + 2 | 0;
+ var $arrayidx1262_0 = $152 + ($add1260 << 2) | 0;
+ var $tmp20 = HEAP16[$arrayidx1262_2 >> 1];
+ var $tmp18 = HEAP8[$arrayidx1262_0];
+ var $shr1289 = $hold_36 >>> ($conv1218 >>> 0);
+ var $sub1292 = $bits_36 - $conv1218 | 0;
+ HEAP32[$25 >> 2] = $conv1218;
+ var $next_41 = $next_40;
+ var $have_41 = $have_40;
+ var $hold_37 = $shr1289;
+ var $bits_37 = $sub1292;
+ var $here_09_0 = $tmp18;
+ var $here_110_0 = $tmp19;
+ var $here_211_0 = $tmp20;
+ var $155 = $conv1218;
+ }
+ } while (0);
+ var $155;
+ var $here_211_0;
+ var $here_110_0;
+ var $here_09_0;
+ var $bits_37;
+ var $hold_37;
+ var $have_41;
+ var $next_41;
+ var $conv1302 = $here_110_0 & 255;
+ var $shr1303 = $hold_37 >>> ($conv1302 >>> 0);
+ var $sub1306 = $bits_37 - $conv1302 | 0;
+ var $add1312 = $155 + $conv1302 | 0;
+ HEAP32[$25 >> 2] = $add1312;
+ var $conv1314 = $here_211_0 & 65535;
+ HEAP32[$21 >> 2] = $conv1314;
+ var $conv1317 = $here_09_0 & 255;
+ var $cmp1318 = $here_09_0 << 24 >> 24 == 0;
+ if ($cmp1318) {
+ HEAP32[$mode >> 2] = 25;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $and1325 = $conv1317 & 32;
+ var $tobool1326 = ($and1325 | 0) == 0;
+ if (!$tobool1326) {
+ HEAP32[$25 >> 2] = -1;
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ var $and1333 = $conv1317 & 64;
+ var $tobool1334 = ($and1333 | 0) == 0;
+ if ($tobool1334) {
+ var $and1341 = $conv1317 & 15;
+ HEAP32[$28 >> 2] = $and1341;
+ HEAP32[$mode >> 2] = 21;
+ var $ret_4 = $ret_3;
+ var $next_42 = $next_41;
+ var $have_42 = $have_41;
+ var $hold_38 = $shr1303;
+ var $bits_38 = $sub1306;
+ var $156 = $and1341;
+ __label__ = 227;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str2171 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_3;
+ var $next_0_be = $next_41;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_41;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1303;
+ var $bits_0_be = $sub1306;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 81) {
+ var $89;
+ var $bits_9;
+ var $hold_9;
+ var $have_11;
+ var $next_11;
+ var $and375 = $89 & 2048;
+ var $tobool376 = ($and375 | 0) == 0;
+ do {
+ if ($tobool376) {
+ var $98 = HEAP32[$18 >> 2];
+ var $cmp424 = ($98 | 0) == 0;
+ if ($cmp424) {
+ var $next_12 = $next_11;
+ var $have_12 = $have_11;
+ break;
+ }
+ var $name428 = $98 + 28 | 0;
+ HEAP32[$name428 >> 2] = 0;
+ var $next_12 = $next_11;
+ var $have_12 = $have_11;
+ } else {
+ var $cmp378 = ($have_11 | 0) == 0;
+ if ($cmp378) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_11;
+ var $have_58 = 0;
+ var $hold_54 = $hold_9;
+ var $bits_54 = $bits_9;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $copy_1 = 0;
+ while (1) {
+ var $copy_1;
+ var $inc = $copy_1 + 1 | 0;
+ var $arrayidx383 = $next_11 + $copy_1 | 0;
+ var $90 = HEAP8[$arrayidx383];
+ var $91 = HEAP32[$18 >> 2];
+ var $cmp386 = ($91 | 0) == 0;
+ do {
+ if (!$cmp386) {
+ var $name = $91 + 28 | 0;
+ var $92 = HEAP32[$name >> 2];
+ var $cmp390 = ($92 | 0) == 0;
+ if ($cmp390) {
+ break;
+ }
+ var $93 = HEAPU32[$21 >> 2];
+ var $name_max = $91 + 32 | 0;
+ var $94 = HEAPU32[$name_max >> 2];
+ var $cmp395 = $93 >>> 0 < $94 >>> 0;
+ if (!$cmp395) {
+ break;
+ }
+ var $inc400 = $93 + 1 | 0;
+ HEAP32[$21 >> 2] = $inc400;
+ var $95 = HEAP32[$name >> 2];
+ var $arrayidx403 = $95 + $93 | 0;
+ HEAP8[$arrayidx403] = $90;
+ }
+ } while (0);
+ var $tobool405 = $90 << 24 >> 24 != 0;
+ var $cmp406 = $inc >>> 0 < $have_11 >>> 0;
+ var $or_cond31 = $tobool405 & $cmp406;
+ if (!$or_cond31) {
+ break;
+ }
+ var $copy_1 = $inc;
+ }
+ var $96 = HEAP32[$17 >> 2];
+ var $and410 = $96 & 512;
+ var $tobool411 = ($and410 | 0) == 0;
+ if (!$tobool411) {
+ var $97 = HEAP32[$16 >> 2];
+ var $call414 = _crc32($97, $next_11, $inc);
+ HEAP32[$16 >> 2] = $call414;
+ }
+ var $sub417 = $have_11 - $inc | 0;
+ var $add_ptr418 = $next_11 + $inc | 0;
+ if ($tobool405) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $add_ptr418;
+ var $have_58 = $sub417;
+ var $hold_54 = $hold_9;
+ var $bits_54 = $bits_9;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_12 = $add_ptr418;
+ var $have_12 = $sub417;
+ }
+ } while (0);
+ var $have_12;
+ var $next_12;
+ HEAP32[$21 >> 2] = 0;
+ HEAP32[$mode >> 2] = 7;
+ var $next_13 = $next_12;
+ var $have_13 = $have_12;
+ var $hold_10 = $hold_9;
+ var $bits_10 = $bits_9;
+ __label__ = 94;
+ break;
+ } else if (__label__ == 227) {
+ var $156;
+ var $bits_38;
+ var $hold_38;
+ var $have_42;
+ var $next_42;
+ var $ret_4;
+ var $tobool1346 = ($156 | 0) == 0;
+ if ($tobool1346) {
+ var $_pre890 = HEAP32[$21 >> 2];
+ var $next_44 = $next_42;
+ var $have_44 = $have_42;
+ var $hold_40 = $hold_38;
+ var $bits_40 = $bits_38;
+ var $160 = $_pre890;
+ } else {
+ var $next_43 = $next_42;
+ var $have_43 = $have_42;
+ var $hold_39 = $hold_38;
+ var $bits_39 = $bits_38;
+ while (1) {
+ var $bits_39;
+ var $hold_39;
+ var $have_43;
+ var $next_43;
+ var $cmp1351 = $bits_39 >>> 0 < $156 >>> 0;
+ if (!$cmp1351) {
+ break;
+ }
+ var $cmp1355 = ($have_43 | 0) == 0;
+ if ($cmp1355) {
+ var $ret_8 = $ret_4;
+ var $next_58 = $next_43;
+ var $have_58 = 0;
+ var $hold_54 = $hold_39;
+ var $bits_54 = $bits_39;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1359 = $have_43 - 1 | 0;
+ var $incdec_ptr1360 = $next_43 + 1 | 0;
+ var $157 = HEAPU8[$next_43];
+ var $conv1361 = $157 & 255;
+ var $shl1362 = $conv1361 << $bits_39;
+ var $add1363 = $shl1362 + $hold_39 | 0;
+ var $add1364 = $bits_39 + 8 | 0;
+ var $next_43 = $incdec_ptr1360;
+ var $have_43 = $dec1359;
+ var $hold_39 = $add1363;
+ var $bits_39 = $add1364;
+ }
+ var $shl1371 = 1 << $156;
+ var $sub1372 = $shl1371 - 1 | 0;
+ var $and1373 = $sub1372 & $hold_39;
+ var $158 = HEAP32[$21 >> 2];
+ var $add1375 = $158 + $and1373 | 0;
+ HEAP32[$21 >> 2] = $add1375;
+ var $shr1378 = $hold_39 >>> ($156 >>> 0);
+ var $sub1380 = $bits_39 - $156 | 0;
+ var $159 = HEAP32[$25 >> 2];
+ var $add1385 = $159 + $156 | 0;
+ HEAP32[$25 >> 2] = $add1385;
+ var $next_44 = $next_43;
+ var $have_44 = $have_43;
+ var $hold_40 = $shr1378;
+ var $bits_40 = $sub1380;
+ var $160 = $add1375;
+ }
+ var $160;
+ var $bits_40;
+ var $hold_40;
+ var $have_44;
+ var $next_44;
+ HEAP32[$29 >> 2] = $160;
+ HEAP32[$mode >> 2] = 22;
+ var $ret_5_ph = $ret_4;
+ var $next_45_ph = $next_44;
+ var $have_45_ph = $have_44;
+ var $hold_41_ph = $hold_40;
+ var $bits_41_ph = $bits_40;
+ __label__ = 234;
+ break;
+ }
+ } while (0);
+ do {
+ if (__label__ == 94) {
+ var $bits_10;
+ var $hold_10;
+ var $have_13;
+ var $next_13;
+ var $99 = HEAP32[$17 >> 2];
+ var $and435 = $99 & 4096;
+ var $tobool436 = ($and435 | 0) == 0;
+ do {
+ if ($tobool436) {
+ var $108 = HEAP32[$18 >> 2];
+ var $cmp488 = ($108 | 0) == 0;
+ if ($cmp488) {
+ var $next_14 = $next_13;
+ var $have_14 = $have_13;
+ break;
+ }
+ var $comment492 = $108 + 36 | 0;
+ HEAP32[$comment492 >> 2] = 0;
+ var $next_14 = $next_13;
+ var $have_14 = $have_13;
+ } else {
+ var $cmp438 = ($have_13 | 0) == 0;
+ if ($cmp438) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_13;
+ var $have_58 = 0;
+ var $hold_54 = $hold_10;
+ var $bits_54 = $bits_10;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $copy_2 = 0;
+ while (1) {
+ var $copy_2;
+ var $inc443 = $copy_2 + 1 | 0;
+ var $arrayidx444 = $next_13 + $copy_2 | 0;
+ var $100 = HEAP8[$arrayidx444];
+ var $101 = HEAP32[$18 >> 2];
+ var $cmp447 = ($101 | 0) == 0;
+ do {
+ if (!$cmp447) {
+ var $comment = $101 + 36 | 0;
+ var $102 = HEAP32[$comment >> 2];
+ var $cmp451 = ($102 | 0) == 0;
+ if ($cmp451) {
+ break;
+ }
+ var $103 = HEAPU32[$21 >> 2];
+ var $comm_max = $101 + 40 | 0;
+ var $104 = HEAPU32[$comm_max >> 2];
+ var $cmp456 = $103 >>> 0 < $104 >>> 0;
+ if (!$cmp456) {
+ break;
+ }
+ var $inc461 = $103 + 1 | 0;
+ HEAP32[$21 >> 2] = $inc461;
+ var $105 = HEAP32[$comment >> 2];
+ var $arrayidx464 = $105 + $103 | 0;
+ HEAP8[$arrayidx464] = $100;
+ }
+ } while (0);
+ var $tobool467 = $100 << 24 >> 24 != 0;
+ var $cmp469 = $inc443 >>> 0 < $have_13 >>> 0;
+ var $or_cond32 = $tobool467 & $cmp469;
+ if (!$or_cond32) {
+ break;
+ }
+ var $copy_2 = $inc443;
+ }
+ var $106 = HEAP32[$17 >> 2];
+ var $and474 = $106 & 512;
+ var $tobool475 = ($and474 | 0) == 0;
+ if (!$tobool475) {
+ var $107 = HEAP32[$16 >> 2];
+ var $call478 = _crc32($107, $next_13, $inc443);
+ HEAP32[$16 >> 2] = $call478;
+ }
+ var $sub481 = $have_13 - $inc443 | 0;
+ var $add_ptr482 = $next_13 + $inc443 | 0;
+ if ($tobool467) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $add_ptr482;
+ var $have_58 = $sub481;
+ var $hold_54 = $hold_10;
+ var $bits_54 = $bits_10;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $next_14 = $add_ptr482;
+ var $have_14 = $sub481;
+ }
+ } while (0);
+ var $have_14;
+ var $next_14;
+ HEAP32[$mode >> 2] = 8;
+ var $next_15 = $next_14;
+ var $have_15 = $have_14;
+ var $hold_11 = $hold_10;
+ var $bits_11 = $bits_10;
+ __label__ = 107;
+ break;
+ } else if (__label__ == 234) {
+ var $bits_41_ph;
+ var $hold_41_ph;
+ var $have_45_ph;
+ var $next_45_ph;
+ var $ret_5_ph;
+ var $161 = HEAP32[$47 >> 2];
+ var $shl1392 = 1 << $161;
+ var $sub1393 = $shl1392 - 1 | 0;
+ var $162 = HEAPU32[$48 >> 2];
+ var $next_45 = $next_45_ph;
+ var $have_45 = $have_45_ph;
+ var $hold_41 = $hold_41_ph;
+ var $bits_41 = $bits_41_ph;
+ while (1) {
+ var $bits_41;
+ var $hold_41;
+ var $have_45;
+ var $next_45;
+ var $and1394 = $sub1393 & $hold_41;
+ var $arrayidx1396_1 = $162 + ($and1394 << 2) + 1 | 0;
+ var $tmp16 = HEAPU8[$arrayidx1396_1];
+ var $conv1398 = $tmp16 & 255;
+ var $cmp1399 = $conv1398 >>> 0 > $bits_41 >>> 0;
+ if (!$cmp1399) {
+ break;
+ }
+ var $cmp1404 = ($have_45 | 0) == 0;
+ if ($cmp1404) {
+ var $ret_8 = $ret_5_ph;
+ var $next_58 = $next_45;
+ var $have_58 = 0;
+ var $hold_54 = $hold_41;
+ var $bits_54 = $bits_41;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1408 = $have_45 - 1 | 0;
+ var $incdec_ptr1409 = $next_45 + 1 | 0;
+ var $163 = HEAPU8[$next_45];
+ var $conv1410 = $163 & 255;
+ var $shl1411 = $conv1410 << $bits_41;
+ var $add1412 = $shl1411 + $hold_41 | 0;
+ var $add1413 = $bits_41 + 8 | 0;
+ var $next_45 = $incdec_ptr1409;
+ var $have_45 = $dec1408;
+ var $hold_41 = $add1412;
+ var $bits_41 = $add1413;
+ }
+ var $arrayidx1396_0 = $162 + ($and1394 << 2) | 0;
+ var $tmp15 = HEAPU8[$arrayidx1396_0];
+ var $arrayidx1396_2 = $162 + ($and1394 << 2) + 2 | 0;
+ var $tmp17 = HEAPU16[$arrayidx1396_2 >> 1];
+ var $conv1418 = $tmp15 & 255;
+ var $and1419 = $conv1418 & 240;
+ var $cmp1420 = ($and1419 | 0) == 0;
+ if ($cmp1420) {
+ var $conv1425 = $tmp17 & 65535;
+ var $add1430 = $conv1398 + $conv1418 | 0;
+ var $shl1431 = 1 << $add1430;
+ var $sub1432 = $shl1431 - 1 | 0;
+ var $next_46 = $next_45;
+ var $have_46 = $have_45;
+ var $hold_42 = $hold_41;
+ var $bits_42 = $bits_41;
+ while (1) {
+ var $bits_42;
+ var $hold_42;
+ var $have_46;
+ var $next_46;
+ var $and1433 = $hold_42 & $sub1432;
+ var $shr1436 = $and1433 >>> ($conv1398 >>> 0);
+ var $add1437 = $shr1436 + $conv1425 | 0;
+ var $arrayidx1439_1 = $162 + ($add1437 << 2) + 1 | 0;
+ var $tmp13 = HEAPU8[$arrayidx1439_1];
+ var $conv1443 = $tmp13 & 255;
+ var $add1444 = $conv1443 + $conv1398 | 0;
+ var $cmp1445 = $add1444 >>> 0 > $bits_42 >>> 0;
+ if (!$cmp1445) {
+ break;
+ }
+ var $cmp1450 = ($have_46 | 0) == 0;
+ if ($cmp1450) {
+ var $ret_8 = $ret_5_ph;
+ var $next_58 = $next_46;
+ var $have_58 = 0;
+ var $hold_54 = $hold_42;
+ var $bits_54 = $bits_42;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec1454 = $have_46 - 1 | 0;
+ var $incdec_ptr1455 = $next_46 + 1 | 0;
+ var $164 = HEAPU8[$next_46];
+ var $conv1456 = $164 & 255;
+ var $shl1457 = $conv1456 << $bits_42;
+ var $add1458 = $shl1457 + $hold_42 | 0;
+ var $add1459 = $bits_42 + 8 | 0;
+ var $next_46 = $incdec_ptr1455;
+ var $have_46 = $dec1454;
+ var $hold_42 = $add1458;
+ var $bits_42 = $add1459;
+ }
+ var $arrayidx1439_2 = $162 + ($add1437 << 2) + 2 | 0;
+ var $arrayidx1439_0 = $162 + ($add1437 << 2) | 0;
+ var $tmp14 = HEAP16[$arrayidx1439_2 >> 1];
+ var $tmp12 = HEAP8[$arrayidx1439_0];
+ var $shr1466 = $hold_42 >>> ($conv1398 >>> 0);
+ var $sub1469 = $bits_42 - $conv1398 | 0;
+ var $165 = HEAP32[$25 >> 2];
+ var $add1475 = $165 + $conv1398 | 0;
+ HEAP32[$25 >> 2] = $add1475;
+ var $next_47 = $next_46;
+ var $have_47 = $have_46;
+ var $hold_43 = $shr1466;
+ var $bits_43 = $sub1469;
+ var $here_09_1 = $tmp12;
+ var $here_110_1 = $tmp13;
+ var $here_211_1 = $tmp14;
+ var $166 = $add1475;
+ } else {
+ var $_pre893 = HEAP32[$25 >> 2];
+ var $next_47 = $next_45;
+ var $have_47 = $have_45;
+ var $hold_43 = $hold_41;
+ var $bits_43 = $bits_41;
+ var $here_09_1 = $tmp15;
+ var $here_110_1 = $tmp16;
+ var $here_211_1 = $tmp17;
+ var $166 = $_pre893;
+ }
+ var $166;
+ var $here_211_1;
+ var $here_110_1;
+ var $here_09_1;
+ var $bits_43;
+ var $hold_43;
+ var $have_47;
+ var $next_47;
+ var $conv1479 = $here_110_1 & 255;
+ var $shr1480 = $hold_43 >>> ($conv1479 >>> 0);
+ var $sub1483 = $bits_43 - $conv1479 | 0;
+ var $add1489 = $166 + $conv1479 | 0;
+ HEAP32[$25 >> 2] = $add1489;
+ var $conv1491 = $here_09_1 & 255;
+ var $and1492 = $conv1491 & 64;
+ var $tobool1493 = ($and1492 | 0) == 0;
+ if ($tobool1493) {
+ var $conv1499 = $here_211_1 & 65535;
+ HEAP32[$30 >> 2] = $conv1499;
+ var $and1502 = $conv1491 & 15;
+ HEAP32[$28 >> 2] = $and1502;
+ HEAP32[$mode >> 2] = 23;
+ var $ret_6 = $ret_5_ph;
+ var $next_48 = $next_47;
+ var $have_48 = $have_47;
+ var $hold_44 = $shr1480;
+ var $bits_44 = $sub1483;
+ var $167 = $and1502;
+ __label__ = 248;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str1170 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_5_ph;
+ var $next_0_be = $next_47;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_47;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $shr1480;
+ var $bits_0_be = $sub1483;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ }
+ } while (0);
+ $_$359 : do {
+ if (__label__ == 107) {
+ var $bits_11;
+ var $hold_11;
+ var $have_15;
+ var $next_15;
+ var $109 = HEAPU32[$17 >> 2];
+ var $and498 = $109 & 512;
+ var $tobool499 = ($and498 | 0) == 0;
+ do {
+ if (!$tobool499) {
+ var $next_16 = $next_15;
+ var $have_16 = $have_15;
+ var $hold_12 = $hold_11;
+ var $bits_12 = $bits_11;
+ while (1) {
+ var $bits_12;
+ var $hold_12;
+ var $have_16;
+ var $next_16;
+ var $cmp503 = $bits_12 >>> 0 < 16;
+ if (!$cmp503) {
+ break;
+ }
+ var $cmp507 = ($have_16 | 0) == 0;
+ if ($cmp507) {
+ var $ret_8 = $ret_0;
+ var $next_58 = $next_16;
+ var $have_58 = 0;
+ var $hold_54 = $hold_12;
+ var $bits_54 = $bits_12;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $dec511 = $have_16 - 1 | 0;
+ var $incdec_ptr512 = $next_16 + 1 | 0;
+ var $110 = HEAPU8[$next_16];
+ var $conv513 = $110 & 255;
+ var $shl514 = $conv513 << $bits_12;
+ var $add515 = $shl514 + $hold_12 | 0;
+ var $add516 = $bits_12 + 8 | 0;
+ var $next_16 = $incdec_ptr512;
+ var $have_16 = $dec511;
+ var $hold_12 = $add515;
+ var $bits_12 = $add516;
+ }
+ var $111 = HEAP32[$16 >> 2];
+ var $and523 = $111 & 65535;
+ var $cmp524 = ($hold_12 | 0) == ($and523 | 0);
+ if ($cmp524) {
+ var $next_17 = $next_16;
+ var $have_17 = $have_16;
+ var $hold_13 = 0;
+ var $bits_13 = 0;
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str5102 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_16;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_16;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_12;
+ var $bits_0_be = $bits_12;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break $_$359;
+ }
+ var $next_17 = $next_15;
+ var $have_17 = $have_15;
+ var $hold_13 = $hold_11;
+ var $bits_13 = $bits_11;
+ } while (0);
+ var $bits_13;
+ var $hold_13;
+ var $have_17;
+ var $next_17;
+ var $112 = HEAPU32[$18 >> 2];
+ var $cmp535 = ($112 | 0) == 0;
+ if (!$cmp535) {
+ var $shr53930 = $109 >>> 9;
+ var $and540 = $shr53930 & 1;
+ var $hcrc = $112 + 44 | 0;
+ HEAP32[$hcrc >> 2] = $and540;
+ var $113 = HEAP32[$18 >> 2];
+ var $done543 = $113 + 48 | 0;
+ HEAP32[$done543 >> 2] = 1;
+ }
+ var $call545 = _crc32(0, 0, 0);
+ HEAP32[$16 >> 2] = $call545;
+ HEAP32[$adler >> 2] = $call545;
+ HEAP32[$mode >> 2] = 11;
+ var $ret_0_be = $ret_0;
+ var $next_0_be = $next_17;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_17;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_13;
+ var $bits_0_be = $bits_13;
+ var $out_0_be = $out_0;
+ __label__ = 268;
+ break;
+ } else if (__label__ == 248) {
+ var $167;
+ var $bits_44;
+ var $hold_44;
+ var $have_48;
+ var $next_48;
+ var $ret_6;
+ var $tobool1507 = ($167 | 0) == 0;
+ if ($tobool1507) {
+ var $next_50 = $next_48;
+ var $have_50 = $have_48;
+ var $hold_46 = $hold_44;
+ var $bits_46 = $bits_44;
+ } else {
+ var $next_49 = $next_48;
+ var $have_49 = $have_48;
+ var $hold_45 = $hold_44;
+ var $bits_45 = $bits_44;
+ while (1) {
+ var $bits_45;
+ var $hold_45;
+ var $have_49;
+ var $next_49;
+ var $cmp1512 = $bits_45 >>> 0 < $167 >>> 0;
+ if (!$cmp1512) {
+ break;
+ }
+ var $cmp1516 = ($have_49 | 0) == 0;
+ if ($cmp1516) {
+ var $ret_8 = $ret_6;
+ var $next_58 = $next_49;
+ var $have_58 = 0;
+ var $hold_54 = $hold_45;
+ var $bits_54 = $bits_45;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ // XXX first chunk with a bug-causing difference
+ var $dec1520 = $have_49 - 1 | 0;
+ var $incdec_ptr1521 = $next_49 + 1 | 0;
+ var $168 = HEAPU8[$next_49];
+ var $conv1522 = $168 & 255;
+ var $shl1523 = $conv1522 << $bits_45;
+ var $add1524 = $shl1523 + $hold_45 | 0;
+ var $add1525 = $bits_45 + 8 | 0;
+ var $next_49 = $incdec_ptr1521;
+ var $have_49 = $dec1520;
+ var $hold_45 = $add1524;
+ var $bits_45 = $add1525;
+ }
+ var $shl1532 = 1 << $167;
+ var $sub1533 = $shl1532 - 1 | 0;
+ var $and1534 = $sub1533 & $hold_45;
+ var $169 = HEAP32[$30 >> 2];
+ var $add1536 = $169 + $and1534 | 0;
+ HEAP32[$30 >> 2] = $add1536;
+ var $shr1539 = $hold_45 >>> ($167 >>> 0);
+ var $sub1541 = $bits_45 - $167 | 0;
+ var $170 = HEAP32[$25 >> 2];
+ var $add1546 = $170 + $167 | 0;
+ HEAP32[$25 >> 2] = $add1546;
+ var $next_50 = $next_49;
+ var $have_50 = $have_49;
+ var $hold_46 = $shr1539;
+ var $bits_46 = $sub1541;
+ }
+ var $bits_46;
+ var $hold_46;
+ var $have_50;
+ var $next_50;
+ HEAP32[$mode >> 2] = 24;
+ var $ret_7 = $ret_6;
+ var $next_51 = $next_50;
+ var $have_51 = $have_50;
+ var $hold_47 = $hold_46;
+ var $bits_47 = $bits_46;
+ __label__ = 254;
+ break;
+ }
+ } while (0);
+ $_$380 : do {
+ if (__label__ == 254) {
+ var $bits_47;
+ var $hold_47;
+ var $have_51;
+ var $next_51;
+ var $ret_7;
+ var $cmp1550 = ($left_0 | 0) == 0;
+ if ($cmp1550) {
+ var $ret_8 = $ret_7;
+ var $next_58 = $next_51;
+ var $have_58 = $have_51;
+ var $hold_54 = $hold_47;
+ var $bits_54 = $bits_47;
+ var $out_4 = $out_0;
+ break $_$12;
+ }
+ var $sub1554 = $out_0 - $left_0 | 0;
+ var $171 = HEAPU32[$30 >> 2];
+ var $cmp1556 = $171 >>> 0 > $sub1554 >>> 0;
+ do {
+ if ($cmp1556) {
+ var $sub1560 = $171 - $sub1554 | 0;
+ var $172 = HEAPU32[$31 >> 2];
+ var $cmp1561 = $sub1560 >>> 0 > $172 >>> 0;
+ do {
+ if ($cmp1561) {
+ var $173 = HEAP32[$32 >> 2];
+ var $tobool1564 = ($173 | 0) == 0;
+ if ($tobool1564) {
+ break;
+ }
+ HEAP32[$msg >> 2] = STRING_TABLE.__str169 | 0;
+ HEAP32[$mode >> 2] = 29;
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $put_0;
+ var $have_0_be = $have_51;
+ var $left_0_be = $left_0;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ break $_$380;
+ }
+ } while (0);
+ var $174 = HEAPU32[$33 >> 2];
+ var $cmp1570 = $sub1560 >>> 0 > $174 >>> 0;
+ if ($cmp1570) {
+ var $sub1574 = $sub1560 - $174 | 0;
+ var $175 = HEAP32[$34 >> 2];
+ var $176 = HEAP32[$35 >> 2];
+ var $sub1575 = $176 - $sub1574 | 0;
+ var $add_ptr1576 = $175 + $sub1575 | 0;
+ var $from_0 = $add_ptr1576;
+ var $copy_7 = $sub1574;
+ } else {
+ var $177 = HEAP32[$34 >> 2];
+ var $sub1580 = $174 - $sub1560 | 0;
+ var $add_ptr1581 = $177 + $sub1580 | 0;
+ var $from_0 = $add_ptr1581;
+ var $copy_7 = $sub1560;
+ }
+ var $copy_7;
+ var $from_0;
+ var $178 = HEAPU32[$21 >> 2];
+ var $cmp1584 = $copy_7 >>> 0 > $178 >>> 0;
+ if (!$cmp1584) {
+ var $from_1 = $from_0;
+ var $copy_8 = $copy_7;
+ var $180 = $178;
+ break;
+ }
+ var $from_1 = $from_0;
+ var $copy_8 = $178;
+ var $180 = $178;
+ } else {
+ var $idx_neg = -$171 | 0;
+ var $add_ptr1591 = $put_0 + $idx_neg | 0;
+ var $179 = HEAP32[$21 >> 2];
+ var $from_1 = $add_ptr1591;
+ var $copy_8 = $179;
+ var $180 = $179;
+ }
+ } while (0);
+ var $180;
+ var $copy_8;
+ var $from_1;
+ var $cmp1594 = $copy_8 >>> 0 > $left_0 >>> 0;
+ var $copy_9 = $cmp1594 ? $left_0 : $copy_8;
+ var $sub1600 = $180 - $copy_9 | 0;
+ HEAP32[$21 >> 2] = $sub1600;
+ var $181 = $copy_8 ^ -1;
+ var $182 = $left_0 ^ -1;
+ var $183 = $181 >>> 0 > $182 >>> 0;
+ var $umax = $183 ? $181 : $182;
+ var $from_2 = $from_1;
+ var $put_1 = $put_0;
+ var $copy_10 = $copy_9;
+ while (1) {
+ var $copy_10;
+ var $put_1;
+ var $from_2;
+ var $incdec_ptr1602 = $from_2 + 1 | 0;
+ var $184 = HEAP8[$from_2];
+ var $incdec_ptr1603 = $put_1 + 1 | 0;
+ HEAP8[$put_1] = $184;
+ var $dec1605 = $copy_10 - 1 | 0;
+ var $tobool1606 = ($dec1605 | 0) == 0;
+ if ($tobool1606) {
+ break;
+ }
+ var $from_2 = $incdec_ptr1602;
+ var $put_1 = $incdec_ptr1603;
+ var $copy_10 = $dec1605;
+ }
+ var $sub1598 = $left_0 - $copy_9 | 0;
+ var $scevgep_sum = $umax ^ -1;
+ var $scevgep632 = $put_0 + $scevgep_sum | 0;
+ var $185 = HEAP32[$21 >> 2];
+ var $cmp1609 = ($185 | 0) == 0;
+ if (!$cmp1609) {
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $scevgep632;
+ var $have_0_be = $have_51;
+ var $left_0_be = $sub1598;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ break;
+ }
+ HEAP32[$mode >> 2] = 20;
+ var $ret_0_be = $ret_7;
+ var $next_0_be = $next_51;
+ var $put_0_be = $scevgep632;
+ var $have_0_be = $have_51;
+ var $left_0_be = $sub1598;
+ var $hold_0_be = $hold_47;
+ var $bits_0_be = $bits_47;
+ var $out_0_be = $out_0;
+ }
+ } while (0);
+ var $out_0_be;
+ var $bits_0_be;
+ var $hold_0_be;
+ var $left_0_be;
+ var $have_0_be;
+ var $put_0_be;
+ var $next_0_be;
+ var $ret_0_be;
+ var $_pre883 = HEAP32[$mode >> 2];
+ var $ret_0 = $ret_0_be;
+ var $next_0 = $next_0_be;
+ var $put_0 = $put_0_be;
+ var $have_0 = $have_0_be;
+ var $left_0 = $left_0_be;
+ var $hold_0 = $hold_0_be;
+ var $bits_0 = $bits_0_be;
+ var $out_0 = $out_0_be;
+ var $49 = $_pre883;
+ }
+ var $out_4;
+ var $bits_54;
+ var $hold_54;
+ var $have_58;
+ var $next_58;
+ var $ret_8;
+ HEAP32[$next_out >> 2] = $put_0;
+ HEAP32[$avail_out >> 2] = $left_0;
+ HEAP32[$next_in >> 2] = $next_58;
+ HEAP32[$avail_in15 >> 2] = $have_58;
+ HEAP32[$11 >> 2] = $hold_54;
+ HEAP32[$13 >> 2] = $bits_54;
+ var $199 = HEAP32[$35 >> 2];
+ var $tobool1755 = ($199 | 0) == 0;
+ do {
+ if ($tobool1755) {
+ var $200 = HEAPU32[$mode >> 2];
+ var $cmp1758 = $200 >>> 0 < 26;
+ if (!$cmp1758) {
+ __label__ = 300;
+ break;
+ }
+ var $201 = HEAP32[$avail_out >> 2];
+ var $cmp1762 = ($out_4 | 0) == ($201 | 0);
+ if ($cmp1762) {
+ __label__ = 300;
+ break;
+ }
+ __label__ = 298;
+ break;
+ } else {
+ __label__ = 298;
+ }
+ } while (0);
+ do {
+ if (__label__ == 298) {
+ var $call1765 = _updatewindow($strm, $out_4);
+ var $tobool1766 = ($call1765 | 0) == 0;
+ if ($tobool1766) {
+ break;
+ }
+ HEAP32[$mode >> 2] = 30;
+ var $retval_0 = -4;
+ break $_$2;
+ }
+ } while (0);
+ var $202 = HEAPU32[$avail_in15 >> 2];
+ var $203 = HEAPU32[$avail_out >> 2];
+ var $sub1774 = $out_4 - $203 | 0;
+ var $total_in = $strm + 8 | 0;
+ var $204 = HEAP32[$total_in >> 2];
+ var $sub1772 = $10 - $202 | 0;
+ var $add1775 = $sub1772 + $204 | 0;
+ HEAP32[$total_in >> 2] = $add1775;
+ var $205 = HEAP32[$total_out >> 2];
+ var $add1777 = $205 + $sub1774 | 0;
+ HEAP32[$total_out >> 2] = $add1777;
+ var $206 = HEAP32[$36 >> 2];
+ var $add1779 = $206 + $sub1774 | 0;
+ HEAP32[$36 >> 2] = $add1779;
+ var $207 = HEAP32[$15 >> 2];
+ var $tobool1781 = ($207 | 0) == 0;
+ var $tobool1783 = ($out_4 | 0) == ($203 | 0);
+ var $or_cond34 = $tobool1781 | $tobool1783;
+ if (!$or_cond34) {
+ var $208 = HEAP32[$17 >> 2];
+ var $tobool1786 = ($208 | 0) == 0;
+ var $209 = HEAP32[$16 >> 2];
+ var $210 = HEAP32[$next_out >> 2];
+ var $idx_neg1790 = -$sub1774 | 0;
+ var $add_ptr1791 = $210 + $idx_neg1790 | 0;
+ if ($tobool1786) {
+ var $call1798 = _adler32($209, $add_ptr1791, $sub1774);
+ var $cond1800 = $call1798;
+ } else {
+ var $call1792 = _crc32($209, $add_ptr1791, $sub1774);
+ var $cond1800 = $call1792;
+ }
+ var $cond1800;
+ HEAP32[$16 >> 2] = $cond1800;
+ HEAP32[$adler >> 2] = $cond1800;
+ }
+ var $211 = HEAP32[$13 >> 2];
+ var $212 = HEAP32[$24 >> 2];
+ var $tobool1806 = ($212 | 0) != 0;
+ var $cond1807 = $tobool1806 ? 64 : 0;
+ var $213 = HEAP32[$mode >> 2];
+ var $cmp1810 = ($213 | 0) == 11;
+ var $cond1812 = $cmp1810 ? 128 : 0;
+ var $cmp1815 = ($213 | 0) == 19;
+ if ($cmp1815) {
+ var $214 = 256;
+ } else {
+ var $cmp1818 = ($213 | 0) == 14;
+ var $phitmp = $cmp1818 ? 256 : 0;
+ var $214 = $phitmp;
+ }
+ var $214;
+ var $add1808 = $cond1807 + $211 | 0;
+ var $add1813 = $add1808 + $cond1812 | 0;
+ var $add1821 = $add1813 + $214 | 0;
+ var $data_type = $strm + 44 | 0;
+ HEAP32[$data_type >> 2] = $add1821;
+ var $cmp1822 = ($10 | 0) == ($202 | 0);
+ var $or_cond35 = $cmp1822 & $tobool1783;
+ var $cmp1828 = ($flush | 0) == 4;
+ var $or_cond36 = $or_cond35 | $cmp1828;
+ var $cmp1831 = ($ret_8 | 0) == 0;
+ var $or_cond37 = $or_cond36 & $cmp1831;
+ var $ret_9 = $or_cond37 ? -5 : $ret_8;
+ var $retval_0 = $ret_9;
+ }
+ } while (0);
+ var $retval_0;
+ STACKTOP = __stackBase__;
+ return $retval_0;
+ return null;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate"]
diff --git a/tools/eliminator/eliminator.coffee b/tools/eliminator/eliminator.coffee
index ba91aa89..05e3788b 100644
--- a/tools/eliminator/eliminator.coffee
+++ b/tools/eliminator/eliminator.coffee
@@ -19,6 +19,7 @@
# Imports.
uglify = require 'uglify-js'
fs = require 'fs'
+os = require 'os'
# Functions which have been generated by Emscripten. We optimize only those.
generatedFunctions = []
@@ -106,8 +107,8 @@ class Eliminator
# Maps a given single-def variable to the AST expression of its initial value.
@initialValue = {}
# Maps identifiers to single-def variables which reference it in their
- # initial value.
- @dependsOn = {}
+ # initial value, i.e., which other variables it affects.
+ @affects = {}
# Runs the eliminator on a given function body updating the AST in-place.
# @returns: The number of variables eliminated, or undefined if skipped.
@@ -156,7 +157,7 @@ class Eliminator
# Analyzes the initial values of single-def variables. Requires basic variable
# stats to have been calculated. Fills the following member variables:
- # dependsOn
+ # affects
# dependsOnAGlobal
# usesOnlySimpleNodes
analyzeInitialValues: ->
@@ -169,25 +170,38 @@ class Eliminator
else if type is 'name'
reference = node[1]
if reference != 'undefined'
- if not @dependsOn[reference]? then @dependsOn[reference] = {}
+ if not @affects[reference]? then @affects[reference] = {}
if not @isLocal[reference] then @dependsOnAGlobal[varName] = true
- @dependsOn[reference][varName] = true
+ @affects[reference][varName] = true
return undefined
return undefined
- # Updates the dependency graph (@dependsOn) to its transitive closure and
+ # Updates the dependency graph (@affects) to its transitive closure and
# synchronizes @dependsOnAGlobal to the new dependencies.
calculateTransitiveDependencies: ->
incomplete = true
+ todo = {}
+ for element of @affects
+ todo[element] = 1
+
+ #process.stdout.write 'pre ' + JSON.stringify(@affects, null, ' ') + '\n'
+
while incomplete
incomplete = false
- for target, sources of @dependsOn
- for source of sources
- for source2 of @dependsOn[source]
- if not @dependsOn[target][source2]
- if not @isLocal[target] then @dependsOnAGlobal[source2] = true
- @dependsOn[target][source2] = true
- incomplete = true
+ nextTodo = {}
+ for source, targets of @affects
+ for target of targets
+ if todo[target]
+ for target2 of @affects[target]
+ if not targets[target2]
+ if not @isLocal[source] then @dependsOnAGlobal[target2] = true
+ targets[target2] = true
+ nextTodo[source] = 1
+ incomplete = true
+ todo = nextTodo
+
+ #process.stdout.write 'post ' + JSON.stringify(@affects, null, ' ') + '\n'
+
return undefined
# Analyzes the live ranges of single-def variables. Requires dependencies to
@@ -210,8 +224,8 @@ class Eliminator
while reference[0] != 'name'
reference = reference[1]
reference = reference[1]
- if @dependsOn[reference]?
- for varName of @dependsOn[reference]
+ if @affects[reference]?
+ for varName of @affects[reference]
if isLive[varName]
isLive[varName] = false
@@ -263,8 +277,8 @@ class Eliminator
if @isSingleDef[varName]
isLive[varName] = true
# Mark variables that depend on it as no longer live
- if @dependsOn[varName]?
- for varNameDep of @dependsOn[varName]
+ if @affects[varName]?
+ for varNameDep of @affects[varName]
if isLive[varNameDep]
isLive[varNameDep] = false
return node
@@ -369,7 +383,8 @@ class ExpressionOptimizer
# function, then writes the optimized result to stdout.
main = ->
# Get the parse tree.
- src = fs.readFileSync('/dev/stdin').toString()
+ #process.stderr.write(JSON.stringify(process.argv[2]) + '\n')
+ src = fs.readFileSync(process.argv[2]).toString()
throw 'Cannot identify generated functions' if GENERATED_FUNCTIONS_MARKER in src
generatedFunctionsLine = src.split('\n').filter (line) ->
@@ -378,22 +393,22 @@ main = ->
ast = uglify.parser.parse src
- #process.stderr.write(JSON.stringify(ast) + '\n')
+ ##process.stderr.write(JSON.stringify(ast) + '\n')
# Run on all functions.
traverse ast, (node, type) ->
if type in ['defun', 'function'] and isGenerated node[1]
# Run the eliminator
- process.stderr.write (node[1] || '(anonymous)') + '\n'
+ #process.stderr.write (node[1] || '(anonymous)') + '\n'
eliminated = new Eliminator(node).run()
if eliminated?
- process.stderr.write " Eliminated #{eliminated} vars.\n"
+ #process.stderr.write " Eliminated #{eliminated} vars.\n"
# Run the expression optimizer
new ExpressionOptimizer(node[3]).run()
else
- process.stderr.write ' Skipped.\n'
+ #process.stderr.write ' Skipped.\n'
return undefined
diff --git a/tools/eliminator/node_modules/coffee-script/lib/command.js b/tools/eliminator/node_modules/coffee-script/lib/command.js
index ca255020..39813201 100644
--- a/tools/eliminator/node_modules/coffee-script/lib/command.js
+++ b/tools/eliminator/node_modules/coffee-script/lib/command.js
@@ -12,7 +12,7 @@
return process.stdout.write(line + '\n');
};
printWarn = function(line) {
- return process.binding('stdio').writeError(line + '\n');
+ return process.stderr.write(line + '\n');
};
BANNER = 'Usage: coffee [options] path/to/script.coffee';
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
diff --git a/tools/emmaken.py b/tools/emmaken.py
index 8e1bfdc8..ae4794f0 100755
--- a/tools/emmaken.py
+++ b/tools/emmaken.py
@@ -113,7 +113,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG:
compiler = 'g++' if 'CXXCompiler' in ' '.join(sys.argv) or os.environ.get('EMMAKEN_CXX') else 'gcc'
cmd = [compiler] + EMSDK_OPTS + sys.argv[1:]
print >> sys.stderr, 'emmaken.py, just configuring: ', cmd
- exit(os.execvp(compiler, cmd))
+ exit(subprocess.call(cmd))
try:
#f=open('/dev/shm/tmp/waka.txt', 'a')
@@ -223,7 +223,7 @@ try:
print >> sys.stderr, "Running:", call, ' '.join(newargs)
- os.execvp(call, [call] + newargs)
+ subprocess.call([call] + newargs)
except Exception, e:
print 'Error in emmaken.py. (Is the config file %s set up properly?) Error:' % EM_CONFIG, e
raise
diff --git a/tools/emmakenxx.py b/tools/emmakenxx.py
index c9ab4ef4..1c31f3c2 100755
--- a/tools/emmakenxx.py
+++ b/tools/emmakenxx.py
@@ -4,7 +4,7 @@
see emmaken.py
'''
-import os, sys
+import os, subprocess, sys
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def path_from_root(*pathelems):
@@ -14,5 +14,5 @@ from tools.shared import *
emmaken = path_from_root('tools', 'emmaken.py')
os.environ['EMMAKEN_CXX'] = '1'
-exit(os.execvp('python', ['python', emmaken] + sys.argv[1:]))
+exit(subprocess.call(['python', emmaken] + sys.argv[1:]))
diff --git a/tools/file_packager.py b/tools/file_packager.py
new file mode 100644
index 00000000..3844b4ae
--- /dev/null
+++ b/tools/file_packager.py
@@ -0,0 +1,399 @@
+'''
+A tool that generates FS API calls to generate a filesystem, and packages the files
+to work with that.
+
+This is called by emcc. You can also call it yourself.
+
+Usage:
+
+ file_packager.py TARGET [--preload A [B..]] [--embed C [D..]] [--compress COMPRESSION_DATA] [--pre-run] [--crunch[=X]]
+
+Notes:
+
+ --pre-run Will generate wrapper code that does preloading in Module.preRun. This is necessary if you add this
+ code before the main file has been loading, which includes necessary components like addRunDependency.
+
+ --crunch=X Will compress dxt files to crn with quality level X. The crunch commandline tool must be present
+ and CRUNCH should be defined in ~/.emscripten that points to it. JS crunch decompressing code will
+ be added to convert the crn to dds in the browser.
+ crunch-worker.js will be generated in the current directory. You should include that file when
+ packaging your site.
+ DDS files will not be crunched if the .crn is more recent than the .dds. This prevents a lot of
+ unneeded computation.
+
+TODO: You can also provide .crn files yourself, pre-crunched. With this option, they will be decompressed
+ to dds files in the browser, exactly the same as if this tool compressed them.
+'''
+
+import os, sys, shutil
+
+from shared import Compression, execute, suffix, unsuffixed
+import shared
+from subprocess import Popen, PIPE, STDOUT
+
+data_target = sys.argv[1]
+
+IMAGE_SUFFIXES = ('.jpg', '.png', '.bmp')
+AUDIO_SUFFIXES = ('.ogg', '.wav', '.mp3')
+AUDIO_MIMETYPES = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' }
+CRUNCH_INPUT_SUFFIX = '.dds'
+CRUNCH_OUTPUT_SUFFIX = '.crn'
+
+DDS_HEADER_SIZE = 128
+
+data_files = []
+in_preload = False
+in_embed = False
+has_preloaded = False
+in_compress = 0
+pre_run = False
+crunch = 0
+
+for arg in sys.argv[1:]:
+ if arg == '--preload':
+ in_preload = True
+ in_embed = False
+ has_preloaded = True
+ in_compress = 0
+ elif arg == '--embed':
+ in_embed = True
+ in_preload = False
+ in_compress = 0
+ elif arg == '--compress':
+ Compression.on = True
+ in_compress = 1
+ in_preload = False
+ in_embed = False
+ elif arg == '--pre-run':
+ pre_run = True
+ in_preload = False
+ in_embed = False
+ in_compress = 0
+ elif arg.startswith('--crunch'):
+ from shared import CRUNCH
+ crunch = arg.split('=')[1] if '=' in arg else '128'
+ in_preload = False
+ in_embed = False
+ in_compress = 0
+ elif in_preload:
+ data_files.append({ 'name': arg, 'mode': 'preload' })
+ elif in_embed:
+ data_files.append({ 'name': arg, 'mode': 'embed' })
+ elif in_compress:
+ if in_compress == 1:
+ Compression.encoder = arg
+ in_compress = 2
+ elif in_compress == 2:
+ Compression.decoder = arg
+ in_compress = 3
+ elif in_compress == 3:
+ Compression.js_name = arg
+ in_compress = 0
+
+code = '''
+function assert(check, msg) {
+ if (!check) throw msg;
+}
+'''
+
+if has_preloaded:
+ code += '''
+ var BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : console.log("warning: cannot build blobs"));
+ var URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs");
+ var hasBlobConstructor;
+ try {
+ new Blob();
+ hasBlobConstructor = true;
+ } catch(e) {
+ hasBlobConstructor = false;
+ console.log("warning: no blob constructor, cannot create blobs with mimetypes");
+ }
+'''
+
+ code += 'Module["preloadedImages"] = {}; // maps url to image data\n'
+ code += 'Module["preloadedAudios"] = {}; // maps url to audio data\n'
+
+# Expand directories into individual files
+def add(mode, dirname, names):
+ for name in names:
+ fullname = os.path.join(dirname, name)
+ if not os.path.isdir(fullname):
+ data_files.append({ 'name': fullname, 'mode': mode })
+
+for file_ in data_files:
+ if os.path.isdir(file_['name']):
+ os.path.walk(file_['name'], add, file_['mode'])
+data_files = filter(lambda file_: not os.path.isdir(file_['name']), data_files)
+
+for file_ in data_files:
+ file_['name'] = file_['name'].replace(os.path.sep, '/') # name in the filesystem, native and emulated
+ file_['localname'] = file_['name'] # name to actually load from local filesystem, after transformations
+
+# Remove duplicates (can occur naively, for example preload dir/, preload dir/subdir/)
+seen = {}
+def was_seen(name):
+ if seen.get(name): return True
+ seen[name] = 1
+ return False
+data_files = filter(lambda file_: not was_seen(file_['name']), data_files)
+
+# Crunch files
+if crunch:
+ shutil.copyfile(shared.path_from_root('tools', 'crunch-worker.js'), 'crunch-worker.js')
+ print '''
+ var decrunchWorker = new Worker('crunch-worker.js');
+ var decrunchCallbacks = [];
+ decrunchWorker.onmessage = function(msg) {
+ decrunchCallbacks[msg.data.callbackID](msg.data.data);
+ console.log('decrunched ' + msg.data.filename + ' in ' + msg.data.time + ' ms, ' + msg.data.data.length + ' bytes');
+ decrunchCallbacks[msg.data.callbackID] = null;
+ };
+ function requestDecrunch(filename, data, callback) {
+ decrunchWorker.postMessage({
+ filename: filename,
+ data: data,
+ callbackID: decrunchCallbacks.length
+ });
+ decrunchCallbacks.push(callback);
+ }
+'''
+
+ for file_ in data_files:
+ if file_['name'].endswith(CRUNCH_INPUT_SUFFIX):
+ # Do not crunch if crunched version exists and is more recent than dds source
+ crunch_name = unsuffixed(file_['name']) + CRUNCH_OUTPUT_SUFFIX
+ file_['localname'] = crunch_name
+ try:
+ crunch_time = os.stat(crunch_name).st_mtime
+ dds_time = os.stat(file_['name']).st_mtime
+ if dds_time < crunch_time: continue
+ except:
+ pass # if one of them does not exist, continue on
+
+ # guess at format. this lets us tell crunch to not try to be clever and use odd formats like DXT5_AGBR
+ try:
+ format = Popen(['file', file_['name']], stdout=PIPE).communicate()[0]
+ if 'DXT5' in format:
+ format = ['-dxt5']
+ elif 'DXT1' in format:
+ format = ['-dxt1']
+ else:
+ raise Exception('unknown format')
+ except:
+ format = []
+ Popen([CRUNCH, '-file', file_['name'], '-quality', crunch] + format, stdout=sys.stderr).communicate()
+ shutil.move(os.path.basename(crunch_name), crunch_name) # crunch places files in the current dir
+ # prepend the dds header
+ crunched = open(crunch_name, 'rb').read()
+ c = open(crunch_name, 'wb')
+ c.write(open(file_['name'], 'rb').read()[:DDS_HEADER_SIZE])
+ c.write(crunched)
+ c.close()
+
+# Set up folders
+partial_dirs = []
+for file_ in data_files:
+ dirname = os.path.dirname(file_['name'])
+ dirname = dirname.lstrip('/') # absolute paths start with '/', remove that
+ if dirname != '':
+ parts = dirname.split('/')
+ for i in range(len(parts)):
+ partial = '/'.join(parts[:i+1])
+ if partial not in partial_dirs:
+ code += '''Module['FS_createFolder']('/%s', '%s', true, true);\n''' % ('/'.join(parts[:i]), parts[i])
+ partial_dirs.append(partial)
+
+if has_preloaded:
+ # Bundle all datafiles into one archive. Avoids doing lots of simultaneous XHRs which has overhead.
+ data = open(data_target, 'wb')
+ start = 0
+ for file_ in data_files:
+ file_['data_start'] = start
+ curr = open(file_['localname'], 'rb').read()
+ file_['data_end'] = start + len(curr)
+ print >> sys.stderr, 'bundling', file_['name'], file_['localname'], file_['data_start'], file_['data_end']
+ start += len(curr)
+ data.write(curr)
+ data.close()
+ if Compression.on:
+ Compression.compress(data_target)
+
+ # Data requests - for getting a block of data out of the big archive - have a similar API to XHRs
+ code += '''
+ function DataRequest() {}
+ DataRequest.prototype = {
+ requests: {},
+ open: function(mode, name) {
+ this.requests[name] = this;
+ },
+ send: function() {}
+ };
+ '''
+
+counter = 0
+for file_ in data_files:
+ filename = file_['name']
+ if file_['mode'] == 'embed':
+ # Embed
+ code += '''Module['FS_createDataFile']('/', '%s', %s, true, true);\n''' % (os.path.basename(filename), str(map(ord, open(file_['localname'], 'rb').read())))
+ elif file_['mode'] == 'preload':
+ # Preload
+ varname = 'filePreload%d' % counter
+ counter += 1
+ image = filename.endswith(IMAGE_SUFFIXES)
+ audio = filename.endswith(AUDIO_SUFFIXES)
+ dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX)
+
+ prepare = ''
+ finish = "Module['removeRunDependency']();\n"
+
+ if image:
+ finish = '''
+ var bb = new BlobBuilder();
+ bb.append(byteArray.buffer);
+ var b = bb.getBlob();
+ var url = URLObject.createObjectURL(b);
+ var img = new Image();
+ img.onload = function() {
+ assert(img.complete, 'Image %(filename)s could not be decoded');
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ Module["preloadedImages"]['%(filename)s'] = canvas;
+ URLObject.revokeObjectURL(url);
+ Module['removeRunDependency']();
+ };
+ img.onerror = function(event) {
+ console.log('Image %(filename)s could not be decoded');
+ };
+ img.src = url;
+''' % { 'filename': filename }
+ elif audio:
+ # Need actual blob constructor here, to set the mimetype or else audios fail to decode
+ finish = '''
+ if (hasBlobConstructor) {
+ var b = new Blob([byteArray.buffer], { type: '%(mimetype)s' });
+ var url = URLObject.createObjectURL(b); // XXX we never revoke this!
+ var audio = new Audio();
+ audio.removedDependency = false;
+ audio['oncanplaythrough'] = function() { // XXX string for closure
+ audio['oncanplaythrough'] = null;
+ Module["preloadedAudios"]['%(filename)s'] = audio;
+ if (!audio.removedDependency) {
+ Module['removeRunDependency']();
+ audio.removedDependency = true;
+ }
+ };
+ audio.onerror = function(event) {
+ if (!audio.removedDependency) {
+ console.log('Audio %(filename)s could not be decoded or timed out trying to decode');
+ Module['removeRunDependency']();
+ audio.removedDependency = true;
+ }
+ };
+ setTimeout(audio.onerror, 2000); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
+ audio.src = url;
+ } else {
+ Module["preloadedAudios"]['%(filename)s'] = new Audio(); // empty shim
+ Module['removeRunDependency']();
+ }
+''' % { 'filename': filename, 'mimetype': AUDIO_MIMETYPES[suffix(filename)] }
+ elif dds:
+ # decompress crunch format into dds
+ prepare = '''
+ var ddsHeader = byteArray.subarray(0, %(dds_header_size)d);
+ requestDecrunch('%(filename)s', byteArray.subarray(%(dds_header_size)d), function(ddsData) {
+ byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
+ byteArray.set(ddsHeader, 0);
+ byteArray.set(ddsData, %(dds_header_size)d);
+''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE }
+
+ finish = '''
+ Module['removeRunDependency']();
+ });
+'''
+
+ code += '''
+ var %(varname)s = new %(request)s();
+ %(varname)s.open('GET', '%(filename)s', true);
+ %(varname)s.responseType = 'arraybuffer';
+ %(varname)s.onload = function() {
+ var arrayBuffer = %(varname)s.response;
+ assert(arrayBuffer, 'Loading file %(filename)s failed.');
+ var byteArray = arrayBuffer.byteLength ? new Uint8Array(arrayBuffer) : arrayBuffer;
+ %(prepare)s
+ Module['FS_createDataFile']('/%(dirname)s', '%(basename)s', byteArray, true, true);
+ %(finish)s
+ };
+ Module['addRunDependency']();
+ %(varname)s.send(null);
+''' % {
+ 'request': 'DataRequest', # In the past we also supported XHRs here
+ 'varname': varname,
+ 'filename': filename,
+ 'dirname': os.path.dirname(filename),
+ 'basename': os.path.basename(filename),
+ 'prepare': prepare,
+ 'finish': finish
+ }
+ else:
+ assert 0
+
+if has_preloaded:
+ # Get the big archive and split it up
+ use_data = ''
+ for file_ in data_files:
+ if file_['mode'] == 'preload':
+ use_data += '''
+ curr = DataRequest.prototype.requests['%s'];
+ curr.response = byteArray.subarray(%d,%d);
+ curr.onload();
+ ''' % (file_['name'], file_['data_start'], file_['data_end'])
+ use_data += " Module['removeRunDependency']();\n"
+
+ if Compression.on:
+ use_data = '''
+ Module["decompress"](byteArray, function(decompressed) {
+ byteArray = new Uint8Array(decompressed);
+ %s
+ });
+''' % use_data
+
+ code += '''
+ var dataFile = new XMLHttpRequest();
+ dataFile.open('GET', '%s', true);
+ dataFile.responseType = 'arraybuffer';
+ dataFile.onload = function() {
+ var arrayBuffer = dataFile.response;
+ assert(arrayBuffer, 'Loading data file failed.');
+ var byteArray = new Uint8Array(arrayBuffer);
+ var curr;
+ %s
+ };
+ Module['addRunDependency']();
+ dataFile.send(null);
+ if (Module['setStatus']) Module['setStatus']('Downloading...');
+ ''' % (Compression.compressed_name(data_target) if Compression.on else data_target, use_data)
+
+if pre_run:
+ print '''
+ if (typeof Module == 'undefined') Module = {};
+ if (!Module['preRun']) Module['preRun'] = [];
+ Module["preRun"].push(function() {
+'''
+
+print code
+
+if pre_run:
+ print ' });\n'
+
+if crunch:
+ print '''
+ if (!Module['postRun']) Module['postRun'] = [];
+ Module["postRun"].push(function() {
+ decrunchWorker.terminate();
+ });
+'''
+
diff --git a/tools/ie7_fix.py b/tools/ie7_fix.py
new file mode 100644
index 00000000..3cdabb07
--- /dev/null
+++ b/tools/ie7_fix.py
@@ -0,0 +1,14 @@
+'''
+Simple tool to replace string lastchar from array access [] to charAt, for the purpose of IE7 support
+'''
+import os, sys, re
+
+inputFilename = sys.argv[1];
+outputFilename = sys.argv[2];
+
+inputFiledata = open(inputFilename).read()
+outputFile = open(outputFilename, "w")
+
+outputFile.write(re.sub('type\[type.length - 1\] ===? "\*"', 'type.charAt(type.length - 1) == "*"', inputFiledata))
+
+outputFile.close()
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 7094cdfc..d58c8c6c 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -24,11 +24,14 @@ if (ENVIRONMENT_IS_NODE) {
};
var nodeFS = require('fs');
+ var nodePath = require('path');
read = function(filename) {
+ filename = nodePath['normalize'](filename);
var ret = nodeFS['readFileSync'](filename).toString();
- if (!ret && filename[0] != '/') {
- filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename;
+ // The path is absolute if the normalized version is the same as the resolved.
+ if (!ret && filename != nodePath['resolve'](filename)) {
+ filename = path.join(__dirname, '..', 'src', filename);
ret = nodeFS['readFileSync'](filename).toString();
}
return ret;
@@ -97,12 +100,15 @@ if (typeof print === 'undefined') {
// Fix read for our location
read = function(filename) {
- if (filename[0] != '/') filename = __dirname.split('/').slice(0, -1).join('/') + '/src/' + filename;
+ // The path is absolute if the normalized version is the same as the resolved.
+ filename = path.normalize(filename);
+ if (filename != path.resolve(filename)) filename = path.join(__dirname, '..', 'src', filename);
return fs.readFileSync(filename).toString();
}
var uglify = require('../tools/eliminator/node_modules/uglify-js');
var fs = require('fs');
+var path = require('path');
// Load some modules
@@ -113,6 +119,8 @@ load('utility.js');
var FUNCTION = set('defun', 'function');
var LOOP = set('do', 'while', 'for');
var LOOP_FLOW = set('break', 'continue');
+var ASSIGN_OR_ALTER = set('assign', 'unary-postfix', 'unary-prefix');
+var CONTROL_FLOW = set('do', 'while', 'for', 'if', 'switch');
var NULL_NODE = ['name', 'null'];
var UNDEFINED_NODE = ['unary-prefix', 'void', ['num', 0]];
@@ -382,7 +390,7 @@ function simplifyExpressionsPre(ast) {
function simplifyBitops(ast) {
var USEFUL_BINARY_OPS = set('<<', '>>', '|', '&', '^');
- var SAFE_BINARY_OPS = set('+', '-', '*', '/', '%');
+ var SAFE_BINARY_OPS = set('+', '-', '*', '%'); // division is unsafe as it creates non-ints in JS
var ZERO = ['num', 0];
var rerun = true;
while (rerun) {
@@ -663,6 +671,18 @@ function optimizeShiftsInternal(ast, conservative) {
}
}
}
+ /* XXX - theoretically useful optimization(s), but commented out as not helpful in practice
+ // Transform (x << 2) >> 2 into x & mask or something even simpler
+ if (type == 'binary' && node[1] == '>>' && node[3][0] == 'num' &&
+ node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' && node[3][1] == node[2][3][1]) {
+ var subNode = node[2];
+ var shifts = node[3][1];
+ var mask = ((0xffffffff << shifts) >>> shifts) | 0;
+ return ['binary', '&', subNode[2], ['num', mask]];
+ //return ['binary', '|', subNode[2], ['num', 0]];
+ //return subNode[2];
+ }
+ */
});
// Re-combine remaining shifts, to undo the breaking up we did before. may require reordering inside +'s
traverse(fun, function(node, type, stack) {
@@ -1134,6 +1154,180 @@ function loopOptimizer(ast) {
vacuum(ast);
}
+// Very simple 'registerization', coalescing of variables into a smaller number.
+// We do not optimize when there are switches, so this pass only makes sense with
+// relooping.
+// TODO: Consider how this fits in with the rest of the optimization toolchain. Do
+// we still need the eliminator? Closure? And in what order? Perhaps just
+// closure simple?
+function registerize(ast) {
+ traverseGeneratedFunctions(ast, function(fun) {
+ // Replace all var definitions with assignments; we will add var definitions at the top after we registerize
+ // We also mark local variables - i.e., having a var definition
+ var localVars = {};
+ var hasSwitch = false; // we cannot optimize variables if there is a switch
+ traverse(fun, function(node, type) {
+ if (type == 'var') {
+ node[1].forEach(function(defined) { localVars[defined[0]] = 1 });
+ var vars = node[1].filter(function(varr) { return varr[1] });
+ if (vars.length > 1) {
+ var ret = ['stat', []];
+ var curr = ret[1];
+ for (var i = 0; i < vars.length-1; i++) {
+ curr[0] = 'seq';
+ curr[1] = ['assign', true, ['name', vars[i][0]], vars[i][1]];
+ if (i != vars.length-2) curr = curr[2] = [];
+ }
+ curr[2] = ['assign', true, ['name', vars[vars.length-1][0]], vars[vars.length-1][1]];
+ return ret;
+ } else if (vars.length == 1) {
+ return ['stat', ['assign', true, ['name', vars[0][0]], vars[0][1]]];
+ } else {
+ return emptyNode();
+ }
+ } else if (type == 'switch') {
+ hasSwitch = true;
+ }
+ });
+ vacuum(fun);
+ // Find the # of uses of each variable.
+ // While doing so, check if all a variable's uses are dominated in a simple
+ // way by a simple assign, if so, then we can assign its register to it
+ // just for its definition to its last use, and not to the entire toplevel loop,
+ // we call such variables "optimizable"
+ var varUses = {};
+ var level = 1;
+ var levelDominations = {};
+ var varLevels = {};
+ var possibles = {};
+ var unoptimizables = {};
+ traverse(fun, function(node, type) {
+ if (type == 'name') {
+ var name = node[1];
+ if (localVars[name]) {
+ if (!varUses[name]) varUses[name] = 0;
+ varUses[name]++;
+ if (possibles[name] && !varLevels[name]) unoptimizables[name] = 1; // used outside of simple domination
+ }
+ } else if (type == 'assign' && typeof node[1] != 'string') {
+ if (node[2] && node[2][0] == 'name') {
+ var name = node[2][1];
+ // if local and not yet used, this might be optimizable if we dominate
+ // all other uses
+ if (localVars[name] && !varUses[name] && !varLevels[name]) {
+ possibles[name] = 1;
+ varLevels[name] = level;
+ if (!levelDominations[level]) levelDominations[level] = {};
+ levelDominations[level][name] = 1;
+ }
+ }
+ } else if (type in CONTROL_FLOW) {
+ level++;
+ }
+ }, function(node, type) {
+ if (type in CONTROL_FLOW) {
+ // Invalidate all dominating on this level, further users make it unoptimizable
+ for (var name in levelDominations[level]) {
+ varLevels[name] = 0;
+ }
+ levelDominations[level] = null;
+ level--;
+ }
+ });
+ var optimizables = {};
+ if (!hasSwitch) {
+ for (var possible in possibles) {
+ if (!unoptimizables[possible]) optimizables[possible] = 1;
+ }
+ }
+ // Go through the function's code, assigning 'registers'.
+ // The only tricky bit is to keep variables locked on a register through loops,
+ // since they can potentially be returned to. Optimizable variables lock onto
+ // loops that they enter, unoptimizable variables lock in a conservative way
+ // into the topmost loop.
+ // Note that we cannot lock onto a variable in a loop if it was used and free'd
+ // before! (then they could overwrite us in the early part of the loop). For now
+ // we just use a fresh register to make sure we avoid this, but it could be
+ // optimized to check for safe registers (free, and not used in this loop level).
+ var varRegs = {}; // maps variables to the register they will use all their life
+ var freeRegs = [];
+ var nextReg = 1;
+ var fullNames = {};
+ var loopRegs = {}; // for each loop nesting level, the list of bound variables
+ var loops = 0; // 0 is toplevel, 1 is first loop, etc
+ var saved = 0;
+ var activeOptimizables = {};
+ var optimizableLoops = {};
+ function decUse(name) {
+ if (!varUses[name]) return false; // no uses left, or not a relevant variable
+ if (optimizables[name]) activeOptimizables[name] = 1;
+ var reg = varRegs[name];
+ if (!reg) {
+ // acquire register
+ if (optimizables[name] && freeRegs.length > 0) {
+ reg = freeRegs.pop();
+ saved++;
+ } else {
+ reg = nextReg++;
+ fullNames[reg] = 'r' + reg; // TODO: even smaller names
+ }
+ varRegs[name] = reg;
+ }
+ varUses[name]--;
+ assert(varUses[name] >= 0);
+ if (varUses[name] == 0) {
+ if (optimizables[name]) delete activeOptimizables[name];
+ // If we are not in a loop, or we are optimizable and not bound to a loop
+ // (we might have been in one but left it), we can free the register now.
+ if (loops == 0 || (optimizables[name] && !optimizableLoops[name])) {
+ // free register
+ freeRegs.push(reg);
+ } else {
+ // when the relevant loop is exited, we will free the register
+ var releventLoop = optimizables[name] ? (optimizableLoops[name] || 1) : 1;
+ if (!loopRegs[releventLoop]) loopRegs[releventLoop] = [];
+ loopRegs[releventLoop].push(reg);
+ }
+ }
+ return true;
+ }
+ traverse(fun, function(node, type) { // XXX we rely on traversal order being the same as execution order here
+ if (type == 'name') {
+ var name = node[1];
+ if (decUse(name)) {
+ node[1] = fullNames[varRegs[name]];
+ }
+ } else if (type in LOOP) {
+ loops++;
+ // Active optimizables lock onto this loop, if not locked onto one that encloses this one
+ for (var name in activeOptimizables) {
+ if (!optimizableLoops[name]) {
+ optimizableLoops[name] = loops;
+ }
+ }
+ }
+ }, function(node, type) {
+ if (type in LOOP) {
+ // Free registers that were locked to this loop
+ if (loopRegs[loops]) {
+ freeRegs = freeRegs.concat(loopRegs[loops]);
+ loopRegs[loops] = [];
+ }
+ loops--;
+ }
+ });
+ // Add vars at the beginning
+ if (nextReg > 1) {
+ var vars = [];
+ for (var i = 1; i < nextReg; i++) {
+ vars.push([fullNames[i]]);
+ }
+ getStatements(fun).unshift(['var', vars]);
+ }
+ //printErr(fun[1] + ': saved ' + saved + ' / ' + (saved + nextReg - 1) + ' vars through registerization'); // not totally accurate
+ });
+}
+
// Passes table
var compress = false;
@@ -1150,6 +1344,7 @@ var passes = {
simplifyExpressionsPost: simplifyExpressionsPost,
hoistMultiples: hoistMultiples,
loopOptimizer: loopOptimizer,
+ registerize: registerize,
compress: function() { compress = true; }
};
diff --git a/tools/ll-strip.py b/tools/ll-strip.py
new file mode 100755
index 00000000..b03e4f3a
--- /dev/null
+++ b/tools/ll-strip.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+import sys, re
+
+def print_usage():
+ print >> sys.stderr, "Usage: ll-strip.py file from to"
+ print >> sys.stderr, "\tStrip function bodies in all ll file in the [from, to] range"
+ sys.exit(1)
+
+try:
+ range_from = int(sys.argv[2])
+ range_to = int(sys.argv[3])
+ if range_from >= range_to:
+ raise "error"
+ file = open(sys.argv[1])
+except:
+ print_usage()
+
+func_start = re.compile("^define\s")
+func_end = re.compile("^}$")
+
+function_counter = 0
+in_function = False
+line_number = 0
+skip = False
+dummy_stmt = "unreachable"
+for orig_line in file:
+ line = orig_line.strip()
+ if func_start.match(line):
+ if in_function:
+ print >> sys.stderr, "Discovered a function inside another function!"
+ sys.exit(1)
+ in_function = True
+ line_number = 0
+ skip = False
+ function_counter = function_counter + 1
+ elif func_end.match(line):
+ if not in_function:
+ print >> sys.stderr, "Discovered a function end without a matching beginning!"
+ sys.exit(1)
+ in_function = False
+ line_number = 0
+ skip = False
+ elif in_function:
+ line_number = line_number + 1
+ if not skip and line_number == 1:
+ if line == dummy_stmt:
+ function_counter = function_counter - 1
+ if range_from <= function_counter <= range_to and line_number == 1:
+ #import pdb;pdb.set_trace()
+ if line != dummy_stmt:
+ skip = True
+ print dummy_stmt
+ if not skip:
+ print orig_line.rstrip("\n")
+
diff --git a/tools/make_minigzip.py b/tools/make_minigzip.py
index cdd9c2ab..60177318 100644
--- a/tools/make_minigzip.py
+++ b/tools/make_minigzip.py
@@ -9,5 +9,5 @@ zlib = shared.Building.build_library('zlib', shared.EMSCRIPTEN_TEMP_DIR, shared.
print 'Building minigzip'
-Popen([shared.EMCC, '-O2', shared.path_from_root('tests', 'zlib', 'minigzip.c'), zlib, '-o', shared.path_from_root('tools', 'minigzip.js')]).communicate()
+Popen(['python', shared.EMCC, '-O2', shared.path_from_root('tests', 'zlib', 'minigzip.c'), zlib, '-o', shared.path_from_root('tools', 'minigzip.js')]).communicate()
diff --git a/tools/scan_js.py b/tools/scan_js.py
new file mode 100644
index 00000000..eeff7c7c
--- /dev/null
+++ b/tools/scan_js.py
@@ -0,0 +1,20 @@
+'''
+Finds why a .js file is large by printing functions by size
+'''
+
+import os, sys
+
+funcs = []
+i = 0
+inside = None
+for line in open(sys.argv[1]):
+ i += 1
+ if line.startswith('function _'):
+ inside = line.replace('function ', '').replace('\n', '')
+ start = i
+ elif inside and line.startswith('}'):
+ funcs.append((inside, i-start))
+ inside = None
+
+print '\n'.join(map(lambda func: str(func[1]) + ':' + func[0], sorted(funcs, key=lambda func: -func[1])))
+
diff --git a/tools/scons/site_scons/site_tools/emscripten/emscripten.py b/tools/scons/site_scons/site_tools/emscripten/emscripten.py
index cb14b58e..7ccf2c5f 100644
--- a/tools/scons/site_scons/site_tools/emscripten/emscripten.py
+++ b/tools/scons/site_scons/site_tools/emscripten/emscripten.py
@@ -28,7 +28,7 @@ def generate(env, emscripten_path=None, **kw):
env.Replace(CC = os.path.join(emscPath, "emcc" ))
env.Replace(CXX = os.path.join(emscPath, "em++" ))
- env.Replace(LINK = os.path.join(emscPath, "emld" ))
+ env.Replace(LINK = os.path.join(emscPath, "emcc" ))
# SHLINK and LDMODULE should use LINK so no
# need to change them here
diff --git a/tools/shared.py b/tools/shared.py
index 6a63d4ec..997c0ad9 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1,4 +1,4 @@
-import shutil, time, os, sys, json, tempfile, copy
+import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess
from subprocess import Popen, PIPE, STDOUT
from tempfile import mkstemp
@@ -6,15 +6,22 @@ __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
def path_from_root(*pathelems):
return os.path.join(__rootpath__, *pathelems)
-# Config file
+# Emscripten configuration is done through the EM_CONFIG environment variable.
+# If the string value contained in this environment variable contains newline
+# separated definitions, then these definitions will be used to configure
+# Emscripten. Otherwise, the string is understood to be a path to a settings
+# file that contains the required definitions.
EM_CONFIG = os.environ.get('EM_CONFIG')
if not EM_CONFIG:
EM_CONFIG = '~/.emscripten'
-CONFIG_FILE = os.path.expanduser(EM_CONFIG)
-if not os.path.exists(CONFIG_FILE):
- shutil.copy(path_from_root('settings.py'), CONFIG_FILE)
- print >> sys.stderr, '''
+if '\n' in EM_CONFIG:
+ CONFIG_FILE = None
+else:
+ CONFIG_FILE = os.path.expanduser(EM_CONFIG)
+ if not os.path.exists(CONFIG_FILE):
+ shutil.copy(path_from_root('settings.py'), CONFIG_FILE)
+ print >> sys.stderr, '''
==============================================================================
Welcome to Emscripten!
@@ -28,11 +35,12 @@ make sure LLVM_ROOT and NODE_JS are correct.
This command will now exit. When you are done editing those paths, re-run it.
==============================================================================
''' % (EM_CONFIG, CONFIG_FILE)
- sys.exit(0)
+ sys.exit(0)
try:
- exec(open(CONFIG_FILE, 'r').read())
+ config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG
+ exec(config_text)
except Exception, e:
- print >> sys.stderr, 'Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e))
+ print >> sys.stderr, 'Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text)
sys.exit(1)
# Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM)
@@ -43,6 +51,8 @@ except Exception, e:
def check_sanity(force=False):
try:
if not force:
+ if not CONFIG_FILE:
+ return # config stored directly in EM_CONFIG => skip sanity checks
settings_mtime = os.stat(CONFIG_FILE).st_mtime
sanity_file = CONFIG_FILE + '_sanity'
try:
@@ -52,6 +62,9 @@ def check_sanity(force=False):
except:
pass
+ print >> sys.stderr, '(Emscripten: Config file changed, clearing cache)' # LLVM may have changed, etc.
+ Cache.erase()
+
print >> sys.stderr, '(Emscripten: Running sanity checks)'
if not check_engine(COMPILER_ENGINE):
@@ -68,6 +81,11 @@ def check_sanity(force=False):
print >> sys.stderr, 'FATAL: Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG)
sys.exit(0)
+ try:
+ subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE)
+ except:
+ print >> sys.stderr, 'WARNING: java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten (see settings.py)'
+
if not os.path.exists(CLOSURE_COMPILER):
print >> sys.stderr, 'WARNING: Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG)
@@ -89,7 +107,6 @@ CLANG_CC=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang'))
CLANG_CPP=os.path.expanduser(os.path.join(LLVM_ROOT, 'clang++'))
CLANG=CLANG_CPP
LLVM_LINK=os.path.join(LLVM_ROOT, 'llvm-link')
-LLVM_LD=os.path.join(LLVM_ROOT, 'llvm-ld')
LLVM_AR=os.path.join(LLVM_ROOT, 'llvm-ar')
LLVM_OPT=os.path.expanduser(os.path.join(LLVM_ROOT, 'opt'))
LLVM_AS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-as'))
@@ -97,6 +114,7 @@ LLVM_DIS=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-dis'))
LLVM_NM=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-nm'))
LLVM_INTERPRETER=os.path.expanduser(os.path.join(LLVM_ROOT, 'lli'))
LLVM_COMPILER=os.path.expanduser(os.path.join(LLVM_ROOT, 'llc'))
+LLVM_EXTRACT=os.path.expanduser(os.path.join(LLVM_ROOT, 'llvm-extract'))
COFFEESCRIPT = path_from_root('tools', 'eliminator', 'node_modules', 'coffee-script', 'bin', 'coffee')
EMSCRIPTEN = path_from_root('emscripten.py')
@@ -105,28 +123,41 @@ NAMESPACER = path_from_root('tools', 'namespacer.py')
EMCC = path_from_root('emcc')
EMXX = path_from_root('em++')
EMAR = path_from_root('emar')
-EMLD = path_from_root('emld')
EMRANLIB = path_from_root('emranlib')
EMLIBTOOL = path_from_root('emlibtool')
+EMCONFIG = path_from_root('em-config')
EMMAKEN = path_from_root('tools', 'emmaken.py')
AUTODEBUGGER = path_from_root('tools', 'autodebugger.py')
BINDINGS_GENERATOR = path_from_root('tools', 'bindings_generator.py')
EXEC_LLVM = path_from_root('tools', 'exec_llvm.py')
VARIABLE_ELIMINATOR = path_from_root('tools', 'eliminator', 'eliminator.coffee')
JS_OPTIMIZER = path_from_root('tools', 'js-optimizer.js')
+FILE_PACKAGER = path_from_root('tools', 'file_packager.py')
-# Temp dir
+# Temp dir. Create a random one, unless EMCC_DEBUG is set, in which case use TEMP_DIR/emscripten_temp
try:
- EMSCRIPTEN_TEMP_DIR = os.path.join(TEMP_DIR, 'emscripten_temp')
- if not os.path.exists(EMSCRIPTEN_TEMP_DIR):
- try:
- os.makedirs(EMSCRIPTEN_TEMP_DIR)
- except Exception, e:
- print >> sys.stderr, 'Warning: Could not create temp dir (%s): %s' % (EMSCRIPTEN_TEMP_DIR, str(e))
+ TEMP_DIR
except:
+ print >> sys.stderr, 'TEMP_DIR not defined in ~/.emscripten, using /tmp'
+ TEMP_DIR = '/tmp'
+
+CANONICAL_TEMP_DIR = os.path.join(TEMP_DIR, 'emscripten_temp')
+EMSCRIPTEN_TEMP_DIR = None
+
+if os.environ.get('EMCC_DEBUG'):
+ try:
+ EMSCRIPTEN_TEMP_DIR = CANONICAL_TEMP_DIR
+ if not os.path.exists(EMSCRIPTEN_TEMP_DIR):
+ os.makedirs(EMSCRIPTEN_TEMP_DIR)
+ except:
+ print >> sys.stderr, 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten'
+
+if not EMSCRIPTEN_TEMP_DIR:
EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_')
- print >> sys.stderr, 'Warning: TEMP_DIR not defined in %s, using %s' % (EM_CONFIG, EMSCRIPTEN_TEMP_DIR)
+ def clean_temp():
+ try_delete(EMSCRIPTEN_TEMP_DIR)
+ atexit.register(clean_temp)
# EM_CONFIG stuff
@@ -144,6 +175,12 @@ try:
except:
CLOSURE_COMPILER = path_from_root('third_party', 'closure-compiler', 'compiler.jar')
+try:
+ JAVA
+except:
+ print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"'
+ JAVA = 'java'
+
# Additional compiler options
try:
@@ -153,7 +190,7 @@ except:
# Force a simple, standard target as much as possible: target 32-bit linux, and disable various flags that hint at other platforms
COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-U__SSE__', '-U__SSE2__', '-U__MMX__',
'-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87', '-DEMSCRIPTEN', '-U__STRICT_ANSI__', '-U__CYGWIN__',
- '-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu']
+ '-D__STDC__', '-Xclang', '-triple=i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN']
USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK')
@@ -161,8 +198,10 @@ USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK')
if USE_EMSDK:
# Disable system C and C++ include directories, and add our own (using -idirafter so they are last, like system dirs, which
# allows projects to override them)
- EMSDK_OPTS = ['-nostdinc', '-nostdinc++', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdinc++', '-Xclang', '-nostdsysteminc',
+ # Note that -nostdinc++ is not needed, since -nostdinc implies that!
+ EMSDK_OPTS = ['-nostdinc', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdsysteminc',
'-Xclang', '-isystem' + path_from_root('system', 'include'),
+ '-Xclang', '-isystem' + path_from_root('system', 'include', 'emscripten'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'bsd'), # posix stuff
'-Xclang', '-isystem' + path_from_root('system', 'include', 'libc'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'libcxx'),
@@ -170,7 +209,7 @@ if USE_EMSDK:
'-Xclang', '-isystem' + path_from_root('system', 'include', 'net'),
'-Xclang', '-isystem' + path_from_root('system', 'include', 'SDL'),
] + [
- '-U__APPLE__'
+ '-U__APPLE__', '-U__linux__'
]
COMPILER_OPTS += EMSDK_OPTS
else:
@@ -178,11 +217,25 @@ else:
# Engine tweaks
-#if 'strict' not in str(SPIDERMONKEY_ENGINE): # XXX temporarily disable strict mode until we sort out some stuff
-# SPIDERMONKEY_ENGINE += ['-e', "options('strict')"] # Strict mode in SpiderMonkey. With V8 we check that fallback to non-strict works too
-
-if 'gcparam' not in str(SPIDERMONKEY_ENGINE):
- SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap
+try:
+ if 'gcparam' not in str(SPIDERMONKEY_ENGINE):
+ if type(SPIDERMONKEY_ENGINE) is str:
+ SPIDERMONKEY_ENGINE = [SPIDERMONKEY_ENGINE]
+ SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap
+except NameError:
+ pass
+
+WINDOWS = sys.platform.startswith('win')
+
+# If we have 'env', we should use that to find python, because |python| may fail while |env python| may work
+# (For example, if system python is 3.x while we need 2.x, and env gives 2.x if told to do so.)
+ENV_PREFIX = []
+if not WINDOWS:
+ try:
+ assert 'Python' in Popen(['env', 'python', '-V'], stdout=PIPE, stderr=STDOUT).communicate()[0]
+ ENV_PREFIX = ['env']
+ except:
+ pass
# Temp file utilities
@@ -190,7 +243,10 @@ def try_delete(filename):
try:
os.unlink(filename)
except:
- pass
+ try:
+ shutil.rmtree(filename)
+ except:
+ pass
class TempFiles:
def __init__(self):
@@ -221,6 +277,8 @@ class TempFiles:
def check_engine(engine):
# TODO: we call this several times, perhaps cache the results?
try:
+ if not CONFIG_FILE:
+ return True # config stored directly in EM_CONFIG => skip engine check
return 'hello, world!' in run_js(path_from_root('tests', 'hello_world.js'), engine)
except Exception, e:
print 'Checking JS engine %s failed. Check %s. Details: %s' % (str(engine), EM_CONFIG, str(e))
@@ -236,11 +294,14 @@ def timeout_run(proc, timeout, note='unnamed process'):
raise Exception("Timed out: " + note)
return proc.communicate()[0]
+EM_DEBUG = os.environ.get('EM_DEBUG')
+
def run_js(filename, engine=None, args=[], check_timeout=False, stdout=PIPE, stderr=None, cwd=None):
if engine is None: engine = JS_ENGINES[0]
if type(engine) is not list: engine = [engine]
- return timeout_run(Popen(engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args,
- stdout=stdout, stderr=stderr, cwd=cwd), 15*60 if check_timeout else None, 'Execution')
+ command = engine + [filename] + (['--'] if 'd8' in engine[0] else []) + args
+ if EM_DEBUG: print >> sys.stderr, 'run_js: ' + ' '.join(command)
+ return timeout_run(Popen(command, stdout=stdout, stderr=stderr, cwd=cwd), 15*60 if check_timeout else None, 'Execution')
def to_cc(cxx):
# By default, LLVM_GCC and CLANG are really the C++ versions. This gets an explicit C version
@@ -272,7 +333,7 @@ def read_pgo_data(filename):
'''
signs_lines = []
overflows_lines = []
-
+
for line in open(filename, 'r'):
try:
if line.rstrip() == '': continue
@@ -335,10 +396,12 @@ class Settings:
if opt_level >= 2:
Settings.RELOOP = 1
if opt_level >= 3:
+ Settings.INLINING_LIMIT = 0
+ Settings.DOUBLE_MODE = 0
+ Settings.PRECISE_I64_MATH = 0
Settings.CORRECT_SIGNS = 0
Settings.CORRECT_OVERFLOWS = 0
Settings.CORRECT_ROUNDINGS = 0
- Settings.DOUBLE_MODE = 0
if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
global Settings
@@ -357,11 +420,11 @@ class Building:
@staticmethod
def get_building_env():
env = os.environ.copy()
- env['CC'] = EMCC
- env['CXX'] = EMXX
- env['AR'] = EMAR
- env['RANLIB'] = EMRANLIB
- env['LIBTOOL'] = EMLIBTOOL
+ env['CC'] = EMCC if not WINDOWS else 'python %r' % EMCC
+ env['CXX'] = EMXX if not WINDOWS else 'python %r' % EMXX
+ env['AR'] = EMAR if not WINDOWS else 'python %r' % EMAR
+ env['RANLIB'] = EMRANLIB if not WINDOWS else 'python %r' % EMRANLIB
+ env['LIBTOOL'] = EMLIBTOOL if not WINDOWS else 'python %r' % EMLIBTOOL
env['EMMAKEN_COMPILER'] = Building.COMPILER
env['EMSCRIPTEN_TOOLS'] = path_from_root('tools')
env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(Building.COMPILER_TEST_OPTS)
@@ -373,14 +436,14 @@ class Building:
@staticmethod
def handle_CMake_toolchain(args, env):
- CMakeToolchain = '''# the name of the target operating system
+ CMakeToolchain = ('''# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Linux)
# which C and C++ compiler to use
-SET(CMAKE_C_COMPILER $EMSCRIPTEN_ROOT/emcc)
-SET(CMAKE_CXX_COMPILER $EMSCRIPTEN_ROOT/em++)
-SET(CMAKE_AR $EMSCRIPTEN_ROOT/emar)
-SET(CMAKE_RANLIB $EMSCRIPTEN_ROOT/emranlib)
+SET(CMAKE_C_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/emcc)
+SET(CMAKE_CXX_COMPILER %(winfix)s$EMSCRIPTEN_ROOT/em++)
+SET(CMAKE_AR %(winfix)s$EMSCRIPTEN_ROOT/emar)
+SET(CMAKE_RANLIB %(winfix)s$EMSCRIPTEN_ROOT/emranlib)
SET(CMAKE_C_FLAGS $CFLAGS)
SET(CMAKE_CXX_FLAGS $CXXFLAGS)
@@ -393,8 +456,8 @@ SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include )
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
-set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
- .replace('$EMSCRIPTEN_ROOT', path_from_root('')) \
+set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS else 'python ' }) \
+ .replace('$EMSCRIPTEN_ROOT', path_from_root('').replace('\\', '/')) \
.replace('$CFLAGS', env['CFLAGS']) \
.replace('$CXXFLAGS', env['CFLAGS'])
toolchainFile = mkstemp(suffix='.txt')[1]
@@ -409,17 +472,17 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
env['EMMAKEN_JUST_CONFIGURE'] = '1'
if 'cmake' in args[0]:
args = Building.handle_CMake_toolchain(args, env)
- Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0]
+ Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()
del env['EMMAKEN_JUST_CONFIGURE']
@staticmethod
def make(args, stdout=None, stderr=None, env=None):
if env is None:
env = Building.get_building_env()
- Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0]
+ Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()
@staticmethod
- def build_library(name, build_dir, output_dir, generated_libs, configure=['./configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=None, cache_name=None, copy_project=False, env_init={}, source_dir=None):
+ def build_library(name, build_dir, output_dir, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=None, cache_name=None, copy_project=False, env_init={}, source_dir=None):
''' Build a library into a .bc file. We build the .bc file once and cache it for all our tests. (We cache in
memory since the test directory is destroyed and recreated for each test. Note that we cache separately
for different compilers).
@@ -453,22 +516,95 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
if configure: # Useful in debugging sometimes to comment this out (and the lines below up to and including the |link| call)
Building.configure(configure + configure_args, stdout=open(os.path.join(project_dir, 'configure_'), 'w'),
stderr=open(os.path.join(project_dir, 'configure_err'), 'w'), env=env)
- Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_'), 'w'),
- stderr=open(os.path.join(project_dir, 'make_err'), 'w'), env=env)
- if cache is not None:
- cache[cache_name] = []
- for f in generated_libs:
- basename = os.path.basename(f)
- cache[cache_name].append((basename, open(f, 'rb').read()))
+ for i in range(2): # workaround for some build systems that need to be run twice to succeed (e.g. poppler)
+ Building.make(make + make_args, stdout=open(os.path.join(project_dir, 'make_' + str(i)), 'w'),
+ stderr=open(os.path.join(project_dir, 'make_err' + str(i)), 'w'), env=env)
+ try:
+ if cache is not None:
+ cache[cache_name] = []
+ for f in generated_libs:
+ basename = os.path.basename(f)
+ cache[cache_name].append((basename, open(f, 'rb').read()))
+ break
+ except:
+ if i > 0: raise Exception('could not build library ' + name)
if old_dir:
os.chdir(old_dir)
return generated_libs
@staticmethod
- def link(files, target):
+ def link(files, target, remove_duplicates=False):
+ actual_files = []
+ unresolved_symbols = set() # necessary for .a linking, see below
+ resolved_symbols = set()
+ temp_dir = None
+ for f in files:
+ if not Building.is_ar(f):
+ if Building.is_bitcode(f):
+ new_symbols = Building.llvm_nm(f)
+ resolved_symbols = resolved_symbols.union(new_symbols.defs)
+ unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
+ actual_files.append(f)
+ else:
+ # Extract object files from ar archives, and link according to gnu ld semantics
+ # (link in an entire .o from the archive if it supplies symbols still unresolved)
+ cwd = os.getcwd()
+ try:
+ temp_dir = os.path.join(EMSCRIPTEN_TEMP_DIR, 'ar_output_' + str(os.getpid()))
+ if not os.path.exists(temp_dir):
+ os.makedirs(temp_dir)
+ os.chdir(temp_dir)
+ contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n'))
+ if len(contents) == 0:
+ print >> sys.stderr, 'Warning: Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f
+ else:
+ for content in contents: # ar will silently fail if the directory for the file does not exist, so make all the necessary directories
+ dirname = os.path.dirname(content)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ Popen([LLVM_AR, 'x', f], stdout=PIPE).communicate() # if absolute paths, files will appear there. otherwise, in this directory
+ contents = map(lambda content: os.path.join(temp_dir, content), contents)
+ contents = filter(os.path.exists, map(os.path.abspath, contents))
+ needed = False # We add or do not add the entire archive. We let llvm dead code eliminate parts we do not need, instead of
+ # doing intra-dependencies between archive contents
+ for content in contents:
+ new_symbols = Building.llvm_nm(content)
+ # Link in the .o if it provides symbols, *or* this is a singleton archive (which is apparently an exception in gcc ld)
+ if new_symbols.defs.intersection(unresolved_symbols) or len(files) == 1:
+ needed = True
+ if needed:
+ for content in contents:
+ if Building.is_bitcode(content):
+ new_symbols = Building.llvm_nm(content)
+ resolved_symbols = resolved_symbols.union(new_symbols.defs)
+ unresolved_symbols = unresolved_symbols.union(new_symbols.undefs.difference(resolved_symbols)).difference(new_symbols.defs)
+ actual_files.append(content)
+ finally:
+ os.chdir(cwd)
try_delete(target)
- output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target], stdout=PIPE).communicate()[0]
- assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output
+
+ if remove_duplicates:
+ # Remove duplicate symbols. This is a workaround for how we compile .a files, we try to
+ # emulate ld behavior which is permissive TODO: cache llvm-nm results
+ seen_symbols = set()
+ print >> sys.stderr, actual_files
+ for actual in actual_files:
+ symbols = Building.llvm_nm(actual)
+ dupes = seen_symbols.intersection(symbols.defs)
+ if len(dupes) > 0:
+ print >> sys.stderr, 'emcc: warning: removing duplicates in', actual
+ for dupe in dupes:
+ print >> sys.stderr, 'emcc: warning: removing duplicate', dupe
+ Popen([LLVM_EXTRACT, actual, '-delete', '-glob=' + dupe, '-o', actual], stderr=PIPE).communicate()
+ Popen([LLVM_EXTRACT, actual, '-delete', '-func=' + dupe, '-o', actual], stderr=PIPE).communicate()
+ Popen([LLVM_EXTRACT, actual, '-delete', '-glob=.str', '-o', actual], stderr=PIPE).communicate() # garbage that appears here
+ seen_symbols = seen_symbols.union(symbols.defs)
+
+ # Finish link
+ output = Popen([LLVM_LINK] + actual_files + ['-o', target], stdout=PIPE).communicate()[0]
+ assert os.path.exists(target) and (output is None or 'Could not open input file' not in output), 'Linking error: ' + output + '\nemcc: If you get duplicate symbol errors, try --remove-duplicates'
+ if temp_dir:
+ try_delete(temp_dir)
# Emscripten optimizations that we run on the .ll file
@staticmethod
@@ -497,12 +633,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
shutil.move(filename + '.o', filename + '.o.pre')
output = Popen([LLVM_OPT, filename + '.o.pre'] + Building.LLVM_OPT_OPTS + ['-o=' + filename + '.o'], stdout=PIPE).communicate()[0]
assert os.path.exists(filename + '.o'), 'Failed to run llvm optimizations: ' + output
- #if Building.LLVM_OPTS == 2:
- # print 'Unsafe LD!'
- # shutil.move(filename + '.o', filename + '.o.pre')
- # output = Popen([LLVM_LD, filename + '.o.pre', '-o=' + filename + '.tmp'], stdout=PIPE).communicate()[0]
- # assert os.path.exists(filename + '.tmp.bc'), 'Failed to run llvm optimizations: ' + output
- # shutil.move(filename + '.tmp.bc', filename + '.o')
@staticmethod
def llvm_dis(input_filename, output_filename=None):
@@ -538,13 +668,15 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
commons = []
for line in output.split('\n'):
if len(line) == 0: continue
- status, symbol = filter(lambda seg: len(seg) > 0, line.split(' '))
- if status == 'U':
- ret.undefs.append(symbol)
- elif status != 'C':
- ret.defs.append(symbol)
- else:
- ret.commons.append(symbol)
+ parts = filter(lambda seg: len(seg) > 0, line.split(' '))
+ if len(parts) == 2: # ignore lines with absolute offsets, these are not bitcode anyhow (e.g. |00000630 t d_source_name|)
+ status, symbol = parts
+ if status == 'U':
+ ret.undefs.append(symbol)
+ elif status != 'C':
+ ret.defs.append(symbol)
+ else:
+ ret.commons.append(symbol)
ret.defs = set(ret.defs)
ret.undefs = set(ret.undefs)
ret.commons = set(ret.commons)
@@ -555,13 +687,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
if output_filename is None:
output_filename = filename + '.o'
try_delete(output_filename)
- Popen([EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate()
+ Popen(ENV_PREFIX + ['python', EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate()
assert os.path.exists(output_filename), 'emcc could not create output file'
@staticmethod
def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None):
try_delete(output_filename)
- Popen([EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate()
+ Popen(ENV_PREFIX + ['python', EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate()
if 'c' in action:
assert os.path.exists(output_filename), 'emar could not create output file'
@@ -572,7 +704,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
# Run Emscripten
settings = Settings.serialize()
- compiler_output = timeout_run(Popen(['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE), None, 'Compiling')
+ compiler_output = timeout_run(Popen(ENV_PREFIX + ['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE), None, 'Compiling')
#print compiler_output
# Detect compilation crashes and errors
@@ -703,8 +835,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
if type(passes) == str:
passes = [passes]
# XXX Disable crankshaft to work around v8 bug 1895
- output, err = Popen([NODE_JS, '--nocrankshaft', JS_OPTIMIZER, filename] + passes, stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate()
- assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + err + '\n\n' + output
+ output = Popen([NODE_JS, '--nocrankshaft', JS_OPTIMIZER, filename] + passes, stdout=PIPE).communicate()[0]
+ assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output
filename += '.jo.js'
f = open(filename, 'w')
f.write(output)
@@ -719,8 +851,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
coffee = path_from_root('tools', 'eliminator', 'node_modules', 'coffee-script', 'bin', 'coffee')
eliminator = path_from_root('tools', 'eliminator', 'eliminator.coffee')
input = open(filename, 'r').read()
- output, err = Popen([NODE_JS, coffee, eliminator], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(input)
- assert len(output) > 0, 'Error in eliminator: ' + err + '\n\n' + output
+ output = Popen([NODE_JS, coffee, eliminator, filename], stdout=PIPE).communicate()[0]
+ assert len(output) > 0, 'Error in eliminator: ' + output
filename += '.el.js'
f = open(filename, 'w')
f.write(output)
@@ -734,13 +866,19 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
# Something like this (adjust memory as needed):
# java -Xmx1024m -jar CLOSURE_COMPILER --compilation_level ADVANCED_OPTIMIZATIONS --variable_map_output_file src.cpp.o.js.vars --js src.cpp.o.js --js_output_file src.cpp.o.cc.js
- cc_output = Popen(['java', '-jar', CLOSURE_COMPILER,
- '--compilation_level', 'ADVANCED_OPTIMIZATIONS',
- '--formatting', 'PRETTY_PRINT',
- #'--variable_map_output_file', filename + '.vars',
- '--js', filename, '--js_output_file', filename + '.cc.js'], stdout=PIPE, stderr=STDOUT).communicate()[0]
- if 'ERROR' in cc_output or not os.path.exists(filename + '.cc.js'):
- raise Exception('closure compiler error: ' + cc_output)
+ args = [JAVA,
+ '-Xmx1024m',
+ '-jar', CLOSURE_COMPILER,
+ '--compilation_level', 'ADVANCED_OPTIMIZATIONS',
+ '--formatting', 'PRETTY_PRINT',
+ #'--variable_map_output_file', filename + '.vars',
+ '--js', filename, '--js_output_file', filename + '.cc.js']
+ if os.environ.get('EMCC_CLOSURE_ARGS'):
+ args += shlex.split(os.environ.get('EMCC_CLOSURE_ARGS'))
+ process = Popen(args, stdout=PIPE, stderr=STDOUT)
+ cc_output = process.communicate()[0]
+ if process.returncode != 0 or not os.path.exists(filename + '.cc.js'):
+ raise Exception('closure compiler error: ' + cc_output + ' (rc: %d)' % process.returncode)
return filename + '.cc.js'
@@ -789,12 +927,14 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \
elif ord(b[0]) == 222 and ord(b[1]) == 192 and ord(b[2]) == 23 and ord(b[3]) == 11:
b = open(filename, 'r').read(24)
return b[20] == 'B' and b[21] == 'C'
-
+
return False
# Permanent cache for dlmalloc and stdlibc++
class Cache:
- dirname = os.path.expanduser(os.path.join('~', '.emscripten_cache'))
+ dirname = os.environ.get('EM_CACHE')
+ if not dirname:
+ dirname = os.path.expanduser(os.path.join('~', '.emscripten_cache'))
@staticmethod
def erase():
@@ -816,3 +956,41 @@ class Cache:
shutil.copyfile(creator(), cachename)
return cachename
+# Compression of code and data for smaller downloads
+class Compression:
+ on = False
+
+ @staticmethod
+ def compressed_name(filename):
+ return filename + '.compress'
+
+ @staticmethod
+ def compress(filename):
+ execute(Compression.encoder, stdin=open(filename, 'rb'), stdout=open(Compression.compressed_name(filename), 'wb'))
+
+ @staticmethod
+ def worth_it(original, compressed):
+ return compressed < original - 1500 # save at least one TCP packet or so
+
+def execute(cmd, *args, **kw):
+ try:
+ return subprocess.Popen(cmd, *args, **kw).communicate() # let compiler frontend print directly, so colors are saved (PIPE kills that)
+ except:
+ if not isinstance(cmd, str):
+ cmd = ' '.join(cmd)
+ print >> sys.stderr, 'Invoking Process failed: <<< ' + cmd + ' >>>'
+ raise
+
+def suffix(name):
+ parts = name.split('.')
+ if len(parts) > 1:
+ return parts[-1]
+ else:
+ return None
+
+def unsuffixed(name):
+ return '.'.join(name.split('.')[:-1])
+
+def unsuffixed_basename(name):
+ return os.path.basename(unsuffixed(name))
+
diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js
index ca76cae1..a312296d 100644
--- a/tools/test-js-optimizer-output.js
+++ b/tools/test-js-optimizer-output.js
@@ -86,7 +86,7 @@ function bits() {
z($f << 2);
z($f * 100 << 2);
z($f % 2 | 255);
- z($f / 55 & 255);
+ z(($f | 0) / 55 & 255);
z($f - 22 ^ 1);
z($f + 15 << 2);
}
@@ -311,4 +311,7 @@ function notComps() {
shoo();
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"]
+function tricky() {
+ var $conv642 = $conv6374 - (($132 << 16 >> 16 | 0) / 2 & -1) & 65535;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps", "tricky"]
diff --git a/tools/test-js-optimizer-regs-output.js b/tools/test-js-optimizer-regs-output.js
new file mode 100644
index 00000000..a5e97f46
--- /dev/null
+++ b/tools/test-js-optimizer-regs-output.js
@@ -0,0 +1,228 @@
+function test() {
+ var r1, r2;
+ r1 = 0;
+ f(r1);
+ r1 += 1;
+ r2 = r1 + 2;
+ g(r1, r2);
+ f(r1);
+ r1 = cheez();
+ r2 = r1 + 2;
+ g(r2, r2);
+ r2 = 200;
+ r2 = 203;
+ r2 = 205;
+ r1 = 208;
+ c(r2);
+ while (f()) {
+ r2 = 5;
+ r1 = 12;
+ gg(r2, r1 * 2);
+ r1 = 100;
+ gg(r1, 20);
+ }
+ r1 = f(), r2 = 100, r2 = 1e3, r2 = 1e5;
+ f(r1());
+}
+function primes() {
+ var r1, r2, r3, r4, r5, r6, r7;
+ r1 = 2;
+ r2 = 0;
+ $_$2 : while (1) {
+ r3 = r1 | 0;
+ r4 = _sqrtf(r3);
+ r3 = 2;
+ $_$4 : while (1) {
+ r5 = r3 | 0;
+ r6 = r5 < r4;
+ if (!r6) {
+ r7 = 1;
+ break $_$4;
+ }
+ r6 = (r1 | 0) % (r3 | 0);
+ r5 = (r6 | 0) == 0;
+ if (r5) {
+ r7 = 0;
+ break $_$4;
+ }
+ r5 = r3 + 1 | 0;
+ r3 = r5;
+ }
+ r3 = r7 + r2 | 0;
+ r4 = r1 + 1 | 0;
+ r5 = (r3 | 0) < 1e5;
+ if (r5) {
+ r1 = r4;
+ r2 = r3;
+ } else {
+ break $_$2;
+ }
+ }
+ r2 = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r1, tempInt));
+ return 1;
+ return null;
+}
+function atomic() {
+ var r1, r2, r3, r4;
+ r1 = STACKTOP;
+ STACKTOP += 4;
+ r2 = r1 >> 2;
+ HEAP32[r2] = 10;
+ r3 = (tempValue = HEAP32[r2], HEAP32[r2] == 10 && (HEAP32[r2] = 7), tempValue);
+ r4 = (r3 | 0) == 10 & 1;
+ r3 = HEAP32[r2];
+ r2 = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = r3, HEAP32[tempInt + 4 >> 2] = r4, tempInt));
+ STACKTOP = r1;
+ return 0;
+ return null;
+}
+function fcntl_open() {
+ var r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17;
+ r1 = STACKTOP;
+ STACKTOP += 84;
+ r2 = r1;
+ r3 = r1 + 72;
+ r4 = r3 | 0;
+ for (r5 = STRING_TABLE.__ZZ4mainE16nonexistent_name | 0, r6 = r4, r7 = r5 + 12; r5 < r7; r5++, r6++) {
+ HEAP8[r6] = HEAP8[r5];
+ }
+ r5 = (r2 + 8 | 0) >> 2;
+ r8 = r2 >> 2;
+ r9 = r3 + 9 | 0;
+ r10 = r3 + 10 | 0;
+ r3 = 0;
+ while (1) {
+ r11 = HEAP32[__ZZ4mainE5modes + (r3 << 2) >> 2];
+ r12 = r11 | 512;
+ r13 = r3 + 97 & 255;
+ r14 = 0;
+ while (1) {
+ r15 = (r14 & 1 | 0) == 0 ? r11 : r12;
+ r16 = (r14 & 2 | 0) == 0 ? r15 : r15 | 2048;
+ r15 = (r14 & 4 | 0) == 0 ? r16 : r16 | 1024;
+ r16 = (r14 & 8 | 0) == 0 ? r15 : r15 | 8;
+ r15 = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = r3, HEAP32[tempInt + 4 >> 2] = r14, tempInt));
+ r15 = _open(STRING_TABLE.__str2 | 0, r16, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ r17 = (r15 | 0) != -1 & 1;
+ r15 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r17, tempInt));
+ r17 = ___errno();
+ r15 = HEAP32[r17 >> 2];
+ r17 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ r15 = _stat(STRING_TABLE.__str2 | 0, r2);
+ r15 = HEAP32[r5] & -512;
+ r17 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ for (r6 = r8, r7 = r6 + 18; r6 < r7; r6++) {
+ HEAP32[r6] = 0;
+ }
+ r15 = _putchar(10);
+ r15 = ___errno();
+ HEAP32[r15 >> 2] = 0;
+ r15 = _printf(STRING_TABLE.__str6 | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = r3, HEAP32[tempInt + 4 >> 2] = r14, tempInt));
+ r15 = _open(STRING_TABLE.__str7 | 0, r16, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ r17 = (r15 | 0) != -1 & 1;
+ r15 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r17, tempInt));
+ r17 = ___errno();
+ r15 = HEAP32[r17 >> 2];
+ r17 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ r15 = _stat(STRING_TABLE.__str7 | 0, r2);
+ r15 = HEAP32[r5] & -512;
+ r17 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ for (r6 = r8, r7 = r6 + 18; r6 < r7; r6++) {
+ HEAP32[r6] = 0;
+ }
+ r15 = _putchar(10);
+ r15 = ___errno();
+ HEAP32[r15 >> 2] = 0;
+ HEAP8[r9] = r13;
+ HEAP8[r10] = r14 + 97 & 255;
+ r15 = _printf(STRING_TABLE.__str8 | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = r3, HEAP32[tempInt + 4 >> 2] = r14, tempInt));
+ r15 = _open(r4, r16, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ r17 = (r15 | 0) != -1 & 1;
+ r15 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r17, tempInt));
+ r17 = ___errno();
+ r15 = HEAP32[r17 >> 2];
+ r17 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ r15 = _stat(r4, r2);
+ r15 = HEAP32[r5] & -512;
+ r17 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r15, tempInt));
+ for (r6 = r8, r7 = r6 + 18; r6 < r7; r6++) {
+ HEAP32[r6] = 0;
+ }
+ r16 = _putchar(10);
+ r16 = ___errno();
+ HEAP32[r16 >> 2] = 0;
+ r16 = r14 + 1 | 0;
+ if ((r16 | 0) == 16) {
+ break;
+ }
+ r14 = r16;
+ }
+ r14 = r3 + 1 | 0;
+ if ((r14 | 0) == 3) {
+ break;
+ }
+ r3 = r14;
+ }
+ r3 = _puts(STRING_TABLE._str | 0);
+ r3 = _creat(STRING_TABLE.__str10 | 0, 511);
+ r6 = (r3 | 0) != -1 & 1;
+ r3 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r6, tempInt));
+ r6 = ___errno();
+ r3 = HEAP32[r6 >> 2];
+ r6 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r3, tempInt));
+ STACKTOP = r1;
+ return 0;
+ return null;
+}
+function ex() {
+ var r1, r2;
+ r1 = STACKTOP;
+ STACKTOP += 4;
+ r2 = r1;
+ r1 = _puts(STRING_TABLE._str17 | 0);
+ r1 = r2 | 0;
+ r2 = 0;
+ while (1) {
+ r1 = _printf(STRING_TABLE.__str15 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = r2, tempInt));
+ ((function() {
+ try {
+ __THREW__ = false;
+ return __Z5magici(r2);
+ } catch (e) {
+ if (typeof e != "number") throw e;
+ if (ABORT) throw e;
+ __THREW__ = true;
+ return null;
+ }
+ }))();
+ }
+}
+function switchey(x) {
+ var r1, r2, r3, r4, r5, r6, r7, r8;
+ r1 = 5;
+ while (1) {
+ switch (x = f(x, r1)) {
+ case 1:
+ g(r1);
+ r2 = x + 1;
+ x--;
+ break;
+ case 2:
+ g(r1 * 2);
+ r3 = x + 22;
+ r4 = r3 + 5;
+ x -= 20;
+ break;
+ default:
+ r5 = x + 22;
+ r6 = r3 + 5;
+ ch(r5, r6 * r3);
+ throw 99;
+ }
+ }
+ r7 = x + 1;
+ p(r1, r7);
+ r8 = x + 2;
+ pp(r8);
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["test", "primes", "atomic", "fcntl_open", "ex", "switchey"]
diff --git a/tools/test-js-optimizer-regs.js b/tools/test-js-optimizer-regs.js
new file mode 100644
index 00000000..2aa95b74
--- /dev/null
+++ b/tools/test-js-optimizer-regs.js
@@ -0,0 +1,233 @@
+function test() {
+ var i = 0;
+ f(i);
+ i+=1;
+ var j = i + 2;
+ g(i, j);
+ f(i);
+ var i2 = cheez();
+ var j2 = i2 + 2;
+ g(j2, j2);
+ var k1 = 200;
+ var k2 = 203;
+ var k3 = 205;
+ var k4 = 208;
+ c(k3);
+ while (f()) {
+ var apple = 5;
+ var orange = 12;
+ gg(apple, orange*2);
+ var tangerine = 100;
+ gg(tangerine, 20);
+ }
+ var ck = f(), ck2 = 100, ck3 = 1000, ck4 = 100000;
+ f(ck());
+}
+function primes() {
+ var __label__;
+ var $curri_01 = 2;
+ var $primes_02 = 0;
+ $_$2 : while (1) {
+ var $primes_02;
+ var $curri_01;
+ var $conv1 = $curri_01 | 0;
+ var $call = _sqrtf($conv1);
+ var $j_0 = 2;
+ $_$4 : while (1) {
+ var $j_0;
+ var $conv = $j_0 | 0;
+ var $cmp2 = $conv < $call;
+ if (!$cmp2) {
+ var $ok_0 = 1;
+ break $_$4;
+ }
+ var $rem = ($curri_01 | 0) % ($j_0 | 0);
+ var $cmp3 = ($rem | 0) == 0;
+ if ($cmp3) {
+ var $ok_0 = 0;
+ break $_$4;
+ }
+ var $inc = $j_0 + 1 | 0;
+ var $j_0 = $inc;
+ }
+ var $ok_0;
+ var $inc5_primes_0 = $ok_0 + $primes_02 | 0;
+ var $inc7 = $curri_01 + 1 | 0;
+ var $cmp = ($inc5_primes_0 | 0) < 1e5;
+ if ($cmp) {
+ var $curri_01 = $inc7;
+ var $primes_02 = $inc5_primes_0;
+ } else {
+ break $_$2;
+ }
+ }
+ var $call8 = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $curri_01, tempInt));
+ return 1;
+ return null;
+}
+function atomic() {
+ var $x$s2;
+ var __stackBase__ = STACKTOP;
+ STACKTOP += 4;
+ var $x$s2 = __stackBase__ >> 2;
+ HEAP32[$x$s2] = 10;
+ var $0 = (tempValue = HEAP32[$x$s2], HEAP32[$x$s2] == 10 && (HEAP32[$x$s2] = 7), tempValue);
+ var $conv = ($0 | 0) == 10 & 1;
+ var $2 = HEAP32[$x$s2];
+ var $call = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = $2, HEAP32[tempInt + 4 >> 2] = $conv, tempInt));
+ STACKTOP = __stackBase__;
+ return 0;
+ return null;
+}
+function fcntl_open() {
+ var $1$s2;
+ var $st_mode$s2;
+ var __stackBase__ = STACKTOP;
+ STACKTOP += 84;
+ var $s = __stackBase__;
+ var $nonexistent_name = __stackBase__ + 72;
+ var $0 = $nonexistent_name | 0;
+ for (var $$src = STRING_TABLE.__ZZ4mainE16nonexistent_name | 0, $$dest = $0, $$stop = $$src + 12; $$src < $$stop; $$src++, $$dest++) {
+ HEAP8[$$dest] = HEAP8[$$src];
+ }
+ var $st_mode$s2 = ($s + 8 | 0) >> 2;
+ var $1$s2 = $s >> 2; // critical variable, becomes r8
+ var $arrayidx43 = $nonexistent_name + 9 | 0;
+ var $arrayidx46 = $nonexistent_name + 10 | 0;
+ var $i_04 = 0;
+ while (1) {
+ var $i_04;
+ var $2 = HEAP32[__ZZ4mainE5modes + ($i_04 << 2) >> 2];
+ var $or = $2 | 512;
+ var $conv42 = $i_04 + 97 & 255;
+ var $j_03 = 0;
+ while (1) {
+ var $j_03;
+ var $flags_0 = ($j_03 & 1 | 0) == 0 ? $2 : $or;
+ var $flags_0_or7 = ($j_03 & 2 | 0) == 0 ? $flags_0 : $flags_0 | 2048;
+ var $flags_2 = ($j_03 & 4 | 0) == 0 ? $flags_0_or7 : $flags_0_or7 | 1024;
+ var $flags_2_or17 = ($j_03 & 8 | 0) == 0 ? $flags_2 : $flags_2 | 8;
+ var $call = _printf(STRING_TABLE.__str | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = $i_04, HEAP32[tempInt + 4 >> 2] = $j_03, tempInt));
+ var $call19 = _open(STRING_TABLE.__str2 | 0, $flags_2_or17, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ var $conv = ($call19 | 0) != -1 & 1;
+ var $call21 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $conv, tempInt));
+ var $call22 = ___errno();
+ var $3 = HEAP32[$call22 >> 2];
+ var $call23 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $3, tempInt));
+ var $call24 = _stat(STRING_TABLE.__str2 | 0, $s);
+ var $and25 = HEAP32[$st_mode$s2] & -512;
+ var $call26 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $and25, tempInt));
+ for (var $$dest = $1$s2, $$stop = $$dest + 18; $$dest < $$stop; $$dest++) {
+ HEAP32[$$dest] = 0;
+ }
+ var $putchar = _putchar(10);
+ var $call28 = ___errno();
+ HEAP32[$call28 >> 2] = 0;
+ var $call29 = _printf(STRING_TABLE.__str6 | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = $i_04, HEAP32[tempInt + 4 >> 2] = $j_03, tempInt));
+ var $call30 = _open(STRING_TABLE.__str7 | 0, $flags_2_or17, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ var $conv32 = ($call30 | 0) != -1 & 1;
+ var $call33 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $conv32, tempInt));
+ var $call34 = ___errno();
+ var $5 = HEAP32[$call34 >> 2];
+ var $call35 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $5, tempInt));
+ var $call36 = _stat(STRING_TABLE.__str7 | 0, $s);
+ var $and38 = HEAP32[$st_mode$s2] & -512;
+ var $call39 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $and38, tempInt));
+ for (var $$dest = $1$s2, $$stop = $$dest + 18; $$dest < $$stop; $$dest++) {
+ HEAP32[$$dest] = 0;
+ }
+ var $putchar1 = _putchar(10);
+ var $call41 = ___errno();
+ HEAP32[$call41 >> 2] = 0;
+ HEAP8[$arrayidx43] = $conv42;
+ HEAP8[$arrayidx46] = $j_03 + 97 & 255;
+ var $call47 = _printf(STRING_TABLE.__str8 | 0, (tempInt = STACKTOP, STACKTOP += 8, HEAP32[tempInt >> 2] = $i_04, HEAP32[tempInt + 4 >> 2] = $j_03, tempInt));
+ var $call48 = _open($0, $flags_2_or17, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = 511, tempInt));
+ var $conv50 = ($call48 | 0) != -1 & 1;
+ var $call51 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $conv50, tempInt));
+ var $call52 = ___errno();
+ var $7 = HEAP32[$call52 >> 2];
+ var $call53 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $7, tempInt));
+ var $call55 = _stat($0, $s);
+ var $and57 = HEAP32[$st_mode$s2] & -512;
+ var $call58 = _printf(STRING_TABLE.__str4 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $and57, tempInt));
+ for (var $$dest = $1$s2, $$stop = $$dest + 18; $$dest < $$stop; $$dest++) {
+ HEAP32[$$dest] = 0;
+ }
+ var $putchar2 = _putchar(10);
+ var $call60 = ___errno();
+ HEAP32[$call60 >> 2] = 0;
+ var $inc = $j_03 + 1 | 0;
+ if (($inc | 0) == 16) {
+ break;
+ }
+ var $j_03 = $inc;
+ }
+ var $inc62 = $i_04 + 1 | 0;
+ if (($inc62 | 0) == 3) {
+ break;
+ }
+ var $i_04 = $inc62;
+ }
+ var $puts = _puts(STRING_TABLE._str | 0);
+ var $call65 = _creat(STRING_TABLE.__str10 | 0, 511);
+ var $conv67 = ($call65 | 0) != -1 & 1;
+ var $call68 = _printf(STRING_TABLE.__str1 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $conv67, tempInt));
+ var $call69 = ___errno();
+ var $9 = HEAP32[$call69 >> 2];
+ var $call70 = _printf(STRING_TABLE.__str3 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $9, tempInt));
+ STACKTOP = __stackBase__;
+ return 0;
+ return null;
+}
+function ex() {
+ var __stackBase__ = STACKTOP;
+ STACKTOP += 4;
+ var $e1 = __stackBase__;
+ var $puts = _puts(STRING_TABLE._str17 | 0);
+ var $x41 = $e1 | 0;
+ var $i_04 = 0;
+ while (1) {
+ var $i_04;
+ var $call1 = _printf(STRING_TABLE.__str15 | 0, (tempInt = STACKTOP, STACKTOP += 4, HEAP32[tempInt >> 2] = $i_04, tempInt));
+ ((function() {
+ try {
+ __THREW__ = false;
+ return __Z5magici($i_04);
+ } catch (e) {
+ if (typeof e != "number") throw e;
+ if (ABORT) throw e;
+ __THREW__ = true;
+ return null;
+ }
+ }))();
+ }
+}
+function switchey(x) {
+ var a = 5;
+ while (1) {
+ switch (x = f(x, a)) {
+ case 1:
+ g(a);
+ var b = x+1;
+ x--;
+ break;
+ case 2:
+ g(a*2);
+ var c = x+22;
+ var d = c+5;
+ x -= 20;
+ break;
+ default:
+ var c1 = x+22;
+ var d2 = c+5;
+ ch(c1, d2*c);
+ throw 99;
+ }
+ }
+ var aa = x+1;
+ p(a, aa);
+ var aaa = x+2;
+ pp(aaa);
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["test", "primes", "atomic", "fcntl_open", "ex", "switchey"]
diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js
index 18c9ac75..e9d973dd 100644
--- a/tools/test-js-optimizer.js
+++ b/tools/test-js-optimizer.js
@@ -422,4 +422,8 @@ function notComps() {
shoo();
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"]
+function tricky() {
+ // The &-1 is a rounding correction, and must not be removed
+ var $conv642 = ($conv6374 - (($132 << 16 >> 16 | 0) / 2 & -1) | 0) & 65535;
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps", "tricky"]