From d2d513b2d9ec6003fba1581be575597904a63202 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Fri, 22 Jan 2016 21:46:16 -0500 Subject: [PATCH 01/16] Start writing the shim Seems that our best bet is to forward the shared memory frame buffer references from the core emulation thread to the worker thread rather than create another copy operation that could defer graphics from being on screen for another 16 ms. --- IodineGBA/core/graphics/RendererShim.js | 68 +++++++++++++++++++++++++++++++++ user_scripts/IodineGBAWorkerGlueCode.js | 4 -- 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 IodineGBA/core/graphics/RendererShim.js diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js new file mode 100644 index 0000000..7083609 --- /dev/null +++ b/IodineGBA/core/graphics/RendererShim.js @@ -0,0 +1,68 @@ +"use strict"; +/* + Copyright (C) 2012-2016 Grant Galitz + + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { + if (!window.SharedArrayBuffer || !Atomics) { + return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); + } + else { + return new GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS); + } + } + function GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS) { + this.coreExposed = coreExposed; + this.initializeWorker(); + this.initializeBuffers(); + this.shareBuffers(skippingBIOS); + } + var tempvar = document.getElementsByTagName("script"); + GameBoyAdvanceGraphicsRendererShim.prototype.filepath = tempvar[tempvar.length-1].src; + GameBoyAdvanceGraphicsRendererShim.prototype.initializeWorker = function () { + this.worker = new Worker(this.filepath.substring(0, (this.filepath.length | 0) - 3) + "Worker.js"); + } + GameBoyAdvanceGraphicsRendererShim.prototype.initializeBuffers = function () { + //Graphics Buffers: + this.gfxCommandBuffer = getSharedInt32Array(0x40000); + this.gfxCommandCounters = getSharedInt32Array(2); + } + GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function (skippingBIOS) { + skippingBIOS = !!skippingBIOS; + this.worker.postMessage({ + skippingBIOS:!!skippingBIOS, + gfxBuffers:gfxBuffers, + gfxCounters:gfxCounters, + gfxCommandBuffer:this.gfxCommandBuffer, + gfxCommandCounters:this.gfxCommandCounters + }, [ + gfxBuffers[0].buffer, + gfxBuffers[1].buffer, + gfxCounters.buffer, + this.gfxCommandBuffer.buffer, + this.gfxCommandCounters.buffer + ]); + } +GameBoyAdvanceGraphicsRendererShim.prototype.pushCommand = function (command, data) { + command = command | 0; + data = data | 0; + //Load the write counter value: + var end = this.gfxCommandCounters[1] | 0; + //Block while full: + Atomics.futexWait(this.gfxCommandCounters, 0, ((end | 0) - 0x40000) | 0); + //Get the write offset into the ring buffer: + var endCorrected = end & 0x3FFFF; + //Push command into buffer: + this.gfxCommandBuffer[endCorrected | 0] = command | 0; + //Push data into buffer: + this.gfxCommandBuffer[endCorrected | 1] = data | 0; + //Update the cross thread buffering count: + end = ((end | 0) + 2) | 0; + //Atomic store to commit writes to memory: + Atomics.store(this.gfxCommandCounters, 1, end | 0); +} diff --git a/user_scripts/IodineGBAWorkerGlueCode.js b/user_scripts/IodineGBAWorkerGlueCode.js index c19b4ba..99610c3 100644 --- a/user_scripts/IodineGBAWorkerGlueCode.js +++ b/user_scripts/IodineGBAWorkerGlueCode.js @@ -42,10 +42,6 @@ IodineGBAWorkerShim.prototype.sendMessageDouble = function (eventCode, eventData eventCode = eventCode | 0; this.worker.postMessage({messageID:eventCode, payload:eventData}); } -IodineGBAWorkerShim.prototype.sendBufferBack = function (eventCode, eventData) { - eventCode = eventCode | 0; - this.worker.postMessage({messageID:eventCode, payload:eventData}, [eventData.buffer]); -} IodineGBAWorkerShim.prototype.play = function () { this.sendMessageSingle(0); } From 9eb01b5199d5203ad480f8f4ca238040730f357d Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Fri, 22 Jan 2016 21:57:53 -0500 Subject: [PATCH 02/16] scan line increment command Also I still am trying to figure out what the best command buffer queue size will turn out to be. --- IodineGBA/core/graphics/RendererProxy.js | 12 ++++++------ IodineGBA/core/graphics/RendererShim.js | 10 +++++++--- index.html | 3 ++- user_scripts/IodineGBAWorkerGlueCodeWorker.js | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/IodineGBA/core/graphics/RendererProxy.js b/IodineGBA/core/graphics/RendererProxy.js index 8ab9083..6d4f916 100644 --- a/IodineGBA/core/graphics/RendererProxy.js +++ b/IodineGBA/core/graphics/RendererProxy.js @@ -1,11 +1,11 @@ "use strict"; /* - Copyright (C) 2012-2015 Grant Galitz - + Copyright (C) 2012-2016 Grant Galitz + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function GameBoyAdvanceRendererProxy(IOCore) { @@ -17,7 +17,7 @@ GameBoyAdvanceRendererProxy.prototype.initialize = function () { this.IOData16 = getUint16View(this.IOData8); this.IOData32 = getInt32View(this.IOData8); this.gfxState = this.IOCore.gfxState; - this.renderer = new GameBoyAdvanceGraphicsRenderer(this.IOCore.coreExposed, !!this.IOCore.SKIPBoot); + this.renderer = getGameBoyAdvanceGraphicsRenderer(this.IOCore.coreExposed, !!this.IOCore.SKIPBoot); } GameBoyAdvanceRendererProxy.prototype.incrementScanLineQueue = function () { this.renderer.incrementScanLineQueue(); @@ -1224,4 +1224,4 @@ GameBoyAdvanceRendererProxy.prototype.readPalette8 = function (address) { address = address | 0; var data = this.renderer.readPalette8(address | 0) | 0; return data | 0; -} \ No newline at end of file +} diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 7083609..5062d37 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -29,7 +29,7 @@ } GameBoyAdvanceGraphicsRendererShim.prototype.initializeBuffers = function () { //Graphics Buffers: - this.gfxCommandBuffer = getSharedInt32Array(0x40000); + this.gfxCommandBuffer = getSharedInt32Array(0x80000); this.gfxCommandCounters = getSharedInt32Array(2); } GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function (skippingBIOS) { @@ -54,9 +54,9 @@ GameBoyAdvanceGraphicsRendererShim.prototype.pushCommand = function (command, da //Load the write counter value: var end = this.gfxCommandCounters[1] | 0; //Block while full: - Atomics.futexWait(this.gfxCommandCounters, 0, ((end | 0) - 0x40000) | 0); + Atomics.futexWait(this.gfxCommandCounters, 0, ((end | 0) - 0x80000) | 0); //Get the write offset into the ring buffer: - var endCorrected = end & 0x3FFFF; + var endCorrected = end & 0x7FFFF; //Push command into buffer: this.gfxCommandBuffer[endCorrected | 0] = command | 0; //Push data into buffer: @@ -66,3 +66,7 @@ GameBoyAdvanceGraphicsRendererShim.prototype.pushCommand = function (command, da //Atomic store to commit writes to memory: Atomics.store(this.gfxCommandCounters, 1, end | 0); } +GameBoyAdvanceGraphicsRendererShim.prototype.incrementScanLineQueue = function () { + //Increment scan line command: + this.pushCommand(0, 0); +} diff --git a/index.html b/index.html index ead1bbd..83933be 100644 --- a/index.html +++ b/index.html @@ -28,6 +28,7 @@ + @@ -114,4 +115,4 @@ - \ No newline at end of file + diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index d14d983..4463631 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -1,6 +1,6 @@ "use strict"; /* - Copyright (C) 2012-2015 Grant Galitz + Copyright (C) 2012-2016 Grant Galitz 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: From dace8cf00c61e605dc7eca2d7fb8ab11c028f973 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Fri, 22 Jan 2016 22:43:00 -0500 Subject: [PATCH 03/16] Add import entry --- user_scripts/IodineGBAWorkerGlueCodeWorker.js | 1 + 1 file changed, 1 insertion(+) diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index 4463631..aa79494 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -32,6 +32,7 @@ importScripts("../IodineGBA/core/CPU/ARM.js"); importScripts("../IodineGBA/core/CPU/THUMB.js"); importScripts("../IodineGBA/core/CPU/CPSR.js"); importScripts("../IodineGBA/core/graphics/Renderer.js"); +importScripts("../IodineGBA/core/graphics/RendererShim.js"); importScripts("../IodineGBA/core/graphics/RendererProxy.js"); importScripts("../IodineGBA/core/graphics/BGTEXT.js"); importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); From faf611f198b657310b010098b0c16d4610556d41 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 00:36:50 -0500 Subject: [PATCH 04/16] Move blitter responsibility to renderer core Will allow shimming and is cleaner in api terms. --- IodineGBA/core/Emulator.js | 38 ++---------------------------------- IodineGBA/core/graphics/Renderer.js | 39 ++++++++++++++++++++++++++++++------- README.md | 34 ++++++++++++++++---------------- 3 files changed, 51 insertions(+), 60 deletions(-) diff --git a/IodineGBA/core/Emulator.js b/IodineGBA/core/Emulator.js index 69f6b3a..b0cd15c 100644 --- a/IodineGBA/core/Emulator.js +++ b/IodineGBA/core/Emulator.js @@ -21,20 +21,12 @@ function GameBoyAdvanceEmulator() { }; this.audioFound = 0; //Do we have audio output sink found yet? this.emulatorStatus = 0x10; //{paused, saves loaded, fault found, loaded} - this.offscreenWidth = 240; //Width of the GBA screen. - this.offscreenHeight = 160; //Height of the GBA screen. this.BIOS = []; //Initialize BIOS as not existing. this.ROM = []; //Initialize BIOS as not existing. - //Cache some frame buffer lengths: - this.offscreenRGBCount = ((this.offscreenWidth | 0) * (this.offscreenHeight | 0) * 3) | 0; - //Graphics buffers to generate in advance: - this.frameBuffer = getInt32Array(this.offscreenRGBCount | 0); //The internal buffer to composite to. - this.swizzledFrame = getUint8Array(this.offscreenRGBCount | 0); //The swizzled output buffer that syncs to the internal framebuffer on v-blank. this.audioUpdateState = 1; //Do we need to update the sound core with new info? this.saveExportHandler = null; //Save export handler attached by GUI. this.saveImportHandler = null; //Save import handler attached by GUI. this.speedCallback = null; //Speed report handler attached by GUI. - this.graphicsHandle = null; //Graphics blitter handler attached by GUI. this.timerIntervalRate = 4; //How often the emulator core is called into (in milliseconds). this.lastTimestamp = 0; //Track the last time given in milliseconds. this.dynamicSpeedRefresh = false; //Whether speed is allowed to be changed dynamically in the current cycle. @@ -47,10 +39,7 @@ GameBoyAdvanceEmulator.prototype.generateCoreExposed = function () { "outputAudio":function (l, r) { parentObj.outputAudio(l, r); }, - "frameBuffer":parentObj.frameBuffer, - "prepareFrame":function () { - parentObj.prepareFrame(); - } + graphicsHandle:null } } GameBoyAdvanceEmulator.prototype.play = function () { @@ -270,7 +259,7 @@ GameBoyAdvanceEmulator.prototype.keyUp = function (keyReleased) { } GameBoyAdvanceEmulator.prototype.attachGraphicsFrameHandler = function (handler) { if (typeof handler == "object") { - this.graphicsHandle = handler; + this.coreExposed.graphicsHandle = handler; } } GameBoyAdvanceEmulator.prototype.attachAudioHandler = function (mixerInputHandler) { @@ -278,29 +267,6 @@ GameBoyAdvanceEmulator.prototype.attachAudioHandler = function (mixerInputHandle this.audio = mixerInputHandler; } } -GameBoyAdvanceEmulator.prototype.swizzleFrameBuffer = function () { - //Convert our dirty 15-bit (15-bit, with internal render flags above it) framebuffer to an 8-bit buffer with separate indices for the RGB channels: - var bufferIndex = 0; - for (var canvasIndex = 0; (canvasIndex | 0) < (this.offscreenRGBCount | 0); bufferIndex = ((bufferIndex | 0) + 1) | 0) { - this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x1F) << 3; //Red - canvasIndex = ((canvasIndex | 0) + 1) | 0; - this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x3E0) >> 2; //Green - canvasIndex = ((canvasIndex | 0) + 1) | 0; - this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x7C00) >> 7; //Blue - canvasIndex = ((canvasIndex | 0) + 1) | 0; - } -} -GameBoyAdvanceEmulator.prototype.prepareFrame = function () { - //Copy the internal frame buffer to the output buffer: - this.swizzleFrameBuffer(); - this.requestDraw(); -} -GameBoyAdvanceEmulator.prototype.requestDraw = function () { - if (this.graphicsHandle) { - //We actually updated the graphics internally, so copy out: - this.graphicsHandle.copyBuffer(this.swizzledFrame); - } -} GameBoyAdvanceEmulator.prototype.enableAudio = function () { if ((this.audioFound | 0) == 0 && this.audio) { this.audioFound = 1; //Set audio to 'found' by default. diff --git a/IodineGBA/core/graphics/Renderer.js b/IodineGBA/core/graphics/Renderer.js index 6cf7991..93cb87f 100644 --- a/IodineGBA/core/graphics/Renderer.js +++ b/IodineGBA/core/graphics/Renderer.js @@ -1,11 +1,11 @@ "use strict"; /* Copyright (C) 2012-2015 Grant Galitz - + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { @@ -30,7 +30,8 @@ if (__VIEWS_SUPPORTED__) { this.paletteRAM32 = getInt32View(this.paletteRAM); this.buffer = getInt32Array(0x680); this.lineBuffer = getInt32ViewCustom(this.buffer, 0, 240); - this.frameBuffer = this.coreExposed.frameBuffer; + this.frameBuffer = getInt32Array(38400); //The internal buffer to composite to. + this.swizzledFrame = getUint8Array(115200); //The swizzled output buffer that syncs to the internal framebuffer on v-blank. this.totalLinesPassed = 0; this.queuedScanLines = 0; this.lastUnrenderedLine = 0; @@ -55,7 +56,8 @@ else { this.paletteRAM16 = getUint16View(this.paletteRAM); this.paletteRAM32 = getInt32View(this.paletteRAM); this.buffer = getInt32Array(0x680); - this.frameBuffer = this.coreExposed.frameBuffer; + this.frameBuffer = getInt32Array(38400); //The internal buffer to composite to. + this.swizzledFrame = getUint8Array(115200); //The swizzled output buffer that syncs to the internal framebuffer on v-blank. this.totalLinesPassed = 0; this.queuedScanLines = 0; this.lastUnrenderedLine = 0; @@ -120,7 +122,30 @@ GameBoyAdvanceGraphicsRenderer.prototype.ensureFraming = function () { //Make sure our gfx are up-to-date: this.graphicsJITVBlank(); //Draw the frame: - this.coreExposed.prepareFrame(); + this.prepareFrame(); + } +} +GameBoyAdvanceGraphicsRenderer.prototype.swizzleFrameBuffer = function () { + //Convert our dirty 15-bit (15-bit, with internal render flags above it) framebuffer to an 8-bit buffer with separate indices for the RGB channels: + var bufferIndex = 0; + for (var canvasIndex = 0; (canvasIndex | 0) < 115200; bufferIndex = ((bufferIndex | 0) + 1) | 0) { + this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x1F) << 3; //Red + canvasIndex = ((canvasIndex | 0) + 1) | 0; + this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x3E0) >> 2; //Green + canvasIndex = ((canvasIndex | 0) + 1) | 0; + this.swizzledFrame[canvasIndex | 0] = (this.frameBuffer[bufferIndex | 0] & 0x7C00) >> 7; //Blue + canvasIndex = ((canvasIndex | 0) + 1) | 0; + } +} +GameBoyAdvanceGraphicsRenderer.prototype.prepareFrame = function () { + //Copy the internal frame buffer to the output buffer: + this.swizzleFrameBuffer(); + this.requestDraw(); +} +GameBoyAdvanceGraphicsRenderer.prototype.requestDraw = function () { + if (this.coreExposed.graphicsHandle) { + //We actually updated the graphics internally, so copy out: + this.coreExposed.graphicsHandle.copyBuffer(this.swizzledFrame); } } GameBoyAdvanceGraphicsRenderer.prototype.graphicsJIT = function () { @@ -1385,4 +1410,4 @@ GameBoyAdvanceGraphicsRenderer.prototype.writePalette16Color = function (address } GameBoyAdvanceGraphicsRenderer.prototype.readPalette8 = function (address) { return this.paletteRAM[address & 0x3FF] | 0; -} \ No newline at end of file +} diff --git a/README.md b/README.md index c2899a3..18e26b7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ JavaScript GameBoy Advance Emulator ================================= -**Copyright (C) 2010 - 2015 Grant Galitz** +**Copyright (C) 2010 - 2016 Grant Galitz** A GameBoy Advance emulator that utilizes HTML5 canvas and JavaScript audio APIs to provide a full emulation of the console. @@ -20,39 +20,39 @@ Screenshots * **Pokemon Ruby:** ![Pokemon Ruby](http://i.imgur.com/OO9XCRk.png "Pokemon Ruby") - + * **Super Mario Advance:** - + ![Super Mario Advance](http://i.imgur.com/ewhtAJg.png "Super Mario Advance") * **Mario & Luigi Superstar Saga:** - + ![Mario & Luigi Superstar Saga](http://i.imgur.com/Do8TbsMh.png "Mario & Luigi Superstar Saga") - + * **Mario Kart Advance:** - + ![Mario Kart Advance](http://i.imgur.com/37xx3yPh.png “Super Circuit”) - + * **Earthworm Jim:** - + ![Earthworm Jim](http://i.imgur.com/Ip3MHzmh.png “Earthworm Jim”) - + * **Advance Wars:** - + ![Advance Wars](http://i.imgur.com/akKzA97h.png “Advance Wars”) - + * **Wario Land 4:** - + ![Wario Land 4](http://i.imgur.com/eaDqCxuh.png “Wario Land 4”) - + * **Golden Sun:** - + ![Golden Sun](http://i.imgur.com/EctuZxo.png “Golden Sun”) * **Game & Watch Gallery 4:** - + ![Game & Watch Gallery 4](http://i.imgur.com/awLMWsIh.png “Game & Watch Gallery 4”) - + * **GBA BIOS:** - ![GBA BIOS](http://i.imgur.com/kzxGoAHh.png “GBA BIOS”) \ No newline at end of file + ![GBA BIOS](http://i.imgur.com/kzxGoAHh.png “GBA BIOS”) From fbece9631c830e962995429c7401fb321e5f6f8f Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 03:26:32 -0500 Subject: [PATCH 05/16] Infrastructure update --- IodineGBA/core/Emulator.js | 48 ++++++++++++++++++++++++-- IodineGBA/core/graphics/Renderer.js | 2 +- IodineGBA/core/graphics/RendererShim.js | 49 +++++++++++++++++++++------ user_scripts/IodineGBAWorkerGlueCodeWorker.js | 1 + 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/IodineGBA/core/Emulator.js b/IodineGBA/core/Emulator.js index b0cd15c..930f71f 100644 --- a/IodineGBA/core/Emulator.js +++ b/IodineGBA/core/Emulator.js @@ -27,6 +27,9 @@ function GameBoyAdvanceEmulator() { this.saveExportHandler = null; //Save export handler attached by GUI. this.saveImportHandler = null; //Save import handler attached by GUI. this.speedCallback = null; //Speed report handler attached by GUI. + this.startCallbacks = []; //Some jobs to run at iteration head. + this.endCallbacks = []; //Some jobs to run at iteration end. + this.terminationCallbacks = []; //Some jobs to run if the emulation core is killed. this.timerIntervalRate = 4; //How often the emulator core is called into (in milliseconds). this.lastTimestamp = 0; //Track the last time given in milliseconds. this.dynamicSpeedRefresh = false; //Whether speed is allowed to be changed dynamically in the current cycle. @@ -36,10 +39,19 @@ function GameBoyAdvanceEmulator() { GameBoyAdvanceEmulator.prototype.generateCoreExposed = function () { var parentObj = this; this.coreExposed = { - "outputAudio":function (l, r) { + outputAudio:function (l, r) { parentObj.outputAudio(l, r); }, - graphicsHandle:null + graphicsHandle:null, + appendStartIterationSync:function (callback) { + parentObj.startCallbacks.push(callback); + }, + appendEndIterationSync:function (callback) { + parentObj.endCallbacks.push(callback); + }, + appendTerminationSync:function (callback) { + parentObj.terminationCallbacks.push(callback); + } } } GameBoyAdvanceEmulator.prototype.play = function () { @@ -93,11 +105,41 @@ GameBoyAdvanceEmulator.prototype.iterationStartSequence = function () { this.emulatorStatus = this.emulatorStatus | 0x2; //If the end routine doesn't unset this, then we are marked as having crashed. this.audioUnderrunAdjustment(); //If audio is enabled, look to see how much we should overclock by to maintain the audio buffer. this.audioPushNewState(); //Check to see if we need to update the audio core for any output changes. + this.runStartJobs(); //Run various callbacks assigned from internal components. } GameBoyAdvanceEmulator.prototype.iterationEndSequence = function () { this.emulatorStatus = this.emulatorStatus & 0x1D; //If core did not throw while running, unset the fatal error flag. this.clockCyclesSinceStart = ((this.clockCyclesSinceStart | 0) + (this.CPUCyclesTotal | 0)) | 0; //Accumulate tracking. this.submitAudioBuffer(); //Flush audio buffer to output. + this.runEndJobs(); //Run various callbacks assigned from internal components. +} +GameBoyAdvanceEmulator.prototype.runStartJobs = function () { + var length = this.startCallbacks.length | 0; + //Loop through all jobs: + for (var index = 0; (index | 0) < (length | 0); index = ((index | 0) + 1) | 0) { + //Run job: + this.startCallbacks[index | 0](); + } +} +GameBoyAdvanceEmulator.prototype.runEndJobs = function () { + var length = this.endCallbacks.length | 0; + //Loop through all jobs: + for (var index = 0; (index | 0) < (length | 0); index = ((index | 0) + 1) | 0) { + //Run job: + this.endCallbacks[index | 0](); + } +} +GameBoyAdvanceEmulator.prototype.runTerminationJobs = function () { + var length = this.terminationCallbacks.length | 0; + //Loop through all jobs: + for (var index = 0; (index | 0) < (length | 0); index = ((index | 0) + 1) | 0) { + //Run job: + this.terminationCallbacks[index | 0](); + } + //Remove old jobs: + this.startCallbacks = []; + this.endCallbacks = []; + this.terminationCallbacks = []; } GameBoyAdvanceEmulator.prototype.attachROM = function (ROM) { this.stop(); @@ -242,6 +284,8 @@ GameBoyAdvanceEmulator.prototype.calculateSpeedPercentage = function () { } } GameBoyAdvanceEmulator.prototype.initializeCore = function () { + //Wrap up any old internal instance callbacks: + this.runTerminationJobs(); //Setup a new instance of the i/o core: this.IOCore = new GameBoyAdvanceIO(this.settings.SKIPBoot, this.coreExposed, this.BIOS, this.ROM); } diff --git a/IodineGBA/core/graphics/Renderer.js b/IodineGBA/core/graphics/Renderer.js index 93cb87f..161efb1 100644 --- a/IodineGBA/core/graphics/Renderer.js +++ b/IodineGBA/core/graphics/Renderer.js @@ -1,6 +1,6 @@ "use strict"; /* - Copyright (C) 2012-2015 Grant Galitz + Copyright (C) 2012-2016 Grant Galitz 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: diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 5062d37..2ef765f 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -9,12 +9,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { - if (!window.SharedArrayBuffer || !Atomics) { + //if (!window.SharedArrayBuffer || !Atomics) { return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); - } + /*} else { return new GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS); - } + }*/ } function GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS) { this.coreExposed = coreExposed; @@ -31,10 +31,31 @@ //Graphics Buffers: this.gfxCommandBuffer = getSharedInt32Array(0x80000); this.gfxCommandCounters = getSharedInt32Array(2); + this.start = 0; + this.end = 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.appendAtomicSync = function () { + //Command buffer counters get synchronized with emulator runtime head/end for efficiency: + var parentObj = this; + this.coreExposed.appendStartIterationSync(function () { + //Load command buffer reader counter value: + parentObj.start = Atomics.load(parentObj.gfxCommandCounters, 0) | 0; + }); + this.coreExposed.appendEndIterationSync(function () { + //Store command buffer writer counter value: + Atomics.store(parentObj.gfxCommandCounters, 1, parentObj.end | 0); + //Tell consumer thread to check command buffer: + this.worker.postMessage({messageID:0}); + }); + this.coreExposed.appendTerminationSync(function () { + //Core instance being replaced, kill the worker thread: + this.worker.terminate(); + }); } GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function (skippingBIOS) { skippingBIOS = !!skippingBIOS; this.worker.postMessage({ + messageID:1, skippingBIOS:!!skippingBIOS, gfxBuffers:gfxBuffers, gfxCounters:gfxCounters, @@ -51,22 +72,30 @@ GameBoyAdvanceGraphicsRendererShim.prototype.pushCommand = function (command, data) { command = command | 0; data = data | 0; - //Load the write counter value: - var end = this.gfxCommandCounters[1] | 0; //Block while full: - Atomics.futexWait(this.gfxCommandCounters, 0, ((end | 0) - 0x80000) | 0); + this.blockIfCommandBufferFull(); //Get the write offset into the ring buffer: - var endCorrected = end & 0x7FFFF; + var endCorrected = this.end & 0x7FFFF; //Push command into buffer: this.gfxCommandBuffer[endCorrected | 0] = command | 0; //Push data into buffer: this.gfxCommandBuffer[endCorrected | 1] = data | 0; //Update the cross thread buffering count: - end = ((end | 0) + 2) | 0; - //Atomic store to commit writes to memory: - Atomics.store(this.gfxCommandCounters, 1, end | 0); + this.end = ((this.end | 0) + 2) | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.blockIfCommandBufferFull = function () { + if ((this.start | 0) == (((this.end | 0) - 0x80000) | 0)) { + //Wait for consumer thread: + Atomics.futexWait(this.gfxCommandCounters, 0, ((this.end | 0) - 0x80000) | 0); + //Reload reader counter value: + this.start = Atomics.load(this.gfxCommandCounters, 0) | 0; + } } GameBoyAdvanceGraphicsRendererShim.prototype.incrementScanLineQueue = function () { //Increment scan line command: this.pushCommand(0, 0); } +GameBoyAdvanceGraphicsRendererShim.prototype.ensureFraming = function () { + //Vertical blank synchronization command: + this.pushCommand(0, 1); +} diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index aa79494..f8ea95d 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -141,6 +141,7 @@ self.onmessage = function (event) { } } var graphicsFrameHandler = { + //Function only called if graphics is THIS thread: copyBuffer:function (swizzledFrame) { //Push a frame of graphics to the blitter handle: //Load the counter values: From 8044160bb6c15396ce3facec55e899c0b7da1a6a Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 03:39:10 -0500 Subject: [PATCH 06/16] eh --- IodineGBA/core/graphics/RendererShim.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 2ef765f..7dbc3e6 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -22,10 +22,8 @@ this.initializeBuffers(); this.shareBuffers(skippingBIOS); } - var tempvar = document.getElementsByTagName("script"); - GameBoyAdvanceGraphicsRendererShim.prototype.filepath = tempvar[tempvar.length-1].src; GameBoyAdvanceGraphicsRendererShim.prototype.initializeWorker = function () { - this.worker = new Worker(this.filepath.substring(0, (this.filepath.length | 0) - 3) + "Worker.js"); + this.worker = new Worker("RendererShimWorker.js"); } GameBoyAdvanceGraphicsRendererShim.prototype.initializeBuffers = function () { //Graphics Buffers: From 2353151818dafe56fbce78a51baaecc6e7ffc836 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 04:30:02 -0500 Subject: [PATCH 07/16] need to make the other side of the thread --- IodineGBA/core/graphics/RendererShimWorker.js | 22 ++++++++++++++++++++++ user_scripts/IodineGBAWorkerGlueCodeWorker.js | 12 ------------ 2 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 IodineGBA/core/graphics/RendererShimWorker.js diff --git a/IodineGBA/core/graphics/RendererShimWorker.js b/IodineGBA/core/graphics/RendererShimWorker.js new file mode 100644 index 0000000..a3c4b8b --- /dev/null +++ b/IodineGBA/core/graphics/RendererShimWorker.js @@ -0,0 +1,22 @@ +"use strict"; +/* + Copyright (C) 2012-2016 Grant Galitz + + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +importScripts("../IodineGBA/core/graphics/Renderer.js"); +importScripts("../IodineGBA/core/graphics/RendererProxy.js"); +importScripts("../IodineGBA/core/graphics/BGTEXT.js"); +importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); +importScripts("../IodineGBA/core/graphics/BGMatrix.js"); +importScripts("../IodineGBA/core/graphics/AffineBG.js"); +importScripts("../IodineGBA/core/graphics/ColorEffects.js"); +importScripts("../IodineGBA/core/graphics/Mosaic.js"); +importScripts("../IodineGBA/core/graphics/OBJ.js"); +importScripts("../IodineGBA/core/graphics/OBJWindow.js"); +importScripts("../IodineGBA/core/graphics/Window.js"); +importScripts("../IodineGBA/core/graphics/Compositor.js"); diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index f8ea95d..8d859fe 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -31,19 +31,7 @@ importScripts("../IodineGBA/core/sound/Channel4.js"); importScripts("../IodineGBA/core/CPU/ARM.js"); importScripts("../IodineGBA/core/CPU/THUMB.js"); importScripts("../IodineGBA/core/CPU/CPSR.js"); -importScripts("../IodineGBA/core/graphics/Renderer.js"); importScripts("../IodineGBA/core/graphics/RendererShim.js"); -importScripts("../IodineGBA/core/graphics/RendererProxy.js"); -importScripts("../IodineGBA/core/graphics/BGTEXT.js"); -importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); -importScripts("../IodineGBA/core/graphics/BGMatrix.js"); -importScripts("../IodineGBA/core/graphics/AffineBG.js"); -importScripts("../IodineGBA/core/graphics/ColorEffects.js"); -importScripts("../IodineGBA/core/graphics/Mosaic.js"); -importScripts("../IodineGBA/core/graphics/OBJ.js"); -importScripts("../IodineGBA/core/graphics/OBJWindow.js"); -importScripts("../IodineGBA/core/graphics/Window.js"); -importScripts("../IodineGBA/core/graphics/Compositor.js"); importScripts("../IodineGBA/core/memory/DMA0.js"); importScripts("../IodineGBA/core/memory/DMA1.js"); importScripts("../IodineGBA/core/memory/DMA2.js"); From aa0cab690f0c6408f5efe314d157284e76856e07 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 04:56:47 -0500 Subject: [PATCH 08/16] typo --- IodineGBA/core/graphics/RendererShim.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 7dbc3e6..602925d 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -43,11 +43,11 @@ //Store command buffer writer counter value: Atomics.store(parentObj.gfxCommandCounters, 1, parentObj.end | 0); //Tell consumer thread to check command buffer: - this.worker.postMessage({messageID:0}); + parentObj.worker.postMessage({messageID:0}); }); this.coreExposed.appendTerminationSync(function () { //Core instance being replaced, kill the worker thread: - this.worker.terminate(); + parentObj.worker.terminate(); }); } GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function (skippingBIOS) { From 893ce663b2565e897455f859e8885c24031b3784 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 06:23:27 -0500 Subject: [PATCH 09/16] adding some intercepts --- IodineGBA/core/graphics/Renderer.js | 4 + IodineGBA/core/graphics/RendererProxy.js | 4 +- IodineGBA/core/graphics/RendererShim.js | 660 +++++++++++++++++++++++++- IodineGBA/core/graphics/RendererShimWorker.js | 1 + 4 files changed, 667 insertions(+), 2 deletions(-) diff --git a/IodineGBA/core/graphics/Renderer.js b/IodineGBA/core/graphics/Renderer.js index 161efb1..e78d1e7 100644 --- a/IodineGBA/core/graphics/Renderer.js +++ b/IodineGBA/core/graphics/Renderer.js @@ -1369,12 +1369,15 @@ GameBoyAdvanceGraphicsRenderer.prototype.writeOAM32 = function (address, data) { this.objRenderer.writeOAM32(address >> 2, data | 0); } GameBoyAdvanceGraphicsRenderer.prototype.readOAM = function (address) { + address = address | 0; return this.objRenderer.readOAM(address | 0) | 0; } GameBoyAdvanceGraphicsRenderer.prototype.readOAM16 = function (address) { + address = address | 0; return this.objRenderer.readOAM16(address | 0) | 0; } GameBoyAdvanceGraphicsRenderer.prototype.readOAM32 = function (address) { + address = address | 0; return this.objRenderer.readOAM32(address | 0) | 0; } GameBoyAdvanceGraphicsRenderer.prototype.writePalette256Color = function (address, palette) { @@ -1409,5 +1412,6 @@ GameBoyAdvanceGraphicsRenderer.prototype.writePalette16Color = function (address } } GameBoyAdvanceGraphicsRenderer.prototype.readPalette8 = function (address) { + address = address | 0; return this.paletteRAM[address & 0x3FF] | 0; } diff --git a/IodineGBA/core/graphics/RendererProxy.js b/IodineGBA/core/graphics/RendererProxy.js index 6d4f916..1d27b93 100644 --- a/IodineGBA/core/graphics/RendererProxy.js +++ b/IodineGBA/core/graphics/RendererProxy.js @@ -1148,7 +1148,9 @@ GameBoyAdvanceRendererProxy.prototype.writeBLDY8 = function (data) { GameBoyAdvanceRendererProxy.prototype.writeVRAM8 = function (address, data) { address = address | 0; data = data | 0; - this.renderer.writeVRAM8(address | 0, data | 0); + //if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.IOData8[0] & 0x7) >= 3)) { + this.renderer.writeVRAM8(address | 0, data | 0); + //} } GameBoyAdvanceRendererProxy.prototype.writeVRAM16 = function (address, data) { address = address | 0; diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 602925d..75b6079 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -9,7 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { - //if (!window.SharedArrayBuffer || !Atomics) { + //if (!__LITTLE_ENDIAN__ || !window.SharedArrayBuffer || !Atomics) { return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); /*} else { @@ -19,6 +19,7 @@ function GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS) { this.coreExposed = coreExposed; this.initializeWorker(); + this.appendAtomicSync(); this.initializeBuffers(); this.shareBuffers(skippingBIOS); } @@ -31,6 +32,15 @@ this.gfxCommandCounters = getSharedInt32Array(2); this.start = 0; this.end = 0; + this.OAMRAM = getUint8Array(0x400); + this.OAMRAM16 = getUint16View(this.OAMRAM); + this.OAMRAM32 = getInt32View(this.OAMRAM); + this.paletteRAM = getUint8Array(0x400); + this.VRAM = getUint8Array(0x18000); + this.VRAM16 = getUint16View(this.VRAM); + this.VRAM32 = getInt32View(this.VRAM); + this.paletteRAM16 = getUint16View(this.paletteRAM); + this.paletteRAM32 = getInt32View(this.paletteRAM); } GameBoyAdvanceGraphicsRendererShim.prototype.appendAtomicSync = function () { //Command buffer counters get synchronized with emulator runtime head/end for efficiency: @@ -97,3 +107,651 @@ GameBoyAdvanceGraphicsRendererShim.prototype.ensureFraming = function () { //Vertical blank synchronization command: this.pushCommand(0, 1); } +GameBoyAdvanceGraphicsRendererShim.prototype.writeDISPCNT8_0 = function (data) { + data = data | 0; + this.pushCommand(1, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeDISPCNT8_1 = function (data) { + data = data | 0; + this.pushCommand(2, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeDISPCNT8_2 = function (data) { + data = data | 0; + this.pushCommand(3, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeDISPCNT16 = function (data) { + data = data | 0; + this.pushCommand(4, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeDISPCNT32 = function (data) { + data = data | 0; + this.pushCommand(5, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0CNT8_0 = function (data) { + data = data | 0; + this.pushCommand(6, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0CNT8_1 = function (data) { + data = data | 0; + this.pushCommand(7, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0CNT16 = function (data) { + data = data | 0; + this.pushCommand(8, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1CNT8_0 = function (data) { + data = data | 0; + this.pushCommand(9, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1CNT8_1 = function (data) { + data = data | 0; + this.pushCommand(10, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1CNT16 = function (data) { + data = data | 0; + this.pushCommand(11, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0BG1CNT32 = function (data) { + data = data | 0; + this.pushCommand(12, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2CNT8_0 = function (data) { + data = data | 0; + this.pushCommand(13, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2CNT8_1 = function (data) { + data = data | 0; + this.pushCommand(14, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2CNT16 = function (data) { + data = data | 0; + this.pushCommand(15, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3CNT8_0 = function (data) { + data = data | 0; + this.pushCommand(16, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3CNT8_1 = function (data) { + data = data | 0; + this.pushCommand(17, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3CNT16 = function (data) { + data = data | 0; + this.pushCommand(18, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2BG3CNT32 = function (data) { + data = data | 0; + this.pushCommand(19, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0HOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(20, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0HOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(21, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0HOFS16 = function (data) { + data = data | 0; + this.pushCommand(22, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0VOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(23, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0VOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(24, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0VOFS16 = function (data) { + data = data | 0; + this.pushCommand(25, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG0OFS32 = function (data) { + data = data | 0; + this.pushCommand(26, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1HOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(27, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1HOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(28, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1HOFS16 = function (data) { + data = data | 0; + this.pushCommand(29, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1VOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(30, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1VOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(31, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1VOFS16 = function (data) { + data = data | 0; + this.pushCommand(32, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG1OFS32 = function (data) { + data = data | 0; + this.pushCommand(33, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2HOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(34, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2HOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(35, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2HOFS16 = function (data) { + data = data | 0; + this.pushCommand(36, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2VOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(37, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2VOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(38, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2VOFS16 = function (data) { + data = data | 0; + this.pushCommand(39, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2OFS32 = function (data) { + data = data | 0; + this.pushCommand(40, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3HOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(41, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3HOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(42, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3HOFS16 = function (data) { + data = data | 0; + this.pushCommand(43, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3VOFS8_0 = function (data) { + data = data | 0; + this.pushCommand(44, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3VOFS8_1 = function (data) { + data = data | 0; + this.pushCommand(45, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3VOFS16 = function (data) { + data = data | 0; + this.pushCommand(46, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3OFS32 = function (data) { + data = data | 0; + this.pushCommand(47, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PA8_0 = function (data) { + data = data | 0; + this.pushCommand(48, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PA8_1 = function (data) { + data = data | 0; + this.pushCommand(49, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PA16 = function (data) { + data = data | 0; + this.pushCommand(50, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PB8_0 = function (data) { + data = data | 0; + this.pushCommand(51, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PB8_1 = function (data) { + data = data | 0; + this.pushCommand(52, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PB16 = function (data) { + data = data | 0; + this.pushCommand(53, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PAB32 = function (data) { + data = data | 0; + this.pushCommand(54, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PC8_0 = function (data) { + data = data | 0; + this.pushCommand(55, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PC8_1 = function (data) { + data = data | 0; + this.pushCommand(56, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PC16 = function (data) { + data = data | 0; + this.pushCommand(57, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PD8_0 = function (data) { + data = data | 0; + this.pushCommand(58, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PD8_1 = function (data) { + data = data | 0; + this.pushCommand(59, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PD16 = function (data) { + data = data | 0; + this.pushCommand(60, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2PCD32 = function (data) { + data = data | 0; + this.pushCommand(61, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PA8_0 = function (data) { + data = data | 0; + this.pushCommand(62, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PA8_1 = function (data) { + data = data | 0; + this.pushCommand(63, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PA16 = function (data) { + data = data | 0; + this.pushCommand(64, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PB8_0 = function (data) { + data = data | 0; + this.pushCommand(65, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PB8_1 = function (data) { + data = data | 0; + this.pushCommand(66, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PB16 = function (data) { + data = data | 0; + this.pushCommand(67, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PAB32 = function (data) { + data = data | 0; + this.pushCommand(68, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PC8_0 = function (data) { + data = data | 0; + this.pushCommand(69, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PC8_1 = function (data) { + data = data | 0; + this.pushCommand(70, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PC16 = function (data) { + data = data | 0; + this.pushCommand(71, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PD8_0 = function (data) { + data = data | 0; + this.pushCommand(72, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PD8_1 = function (data) { + data = data | 0; + this.pushCommand(73, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PD16 = function (data) { + data = data | 0; + this.pushCommand(74, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3PCD32 = function (data) { + data = data | 0; + this.pushCommand(75, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X8_0 = function (data) { + data = data | 0; + this.pushCommand(76, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X8_1 = function (data) { + data = data | 0; + this.pushCommand(77, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X8_2 = function (data) { + data = data | 0; + this.pushCommand(78, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X8_3 = function (data) { + data = data | 0; + this.pushCommand(79, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X16_0 = function (data) { + data = data | 0; + this.pushCommand(80, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X16_1 = function (data) { + data = data | 0; + this.pushCommand(81, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2X32 = function (data) { + data = data | 0; + this.pushCommand(82, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y8_0 = function (data) { + data = data | 0; + this.pushCommand(83, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y8_1 = function (data) { + data = data | 0; + this.pushCommand(84, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y8_2 = function (data) { + data = data | 0; + this.pushCommand(85, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y8_3 = function (data) { + data = data | 0; + this.pushCommand(86, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y16_0 = function (data) { + data = data | 0; + this.pushCommand(87, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y16_1 = function (data) { + data = data | 0; + this.pushCommand(88, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG2Y32 = function (data) { + data = data | 0; + this.pushCommand(89, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X8_0 = function (data) { + data = data | 0; + this.pushCommand(90, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X8_1 = function (data) { + data = data | 0; + this.pushCommand(91, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X8_2 = function (data) { + data = data | 0; + this.pushCommand(92, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X8_3 = function (data) { + data = data | 0; + this.pushCommand(93, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X16_0 = function (data) { + data = data | 0; + this.pushCommand(94, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X16_1 = function (data) { + data = data | 0; + this.pushCommand(95, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3X32 = function (data) { + data = data | 0; + this.pushCommand(96, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y8_0 = function (data) { + data = data | 0; + this.pushCommand(97, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y8_1 = function (data) { + data = data | 0; + this.pushCommand(98, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y8_2 = function (data) { + data = data | 0; + this.pushCommand(99, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y8_3 = function (data) { + data = data | 0; + this.pushCommand(100, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y16_0 = function (data) { + data = data | 0; + this.pushCommand(101, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y16_1 = function (data) { + data = data | 0; + this.pushCommand(102, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBG3Y32 = function (data) { + data = data | 0; + this.pushCommand(103, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0XCOORDRight8 = function (data) { + data = data | 0; + this.pushCommand(104, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0XCOORDLeft8 = function (data) { + data = data | 0; + this.pushCommand(105, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0XCOORD16 = function (data) { + data = data | 0; + this.pushCommand(106, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1XCOORDRight8 = function (data) { + data = data | 0; + this.pushCommand(107, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1XCOORDLeft8 = function (data) { + data = data | 0; + this.pushCommand(108, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1XCOORD16 = function (data) { + data = data | 0; + this.pushCommand(109, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINXCOORD32 = function (data) { + data = data | 0; + this.pushCommand(110, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0YCOORDBottom8 = function (data) { + data = data | 0; + this.pushCommand(111, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0YCOORDTop8 = function (data) { + data = data | 0; + this.pushCommand(112, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0YCOORD16 = function (data) { + data = data | 0; + this.pushCommand(113, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1YCOORDBottom8 = function (data) { + data = data | 0; + this.pushCommand(114, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1YCOORDTop8 = function (data) { + data = data | 0; + this.pushCommand(115, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1YCOORD16 = function (data) { + data = data | 0; + this.pushCommand(116, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINYCOORD32 = function (data) { + data = data | 0; + this.pushCommand(117, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN0IN8 = function (data) { + data = data | 0; + this.pushCommand(118, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWIN1IN8 = function (data) { + data = data | 0; + this.pushCommand(119, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWININ16 = function (data) { + data = data | 0; + this.pushCommand(120, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINOUT8 = function (data) { + data = data | 0; + this.pushCommand(121, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINOBJIN8 = function (data) { + data = data | 0; + this.pushCommand(122, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINOUT16 = function (data) { + data = data | 0; + this.pushCommand(123, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeWINCONTROL32 = function (data) { + data = data | 0; + this.pushCommand(124, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeMOSAIC8_0 = function (data) { + data = data | 0; + this.pushCommand(125, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeMOSAIC8_1 = function (data) { + data = data | 0; + this.pushCommand(126, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeMOSAIC16 = function (data) { + data = data | 0; + this.pushCommand(127, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDCNT8_0 = function (data) { + data = data | 0; + this.pushCommand(128, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDCNT8_1 = function (data) { + data = data | 0; + this.pushCommand(129, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDCNT16 = function (data) { + data = data | 0; + this.pushCommand(130, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDALPHA8_0 = function (data) { + data = data | 0; + this.pushCommand(131, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDALPHA8_1 = function (data) { + data = data | 0; + this.pushCommand(132, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDALPHA16 = function (data) { + data = data | 0; + this.pushCommand(133, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDCNT32 = function (data) { + data = data | 0; + this.pushCommand(134, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDY8 = function (data) { + data = data | 0; + this.pushCommand(135, data | 0); +} +if (typeof Math.imul == "function") { + //Math.imul found, insert the optimized path in: + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + address = (address >> 1) & 0xFFFF; + data = Math.imul(data & 0xFF, 0x101) | 0; + this.VRAM16[address | 0] = data | 0; + this.pushCommand(0x20000 | address, data | 0); + } +} +else { + //Math.imul not found, use the compatibility method: + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + address = (address >> 1) & 0xFFFF; + data = (data & 0xFF) * 0x101; + this.VRAM16[address | 0] = data | 0; + this.pushCommand(0x20000 | address, data | 0); + } +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM16 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + address = (address >> 1) & 0xFFFF; + data = data & 0xFFFF; + this.VRAM16[address | 0] = data | 0; + this.pushCommand(0x40000 | address, | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + address = (address >> 2) & 0x7FFF; + this.VRAM32[address | 0] = data | 0; + this.pushCommand(0x60000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { + address = address | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + return this.VRAM16[(address >> 1) & 0xFFFF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM32 = function (address) { + address = address | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + return this.VRAM32[(address >> 2) & 0x7FFF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.writePalette16 = function (address, data) { + data = data | 0; + address = address >> 1; + address = address & 0x1FF; + this.paletteRAM16[address | 0] = data | 0; + this.pushCommand(0x80000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { + data = data | 0; + address = address >> 1; + address = (address >> 1) & 0xFF; + this.paletteRAM32[address | 0] = data | 0; + this.pushCommand(0x100000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { + address = address | 0; + return this.paletteRAM16[(address >> 1) & 0x1FF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readPalette32 = function (address) { + address = address | 0; + return this.paletteRAM32[(address >> 2) & 0xFF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM8 = function (address) { + address = address | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + return this.VRAM[address & 0x1FFFF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM16 = function (address, data) { + address = address | 0; + data = data | 0; + address = address >> 1; + this.OAMRAM16[address | 0] = data | 0; + this.pushCommand(0x120000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { + address = address | 0; + data = data | 0; + address = address >> 2; + this.OAMRAM32[address | 0] = data | 0; + this.pushCommand(0x140000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.readOAM = function (address) { + address = address | 0; + return this.OAMRAM[address & 0x3FF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { + address = address | 0; + return this.OAMRAM16[(address >> 1) & 0x1FF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readOAM32 = function (address) { + address = address | 0; + return this.OAMRAM32[(address >> 2) & 0xFF] | 0; +} +GameBoyAdvanceGraphicsRendererShim.prototype.readPalette8 = function (address) { + address = address | 0; + return this.paletteRAM[address & 0x3FF] | 0; +} diff --git a/IodineGBA/core/graphics/RendererShimWorker.js b/IodineGBA/core/graphics/RendererShimWorker.js index a3c4b8b..ca38daf 100644 --- a/IodineGBA/core/graphics/RendererShimWorker.js +++ b/IodineGBA/core/graphics/RendererShimWorker.js @@ -8,6 +8,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +importScripts("../IodineGBA/includes/TypedArrayShim.js"); importScripts("../IodineGBA/core/graphics/Renderer.js"); importScripts("../IodineGBA/core/graphics/RendererProxy.js"); importScripts("../IodineGBA/core/graphics/BGTEXT.js"); From 04eccbd0b81a8fd0c11b0127b02ae8089bc7534c Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 12:45:08 -0500 Subject: [PATCH 10/16] continuation of stuff --- IodineGBA/core/Memory.js | 4 +- IodineGBA/core/graphics/OBJ.js | 24 ++-- IodineGBA/core/graphics/Renderer.js | 78 ++++------ IodineGBA/core/graphics/RendererProxy.js | 56 +++++--- IodineGBA/core/graphics/RendererShim.js | 240 +++++++++++++++++++------------ 5 files changed, 227 insertions(+), 175 deletions(-) diff --git a/IodineGBA/core/Memory.js b/IodineGBA/core/Memory.js index cdb20c8..5d00e17 100644 --- a/IodineGBA/core/Memory.js +++ b/IodineGBA/core/Memory.js @@ -2102,7 +2102,7 @@ GameBoyAdvanceMemory.prototype.writeOBJ16 = function (address, data) { data = data | 0; this.IOCore.updateGraphicsClocking(); this.wait.OAMAccess(); - this.gfxRenderer.writeOAM16(address & 0x3FE, data & 0xFFFF); + this.gfxRenderer.writeOAM16(address | 0, data | 0); } GameBoyAdvanceMemory.prototype.writePalette32 = function (address, data) { address = address | 0; @@ -2123,7 +2123,7 @@ GameBoyAdvanceMemory.prototype.writeOBJ32 = function (address, data) { data = data | 0; this.IOCore.updateGraphicsClocking(); this.wait.OAMAccess(); - this.gfxRenderer.writeOAM32(address & 0x3FC, data | 0); + this.gfxRenderer.writeOAM32(address | 0, data | 0); } GameBoyAdvanceMemory.prototype.writeROM8 = function (address, data) { address = address | 0; diff --git a/IodineGBA/core/graphics/OBJ.js b/IodineGBA/core/graphics/OBJ.js index 0d875f9..5fb364c 100644 --- a/IodineGBA/core/graphics/OBJ.js +++ b/IodineGBA/core/graphics/OBJ.js @@ -1,11 +1,11 @@ "use strict"; /* Copyright (C) 2012-2015 Grant Galitz - + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function GameBoyAdvanceOBJRenderer(gfx) { @@ -293,7 +293,7 @@ GameBoyAdvanceOBJRenderer.prototype.computeCycles = function (cycles, matrix2D, cyclesToSubtract = cyclesToSubtract << 1; cyclesToSubtract = ((cyclesToSubtract | 0) + 10) | 0; cycles = ((cycles | 0) - (cyclesToSubtract | 0)) | 0; - + } else { //Regular Scrolling: @@ -896,7 +896,7 @@ if (__LITTLE_ENDIAN__) { default: this.OBJMatrixParameters[address >> 2] = (data << 16) >> 16; } - this.OAMRAM16[address | 0] = data | 0; + this.OAMRAM16[address | 0] = data & 0xFFFF; } GameBoyAdvanceOBJRenderer.prototype.writeOAM32 = function (address, data) { address = address | 0; @@ -930,17 +930,18 @@ if (__LITTLE_ENDIAN__) { } GameBoyAdvanceOBJRenderer.prototype.readOAM16 = function (address) { address = address | 0; - return this.OAMRAM16[(address >> 1) & 0x1FF] | 0; + return this.OAMRAM16[address & 0x1FF] | 0; } GameBoyAdvanceOBJRenderer.prototype.readOAM32 = function (address) { address = address | 0; - return this.OAMRAM32[(address >> 2) & 0xFF] | 0; + return this.OAMRAM32[address & 0xFF] | 0; } } else { GameBoyAdvanceOBJRenderer.prototype.writeOAM16 = function (address, data) { address = address | 0; data = data | 0; + address = address & 0x1FF; var OAMTable = this.OAMTable[address >> 2]; switch (address & 0x3) { //Attrib 0: @@ -978,6 +979,7 @@ else { GameBoyAdvanceOBJRenderer.prototype.writeOAM32 = function (address, data) { address = address | 0; data = data | 0; + address = address & 0xFF; var OAMTable = this.OAMTable[address >> 1]; if ((address & 0x1) == 0) { //Attrib 0: @@ -1010,11 +1012,13 @@ else { this.OAMRAM[address | 3] = data >>> 24; } GameBoyAdvanceOBJRenderer.prototype.readOAM16 = function (address) { - address &= 0x3FE; + address &= 0x1FF; + address <<= 1; return this.OAMRAM[address] | (this.OAMRAM[address | 1] << 8); } GameBoyAdvanceOBJRenderer.prototype.readOAM32 = function (address) { - address &= 0x3FC; + address &= 0xFF; + address <<= 2; return this.OAMRAM[address] | (this.OAMRAM[address | 1] << 8) | (this.OAMRAM[address | 2] << 16) | (this.OAMRAM[address | 3] << 24); } -} \ No newline at end of file +} diff --git a/IodineGBA/core/graphics/Renderer.js b/IodineGBA/core/graphics/Renderer.js index e78d1e7..4600589 100644 --- a/IodineGBA/core/graphics/Renderer.js +++ b/IodineGBA/core/graphics/Renderer.js @@ -1209,68 +1209,42 @@ GameBoyAdvanceGraphicsRenderer.prototype.writeBLDY8 = function (data) { this.colorEffectsRenderer.writeBLDY8(data | 0); } if (__LITTLE_ENDIAN__) { - if (typeof Math.imul == "function") { - //Math.imul found, insert the optimized path in: - GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM8 = function (address, data) { - address = address | 0; - data = data | 0; - if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.displayControl & 0x7) >= 3)) { - this.graphicsJIT(); - address = address & (((address & 0x10000) >> 1) ^ address); - this.VRAM16[(address >> 1) & 0xFFFF] = Math.imul(data & 0xFF, 0x101) | 0; - } - } - } - else { - //Math.imul not found, use the compatibility method: - GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM8 = function (address, data) { - address = address | 0; - data = data | 0; - if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.displayControl & 0x7) >= 3)) { - this.graphicsJIT(); - address = address & (((address & 0x10000) >> 1) ^ address); - this.VRAM16[(address >> 1) & 0xFFFF] = (data & 0xFF) * 0x101; - } - } - } + GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM8 = GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM16 = function (address, data) { address = address | 0; data = data | 0; this.graphicsJIT(); - address = address & (((address & 0x10000) >> 1) ^ address); - this.VRAM16[(address >> 1) & 0xFFFF] = data & 0xFFFF; + this.VRAM16[address & 0xFFFF] = data & 0xFFFF; } GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM32 = function (address, data) { address = address | 0; data = data | 0; this.graphicsJIT(); - address = address & (((address & 0x10000) >> 1) ^ address); - this.VRAM32[(address >> 2) & 0x7FFF] = data | 0; + this.VRAM32[address & 0x7FFF] = data | 0; } GameBoyAdvanceGraphicsRenderer.prototype.readVRAM16 = function (address) { address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - return this.VRAM16[(address >> 1) & 0xFFFF] | 0; + return this.VRAM16[address & 0xFFFF] | 0; } GameBoyAdvanceGraphicsRenderer.prototype.readVRAM32 = function (address) { address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - return this.VRAM32[(address >> 2) & 0x7FFF] | 0; + return this.VRAM32[address & 0x7FFF] | 0; } GameBoyAdvanceGraphicsRenderer.prototype.writePalette16 = function (address, data) { data = data | 0; - address = address >> 1; + address = address | 0; this.graphicsJIT(); - this.paletteRAM16[address & 0x1FF] = data | 0; + this.paletteRAM16[address & 0x1FF] = data & 0xFFFF; data = data & 0x7FFF; this.writePalette256Color(address | 0, data | 0); this.writePalette16Color(address | 0, data | 0); } GameBoyAdvanceGraphicsRenderer.prototype.writePalette32 = function (address, data) { data = data | 0; - address = address >> 1; + address = address | 0; this.graphicsJIT(); - this.paletteRAM32[(address >> 1) & 0xFF] = data | 0; + this.paletteRAM32[address & 0xFF] = data | 0; + address = address << 1; var palette = data & 0x7FFF; this.writePalette256Color(address | 0, palette | 0); this.writePalette16Color(address | 0, palette | 0); @@ -1280,30 +1254,25 @@ if (__LITTLE_ENDIAN__) { } GameBoyAdvanceGraphicsRenderer.prototype.readPalette16 = function (address) { address = address | 0; - return this.paletteRAM16[(address >> 1) & 0x1FF] | 0; + return this.paletteRAM16[address & 0x1FF] | 0; } GameBoyAdvanceGraphicsRenderer.prototype.readPalette32 = function (address) { address = address | 0; - return this.paletteRAM32[(address >> 2) & 0xFF] | 0; + return this.paletteRAM32[address & 0xFF] | 0; } } else { - GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM8 = function (address, data) { - address &= 0x1FFFE & (((address & 0x10000) >> 1) ^ address); - if (address < 0x10000 || ((address & 0x17FFF) < 0x14000 && (this.displayControl & 0x7) >= 3)) { - this.graphicsJIT(); - this.VRAM[address++] = data & 0xFF; - this.VRAM[address] = data & 0xFF; - } - } + GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM8 = GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM16 = function (address, data) { - address &= 0x1FFFE & (((address & 0x10000) >> 1) ^ address); + address <<= 1; + address &= 0x1FFFE; this.graphicsJIT(); this.VRAM[address++] = data & 0xFF; this.VRAM[address] = (data >> 8) & 0xFF; } GameBoyAdvanceGraphicsRenderer.prototype.writeVRAM32 = function (address, data) { - address &= 0x1FFFC & (((address & 0x10000) >> 1) ^ address); + address <<= 2; + address &= 0x1FFFC; this.graphicsJIT(); this.VRAM[address++] = data & 0xFF; this.VRAM[address++] = (data >> 8) & 0xFF; @@ -1311,15 +1280,18 @@ else { this.VRAM[address] = data >>> 24; } GameBoyAdvanceGraphicsRenderer.prototype.readVRAM16 = function (address) { - address &= 0x1FFFE & (((address & 0x10000) >> 1) ^ address); + address <<= 1; + address &= 0x1FFFE; return this.VRAM[address] | (this.VRAM[address + 1] << 8); } GameBoyAdvanceGraphicsRenderer.prototype.readVRAM32 = function (address) { - address &= 0x1FFFC & (((address & 0x10000) >> 1) ^ address); + address <<= 2; + address &= 0x1FFFC; return this.VRAM[address] | (this.VRAM[address + 1] << 8) | (this.VRAM[address + 2] << 16) | (this.VRAM[address + 3] << 24); } GameBoyAdvanceGraphicsRenderer.prototype.writePalette16 = function (address, data) { this.graphicsJIT(); + address <<= 1; this.paletteRAM[address] = data & 0xFF; this.paletteRAM[address | 1] = data >> 8; data &= 0x7FFF; @@ -1329,6 +1301,7 @@ else { } GameBoyAdvanceGraphicsRenderer.prototype.writePalette32 = function (address, data) { this.graphicsJIT(); + address <<= 2; this.paletteRAM[address] = data & 0xFF; this.paletteRAM[address | 1] = (data >> 8) & 0xFF; this.paletteRAM[address | 2] = (data >> 16) & 0xFF; @@ -1353,20 +1326,19 @@ else { } GameBoyAdvanceGraphicsRenderer.prototype.readVRAM8 = function (address) { address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); return this.VRAM[address & 0x1FFFF] | 0; } GameBoyAdvanceGraphicsRenderer.prototype.writeOAM16 = function (address, data) { address = address | 0; data = data | 0; this.graphicsJIT(); - this.objRenderer.writeOAM16(address >> 1, data | 0); + this.objRenderer.writeOAM16(address & 0x1FF, data & 0xFFFF); } GameBoyAdvanceGraphicsRenderer.prototype.writeOAM32 = function (address, data) { address = address | 0; data = data | 0; this.graphicsJIT(); - this.objRenderer.writeOAM32(address >> 2, data | 0); + this.objRenderer.writeOAM32(address & 0xFF, data | 0); } GameBoyAdvanceGraphicsRenderer.prototype.readOAM = function (address) { address = address | 0; diff --git a/IodineGBA/core/graphics/RendererProxy.js b/IodineGBA/core/graphics/RendererProxy.js index 1d27b93..f08964e 100644 --- a/IodineGBA/core/graphics/RendererProxy.js +++ b/IodineGBA/core/graphics/RendererProxy.js @@ -1145,42 +1145,65 @@ GameBoyAdvanceRendererProxy.prototype.writeBLDY8 = function (data) { this.IOCore.updateGraphicsClocking(); this.renderer.writeBLDY8(data | 0); } -GameBoyAdvanceRendererProxy.prototype.writeVRAM8 = function (address, data) { - address = address | 0; - data = data | 0; - //if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.IOData8[0] & 0x7) >= 3)) { - this.renderer.writeVRAM8(address | 0, data | 0); - //} +if (typeof Math.imul == "function") { + //Math.imul found, insert the optimized path in: + GameBoyAdvanceRendererProxy.prototype.writeVRAM8 = function (address, data) { + address = address | 0; + data = data | 0; + if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.IOData8[0] & 0x7) >= 3)) { + address = address & (((address & 0x10000) >> 1) ^ address); + address = address >> 1; + data = Math.imul(data & 0xFF, 0x101) | 0; + this.renderer.writeVRAM8(address | 0, data | 0); + } + } +} +else { + //Math.imul not found, use the compatibility method: + GameBoyAdvanceRendererProxy.prototype.writeVRAM8 = function (address, data) { + address = address | 0; + data = data | 0; + if ((address & 0x10000) == 0 || ((address & 0x17FFF) < 0x14000 && (this.IOData8[0] & 0x7) >= 3)) { + address = address & (((address & 0x10000) >> 1) ^ address); + address = address >> 1; + data = (data & 0xFF) * 0x101; + this.renderer.writeVRAM8(address | 0, data | 0); + } + } } GameBoyAdvanceRendererProxy.prototype.writeVRAM16 = function (address, data) { address = address | 0; data = data | 0; - this.renderer.writeVRAM16(address | 0, data | 0); + address = address & (((address & 0x10000) >> 1) ^ address); + this.renderer.writeVRAM16(address >> 1, data | 0); } GameBoyAdvanceRendererProxy.prototype.writeVRAM32 = function (address, data) { address = address | 0; data = data | 0; - this.renderer.writeVRAM32(address | 0, data | 0); + address = address & (((address & 0x10000) >> 1) ^ address); + this.renderer.writeVRAM32(address >> 2, data | 0); } GameBoyAdvanceRendererProxy.prototype.readVRAM16 = function (address) { address = address | 0; - var data = this.renderer.readVRAM16(address | 0) | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + var data = this.renderer.readVRAM16(address >> 1) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.readVRAM32 = function (address) { address = address | 0; - var data = this.renderer.readVRAM32(address | 0) | 0; + address = address & (((address & 0x10000) >> 1) ^ address); + var data = this.renderer.readVRAM32(address >> 2) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.writePalette16 = function (address, data) { data = data | 0; address = address | 0; - this.renderer.writePalette16(address | 0, data | 0); + this.renderer.writePalette16(address >> 1, data | 0); } GameBoyAdvanceRendererProxy.prototype.writePalette32 = function (address, data) { data = data | 0; address = address | 0; - this.renderer.writePalette32(address | 0, data | 0); + this.renderer.writePalette32(address >> 2, data | 0); } GameBoyAdvanceRendererProxy.prototype.readPalette16 = function (address) { address = address | 0; @@ -1194,18 +1217,19 @@ GameBoyAdvanceRendererProxy.prototype.readPalette32 = function (address) { } GameBoyAdvanceRendererProxy.prototype.readVRAM8 = function (address) { address = address | 0; + address = address & (((address & 0x10000) >> 1) ^ address); var data = this.renderer.readVRAM8(address | 0) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.writeOAM16 = function (address, data) { address = address | 0; data = data | 0; - this.renderer.writeOAM16(address | 0, data | 0); + this.renderer.writeOAM16(address >> 1, data | 0); } GameBoyAdvanceRendererProxy.prototype.writeOAM32 = function (address, data) { address = address | 0; data = data | 0; - this.renderer.writeOAM32(address | 0, data | 0); + this.renderer.writeOAM32(address >> 2, data | 0); } GameBoyAdvanceRendererProxy.prototype.readOAM = function (address) { address = address | 0; @@ -1214,12 +1238,12 @@ GameBoyAdvanceRendererProxy.prototype.readOAM = function (address) { } GameBoyAdvanceRendererProxy.prototype.readOAM16 = function (address) { address = address | 0; - var data = this.renderer.readOAM16(address | 0) | 0; + var data = this.renderer.readOAM16(address >> 1) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.readOAM32 = function (address) { address = address | 0; - var data = this.renderer.readOAM32(address | 0) | 0; + var data = this.renderer.readOAM32(address >> 2) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.readPalette8 = function (address) { diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 75b6079..899cdc1 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -46,14 +46,10 @@ //Command buffer counters get synchronized with emulator runtime head/end for efficiency: var parentObj = this; this.coreExposed.appendStartIterationSync(function () { - //Load command buffer reader counter value: - parentObj.start = Atomics.load(parentObj.gfxCommandCounters, 0) | 0; + parentObj.synchronizeReader(); }); this.coreExposed.appendEndIterationSync(function () { - //Store command buffer writer counter value: - Atomics.store(parentObj.gfxCommandCounters, 1, parentObj.end | 0); - //Tell consumer thread to check command buffer: - parentObj.worker.postMessage({messageID:0}); + parentObj.synchronizeWriter(); }); this.coreExposed.appendTerminationSync(function () { //Core instance being replaced, kill the worker thread: @@ -93,12 +89,24 @@ GameBoyAdvanceGraphicsRendererShim.prototype.pushCommand = function (command, da } GameBoyAdvanceGraphicsRendererShim.prototype.blockIfCommandBufferFull = function () { if ((this.start | 0) == (((this.end | 0) - 0x80000) | 0)) { + //Give the reader our updated counter and tell it to run: + this.synchronizeWriter(); //Wait for consumer thread: Atomics.futexWait(this.gfxCommandCounters, 0, ((this.end | 0) - 0x80000) | 0); //Reload reader counter value: - this.start = Atomics.load(this.gfxCommandCounters, 0) | 0; + this.synchronizeReader(); } } +GameBoyAdvanceGraphicsRendererShim.prototype.synchronizeWriter = function () { + //Store command buffer writer counter value: + Atomics.store(this.gfxCommandCounters, 1, this.end | 0); + //Tell consumer thread to check command buffer: + this.worker.postMessage({messageID:0}); +} +GameBoyAdvanceGraphicsRendererShim.prototype.synchronizeReader = function () { + //Load command buffer reader counter value: + this.start = Atomics.load(this.gfxCommandCounters, 0) | 0; +} GameBoyAdvanceGraphicsRendererShim.prototype.incrementScanLineQueue = function () { //Increment scan line command: this.pushCommand(0, 0); @@ -647,110 +655,154 @@ GameBoyAdvanceGraphicsRendererShim.prototype.writeBLDY8 = function (data) { data = data | 0; this.pushCommand(135, data | 0); } -if (typeof Math.imul == "function") { - //Math.imul found, insert the optimized path in: - GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = function (address, data) { +if (__LITTLE_ENDIAN__) { + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM16 = function (address, data) { address = address | 0; data = data | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - address = (address >> 1) & 0xFFFF; - data = Math.imul(data & 0xFF, 0x101) | 0; - this.VRAM16[address | 0] = data | 0; + this.VRAM16[address & 0xFFFF] = data & 0xFFFF; this.pushCommand(0x20000 | address, data | 0); } -} -else { - //Math.imul not found, use the compatibility method: - GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = function (address, data) { + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { address = address | 0; data = data | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - address = (address >> 1) & 0xFFFF; - data = (data & 0xFF) * 0x101; - this.VRAM16[address | 0] = data | 0; - this.pushCommand(0x20000 | address, data | 0); + this.VRAM32[address & 0x7FFF] = data | 0; + this.pushCommand(0x40000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { + address = address | 0; + return this.VRAM16[address & 0xFFFF] | 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM32 = function (address) { + address = address | 0; + return this.VRAM32[address & 0x7FFF] | 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.writePalette16 = function (address, data) { + data = data | 0; + address = address | 0; + this.paletteRAM16[address & 0x1FF] = data & 0xFFFF; + this.pushCommand(0x60000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { + data = data | 0; + address = address | 0; + this.paletteRAM32[address & 0xFF] = data | 0; + this.pushCommand(0x80000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { + address = address | 0; + return this.paletteRAM16[address & 0x1FF] | 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.readPalette32 = function (address) { + address = address | 0; + return this.paletteRAM32[address & 0xFF] | 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM16 = function (address, data) { + address = address | 0; + data = data | 0; + this.OAMRAM16[address & 0x1FF] = data & 0xFFFF; + this.pushCommand(0xA0000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { + address = address | 0; + data = data | 0; + this.OAMRAM32[address & 0xFF] = data | 0; + this.pushCommand(0xC0000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { + address = address | 0; + return this.OAMRAM16[address & 0x1FF] | 0; + } + GameBoyAdvanceGraphicsRendererShim.prototype.readOAM32 = function (address) { + address = address | 0; + return this.OAMRAM32[address & 0xFF] | 0; } } -GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM16 = function (address, data) { - address = address | 0; - data = data | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - address = (address >> 1) & 0xFFFF; - data = data & 0xFFFF; - this.VRAM16[address | 0] = data | 0; - this.pushCommand(0x40000 | address, | 0); -} -GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { - address = address | 0; - data = data | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - address = (address >> 2) & 0x7FFF; - this.VRAM32[address | 0] = data | 0; - this.pushCommand(0x60000 | address, data | 0); -} -GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { - address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - return this.VRAM16[(address >> 1) & 0xFFFF] | 0; -} -GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM32 = function (address) { - address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); - return this.VRAM32[(address >> 2) & 0x7FFF] | 0; -} -GameBoyAdvanceGraphicsRendererShim.prototype.writePalette16 = function (address, data) { - data = data | 0; - address = address >> 1; - address = address & 0x1FF; - this.paletteRAM16[address | 0] = data | 0; - this.pushCommand(0x80000 | address, data | 0); -} -GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { - data = data | 0; - address = address >> 1; - address = (address >> 1) & 0xFF; - this.paletteRAM32[address | 0] = data | 0; - this.pushCommand(0x100000 | address, data | 0); -} -GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { - address = address | 0; - return this.paletteRAM16[(address >> 1) & 0x1FF] | 0; -} -GameBoyAdvanceGraphicsRendererShim.prototype.readPalette32 = function (address) { - address = address | 0; - return this.paletteRAM32[(address >> 2) & 0xFF] | 0; +else { + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM8 = + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM16 = function (address, data) { + address <<= 1; + address &= 0x1FFFE; + this.VRAM[address] = data & 0xFF; + this.VRAM[address + 1] = (data >> 8) & 0xFF; + this.pushCommand(0x20000 | address, data); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { + address <<= 2; + address &= 0x1FFFC; + this.VRAM[address] = data & 0xFF; + this.VRAM[address + 1 = (data >> 8) & 0xFF; + this.VRAM[address + 2] = (data >> 16) & 0xFF; + this.VRAM[address + 3] = data >>> 24; + this.pushCommand(0x40000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { + address <<= 1; + address &= 0x1FFFE; + return this.VRAM[address] | (this.VRAM[address + 1] << 8); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM32 = function (address) { + address <<= 2; + address &= 0x1FFFC; + return this.VRAM[address] | (this.VRAM[address + 1] << 8) | (this.VRAM[address + 2] << 16) | (this.VRAM[address + 3] << 24); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writePalette16 = function (address, data) { + this.paletteRAM[address << 1] = data & 0xFF; + this.paletteRAM[(address << 1) + 1] = data >> 8; + this.pushCommand(0x60000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { + address <<= 2; + this.paletteRAM[address] = data & 0xFF; + this.paletteRAM[address | 1] = (data >> 8) & 0xFF; + this.paletteRAM[address | 2] = (data >> 16) & 0xFF; + this.paletteRAM[address | 3] = data >>> 24; + address >>= 2; + this.pushCommand(0x80000 | address, data | 0); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { + address &= 0x3FE; + return this.paletteRAM[address] | (this.paletteRAM[address | 1] << 8); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readPalette32 = function (address) { + address &= 0x3FC; + return this.paletteRAM[address] | (this.paletteRAM[address | 1] << 8) | (this.paletteRAM[address | 2] << 16) | (this.paletteRAM[address | 3] << 24); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM16 = function (address, data) { + address &= 0x1FF; + this.OAMRAM[address << 1] = data & 0xFF; + this.OAMRAM[(address << 1) | 1] = data >> 8; + this.pushCommand(0xA0000 | address, data); + } + GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { + address &= 0xFF; + address <<= 2; + this.OAMRAM[address] = data & 0xFF; + this.OAMRAM[address + 1] = (data >> 8) & 0xFF; + this.OAMRAM[address + 2] = (data >> 16) & 0xFF; + this.OAMRAM[address + 3] = data >>> 24; + address >>= 2; + this.pushCommand(0xC0000 | address, data); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { + address &= 0x1FF; + address <<= 1; + return this.OAMRAM[address] | (this.OAMRAM[address | 1] << 8); + } + GameBoyAdvanceGraphicsRendererShim.prototype.readOAM32 = function (address) { + address &= 0xFF; + address <<= 2; + return this.OAMRAM[address] | (this.OAMRAM[address | 1] << 8) | (this.OAMRAM[address | 2] << 16) | (this.OAMRAM[address | 3] << 24); + } } GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM8 = function (address) { address = address | 0; - address = address & (((address & 0x10000) >> 1) ^ address); return this.VRAM[address & 0x1FFFF] | 0; } -GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM16 = function (address, data) { - address = address | 0; - data = data | 0; - address = address >> 1; - this.OAMRAM16[address | 0] = data | 0; - this.pushCommand(0x120000 | address, data | 0); -} -GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { - address = address | 0; - data = data | 0; - address = address >> 2; - this.OAMRAM32[address | 0] = data | 0; - this.pushCommand(0x140000 | address, data | 0); -} GameBoyAdvanceGraphicsRendererShim.prototype.readOAM = function (address) { address = address | 0; return this.OAMRAM[address & 0x3FF] | 0; } -GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { - address = address | 0; - return this.OAMRAM16[(address >> 1) & 0x1FF] | 0; -} -GameBoyAdvanceGraphicsRendererShim.prototype.readOAM32 = function (address) { - address = address | 0; - return this.OAMRAM32[(address >> 2) & 0xFF] | 0; -} GameBoyAdvanceGraphicsRendererShim.prototype.readPalette8 = function (address) { address = address | 0; return this.paletteRAM[address & 0x3FF] | 0; From 9761c4fb40811e41bc7a19843343e0923d131040 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 13:19:13 -0500 Subject: [PATCH 11/16] allow big endian support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit need to verify that though…….. --- IodineGBA/core/graphics/RendererShim.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 899cdc1..9c22b1b 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -9,7 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { - //if (!__LITTLE_ENDIAN__ || !window.SharedArrayBuffer || !Atomics) { + //if (!window.SharedArrayBuffer || !Atomics) { return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); /*} else { From f23fa375f362d9b4dfcd5f95d075de1924ef73c8 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 15:00:28 -0500 Subject: [PATCH 12/16] fix some typos --- IodineGBA/core/graphics/Renderer.js | 2 ++ IodineGBA/core/graphics/RendererProxy.js | 4 ++-- IodineGBA/core/graphics/RendererShim.js | 2 +- user_scripts/IodineGBAWorkerGlueCodeWorker.js | 12 ++++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/IodineGBA/core/graphics/Renderer.js b/IodineGBA/core/graphics/Renderer.js index 4600589..aaf34e1 100644 --- a/IodineGBA/core/graphics/Renderer.js +++ b/IodineGBA/core/graphics/Renderer.js @@ -1316,10 +1316,12 @@ else { this.writePalette16Color(address, palette); } GameBoyAdvanceGraphicsRenderer.prototype.readPalette16 = function (address) { + address <<= 1; address &= 0x3FE; return this.paletteRAM[address] | (this.paletteRAM[address | 1] << 8); } GameBoyAdvanceGraphicsRenderer.prototype.readPalette32 = function (address) { + address <<= 2; address &= 0x3FC; return this.paletteRAM[address] | (this.paletteRAM[address | 1] << 8) | (this.paletteRAM[address | 2] << 16) | (this.paletteRAM[address | 3] << 24); } diff --git a/IodineGBA/core/graphics/RendererProxy.js b/IodineGBA/core/graphics/RendererProxy.js index f08964e..e8e3b21 100644 --- a/IodineGBA/core/graphics/RendererProxy.js +++ b/IodineGBA/core/graphics/RendererProxy.js @@ -1207,12 +1207,12 @@ GameBoyAdvanceRendererProxy.prototype.writePalette32 = function (address, data) } GameBoyAdvanceRendererProxy.prototype.readPalette16 = function (address) { address = address | 0; - var data = this.renderer.readPalette16(address | 0) | 0; + var data = this.renderer.readPalette16(address >> 1) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.readPalette32 = function (address) { address = address | 0; - var data = this.renderer.readPalette32(address | 0) | 0; + var data = this.renderer.readPalette32(address >> 2) | 0; return data | 0; } GameBoyAdvanceRendererProxy.prototype.readVRAM8 = function (address) { diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 9c22b1b..2c45474 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -731,7 +731,7 @@ else { address <<= 2; address &= 0x1FFFC; this.VRAM[address] = data & 0xFF; - this.VRAM[address + 1 = (data >> 8) & 0xFF; + this.VRAM[address + 1] = (data >> 8) & 0xFF; this.VRAM[address + 2] = (data >> 16) & 0xFF; this.VRAM[address + 3] = data >>> 24; this.pushCommand(0x40000 | address, data | 0); diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index 8d859fe..bd9ce5d 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -31,7 +31,19 @@ importScripts("../IodineGBA/core/sound/Channel4.js"); importScripts("../IodineGBA/core/CPU/ARM.js"); importScripts("../IodineGBA/core/CPU/THUMB.js"); importScripts("../IodineGBA/core/CPU/CPSR.js"); +importScripts("../IodineGBA/core/graphics/RendererProxy.js"); importScripts("../IodineGBA/core/graphics/RendererShim.js"); +importScripts("../IodineGBA/core/graphics/Renderer.js"); +importScripts("../IodineGBA/core/graphics/BGTEXT.js"); +importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); +importScripts("../IodineGBA/core/graphics/BGMatrix.js"); +importScripts("../IodineGBA/core/graphics/AffineBG.js"); +importScripts("../IodineGBA/core/graphics/ColorEffects.js"); +importScripts("../IodineGBA/core/graphics/Mosaic.js"); +importScripts("../IodineGBA/core/graphics/OBJ.js"); +importScripts("../IodineGBA/core/graphics/OBJWindow.js"); +importScripts("../IodineGBA/core/graphics/Window.js"); +importScripts("../IodineGBA/core/graphics/Compositor.js"); importScripts("../IodineGBA/core/memory/DMA0.js"); importScripts("../IodineGBA/core/memory/DMA1.js"); importScripts("../IodineGBA/core/memory/DMA2.js"); From 3709e01d9896094b35a56643251e0837aecef2be Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sat, 23 Jan 2016 23:27:20 -0500 Subject: [PATCH 13/16] Continuation --- IodineGBA/core/graphics/RendererShim.js | 15 ++-- IodineGBA/core/graphics/RendererShimWorker.js | 109 +++++++++++++++++++++++++- IodineGBA/includes/TypedArrayShim.js | 6 +- 3 files changed, 120 insertions(+), 10 deletions(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 2c45474..4f50dea 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -18,13 +18,18 @@ } function GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS) { this.coreExposed = coreExposed; - this.initializeWorker(); + this.initializeWorker(skippingBIOS); this.appendAtomicSync(); this.initializeBuffers(); - this.shareBuffers(skippingBIOS); + this.shareBuffers(); } - GameBoyAdvanceGraphicsRendererShim.prototype.initializeWorker = function () { + GameBoyAdvanceGraphicsRendererShim.prototype.initializeWorker = function (skippingBIOS) { + skippingBIOS = !!skippingBIOS; this.worker = new Worker("RendererShimWorker.js"); + this.worker.postMessage({ + messageID:2, + skippingBIOS:!!skippingBIOS + }); } GameBoyAdvanceGraphicsRendererShim.prototype.initializeBuffers = function () { //Graphics Buffers: @@ -56,11 +61,9 @@ parentObj.worker.terminate(); }); } - GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function (skippingBIOS) { - skippingBIOS = !!skippingBIOS; + GameBoyAdvanceGraphicsRendererShim.prototype.shareBuffers = function () { this.worker.postMessage({ messageID:1, - skippingBIOS:!!skippingBIOS, gfxBuffers:gfxBuffers, gfxCounters:gfxCounters, gfxCommandBuffer:this.gfxCommandBuffer, diff --git a/IodineGBA/core/graphics/RendererShimWorker.js b/IodineGBA/core/graphics/RendererShimWorker.js index ca38daf..26ca079 100644 --- a/IodineGBA/core/graphics/RendererShimWorker.js +++ b/IodineGBA/core/graphics/RendererShimWorker.js @@ -10,7 +10,6 @@ */ importScripts("../IodineGBA/includes/TypedArrayShim.js"); importScripts("../IodineGBA/core/graphics/Renderer.js"); -importScripts("../IodineGBA/core/graphics/RendererProxy.js"); importScripts("../IodineGBA/core/graphics/BGTEXT.js"); importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); importScripts("../IodineGBA/core/graphics/BGMatrix.js"); @@ -21,3 +20,111 @@ importScripts("../IodineGBA/core/graphics/OBJ.js"); importScripts("../IodineGBA/core/graphics/OBJWindow.js"); importScripts("../IodineGBA/core/graphics/Window.js"); importScripts("../IodineGBA/core/graphics/Compositor.js"); +var renderer = null; +var gfxBuffers = null; +var gfxCounters = null; +var gfxCommandBuffer = null; +var gfxCommandCounters = null; +self.onmessage = function (event) { + var data = event.data; + switch (data.messageID) { + case 0: + processCommands(); + break; + case 1: + assignBuffers(data.gfxBuffers, data.gfxCounters, data.gfxCommandBuffer, data.gfxCommandCounters); + break; + default: + initializeRenderer(!!data.skippingBIOS); + } +} +var coreExposed = { + graphicsHandle:{ + copyBuffer:function (swizzledFrame) { + //Push a frame of graphics to the blitter handle: + //Load the counter values: + var start = gfxCounters[0] | 0; //Written by the other thread. + var end = gfxCounters[1] | 0; //Written by this thread. + //Check if buffer is full: + if ((end | 0) == (((start | 0) + 2) | 0)) { + //Skip copying a frame out: + return; + } + //Copy samples into the ring buffer: + //Hardcoded for 2 buffers for a triple buffer effect: + gfxBuffers[end & 0x1].set(swizzledFrame); + //Increment the ending position counter by 1: + //Atomic to commit the counter to memory: + Atomics.store(gfxCounters, 1, ((end | 0) + 1) | 0); + } + } +} +function initializeRenderer(skippingBIOS) { + skippingBIOS = !!skippingBIOS; + renderer = new GameBoyAdvanceGraphicsRenderer(coreExposed, !!skippingBIOS); +} +function assignBuffers(gfxBuffers, gfxCounters, gfxCommandBuffer, gfxCommandCounters) { + gfxBuffers = gfxBuffers; + gfxCounters = gfxCounters; + gfxCommandBuffer = gfxCommandBuffer; + gfxCommandCounters = gfxCommandCounters; +} +function processCommands() { + //Load the counter values: + var start = gfxCommandCounters[0] | 0; //Written by this thread. + var end = Atomics.load(gfxCommandCounters, 1) | 0; //Written by the other thread. + //Don't process if nothing to process: + if ((end | 0) == (start | 0)) { + //Buffer is empty: + return; + } + //Dispatch commands: + var startCorrected = start & 0x7FFFF; + var endCorrected = end & 0x7FFFF; + do { + dispatchCommand(gfxCommandBuffer[startCorrected | 0] | 0, gfxCommandBuffer[startCorrected | 1] | 0); + startCorrected = ((startCorrected | 0) + 2) | 0; + } while ((startCorrected | 0) != (endCorrected | 0)); + //Update the starting position counter to match the end position: + Atomics.store(gfxCommandCounters, 0, end | 0); +} +function dispatchCommand(command, data) { + command = command | 0; + data = data | 0; + switch (command >> 17) { + //IO: + case 0: + dispatchIOCommand(command | 0, data | 0); + break; + //VRAM 16-BIT: + case 1: + renderer.writeVRAM16(command & 0xFFFF, data | 0); + break; + //VRAM 32-BIT: + case 2: + renderer.writeVRAM32(command & 0x7FFF, data | 0); + break; + //Palette 16-BIT: + case 3: + renderer.writePalette16(command & 0x1FF, data | 0); + break; + //Palette 32-BIT: + case 4: + renderer.writePalette32(command & 0xFF, data | 0); + break; + //OAM 16-BIT: + case 5: + renderer.writeOAM16(command & 0x1FF, data | 0); + break; + //OAM 32-BIT: + default: + renderer.writeOAM32(command & 0xFF, data | 0); + } +} +function dispatchIOCommand(command, data) { + command = command | 0; + data = data | 0; + switch (command | 0) { + + } +} diff --git a/IodineGBA/includes/TypedArrayShim.js b/IodineGBA/includes/TypedArrayShim.js index bc29659..4a7d07e 100644 --- a/IodineGBA/includes/TypedArrayShim.js +++ b/IodineGBA/includes/TypedArrayShim.js @@ -1,11 +1,11 @@ "use strict"; /* Copyright (C) 2012-2015 Grant Galitz - + 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getInt8Array(size_t) { From 056c49026ab5f1ba4964f6a48bc01cd91c678bd2 Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sun, 24 Jan 2016 00:08:22 -0500 Subject: [PATCH 14/16] continuation --- IodineGBA/core/graphics/RendererShim.js | 6 +- IodineGBA/core/graphics/RendererShimWorker.js | 418 +++++++++++++++++++++++++- user_scripts/IodineGBAWorkerGlueCodeWorker.js | 4 +- 3 files changed, 422 insertions(+), 6 deletions(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index 4f50dea..fed275c 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -9,12 +9,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { - //if (!window.SharedArrayBuffer || !Atomics) { + if (!window.SharedArrayBuffer || !Atomics) { return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); - /*} + } else { return new GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS); - }*/ + } } function GameBoyAdvanceGraphicsRendererShim(coreExposed, skippingBIOS) { this.coreExposed = coreExposed; diff --git a/IodineGBA/core/graphics/RendererShimWorker.js b/IodineGBA/core/graphics/RendererShimWorker.js index 26ca079..d2957af 100644 --- a/IodineGBA/core/graphics/RendererShimWorker.js +++ b/IodineGBA/core/graphics/RendererShimWorker.js @@ -125,6 +125,422 @@ function dispatchIOCommand(command, data) { command = command | 0; data = data | 0; switch (command | 0) { - + case 0: + decodeInternalCommand(data | 0); + break; + case 1: + renderer.writeDISPCNT8_0(data | 0); + break; + case 2: + renderer.writeDISPCNT8_1(data | 0); + break; + case 3: + renderer.writeDISPCNT8_2(data | 0); + break; + case 4: + renderer.writeDISPCNT16(data | 0); + break; + case 5: + renderer.writeDISPCNT32(data | 0); + break; + case 6: + renderer.writeBG0CNT8_0(data | 0); + break; + case 7: + renderer.writeBG0CNT8_1(data | 0); + break; + case 8: + renderer.writeBG0CNT16(data | 0); + break; + case 9: + renderer.writeBG1CNT8_0(data | 0); + break; + case 10: + renderer.writeBG1CNT8_1(data | 0); + break; + case 11: + renderer.writeBG1CNT16(data | 0); + break; + case 12: + renderer.writeBG0BG1CNT32(data | 0); + break; + case 13: + renderer.writeBG2CNT8_0(data | 0); + break; + case 14: + renderer.writeBG2CNT8_1(data | 0); + break; + case 15: + renderer.writeBG2CNT16(data | 0); + break; + case 16: + renderer.writeBG3CNT8_0(data | 0); + break; + case 17: + renderer.writeBG3CNT8_1(data | 0); + break; + case 18: + renderer.writeBG3CNT16(data | 0); + break; + case 19: + renderer.writeBG2BG3CNT32(data | 0); + break; + case 20: + renderer.writeBG0HOFS8_0(data | 0); + break; + case 21: + renderer.writeBG0HOFS8_1(data | 0); + break; + case 22: + renderer.writeBG0HOFS16(data | 0); + break; + case 23: + renderer.writeBG0VOFS8_0(data | 0); + break; + case 24: + renderer.writeBG0VOFS8_1(data | 0); + break; + case 25: + renderer.writeBG0VOFS16(data | 0); + break; + case 26: + renderer.writeBG0OFS32(data | 0); + break; + case 27: + renderer.writeBG1HOFS8_0(data | 0); + break; + case 28: + renderer.writeBG1HOFS8_1(data | 0); + break; + case 29: + renderer.writeBG1HOFS16(data | 0); + break; + case 30: + renderer.writeBG1VOFS8_0(data | 0); + break; + case 31: + renderer.writeBG1VOFS8_1(data | 0); + break; + case 32: + renderer.writeBG1VOFS16(data | 0); + break; + case 33: + renderer.writeBG1OFS32(data | 0); + break; + case 34: + renderer.writeBG2HOFS8_0(data | 0); + break; + case 35: + renderer.writeBG2HOFS8_1(data | 0); + break; + case 36: + renderer.writeBG2HOFS16(data | 0); + break; + case 37: + renderer.writeBG2VOFS8_0(data | 0); + break; + case 38: + renderer.writeBG2VOFS8_1(data | 0); + break; + case 39: + renderer.writeBG2VOFS16(data | 0); + break; + case 40: + renderer.writeBG2OFS32(data | 0); + break; + case 41: + renderer.writeBG3HOFS8_0(data | 0); + break; + case 42: + renderer.writeBG3HOFS8_1(data | 0); + break; + case 43: + renderer.writeBG3HOFS16(data | 0); + break; + case 44: + renderer.writeBG3VOFS8_0(data | 0); + break; + case 45: + renderer.writeBG3VOFS8_1(data | 0); + break; + case 46: + renderer.writeBG3VOFS16(data | 0); + break; + case 47: + renderer.writeBG3OFS32(data | 0); + break; + case 48: + renderer.writeBG2PA8_0(data | 0); + break; + case 49: + renderer.writeBG2PA8_1(data | 0); + break; + case 50: + renderer.writeBG2PA16(data | 0); + break; + case 51: + renderer.writeBG2PB8_0(data | 0); + break; + case 52: + renderer.writeBG2PB8_1(data | 0); + break; + case 53: + renderer.writeBG2PB16(data | 0); + break; + case 54: + renderer.writeBG2PAB32(data | 0); + break; + case 55: + renderer.writeBG2PC8_0(data | 0); + break; + case 56: + renderer.writeBG2PC8_1(data | 0); + break; + case 57: + renderer.writeBG2PC16(data | 0); + break; + case 58: + renderer.writeBG2PD8_0(data | 0); + break; + case 59: + renderer.writeBG2PD8_1(data | 0); + break; + case 60: + renderer.writeBG2PD16(data | 0); + break; + case 61: + renderer.writeBG2PCD32(data | 0); + break; + case 62: + renderer.writeBG3PA8_0(data | 0); + break; + case 63: + renderer.writeBG3PA8_1(data | 0); + break; + case 64: + renderer.writeBG3PA16(data | 0); + break; + case 65: + renderer.writeBG3PB8_0(data | 0); + break; + case 66: + renderer.writeBG3PB8_1(data | 0); + break; + case 67: + renderer.writeBG3PB16(data | 0); + break; + case 68: + renderer.writeBG3PAB32(data | 0); + break; + case 69: + renderer.writeBG3PC8_0(data | 0); + break; + case 70: + renderer.writeBG3PC8_1(data | 0); + break; + case 71: + renderer.writeBG3PC16(data | 0); + break; + case 72: + renderer.writeBG3PD8_0(data | 0); + break; + case 73: + renderer.writeBG3PD8_1(data | 0); + break; + case 74: + renderer.writeBG3PD16(data | 0); + break; + case 75: + renderer.writeBG3PCD32(data | 0); + break; + case 76: + renderer.writeBG2X8_0(data | 0); + break; + case 77: + renderer.writeBG2X8_1(data | 0); + break; + case 78: + renderer.writeBG2X8_2(data | 0); + break; + case 79: + renderer.writeBG2X8_3(data | 0); + break; + case 80: + renderer.writeBG2X16_0(data | 0); + break; + case 81: + renderer.writeBG2X16_1(data | 0); + break; + case 82: + renderer.writeBG2X32(data | 0); + break; + case 83: + renderer.writeBG2Y8_0(data | 0); + break; + case 84: + renderer.writeBG2Y8_1(data | 0); + break; + case 85: + renderer.writeBG2Y8_2(data | 0); + break; + case 86: + renderer.writeBG2Y8_3(data | 0); + break; + case 87: + renderer.writeBG2Y16_0(data | 0); + break; + case 88: + renderer.writeBG2Y16_1(data | 0); + break; + case 89: + renderer.writeBG2Y32(data | 0); + break; + case 90: + renderer.writeBG3X8_0(data | 0); + break; + case 91: + renderer.writeBG3X8_1(data | 0); + break; + case 92: + renderer.writeBG3X8_2(data | 0); + break; + case 93: + renderer.writeBG3X8_3(data | 0); + break; + case 94: + renderer.writeBG3X16_0(data | 0); + break; + case 95: + renderer.writeBG3X16_1(data | 0); + break; + case 96: + renderer.writeBG3X32(data | 0); + break; + case 97: + renderer.writeBG3Y8_0(data | 0); + break; + case 98: + renderer.writeBG3Y8_1(data | 0); + break; + case 99: + renderer.writeBG3Y8_2(data | 0); + break; + case 100: + renderer.writeBG3Y8_3(data | 0); + break; + case 101: + renderer.writeBG3Y16_0(data | 0); + break; + case 102: + renderer.writeBG3Y16_1(data | 0); + break; + case 103: + renderer.writeBG3Y32(data | 0); + break; + case 104: + renderer.writeWIN0XCOORDRight8(data | 0); + break; + case 105: + renderer.writeWIN0XCOORDLeft8(data | 0); + break; + case 106: + renderer.writeWIN0XCOORD16(data | 0); + break; + case 107: + renderer.writeWIN1XCOORDRight8(data | 0); + break; + case 108: + renderer.writeWIN1XCOORDLeft8(data | 0); + break; + case 109: + renderer.writeWIN1XCOORD16(data | 0); + break; + case 110: + renderer.writeWINXCOORD32(data | 0); + break; + case 111: + renderer.writeWIN0YCOORDBottom8(data | 0); + break; + case 112: + renderer.writeWIN0YCOORDTop8(data | 0); + break; + case 113: + renderer.writeWIN0YCOORD16(data | 0); + break; + case 114: + renderer.writeWIN1YCOORDBottom8(data | 0); + break; + case 115: + renderer.writeWIN1YCOORDTop8(data | 0); + break; + case 116: + renderer.writeWIN1YCOORD16(data | 0); + break; + case 117: + renderer.writeWINYCOORD32(data | 0); + break; + case 118: + renderer.writeWIN0IN8(data | 0); + break; + case 119: + renderer.writeWIN1IN8(data | 0); + break; + case 120: + renderer.writeWININ16(data | 0); + break; + case 121: + renderer.writeWINOUT8(data | 0); + break; + case 122: + renderer.writeWINOBJIN8(data | 0); + break; + case 123: + renderer.writeWINOUT16(data | 0); + break; + case 124: + renderer.writeWINCONTROL32(data | 0); + break; + case 125: + renderer.writeMOSAIC8_0(data | 0); + break; + case 126: + renderer.writeMOSAIC8_1(data | 0); + break; + case 127: + renderer.writeMOSAIC16(data | 0); + break; + case 128: + renderer.writeBLDCNT8_0(data | 0); + break; + case 129: + renderer.writeBLDCNT8_1(data | 0); + break; + case 130: + renderer.writeBLDCNT16(data | 0); + break; + case 131: + renderer.writeBLDALPHA8_0(data | 0); + break; + case 132: + renderer.writeBLDALPHA8_1(data | 0); + break; + case 133: + renderer.writeBLDALPHA16(data | 0); + break; + case 134: + renderer.writeBLDCNT32(data | 0); + break; + default: + renderer.writeBLDY8(data | 0); + } +} +function decodeInternalCommand(data) { + data = data | 0; + switch (data | 0) { + case 0: + renderer.incrementScanLineQueue(); + break; + default: + renderer.ensureFraming(); } } diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/user_scripts/IodineGBAWorkerGlueCodeWorker.js index bd9ce5d..a7a7cb2 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/user_scripts/IodineGBAWorkerGlueCodeWorker.js @@ -33,7 +33,7 @@ importScripts("../IodineGBA/core/CPU/THUMB.js"); importScripts("../IodineGBA/core/CPU/CPSR.js"); importScripts("../IodineGBA/core/graphics/RendererProxy.js"); importScripts("../IodineGBA/core/graphics/RendererShim.js"); -importScripts("../IodineGBA/core/graphics/Renderer.js"); +/*importScripts("../IodineGBA/core/graphics/Renderer.js"); importScripts("../IodineGBA/core/graphics/BGTEXT.js"); importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); importScripts("../IodineGBA/core/graphics/BGMatrix.js"); @@ -43,7 +43,7 @@ importScripts("../IodineGBA/core/graphics/Mosaic.js"); importScripts("../IodineGBA/core/graphics/OBJ.js"); importScripts("../IodineGBA/core/graphics/OBJWindow.js"); importScripts("../IodineGBA/core/graphics/Window.js"); -importScripts("../IodineGBA/core/graphics/Compositor.js"); +importScripts("../IodineGBA/core/graphics/Compositor.js");*/ importScripts("../IodineGBA/core/memory/DMA0.js"); importScripts("../IodineGBA/core/memory/DMA1.js"); importScripts("../IodineGBA/core/memory/DMA2.js"); From f00e52c46d6d82cdd2429aaf726856827e05f9af Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sun, 24 Jan 2016 03:29:55 -0500 Subject: [PATCH 15/16] continuation --- .../core/Worker.js | 77 ++++++++++------------ IodineGBA/core/graphics/RendererShim.js | 8 ++- .../graphics/{RendererShimWorker.js => Worker.js} | 35 +++++----- user_scripts/IodineGBACoreGlueCode.js | 2 +- user_scripts/IodineGBAWorkerGlueCode.js | 5 +- 5 files changed, 62 insertions(+), 65 deletions(-) rename user_scripts/IodineGBAWorkerGlueCodeWorker.js => IodineGBA/core/Worker.js (79%) rename IodineGBA/core/graphics/{RendererShimWorker.js => Worker.js} (94%) diff --git a/user_scripts/IodineGBAWorkerGlueCodeWorker.js b/IodineGBA/core/Worker.js similarity index 79% rename from user_scripts/IodineGBAWorkerGlueCodeWorker.js rename to IodineGBA/core/Worker.js index a7a7cb2..74029e2 100644 --- a/user_scripts/IodineGBAWorkerGlueCodeWorker.js +++ b/IodineGBA/core/Worker.js @@ -8,50 +8,39 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -importScripts("../IodineGBA/includes/TypedArrayShim.js"); -importScripts("../IodineGBA/core/Cartridge.js"); -importScripts("../IodineGBA/core/DMA.js"); -importScripts("../IodineGBA/core/Emulator.js"); -importScripts("../IodineGBA/core/Graphics.js"); -importScripts("../IodineGBA/core/RunLoop.js"); -importScripts("../IodineGBA/core/Memory.js"); -importScripts("../IodineGBA/core/IRQ.js"); -importScripts("../IodineGBA/core/JoyPad.js"); -importScripts("../IodineGBA/core/Serial.js"); -importScripts("../IodineGBA/core/Sound.js"); -importScripts("../IodineGBA/core/Timer.js"); -importScripts("../IodineGBA/core/Wait.js"); -importScripts("../IodineGBA/core/CPU.js"); -importScripts("../IodineGBA/core/Saves.js"); -importScripts("../IodineGBA/core/sound/FIFO.js"); -importScripts("../IodineGBA/core/sound/Channel1.js"); -importScripts("../IodineGBA/core/sound/Channel2.js"); -importScripts("../IodineGBA/core/sound/Channel3.js"); -importScripts("../IodineGBA/core/sound/Channel4.js"); -importScripts("../IodineGBA/core/CPU/ARM.js"); -importScripts("../IodineGBA/core/CPU/THUMB.js"); -importScripts("../IodineGBA/core/CPU/CPSR.js"); -importScripts("../IodineGBA/core/graphics/RendererProxy.js"); -importScripts("../IodineGBA/core/graphics/RendererShim.js"); -/*importScripts("../IodineGBA/core/graphics/Renderer.js"); -importScripts("../IodineGBA/core/graphics/BGTEXT.js"); -importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); -importScripts("../IodineGBA/core/graphics/BGMatrix.js"); -importScripts("../IodineGBA/core/graphics/AffineBG.js"); -importScripts("../IodineGBA/core/graphics/ColorEffects.js"); -importScripts("../IodineGBA/core/graphics/Mosaic.js"); -importScripts("../IodineGBA/core/graphics/OBJ.js"); -importScripts("../IodineGBA/core/graphics/OBJWindow.js"); -importScripts("../IodineGBA/core/graphics/Window.js"); -importScripts("../IodineGBA/core/graphics/Compositor.js");*/ -importScripts("../IodineGBA/core/memory/DMA0.js"); -importScripts("../IodineGBA/core/memory/DMA1.js"); -importScripts("../IodineGBA/core/memory/DMA2.js"); -importScripts("../IodineGBA/core/memory/DMA3.js"); -importScripts("../IodineGBA/core/cartridge/SaveDeterminer.js"); -importScripts("../IodineGBA/core/cartridge/SRAM.js"); -importScripts("../IodineGBA/core/cartridge/FLASH.js"); -importScripts("../IodineGBA/core/cartridge/EEPROM.js"); +importScripts("../includes/TypedArrayShim.js"); +importScripts("Cartridge.js"); +importScripts("DMA.js"); +importScripts("Emulator.js"); +importScripts("Graphics.js"); +importScripts("RunLoop.js"); +importScripts("Memory.js"); +importScripts("IRQ.js"); +importScripts("JoyPad.js"); +importScripts("Serial.js"); +importScripts("Sound.js"); +importScripts("Timer.js"); +importScripts("Wait.js"); +importScripts("CPU.js"); +importScripts("Saves.js"); +importScripts("sound/FIFO.js"); +importScripts("sound/Channel1.js"); +importScripts("sound/Channel2.js"); +importScripts("sound/Channel3.js"); +importScripts("sound/Channel4.js"); +importScripts("CPU/ARM.js"); +importScripts("CPU/THUMB.js"); +importScripts("CPU/CPSR.js"); +importScripts("graphics/RendererProxy.js"); +importScripts("graphics/RendererShim.js"); +importScripts("memory/DMA0.js"); +importScripts("memory/DMA1.js"); +importScripts("memory/DMA2.js"); +importScripts("memory/DMA3.js"); +importScripts("cartridge/SaveDeterminer.js"); +importScripts("cartridge/SRAM.js"); +importScripts("cartridge/FLASH.js"); +importScripts("cartridge/EEPROM.js"); var Iodine = new GameBoyAdvanceEmulator(); //Save callbacks waiting to be satisfied: var saveImportPool = []; diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index fed275c..d4695e0 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -9,7 +9,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ function getGameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS) { - if (!window.SharedArrayBuffer || !Atomics) { + if (typeof SharedArrayBuffer != "function" || typeof Atomics != "object") { return new GameBoyAdvanceGraphicsRenderer(coreExposed, skippingBIOS); } else { @@ -25,7 +25,11 @@ } GameBoyAdvanceGraphicsRendererShim.prototype.initializeWorker = function (skippingBIOS) { skippingBIOS = !!skippingBIOS; - this.worker = new Worker("RendererShimWorker.js"); + var loc = location.href; + loc = loc.split("/"); + loc = loc.slice(0, loc.length - 1).join("/"); + loc += "/graphics/Worker.js"; + this.worker = new Worker(loc); this.worker.postMessage({ messageID:2, skippingBIOS:!!skippingBIOS diff --git a/IodineGBA/core/graphics/RendererShimWorker.js b/IodineGBA/core/graphics/Worker.js similarity index 94% rename from IodineGBA/core/graphics/RendererShimWorker.js rename to IodineGBA/core/graphics/Worker.js index d2957af..6b648a2 100644 --- a/IodineGBA/core/graphics/RendererShimWorker.js +++ b/IodineGBA/core/graphics/Worker.js @@ -8,18 +8,18 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -importScripts("../IodineGBA/includes/TypedArrayShim.js"); -importScripts("../IodineGBA/core/graphics/Renderer.js"); -importScripts("../IodineGBA/core/graphics/BGTEXT.js"); -importScripts("../IodineGBA/core/graphics/BG2FrameBuffer.js"); -importScripts("../IodineGBA/core/graphics/BGMatrix.js"); -importScripts("../IodineGBA/core/graphics/AffineBG.js"); -importScripts("../IodineGBA/core/graphics/ColorEffects.js"); -importScripts("../IodineGBA/core/graphics/Mosaic.js"); -importScripts("../IodineGBA/core/graphics/OBJ.js"); -importScripts("../IodineGBA/core/graphics/OBJWindow.js"); -importScripts("../IodineGBA/core/graphics/Window.js"); -importScripts("../IodineGBA/core/graphics/Compositor.js"); +importScripts("../../includes/TypedArrayShim.js"); +importScripts("Renderer.js"); +importScripts("BGTEXT.js"); +importScripts("BG2FrameBuffer.js"); +importScripts("BGMatrix.js"); +importScripts("AffineBG.js"); +importScripts("ColorEffects.js"); +importScripts("Mosaic.js"); +importScripts("OBJ.js"); +importScripts("OBJWindow.js"); +importScripts("Window.js"); +importScripts("Compositor.js"); var renderer = null; var gfxBuffers = null; var gfxCounters = null; @@ -63,11 +63,11 @@ function initializeRenderer(skippingBIOS) { skippingBIOS = !!skippingBIOS; renderer = new GameBoyAdvanceGraphicsRenderer(coreExposed, !!skippingBIOS); } -function assignBuffers(gfxBuffers, gfxCounters, gfxCommandBuffer, gfxCommandCounters) { - gfxBuffers = gfxBuffers; - gfxCounters = gfxCounters; - gfxCommandBuffer = gfxCommandBuffer; - gfxCommandCounters = gfxCommandCounters; +function assignBuffers(gfxb, gfxc, cmdb, cmdc) { + gfxBuffers = gfxb; + gfxCounters = gfxc; + gfxCommandBuffer = cmdb; + gfxCommandCounters = cmdc; } function processCommands() { //Load the counter values: @@ -87,6 +87,7 @@ function processCommands() { } while ((startCorrected | 0) != (endCorrected | 0)); //Update the starting position counter to match the end position: Atomics.store(gfxCommandCounters, 0, end | 0); + Atomics.futexWake(gfxCommandCounters, 1, end | 0); } function dispatchCommand(command, data) { command = command | 0; diff --git a/user_scripts/IodineGBACoreGlueCode.js b/user_scripts/IodineGBACoreGlueCode.js index 913c79e..326406b 100644 --- a/user_scripts/IodineGBACoreGlueCode.js +++ b/user_scripts/IodineGBACoreGlueCode.js @@ -64,7 +64,7 @@ window.onload = function () { function registerIodineHandler() { try { //Will run like shit if missing some of this for the webworker copy: - if (!window.SharedArrayBuffer || !Atomics) { + if (typeof SharedArrayBuffer != "function" || typeof Atomics != "object") { throw null; } //Try starting Iodine in a webworker: diff --git a/user_scripts/IodineGBAWorkerGlueCode.js b/user_scripts/IodineGBAWorkerGlueCode.js index 99610c3..90a2398 100644 --- a/user_scripts/IodineGBAWorkerGlueCode.js +++ b/user_scripts/IodineGBAWorkerGlueCode.js @@ -29,7 +29,10 @@ var tempvar = document.getElementsByTagName("script"); IodineGBAWorkerShim.prototype.filepath = tempvar[tempvar.length-1].src; IodineGBAWorkerShim.prototype.initialize = function () { var parentObj = this; - this.worker = new Worker(this.filepath.substring(0, (this.filepath.length | 0) - 3) + "Worker.js"); + var loc = this.filepath.split("/"); + loc = loc.slice(0, loc.length - 2).join("/"); + loc += "/IodineGBA/core/Worker.js"; + this.worker = new Worker(loc); this.worker.onmessage = function (event) { parentObj.decodeMessage(event.data); } From f6892ef77d5cb78c702273ed56c167b561769f2d Mon Sep 17 00:00:00 2001 From: Grant Galitz Date: Sun, 24 Jan 2016 05:40:34 -0500 Subject: [PATCH 16/16] Wrap up off thread gfx --- IodineGBA/core/graphics/RendererShim.js | 60 ++++++++++++++++++++++++++------- IodineGBA/core/graphics/Worker.js | 4 +-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/IodineGBA/core/graphics/RendererShim.js b/IodineGBA/core/graphics/RendererShim.js index d4695e0..e3b4fc7 100644 --- a/IodineGBA/core/graphics/RendererShim.js +++ b/IodineGBA/core/graphics/RendererShim.js @@ -114,6 +114,42 @@ GameBoyAdvanceGraphicsRendererShim.prototype.synchronizeReader = function () { //Load command buffer reader counter value: this.start = Atomics.load(this.gfxCommandCounters, 0) | 0; } +GameBoyAdvanceGraphicsRendererShim.prototype.pushVRAM16 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0xFFFF; + this.pushCommand(0x10000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.pushVRAM32 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0x7FFF; + this.pushCommand(0x20000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.pushPAL16 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0x1FF; + this.pushCommand(0x30000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.pushPAL32 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0xFF; + this.pushCommand(0x40000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.pushOAM16 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0x1FF; + this.pushCommand(0x50000 | address, data | 0); +} +GameBoyAdvanceGraphicsRendererShim.prototype.pushOAM32 = function (address, data) { + address = address | 0; + data = data | 0; + address = address & 0xFF; + this.pushCommand(0x60000 | address, data | 0); +} GameBoyAdvanceGraphicsRendererShim.prototype.incrementScanLineQueue = function () { //Increment scan line command: this.pushCommand(0, 0); @@ -668,13 +704,13 @@ if (__LITTLE_ENDIAN__) { address = address | 0; data = data | 0; this.VRAM16[address & 0xFFFF] = data & 0xFFFF; - this.pushCommand(0x20000 | address, data | 0); + this.pushVRAM16(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { address = address | 0; data = data | 0; this.VRAM32[address & 0x7FFF] = data | 0; - this.pushCommand(0x40000 | address, data | 0); + this.pushVRAM32(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { address = address | 0; @@ -688,13 +724,13 @@ if (__LITTLE_ENDIAN__) { data = data | 0; address = address | 0; this.paletteRAM16[address & 0x1FF] = data & 0xFFFF; - this.pushCommand(0x60000 | address, data | 0); + this.pushPAL16(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { data = data | 0; address = address | 0; this.paletteRAM32[address & 0xFF] = data | 0; - this.pushCommand(0x80000 | address, data | 0); + this.pushPAL32(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { address = address | 0; @@ -708,13 +744,13 @@ if (__LITTLE_ENDIAN__) { address = address | 0; data = data | 0; this.OAMRAM16[address & 0x1FF] = data & 0xFFFF; - this.pushCommand(0xA0000 | address, data | 0); + this.pushOAM16(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { address = address | 0; data = data | 0; this.OAMRAM32[address & 0xFF] = data | 0; - this.pushCommand(0xC0000 | address, data | 0); + this.pushOAM32(address | 0, data | 0); } GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { address = address | 0; @@ -732,7 +768,7 @@ else { address &= 0x1FFFE; this.VRAM[address] = data & 0xFF; this.VRAM[address + 1] = (data >> 8) & 0xFF; - this.pushCommand(0x20000 | address, data); + this.pushVRAM16(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.writeVRAM32 = function (address, data) { address <<= 2; @@ -741,7 +777,7 @@ else { this.VRAM[address + 1] = (data >> 8) & 0xFF; this.VRAM[address + 2] = (data >> 16) & 0xFF; this.VRAM[address + 3] = data >>> 24; - this.pushCommand(0x40000 | address, data | 0); + this.pushVRAM32(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.readVRAM16 = function (address) { address <<= 1; @@ -756,7 +792,7 @@ else { GameBoyAdvanceGraphicsRendererShim.prototype.writePalette16 = function (address, data) { this.paletteRAM[address << 1] = data & 0xFF; this.paletteRAM[(address << 1) + 1] = data >> 8; - this.pushCommand(0x60000 | address, data | 0); + this.pushPAL16(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.writePalette32 = function (address, data) { address <<= 2; @@ -765,7 +801,7 @@ else { this.paletteRAM[address | 2] = (data >> 16) & 0xFF; this.paletteRAM[address | 3] = data >>> 24; address >>= 2; - this.pushCommand(0x80000 | address, data | 0); + this.pushPAL32(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.readPalette16 = function (address) { address &= 0x3FE; @@ -779,7 +815,7 @@ else { address &= 0x1FF; this.OAMRAM[address << 1] = data & 0xFF; this.OAMRAM[(address << 1) | 1] = data >> 8; - this.pushCommand(0xA0000 | address, data); + this.pushOAM16(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.writeOAM32 = function (address, data) { address &= 0xFF; @@ -789,7 +825,7 @@ else { this.OAMRAM[address + 2] = (data >> 16) & 0xFF; this.OAMRAM[address + 3] = data >>> 24; address >>= 2; - this.pushCommand(0xC0000 | address, data); + this.pushOAM32(address, data); } GameBoyAdvanceGraphicsRendererShim.prototype.readOAM16 = function (address) { address &= 0x1FF; diff --git a/IodineGBA/core/graphics/Worker.js b/IodineGBA/core/graphics/Worker.js index 6b648a2..6e4d1c0 100644 --- a/IodineGBA/core/graphics/Worker.js +++ b/IodineGBA/core/graphics/Worker.js @@ -83,7 +83,7 @@ function processCommands() { var endCorrected = end & 0x7FFFF; do { dispatchCommand(gfxCommandBuffer[startCorrected | 0] | 0, gfxCommandBuffer[startCorrected | 1] | 0); - startCorrected = ((startCorrected | 0) + 2) | 0; + startCorrected = ((startCorrected | 0) + 2) & 0x7FFFF; } while ((startCorrected | 0) != (endCorrected | 0)); //Update the starting position counter to match the end position: Atomics.store(gfxCommandCounters, 0, end | 0); @@ -92,7 +92,7 @@ function processCommands() { function dispatchCommand(command, data) { command = command | 0; data = data | 0; - switch (command >> 17) { + switch (command >> 16) { //IO: case 0: dispatchIOCommand(command | 0, data | 0);