summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS6
-rwxr-xr-xem-config24
-rwxr-xr-xemcc368
-rwxr-xr-xemld60
-rwxr-xr-xemscripten.py17
-rw-r--r--settings.py8
-rw-r--r--src/analyzer.js128
-rw-r--r--src/compiler.js4
-rw-r--r--src/experimental/stringCache.diff147
-rw-r--r--src/intertyper.js14
-rw-r--r--src/jsifier.js52
-rw-r--r--src/library.js316
-rw-r--r--src/library_browser.js343
-rw-r--r--src/library_egl.js6
-rw-r--r--src/library_gc.js167
-rw-r--r--src/library_gl.js1939
-rw-r--r--src/library_glut.js26
-rw-r--r--src/library_sdl.js745
-rw-r--r--src/modules.js5
-rw-r--r--src/parseTools.js72
-rw-r--r--src/postamble.js49
-rw-r--r--src/preamble.js76
-rw-r--r--src/runtime.js71
-rw-r--r--src/settings.js19
-rw-r--r--src/shell.html57
-rw-r--r--src/shell.js18
-rw-r--r--src/utility.js4
-rw-r--r--system/include/emscripten.h54
-rw-r--r--system/include/emscripten/emscripten.h133
-rw-r--r--system/include/features.h3
-rw-r--r--system/include/gc.h50
-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.h8
-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/sys/ioctl.h15
-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/Makefile1
-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.html6
-rw-r--r--tests/cases/complexphi.ll4
-rw-r--r--tests/cases/dash.ll18
-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/subnums.ll18
-rw-r--r--tests/cases/subnums.txt1
-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.cpp68
-rw-r--r--tests/emscripten_fs_api_browser.cpp69
-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/gl_matrix_identity.c129
-rw-r--r--tests/gl_ps.c230
-rw-r--r--tests/gl_ps.pngbin0 -> 203535 bytes
-rw-r--r--tests/glshaderinfo.cpp52
-rw-r--r--tests/hello_world_gles.c63
-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
-rwxr-xr-xtests/runner.py1082
-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.c16
-rw-r--r--tests/sdl_audio_quickload.c44
-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.c26
-rw-r--r--tests/sdl_key.c18
-rw-r--r--tests/sdl_maprgba.c33
-rw-r--r--tests/sdl_maprgba.pngbin0 -> 1875 bytes
-rw-r--r--tests/sdl_mouse.c23
-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/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.py65
-rwxr-xr-xtools/bindings_generator.py29
-rw-r--r--tools/bisect_pair.py18
-rw-r--r--tools/clean_webconsole.py23
-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.coffee65
-rw-r--r--tools/file_packager.py399
-rw-r--r--tools/ie7_fix.py14
-rw-r--r--tools/js-optimizer.js189
-rw-r--r--tools/scons/site_scons/site_tools/emscripten/emscripten.py2
-rw-r--r--tools/shared.py282
-rw-r--r--tools/test-js-optimizer-regs-output.js228
-rw-r--r--tools/test-js-optimizer-regs.js233
188 files changed, 25753 insertions, 1451 deletions
diff --git a/AUTHORS b/AUTHORS
index 6148afb6..866bc0c3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -20,4 +20,10 @@ under the licensing terms detailed in LICENSE.
* 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-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/emcc b/emcc
index fb215a60..7cc59c53 100755
--- a/emcc
+++ b/emcc
@@ -77,15 +77,7 @@ emcc can be influenced by a few environment variables:
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.
'''
@@ -220,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,
@@ -269,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:
@@ -290,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)
@@ -322,31 +334,17 @@ 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')
-AUDIO_SUFFIXES = ('.ogg', '.wav', '.mp3')
-AUDIO_MIMETYPES = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' }
-
-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 unsuffixed_uniquename(name):
- ret = unsuffixed_basename(name)
+def uniquename(name):
if name not in seen_names:
seen_names[name] = str(len(seen_names))
- return ret + '_' + seen_names[name]
+ return unsuffixed(name) + '_' + seen_names[name] + (('.' + suffix(name)) if suffix(name) else '')
# ---------------- End configs -------------
@@ -401,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
@@ -430,13 +413,16 @@ try:
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)'
@@ -471,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'):
@@ -486,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'):
@@ -509,11 +495,23 @@ try:
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]
@@ -528,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])
@@ -583,6 +583,8 @@ try:
libs.append(arg[2:])
newargs[i] = ''
+ original_input_files = input_files[:]
+
newargs = [ arg for arg in newargs if arg is not '' ]
# Find library files
@@ -648,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_uniquename(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)
@@ -659,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_uniquename(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
@@ -672,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_uniquename(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)
@@ -684,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_uniquename(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_uniquename(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
@@ -713,9 +713,9 @@ try:
# dlmalloc
def create_dlmalloc():
if DEBUG: print >> sys.stderr, 'emcc: building dlmalloc for cache'
- execute(['python', 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(['python', 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():
@@ -741,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)
@@ -753,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)
@@ -787,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:
@@ -837,215 +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 = ''
-
- if final_suffix == 'html':
- 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 += 'var preloadedImages = {}; // maps url to image data\n'
- code += 'var 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_['net_name'] = file_['name']
-
- data_target = unsuffixed(target) + '.data'
-
- # Set up folders
- partial_dirs = []
- for file_ in data_files:
- dirname = os.path.dirname(file_['name'])
- if dirname != '' and dirname != os.path.sep:
- parts = dirname.split(os.path.sep)
- for i in range(len(parts)):
- partial = os.path.sep.join(parts[:i+1])
- if partial not in partial_dirs:
- code += '''FS.createFolder('/%s', '%s', true, false);\n''' % (os.path.sep.join(parts[:i]), parts[i])
- partial_dirs.append(partial)
-
- if final_suffix == 'html':
- # 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_['name']).read()
- file_['data_end'] = start + len(curr)
- 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 += '''FS.createDataFile('/', '%s', %s, true, true);\n''' % (os.path.basename(filename), str(map(ord, open(filename, 'rb').read())))
- elif file_['mode'] == 'preload':
- # Preload
- assert final_suffix == 'html', 'Can only preload files when generating HTML'
-
- varname = 'filePreload%d' % counter
- counter += 1
- image = filename.endswith(IMAGE_SUFFIXES)
- audio = filename.endswith(AUDIO_SUFFIXES)
-
- 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);
- preloadedImages['%(filename)s'] = canvas;
- URLObject.revokeObjectURL(url);
- 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['oncanplaythrough'] = function() { // XXX string for closure
- audio['oncanplaythrough'] = null;
- preloadedAudios['%(filename)s'] = audio;
- removeRunDependency();
- };
- audio.onerror = function(event) {
- console.log('Audio %(filename)s could not be decoded');
- };
- audio.src = url;
- } else {
- preloadedAudios['%(filename)s'] = new Audio(); // empty shim
- removeRunDependency();
- }
-''' % { 'filename': filename, 'mimetype': AUDIO_MIMETYPES[suffix(filename)] }
- else:
- finish = 'removeRunDependency();\n'
-
- code += '''
- var %(varname)s = new %(request)s();
- %(varname)s.open('GET', '%(netname)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;
- FS.createDataFile('/%(dirname)s', '%(basename)s', byteArray, true, true);
- %(finish)s
- };
- addRunDependency();
- %(varname)s.send(null);
-''' % {
- 'request': 'DataRequest', # In the past we also supported XHRs here
- 'varname': varname,
- 'filename': filename,
- 'netname': file_['net_name'],
- 'dirname': os.path.dirname(filename),
- 'basename': os.path.basename(filename),
- 'finish': finish
- }
- else:
- assert 0
-
- if final_suffix == 'html':
- # 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 += ' 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
- };
- addRunDependency();
- dataFile.send(null);
- if (Module['setStatus']) Module['setStatus']('Downloading...');
- ''' % (Compression.compressed_name(data_target) if Compression.on else data_target, use_data)
-
+ 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:
+ 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)
@@ -1056,7 +869,7 @@ 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
@@ -1095,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()
@@ -1116,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']
diff --git a/emld b/emld
deleted file mode 100755
index 695be784..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, subprocess, 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)
-subprocess.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 29ae47dd..89da32d5 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -114,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));
@@ -122,6 +123,7 @@ if (settings_file) {
}
}
+
if (CORRECT_SIGNS >= 2) {
CORRECT_SIGNS_LINES = set(CORRECT_SIGNS_LINES); // for fast checking
}
@@ -144,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/intertyper.js b/src/intertyper.js
index 0f9ce659..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,
@@ -350,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';
@@ -790,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 904517e1..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({
@@ -283,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);
}
@@ -408,8 +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('{', '{ var ret = (function() {Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments) + "]"); ');
- snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); Module.printErr(" [ return:" + ret); return ret; }';
+ 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; }';
}
}
@@ -432,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 + ';';
@@ -450,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;
}
@@ -555,9 +558,6 @@ function JSify(data, functionsOnly, givenFunctions) {
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) {
@@ -748,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) {
@@ -762,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:
@@ -789,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('|');
@@ -1030,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
@@ -1052,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);
diff --git a/src/library.js b/src/library.js
index 5b85c56f..bb73c48a 100644
--- a/src/library.js
+++ b/src/library.js
@@ -28,7 +28,14 @@ LibraryManager.library = {
$FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'],
$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() } });',
+ '__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: '/',
@@ -90,18 +97,18 @@ LibraryManager.library = {
#if FS_LOG
var inputPath = path;
function log() {
- 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 + '}');
+ 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);
@@ -177,11 +184,11 @@ LibraryManager.library = {
// Creates a file system record: file, link, device or folder.
createObject: function(parent, name, properties, canRead, canWrite) {
#if FS_LOG
- print('FS.createObject("' + parent + '", ' +
- '"' + name + '", ' +
- JSON.stringify(properties) + ', ' +
- canRead + ', ' +
- canWrite + ')');
+ Module['print']('FS.createObject("' + parent + '", ' +
+ '"' + name + '", ' +
+ JSON.stringify(properties) + ', ' +
+ canRead + ', ' +
+ canWrite + ')');
#endif
if (!parent) parent = '/';
if (typeof parent === 'string') parent = FS.findObject(parent);
@@ -257,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};
@@ -340,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();
@@ -371,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);
@@ -1476,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.
@@ -1867,7 +1886,7 @@ LibraryManager.library = {
#if CATCH_EXIT_CODE
throw new ExitStatus();
-#else
+#else
throw 'exit(' + status + ') called, at ' + new Error().stack;
#endif
},
@@ -2217,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);
@@ -2242,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);
@@ -2249,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();
@@ -2264,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++;
@@ -2288,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();
@@ -2302,6 +2342,7 @@ LibraryManager.library = {
} else {
break;
}
+ first = false;
}
}
if (buffer.length === 0) return 0; // Failure.
@@ -2309,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') }}}
@@ -2330,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) {
@@ -2666,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));
}
}
@@ -2808,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',
@@ -3413,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++;
@@ -3429,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)) {
@@ -3480,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) {
@@ -3956,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) {
@@ -4149,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;
@@ -4280,19 +4382,13 @@ LibraryManager.library = {
isdigit: function(chr) {
return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0);
},
- isdigit_l__deps: ['isdigit'],
- isdigit_l: function(chr, loc) {
- return _isdigit(chr);
- },
+ 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__deps: ['isxdigit'],
- isxdigit_l: function(chr, loc) {
- return _isxdigit(chr);
- },
+ 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)) ||
@@ -4422,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 = [];
@@ -4436,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 ) {
@@ -4615,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'
@@ -4682,6 +4793,42 @@ 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;
@@ -4700,6 +4847,24 @@ LibraryManager.library = {
};
},
+ 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
+ };
+ },
+
llvm_stacksave: function() {
var self = _llvm_stacksave;
if (!self.LLVM_SAVEDSTACKS) {
@@ -4739,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
// ==========================================================================
@@ -4963,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',
@@ -5367,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);
@@ -5374,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);
@@ -6080,6 +6252,10 @@ LibraryManager.library = {
return eval(Pointer_stringify(ptr));
},
+ emscripten_random: function() {
+ return Math.random();
+ },
+
$Profiling: {
max_: 0,
times: null,
diff --git a/src/library_browser.js b/src/library_browser.js
index 17dff2eb..075bd8bf 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -3,24 +3,30 @@
// Utilities for browser environments
mergeInto(LibraryManager.library, {
- emscripten_set_main_loop: function(func, fps) {
- fps = fps || 60; // TODO: use requestAnimationFrame
- _emscripten_set_main_loop.cancel = false;
- var jsFunc = FUNCTION_TABLE[func];
- function doOne() {
- if (_emscripten_set_main_loop.cancel) return;
- jsFunc();
- setTimeout(doOne, 1000/fps); // doing this each time means that on exception, we stop
- }
- setTimeout(doOne, 1000/fps);
- },
-
- emscripten_cancel_main_loop: function(func) {
- _emscripten_set_main_loop.cancel = true;
- },
-
+ $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: {
- createContext: function(canvas, useWebGL) {
+ mainLoop: {
+ scheduler: null,
+ shouldPause: false,
+ paused: false,
+ pause: function() {
+ Browser.mainLoop.shouldPause = true;
+ },
+ resume: function() {
+ if (Browser.mainLoop.paused) {
+ Browser.mainLoop.paused = false;
+ Browser.mainLoop.scheduler();
+ }
+ 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)');
@@ -39,50 +45,19 @@ mergeInto(LibraryManager.library, {
// Useful to debug native webgl apps: var Module = { printErr: function(x) { console.log(x) } };
var tempCtx = ctx;
var wrapper = {};
- wrapper.objectMap = new WeakMap();
- wrapper.objectCounter = 1;
for (var prop in tempCtx) {
(function(prop) {
switch (typeof tempCtx[prop]) {
case 'function': {
wrapper[prop] = function() {
- var printArgs = Array.prototype.slice.call(arguments).map(function(arg) {
- if (wrapper.objectMap[arg]) return '<' + arg + '|' + wrapper.objectMap[arg] + '>';
- if (arg.toString() == '[object HTMLImageElement]') {
- return arg + '\n\n';
- }
- if (arg.byteLength) {
- var buf = new ArrayBuffer(32);
- var i8buf = new Int8Array(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;
- 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;
- }
- return arg;
- });
- Module.printErr('[gl_f:' + prop + ':' + printArgs + ']');
+ 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);
- var printRet = ret;
- if (typeof ret == 'object') {
- wrapper.objectMap[ret] = wrapper.objectCounter++;
- printRet = '<' + ret + '|' + wrapper.objectMap[ret] + '>';
+ if (GL.debug && typeof ret != 'undefined') {
+ Module.printErr('[ gl:' + prop + ':return:' + Runtime.prettyPrint(ret) + ']');
}
- Module.printErr('[ gl:' + prop + ':return:' + printRet + ']');
return ret;
}
break;
@@ -93,7 +68,9 @@ mergeInto(LibraryManager.library, {
return tempCtx[prop];
});
wrapper.__defineSetter__(prop, function(value) {
- Module.printErr('[gl_s:' + prop + ':' + value + ']');
+ if (GL.debug) {
+ Module.printErr('[gl_s:' + prop + ':' + value + ']');
+ }
tempCtx[prop] = value;
});
break;
@@ -105,50 +82,232 @@ mergeInto(LibraryManager.library, {
#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;
},
- // 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.
- // This is deprecated, it is preferred to load binary files, createObjectURL, etc.,
- // see the sdl_* tests.
- /*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];
- }
+ 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();
}
- if (leftbits == 2) {
- ret += BASE[(leftchar&3) << 4];
- ret += PAD + PAD;
- } else if (leftbits == 4) {
- ret += BASE[(leftchar&0xf) << 2];
- ret += PAD;
+ }
+
+ 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;
+ };
+ 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);
}
- 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;
- },*/
+ });
+ },
+
+ 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.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(func) {
+ Browser.mainLoop.scheduler = null;
+ Browser.mainLoop.shouldPause = true;
+ },
+
+ emscripten_pause_main_loop: function(func) {
+ Browser.mainLoop.pause();
+ },
+
+ emscripten_resume_main_loop: function(func) {
+ Browser.mainLoop.resume();
+ },
+
+ 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
index f1558f80..635e00a7 100644
--- a/src/library_egl.js
+++ b/src/library_egl.js
@@ -12,6 +12,12 @@ var LibraryEGL = {
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() {},
};
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 3c33ec2c..f3cea384 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -4,17 +4,27 @@
*/
var LibraryGL = {
+ $GL__postset: 'GL.init()',
$GL: {
+#if GL_DEBUG
+ debug: true,
+#endif
+
counter: 1,
buffers: {},
programs: {},
framebuffers: {},
- renderbuffer: {},
+ renderbuffers: {},
textures: {},
uniforms: {},
shaders: {},
- matrix: {},
+ 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) {
@@ -51,9 +61,135 @@ var LibraryGL = {
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
+ }
+ }
+ 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
+ }
+ },
+
+ 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 0x1F00 /* GL_VENDOR */:
@@ -62,12 +198,22 @@ var LibraryGL = {
return allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL);
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) {
+ 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":
@@ -205,104 +351,53 @@ var LibraryGL = {
}
},
- glCompressedTexImage2D: function(target, level, internalformat, width, height, border, imageSize, data) {
+ 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);
+ 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);
+ Module.ctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, data);
},
- glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) {
+ glTexImage2D: function(target, level, internalFormat, width, height, border, format, type, pixels) {
if (pixels) {
- 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 + ') passed to glTexImage2D';
- }
- pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+width*height*sizePerPixel') }}};
- 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;
- pixels = {{{ makeHEAPView('U16', 'pixels', 'pixels+width*height*sizePerPixel') }}};
- break;
- default:
- throw 'Invalid type (' + type + ') passed to glTexImage2D';
- }
+ 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) {
- 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 + ') passed to glTexSubImage2D';
- }
- pixels = {{{ makeHEAPView('U8', 'pixels', 'pixels+width*height*sizePerPixel') }}};
- 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;
- pixels = {{{ makeHEAPView('U16', 'pixels', 'pixels+width*height*sizePerPixel') }}};
- break;
- default:
- throw 'Invalid type (' + type + ') passed to glTexSubImage2D';
- }
+ 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.textures[texture]);
+ Module.ctx.bindTexture(target, texture ? GL.textures[texture] : null);
},
glGetTexParameterfv: function(target, pname, params) {
@@ -316,7 +411,7 @@ var LibraryGL = {
glIsTexture: function(texture) {
var fb = GL.textures[texture];
if (typeof(fb) == 'undefined') {
- return false;
+ return 0;
}
return Module.ctx.isTexture(fb);
},
@@ -337,6 +432,10 @@ var LibraryGL = {
}
},
+ glGetBufferParameteriv: function(target, value, data) {
+ {{{ makeSetValue('data', '0', 'Module.ctx.getBufferParameter(target, value)', 'i32') }}};
+ },
+
glBufferData: function(target, size, data, usage) {
Module.ctx.bufferData(target, HEAPU8.subarray(data, data+size), usage);
},
@@ -349,7 +448,7 @@ var LibraryGL = {
glIsBuffer: function(buffer) {
var fb = GL.buffers[buffer];
if (typeof(fb) == 'undefined') {
- return false;
+ return 0;
}
return Module.ctx.isBuffer(fb);
},
@@ -371,7 +470,7 @@ var LibraryGL = {
},
glBindRenderbuffer: function(target, renderbuffer) {
- Module.ctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]);
+ Module.ctx.bindRenderbuffer(target, renderbuffer ? GL.renderbuffers[renderbuffer] : null);
},
glGetRenderbufferParameteriv: function(target, pname, params) {
@@ -381,11 +480,33 @@ var LibraryGL = {
glIsRenderbuffer: function(renderbuffer) {
var fb = GL.renderbuffers[renderbuffer];
if (typeof(fb) == 'undefined') {
- return false;
+ 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') }}};
+ }
+ }
+ },
+
glGetUniformLocation: function(program, name) {
name = Pointer_stringify(name);
var loc = Module.ctx.getUniformLocation(GL.programs[program], name);
@@ -395,11 +516,37 @@ var LibraryGL = {
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);
+ var infoname = info.name.slice(0, bufSize - 1);
writeStringToMemory(infoname, name);
if (length) {
@@ -529,7 +676,7 @@ var LibraryGL = {
},
glBindBuffer: function(target, buffer) {
- Module.ctx.bindBuffer(target, GL.buffers[buffer]);
+ Module.ctx.bindBuffer(target, buffer ? GL.buffers[buffer] : null);
},
glVertexAttrib1fv: function(index, v) {
@@ -562,7 +709,7 @@ var LibraryGL = {
program = GL.programs[program];
var info = Module.ctx.getActiveAttrib(program, index);
- var infoname = info.name.slice(0, bufsize - 1);
+ var infoname = info.name.slice(0, bufSize - 1);
writeStringToMemory(infoname, name);
if (length) {
@@ -605,42 +752,13 @@ var LibraryGL = {
},
glShaderSource: 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
- }
- }
+ var source = GL.getSource(shader, count, string, length);
Module.ctx.shaderSource(GL.shaders[shader], source);
},
- glGetShaderSource: function(shader, bufsize, length, source) {
+ glGetShaderSource: function(shader, bufSize, length, source) {
var result = Module.ctx.getShaderSource(GL.shaders[shader]);
- result.slice(0, bufsize - 1);
+ result.slice(0, bufSize - 1);
writeStringToMemory(result, source);
if (length) {
{{{ makeSetValue('length', '0', 'result.length', 'i32') }}};
@@ -665,17 +783,25 @@ var LibraryGL = {
},
glGetShaderiv : function(shader, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.shaders[shader], pname)', 'i32') }}};
+ 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 : function(program, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.programs[program], pname)', 'i32') }}};
+ 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 false;
+ return 0;
}
return Module.ctx.isShader(fb);
},
@@ -721,7 +847,7 @@ var LibraryGL = {
},
glUseProgram: function(program) {
- Module.ctx.useProgram(GL.programs[program]);
+ Module.ctx.useProgram(program ? GL.programs[program] : null);
},
glValidateProgram: function(program) {
@@ -731,7 +857,7 @@ var LibraryGL = {
glIsProgram: function(program) {
var fb = GL.programs[program];
if (typeof(fb) == 'undefined') {
- return false;
+ return 0;
}
return Module.ctx.isProgram(fb);
},
@@ -742,7 +868,7 @@ var LibraryGL = {
},
glBindFramebuffer: function(target, framebuffer) {
- Module.ctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
+ Module.ctx.bindFramebuffer(target, framebuffer ? GL.framebuffers[framebuffer] : null);
},
glGenFramebuffers: function(n, ids) {
@@ -779,57 +905,452 @@ var LibraryGL = {
glIsFramebuffer: function(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__deps: ['glCreateShader', 'glShaderSource', 'glCompileShader', 'glCreateProgram', 'glDeleteShader', 'glDeleteProgram', 'glAttachShader', 'glActiveTexture', 'glGetShaderiv', 'glGetProgramiv', 'glLinkProgram'],
+ $GLEmulation__postset: 'GLEmulation.init();',
$GLEmulation: {
- procReplacements: {
- 'glCreateShaderObjectARB': 'glCreateShader',
- 'glShaderSourceARB': 'glShaderSource',
- 'glCompileShaderARB': 'glCompileShader',
- 'glCreateProgramObjectARB': 'glCreateProgram',
- 'glAttachObjectARB': 'glAttachShader',
- 'glLinkProgramARB': 'glLinkProgram',
- 'glActiveTextureARB': 'glActiveTexture'
- },
+ // 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_);
+ };
- procs: {
- glDeleteObjectARB: function(id) {
- if (GL.programs[id]) {
- _glDeleteProgram(id);
- } else if (GL.shaders[id]) {
- _glDeleteShader(id);
- } else {
- console.log('WARNING: deleteObjectARB received invalid id: ' + id);
+ // 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);
+ }
- glGetObjectParameterivARB: function(id, type, result) {
- if (GL.programs[id]) {
- _glGetProgramiv(id, type, result);
- } else if (GL.shaders[id]) {
- _glGetShaderiv(id, type, result);
+ 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 {
- console.log('WARNING: getObjectParameterivARB received invalid id: ' + id);
+ glGetFloatv(pname, params);
+ }
+ };
+
+ var glHint = _glHint;
+ _glHint = function(target, mode) {
+ if (target == 0x84EF) { // GL_TEXTURE_COMPRESSION_HINT
+ return;
}
- },
+ glHint(target, mode);
+ };
},
- getProcAddress: function(name_) {
- name_ = GLEmulation.procReplacements[name_] || name_;
- var func = GLEmulation.procs[name_];
- if (!func) {
- try {
- func = eval('_' + name_);
- } catch(e) {
- console.log('WARNING: getProcAddress failed for ' + name_);
+ 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() {
- console.log('WARNING: empty replacement for ' + name_ + ' called, no-op');
+ Module.printErr('WARNING: empty replacement for ' + name + ' called, no-op');
return 0;
};
}
@@ -838,32 +1359,1122 @@ var LibraryGL = {
}
},
- glBegin__deps: ['$GL', function() { return 'GL.matrix.lib = ' + read('gl-matrix.js') }],
- glBegin: function() {
- Module.print('TODO');
+ // 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
+ },
+
+ 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;
+ },
+
+ // 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;
+ }
+ 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);
+ },
+
+ // 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;
+ },
+
+ // 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;
+ };
+ },
+
+ // 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;
+ },
+
+ 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',
+
+ glVertex3fv__deps: ['glVertex3f'],
+ glVertex3fv: function(p) {
+ _glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}});
+ },
+
+ 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:
+ _glFogf(pname, {{{ makeGetValue('param', '0', 'i32') }}}); break;
+ }
+ },
+ glFogx: 'glFogi',
+ glFogxv: 'glFogiv',
+
+ glPolygonMode: function(){}, // TODO
+
+ glAlphaFunc: function(){}, // TODO
+
+ glNormal3f: function(){}, // TODO
+
+ // 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;
+ }
+ 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);
+ },
+
+ 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);
+ },
+ 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);
+ },
+
+ glClientActiveTexture: function(texture) {
+ GL.immediate.clientActiveTexture = texture - 0x84C0; // GL_TEXTURE0
+ },
+
+ // 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";
+ }
+ },
+
+ glPushMatrix: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrixStack[GL.immediate.currentMatrix].push(
+ Array.prototype.slice.call(GL.immediate.matrix[GL.immediate.currentMatrix]));
+ },
+
+ glPopMatrix: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix[GL.immediate.currentMatrix] = GL.immediate.matrixStack[GL.immediate.currentMatrix].pop();
+ },
+
+ glLoadIdentity__deps: ['$GL', '$GLImmediateSetup'],
+ glLoadIdentity: function() {
+ GL.immediate.matricesModified = true;
+ GL.immediate.matrix.lib.mat4.identity(GL.immediate.matrix[GL.immediate.currentMatrix]);
+ },
+
+ 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',
+
+ 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
-[[0, 'shadeModel fogi fogfv getError finish flush'],
- [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus generateMipmap activeTexture blendEquation'],
- [2, 'pixelStorei blendFunc blendEquationSeparate'],
- [3, 'texParameteri texParameterf drawArrays vertexAttrib2f'],
- [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage blendFuncSeparate'],
+// 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 stub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })';
- names.split(' ').forEach(function(name_) {
- var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1);
+ 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_));
+ 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);
diff --git a/src/library_glut.js b/src/library_glut.js
index 0de0ce6a..d33f8436 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -226,13 +226,13 @@ var LibraryGLUT = {
onFullScreenEventChange: function(event){
var width;
var height;
- if (document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen) {
+ if (document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
width = screen["width"];
height = screen["height"];
} else {
width = GLUT.windowWidth;
height = GLUT.windowHeight;
- // TODO set position
+ // TODO set position
document.removeEventListener('fullscreenchange', GLUT.onFullScreenEventChange, true);
document.removeEventListener('mozfullscreenchange', GLUT.onFullScreenEventChange, true);
document.removeEventListener('webkitfullscreenchange', GLUT.onFullScreenEventChange, true);
@@ -241,6 +241,7 @@ var LibraryGLUT = {
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();
@@ -262,16 +263,7 @@ var LibraryGLUT = {
document['webkitCancelFullScreen'] ||
(function() {});
CFS.apply(document, []);
- },
-
- requestAnimationFrame: function(func) {
- var RAF = window['requestAnimationFrame'] ||
- window['mozRequestAnimationFrame'] ||
- window['webkitRequestAnimationFrame'] ||
- window['msRequestAnimationFrame'] ||
- window['setTimeout'];
- RAF.apply(window, [func]);
- },
+ }
},
glutGetModifiers: function() { return GLUT.modifiers; },
@@ -286,6 +278,10 @@ var LibraryGLUT = {
Module['canvas'].height = GLUT.initWindowHeight = height;
},
+ glutInitWindowPosition: function(x, y) {
+ // Ignore for now
+ },
+
glutGet: function(type) {
switch (type) {
case 100: /* GLUT_WINDOW_X */
@@ -367,16 +363,18 @@ var LibraryGLUT = {
glutCreateWindow__deps: ['$Browser'],
glutCreateWindow: function(name) {
- Module.ctx = Browser.createContext(Module['canvas'], true);
+ 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();
@@ -406,7 +404,7 @@ var LibraryGLUT = {
glutPostRedisplay: function() {
if (GLUT.displayFunc) {
- GLUT.requestAnimationFrame(FUNCTION_TABLE[GLUT.displayFunc]);
+ Browser.requestAnimationFrame(FUNCTION_TABLE[GLUT.displayFunc]);
}
},
diff --git a/src/library_sdl.js b/src/library_sdl.js
index b607bdb3..73848502 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1,81 +1,9 @@
//"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, {
+var LibrarySDL = {
$SDL__deps: ['$FS', '$Browser'],
$SDL: {
defaults: {
@@ -88,27 +16,76 @@ mergeInto(LibraryManager.library, {
surfaces: {},
events: [],
- audios: [null],
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
+ 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
+
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
+ scanCodes: { // SDL keycode ==> SDL scancode. See SDL_scancode.h
97: 4, // A
98: 5,
99: 6,
@@ -135,25 +112,26 @@ mergeInto(LibraryManager.library, {
120: 27,
121: 28,
122: 29, // Z
- 48: 30, // 0
- 49: 31,
- 50: 32,
- 51: 33,
- 52: 34,
- 53: 35,
- 54: 36,
- 55: 37,
- 56: 38,
- 57: 39, // 9
+ 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
- 47: 56, // slash
- 1106: 82, // up arrow
- 1105: 81, // down arrow
- 1104: 80, // left arrow
- 1103: 79 // right arrow
+ 305: 224, // ctrl
+ 308: 226, // alt
},
structs: {
@@ -249,31 +227,39 @@ mergeInto(LibraryManager.library, {
return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')';
},
- makeSurface: function(width, height, flags, usePageCanvas, source) {
+ 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); // 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', 'i32') }}} // 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
@@ -285,10 +271,7 @@ mergeInto(LibraryManager.library, {
} else {
canvas = Module['canvas'];
}
- var ctx = Browser.createContext(canvas, useWebGL);
- if (usePageCanvas) {
- Module.ctx = ctx;
- }
+ var ctx = Browser.createContext(canvas, useWebGL, usePageCanvas);
SDL.surfaces[surf] = {
width: width,
height: height,
@@ -301,11 +284,54 @@ mergeInto(LibraryManager.library, {
flags: flags,
locked: 0,
usePageCanvas: usePageCanvas,
- source: source
+ source: source,
+
+ isFlagSet: function (flag) {
+ return flags & flag;
+ }
};
+
return surf;
},
+ // 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;
+ }
+
+ 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];
+ }
+ }
+ },
+
freeSurface: function(surf) {
_free(SDL.surfaces[surf].buffer);
_free(SDL.surfaces[surf].pixelFormat);
@@ -315,73 +341,143 @@ mergeInto(LibraryManager.library, {
receiveEvent: function(event) {
switch(event.type) {
- case 'keydown': case 'keyup': case 'mousedown': case 'mouseup': case 'mousemove':
+ 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': {
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;
+ }
+ var scan;
+ if (key >= 1024) {
+ scan = key - 1024;
+ } else {
+ scan = SDL.scanCodes[key] || key;
}
- var scan = SDL.scanCodes[key] || key;
- {{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'down ? 0x300 : 0x301', 'i32') }}}
+ {{{ 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', 'scan', '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': case 'mousemove': {
- var x = event.pageX - Module['canvas'].offsetLeft;
- var y = event.pageY - Module['canvas'].offsetTop;
+ 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', 'down ? 0x401 : 0x402', 'i32') }}};
+ {{{ 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', '0x400', 'i32') }}};
- {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.button', 'event.button', 'i8') }}};
- {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.state', 'down ? 1 : 0', 'i8') }}};
+ {{{ 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', 'x - SDL.mouseX', 'i32') }}};
- {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'y - SDL.mouseY', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.xrel', 'movementX', 'i32') }}};
+ {{{ makeSetValue('ptr', 'SDL.structs.MouseMotionEvent.yrel', 'movementY', 'i32') }}};
}
SDL.mouseX = x;
SDL.mouseY = y;
break;
}
- default:
- throw 'Unhandled SDL event: ' + event.type;
+ default: throw 'Unhandled SDL event: ' + event.type;
}
},
@@ -397,6 +493,30 @@ mergeInto(LibraryManager.library, {
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) {
@@ -420,7 +540,6 @@ mergeInto(LibraryManager.library, {
return SDL.version;
},
- SDL_Init__deps: ['$SDL'],
SDL_Init: function(what) {
SDL.startTime = Date.now();
['keydown', 'keyup'].forEach(function(event) {
@@ -428,6 +547,12 @@ mergeInto(LibraryManager.library, {
});
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
},
@@ -454,8 +579,39 @@ mergeInto(LibraryManager.library, {
return -1; // -1 == all modes are ok. 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'].forEach(function(event) {
+ ['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mouseout'].forEach(function(event) {
Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
});
Module['canvas'].width = width;
@@ -463,6 +619,14 @@ mergeInto(LibraryManager.library, {
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();
@@ -475,7 +639,7 @@ mergeInto(LibraryManager.library, {
var surfData = SDL.surfaces[surf];
surfData.locked++;
- if (surfData.locked > 1) return;
+ if (surfData.locked > 1) return 0;
if (!surfData.image) {
surfData.image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
@@ -489,17 +653,44 @@ mergeInto(LibraryManager.library, {
}
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;
- // TODO: use typed array Set()
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
@@ -510,8 +701,10 @@ mergeInto(LibraryManager.library, {
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
@@ -533,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
@@ -547,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];
@@ -571,6 +764,10 @@ mergeInto(LibraryManager.library, {
// 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) {
throw 'SDL_Delay called! Potential infinite loop, quitting. ' + new Error().stack;
},
@@ -588,12 +785,33 @@ mergeInto(LibraryManager.library, {
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
},
@@ -603,7 +821,7 @@ mergeInto(LibraryManager.library, {
},
SDL_CreateRGBSurface: function(flags, width, height, depth, rmask, gmask, bmask, amask) {
- return SDL.makeSurface(width, height, flags, false, 'CreateRGBSurface');
+ return SDL.makeSurface(width, height, flags, false, 'CreateRGBSurface', rmask, gmask, bmask, amask);
},
SDL_DisplayFormatAlpha: function(surf) {
@@ -634,13 +852,28 @@ mergeInto(LibraryManager.library, {
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];
assert(!surfData.locked); // but we could unlock and re-lock if we must..
- var r = SDL.loadRect(rect);
+
+ 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);
@@ -670,42 +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 = FS.standardizePath(Pointer_stringify(filename));
- var raw = preloadedImages[filename];
- assert(raw, 'Cannot find preloaded image ' + 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');
@@ -774,24 +1067,52 @@ mergeInto(LibraryManager.library, {
SDL_CondWait: function() {},
SDL_DestroyCond: function() {},
+ SDL_StartTextInput: function() {}, // TODO
+ SDL_StopTextInput: function() {}, // TODO
+
// SDL Mixer
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_HookMusicFinished: function(func) {
- SDL.hookMusicFinished = func;
+ 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_VolumeMusic: function(func) {
- return 0; // TODO
+ Mix_SetPanning: function() {
+ return 0; // error
},
Mix_LoadWAV_RW: function(filename, freesrc) {
filename = FS.standardizePath(Pointer_stringify(filename));
- var raw = preloadedAudios[filename];
- assert(raw, 'Cannot find preloaded audio ' + 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,
@@ -800,50 +1121,129 @@ mergeInto(LibraryManager.library, {
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].audio.pause();
SDL.audios[id] = null;
},
Mix_PlayChannel: function(channel, id, loops) {
// TODO: handle loops
- var audio = SDL.audios[id].audio;
- if (audio.currentTime) audio.src = audio.src; // This hack prevents lags on replaying // TODO: parallel sounds through //cloneNode(true).play()
- audio.play();
- return 1; // XXX should return channel
+ 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;
+ 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(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
- audio.play();
- SDL.music = audio;
+ 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(id) {
- var audio = SDL.audios[id].audio;
+ Mix_PauseMusic: function() {
+ var audio = SDL.music.audio;
+ if (!audio) return 0;
audio.pause();
return 0;
},
- Mix_ResumeMusic: function(id) {
- var audio = SDL.audios[id].audio;
+ Mix_ResumeMusic: function() {
+ var audio = SDL.music.audio;
+ if (!audio) return 0;
audio.play();
return 0;
},
Mix_HaltMusic: function() {
- var audio = SDL.music;
+ var audio = SDL.music.audio;
if (!audio) return 0;
audio.src = audio.src; // rewind
audio.pause();
- SDL.music = null;
+ SDL.music.audio = null;
if (SDL.hookMusicFinished) {
FUNCTION_TABLE[SDL.hookMusicFinished]();
}
@@ -854,6 +1254,14 @@ mergeInto(LibraryManager.library, {
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 },
@@ -987,5 +1395,8 @@ mergeInto(LibraryManager.library, {
window.clearTimeout(id);
return true;
}
-});
+};
+
+autoAddDeps(LibrarySDL, '$SDL');
+mergeInto(LibraryManager.library, LibrarySDL);
diff --git a/src/modules.js b/src/modules.js
index 2bed1756..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', '_glut', '_xlib', '_egl')) {
- 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 8ccf1f9f..86e3c643 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -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;
@@ -767,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
@@ -986,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('; ');
}
@@ -1147,7 +1155,7 @@ 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 + ')';
+ return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
}
var PLUS_MUL = set('+', '*');
@@ -1163,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') {
@@ -1209,7 +1217,7 @@ function getFastValue(a, op, b, type) {
return a;
}
}
- return a + op + b;
+ return '(' + a + ')' + op + '(' + b + ')';
}
function getFastValues(list, op, type) {
@@ -1256,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
@@ -1314,27 +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)) {
- warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the source');
- // 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 = {
diff --git a/src/postamble.js b/src/postamble.js
index cf863669..10ac1888 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -32,28 +32,47 @@ Module.callMain = function callMain(args) {
function run(args) {
args = args || Module['arguments'];
- if (Module['setStatus']) {
- Module['setStatus'](''); // clear the status from "Downloading.." etc.
- }
-
if (Module['preRun']) {
- 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']) {
- preMain();
- 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['postRun']) {
- Module['postRun']();
+ 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;
diff --git a/src/preamble.js b/src/preamble.js
index 7c2b1a50..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);
@@ -315,8 +315,10 @@ 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)
@@ -324,10 +326,16 @@ function ccall(ident, returnType, argTypes, args) {
var stack = 0;
function toC(value, type) {
if (type == 'string') {
+ 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;
}
@@ -335,6 +343,7 @@ function ccall(ident, returnType, argTypes, args) {
if (type == 'string') {
return Pointer_stringify(value);
}
+ assert(type != 'array');
return value;
}
try {
@@ -713,40 +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, offset /*optional*/) {
- // TODO: optimize this!
- if (offset === undefined) {
- offset = 0;
- }
- var arr = new Uint8Array(num - offset);
- for (var i = offset; i < num; ++i) {
- arr[i - offset] = {{{ 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
@@ -754,17 +729,6 @@ 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.
@@ -830,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 }}}
@@ -837,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++;
@@ -846,6 +820,7 @@ function addRunDependency() {
Module['monitorRunDependencies'](runDependencies);
}
}
+Module['addRunDependency'] = addRunDependency;
function removeRunDependency() {
runDependencies--;
if (Module['monitorRunDependencies']) {
@@ -853,6 +828,7 @@ function removeRunDependency() {
}
if (runDependencies == 0) run();
}
+Module['removeRunDependency'] = removeRunDependency;
// === Body ===
diff --git a/src/runtime.js b/src/runtime.js
index 0e4b7b2d..1f8a618f 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -313,7 +313,78 @@ var Runtime = {
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 7df86c90..2526081b 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
@@ -100,9 +101,13 @@ 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 GL_DEBUG = 0; // Print out all calls into WebGL
+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
@@ -209,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 37509889..c04ae84b 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -1,20 +1,30 @@
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<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' style="border: 1px solid black"
- oncontextmenu="event.preventDefault()"></canvas>
- <hr>
- <textarea id="output" style="font-family: monospace; width: 80%" rows="8"></textarea>
- <hr>
- <div id='status'>Downloading...</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
@@ -28,19 +38,42 @@
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);
- Module.setStatus(left ? 'Downloading: ' + (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 ab54c284..891a6328 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -46,7 +46,7 @@ if (ENVIRONMENT_IS_NODE) {
}
} 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') {
@@ -104,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 7d5e0970..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;
}
}
diff --git a/system/include/emscripten.h b/system/include/emscripten.h
deleted file mode 100644
index ea078e8c..00000000
--- a/system/include/emscripten.h
+++ /dev/null
@@ -1,54 +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);
-
-/*
- * 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 as the fps will use the default browser
- * frame rate.
- */
-extern void emscripten_set_main_loop(void (*func)(), int fps);
-extern void emscripten_cancel_main_loop();
-
-/*
- * 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..5b71ce6a
--- /dev/null
+++ b/system/include/emscripten/emscripten.h
@@ -0,0 +1,133 @@
+/**
+ * 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();
+
+/*
+ * 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/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 77acc92e..2f887537 100644
--- a/system/include/libc/sys/types.h
+++ b/system/include/libc/sys/types.h
@@ -140,12 +140,8 @@ typedef unsigned long vm_size_t;
#define __BIT_TYPES_DEFINED__
-// XXX Emscripten: removed unsigned types which are already defined
-typedef signed char int8_t;
-typedef short int16_t;
-typedef int int32_t;
-typedef long long 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/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/sys/ioctl.h b/system/include/sys/ioctl.h
index 061ba925..b7ade699 100644
--- a/system/include/sys/ioctl.h
+++ b/system/include/sys/ioctl.h
@@ -1,7 +1,20 @@
+#ifndef _IOCTL_H
+#define _IOCTL_H
-/* 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 98a5974d..814921ea 100644
--- a/system/lib/libcxx/Makefile
+++ b/system/lib/libcxx/Makefile
@@ -12,7 +12,6 @@ OBJECTS = \
debug.bc \
hash.bc \
mutex.bc \
- readme.txt \
string.bc \
thread.bc \
valarray.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
index 3fbe8646..86f3749f 100644
--- a/tests/browser_harness.html
+++ b/tests/browser_harness.html
@@ -1,5 +1,9 @@
<html>
+<head>
+ <title>Emscripten Browser Test Harness</title>
+</head>
<body>
+<h2><b>Running tests...</b></h2>
<div id="output"></div>
<script>
var counter = 0;
@@ -9,8 +13,8 @@
try {
request.send(null);
if (request.responseText != 'False') {
- document.getElementById('output').innerHTML += 'opening test window ' + (counter++) + '..<br>';
window.open(request.responseText);
+ document.getElementById('output').innerHTML += 'opened test window ' + (counter++) + '..<br>';
}
setTimeout(check, 333);
} catch(e) {
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/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/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/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..20e2dbb5
--- /dev/null
+++ b/tests/emscripten_api_browser.cpp
@@ -0,0 +1,68 @@
+#include<stdio.h>
+#include<math.h>
+#include<stdlib.h>
+#include<SDL.h>
+#include<emscripten.h>
+#include<assert.h>
+
+int last = 0;
+
+extern "C" {
+
+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
+ int result = fived;
+ 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/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/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/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 6f7a4324..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.
@@ -113,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 *
@@ -139,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 *
@@ -289,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
*/
@@ -316,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
@@ -333,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
};
@@ -342,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
@@ -358,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
@@ -376,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] = {
@@ -420,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
@@ -485,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.
*/
@@ -520,7 +520,7 @@ draw_gear(struct gear *gear, GLfloat *transform,
glDisableVertexAttribArray(0);
}
-/**
+/**
* Draws the gears.
*/
static void
@@ -549,9 +549,9 @@ gears_draw(void)
glutSwapBuffers();
}
-/**
+/**
* Handles a new window size or exposure.
- *
+ *
* @param width the window width
* @param height the window height
*/
@@ -565,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
@@ -586,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;
}
}
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/runner.py b/tests/runner.py
index 673193c5..4bf3f5ee 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -14,7 +14,7 @@ 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:
@@ -79,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
@@ -259,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]
@@ -355,7 +357,6 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
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)
@@ -909,6 +910,84 @@ m_divisor is 1091269979
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')
@@ -1131,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>
@@ -1341,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>
@@ -1630,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>
@@ -1710,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
@@ -2323,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;
}
'''
@@ -2337,7 +2497,7 @@ 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'''
@@ -2697,7 +2857,7 @@ def process(filename):
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'
+ 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:
@@ -2799,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:
@@ -3541,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));
@@ -3565,9 +3769,14 @@ def process(filename):
0
0
0
+ 0
1
1
1
+ 0
+ 0.5
+ 0.5
+ 0
123
123.456
-123.456
@@ -3583,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'''
@@ -3763,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'''
@@ -3839,8 +4075,9 @@ def process(filename):
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() {
@@ -3890,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):
@@ -4581,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):
@@ -4806,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'
@@ -4903,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(),
@@ -5281,6 +5571,7 @@ def process(filename):
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');
@@ -5304,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*\nstack is ok.\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')
@@ -5367,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);
};
@@ -5404,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"
@@ -6029,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):
@@ -6121,11 +6528,15 @@ TT = %s
# --version
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].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(['python', compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate()
self.assertContained('''%s [options] file...
@@ -6269,7 +6680,7 @@ Options that are modified or new in %s include:
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 [
@@ -6354,6 +6765,26 @@ f.close()
# 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
@@ -6412,6 +6843,38 @@ f.close()
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
@@ -6445,6 +6908,30 @@ f.close()
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'''
@@ -6463,6 +6950,10 @@ f.close()
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
@@ -6538,6 +7029,38 @@ f.close()
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>
@@ -6574,10 +7097,47 @@ f.close()
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):
- 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]
+ 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):
@@ -6597,6 +7157,8 @@ f.close()
['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'))
@@ -6608,6 +7170,15 @@ f.close()
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'))
@@ -6632,36 +7203,125 @@ 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
-
- # 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 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
browser.harness_queue = multiprocessing.Queue()
- browser.harness_server = multiprocessing.Process(target=server_func, args=(browser.harness_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')
@@ -6672,44 +7332,29 @@ elif 'browser' in str(sys.argv):
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):
- 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(self.get_dir())
- 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()
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.'
@@ -6778,9 +7423,9 @@ elif 'browser' in str(sys.argv):
img.src = '%s';
};
Module['postRun'] = doReftest;
- Module['preRun'] = function() {
- setTimeout(doReftest, 0); // if run() throws an exception and postRun is not called, this will kick in
- };
+ 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):
@@ -6789,6 +7434,17 @@ elif 'browser' in str(sys.argv):
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>
@@ -6801,6 +7457,7 @@ elif 'browser' in str(sys.argv):
}
'''))
+ 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'),
@@ -6813,27 +7470,47 @@ elif 'browser' in str(sys.argv):
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))
+ 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')
+ # 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
self.clear()
@@ -6903,6 +7580,7 @@ elif 'browser' in str(sys.argv):
}
'''))
+ 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'),
@@ -6914,11 +7592,11 @@ elif 'browser' in str(sys.argv):
self.run_browser('page.html', '', '/report_result?1')
def test_sdl_image(self):
- # load an image file, get pixel data
+ # 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(['python', 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_sdl_image_compressed(self):
@@ -6931,6 +7609,7 @@ elif 'browser' in str(sys.argv):
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))
+ 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'),
@@ -6998,10 +7677,11 @@ elif 'browser' in str(sys.argv):
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'), '-o', 'page.html', '--pre-js', 'pre.js']).communicate()
+ 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):
@@ -7013,6 +7693,75 @@ elif 'browser' in str(sys.argv):
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(['python', EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate()
@@ -7093,6 +7842,141 @@ elif 'browser' in str(sys.argv):
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 += ['--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])
+
+ def test_emscripten_api(self):
+ self.btest('emscripten_api_browser.cpp', '1')
+
+ def test_emscripten_fs_api(self):
+ self.btest('emscripten_fs_api_browser.cpp', '1')
+
+ def test_gc(self):
+ self.btest('browser_gc.cpp', '1')
+
+ def test_glshaderinfo(self):
+ self.btest('glshaderinfo.cpp', '1')
+
+ def test_sdlglshader(self):
+ self.btest('sdlglshader.c', reference='sdlglshader.png', args=['--closure', '1'])
+
+ 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_matrix_identity(self):
+ self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'])
+
+ def test_cubegeom_pre(self):
+ self.btest('cubegeom_pre.c', expected='-1472804742')
+
+ 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
+
+ def test_cubegeom_pre3(self):
+ self.btest('cubegeom_pre3.c', expected='-1472804742')
+
+ def test_cubegeom(self):
+ self.btest('cubegeom.c', expected=['188641320', '1522377227'])
+
+ def test_cubegeom_color(self):
+ self.btest('cubegeom_color.c', expected='588472350')
+
+ def test_cubegeom_normal(self):
+ self.btest('cubegeom_normal.c', expected='752917084')
+
+ 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')
+
+ def test_cubegeom_normal_dap_far(self): # indices do nto start from 0
+ self.btest('cubegeom_normal_dap_far.c', expected='752917084')
+
+ def test_cubegeom_normal_dap_far_range(self): # glDrawRangeElements
+ self.btest('cubegeom_normal_dap_far_range.c', expected='752917084')
+
+ def test_cubegeom_normal_dap_far_glda(self): # use glDrawArrays
+ self.btest('cubegeom_normal_dap_far_glda.c', expected='-218745386')
+
+ def test_cubegeom_normal_dap_far_glda_quad(self): # with quad
+ self.btest('cubegeom_normal_dap_far_glda_quad.c', expected='1757386625')
+
+ def test_cubegeom_mt(self):
+ self.btest('cubegeom_mt.c', expected='-457159152') # multitexture
+
+ 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
# |benchmark.test_X|.
@@ -7188,10 +8072,9 @@ elif 'benchmark' in str(sys.argv):
try_delete(final_filename)
output = Popen(['python', EMCC, filename, '-O3',
- '-s', 'INLINING_LIMIT=0',
'-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
@@ -7558,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'
@@ -7600,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
index 4927d868..938df3c4 100644
--- a/tests/sdl_audio.c
+++ b/tests/sdl_audio.c
@@ -10,14 +10,23 @@ void play2();
void play() {
int channel = Mix_PlayChannel(-1, sound, 1);
- assert(channel >= 0);
+ 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 >= 0);
+ assert(channel2 == 1);
}
int main(int argc, char **argv) {
@@ -42,9 +51,6 @@ int main(int argc, char **argv) {
printf("you should hear two sounds. press the button to replay!\n");
- int result = 1;
- REPORT_RESULT();
-
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_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 d934f863..9d8c36f2 100644
--- a/tests/sdl_image.c
+++ b/tests/sdl_image.c
@@ -4,30 +4,40 @@
#include <assert.h>
#include <emscripten.h>
-int main() {
- SDL_Init(SDL_INIT_VIDEO);
- SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_SWSURFACE);
-
- 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);
- 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
index 6a5ad694..19b0a3d6 100644
--- a/tests/sdl_key.c
+++ b/tests/sdl_key.c
@@ -23,8 +23,10 @@ void one() {
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'");
+ 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;
@@ -38,13 +40,13 @@ 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)");
- emscripten_run_script("simulateKeyEvent(40)");
- emscripten_run_script("simulateKeyEvent(37)");
- emscripten_run_script("simulateKeyEvent(39)");
- emscripten_run_script("simulateKeyEvent(32)");
- emscripten_run_script("simulateKeyEvent(97)");
- emscripten_run_script("simulateKeyEvent(98)");
+ 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
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
index dae3f636..0c10198a 100644
--- a/tests/sdl_mouse.c
+++ b/tests/sdl_mouse.c
@@ -12,6 +12,7 @@ void one() {
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);
@@ -33,12 +34,17 @@ void one() {
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);
@@ -46,13 +52,18 @@ int main() {
SDL_Rect rect = { 0, 0, 600, 450 };
SDL_FillRect(screen, &rect, 0x2244ffff);
- emscripten_run_script("simulateMouseEvent(10, 20, -1)"); // move from 0,0 to 10,20
- emscripten_run_script("simulateMouseEvent(10, 20, 0)"); // click
- emscripten_run_script("simulateMouseEvent(30, 77, -1)"); // move some more
- emscripten_run_script("simulateMouseEvent(30, 77, 1)"); // trigger the end
-
- emscripten_set_main_loop(one, 0);
+ 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/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 943ff043..3631548c 100644
--- a/tools/autodebugger.py
+++ b/tools/autodebugger.py
@@ -13,6 +13,7 @@ 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]
@@ -206,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'):
@@ -215,50 +217,55 @@ 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'))
- 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 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
- 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
+ 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(' call void @llvm\.memcpy\.p0i8\.p0i8\.i32\(i8\* %(?P<dst>[\w_.]+), i8\* %(?P<src>[\w_.]+), i32 8, i32 (?P<align>\d+),.*', lines[i])
+ 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 %%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
+ 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:
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
index 56bd9e2b..43694179 100644
--- a/tools/clean_webconsole.py
+++ b/tools/clean_webconsole.py
@@ -2,7 +2,23 @@
Removes timestamp and line info from a webgl log
'''
-import os, sys
+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')
@@ -10,8 +26,9 @@ 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
+#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 a4c98930..05e3788b 100644
--- a/tools/eliminator/eliminator.coffee
+++ b/tools/eliminator/eliminator.coffee
@@ -107,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.
@@ -157,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: ->
@@ -170,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
@@ -211,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
@@ -264,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
@@ -370,14 +383,8 @@ class ExpressionOptimizer
# function, then writes the optimized result to stdout.
main = ->
# Get the parse tree.
- if os.platform().substr(0, 3) != 'win'
- src = fs.readFileSync('/dev/stdin').toString()
- else
- # The following seems to work on windows, but fails on linux..
- src = ''
- size = fs.fstatSync(process.stdin.fd).size
- if size > 0
- src = fs.readSync(process.stdin.fd, size)[0]
+ #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) ->
@@ -386,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/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 b51fe22e..d58c8c6c 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -119,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]];
@@ -669,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) {
@@ -1140,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;
@@ -1156,6 +1344,7 @@ var passes = {
simplifyExpressionsPost: simplifyExpressionsPost,
hoistMultiples: hoistMultiples,
loopOptimizer: loopOptimizer,
+ registerize: registerize,
compress: function() { compress = true; }
};
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 532f561f..997c0ad9 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -1,4 +1,4 @@
-import shutil, time, os, sys, json, tempfile, copy, shlex
+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,23 +123,31 @@ 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. Create a random one, unless EMCC_DEBUG is set, in which case use TEMP_DIR/emscripten_temp
+try:
+ 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 = os.path.join(TEMP_DIR, 'emscripten_temp')
+ EMSCRIPTEN_TEMP_DIR = CANONICAL_TEMP_DIR
if not os.path.exists(EMSCRIPTEN_TEMP_DIR):
os.makedirs(EMSCRIPTEN_TEMP_DIR)
except:
@@ -129,6 +155,9 @@ if os.environ.get('EMCC_DEBUG'):
if not EMSCRIPTEN_TEMP_DIR:
EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_')
+ def clean_temp():
+ try_delete(EMSCRIPTEN_TEMP_DIR)
+ atexit.register(clean_temp)
# EM_CONFIG stuff
@@ -146,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:
@@ -155,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')
@@ -163,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'),
@@ -172,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:
@@ -180,13 +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
-
-WINDOWS = sys.platform.startswith ('win')
+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
@@ -228,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))
@@ -243,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
@@ -342,11 +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
- Settings.PRECISE_I64_MATH = 0
if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
global Settings
@@ -461,24 +516,95 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
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)
- stub = os.path.join(EMSCRIPTEN_TEMP_DIR, 'stub_deleteme')
- output = Popen([LLVM_LD, '-disable-opt'] + files + ['-b', target, '-o', stub], stdout=PIPE).communicate()[0]
- try_delete(stub) # clean up stub left by the linker
- 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
@@ -507,12 +633,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
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):
@@ -548,13 +668,15 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
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)
@@ -565,13 +687,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
if output_filename is None:
output_filename = filename + '.o'
try_delete(output_filename)
- Popen(['python', 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(['python', 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'
@@ -582,7 +704,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# 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
@@ -713,8 +835,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
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)
@@ -729,8 +851,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
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)
@@ -744,7 +866,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# 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
- args = ['java',
+ args = [JAVA,
'-Xmx1024m',
'-jar', CLOSURE_COMPILER,
'--compilation_level', 'ADVANCED_OPTIMIZATIONS',
@@ -810,7 +932,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
# 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():
@@ -832,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-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"]