diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/library.js | 28 | ||||
-rw-r--r-- | src/library_gl.js | 481 | ||||
-rw-r--r-- | src/library_sdl.js | 15 | ||||
-rw-r--r-- | src/preamble.js | 39 | ||||
-rw-r--r-- | src/shell.html | 5 |
5 files changed, 538 insertions, 30 deletions
diff --git a/src/library.js b/src/library.js index 355a0c61..45c64bc7 100644 --- a/src/library.js +++ b/src/library.js @@ -4682,6 +4682,34 @@ LibraryManager.library = { }, nanf: 'nan', + sincos: function(x, sine, cosine) { + var sineVal = Math.sin(x), + cosineVal = Math.cos(x); + {{{ makeSetValue('sine', '0', 'sineVal', 'double') }}}; + {{{ makeSetValue('cosine', '0', 'cosineVal', 'double') }}}; + }, + + sincosf: function(x, sine, cosine) { + var sineVal = Math.sin(x), + cosineVal = Math.cos(x); + {{{ makeSetValue('sine', '0', 'sineVal', 'float') }}}; + {{{ makeSetValue('cosine', '0', 'cosineVal', 'float') }}}; + }, + + __div_t_struct_layout: Runtime.generateStructInfo([ + ['i32', 'quot'], + ['i32', 'rem'], + ]), + div__deps: ['__div_t_struct_layout'], + div: function(divt, numer, denom) { + var quot = Math.floor(numer / denom); + var rem = numer - quot * denom; + var offset = ___div_t_struct_layout.rem; + {{{ makeSetValue('divt', '0', 'quot', 'i32') }}}; + {{{ makeSetValue('divt', 'offset', 'rem', 'i32') }}}; + return divt; + }, + __fpclassifyf: function(x) { if (isNaN(x)) return {{{ cDefine('FP_NAN') }}}; if (!isFinite(x)) return {{{ cDefine('FP_INFINITE') }}}; diff --git a/src/library_gl.js b/src/library_gl.js index 2be881df..e1a7c73b 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4,8 +4,35 @@ var LibraryGL = { $GL: { - textures: {}, - textureCounter: 0, + hashtable: function(name) { + if (!this._hashtables) { + this._hashtables = {}; + } + if (!(name in this._hashtables)) { + this._hashtables[name] = { + table: {}, + counter: 0, + add: function(obj) { + var id = this.counter++; + this.table[id] = obj; + return id; + }, + get: function(id) { +#if ASSERTIONS + assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); +#endif + return this.table[id]; + }, + remove: function(id) { +#if ASSERTIONS + assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); +#endif + delete this.table[id]; + } + }; + } + return this._hashtables[name]; + }, }, glGetString: function(name_) { @@ -24,7 +51,7 @@ var LibraryGL = { glGetIntegerv: function(name_, p) { switch(name_) { case Module.ctx.MAX_TEXTURE_SIZE: - IHEAP[p] = Module.ctx.getParameter(name_); + {{{ makeSetValue('p', '0', 'Module.ctx.getParameter(name_)', 'i32') }}}; break; default: throw 'Failure: Invalid glGetIntegerv value: ' + name_; @@ -34,78 +61,476 @@ var LibraryGL = { glGenTextures__deps: ['$GL'], glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = GL.textureCounter++; - GL.textures[id] = Module.ctx.createTexture(); - IHEAP[textures+QUANTUM_SIZE*i] = id; + var id = GL.hashtable("texture").add(Module.ctx.createTexture()); + {{{ makeSetValue('textures', 'i', 'id', 'i32') }}}; } }, glDeleteTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = IHEAP[textures+QUANTUM_SIZE*i]; - Module.ctx.deleteTexture(GL.textures[id]); - delete GL.textures[id]; + var id = {{{ makeGetValue('textures', 'i', 'i32') }}}; + Module.ctx.deleteTexture(GL.hashtable("texture").get(id)); + GL.hashtable("texture").remove(id); } }, glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(IHEAP.slice(pixels, pixels + width*height*4)); // TODO: optimize + pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize } Module.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); }, glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(IHEAP.slice(pixels, pixels + width*height*4)); // TODO: optimize + pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize } Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); }, glBindTexture: function(target, texture) { - Module.ctx.bindTexture(target, GL.textures[texture]); + Module.ctx.bindTexture(target, GL.hashtable("texture").get(texture)); }, - glClearColor: function(red, green, blue, alpha) { - Module.ctx.clearColor(red, green, blue, alpha); + glGenBuffers__deps: ['$GL'], + glGenBuffers: function(n, buffers) { + for (var i = 0; i < n; i++) { + var id = GL.hashtable("buffer").add(Module.ctx.createBuffer()); + {{{ makeSetValue('buffers', 'i', 'id', 'i32') }}}; + } + }, + + glDeleteBuffers: function(n, buffers) { + for (var i = 0; i < n; i++) { + var id = {{{ makeGetValue('buffers', 'i', 'i32') }}}; + Module.ctx.deleteBuffer(GL.hashtable("buffer").get(id)); + GL.hashtable("buffer").remove(id); + } + }, + + glBufferData: function(target, size, data, usage) { + var floatArray = new Float32Array(TypedArray_copy(data, size)); + Module.ctx.bufferData(target, floatArray, usage); + }, + + glBindAttribLocation_deps: ['$GL'], + glGetUniformLocation: function(program, name) { + name = Pointer_stringify(name); + return GL.hashtable("uniform").add( + Module.ctx.getUniformLocation(GL.hashtable("program").get(program), name)); + }, + + glUniform1f: function(Location, v0) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform1f(Location, v0); + }, + + glUniform2f: function(Location, v0, v1) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform2f(Location, v0, v1); + }, + + glUniform3f: function(Location, v0, v1, v2) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform3f(Location, v0, v1, v2); }, - glClear: function(mask) { - Module.ctx.clear(mask); + glUniform4f: function(Location, v0, v1, v2, v3) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform4f(Location, v0, v1, v2, v3); }, - glEnable: function(cap) { - Module.ctx.enable(cap); + glUniform1i: function(Location, v0) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform1i(Location, v0); }, - glScissor: function(x, y, width, height) { - Module.ctx.scissor(x, y, width, height); + glUniform2i: function(Location, v0, v1) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform2i(Location, v0, v1); + }, + + glUniform3i: function(Location, v0, v1, v2) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform3i(Location, v0, v1, v2); + }, + + glUniform4i: function(Location, v0, v1, v2, v3) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform4i(Location, v0, v1, v2, v3); + }, + + glUniform1fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform1fv(Location, value); + }, + + glUniform2fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 2; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform2fv(Location, value); + }, + + glUniform3fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 3; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform3fv(Location, value); + }, + + glUniform4fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform4fv(Location, value); + }, + + glUniform1fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform1fi(Location, value); + }, + + glUniform2fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 2; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform2fi(Location, value); + }, + + glUniform3fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 3; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform3fi(Location, value); + }, + + glUniform4fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform4fi(Location, value); + }, + + glUniformMatrix2fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix2fv(Location, transpose, value); + }, + + glUniformMatrix3fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 9; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix3fv(Location, transpose, value); + }, + + glUniformMatrix4fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 16; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix4fv(Location, transpose, value); + }, + + glBindBuffer: function(target, buffer) { + Module.ctx.bindBuffer(target, GL.hashtable("buffer").get(buffer)); + }, + + glVertexAttrib1f: function(index, v0) { + Module.ctx.vertexAttrib1f(index, v0); + }, + + glVertexAttrib2f: function(index, v0, v1) { + Module.ctx.vertexAttrib2f(index, v0, v1); + }, + + glVertexAttrib3f: function(index, v0, v1, v2) { + Module.ctx.vertexAttrib3f(index, v0, v1, v2); + }, + + glVertexAttrib4f: function(index, v0, v1, v2, v3) { + Module.ctx.vertexAttrib4f(index, v0, v1, v2, v3); + }, + + glVertexAttrib1fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 1*4)); // TODO: optimize + Module.ctx.vertexAttrib1fv(index, v); + }, + + glVertexAttrib2fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 2*4)); // TODO: optimize + Module.ctx.vertexAttrib2fv(index, v); + }, + + glVertexAttrib3fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 3*4)); // TODO: optimize + Module.ctx.vertexAttrib3fv(index, v); + }, + + glVertexAttrib4fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 4*4)); // TODO: optimize + Module.ctx.vertexAttrib4fv(index, v); + }, + + glVertexAttribPointer: function(index, size, type, normalized, stride, pointer) { + Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, pointer); + }, + + glEnableVertexAttribArray: function(index) { + Module.ctx.enableVertexAttribArray(index); + }, + + glDisableVertexAttribArray: function(index) { + Module.ctx.disableVertexAttribArray(index); + }, + + glDrawArrays: function(mode, first, count) { + Module.ctx.drawArrays(mode, first, count); + }, + + glGetAttribLocation: function(program, name) { + program = GL.hashtable("program").get(program); + name = Pointer_stringify(name); + Module.ctx.getAttribLocation(program, name); + }, + + glCreateShader_deps: ['$GL'], + glCreateShader: function(shaderType) { + var shader = Module.ctx.createShader(shaderType); + return GL.hashtable("shader").add(shader); + }, + + glShaderSource_deps: ['$GL'], + glShaderSource: function(shader, count, string, length) { + var source = ""; + for (var i = 0; i < count; ++i) { + var frag = string[i]; + if (length) { + var len = {{{ makeGetValue('length', 'i', 'i32') }}}; + if (len < 0) { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}, len); + } + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); + } + if (source.length) { + source += "\n"; + } + source += frag; + } + Module.ctx.shaderSource(GL.hashtable("shader").get(shader), source); + }, + + glCompileShader_deps: ['$GL'], + glCompileShader: function(shader) { + Module.ctx.compileShader(GL.hashtable("shader").get(shader)); + }, + + glGetShaderInfoLog_deps: ['$GL'], + glGetShaderInfoLog: function(shader, maxLength, length, infoLog) { + var log = Module.ctx.getShaderInfoLog(GL.hashtable("shader").get(shader)); + log.slice(0, maxLength - 1); + writeStringToMemory(log, infoLog); + if (length) { + {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + } + }, + + glCreateProgram_deps: ['$GL'], + glCreateProgram: function() { + return GL.hashtable("program").add(Module.ctx.createProgram()); + }, + + glAttachShader_deps: ['$GL'], + glAttachShader: function(program, shader) { + Module.ctx.attachShader(GL.hashtable("program").get(program), + GL.hashtable("shader").get(shader)); + }, + + glLinkProgram_deps: ['$GL'], + glLinkProgram: function(program) { + Module.ctx.linkProgram(GL.hashtable("program").get(program)); + }, + + glGetProgramInfoLog_deps: ['$GL'], + glGetProgramInfoLog: function(program, maxLength, length, infoLog) { + var log = Module.ctx.getProgramInfoLog(GL.hashtable("program").get(program)); + // Work around a bug in Chromium which causes getProgramInfoLog to return null + if (!log) { + log = ""; + } + log = log.substr(0, maxLength - 1); + writeStringToMemory(log, infoLog); + if (length) { + {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + } + }, + + glUseProgram_deps: ['$Gl'], + glUseProgram: function(program) { + Module.ctx.useProgram(GL.hashtable("program").get(program)); + }, + + glBindAttribLocation_deps: ['$GL'], + glBindAttribLocation: function(program, index, name) { + name = Pointer_stringify(name); + Module.ctx.bindAttribLocation(GL.hashtable("program").get(program), index, name); }, }; -// Ignored stubs for fixed-function pipeline. We will need to emulate this -'begin end matrixMode loadIdentity ortho color3f texCoord2f vertex2f blendFunc pushMatrix popMatrix translatef scalef color4ub enableClientState disableClientState vertexPointer colorPointer normalPointer texCoordPointer drawArrays clientActiveTexture_'.split(' ').forEach(function(name_) { - var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1); - LibraryGL[cName] = function(){}; -}); // Simple pass-through functions -[[0, 'shadeModel fogi fogfv'], - [1, 'clearDepth depthFunc enable disable frontFace cullFace'], +[[0, 'shadeModel fogi fogfv getError'], + [1, 'clearDepth depthFunc enable disable frontFace cullFace clear'], [2, 'pixelStorei'], [3, 'texParameteri texParameterf'], - [4, 'viewport clearColor']].forEach(function(data) { + [4, 'viewport clearColor scissor']].forEach(function(data) { var num = data[0]; var names = data[1]; var args = range(num).map(function(i) { return 'x' + i }).join(', '); var stub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })'; names.split(' ').forEach(function(name_) { var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1); +#if ASSERTIONS + assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName); +#endif LibraryGL[cName] = eval(stub.replace('NAME', name_)); //print(cName + ': ' + LibraryGL[cName]); }); }); +var LibraryGLUT = { + $GLUT: { + initTime: null, + idleFunc: null, + keyboardFunc: null, + reshapeFunc: null, + lastX: 0, + lastY: 0, + + onMousemove: function(event) { + GLUT.lastX = event['clientX']; + GLUT.lastY = event['clientY']; + }, + + onKeydown: function(event) { + if (GLUT.keyboardFunc) { + var key = null; + switch (event['keyCode']) { + case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break; + case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break; + case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break; + case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break; + case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break; + case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break; + case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break; + case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break; + case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break; + case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break; + case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break; + case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break; + case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break; + case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break; + case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break; + case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break; + case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break; + case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break; + case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break; + case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break; + case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break; + default: return; + }; + if (key !== null) { + FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY); + } + } + }, + }, + + glutInit__deps: ['$GLUT'], + glutInit: function(argcp, argv) { + // Ignore arguments + GLUT.initTime = Date.now(); + window.addEventListener("keydown", GLUT.onKeydown, true); + window.addEventListener("mousemove", GLUT.onMousemove, true); + }, + + glutInitWindowSize: function(width, height) { + Module['canvas'].width = width; + Module['canvas'].height = height; + }, + + glutGet: function(type) { + switch (type) { + case 700: /* GLUT_ELAPSED_TIME */ + var now = Date.now(); + return now - GLUT.initTime; + default: + throw "glutGet(" + type + ") not implemented yet"; + } + }, + + glutDisplayFunc: function(func) { + var RAF = window['setTimeout']; + if (window['requestAnimationFrame']) { + RAF = window['requestAnimationFrame']; + } else if (window['mozRequestAnimationFrame']) { + RAF = window['mozRequestAnimationFrame']; + } else if (window['webkitRequestAnimationFrame']) { + RAF = window['webkitRequestAnimationFrame']; + } else if (window['msRequestAnimationFrame']) { + RAF = window['msRequestAnimationFrame']; + } + RAF.apply(window, [function() { + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](Module['canvas'].width, + Module['canvas'].height); + } + if (GLUT.idleFunc) { + FUNCTION_TABLE[GLUT.idleFunc](); + } + FUNCTION_TABLE[func](); + _glutDisplayFunc(func); + }]); + }, + + glutIdleFunc: function(func) { + GLUT.idleFunc = func; + }, + + glutSpecialFunc: function(func) { + GLUT.keyboardFunc = func; + }, + + glutReshapeFunc: function(func) { + GLUT.reshapeFunc = func; + }, + + glutCreateWindow: function(name) { + try { + var ctx = Module.canvas.getContext('experimental-webgl'); + if (!ctx) throw 'Could not create canvas :('; + Module.ctx = ctx; + // Set the background of the canvas to black, because glut gives us a + // window which has a black background by default. + Module.canvas.style.backgroundColor = "black"; + } catch (e) { + Module.print('(canvas not available)'); + } + }, + + glutInitDisplayMode: function(mode) {}, + glutMainLoop: function() {}, + glutSwapBuffers: function() {}, + glutPostRedisplay: function() {}, +}; + mergeInto(LibraryManager.library, LibraryGL); +mergeInto(LibraryManager.library, LibraryGLUT); diff --git a/src/library_sdl.js b/src/library_sdl.js index ce26a106..d438fc23 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -176,6 +176,11 @@ mergeInto(LibraryManager.library, { try { var ctx = Module.canvas.getContext(useWebGL ? 'experimental-webgl' : '2d'); if (!ctx) throw 'Could not create canvas :('; + if (useWebGL) { + // Set the background of the WebGL canvas to black, because SDL gives us a + // window which has a black background by default. + Module.canvas.style.backgroundColor = "black"; + } return Module.ctx = ctx; } catch (e) { Module.print('(canvas not available)'); @@ -555,5 +560,15 @@ mergeInto(LibraryManager.library, { // SDL Mixer Mix_OpenAudio: function() { return -1 }, + + SDL_AddTimer: function(interval, callback, param) { + return window.setTimeout(function() { + FUNCTION_TABLE[callback](interval, param); + }, interval); + }, + SDL_RemoveTimer: function(id) { + window.clearTimeout(id); + return true; + }, }); diff --git a/src/preamble.js b/src/preamble.js index b9da766f..9370fa54 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -496,16 +496,18 @@ function allocate(slab, types, allocator) { } Module['allocate'] = allocate; -function Pointer_stringify(ptr) { +function Pointer_stringify(ptr, /* optional */ length) { + var nullTerminated = typeof(length) == "undefined"; var ret = ""; var i = 0; var t; var nullByte = String.fromCharCode(0); while (1) { t = String.fromCharCode({{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}}); - if (t == nullByte) { break; } else {} + if (nullTerminated && t == nullByte) { break; } else {} ret += t; i += 1; + if (!nullTerminated && i == length) { break; } } return ret; } @@ -690,6 +692,20 @@ function Array_copy(ptr, num) { } Module['Array_copy'] = Array_copy; +#if USE_TYPED_ARRAYS +// Copies a list of num items on the HEAP into a +// JavaScript typed array. +function TypedArray_copy(ptr, num) { + // TODO: optimize this! + var arr = new Uint8Array(num); + for (var i = 0; i < num; ++i) { + arr[i] = {{{ makeGetValue('ptr', 'i', 'i8') }}}; + } + return arr.buffer; +} +Module['TypedArray_copy'] = TypedArray_copy; +#endif + function String_len(ptr) { var i = 0; while ({{{ makeGetValue('ptr', 'i', 'i8') }}}) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds @@ -750,6 +766,25 @@ function intArrayToString(array) { } Module['intArrayToString'] = intArrayToString; +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var i = 0; + while (i < string.length) { + var chr = string.charCodeAt(i); + if (chr > 0xFF) { +#if ASSERTIONS + assert(false, 'Character code ' + chr + ' (' + string[i] + ') at offset ' + i + ' not in 0x00-0xFF.'); +#endif + chr &= 0xFF; + } + {{{ makeSetValue('buffer', 'i', 'chr', 'i8') }}} + i = i + 1; + } + if (!dontAddNull) { + {{{ makeSetValue('buffer', 'i', '0', 'i8') }}} + } +} + var STRING_TABLE = []; {{{ unSign }}} diff --git a/src/shell.html b/src/shell.html index 6b6bbdad..69217b18 100644 --- a/src/shell.html +++ b/src/shell.html @@ -9,6 +9,11 @@ <div id='output'></div> <hr> <script type='text/javascript'> + /** + * TODO: Encapsulate this part in a reusable token such as + * EMSCRIPTEN_ENVIRONMENT so that we can share code + * between the default shell and custom ones. + */ // connect to canvas var Module = { print: (function() { |