401
471
// ignore extra ups, can happen if we leave the canvas while pressing down, then return,
402
472
// since we add a mouseup in that case
403
473
if (!SDL.DOMButtons[event.button]) {
404
event.preventDefault();
408
477
SDL.DOMButtons[event.button] = 0;
411
if (event.type == 'keypress' && !SDL.textInput) {
415
SDL.events.push(event);
480
// We can only request fullscreen as the result of user input.
481
// Due to this limitation, we toggle a boolean on keydown which
482
// SDL_WM_ToggleFullScreen will check and subsequently set another
483
// flag indicating for us to request fullscreen on the following
484
// keyup. This isn't perfect, but it enables SDL_WM_ToggleFullScreen
485
// to work as the result of a keypress (which is an extremely
487
if (event.type === 'keydown') {
488
SDL.canRequestFullscreen = true;
489
} else if (event.type === 'keyup') {
490
if (SDL.isRequestingFullscreen) {
491
Module['requestFullScreen'](true, true);
492
SDL.isRequestingFullscreen = false;
494
SDL.canRequestFullscreen = false;
497
// SDL expects a unicode character to be passed to its keydown events.
498
// Unfortunately, the browser APIs only provide a charCode property on
499
// keypress events, so we must backfill in keydown events with their
500
// subsequent keypress event's charCode.
501
if (event.type === 'keypress' && SDL.savedKeydown) {
502
// charCode is read-only
503
SDL.savedKeydown.keypressCharCode = event.charCode;
504
SDL.savedKeydown = null;
505
} else if (event.type === 'keydown') {
506
SDL.savedKeydown = event;
509
// Don't push keypress events unless SDL_StartTextInput has been called.
510
if (event.type !== 'keypress' || SDL.textInput) {
511
SDL.events.push(event);
418
515
// Un-press all pressed mouse buttons, because we might miss the release outside of the canvas
450
549
SDL.events.push(event);
550
// manually triggered resize event doesn't have a preventDefault member
551
if (event.preventDefault) {
552
event.preventDefault();
453
556
if (SDL.events.length >= 10000) {
454
557
Module.printErr('SDL event queue full, dropping events');
455
558
SDL.events = SDL.events.slice(0, 10000);
457
// manually triggered resize event doesn't have a preventDefault member
458
if (event.preventDefault) {
459
event.preventDefault();
563
handleEvent: function(event) {
564
if (event.handled) return;
565
event.handled = true;
567
switch (event.type) {
568
case 'keydown': case 'keyup': {
569
var down = event.type === 'keydown';
570
var code = event.keyCode;
571
if (code >= 65 && code <= 90) {
572
code += 32; // make lowercase for SDL
574
code = SDL.keyCodes[event.keyCode] || event.keyCode;
577
{{{ makeSetValue('SDL.keyboardState', 'code', 'down', 'i8') }}};
578
// TODO: lmeta, rmeta, numlock, capslock, KMOD_MODE, KMOD_RESERVED
579
SDL.modState = ({{{ makeGetValue('SDL.keyboardState', '1248', 'i8') }}} ? 0x0040 | 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL
580
({{{ makeGetValue('SDL.keyboardState', '1249', 'i8') }}} ? 0x0001 | 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT
581
({{{ makeGetValue('SDL.keyboardState', '1250', 'i8') }}} ? 0x0100 | 0x0200 : 0); // KMOD_LALT & KMOD_RALT
584
SDL.keyboardMap[code] = event.keyCode; // save the DOM input, which we can use to unpress it during blur
586
delete SDL.keyboardMap[code];
591
case 'mousedown': case 'mouseup':
592
if (event.type == 'mousedown') {
593
// SDL_BUTTON(x) is defined as (1 << ((x)-1)). SDL buttons are 1-3,
594
// and DOM buttons are 0-2, so this means that the below formula is
596
SDL.buttonState |= 1 << event.button;
597
} else if (event.type == 'mouseup') {
598
SDL.buttonState &= ~(1 << event.button);
602
Browser.calculateMouseEvent(event);
464
608
makeCEvent: function(event, ptr) {
465
609
if (typeof event === 'number') {
466
610
// This is a pointer to a native C event that was SDL_PushEvent'ed
485
631
scan = SDL.scanCodes[key] || key;
488
var code = SDL.keyCodes[event.keyCode] || event.keyCode;
489
{{{ makeSetValue('SDL.keyboardState', 'code', 'down', 'i8') }}};
491
SDL.keyboardMap[code] = event.keyCode; // save the DOM input, which we can use to unpress it during blur
493
delete SDL.keyboardMap[code];
496
// TODO: lmeta, rmeta, numlock, capslock, KMOD_MODE, KMOD_RESERVED
497
SDL.modState = ({{{ makeGetValue('SDL.keyboardState', '1248', 'i8') }}} ? 0x0040 | 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL
498
({{{ makeGetValue('SDL.keyboardState', '1249', 'i8') }}} ? 0x0001 | 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT
499
({{{ makeGetValue('SDL.keyboardState', '1250', 'i8') }}} ? 0x0100 | 0x0200 : 0); // KMOD_LALT & KMOD_RALT
501
634
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.type', 'SDL.DOMEventToSDLEvent[event.type]', 'i32') }}}
502
635
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.state', 'down ? 1 : 0', 'i8') }}}
503
636
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.repeat', '0', 'i8') }}} // TODO
504
637
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.scancode', 'scan', 'i32') }}}
505
638
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.sym', 'key', 'i32') }}}
506
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', 'SDL.modState', 'i32') }}}
507
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'key', 'i32') }}}
639
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.mod', 'SDL.modState', 'i16') }}}
640
// some non-character keys (e.g. backspace and tab) won't have keypressCharCode set, fill in with the keyCode.
641
{{{ makeSetValue('ptr', 'SDL.structs.KeyboardEvent.keysym + SDL.structs.keysym.unicode', 'event.keypressCharCode || key', 'i32') }}}
1029
1166
zoomSurface: function(src, x, y, smooth) {
1030
1167
var srcData = SDL.surfaces[src];
1031
var w = srcData.width*x;
1032
var h = srcData.height*y;
1033
var ret = SDL.makeSurface(w, h, srcData.flags, false, 'zoomSurface');
1168
var w = srcData.width * x;
1169
var h = srcData.height * y;
1170
var ret = SDL.makeSurface(Math.abs(w), Math.abs(h), srcData.flags, false, 'zoomSurface');
1034
1171
var dstData = SDL.surfaces[ret];
1035
dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
1172
if (x >= 0 && y >= 0) dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
1175
dstData.ctx.scale(x < 0 ? -1 : 1, y < 0 ? -1 : 1);
1176
dstData.ctx.drawImage(srcData.canvas, w < 0 ? w : 0, h < 0 ? h : 0, Math.abs(w), Math.abs(h));
1177
// XXX I think this should work according to the spec, but currently
1178
// fails on FF: dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
1179
dstData.ctx.restore();
1184
rotozoomSurface__deps: ['zoomSurface'],
1039
1185
rotozoomSurface: function(src, angle, zoom, smooth) {
1186
if (angle % 360 === 0) {
1187
return _zoomSurface(src, zoom, zoom, smooth);
1040
1189
var srcData = SDL.surfaces[src];
1041
1190
var w = srcData.width * zoom;
1042
1191
var h = srcData.height * zoom;
1153
1323
return flags; // We support JPG, PNG, TIF because browsers do
1156
IMG_Load__deps: ['SDL_LockSurface'],
1157
IMG_Load: function(filename) {
1158
filename = FS.standardizePath(Pointer_stringify(filename));
1159
if (filename[0] == '/') {
1160
// Convert the path to relative
1161
filename = filename.substr(1);
1163
var raw = Module["preloadedImages"][filename];
1165
if (raw === null) Module.printErr('Trying to reuse preloaded image, but freePreloadedMediaOnUse is set!');
1166
Runtime.warnOnce('Cannot find preloaded image ' + filename);
1169
if (Module['freePreloadedMediaOnUse']) {
1170
Module["preloadedImages"][filename] = null;
1172
var surf = SDL.makeSurface(raw.width, raw.height, 0, false, 'load:' + filename);
1173
var surfData = SDL.surfaces[surf];
1174
surfData.ctx.globalCompositeOperation = "copy";
1175
surfData.ctx.drawImage(raw, 0, 0, raw.width, raw.height, 0, 0, raw.width, raw.height);
1176
surfData.ctx.globalCompositeOperation = "source-over";
1177
// XXX SDL does not specify that loaded images must have available pixel data, in fact
1178
// there are cases where you just want to blit them, so you just need the hardware
1179
// accelerated version. However, code everywhere seems to assume that the pixels
1180
// are in fact available, so we retrieve it here. This does add overhead though.
1181
_SDL_LockSurface(surf);
1182
surfData.locked--; // The surface is not actually locked in this hack
1184
// After getting the pixel data, we can free the canvas and context if we do not need to do 2D canvas blitting
1185
surfData.canvas = surfData.ctx = null;
1326
IMG_Load_RW__deps: ['SDL_LockSurface', 'SDL_FreeRW'],
1327
IMG_Load_RW: function(rwopsID, freeSrc) {
1329
// stb_image integration support
1330
var cleanup = function() {
1331
if (rwops && freeSrc) _SDL_FreeRW(rwopsID);
1333
function addCleanup(func) {
1335
cleanup = function() {
1340
function callStbImage(func, params) {
1341
var x = Module['_malloc']({{{ QUANTUM_SIZE }}});
1342
var y = Module['_malloc']({{{ QUANTUM_SIZE }}});
1343
var comp = Module['_malloc']({{{ QUANTUM_SIZE }}});
1344
addCleanup(function() {
1347
Module['_free'](comp);
1348
if (data) Module['_stbi_image_free'](data);
1350
var data = Module['_' + func].apply(null, params.concat([x, y, comp, 0]));
1351
if (!data) return null;
1355
width: {{{ makeGetValue('x', 0, 'i32') }}},
1356
height: {{{ makeGetValue('y', 0, 'i32') }}},
1357
size: {{{ makeGetValue('x', 0, 'i32') }}} * {{{ makeGetValue('y', 0, 'i32') }}} * {{{ makeGetValue('comp', 0, 'i32') }}},
1358
bpp: {{{ makeGetValue('comp', 0, 'i32') }}}
1362
var rwops = SDL.rwops[rwopsID];
1363
if (rwops === undefined) {
1367
var filename = rwops.filename;
1368
if (filename === undefined) {
1370
var raw = callStbImage('stbi_load_from_memory', [rwops.bytes, rwops.count]);
1373
Runtime.warnOnce('Only file names that have been preloaded are supported for IMG_Load_RW. Consider using STB_IMAGE=1 if you want synchronous image decoding (see settings.js)');
1379
filename = PATH.resolve(filename);
1380
var raw = Module["preloadedImages"][filename];
1382
if (raw === null) Module.printErr('Trying to reuse preloaded image, but freePreloadedMediaOnUse is set!');
1384
var name = Module['_malloc'](filename.length+1);
1385
writeStringToMemory(filename, name);
1386
addCleanup(function() {
1387
Module['_free'](name);
1389
var raw = callStbImage('stbi_load', [name]);
1392
Runtime.warnOnce('Cannot find preloaded image ' + filename);
1393
Runtime.warnOnce('Cannot find preloaded image ' + filename + '. Consider using STB_IMAGE=1 if you want synchronous image decoding (see settings.js)');
1396
} else if (Module['freePreloadedMediaOnUse']) {
1397
Module["preloadedImages"][filename] = null;
1401
var surf = SDL.makeSurface(raw.width, raw.height, 0, false, 'load:' + filename);
1402
var surfData = SDL.surfaces[surf];
1403
surfData.ctx.globalCompositeOperation = "copy";
1405
surfData.ctx.drawImage(raw, 0, 0, raw.width, raw.height, 0, 0, raw.width, raw.height);
1407
var imageData = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
1409
imageData.data.set({{{ makeHEAPView('U8', 'raw.data', 'raw.data+raw.size') }}});
1410
} else if (raw.bpp == 3) {
1411
var pixels = raw.size/3;
1412
var data = imageData.data;
1413
var sourcePtr = raw.data;
1415
for (var i = 0; i < pixels; i++) {
1416
data[destPtr++] = {{{ makeGetValue('sourcePtr++', 0, 'i8', null, 1) }}};
1417
data[destPtr++] = {{{ makeGetValue('sourcePtr++', 0, 'i8', null, 1) }}};
1418
data[destPtr++] = {{{ makeGetValue('sourcePtr++', 0, 'i8', null, 1) }}};
1419
data[destPtr++] = 255;
1422
Module.printErr('cannot handle bpp ' + raw.bpp);
1425
surfData.ctx.putImageData(imageData, 0, 0);
1427
surfData.ctx.globalCompositeOperation = "source-over";
1428
// XXX SDL does not specify that loaded images must have available pixel data, in fact
1429
// there are cases where you just want to blit them, so you just need the hardware
1430
// accelerated version. However, code everywhere seems to assume that the pixels
1431
// are in fact available, so we retrieve it here. This does add overhead though.
1432
_SDL_LockSurface(surf);
1433
surfData.locked--; // The surface is not actually locked in this hack
1435
// After getting the pixel data, we can free the canvas and context if we do not need to do 2D canvas blitting
1436
surfData.canvas = surfData.ctx = null;
1189
1443
SDL_LoadBMP: 'IMG_Load',
1190
SDL_LoadBMP_RW: 'IMG_Load',
1191
IMG_Load_RW: 'IMG_Load',
1444
SDL_LoadBMP_RW: 'IMG_Load_RW',
1445
IMG_Load__deps: ['IMG_Load_RW', 'SDL_RWFromFile'],
1446
IMG_Load: function(filename){
1447
var rwops = _SDL_RWFromFile(filename);
1448
var result = _IMG_Load_RW(rwops, 1);
1324
1583
return 0; // error
1327
Mix_LoadWAV_RW: function(filename, freesrc) {
1328
filename = FS.standardizePath(Pointer_stringify(filename));
1329
var raw = Module["preloadedAudios"][filename];
1331
if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!');
1332
Runtime.warnOnce('Cannot find preloaded audio ' + filename);
1335
if (Module['freePreloadedMediaOnUse']) {
1336
Module["preloadedAudios"][filename] = null;
1586
Mix_LoadWAV_RW: function(rwopsID, freesrc) {
1587
var rwops = SDL.rwops[rwopsID];
1589
if (rwops === undefined)
1596
if (rwops.filename !== undefined) {
1597
filename = PATH.resolve(rwops.filename);
1598
var raw = Module["preloadedAudios"][filename];
1600
if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!');
1601
Runtime.warnOnce('Cannot find preloaded audio ' + filename);
1603
// see if we can read the file-contents from the in-memory FS
1604
var fileObject = FS.findObject(filename);
1606
if (fileObject === null) Module.printErr('Couldn\'t find file for: ' + filename);
1608
// We found the file. Load the contents
1609
if (fileObject && !fileObject.isFolder && fileObject.read) {
1610
bytes = fileObject.contents;
1615
if (Module['freePreloadedMediaOnUse']) {
1616
Module["preloadedAudios"][filename] = null;
1620
else if (rwops.bytes !== undefined) {
1621
bytes = HEAPU8.subarray(rwops.bytes, rwops.bytes + rwops.count);
1627
// Here, we didn't find a preloaded audio but we either were passed a filepath for
1628
// which we loaded bytes, or we were passed some bytes
1629
if (audio === undefined && bytes) {
1630
var blob = new Blob([new Uint8Array(bytes)], {type: rwops.mimetype});
1631
var url = URL.createObjectURL(blob);
1632
audio = new Audio();
1338
1636
var id = SDL.audios.length;
1339
1637
// Keep the loaded audio in the audio arrays, ready for playback
1340
1638
SDL.audios.push({
1341
1639
source: filename,
1676
1996
return Math.floor(fontData.size*0.02); // XXX
1999
TTF_FontHeight: function(font) {
2000
var fontData = SDL.fonts[font];
2001
return fontData.size;
2007
drawRectangle: function(surf, x1, y1, x2, y2, action, cssColor) {
2008
x1 = x1 << 16 >> 16;
2009
y1 = y1 << 16 >> 16;
2010
x2 = x2 << 16 >> 16;
2011
y2 = y2 << 16 >> 16;
2012
var surfData = SDL.surfaces[surf];
2013
assert(!surfData.locked); // but we could unlock and re-lock if we must..
2014
// TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc.
2015
var x = x1 < x2 ? x1 : x2;
2016
var y = y1 < y2 ? y1 : y2;
2017
var w = Math.abs(x2 - x1);
2018
var h = Math.abs(y2 - y1);
2019
surfData.ctx.save();
2020
surfData.ctx[action + 'Style'] = cssColor;
2021
surfData.ctx[action + 'Rect'](x, y, w, h);
2022
surfData.ctx.restore();
2024
drawLine: function(surf, x1, y1, x2, y2, cssColor) {
2025
x1 = x1 << 16 >> 16;
2026
y1 = y1 << 16 >> 16;
2027
x2 = x2 << 16 >> 16;
2028
y2 = y2 << 16 >> 16;
2029
var surfData = SDL.surfaces[surf];
2030
assert(!surfData.locked); // but we could unlock and re-lock if we must..
2031
surfData.ctx.save();
2032
surfData.ctx.strokeStyle = cssColor;
2033
surfData.ctx.beginPath();
2034
surfData.ctx.moveTo(x1, y1);
2035
surfData.ctx.lineTo(x2, y2);
2036
surfData.ctx.stroke();
2037
surfData.ctx.restore();
2039
// See http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
2040
drawEllipse: function(surf, x, y, rx, ry, action, cssColor) {
2043
rx = rx << 16 >> 16;
2044
ry = ry << 16 >> 16;
2045
var surfData = SDL.surfaces[surf];
2046
assert(!surfData.locked); // but we could unlock and re-lock if we must..
2048
surfData.ctx.save();
2049
surfData.ctx.beginPath();
2050
surfData.ctx.translate(x, y);
2051
surfData.ctx.scale(rx, ry);
2052
surfData.ctx.arc(0, 0, 1, 0, 2 * Math.PI);
2053
surfData.ctx.restore();
2055
surfData.ctx.save();
2056
surfData.ctx[action + 'Style'] = cssColor;
2057
surfData.ctx[action]();
2058
surfData.ctx.restore();
2060
// the gfx library uses something different from the rest of SDL...
2061
translateColorToCSSRGBA: function(rgba) {
2062
return 'rgba(' + (rgba>>>24) + ',' + (rgba>>16 & 0xff) + ',' + (rgba>>8 & 0xff) + ',' + (rgba&0xff) + ')';
2066
boxColor__deps: ['$SDL_gfx'],
2067
boxColor: function(surf, x1, y1, x2, y2, color) {
2068
return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL_gfx.translateColorToCSSRGBA(color));
2071
boxRGBA__deps: ['$SDL_gfx'],
1681
2072
boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
1682
var surfData = SDL.surfaces[surf];
1683
assert(!surfData.locked); // but we could unlock and re-lock if we must..
1684
// TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc.
1685
surfData.ctx.save();
1686
surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
1687
surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1);
1688
surfData.ctx.restore();
2073
return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a));
2076
rectangleColor__deps: ['$SDL_gfx'],
2077
rectangleColor: function(surf, x1, y1, x2, y2, color) {
2078
return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL_gfx.translateColorToCSSRGBA(color));
2081
rectangleRGBA__deps: ['$SDL_gfx'],
1691
2082
rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
1692
var surfData = SDL.surfaces[surf];
1693
assert(!surfData.locked); // but we could unlock and re-lock if we must..
1694
surfData.ctx.save();
1695
surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
1696
surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1);
1697
surfData.ctx.restore();
2083
return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a));
2086
ellipseColor__deps: ['$SDL_gfx'],
2087
ellipseColor: function(surf, x, y, rx, ry, color) {
2088
return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL_gfx.translateColorToCSSRGBA(color));
2091
ellipseRGBA__deps: ['$SDL_gfx'],
2092
ellipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) {
2093
return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a));
2096
filledEllipseColor__deps: ['$SDL_gfx'],
2097
filledEllipseColor: function(surf, x, y, rx, ry, color) {
2098
return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL_gfx.translateColorToCSSRGBA(color));
2101
filledEllipseRGBA__deps: ['$SDL_gfx'],
2102
filledEllipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) {
2103
return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a));
2106
lineColor__deps: ['$SDL_gfx'],
2107
lineColor: function(surf, x1, y1, x2, y2, color) {
2108
return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL_gfx.translateColorToCSSRGBA(color));
2111
lineRGBA__deps: ['$SDL_gfx'],
1700
2112
lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
1701
var surfData = SDL.surfaces[surf];
1702
assert(!surfData.locked); // but we could unlock and re-lock if we must..
1703
surfData.ctx.save();
1704
surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
1705
surfData.ctx.beginPath();
1706
surfData.ctx.moveTo(x1, y1);
1707
surfData.ctx.lineTo(x2, y2);
1708
surfData.ctx.stroke();
1709
surfData.ctx.restore();
2113
return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL.translateRGBAToCSSRGBA(r, g, b, a));
1712
2116
pixelRGBA__deps: ['boxRGBA'],
1791
SDL_SetGammaRamp: function (redTable, greenTable, blueTable) {
2195
SDL_SetGammaRamp: function(redTable, greenTable, blueTable) {
2201
SDL_NumJoysticks: function() { return 0; },
2203
SDL_JoystickName: function(deviceIndex) { return 0; },
2205
SDL_JoystickOpen: function(deviceIndex) { return 0; },
2207
SDL_JoystickOpened: function(deviceIndex) { return 0; },
2209
SDL_JoystickIndex: function(joystick) { return 0; },
2211
SDL_JoystickNumAxes: function(joystick) { return 0; },
2213
SDL_JoystickNumBalls: function(joystick) { return 0; },
2215
SDL_JoystickNumHats: function(joystick) { return 0; },
2217
SDL_JoystickNumButtons: function(joystick) { return 0; },
2219
SDL_JoystickUpdate: function() {},
2221
SDL_JoystickEventState: function(state) { return 0; },
2223
SDL_JoystickGetAxis: function(joystick, axis) { return 0; },
2225
SDL_JoystickGetHat: function(joystick, hat) { return 0; },
2227
SDL_JoystickGetBall: function(joystick, ball, dxptr, dyptr) { return -1; },
2229
SDL_JoystickGetButton: function(joystick, button) { return 0; },
2231
SDL_JoystickClose: function(joystick) {},
1797
2235
SDL_InitSubSystem: function(flags) { return 0 },
1799
SDL_NumJoysticks: function() { return 0 },
2237
SDL_RWFromConstMem: function(mem, size) {
2238
var id = SDL.rwops.length; // TODO: recycle ids when they are null
2239
SDL.rwops.push({ bytes: mem, count: size });
2242
SDL_RWFromMem: 'SDL_RWFromConstMem',
1801
SDL_RWFromFile: function(filename, mode) {
1802
return filename; // XXX We just forward the filename
2244
SDL_RWFromFile: function(_name, mode) {
2245
var id = SDL.rwops.length; // TODO: recycle ids when they are null
2246
var name = Pointer_stringify(_name)
2247
SDL.rwops.push({ filename: name, mimetype: Browser.getMimetype(name) });
2251
SDL_FreeRW: function(rwopsID) {
2252
SDL.rwops[rwopsID] = null;
2253
while (SDL.rwops.length > 0 && SDL.rwops[SDL.rwops.length-1] === null) {
1805
2258
SDL_EnableUNICODE: function(on) {