Created
May 15, 2012 19:48
-
-
Save jocull/2704564 to your computer and use it in GitHub Desktop.
http://gamecenter.grantgalitz.org on 5/15/12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var windowingInitialized = !1, | |
inFullscreen = !1, | |
shortcutHashes = [ | |
["PokemonRed", 25, "PokemonRed.gb"], | |
["PokemonBlue", 26, "PokemonBlue.gb"], | |
["PokemonYellow", 27, "PokemonYellow.gbc"], | |
["PokemonSilver", 28, "PokemonSilver.gbc"], | |
["PokemonGold", 29, "PokemonGold.gbc"], | |
["PokemonCrystal", 30, "PokemonCrystal.gbc"], | |
["PokemonPinball", 31, "PokemonPinball.gbc"], | |
["PokemonTradingCardGame", 32, "PokemonTradingCardGame.gbc"], | |
["PokemonTradingCardGame2", 33, "PokemonCardGame2.gbc"] | |
]; | |
function windowingPreInitUnsafe() { | |
windowingInitialized || (windowingInitialized = !0, windowingInitialize()) | |
} | |
function windowingPreInitSafe() { | |
("undefined" == typeof document.readyState || "complete" == document.readyState) && windowingPreInitUnsafe() | |
} | |
function windowingInitUnload() { | |
removeEvent("DOMContentLoaded", document, windowingPreInitUnsafe); | |
removeEvent("readystatechange", document, windowingPreInitSafe); | |
removeEvent("load", document, windowingPreInitUnsafe) | |
} | |
function windowingInitialize() { | |
windowingInitUnload(); | |
try { | |
registerGUIEvents(), matchHashbang() | |
} catch (a) { | |
alert('Fatal initialization error: "' + a.message + '" file:' + a.fileName + " line: " + a.lineNumber, 2) | |
} | |
} | |
function matchHashbang() { | |
for (var a = shortcutHashes.length, b = 0; b < a; ++b) if (window.location.hash == "#" + shortcutHashes[b][0]) { | |
runShortcut(shortcutHashes[b]); | |
return | |
} | |
document.getElementById("dropdown_select").selectedIndex = 0 | |
} | |
function runShortcut(a) { | |
document.getElementById("dropdown_select").selectedIndex = a[1]; | |
try { | |
document.getElementById("dropdown_progress").style.display = "block", new Ajax({ | |
URL: "./romStorage/" + a[2] + ".txt", | |
Accept: "TEXT", | |
Cached: !0, | |
Complete: function (a, b) { | |
try { | |
initPlayer(), start(document.getElementById("game_canvas"), base64_decode(b)) | |
} catch (f) { | |
alert(f.message + " file: " + f.fileName + " line: " + f.lineNumber) | |
} | |
} | |
}) | |
} catch (b) { | |
alert(b.message + " file: " + b.fileName + " line: " + b.lineNumber) | |
} | |
} | |
function keyCodeOverride(a) { | |
switch (a.keyCode) { | |
case 74: | |
case 88: | |
settings[3][4] = a.keyCode; | |
break; | |
case 81: | |
case 89: | |
case 90: | |
settings[3][5] = a.keyCode | |
} | |
return a | |
} | |
function registerGUIEvents() { | |
document.getElementById("enable_sound").checked = settings[0]; | |
document.getElementById("gb_boot_rom_utilized").checked = settings[11]; | |
addEvent("keydown", document, function (a) { | |
switch (a.keyCode) { | |
case 27: | |
fullscreenPlayer(); | |
break; | |
case 68: | |
lowerVolume(); | |
break; | |
case 82: | |
raiseVolume(); | |
break; | |
default: | |
GameBoyKeyDown(keyCodeOverride(a)) | |
} | |
}); | |
addEvent("keyup", document, function (a) { | |
GameBoyKeyUp(keyCodeOverride(a)) | |
}); | |
addEvent("MozOrientation", window, GameBoyGyroSignalHandler); | |
addEvent("deviceorientation", window, GameBoyGyroSignalHandler); | |
var a = document.getElementById("dropdown_select"); | |
a.value = "none"; | |
addEvent("change", a, function () { | |
var b = this.value; | |
if ("none" != b) try { | |
document.getElementById("dropdown_progress").style.display = "block", new Ajax({ | |
URL: "./romStorage/" + b + ".txt", | |
Accept: "TEXT", | |
Cached: !0, | |
Complete: function (a, b) { | |
try { | |
initPlayer(), start(document.getElementById("game_canvas"), base64_decode(b)) | |
} catch (c) { | |
alert(c.message + " file: " + c.fileName + " line: " + c.lineNumber) | |
} | |
} | |
}), a.blur() | |
} catch (c) { | |
alert(c.message + " file: " + c.fileName + " line: " + c.lineNumber) | |
} | |
}); | |
addEvent("dragover", document.getElementById("gameboy"), stopDragPropagation); | |
addEvent("drop", document.getElementById("gameboy"), function (a) { | |
stopDragPropagation(a); | |
if (a.dataTransfer && a.dataTransfer.files && 0 < a.dataTransfer.files.length) try { | |
var c = new FileReader; | |
c.readAsBinaryString(a.dataTransfer.files[0]); | |
c.onload = function (a) { | |
try { | |
initPlayer(), start(document.getElementById("game_canvas"), a.target.result) | |
} catch (b) { | |
alert(b.message + " file: " + b.fileName + " line: " + b.lineNumber) | |
} | |
} | |
} catch (e) { | |
alert(e.message + " file: " + e.fileName + " line: " + e.lineNumber) | |
} | |
}); | |
addEvent("click", document.getElementById("enable_sound"), function () { | |
settings[0] = document.getElementById("enable_sound").checked; | |
GameBoyEmulatorInitialized() && gameboy.initSound() | |
}); | |
addEvent("click", document.getElementById("gb_boot_rom_utilized"), function () { | |
settings[11] = document.getElementById("gb_boot_rom_utilized").checked | |
}); | |
addEvent("unload", window, function () { | |
autoSave() | |
}) | |
} | |
function lowerVolume() { | |
settings[13] = Math.max(settings[13] - 0.04, 0); | |
GameBoyEmulatorInitialized() && gameboy.changeVolume() | |
} | |
function raiseVolume() { | |
settings[13] = Math.min(settings[13] + 0.04, 1); | |
GameBoyEmulatorInitialized() && gameboy.changeVolume() | |
} | |
function stopDragPropagation(a) { | |
a.stopPropagation(); | |
a.preventDefault() | |
} | |
function initPlayer() { | |
document.getElementById("dropdown_progress").style.display = "none"; | |
document.getElementById("master_container").style.display = "inline-block"; | |
document.getElementById("fullscreenCanvas").style.display = "none" | |
} | |
function fullscreenPlayer() { | |
GameBoyEmulatorInitialized() ? (inFullscreen ? (gameboy.canvas = document.getElementById("game_canvas"), document.getElementById("fullscreenCanvas").style.display = "none", document.getElementById("master_container").style.display = "inline-block") : (gameboy.canvas = document.getElementById("fullscreenCanvas"), gameboy.canvas.style.display = "block", document.getElementById("master_container").style.display = "none"), gameboy.initLCD(), inFullscreen = !inFullscreen) : cout("Cannot go into fullscreen mode.", 2) | |
} | |
function findValue(a) { | |
try { | |
if (null != window.localStorage.getItem(a)) return JSON.parse(window.localStorage.getItem(a)) | |
} catch (b) { | |
if (null != window.globalStorage[location.hostname].getItem(a)) return JSON.parse(window.globalStorage[location.hostname].getItem(a)) | |
} | |
return null | |
} | |
function setValue(a, b) { | |
try { | |
window.localStorage.setItem(a, JSON.stringify(b)) | |
} catch (c) { | |
window.globalStorage[location.hostname].setItem(a, JSON.stringify(b)) | |
} | |
} | |
function deleteValue(a) { | |
try { | |
window.localStorage.removeItem(a) | |
} catch (b) { | |
window.globalStorage[location.hostname].removeItem(a) | |
} | |
} | |
function addEvent(a, b, c) { | |
try { | |
b.addEventListener(a, c, !1), cout('In addEvent() : Standard addEventListener() called to add a(n) "' + a + '" event.', -1) | |
} catch (e) { | |
b.attachEvent("on" + a, c), cout('In addEvent() : Nonstandard attachEvent() called to add an "on' + a + '" event.', -1) | |
} | |
} | |
function removeEvent(a, b, c) { | |
try { | |
b.removeEventListener(a, c, !1), cout('In removeEvent() : Standard removeEventListener() called to remove a(n) "' + a + '" event.', -1) | |
} catch (e) { | |
b.detachEvent("on" + a, c), cout('In removeEvent() : Nonstandard detachEvent() called to remove an "on' + a + '" event.', -1) | |
} | |
} | |
function cout(a, b) { | |
switch (b) { | |
case 0: | |
outputMessage("<DEBUG>: " + a, "white"); | |
break; | |
case 1: | |
outputMessage("<WARNING>: " + a, "yellow"); | |
break; | |
case 2: | |
outputMessage("<ERROR>: " + a, "red") | |
} | |
} | |
function outputMessage(a, b) { | |
var c = document.getElementById("debug_log"), | |
e = document.createTextNode(a), | |
f = document.createElement("div"); | |
f.appendChild(e); | |
f.style.color = b; | |
c.appendChild(f); | |
c.style.display = "block" | |
} | |
var toBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(""), | |
fromBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
function base64(a) { | |
try { | |
var b = window.btoa(a) | |
} catch (c) { | |
var b = "", | |
e = a.length; | |
if (0 < e) { | |
for (var f = [0, 0, 0], g = 0, d = e % 3; 0 < a.length % 3;) a[a.length] = " "; | |
for (; g < e;) f = [a.charCodeAt(g++) & 255, a.charCodeAt(g++) & 255, a.charCodeAt(g++) & 255], b += toBase64[f[0] >> 2] + toBase64[(f[0] & 3) << 4 | f[1] >> 4] + toBase64[(f[1] & 15) << 2 | f[2] >> 6] + toBase64[f[2] & 63]; | |
0 < d && (b[b.length - 1] = "=", 2 == d ? (b[b.length - 2] = "=", b[b.length - 3] = toBase64[(f[0] & 3) << 4]) : b[b.length - 2] = toBase64[(f[1] & 15) << 2]) | |
} | |
} | |
return b | |
} | |
function base64_decode(a) { | |
try { | |
var b = window.atob(a) | |
} catch (c) { | |
var b = "", | |
e = a.length; | |
if (3 < e && 0 == e % 4) { | |
for (var f = [0, 0, 0, 0], g = 0; g < e;) f = [fromBase64.indexOf(a.charAt(g++)), fromBase64.indexOf(a.charAt(g++)), fromBase64.indexOf(a.charAt(g++)), fromBase64.indexOf(a.charAt(g++))], b += String.fromCharCode(f[0] << 2 | f[1] >> 4) + String.fromCharCode((f[1] & 15) << 4 | f[2] >> 2) + String.fromCharCode((f[2] & 3) << 6 | f[3]); | |
64 <= f[3] && (b.length -= 1, 64 <= f[2] && (b.length -= 1)) | |
} | |
} | |
return b | |
} | |
function to_little_endian_dword(a) { | |
return to_little_endian_word(a) + String.fromCharCode(a >> 16 & 255, a >> 24 & 255) | |
} | |
function to_little_endian_word(a) { | |
return to_byte(a) + String.fromCharCode(a >> 8 & 255) | |
} | |
function to_byte(a) { | |
return String.fromCharCode(a & 255) | |
} | |
function arrayToBase64(a) { | |
for (var b = "", c = a.length, e = 0; e < c; ++e) "number" == typeof a[e] && (b += String.fromCharCode(a[e])); | |
return base64(b) | |
} | |
function base64ToArray(a) { | |
for (var a = base64_decode(a), b = [], c = a.length, e = 0; e < c;) b.push(a.charCodeAt(e++) & 255); | |
return b | |
} | |
function Ajax(a) { | |
this.typeCheck("object", a); | |
if (null != a) { | |
this.Method = 3; | |
this.MethodCodes = ["XMLHttpRequest", "ActiveXObject", "iFrameMethod", "NONE"]; | |
this.Status = 0; | |
this.StatusCodes = ["initializing", "loading", "complete", "failed"]; | |
this.pArguments = null; | |
this.sSelectedURL = this.sActiveXURL = this.sIFrameURL = this.sXMLURL = this.sURL = ""; | |
this.bReadyStateChangeSupported = !1; | |
this.bAsynchronous = !0; | |
this.bEmptyResponseAllowed = this.bCached = !1; | |
this.fFail = function () {}; | |
this.fLoading = function () {}; | |
this.bAcceptEnforce = !0; | |
this.sAcceptType = "AUTO"; | |
this.ajaxHandle = null; | |
this.fComplete = function () {}; | |
this.aPost = []; | |
this.aGet = []; | |
this.nTimeout = 60; | |
this.aOrder = [0, 1, 2]; | |
this.bRetryAllowed = !0; | |
this.nIFrameSafeTimeout = 1E3; | |
this.aXMLPost = []; | |
this.aActiveXPost = []; | |
this.aIFramePost = []; | |
this.aXMLGet = []; | |
this.aActiveXGet = []; | |
this.aIFrameGet = []; | |
this.aSelectedGet = []; | |
this.aSelectedPost = []; | |
this.sIFrameAcceptType = this.sActiveXAcceptType = this.sXMLAcceptType = this.sSelectedAcceptType = "AUTO"; | |
this.StartTime = this.timestamp(); | |
var b = null; | |
for (b in a) { | |
switch (b) { | |
case "URL": | |
case "XMLURL": | |
case "ActiveXURL": | |
case "IFrameURL": | |
case "Accept": | |
case "XMLAccept": | |
case "ActiveXAccept": | |
case "IFrameAccept": | |
this.typeCheck("string", a[b]); | |
break; | |
case "Asynchronous": | |
case "Cached": | |
case "EmptyResponseAllowed": | |
case "AcceptEnforce": | |
case "TryBackup": | |
this.typeCheck("boolean", a[b]); | |
break; | |
case "Fail": | |
case "Loading": | |
case "Complete": | |
this.typeCheck("function", a[b]); | |
break; | |
case "POST": | |
case "XMLPOST": | |
case "ActiveXPOST": | |
case "IFramePOST": | |
case "GET": | |
case "XMLGET": | |
case "ActiveXGET": | |
case "IFrameGET": | |
case "ORDER": | |
this.typeCheck("object", a[b]); | |
break; | |
case "Timeout": | |
case "IFrameSafeTimeout": | |
this.typeCheck("number", a[b]) | |
} | |
switch (b) { | |
case "XMLURL": | |
this.sXMLURL = a[b]; | |
break; | |
case "IFrameURL": | |
this.sIFrameURL = a[b]; | |
break; | |
case "ActiveXURL": | |
this.sActiveXURL = a[b]; | |
break; | |
case "URL": | |
this.sURL = a[b]; | |
break; | |
case "Accept": | |
this.sAcceptType = a[b]; | |
break; | |
case "XMLAccept": | |
this.sXMLAcceptType = a[b]; | |
break; | |
case "ActiveXAccept": | |
this.sActiveXAcceptType = a[b]; | |
break; | |
case "IFrameAccept": | |
this.sIFrameAcceptType = a[b]; | |
break; | |
case "Asynchronous": | |
this.bAsynchronous = a[b]; | |
break; | |
case "Cached": | |
this.bCached = a[b]; | |
break; | |
case "EmptyResponseAllowed": | |
this.bEmptyResponseAllowed = a[b]; | |
break; | |
case "AcceptEnforce": | |
this.bAcceptEnforce = a[b]; | |
break; | |
case "TryBackup": | |
this.bRetryAllowed = a[b]; | |
break; | |
case "Fail": | |
this.fFail = a[b]; | |
break; | |
case "Loading": | |
this.fLoading = a[b]; | |
break; | |
case "Complete": | |
this.fComplete = a[b]; | |
break; | |
case "POST": | |
this.aPost = a[b]; | |
break; | |
case "XMLPOST": | |
this.aXMLPost = a[b]; | |
break; | |
case "ActiveXPOST": | |
this.aActiveXPost = a[b]; | |
break; | |
case "IFramePOST": | |
this.aIFramePost = a[b]; | |
break; | |
case "GET": | |
this.aGet = a[b]; | |
break; | |
case "XMLGET": | |
this.aXMLGet = a[b]; | |
break; | |
case "ActiveXGET": | |
this.aActiveXGet = a[b]; | |
break; | |
case "IFrameGET": | |
this.aIFrameGet = a[b]; | |
break; | |
case "ORDER": | |
this.aOrder = a[b]; | |
break; | |
case "Timeout": | |
this.nTimeout = a[b]; | |
break; | |
case "Arguments": | |
this.pArguments = a[b]; | |
break; | |
case "IFrameSafeTimeout": | |
this.nIFrameSafeTimeout = a[b] | |
} | |
} | |
} | |
this.launch() | |
} | |
Ajax.prototype.typeCheck = function (a, b) { | |
if (typeof b != a) throw "Type of a variable found is invalid"; | |
}; | |
Ajax.prototype.timestamp = function () { | |
return (new Date).getTime() | |
}; | |
Ajax.prototype.status = function () { | |
return this.StatusCodes[this.Status] | |
}; | |
Ajax.prototype.abort = function () { | |
this.ajaxHandle.abort(); | |
this.Status = 2 | |
}; | |
Ajax.prototype.method = function () { | |
return this.MethodCodes[this.Method] | |
}; | |
Ajax.prototype.update = function () { | |
this.Status = 1; | |
this.StartTime = this.timestamp(); | |
this.run() | |
}; | |
Ajax.prototype.setupMethodProperties = function () { | |
this.aSelectedGet = this.aGet; | |
this.aSelectedPost = this.aPost; | |
this.sSelectedURL = this.sURL; | |
this.sSelectedAcceptType = this.sAcceptType; | |
switch (this.Method) { | |
case 0: | |
"" != this.sXMLURL && (this.aSelectedGet = this.aXMLGet, this.aSelectedPost = this.aXMLPost, this.sSelectedURL = this.sXMLURL, this.sSelectedAcceptType = this.sXMLAcceptType); | |
break; | |
case 1: | |
"" != this.sActiveXURL && (this.aSelectedGet = this.aActiveXGet, this.aSelectedPost = this.aActiveXPost, this.sSelectedURL = this.sActiveXURL, this.sSelectedAcceptType = this.sActiveXAcceptType); | |
break; | |
case 2: | |
"" != this.sIFrameURL && (this.aSelectedGet = this.aIFrameGet, this.aSelectedPost = this.aIFramePost, this.sSelectedURL = this.sIFrameURL, this.sSelectedAcceptType = this.sIFrameAcceptType) | |
} | |
}; | |
Ajax.prototype.errorCaught = function (a) { | |
for (var b = 0; b < this.aOrder.length; b++) this.aOrder[b] == this.Method && (this.aOrder[b] = -1); | |
this.bRetryAllowed && this.lookupMethods() ? (this.ajaxHandle.abort(), this.update()) : (this.Status = 3, this.ajaxHandle.abort(), this.fFail(a, this.pArguments)) | |
}; | |
Ajax.prototype.CheckXMLHttpRequest = function () { | |
try { | |
this.ajaxHandle = new XMLHttpRequest | |
} catch (a) { | |
return !1 | |
} | |
this.Method = 0; | |
return !0 | |
}; | |
Ajax.prototype.CheckActiveXObject = function () { | |
try { | |
this.ajaxHandle = new ActiveXObject("Msxml2.XMLHTTP.6.0") | |
} catch (a) { | |
try { | |
this.ajaxHandle = new ActiveXObject("Msxml2.XMLHTTP.3.0") | |
} catch (b) { | |
try { | |
this.ajaxHandle = new ActiveXObject("Msxml2.XMLHTTP") | |
} catch (c) { | |
try { | |
this.ajaxHandle = new ActiveXObject("Microsoft.XMLHTTP") | |
} catch (e) { | |
return !1 | |
} | |
} | |
} | |
} | |
this.Method = 1; | |
return !0 | |
}; | |
Ajax.prototype.CheckiFrameMethod = function () { | |
try { | |
this.ajaxHandle = new iFrameMethod(this) | |
} catch (a) { | |
return !1 | |
} | |
this.Method = 2; | |
return !0 | |
}; | |
Ajax.prototype.lookupMethods = function () { | |
for (var a = !1, b = 0; b < this.aOrder.length; b++) { | |
switch (this.aOrder[b]) { | |
case 0: | |
a = this.CheckXMLHttpRequest(); | |
break; | |
case 1: | |
a = this.CheckActiveXObject(); | |
break; | |
case 2: | |
a = this.CheckiFrameMethod() | |
} | |
if (a) return this.setupMethodProperties(), !0 | |
} | |
return !1 | |
}; | |
Ajax.prototype.launch = function () { | |
this.lookupMethods() ? (this.Status = 1, this.fLoading(), this.run()) : this.errorCaught("No data transport method could be found.") | |
}; | |
Ajax.prototype.run = function () { | |
try { | |
if (1 >= this.Method) { | |
this.ajaxHandle.open(0 < this.aSelectedPost.length ? "POST" : "GET", this.sSelectedURL + this.composeGET(), this.bAsynchronous); | |
0 < this.aSelectedPost.length && this.ajaxHandle.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); | |
"number" == typeof this.ajaxHandle.timeout && (this.ajaxHandle.timeout = 1E3 * this.nTimeout); | |
if (this.bAsynchronous) if ("undefined" != typeof this.ajaxHandle.onreadystatechange) { | |
this.bReadyStateChangeSupported = !0; | |
var a = this; | |
this.ajaxHandle.onreadystatechange = function () { | |
a.checkWait() | |
} | |
} else this.checkWait(); | |
this.ajaxHandle.send(0 < this.aSelectedPost.length ? this.composePOST() : null); | |
if (!this.bAsynchronous) { | |
if (this.checkHTTPCode(this.ajaxHandle)) throw "Target file not found."; | |
this.lookupResponse() | |
} | |
} else this.ajaxHandle.generateFrame() | |
} catch (b) { | |
this.errorCaught(b) | |
} | |
}; | |
Ajax.prototype.composeGET = function () { | |
var a = "", | |
b = this.aSelectedGet.slice(0); | |
this.bCached || (b[b.length] = "ajaxtimestamp=" + this.timestamp()); | |
for (var c = 0; c < b.length; c++) a += 0 == c ? "?" : "&", a += b[c]; | |
return a | |
}; | |
Ajax.prototype.composePOST = function () { | |
for (var a = "", b = 0; b < this.aSelectedPost.length; b++) a += this.aSelectedPost[b], b + 1 < this.aSelectedPost.length && (a += "&"); | |
return a | |
}; | |
Ajax.prototype.lookupResponse = function () { | |
var a = null, | |
b = null, | |
c = null; | |
if (1 == this.Status) { | |
"object" == typeof this.ajaxHandle.responseXML && (a = this.inspectXML(this.ajaxHandle.responseXML)); | |
"object" == typeof this.ajaxHandle.responseHTML && (c = this.inspectXML(this.ajaxHandle.responseHTML)); | |
if ("string" == typeof this.ajaxHandle.responseText) { | |
if (b = this.ajaxHandle.responseText, null == a) { | |
a = null; | |
try { | |
a = (new DOMParser).parseFromString(this.ajaxHandle.responseText, "text/xml") | |
} catch (e) { | |
try { | |
a = new ActiveXObject("Microsoft.XMLDOM"), a.async = "false", a.loadXML(this.ajaxHandle.responseText) | |
} catch (f) {} | |
} | |
a = this.inspectXML(a) | |
} | |
} else if (null != c) try { | |
null != c.outerHTML && (b = c.outerHTML) | |
} catch (g) {} | |
if (null != a || null != b || null != c || this.bEmptyResponseAllowed) { | |
if (this.bAcceptEnforce && !this.bEmptyResponseAllowed && ("HTML" == this.sSelectedAcceptType || "XML" == this.sSelectedAcceptType || "TEXT" == this.sSelectedAcceptType)) switch (this.sSelectedAcceptType) { | |
case "HTML": | |
if (null == c) throw "No HTML output."; | |
break; | |
case "TEXT": | |
if (null == b) throw "No TEXT output."; | |
break; | |
case "XML": | |
if (null == a) throw "No XML output."; | |
} | |
this.Status = 2; | |
try { | |
this.fComplete(a, b, c, this.pArguments) | |
} catch (d) { | |
this.errorCaught(d) | |
} | |
} else throw "No data downloaded"; | |
} | |
}; | |
Ajax.prototype.inspectXML = function (a) { | |
return "object" == typeof a && null != a && "object" == typeof a.documentElement ? a : null | |
}; | |
Ajax.prototype.checkHTTPCode = function (a) { | |
var b = !1; | |
if (3 <= a.readyState && "number" == typeof a.status && (200 > a.status || 300 <= a.status)) b = !0; | |
return b | |
}; | |
Ajax.prototype.checkWait = function () { | |
try { | |
if (!(3 == this.Status || 2 == this.Status || "number" != typeof this.ajaxHandle.readyState)) { | |
if (this.checkHTTPCode(this.ajaxHandle)) throw "Target file not found."; | |
switch (this.ajaxHandle.readyState) { | |
case 1: | |
case 2: | |
case 3: | |
if (this.timestamp() - this.StartTime < 1E3 * this.nTimeout) { | |
if (!this.bReadyStateChangeSupported) { | |
var a = this; | |
setTimeout(function () { | |
a.checkWait() | |
}, 1) | |
} | |
} else throw "Timeout was reached by " + (this.timestamp() - this.StartTime) / 1E3 + " seconds."; | |
break; | |
case 4: | |
this.lookupResponse() | |
} | |
} | |
} catch (b) { | |
this.errorCaught(b) | |
} | |
}; | |
function iFrameMethod(a) { | |
this.XHRVars = a; | |
this.formElement = this.iframe = this.responseHTML = this.responseXML = null; | |
this.count = 0; | |
this.cleaned = !1 | |
} | |
iFrameMethod.prototype.generateFrame = function () { | |
for (; null != document.getElementById("iframe_" + this.count);) this.count++; | |
this.iframe = document.createElement("iframe"); | |
this.hide(this.iframe); | |
0 == this.XHRVars.aSelectedPost.length ? this.iframe.src = this.XHRVars.sSelectedURL + this.XHRVars.composeGET() : (this.iframe.id = "iframe_" + this.count, this.iframe.name = "iframe_" + this.count, this.formSetup()); | |
var a = this; | |
"undefined" != typeof this.iframe.attachEvent ? this.iframe.attachEvent("onload", function () { | |
a.populateXHR() | |
}) : "undefined" != typeof this.iframe.onreadystatechange ? this.iframe.onreadystatechange = function () { | |
a.populateXHR() | |
} : "undefined" != typeof this.iframe.addEventListener ? this.iframe.addEventListener("load", function () { | |
a.populateXHR() | |
}, !1) : this.iframe.onload = function () { | |
a.populateXHR() | |
}; | |
document.getElementsByTagName("body")[0].appendChild(this.iframe); | |
null != this.formElement && ("object" == typeof window.self && null != window.self && ("object" == typeof window.self.frames && null != window.self.frames && "object" == typeof window.self.frames["iframe_" + this.count] && null != window.self.frames["iframe_" + this.count] && window.self.frames["iframe_" + this.count].name != "iframe_" + this.count) && (window.self.frames["iframe_" + this.count].name = "iframe_" + this.count), this.formElement.submit()); | |
setTimeout(function () { | |
a.errorMessage("iFrame failed to load.") | |
}, 1E3 * a.XHRVars.nTimeout) | |
}; | |
iFrameMethod.prototype.formSetup = function () { | |
this.formElement = document.createElement("form"); | |
this.hide(this.formElement); | |
this.formElement.action = this.XHRVars.sSelectedURL + this.XHRVars.composeGET(); | |
this.formElement.method = "post"; | |
this.formElement.target = "iframe_" + this.count; | |
for (var a = this.XHRVars.aSelectedPost, b = 0; b < a.length; b++) { | |
var c = document.createElement("input"); | |
this.hide(c); | |
c.type = "hidden"; | |
var e = a[b].split("="); | |
c.name = unescape(e[0]); | |
c.value = unescape(e[1]); | |
this.formElement.appendChild(c) | |
} | |
document.getElementsByTagName("body")[0].appendChild(this.formElement) | |
}; | |
iFrameMethod.prototype.hide = function (a) { | |
a.style.visibility = "hidden"; | |
a.style.height = "0px"; | |
a.style.width = "0px"; | |
a.margin = "0px"; | |
a.padding = "0px"; | |
a.style.zIndex = 1E5; | |
a.style.position = "absolute"; | |
a.style.top = "0px"; | |
a.style.left = "0px" | |
}; | |
iFrameMethod.prototype.errorMessage = function (a) { | |
1 == this.XHRVars.Status && this.XHRVars.errorCaught(a) | |
}; | |
iFrameMethod.prototype.finish = function () { | |
if (1 == this.XHRVars.Status && !this.cleaned) { | |
this.clean(); | |
try { | |
this.XHRVars.lookupResponse() | |
} catch (a) { | |
this.errorMessage(a) | |
} | |
} | |
}; | |
iFrameMethod.prototype.abort = function () { | |
this.clean() | |
}; | |
iFrameMethod.prototype.clean = function () { | |
!this.cleaned && null != this.iframe && (this.cleaned = !0, null != this.formElement && this.formElement.parentNode.removeChild(this.formElement)) | |
}; | |
iFrameMethod.prototype.isHTML = function (a) { | |
return null != a && null != a.documentElement && "HTML" == a.documentElement.nodeName.toUpperCase() && 1 == a.getElementsByTagName("body").length ? !0 : !1 | |
}; | |
iFrameMethod.prototype.populateXHR = function () { | |
try { | |
if (null != this.iframe && !this.cleaned) { | |
if (1 == this.XHRVars.Status) { | |
var a = this; | |
if ("undefined" != typeof this.iframe.readyState) { | |
if ("complete" != this.iframe.readyState) { | |
setTimeout(function () { | |
a.populateXHR() | |
}, 1); | |
return | |
} | |
} else if ("undefined" != typeof this.iframe.contentDocument.readyState && "complete" != this.iframe.contentDocument.readyState) { | |
setTimeout(function () { | |
a.populateXHR() | |
}, 1); | |
return | |
} | |
"undefined" != typeof this.iframe.contentWindow ? "undefined" != typeof this.iframe.contentWindow.document ? (this.responseHTML = this.iframe.contentWindow.document, "undefined" != typeof this.iframe.contentWindow.document.XMLDocument ? this.responseXML = this.iframe.contentWindow.document.XMLDocument : "undefined" != typeof this.iframe.contentDocument && (this.responseXML = this.iframe.contentDocument)) : "undefined" != typeof this.iframe.contentDocument && (this.responseXML = this.iframe.contentDocument) : "undefined" != typeof this.iframe.contentDocument && (this.responseXML = this.iframe.contentDocument); | |
null != this.responseXML && null == this.responseHTML && (this.responseHTML = this.responseXML); | |
if (null != this.responseXML) if (this.responseXML.hasChildNodes()) this.isHTML(this.responseXML) ? "HTML" == this.XHRVars.sSelectedAcceptType && this.isHTML(this.responseHTML) ? setTimeout(function () { | |
a.finish() | |
}, a.XHRVars.nIFrameSafeTimeout) : "undefined" != typeof this.iframe.contentDocument.readyState || "undefined" != typeof this.iframe.readyState ? setTimeout(function () { | |
a.populateXHR() | |
}, 1) : setTimeout(function () { | |
a.populateXHR() | |
}, a.XHRVars.nIFrameSafeTimeout) : this.finish(); | |
else throw "Browser does not support ajax (DOM did not have root node)."; | |
else if (this.isHTML(this.responseHTML)) setTimeout(function () { | |
a.finish() | |
}, a.XHRVars.nIFrameSafeTimeout); | |
else throw "Browser does not support ajax (DOM was null)."; | |
} | |
} else throw "Browser does not support ajax (iframe was null)."; | |
} catch (b) { | |
this.errorMessage(b) | |
} | |
}; | |
this.JSON || (this.JSON = {}); | |
(function () { | |
function a(a) { | |
return a < 10 ? "0" + a : a | |
} | |
function b(a) { | |
f.lastIndex = 0; | |
return f.test(a) ? '"' + a.replace(f, function (a) { | |
var b = h[a]; | |
return typeof b === "string" ? b : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4) | |
}) + '"' : '"' + a + '"' | |
} | |
function c(a, f) { | |
var e, h, t, u, z = g, | |
r, o = f[a]; | |
o && (typeof o === "object" && typeof o.toJSON === "function") && (o = o.toJSON(a)); | |
typeof i === "function" && (o = i.call(f, a, o)); | |
switch (typeof o) { | |
case "string": | |
return b(o); | |
case "number": | |
return isFinite(o) ? "" + o : "null"; | |
case "boolean": | |
case "null": | |
return "" + o; | |
case "object": | |
if (!o) return "null"; | |
g = g + d; | |
r = []; | |
if (Object.prototype.toString.apply(o) === "[object Array]") { | |
u = o.length; | |
for (e = 0; e < u; e = e + 1) r[e] = c(e, o) || "null"; | |
t = r.length === 0 ? "[]" : g ? "[\n" + g + r.join(",\n" + g) + "\n" + z + "]" : "[" + r.join(",") + "]"; | |
g = z; | |
return t | |
} | |
if (i && typeof i === "object") { | |
u = i.length; | |
for (e = 0; e < u; e = e + 1) { | |
h = i[e]; | |
if (typeof h === "string")(t = c(h, o)) && r.push(b(h) + (g ? ": " : ":") + t) | |
} | |
} else for (h in o) if (Object.hasOwnProperty.call(o, h))(t = c(h, o)) && r.push(b(h) + (g ? ": " : ":") + t); | |
t = r.length === 0 ? "{}" : g ? "{\n" + g + r.join(",\n" + g) + "\n" + z + "}" : "{" + r.join(",") + "}"; | |
g = z; | |
return t | |
} | |
} | |
if (typeof Date.prototype.toJSON !== "function") { | |
Date.prototype.toJSON = function () { | |
return isFinite(this.valueOf()) ? this.getUTCFullYear() + "-" + a(this.getUTCMonth() + 1) + "-" + a(this.getUTCDate()) + "T" + a(this.getUTCHours()) + ":" + a(this.getUTCMinutes()) + ":" + a(this.getUTCSeconds()) + "Z" : null | |
}; | |
String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function () { | |
return this.valueOf() | |
} | |
} | |
var e = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | |
f = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | |
g, d, h = { | |
"\u0008": "\\b", | |
"\t": "\\t", | |
"\n": "\\n", | |
"\u000c": "\\f", | |
"\r": "\\r", | |
'"': '\\"', | |
"\\": "\\\\" | |
}, | |
i; | |
if (typeof JSON.stringify !== "function") JSON.stringify = function (a, b, e) { | |
var f; | |
d = g = ""; | |
if (typeof e === "number") for (f = 0; f < e; f = f + 1) d = d + " "; | |
else typeof e === "string" && (d = e); | |
if ((i = b) && typeof b !== "function" && (typeof b !== "object" || typeof b.length !== "number")) throw Error("JSON.stringify"); | |
return c("", { | |
"": a | |
}) | |
}; | |
if (typeof JSON.parse !== "function") JSON.parse = function (a, b) { | |
function c(a, d) { | |
var e, f, g = a[d]; | |
if (g && typeof g === "object") for (e in g) if (Object.hasOwnProperty.call(g, e)) { | |
f = c(g, e); | |
f !== void 0 ? g[e] = f : delete g[e] | |
} | |
return b.call(a, d, g) | |
} | |
var d, a = "" + a; | |
e.lastIndex = 0; | |
e.test(a) && (a = a.replace(e, function (a) { | |
return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4) | |
})); | |
if (/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]").replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) { | |
d = eval("(" + a + ")"); | |
return typeof b === "function" ? c({ | |
"": d | |
}, "") : d | |
} | |
throw new SyntaxError("JSON.parse"); | |
} | |
})(); | |
var swfobject = function () { | |
function a() { | |
if (!A) { | |
try { | |
var a = m.getElementsByTagName("body")[0].appendChild(m.createElement("span")); | |
a.parentNode.removeChild(a) | |
} catch (b) { | |
return | |
} | |
A = true; | |
for (var a = D.length, c = 0; c < a; c++) D[c]() | |
} | |
} | |
function b(a) { | |
A ? a() : D[D.length] = a | |
} | |
function c(a) { | |
if (typeof s.addEventListener != p) s.addEventListener("load", a, false); | |
else if (typeof m.addEventListener != p) m.addEventListener("load", a, false); | |
else if (typeof s.attachEvent != p) t(s, "onload", a); | |
else if (typeof s.onload == "function") { | |
var b = s.onload; | |
s.onload = function () { | |
b(); | |
a() | |
} | |
} else s.onload = a | |
} | |
function e() { | |
var a = m.getElementsByTagName("body")[0], | |
b = m.createElement(v); | |
b.setAttribute("type", E); | |
var c = a.appendChild(b); | |
if (c) { | |
var d = 0; | |
(function () { | |
if (typeof c.GetVariable != p) { | |
var e = c.GetVariable("$version"); | |
if (e) { | |
e = e.split(" ")[1].split(","); | |
k.pv = [parseInt(e[0], 10), parseInt(e[1], 10), parseInt(e[2], 10)] | |
} | |
} else if (d < 10) { | |
d++; | |
setTimeout(arguments.callee, 10); | |
return | |
} | |
a.removeChild(b); | |
c = null; | |
f() | |
})() | |
} else f() | |
} | |
function f() { | |
var a = x.length; | |
if (a > 0) for (var b = 0; b < a; b++) { | |
var c = x[b].id, | |
e = x[b].callbackFn, | |
f = { | |
success: false, | |
id: c | |
}; | |
if (k.pv[0] > 0) { | |
var j = n(c); | |
if (j) if (u(x[b].swfVersion) && !(k.wk && k.wk < 312)) { | |
r(c, true); | |
if (e) { | |
f.success = true; | |
f.ref = g(c); | |
e(f) | |
} | |
} else if (x[b].expressInstall && d()) { | |
f = {}; | |
f.data = x[b].expressInstall; | |
f.width = j.getAttribute("width") || "0"; | |
f.height = j.getAttribute("height") || "0"; | |
if (j.getAttribute("class")) f.styleclass = j.getAttribute("class"); | |
if (j.getAttribute("align")) f.align = j.getAttribute("align"); | |
for (var l = {}, j = j.getElementsByTagName("param"), m = j.length, o = 0; o < m; o++) j[o].getAttribute("name").toLowerCase() != "movie" && (l[j[o].getAttribute("name")] = j[o].getAttribute("value")); | |
h(f, l, c, e) | |
} else { | |
i(j); | |
e && e(f) | |
} | |
} else { | |
r(c, true); | |
if (e) { | |
if ((c = g(c)) && typeof c.SetVariable != p) { | |
f.success = true; | |
f.ref = c | |
} | |
e(f) | |
} | |
} | |
} | |
} | |
function g(a) { | |
var b = null; | |
if ((a = n(a)) && a.nodeName == "OBJECT") if (typeof a.SetVariable != p) b = a; | |
else(a = a.getElementsByTagName(v)[0]) && (b = a); | |
return b | |
} | |
function d() { | |
return !F && u("6.0.65") && (k.win || k.mac) && !(k.wk && k.wk < 312) | |
} | |
function h(a, b, c, d) { | |
F = true; | |
I = d || null; | |
K = { | |
success: false, | |
id: c | |
}; | |
var e = n(c); | |
if (e) { | |
if (e.nodeName == "OBJECT") { | |
C = j(e); | |
G = null | |
} else { | |
C = e; | |
G = c | |
} | |
a.id = L; | |
if (typeof a.width == p || !/%$/.test(a.width) && parseInt(a.width, 10) < 310) a.width = "310"; | |
if (typeof a.height == p || !/%$/.test(a.height) && parseInt(a.height, 10) < 137) a.height = "137"; | |
m.title = m.title.slice(0, 47) + " - Flash Player Installation"; | |
d = k.ie && k.win ? "ActiveX" : "PlugIn"; | |
d = "MMredirectURL=" + s.location.toString().replace(/&/g, "%26") + "&MMplayerType=" + d + "&MMdoctitle=" + m.title; | |
b.flashvars = typeof b.flashvars != p ? b.flashvars + ("&" + d) : d; | |
if (k.ie && k.win && e.readyState != 4) { | |
d = m.createElement("div"); | |
c = c + "SWFObjectNew"; | |
d.setAttribute("id", c); | |
e.parentNode.insertBefore(d, e); | |
e.style.display = "none"; | |
(function () { | |
e.readyState == 4 ? e.parentNode.removeChild(e) : setTimeout(arguments.callee, 10) | |
})() | |
} | |
q(a, b, c) | |
} | |
} | |
function i(a) { | |
if (k.ie && k.win && a.readyState != 4) { | |
var b = m.createElement("div"); | |
a.parentNode.insertBefore(b, a); | |
b.parentNode.replaceChild(j(a), b); | |
a.style.display = "none"; | |
(function () { | |
a.readyState == 4 ? a.parentNode.removeChild(a) : setTimeout(arguments.callee, 10) | |
})() | |
} else a.parentNode.replaceChild(j(a), a) | |
} | |
function j(a) { | |
var b = m.createElement("div"); | |
if (k.win && k.ie) b.innerHTML = a.innerHTML; | |
else if (a = a.getElementsByTagName(v)[0]) if (a = a.childNodes) for (var c = a.length, d = 0; d < c; d++)!(a[d].nodeType == 1 && a[d].nodeName == "PARAM") && a[d].nodeType != 8 && b.appendChild(a[d].cloneNode(true)); | |
return b | |
} | |
function q(a, b, c) { | |
var d, e = n(c); | |
if (k.wk && k.wk < 312) return d; | |
if (e) { | |
if (typeof a.id == p) a.id = c; | |
if (k.ie && k.win) { | |
var f = "", | |
g; | |
for (g in a) if (a[g] != Object.prototype[g]) g.toLowerCase() == "data" ? b.movie = a[g] : g.toLowerCase() == "styleclass" ? f = f + (' class="' + a[g] + '"') : g.toLowerCase() != "classid" && (f = f + (" " + g + '="' + a[g] + '"')); | |
g = ""; | |
for (var h in b) b[h] != Object.prototype[h] && (g = g + ('<param name="' + h + '" value="' + b[h] + '" />')); | |
e.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + f + ">" + g + "</object>"; | |
H[H.length] = a.id; | |
d = n(a.id) | |
} else { | |
h = m.createElement(v); | |
h.setAttribute("type", E); | |
for (var i in a) a[i] != Object.prototype[i] && (i.toLowerCase() == "styleclass" ? h.setAttribute("class", a[i]) : i.toLowerCase() != "classid" && h.setAttribute(i, a[i])); | |
for (f in b) if (b[f] != Object.prototype[f] && f.toLowerCase() != "movie") { | |
a = h; | |
g = f; | |
i = b[f]; | |
c = m.createElement("param"); | |
c.setAttribute("name", g); | |
c.setAttribute("value", i); | |
a.appendChild(c) | |
} | |
e.parentNode.replaceChild(h, e); | |
d = h | |
} | |
} | |
return d | |
} | |
function l(a) { | |
var b = n(a); | |
if (b && b.nodeName == "OBJECT") if (k.ie && k.win) { | |
b.style.display = "none"; | |
(function () { | |
if (b.readyState == 4) { | |
var c = n(a); | |
if (c) { | |
for (var d in c) typeof c[d] == "function" && (c[d] = null); | |
c.parentNode.removeChild(c) | |
} | |
} else setTimeout(arguments.callee, 10) | |
})() | |
} else b.parentNode.removeChild(b) | |
} | |
function n(a) { | |
var b = null; | |
try { | |
b = m.getElementById(a) | |
} catch (c) {} | |
return b | |
} | |
function t(a, b, c) { | |
a.attachEvent(b, c); | |
B[B.length] = [a, b, c] | |
} | |
function u(a) { | |
var b = k.pv, | |
a = a.split("."); | |
a[0] = parseInt(a[0], 10); | |
a[1] = parseInt(a[1], 10) || 0; | |
a[2] = parseInt(a[2], 10) || 0; | |
return b[0] > a[0] || b[0] == a[0] && b[1] > a[1] || b[0] == a[0] && b[1] == a[1] && b[2] >= a[2] ? true : false | |
} | |
function z(a, b, c, d) { | |
if (!k.ie || !k.mac) { | |
var e = m.getElementsByTagName("head")[0]; | |
if (e) { | |
c = c && typeof c == "string" ? c : "screen"; | |
if (d) J = w = null; | |
if (!w || J != c) { | |
d = m.createElement("style"); | |
d.setAttribute("type", "text/css"); | |
d.setAttribute("media", c); | |
w = e.appendChild(d); | |
k.ie && (k.win && typeof m.styleSheets != p && m.styleSheets.length > 0) && (w = m.styleSheets[m.styleSheets.length - 1]); | |
J = c | |
} | |
k.ie && k.win ? w && typeof w.addRule == v && w.addRule(a, b) : w && typeof m.createTextNode != p && w.appendChild(m.createTextNode(a + " {" + b + "}")) | |
} | |
} | |
} | |
function r(a, b) { | |
if (M) { | |
var c = b ? "visible" : "hidden"; | |
A && n(a) ? n(a).style.visibility = c : z("#" + a, "visibility:" + c) | |
} | |
} | |
function o(a) { | |
return /[\\\"<>\.;]/.exec(a) != null && typeof encodeURIComponent != p ? encodeURIComponent(a) : a | |
} | |
var p = "undefined", | |
v = "object", | |
E = "application/x-shockwave-flash", | |
L = "SWFObjectExprInst", | |
s = window, | |
m = document, | |
y = navigator, | |
N = false, | |
D = [function () { | |
N ? e() : f() | |
}], | |
x = [], | |
H = [], | |
B = [], | |
C, G, I, K, A = false, | |
F = false, | |
w, J, M = true, | |
k = function () { | |
var a = typeof m.getElementById != p && typeof m.getElementsByTagName != p && typeof m.createElement != p, | |
b = y.userAgent.toLowerCase(), | |
c = y.platform.toLowerCase(), | |
d = c ? /win/.test(c) : /win/.test(b), | |
c = c ? /mac/.test(c) : /mac/.test(b), | |
b = /webkit/.test(b) ? parseFloat(b.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, | |
e = !+"\v1", | |
f = [0, 0, 0], | |
g = null; | |
if (typeof y.plugins != p && typeof y.plugins["Shockwave Flash"] == v) { | |
if ((g = y.plugins["Shockwave Flash"].description) && !(typeof y.mimeTypes != p && y.mimeTypes[E] && !y.mimeTypes[E].enabledPlugin)) { | |
N = true; | |
e = false; | |
g = g.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); | |
f[0] = parseInt(g.replace(/^(.*)\..*$/, "$1"), 10); | |
f[1] = parseInt(g.replace(/^.*\.(.*)\s.*$/, "$1"), 10); | |
f[2] = /[a-zA-Z]/.test(g) ? parseInt(g.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0 | |
} | |
} else if (typeof s.ActiveXObject != p) try { | |
var h = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); | |
if (h) if (g = h.GetVariable("$version")) { | |
e = true; | |
g = g.split(" ")[1].split(","); | |
f = [parseInt(g[0], 10), parseInt(g[1], 10), parseInt(g[2], 10)] | |
} | |
} catch (i) {} | |
return { | |
w3: a, | |
pv: f, | |
wk: b, | |
ie: e, | |
win: d, | |
mac: c | |
} | |
}(); | |
(function () { | |
if (k.w3) { | |
(typeof m.readyState != p && m.readyState == "complete" || typeof m.readyState == p && (m.getElementsByTagName("body")[0] || m.body)) && a(); | |
if (!A) { | |
typeof m.addEventListener != p && m.addEventListener("DOMContentLoaded", a, false); | |
if (k.ie && k.win) { | |
m.attachEvent("onreadystatechange", function () { | |
if (m.readyState == "complete") { | |
m.detachEvent("onreadystatechange", arguments.callee); | |
a() | |
} | |
}); | |
s == top && | |
function () { | |
if (!A) { | |
try { | |
m.documentElement.doScroll("left") | |
} catch (b) { | |
setTimeout(arguments.callee, 0); | |
return | |
} | |
a() | |
} | |
}() | |
} | |
k.wk && | |
function () { | |
A || (/loaded|complete/.test(m.readyState) ? a() : setTimeout(arguments.callee, 0)) | |
}(); | |
c(a) | |
} | |
} | |
})(); | |
(function () { | |
k.ie && k.win && window.attachEvent("onunload", function () { | |
for (var a = B.length, b = 0; b < a; b++) B[b][0].detachEvent(B[b][1], B[b][2]); | |
a = H.length; | |
for (b = 0; b < a; b++) l(H[b]); | |
for (var c in k) k[c] = null; | |
k = null; | |
for (var d in swfobject) swfobject[d] = null; | |
swfobject = null | |
}) | |
})(); | |
return { | |
registerObject: function (a, b, c, d) { | |
if (k.w3 && a && b) { | |
var e = {}; | |
e.id = a; | |
e.swfVersion = b; | |
e.expressInstall = c; | |
e.callbackFn = d; | |
x[x.length] = e; | |
r(a, false) | |
} else d && d({ | |
success: false, | |
id: a | |
}) | |
}, | |
getObjectById: function (a) { | |
if (k.w3) return g(a) | |
}, | |
embedSWF: function (a, c, e, f, g, i, j, l, n, m) { | |
var o = { | |
success: false, | |
id: c | |
}; | |
if (k.w3 && !(k.wk && k.wk < 312) && a && c && e && f && g) { | |
r(c, false); | |
b(function () { | |
e = e + ""; | |
f = f + ""; | |
var b = {}; | |
if (n && typeof n === v) for (var k in n) b[k] = n[k]; | |
b.data = a; | |
b.width = e; | |
b.height = f; | |
k = {}; | |
if (l && typeof l === v) for (var s in l) k[s] = l[s]; | |
if (j && typeof j === v) for (var t in j) k.flashvars = typeof k.flashvars != p ? k.flashvars + ("&" + t + "=" + j[t]) : t + "=" + j[t]; | |
if (u(g)) { | |
s = q(b, k, c); | |
b.id == c && r(c, true); | |
o.success = true; | |
o.ref = s | |
} else { | |
if (i && d()) { | |
b.data = i; | |
h(b, k, c, m); | |
return | |
} | |
r(c, true) | |
} | |
m && m(o) | |
}) | |
} else m && m(o) | |
}, | |
switchOffAutoHideShow: function () { | |
M = false | |
}, | |
ua: k, | |
getFlashPlayerVersion: function () { | |
return { | |
major: k.pv[0], | |
minor: k.pv[1], | |
release: k.pv[2] | |
} | |
}, | |
hasFlashPlayerVersion: u, | |
createSWF: function (a, b, c) { | |
if (k.w3) return q(a, b, c) | |
}, | |
showExpressInstall: function (a, b, c, e) { | |
k.w3 && d() && h(a, b, c, e) | |
}, | |
removeSWF: function (a) { | |
k.w3 && l(a) | |
}, | |
createCSS: function (a, b, c, d) { | |
k.w3 && z(a, b, c, d) | |
}, | |
addDomLoadEvent: b, | |
addLoadEvent: c, | |
getQueryParamValue: function (a) { | |
var b = m.location.search || m.location.hash; | |
if (b) { | |
/\?/.test(b) && (b = b.split("?")[1]); | |
if (a == null) return o(b); | |
for (var b = b.split("&"), c = 0; c < b.length; c++) if (b[c].substring(0, b[c].indexOf("=")) == a) return o(b[c].substring(b[c].indexOf("=") + 1)) | |
} | |
return "" | |
}, | |
expressInstallCallback: function () { | |
if (F) { | |
var a = n(L); | |
if (a && C) { | |
a.parentNode.replaceChild(C, a); | |
if (G) { | |
r(G, true); | |
if (k.ie && k.win) C.style.display = "block" | |
} | |
I && I(K) | |
} | |
F = false | |
} | |
} | |
} | |
}(); | |
function Resampler(a, b, c, e, f) { | |
this.fromSampleRate = a; | |
this.toSampleRate = b; | |
this.channels = c | 0; | |
this.outputBufferSize = e; | |
this.noReturn = !! f; | |
this.initialize() | |
} | |
Resampler.prototype.initialize = function () { | |
if (this.fromSampleRate > 0 && this.toSampleRate > 0 && this.channels > 0) if (this.fromSampleRate == this.toSampleRate) { | |
this.resampler = this.bypassResampler; | |
this.ratioWeight = 1 | |
} else { | |
if (this.fromSampleRate < this.toSampleRate) { | |
this.compileLinearInterpolationFunction(); | |
this.lastWeight = 1 | |
} else { | |
this.compileMultiTapFunction(); | |
this.tailExists = false; | |
this.lastWeight = 0 | |
} | |
this.ratioWeight = this.fromSampleRate / this.toSampleRate; | |
this.initializeBuffers() | |
} else throw Error("Invalid settings specified for the resampler."); | |
}; | |
Resampler.prototype.compileLinearInterpolationFunction = function () { | |
for (var a = "var bufferLength = buffer.length;var outLength = this.outputBufferSize;if ((bufferLength % " + this.channels + ") == 0) {if (bufferLength > 0) {var ratioWeight = this.ratioWeight;var weight = this.lastWeight;var firstWeight = 0;var secondWeight = 0;var sourceOffset = 0;var outputOffset = 0;var outputBuffer = this.outputBuffer;for (; weight < 1; weight += ratioWeight) {secondWeight = weight % 1;firstWeight = 1 - secondWeight;", b = 0; b < this.channels; ++b) a = a + ("outputBuffer[outputOffset++] = (this.lastOutput[" + b + "] * firstWeight) + (buffer[" + b + "] * secondWeight);"); | |
a = a + ("}weight -= 1;for (bufferLength -= " + this.channels + ", sourceOffset = Math.floor(weight) * " + this.channels + "; outputOffset < outLength && sourceOffset < bufferLength;) {secondWeight = weight % 1;firstWeight = 1 - secondWeight;"); | |
for (b = 0; b < this.channels; ++b) a = a + ("outputBuffer[outputOffset++] = (buffer[sourceOffset" + (b > 0 ? " + " + b : "") + "] * firstWeight) + (buffer[sourceOffset + " + (this.channels + b) + "] * secondWeight);"); | |
a = a + ("weight += ratioWeight;sourceOffset = Math.floor(weight) * " + this.channels + ";}"); | |
for (b = 0; b < this.channels; ++b) a = a + ("this.lastOutput[" + b + "] = buffer[sourceOffset++];"); | |
this.resampler = Function("buffer", a + 'this.lastWeight = weight % 1;return this.bufferSlice(outputOffset);}else {return (this.noReturn) ? 0 : [];}}else {throw(new Error("Buffer was of incorrect sample length."));}') | |
}; | |
Resampler.prototype.compileMultiTapFunction = function () { | |
for (var a = "var bufferLength = buffer.length;var outLength = this.outputBufferSize;if ((bufferLength % " + this.channels + ") == 0) {if (bufferLength > 0) {var ratioWeight = this.ratioWeight;var weight = 0;", b = 0; b < this.channels; ++b) a = a + ("var output" + b + " = 0;"); | |
a = a + "var actualPosition = 0;var amountToNext = 0;var alreadyProcessedTail = !this.tailExists;this.tailExists = false;var outputBuffer = this.outputBuffer;var outputOffset = 0;var currentPosition = 0;do {if (alreadyProcessedTail) {weight = ratioWeight;"; | |
for (b = 0; b < this.channels; ++b) a = a + ("output" + b + " = 0;"); | |
a = a + "}else {weight = this.lastWeight;"; | |
for (b = 0; b < this.channels; ++b) a = a + ("output" + b + " = this.lastOutput[" + b + "];"); | |
a = a + "alreadyProcessedTail = true;}while (weight > 0 && actualPosition < bufferLength) {amountToNext = 1 + actualPosition - currentPosition;if (weight >= amountToNext) {"; | |
for (b = 0; b < this.channels; ++b) a = a + ("output" + b + " += buffer[actualPosition++] * amountToNext;"); | |
a = a + "currentPosition = actualPosition;weight -= amountToNext;}else {"; | |
for (b = 0; b < this.channels; ++b) a = a + ("output" + b + " += buffer[actualPosition" + (b > 0 ? " + " + b : "") + "] * weight;"); | |
a = a + "currentPosition += weight;weight = 0;break;}}if (weight == 0) {"; | |
for (b = 0; b < this.channels; ++b) a = a + ("outputBuffer[outputOffset++] = output" + b + " / ratioWeight;"); | |
a = a + "}else {this.lastWeight = weight;"; | |
for (b = 0; b < this.channels; ++b) a = a + ("this.lastOutput[" + b + "] = output" + b + ";"); | |
this.resampler = Function("buffer", a + 'this.tailExists = true;break;}} while (actualPosition < bufferLength && outputOffset < outLength);return this.bufferSlice(outputOffset);}else {return (this.noReturn) ? 0 : [];}}else {throw(new Error("Buffer was of incorrect sample length."));}') | |
}; | |
Resampler.prototype.bypassResampler = function (a) { | |
if (this.noReturn) { | |
this.outputBuffer = a; | |
return a.length | |
} | |
return a | |
}; | |
Resampler.prototype.bufferSlice = function (a) { | |
if (this.noReturn) return a; | |
try { | |
return this.outputBuffer.subarray(0, a) | |
} catch (b) { | |
try { | |
this.outputBuffer.length = a; | |
return this.outputBuffer | |
} catch (c) { | |
return this.outputBuffer.slice(0, a) | |
} | |
} | |
}; | |
Resampler.prototype.initializeBuffers = function () { | |
try { | |
this.outputBuffer = new Float32Array(this.outputBufferSize); | |
this.lastOutput = new Float32Array(this.channels) | |
} catch (a) { | |
this.outputBuffer = []; | |
this.lastOutput = [] | |
} | |
}; | |
function XAudioServer(a, b, c, e, f, g) { | |
this.audioChannels = a == 2 ? 2 : 1; | |
webAudioMono = this.audioChannels == 1; | |
XAudioJSSampleRate = Math.abs(b); | |
webAudioMinBufferSize = c >= samplesPerCallback << this.audioChannels - 1 && c < e ? c & -this.audioChannels : samplesPerCallback << this.audioChannels - 1; | |
webAudioMaxBufferSize = Math.floor(e) > webAudioMinBufferSize + this.audioChannels ? e & -this.audioChannels : c << this.audioChannels - 1; | |
this.underRunCallback = typeof f == "function" ? f : function () {}; | |
XAudioJSVolume = g >= 0 && g <= 1 ? g : 1; | |
this.audioType = -1; | |
this.mozAudioTail = []; | |
this.audioHandleFlash = this.audioHandleMoz = null; | |
this.mozAudioFound = this.flashInitialized = false; | |
this.initializeAudio() | |
} | |
XAudioServer.prototype.MOZWriteAudio = function (a) { | |
this.MOZWriteAudioNoCallback(a); | |
this.MOZExecuteCallback() | |
}; | |
XAudioServer.prototype.MOZWriteAudioNoCallback = function (a) { | |
this.writeMozAudio(a) | |
}; | |
XAudioServer.prototype.callbackBasedWriteAudio = function (a) { | |
this.callbackBasedWriteAudioNoCallback(a); | |
this.callbackBasedExecuteCallback() | |
}; | |
XAudioServer.prototype.callbackBasedWriteAudioNoCallback = function (a) { | |
for (var b = a.length, c = 0; c < b && audioBufferSize < webAudioMaxBufferSize;) audioContextSampleBuffer[audioBufferSize++] = a[c++] | |
}; | |
XAudioServer.prototype.writeAudio = function (a) { | |
this.audioType == 0 ? this.MOZWriteAudio(a) : this.audioType == 1 ? this.callbackBasedWriteAudio(a) : this.audioType == 2 && (this.checkFlashInit() || launchedContext ? this.callbackBasedWriteAudio(a) : this.mozAudioFound && this.MOZWriteAudio(a)) | |
}; | |
XAudioServer.prototype.writeAudioNoCallback = function (a) { | |
this.audioType == 0 ? this.MOZWriteAudioNoCallback(a) : this.audioType == 1 ? this.callbackBasedWriteAudioNoCallback(a) : this.audioType == 2 && (this.checkFlashInit() || launchedContext ? this.callbackBasedWriteAudioNoCallback(a) : this.mozAudioFound && this.MOZWriteAudioNoCallback(a)) | |
}; | |
XAudioServer.prototype.remainingBuffer = function () { | |
if (this.audioType == 0) return this.samplesAlreadyWritten - this.audioHandleMoz.mozCurrentSampleOffset(); | |
if (this.audioType == 1) return (resampledSamplesLeft() * resampleControl.ratioWeight >> this.audioChannels - 1 << this.audioChannels - 1) + audioBufferSize; | |
if (this.audioType == 2) { | |
if (this.checkFlashInit() || launchedContext) return (resampledSamplesLeft() * resampleControl.ratioWeight >> this.audioChannels - 1 << this.audioChannels - 1) + audioBufferSize; | |
if (this.mozAudioFound) return this.samplesAlreadyWritten - this.audioHandleMoz.mozCurrentSampleOffset() | |
} | |
return 0 | |
}; | |
XAudioServer.prototype.MOZExecuteCallback = function () { | |
var a = webAudioMinBufferSize - this.remainingBuffer(); | |
a > 0 && this.writeMozAudio(this.underRunCallback(a)) | |
}; | |
XAudioServer.prototype.callbackBasedExecuteCallback = function () { | |
var a = webAudioMinBufferSize - this.remainingBuffer(); | |
a > 0 && this.callbackBasedWriteAudioNoCallback(this.underRunCallback(a)) | |
}; | |
XAudioServer.prototype.executeCallback = function () { | |
this.audioType == 0 ? this.MOZExecuteCallback() : this.audioType == 1 ? this.callbackBasedExecuteCallback() : this.audioType == 2 && (this.checkFlashInit() || launchedContext ? this.callbackBasedExecuteCallback() : this.mozAudioFound && this.MOZExecuteCallback()) | |
}; | |
XAudioServer.prototype.initializeAudio = function () { | |
try { | |
this.preInitializeMozAudio(); | |
if (navigator.platform == "Linux i686") throw Error(""); | |
this.initializeMozAudio() | |
} catch (a) { | |
try { | |
this.initializeWebAudio() | |
} catch (b) { | |
try { | |
this.initializeFlashAudio() | |
} catch (c) { | |
throw Error("Browser does not support real time audio output."); | |
} | |
} | |
} | |
}; | |
XAudioServer.prototype.preInitializeMozAudio = function () { | |
this.audioHandleMoz = new Audio; | |
this.audioHandleMoz.mozSetup(this.audioChannels, XAudioJSSampleRate); | |
this.samplesAlreadyWritten = 0; | |
var a = this.audioChannels == 2 ? [0, 0] : [0], | |
b = 0; | |
if (navigator.platform != "MacIntel" && navigator.platform != "MacPPC") { | |
for (; this.audioHandleMoz.mozCurrentSampleOffset() == 0;) b = b + this.audioHandleMoz.mozWriteAudio(a); | |
for (var c = b / this.audioChannels, e = 0; e < c; e++) this.samplesAlreadyWritten = this.samplesAlreadyWritten + this.audioHandleMoz.mozWriteAudio(a) | |
} | |
this.samplesAlreadyWritten = this.samplesAlreadyWritten + b; | |
webAudioMinBufferSize = webAudioMinBufferSize + this.samplesAlreadyWritten; | |
this.mozAudioFound = true | |
}; | |
XAudioServer.prototype.initializeMozAudio = function () { | |
this.writeMozAudio(getFloat32(webAudioMinBufferSize)); | |
this.audioType = 0 | |
}; | |
XAudioServer.prototype.initializeWebAudio = function () { | |
if (launchedContext) { | |
resetCallbackAPIAudioBuffer(webAudioActualSampleRate, samplesPerCallback); | |
this.audioType = 1 | |
} else throw Error(""); | |
}; | |
XAudioServer.prototype.initializeFlashAudio = function () { | |
var a = document.getElementById("XAudioJS"); | |
if (a == null) { | |
var b = this, | |
a = document.createElement("div"); | |
a.setAttribute("style", "position: fixed; bottom: 0px; right: 0px; margin: 0px; padding: 0px; border: none; width: 8px; height: 8px; overflow: hidden; z-index: -1000; "); | |
var c = document.createElement("div"); | |
c.setAttribute("style", "position: static; border: none; width: 0px; height: 0px; visibility: hidden; margin: 8px; padding: 0px;"); | |
c.setAttribute("id", "XAudioJS"); | |
a.appendChild(c); | |
document.getElementsByTagName("body")[0].appendChild(a); | |
swfobject.embedSWF("XAudioJS.swf", "XAudioJS", "8", "8", "9.0.0", "", {}, { | |
allowscriptaccess: "always" | |
}, { | |
style: "position: static; visibility: hidden; margin: 8px; padding: 0px; border: none" | |
}, function (a) { | |
a.success ? b.audioHandleFlash = a.ref : b.audioType = 1 | |
}) | |
} else this.audioHandleFlash = a; | |
this.audioType = 2 | |
}; | |
XAudioServer.prototype.changeVolume = function (a) { | |
if (a >= 0 && a <= 1) { | |
XAudioJSVolume = a; | |
this.checkFlashInit() && this.audioHandleFlash.changeVolume(XAudioJSVolume); | |
if (this.mozAudioFound) this.audioHandleMoz.volume = XAudioJSVolume | |
} | |
}; | |
XAudioServer.prototype.writeMozAudio = function (a) { | |
var b = this.mozAudioTail.length; | |
if (b > 0) { | |
var c = this.audioHandleMoz.mozWriteAudio(this.mozAudioTail); | |
this.samplesAlreadyWritten = this.samplesAlreadyWritten + c; | |
this.mozAudioTail.splice(0, c) | |
} | |
b = Math.min(a.length, webAudioMaxBufferSize - this.samplesAlreadyWritten + this.audioHandleMoz.mozCurrentSampleOffset()); | |
c = this.audioHandleMoz.mozWriteAudio(a); | |
this.samplesAlreadyWritten = this.samplesAlreadyWritten + c; | |
for (var e = 0; b > c; --b) this.mozAudioTail.push(a[e++]) | |
}; | |
XAudioServer.prototype.checkFlashInit = function () { | |
if (!this.flashInitialized && this.audioHandleFlash && this.audioHandleFlash.initialize) { | |
this.flashInitialized = true; | |
this.audioHandleFlash.initialize(this.audioChannels, XAudioJSVolume); | |
resetCallbackAPIAudioBuffer(44100, samplesPerCallback) | |
} | |
return this.flashInitialized | |
}; | |
function getFloat32(a) { | |
try { | |
return new Float32Array(a) | |
} catch (b) { | |
return Array(a) | |
} | |
} | |
function getFloat32Flat(a) { | |
try { | |
var b = new Float32Array(a) | |
} catch (c) { | |
var b = Array(a), | |
e = 0; | |
do b[e] = 0; | |
while (++e < a) | |
} | |
return b | |
} | |
var samplesPerCallback = 2048, | |
outputConvert = null; | |
function audioOutputFlashEvent() { | |
resampleRefill(); | |
return outputConvert() | |
} | |
function generateFlashStereoString() { | |
for (var a = "", b = "", c = 0; c < samplesPerCallback && resampleBufferStart != resampleBufferEnd; ++c) { | |
a = a + String.fromCharCode((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), 2) * 16383 | 0) + 12288); | |
b = b + String.fromCharCode((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), 2) * 16383 | 0) + 12288); | |
resampleBufferStart == resampleBufferSize && (resampleBufferStart = 0) | |
} | |
return a + b | |
} | |
function generateFlashMonoString() { | |
for (var a = "", b = 0; b < samplesPerCallback && resampleBufferStart != resampleBufferEnd; ++b) { | |
a = a + String.fromCharCode((Math.min(Math.max(resampled[resampleBufferStart++] + 1, 0), 2) * 16383 | 0) + 12288); | |
resampleBufferStart == resampleBufferSize && (resampleBufferStart = 0) | |
} | |
return a | |
} | |
var audioContextHandle = null, | |
audioNode = null, | |
audioSource = null, | |
launchedContext = !1, | |
audioContextSampleBuffer = [], | |
resampled = [], | |
webAudioMinBufferSize = 15E3, | |
webAudioMaxBufferSize = 25E3, | |
webAudioActualSampleRate = 44100, | |
XAudioJSSampleRate = 0, | |
webAudioMono = !1, | |
XAudioJSVolume = 1, | |
resampleControl = null, | |
audioBufferSize = 0, | |
resampleBufferStart = 0, | |
resampleBufferEnd = 0, | |
resampleBufferSize = 2; | |
function audioOutputEvent(a) { | |
var b = 0, | |
c = a.outputBuffer.getChannelData(0), | |
a = a.outputBuffer.getChannelData(1); | |
resampleRefill(); | |
if (webAudioMono) for (; b < samplesPerCallback && resampleBufferStart != resampleBufferEnd;) { | |
a[b] = c[b] = resampled[resampleBufferStart++] * XAudioJSVolume; | |
++b; | |
resampleBufferStart == resampleBufferSize && (resampleBufferStart = 0) | |
} else for (; b < samplesPerCallback && resampleBufferStart != resampleBufferEnd;) { | |
c[b] = resampled[resampleBufferStart++] * XAudioJSVolume; | |
a[b++] = resampled[resampleBufferStart++] * XAudioJSVolume; | |
resampleBufferStart == resampleBufferSize && (resampleBufferStart = 0) | |
} | |
for (; b < samplesPerCallback;) { | |
a[b] = c[b] = 0; | |
++b | |
} | |
} | |
function resampleRefill() { | |
if (audioBufferSize > 0) { | |
for (var a = resampleControl.resampler(getBufferSamples()), b = resampleControl.outputBuffer, c = 0; c < a; ++c) { | |
resampled[resampleBufferEnd++] = b[c]; | |
resampleBufferEnd == resampleBufferSize && (resampleBufferEnd = 0); | |
if (resampleBufferStart == resampleBufferEnd) { | |
++resampleBufferStart; | |
resampleBufferStart == resampleBufferSize && (resampleBufferStart = 0) | |
} | |
} | |
audioBufferSize = 0 | |
} | |
} | |
function resampledSamplesLeft() { | |
return (resampleBufferStart <= resampleBufferEnd ? 0 : resampleBufferSize) + resampleBufferEnd - resampleBufferStart | |
} | |
function getBufferSamples() { | |
try { | |
return audioContextSampleBuffer.subarray(0, audioBufferSize) | |
} catch (a) { | |
try { | |
audioContextSampleBuffer.length = audioBufferSize; | |
return audioContextSampleBuffer | |
} catch (b) { | |
return audioContextSampleBuffer.slice(0, audioBufferSize) | |
} | |
} | |
} | |
function resetCallbackAPIAudioBuffer(a) { | |
audioContextSampleBuffer = getFloat32(webAudioMaxBufferSize); | |
audioBufferSize = resampleBufferEnd = resampleBufferStart = 0; | |
if (webAudioMono) { | |
resampleBufferSize = Math.max(webAudioMaxBufferSize * Math.ceil(a / XAudioJSSampleRate) + 1, samplesPerCallback); | |
resampleControl = new Resampler(XAudioJSSampleRate, a, 1, resampleBufferSize, true); | |
outputConvert = generateFlashMonoString | |
} else { | |
resampleBufferSize = Math.max(webAudioMaxBufferSize * Math.ceil(a / XAudioJSSampleRate) + 2, samplesPerCallback << 1); | |
resampleControl = new Resampler(XAudioJSSampleRate, a, 2, resampleBufferSize, true); | |
outputConvert = generateFlashStereoString | |
} | |
resampled = getFloat32Flat(resampleBufferSize) | |
} | |
(function () { | |
if (!launchedContext) { | |
try { | |
audioContextHandle = new webkitAudioContext | |
} catch (a) { | |
try { | |
audioContextHandle = new AudioContext | |
} catch (b) { | |
return | |
} | |
} | |
try { | |
audioSource = audioContextHandle.createBufferSource(); | |
audioSource.loop = false; | |
XAudioJSSampleRate = webAudioActualSampleRate = audioContextHandle.sampleRate; | |
audioSource.buffer = audioContextHandle.createBuffer(1, 1, webAudioActualSampleRate); | |
audioNode = audioContextHandle.createJavaScriptNode(samplesPerCallback, 1, 2); | |
audioNode.onaudioprocess = audioOutputEvent; | |
audioSource.connect(audioNode); | |
audioNode.connect(audioContextHandle.destination); | |
audioSource.noteOn(0) | |
} catch (c) { | |
return | |
} | |
launchedContext = true | |
} | |
})(); | |
function Resize(a, b, c, e, f, g) { | |
this.widthOriginal = Math.abs(parseInt(a) || 0); | |
this.heightOriginal = Math.abs(parseInt(b) || 0); | |
this.targetWidth = Math.abs(parseInt(c) || 0); | |
this.targetHeight = Math.abs(parseInt(e) || 0); | |
this.colorChannels = f ? 4 : 3; | |
this.interpolationPass = !! g; | |
this.targetWidthMultipliedByChannels = this.targetWidth * this.colorChannels; | |
this.originalWidthMultipliedByChannels = this.widthOriginal * this.colorChannels; | |
this.originalHeightMultipliedByChannels = this.heightOriginal * this.colorChannels; | |
this.widthPassResultSize = this.targetWidthMultipliedByChannels * this.heightOriginal; | |
this.finalResultSize = this.targetWidthMultipliedByChannels * this.targetHeight; | |
this.initialize() | |
} | |
Resize.prototype.initialize = function () { | |
if (this.widthOriginal > 0 && this.heightOriginal > 0 && this.targetWidth > 0 && this.targetHeight > 0) { | |
if (this.widthOriginal == this.targetWidth) this.resizeWidth = this.bypassResizer; | |
else { | |
this.ratioWeightWidthPass = this.widthOriginal / this.targetWidth; | |
if (this.ratioWeightWidthPass < 1 && this.interpolationPass) { | |
this.initializeFirstPassBuffers(true); | |
this.resizeWidth = this.colorChannels == 4 ? this.resizeWidthInterpolatedRGBA : this.resizeWidthInterpolatedRGB | |
} else { | |
this.initializeFirstPassBuffers(false); | |
this.resizeWidth = this.colorChannels == 4 ? this.resizeWidthRGBA : this.resizeWidthRGB | |
} | |
} | |
if (this.heightOriginal == this.targetHeight) this.resizeHeight = this.bypassResizer; | |
else { | |
this.ratioWeightHeightPass = this.heightOriginal / this.targetHeight; | |
if (this.ratioWeightHeightPass < 1 && this.interpolationPass) { | |
this.initializeSecondPassBuffers(true); | |
this.resizeHeight = this.resizeHeightInterpolated | |
} else { | |
this.initializeSecondPassBuffers(false); | |
this.resizeHeight = this.colorChannels == 4 ? this.resizeHeightRGBA : this.resizeHeightRGB | |
} | |
} | |
} else throw Error("Invalid settings specified for the resizer."); | |
}; | |
Resize.prototype.resizeWidthRGB = function (a) { | |
var b = this.ratioWeightWidthPass, | |
c = 0, | |
e = 0, | |
f = 0, | |
g = 0, | |
d = 0, | |
h = 0, | |
i = 0, | |
j = this.originalWidthMultipliedByChannels - 2, | |
q = this.targetWidthMultipliedByChannels - 2, | |
l = this.outputWidthWorkBench, | |
n = this.widthBuffer; | |
do { | |
for (d = 0; d < this.originalHeightMultipliedByChannels;) { | |
l[d++] = 0; | |
l[d++] = 0; | |
l[d++] = 0 | |
} | |
c = b; | |
do { | |
e = 1 + f - g; | |
if (c >= e) { | |
d = 0; | |
for (h = f; d < this.originalHeightMultipliedByChannels; h = h + j) { | |
l[d++] += a[h++] * e; | |
l[d++] += a[h++] * e; | |
l[d++] += a[h] * e | |
} | |
g = f = f + 3; | |
c = c - e | |
} else { | |
d = 0; | |
for (h = f; d < this.originalHeightMultipliedByChannels; h = h + j) { | |
l[d++] += a[h++] * c; | |
l[d++] += a[h++] * c; | |
l[d++] += a[h] * c | |
} | |
g = g + c; | |
break | |
} | |
} while (c > 0 && f < this.originalWidthMultipliedByChannels); | |
d = 0; | |
for (h = i; d < this.originalHeightMultipliedByChannels; h = h + q) { | |
n[h++] = l[d++] / b; | |
n[h++] = l[d++] / b; | |
n[h] = l[d++] / b | |
} | |
i = i + 3 | |
} while (i < this.targetWidthMultipliedByChannels); | |
return n | |
}; | |
Resize.prototype.resizeWidthInterpolatedRGB = function (a) { | |
for (var b = this.ratioWeightWidthPass, c = 0, e = 0, f = 0, g = 0, d = 0, h = this.widthBuffer, i = 0; c < 0.25; i = i + 3, c = c + b) { | |
e = i; | |
for (f = 0; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f]; | |
h[e + 1] = a[f + 1]; | |
h[e + 2] = a[f + 2] | |
} | |
} | |
for (var c = c - 0.25, j = this.widthOriginal - 1; c < j; i = i + 3, c = c + b) { | |
d = c % 1; | |
g = 1 - d; | |
e = i; | |
for (f = Math.floor(c) * 3; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f] * g + a[f + 3] * d; | |
h[e + 1] = a[f + 1] * g + a[f + 4] * d; | |
h[e + 2] = a[f + 2] * g + a[f + 5] * d | |
} | |
} | |
for (j = this.originalWidthMultipliedByChannels - 3; i < this.targetWidthMultipliedByChannels; i = i + 3) { | |
e = i; | |
for (f = j; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f]; | |
h[e + 1] = a[f + 1]; | |
h[e + 2] = a[f + 2] | |
} | |
} | |
return h | |
}; | |
Resize.prototype.resizeWidthRGBA = function (a) { | |
var b = this.ratioWeightWidthPass, | |
c = 0, | |
e = 0, | |
f = 0, | |
g = 0, | |
d = 0, | |
h = 0, | |
i = 0, | |
j = this.originalWidthMultipliedByChannels - 3, | |
q = this.targetWidthMultipliedByChannels - 3, | |
l = this.outputWidthWorkBench, | |
n = this.widthBuffer; | |
do { | |
for (d = 0; d < this.originalHeightMultipliedByChannels;) { | |
l[d++] = 0; | |
l[d++] = 0; | |
l[d++] = 0; | |
l[d++] = 0 | |
} | |
c = b; | |
do { | |
e = 1 + f - g; | |
if (c >= e) { | |
d = 0; | |
for (h = f; d < this.originalHeightMultipliedByChannels; h = h + j) { | |
l[d++] += a[h++] * e; | |
l[d++] += a[h++] * e; | |
l[d++] += a[h++] * e; | |
l[d++] += a[h] * e | |
} | |
g = f = f + 4; | |
c = c - e | |
} else { | |
d = 0; | |
for (h = f; d < this.originalHeightMultipliedByChannels; h = h + j) { | |
l[d++] += a[h++] * c; | |
l[d++] += a[h++] * c; | |
l[d++] += a[h++] * c; | |
l[d++] += a[h] * c | |
} | |
g = g + c; | |
break | |
} | |
} while (c > 0 && f < this.originalWidthMultipliedByChannels); | |
d = 0; | |
for (h = i; d < this.originalHeightMultipliedByChannels; h = h + q) { | |
n[h++] = l[d++] / b; | |
n[h++] = l[d++] / b; | |
n[h++] = l[d++] / b; | |
n[h] = l[d++] / b | |
} | |
i = i + 4 | |
} while (i < this.targetWidthMultipliedByChannels); | |
return n | |
}; | |
Resize.prototype.resizeWidthInterpolatedRGBA = function (a) { | |
for (var b = this.ratioWeightWidthPass, c = 0, e = 0, f = 0, g = 0, d = 0, h = this.widthBuffer, i = 0; c < 0.25; i = i + 4, c = c + b) { | |
e = i; | |
for (f = 0; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f]; | |
h[e + 1] = a[f + 1]; | |
h[e + 2] = a[f + 2]; | |
h[e + 3] = a[f + 3] | |
} | |
} | |
for (var c = c - 0.25, j = this.widthOriginal - 1; c < j; i = i + 4, c = c + b) { | |
d = c % 1; | |
g = 1 - d; | |
e = i; | |
for (f = Math.floor(c) * 4; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f] * g + a[f + 4] * d; | |
h[e + 1] = a[f + 1] * g + a[f + 5] * d; | |
h[e + 2] = a[f + 2] * g + a[f + 6] * d; | |
h[e + 3] = a[f + 3] * g + a[f + 7] * d | |
} | |
} | |
for (j = this.originalWidthMultipliedByChannels - 4; i < this.targetWidthMultipliedByChannels; i = i + 4) { | |
e = i; | |
for (f = j; e < this.widthPassResultSize; f = f + this.originalWidthMultipliedByChannels, e = e + this.targetWidthMultipliedByChannels) { | |
h[e] = a[f]; | |
h[e + 1] = a[f + 1]; | |
h[e + 2] = a[f + 2]; | |
h[e + 3] = a[f + 3] | |
} | |
} | |
return h | |
}; | |
Resize.prototype.resizeHeightRGB = function (a) { | |
var b = this.ratioWeightHeightPass, | |
c = 0, | |
e = 0, | |
f = 0, | |
g = 0, | |
d = 0, | |
h = 0, | |
i = this.outputHeightWorkBench, | |
j = this.heightBuffer; | |
do { | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] = 0; | |
i[d++] = 0; | |
i[d++] = 0 | |
} | |
c = b; | |
do { | |
e = 1 + f - g; | |
if (c >= e) { | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] += a[f++] * e; | |
i[d++] += a[f++] * e; | |
i[d++] += a[f++] * e | |
} | |
g = f; | |
c = c - e | |
} else { | |
d = 0; | |
for (e = f; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] += a[e++] * c; | |
i[d++] += a[e++] * c; | |
i[d++] += a[e++] * c | |
} | |
g = g + c; | |
break | |
} | |
} while (c > 0 && f < this.widthPassResultSize); | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
j[h++] = Math.round(i[d++] / b); | |
j[h++] = Math.round(i[d++] / b); | |
j[h++] = Math.round(i[d++] / b) | |
} | |
} while (h < this.finalResultSize); | |
return j | |
}; | |
Resize.prototype.resizeHeightInterpolated = function (a) { | |
for (var b = this.ratioWeightHeightPass, c = 0, e = 0, f = 0, g = 0, d = 0, h = 0, i = 0, j = this.heightBuffer; c < 0.25; c = c + b) for (f = 0; f < this.targetWidthMultipliedByChannels;) j[e++] = a[f++]; | |
for (var c = c - 0.25, q = this.heightOriginal - 1; c < q; c = c + b) { | |
i = c % 1; | |
h = 1 - i; | |
g = Math.floor(c) * this.targetWidthMultipliedByChannels; | |
d = g + this.targetWidthMultipliedByChannels; | |
for (f = 0; f < this.targetWidthMultipliedByChannels; ++f) j[e++] = a[g + f] * h + a[d + f] * i | |
} | |
for (; e < this.finalResultSize;) { | |
f = 0; | |
for (g = q * this.targetWidthMultipliedByChannels; f < this.targetWidthMultipliedByChannels; ++f) j[e++] = a[g++] | |
} | |
return j | |
}; | |
Resize.prototype.resizeHeightRGBA = function (a) { | |
var b = this.ratioWeightHeightPass, | |
c = 0, | |
e = 0, | |
f = 0, | |
g = 0, | |
d = 0, | |
h = 0, | |
i = this.outputHeightWorkBench, | |
j = this.heightBuffer; | |
do { | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] = 0; | |
i[d++] = 0; | |
i[d++] = 0; | |
i[d++] = 0 | |
} | |
c = b; | |
do { | |
e = 1 + f - g; | |
if (c >= e) { | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] += a[f++] * e; | |
i[d++] += a[f++] * e; | |
i[d++] += a[f++] * e; | |
i[d++] += a[f++] * e | |
} | |
g = f; | |
c = c - e | |
} else { | |
d = 0; | |
for (e = f; d < this.targetWidthMultipliedByChannels;) { | |
i[d++] += a[e++] * c; | |
i[d++] += a[e++] * c; | |
i[d++] += a[e++] * c; | |
i[d++] += a[e++] * c | |
} | |
g = g + c; | |
break | |
} | |
} while (c > 0 && f < this.widthPassResultSize); | |
for (d = 0; d < this.targetWidthMultipliedByChannels;) { | |
j[h++] = Math.round(i[d++] / b); | |
j[h++] = Math.round(i[d++] / b); | |
j[h++] = Math.round(i[d++] / b); | |
j[h++] = Math.round(i[d++] / b) | |
} | |
} while (h < this.finalResultSize); | |
return j | |
}; | |
Resize.prototype.resize = function (a) { | |
return this.resizeHeight(this.resizeWidth(a)) | |
}; | |
Resize.prototype.bypassResizer = function (a) { | |
return a | |
}; | |
Resize.prototype.initializeFirstPassBuffers = function (a) { | |
this.widthBuffer = this.generateFloatBuffer(this.widthPassResultSize); | |
if (!a) this.outputWidthWorkBench = this.generateFloatBuffer(this.originalHeightMultipliedByChannels) | |
}; | |
Resize.prototype.initializeSecondPassBuffers = function (a) { | |
this.heightBuffer = this.generateUint8Buffer(this.finalResultSize); | |
if (!a) this.outputHeightWorkBench = this.generateFloatBuffer(this.targetWidthMultipliedByChannels) | |
}; | |
Resize.prototype.generateFloatBuffer = function (a) { | |
try { | |
return new Float32Array(a) | |
} catch (b) { | |
return [] | |
} | |
}; | |
Resize.prototype.generateUint8Buffer = function (a) { | |
try { | |
return this.checkForOperaMathBug(new Uint8Array(a)) | |
} catch (b) { | |
return [] | |
} | |
}; | |
Resize.prototype.checkForOperaMathBug = function (a) { | |
a[0] = -1; | |
a[0] = a[0] >> 0; | |
return a[0] != 255 ? [] : a | |
}; | |
function GameBoyCore(a, b) { | |
this.canvas = a; | |
this.drawContext = null; | |
this.ROMImage = b; | |
this.registerA = 1; | |
this.FZero = true; | |
this.FSubtract = false; | |
this.FCarry = this.FHalfCarry = true; | |
this.registerB = 0; | |
this.registerC = 19; | |
this.registerD = 0; | |
this.registerE = 216; | |
this.registersHL = 333; | |
this.stackPointer = 65534; | |
this.programCounter = 256; | |
this.remainingClocks = this.baseCPUCyclesPerIteration = this.CPUCyclesTotalRoundoff = this.CPUCyclesTotalCurrent = this.CPUCyclesTotalBase = this.CPUCyclesTotal = 0; | |
this.inBootstrap = true; | |
this.skipPCIncrement = this.halt = this.usedGBCBootROM = this.usedBootROM = false; | |
this.stopEmulator = 3; | |
this.IME = true; | |
this.interruptsEnabled = this.interruptsRequested = this.IRQLineMatched = 0; | |
this.hdmaRunning = false; | |
this.doubleSpeedShifter = this.CPUTicks = 0; | |
this.JoyPad = 255; | |
this.CPUStopped = false; | |
this.memoryReader = []; | |
this.memoryWriter = []; | |
this.memoryHighReader = []; | |
this.memoryHighWriter = []; | |
this.ROM = []; | |
this.memory = []; | |
this.MBCRam = []; | |
this.VRAM = []; | |
this.GBCMemory = []; | |
this.MBCRAMBanksEnabled = this.MBC1Mode = false; | |
this.currMBCRAMBank = 0; | |
this.currMBCRAMBankPosition = -40960; | |
this.cGBC = false; | |
this.gbcRamBank = 1; | |
this.gbcRamBankPosition = -53248; | |
this.gbcRamBankPositionECHO = -61440; | |
this.RAMBanks = [0, 1, 2, 4, 16]; | |
this.cartridgeType = this.currentROMBank = this.ROMBank1offs = 0; | |
this.gameCode = this.name = ""; | |
this.fromSaveState = false; | |
this.savedStateFileName = ""; | |
this.modeSTAT = this.STATTracker = 0; | |
this.spriteCount = 252; | |
this.LCDisOn = this.mode0TriggerSTAT = this.mode1TriggerSTAT = this.mode2TriggerSTAT = this.LYCMatchTriggerSTAT = false; | |
this.LINECONTROL = []; | |
this.DISPLAYOFFCONTROL = [function () {}]; | |
this.LCDCONTROL = null; | |
this.initializeLCDController(); | |
this.RTCisLatched = false; | |
this.RTCDays = this.RTCHours = this.RTCMinutes = this.RTCSeconds = this.latchedHDays = this.latchedLDays = this.latchedHours = this.latchedMinutes = this.latchedSeconds = 0; | |
this.RTCHALT = this.RTCDayOverFlow = false; | |
this.lowY = this.highY = this.lowX = this.highX = 127; | |
this.audioHandle = null; | |
this.sampleSize = this.numSamplesTotal = 0; | |
this.dutyLookup = [ | |
[false, false, false, false, false, false, false, true], | |
[true, false, false, false, false, false, false, true], | |
[true, false, false, false, false, true, true, true], | |
[false, true, true, true, true, true, true, false] | |
]; | |
this.currentBuffer = []; | |
this.bufferContainAmount = 0; | |
this.noiseSampleTable = this.LSFR7Table = this.LSFR15Table = null; | |
this.initializeAudioStartState(); | |
this.soundMasterEnabled = false; | |
this.channel3PCM = null; | |
this.VinRightChannelMasterVolume = this.VinLeftChannelMasterVolume = 8; | |
this.rightChannel4 = this.rightChannel3 = this.rightChannel2 = this.rightChannel1 = this.leftChannel4 = this.leftChannel3 = this.leftChannel2 = this.leftChannel1 = false; | |
this.mixerOutputCache = this.channel2currentSampleRightTrimary = this.channel2currentSampleLeftTrimary = this.channel1currentSampleRightTrimary = this.channel1currentSampleLeftTrimary = this.channel4currentSampleRightSecondary = this.channel4currentSampleLeftSecondary = this.channel3currentSampleRightSecondary = this.channel3currentSampleLeftSecondary = this.channel2currentSampleRightSecondary = this.channel2currentSampleLeftSecondary = this.channel1currentSampleRightSecondary = this.channel1currentSampleLeftSecondary = this.channel4currentSampleRight = this.channel4currentSampleLeft = this.channel3currentSampleRight = this.channel3currentSampleLeft = this.channel2currentSampleRight = this.channel2currentSampleLeft = this.channel1currentSampleRight = this.channel1currentSampleLeft = 0; | |
this.initializeTiming(); | |
this.emulatorTicks = this.rollover = this.audioIndex = this.audioTicks = this.machineOut = 0; | |
this.DIVTicks = 56; | |
this.LCDTicks = 60; | |
this.timerTicks = 0; | |
this.TIMAEnabled = false; | |
this.TACClocker = 1024; | |
this.IRQEnableDelay = this.serialShiftTimerAllocated = this.serialShiftTimer = this.serialTimer = 0; | |
var c = new Date; | |
this.lastIteration = c.getTime(); | |
c = new Date; | |
this.firstIteration = c.getTime(); | |
this.haltPostClocks = this.totalLinesPassed = this.queuedScanLines = this.lastUnrenderedLine = this.actualScanLine = this.iterations = 0; | |
this.cTIMER = this.cHuC1 = this.cHuC3 = this.cTAMA5 = this.cCamera = this.cRUMBLE = this.cMMMO1 = this.cSRAM = this.cMBC7 = this.cMBC5 = this.cMBC3 = this.cMBC2 = this.cMBC1 = false; | |
this.ROMBanks = [2, 4, 8, 16, 32, 64, 128, 256, 512]; | |
this.ROMBanks[82] = 72; | |
this.ROMBanks[83] = 80; | |
this.ROMBanks[84] = 96; | |
this.backgroundY = this.backgroundX = this.currVRAMBank = this.numRAMBanks = 0; | |
this.gfxSpriteShow = this.gfxWindowDisplay = false; | |
this.BGPriorityEnabled = this.bgEnabled = this.gfxSpriteNormalHeight = true; | |
this.gfxBackgroundCHRBankPosition = this.gfxWindowCHRBankPosition = 0; | |
this.gfxBackgroundBankOffset = 128; | |
this.drewBlank = this.windowX = this.windowY = 0; | |
this.drewFrame = false; | |
this.midScanlineOffset = -1; | |
this.currentX = this.pixelEnd = 0; | |
this.tileCache = this.BGCHRCurrentBank = this.BGCHRBank2 = this.BGCHRBank1 = null; | |
this.colors = [15728606, 11392916, 5411443, 1586242]; | |
this.cachedOBJPaletteConversion = this.cachedBGPaletteConversion = this.gbOBJColorizedPalette = this.gbBGColorizedPalette = this.gbcBGPalette = this.gbcOBJPalette = this.gbBGPalette = this.gbOBJPalette = this.gbcBGRawPalette = this.gbcOBJRawPalette = this.BGPalette = this.OBJPalette = null; | |
this.updateGBBGPalette = this.updateGBRegularBGPalette; | |
this.updateGBOBJPalette = this.updateGBRegularOBJPalette; | |
this.colorizedGBPalettes = false; | |
this.SpriteLayerRender = this.WindowLayerRender = this.BGLayerRender = null; | |
this.frameBuffer = []; | |
this.canvasBuffer = this.swizzledFrame = null; | |
this.pixelStart = 0; | |
this.onscreenWidth = this.offscreenWidth = 160; | |
this.onscreenHeight = this.offScreenheight = 144; | |
this.offscreenRGBCount = this.onscreenWidth * this.onscreenHeight * 4; | |
this.intializeWhiteNoise() | |
} | |
GameBoyCore.prototype.GBBOOTROM = [49, 254, 255, 175, 33, 255, 159, 50, 203, 124, 32, 251, 33, 38, 255, 14, 17, 62, 128, 50, 226, 12, 62, 243, 226, 50, 62, 119, 119, 62, 252, 224, 71, 17, 4, 1, 33, 16, 128, 26, 205, 149, 0, 205, 150, 0, 19, 123, 254, 52, 32, 243, 17, 216, 0, 6, 8, 26, 19, 34, 35, 5, 32, 249, 62, 25, 234, 16, 153, 33, 47, 153, 14, 12, 61, 40, 8, 50, 13, 32, 249, 46, 15, 24, 243, 103, 62, 100, 87, 224, 66, 62, 145, 224, 64, 4, 30, 2, 14, 12, 240, 68, 254, 144, 32, 250, 13, 32, 247, 29, 32, 242, 14, 19, 36, 124, 30, 131, 254, 98, 40, 6, 30, 193, 254, 100, 32, 6, 123, 226, 12, 62, 135, 226, 240, 66, 144, 224, 66, 21, 32, 210, 5, 32, 79, 22, 32, 24, 203, 79, 6, 4, 197, 203, 17, 23, 193, 203, 17, 23, 5, 32, 245, 34, 35, 34, 35, 201, 206, 237, 102, 102, 204, 13, 0, 11, 3, 115, 0, 131, 0, 12, 0, 13, 0, 8, 17, 31, 136, 137, 0, 14, 220, 204, 110, 230, 221, 221, 217, 153, 187, 187, 103, 99, 110, 14, 236, 204, 221, 220, 153, 159, 187, 185, 51, 62, 60, 66, 185, 165, 185, 165, 66, 60, 33, 4, 1, 17, 168, 0, 26, 19, 190, 32, 254, 35, 125, 254, 52, 32, 245, 6, 25, 120, 134, 35, 5, 32, 251, 134, 32, 254, 62, 1, 224, 80]; | |
GameBoyCore.prototype.GBCBOOTROM = [49, 254, 255, 62, 2, 195, 124, 0, 211, 0, 152, 160, 18, 211, 0, 128, 0, 64, 30, 83, 208, 0, 31, 66, 28, 0, 20, 42, 77, 25, 140, 126, 0, 124, 49, 110, 74, 69, 82, 74, 0, 0, 255, 83, 31, 124, 255, 3, 31, 0, 255, 31, 167, 0, 239, 27, 31, 0, 239, 27, 0, 124, 0, 0, 255, 3, 206, 237, 102, 102, 204, 13, 0, 11, 3, 115, 0, 131, 0, 12, 0, 13, 0, 8, 17, 31, 136, 137, 0, 14, 220, 204, 110, 230, 221, 221, 217, 153, 187, 187, 103, 99, 110, 14, 236, 204, 221, 220, 153, 159, 187, 185, 51, 62, 60, 66, 185, 165, 185, 165, 66, 60, 88, 67, 224, 112, 62, 252, 224, 71, 205, 117, 2, 205, 0, 2, 38, 208, 205, 3, 2, 33, 0, 254, 14, 160, 175, 34, 13, 32, 252, 17, 4, 1, 33, 16, 128, 76, 26, 226, 12, 205, 198, 3, 205, 199, 3, 19, 123, 254, 52, 32, 241, 17, 114, 0, 6, 8, 26, 19, 34, 35, 5, 32, 249, 205, 240, 3, 62, 1, 224, 79, 62, 145, 224, 64, 33, 178, 152, 6, 78, 14, 68, 205, 145, 2, 175, 224, 79, 14, 128, 33, 66, 0, 6, 24, 242, 12, 190, 32, 254, 35, 5, 32, 247, 33, 52, 1, 6, 25, 120, 134, 44, 5, 32, 251, 134, 32, 254, 205, 28, 3, 24, 2, 0, 0, 205, 208, 5, 175, 224, 112, 62, 17, 224, 80, 33, 0, 128, 175, 34, 203, 108, 40, 251, 201, 42, 18, 19, 13, 32, 250, 201, 229, 33, 15, 255, 203, 134, 203, 70, 40, 252, 225, 201, 17, 0, 255, 33, 3, 208, 14, 15, 62, 48, 18, 62, 32, 18, 26, 47, 161, 203, 55, 71, 62, 16, 18, 26, 47, 161, 176, 79, 126, 169, 230, 240, 71, 42, 169, 161, 176, 50, 71, 121, 119, 62, 48, 18, 201, 62, 128, 224, 104, 224, 106, 14, 107, 42, 226, 5, 32, 251, 74, 9, 67, 14, 105, 42, 226, 5, 32, 251, 201, 197, 213, 229, 33, 0, 216, 6, 1, 22, 63, 30, 64, 205, 74, 2, 225, 209, 193, 201, 62, 128, 224, 38, 224, 17, 62, 243, 224, 18, 224, 37, 62, 119, 224, 36, 33, 48, 255, 175, 14, 16, 34, 47, 13, 32, 251, 201, 205, 17, 2, 205, 98, 2, 121, 254, 56, 32, 20, 229, 175, 224, 79, 33, 167, 153, 62, 56, 34, 60, 254, 63, 32, 250, 62, 1, 224, 79, 225, 197, 229, 33, 67, 1, 203, 126, 204, 137, 5, 225, 193, 205, 17, 2, 121, 214, 48, 210, 6, 3, 121, 254, 1, 202, 6, 3, 125, 254, 209, 40, 33, 197, 6, 3, 14, 1, 22, 3, 126, 230, 248, 177, 34, 21, 32, 248, 12, 121, 254, 6, 32, 240, 17, 17, 0, 25, 5, 32, 231, 17, 161, 255, 25, 193, 4, 120, 30, 131, 254, 98, 40, 6, 30, 193, 254, 100, 32, 7, 123, 224, 19, 62, 135, 224, 20, 250, 2, 208, 254, 0, 40, 10, 61, 234, 2, 208, 121, 254, 1, 202, 145, 2, 13, 194, 145, 2, 201, 14, 38, 205, 74, 3, 205, 17, 2, 205, 98, 2, 13, 32, 244, 205, 17, 2, 62, 1, 224, 79, 205, 62, 3, 205, 65, 3, 175, 224, 79, 205, 62, 3, 201, 33, 8, 0, 17, 81, 255, 14, 5, 205, 10, 2, 201, 197, 213, 229, 33, 64, 216, 14, 32, 126, 230, 31, 254, 31, 40, 1, 60, 87, 42, 7, 7, 7, 230, 7, 71, 58, 7, 7, 7, 230, 24, 176, 254, 31, 40, 1, 60, 15, 15, 15, 71, 230, 224, 178, 34, 120, 230, 3, 95, 126, 15, 15, 230, 31, 254, 31, 40, 1, 60, 7, 7, 179, 34, 13, 32, 199, 225, 209, 193, 201, 14, 0, 26, 230, 240, 203, 73, 40, 2, 203, 55, 71, 35, 126, 176, 34, 26, 230, 15, 203, 73, 32, 2, 203, 55, 71, 35, 126, 176, 34, 19, 203, 65, 40, 13, 213, 17, 248, 255, 203, 73, 40, 3, 17, 8, 0, 25, 209, 12, 121, 254, 24, 32, 204, 201, 71, 213, 22, 4, 88, 203, 16, 23, 203, 19, 23, 21, 32, 246, 209, 34, 35, 34, 35, 201, 62, 25, 234, 16, 153, 33, 47, 153, 14, 12, 61, 40, 8, 50, 13, 32, 249, 46, 15, 24, 243, 201, 62, 1, 224, 79, 205, 0, 2, 17, 7, 6, 33, 128, 128, 14, 192, 26, 34, 35, 34, 35, 19, 13, 32, 247, 17, 4, 1, 205, 143, 3, 1, 168, 255, 9, 205, 143, 3, 1, 248, 255, 9, 17, 114, 0, 14, 8, 35, 26, 34, 19, 13, 32, 249, 33, 194, 152, 6, 8, 62, 8, 14, 16, 34, 13, 32, 252, 17, 16, 0, 25, 5, 32, 243, 175, 224, 79, 33, 194, 152, 62, 8, 34, 60, 254, 24, 32, 2, 46, 226, 254, 40, 32, 3, 33, 2, 153, 254, 56, 32, 237, 33, 216, 8, 17, 64, 216, 6, 8, 62, 255, 18, 19, 18, 19, 14, 2, 205, 10, 2, 62, 0, 18, 19, 18, 19, 19, 19, 5, 32, 234, 205, 98, 2, 33, 75, 1, 126, 254, 51, 32, 11, 46, 68, 30, 48, 42, 187, 32, 73, 28, 24, 4, 46, 75, 30, 1, 42, 187, 32, 62, 46, 52, 1, 16, 0, 42, 128, 71, 13, 32, 250, 234, 0, 208, 33, 199, 6, 14, 0, 42, 184, 40, 8, 12, 121, 254, 79, 32, 246, 24, 31, 121, 214, 65, 56, 28, 33, 22, 7, 22, 0, 95, 25, 250, 55, 1, 87, 126, 186, 40, 13, 17, 14, 0, 25, 121, 131, 79, 214, 94, 56, 237, 14, 0, 33, 51, 7, 6, 0, 9, 126, 230, 31, 234, 8, 208, 126, 230, 224, 7, 7, 7, 234, 11, 208, 205, 233, 4, 201, 17, 145, 7, 33, 0, 217, 250, 11, 208, 71, 14, 30, 203, 64, 32, 2, 19, 19, 26, 34, 32, 2, 27, 27, 203, 72, 32, 2, 19, 19, 26, 34, 19, 19, 32, 2, 27, 27, 203, 80, 40, 5, 27, 43, 26, 34, 19, 26, 34, 19, 13, 32, 215, 33, 0, 217, 17, 0, 218, 205, 100, 5, 201, 33, 18, 0, 250, 5, 208, 7, 7, 6, 0, 79, 9, 17, 64, 216, 6, 8, 229, 14, 2, 205, 10, 2, 19, 19, 19, 19, 19, 19, 225, 5, 32, 240, 17, 66, 216, 14, 2, 205, 10, 2, 17, 74, 216, 14, 2, 205, 10, 2, 43, 43, 17, 68, 216, 14, 2, 205, 10, 2, 201, 14, 96, 42, 229, 197, 33, 232, 7, 6, 0, 79, 9, 14, 8, 205, 10, 2, 193, 225, 13, 32, 236, 201, 250, 8, 208, 17, 24, 0, 60, 61, 40, 3, 25, 32, 250, 201, 205, 29, 2, 120, 230, 255, 40, 15, 33, 228, 8, 6, 0, 42, 185, 40, 8, 4, 120, 254, 12, 32, 246, 24, 45, 120, 234, 5, 208, 62, 30, 234, 2, 208, 17, 11, 0, 25, 86, 122, 230, 31, 95, 33, 8, 208, 58, 34, 123, 119, 122, 230, 224, 7, 7, 7, 95, 33, 11, 208, 58, 34, 123, 119, 205, 233, 4, 205, 40, 5, 201, 205, 17, 2, 250, 67, 1, 203, 127, 40, 4, 224, 76, 24, 40, 62, 4, 224, 76, 62, 1, 224, 108, 33, 0, 218, 205, 123, 5, 6, 16, 22, 0, 30, 8, 205, 74, 2, 33, 122, 0, 250, 0, 208, 71, 14, 2, 42, 184, 204, 218, 3, 13, 32, 248, 201, 1, 15, 63, 126, 255, 255, 192, 0, 192, 240, 241, 3, 124, 252, 254, 254, 3, 7, 7, 15, 224, 224, 240, 240, 30, 62, 126, 254, 15, 15, 31, 31, 255, 255, 0, 0, 1, 1, 1, 3, 255, 255, 225, 224, 192, 240, 249, 251, 31, 127, 248, 224, 243, 253, 62, 30, 224, 240, 249, 127, 62, 124, 248, 224, 248, 240, 240, 248, 0, 0, 127, 127, 7, 15, 159, 191, 158, 31, 255, 255, 15, 30, 62, 60, 241, 251, 127, 127, 254, 222, 223, 159, 31, 63, 62, 60, 248, 248, 0, 0, 3, 3, 7, 7, 255, 255, 193, 192, 243, 231, 247, 243, 192, 192, 192, 192, 31, 31, 30, 62, 63, 31, 62, 62, 128, 0, 0, 0, 124, 31, 7, 0, 15, 255, 254, 0, 124, 248, 240, 0, 31, 15, 15, 0, 124, 248, 248, 0, 63, 62, 28, 0, 15, 15, 15, 0, 124, 255, 255, 0, 0, 248, 248, 0, 7, 15, 15, 0, 129, 255, 255, 0, 243, 225, 128, 0, 224, 255, 127, 0, 252, 240, 192, 0, 62, 124, 124, 0, 0, 0, 0, 0, 0, 136, 22, 54, 209, 219, 242, 60, 140, 146, 61, 92, 88, 201, 62, 112, 29, 89, 105, 25, 53, 168, 20, 170, 117, 149, 153, 52, 111, 21, 255, 151, 75, 144, 23, 16, 57, 247, 246, 162, 73, 78, 67, 104, 224, 139, 240, 206, 12, 41, 232, 183, 134, 154, 82, 1, 157, 113, 156, 189, 93, 109, 103, 63, 107, 179, 70, 40, 165, 198, 211, 39, 97, 24, 102, 106, 191, 13, 244, 66, 69, 70, 65, 65, 82, 66, 69, 75, 69, 75, 32, 82, 45, 85, 82, 65, 82, 32, 73, 78, 65, 73, 76, 73, 67, 69, 32, 82, 124, 8, 18, 163, 162, 7, 135, 75, 32, 18, 101, 168, 22, 169, 134, 177, 104, 160, 135, 102, 18, 161, 48, 60, 18, 133, 18, 100, 27, 7, 6, 111, 110, 110, 174, 175, 111, 178, 175, 178, 168, 171, 111, 175, 134, 174, 162, 162, 18, 175, 19, 18, 161, 110, 175, 175, 173, 6, 76, 110, 175, 175, 18, 124, 172, 168, 106, 110, 19, 160, 45, 168, 43, 172, 100, 172, 109, 135, 188, 96, 180, 19, 114, 124, 181, 174, 174, 124, 124, 101, 162, 108, 100, 133, 128, 176, 64, 136, 32, 104, 222, 0, 112, 222, 32, 120, 32, 32, 56, 32, 176, 144, 32, 176, 160, 224, 176, 192, 152, 182, 72, 128, 224, 80, 30, 30, 88, 32, 184, 224, 136, 176, 16, 32, 0, 16, 32, 224, 24, 224, 24, 0, 24, 224, 32, 168, 224, 32, 24, 224, 0, 32, 24, 216, 200, 24, 224, 0, 224, 64, 40, 40, 40, 24, 224, 96, 32, 24, 224, 0, 0, 8, 224, 24, 48, 208, 208, 208, 32, 224, 232, 255, 127, 191, 50, 208, 0, 0, 0, 159, 99, 121, 66, 176, 21, 203, 4, 255, 127, 49, 110, 74, 69, 0, 0, 255, 127, 239, 27, 0, 2, 0, 0, 255, 127, 31, 66, 242, 28, 0, 0, 255, 127, 148, 82, 74, 41, 0, 0, 255, 127, 255, 3, 47, 1, 0, 0, 255, 127, 239, 3, 214, 1, 0, 0, 255, 127, 181, 66, 200, 61, 0, 0, 116, 126, 255, 3, 128, 1, 0, 0, 255, 103, 172, 119, 19, 26, 107, 45, 214, 126, 255, 75, 117, 33, 0, 0, 255, 83, 95, 74, 82, 126, 0, 0, 255, 79, 210, 126, 76, 58, 224, 28, 237, 3, 255, 127, 95, 37, 0, 0, 106, 3, 31, 2, 255, 3, 255, 127, 255, 127, 223, 1, 18, 1, 0, 0, 31, 35, 95, 3, 242, 0, 9, 0, 255, 127, 234, 3, 31, 1, 0, 0, 159, 41, 26, 0, 12, 0, 0, 0, 255, 127, 127, 2, 31, 0, 0, 0, 255, 127, 224, 3, 6, 2, 32, 1, 255, 127, 235, 126, 31, 0, 0, 124, 255, 127, 255, 63, 0, 126, 31, 0, 255, 127, 255, 3, 31, 0, 0, 0, 255, 3, 31, 0, 12, 0, 0, 0, 255, 127, 63, 3, 147, 1, 0, 0, 0, 0, 0, 66, 127, 3, 255, 127, 255, 127, 140, 126, 0, 124, 0, 0, 255, 127, 239, 27, 128, 97, 0, 0, 255, 127, 0, 124, 224, 3, 31, 124, 31, 0, 255, 3, 64, 65, 66, 32, 33, 34, 128, 129, 130, 16, 17, 18, 18, 176, 121, 184, 173, 22, 23, 7, 186, 5, 124, 19, 0, 0, 0, 0]; | |
GameBoyCore.prototype.ffxxDump = [15, 0, 124, 255, 0, 0, 0, 248, 255, 255, 255, 255, 255, 255, 255, 1, 128, 191, 243, 255, 191, 255, 63, 0, 255, 191, 127, 255, 159, 255, 191, 255, 255, 0, 0, 191, 119, 243, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 145, 128, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 255, 126, 255, 254, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 193, 0, 254, 255, 255, 255, 248, 255, 0, 0, 0, 143, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 206, 237, 102, 102, 204, 13, 0, 11, 3, 115, 0, 131, 0, 12, 0, 13, 0, 8, 17, 31, 136, 137, 0, 14, 220, 204, 110, 230, 221, 221, 217, 153, 187, 187, 103, 99, 110, 14, 236, 204, 221, 220, 153, 159, 187, 185, 51, 62, 69, 236, 82, 250, 8, 183, 7, 93, 1, 253, 192, 255, 8, 252, 0, 229, 11, 248, 194, 206, 244, 249, 15, 127, 69, 109, 61, 254, 70, 151, 51, 94, 8, 239, 241, 255, 134, 131, 36, 116, 18, 252, 0, 159, 180, 183, 6, 213, 208, 122, 0, 158, 4, 95, 65, 47, 29, 119, 54, 117, 129, 170, 112, 58, 152, 209, 113, 2, 77, 1, 193, 255, 13, 0, 211, 5, 249, 0, 11, 0]; | |
GameBoyCore.prototype.OPCODE = [function () {}, function (a) { | |
a.registerC = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.registerB = a.memoryRead(a.programCounter + 1 & 65535); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
a.memoryWrite(a.registerB << 8 | a.registerC, a.registerA) | |
}, function (a) { | |
var b = (a.registerB << 8 | a.registerC) + 1; | |
a.registerB = b >> 8 & 255; | |
a.registerC = b & 255 | |
}, function (a) { | |
a.registerB = a.registerB + 1 & 255; | |
a.FZero = a.registerB == 0; | |
a.FHalfCarry = (a.registerB & 15) == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerB = a.registerB - 1 & 255; | |
a.FZero = a.registerB == 0; | |
a.FHalfCarry = (a.registerB & 15) == 15; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerB = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.FCarry = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255 | a.registerA >> 7; | |
a.FZero = a.FSubtract = a.FHalfCarry = false | |
}, function (a) { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.memoryWrite(b, a.stackPointer & 255); | |
a.memoryWrite(b + 1 & 65535, a.stackPointer >> 8) | |
}, function (a) { | |
var b = a.registersHL + (a.registerB << 8 | a.registerC); | |
a.FHalfCarry = (a.registersHL & 4095) > (b & 4095); | |
a.FCarry = b > 65535; | |
a.registersHL = b & 65535; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerA = a.memoryRead(a.registerB << 8 | a.registerC) | |
}, function (a) { | |
var b = (a.registerB << 8 | a.registerC) - 1 & 65535; | |
a.registerB = b >> 8; | |
a.registerC = b & 255 | |
}, function (a) { | |
a.registerC = a.registerC + 1 & 255; | |
a.FZero = a.registerC == 0; | |
a.FHalfCarry = (a.registerC & 15) == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerC = a.registerC - 1 & 255; | |
a.FZero = a.registerC == 0; | |
a.FHalfCarry = (a.registerC & 15) == 15; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerC = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.registerA = a.registerA >> 1 | (a.registerA & 1) << 7; | |
a.FCarry = a.registerA > 127; | |
a.FZero = a.FSubtract = a.FHalfCarry = false | |
}, function (a) { | |
if (a.cGBC) if ((a.memory[65357] & 1) == 1) { | |
if (a.memory[65357] > 127) { | |
cout("Going into single clock speed mode.", 0); | |
a.doubleSpeedShifter = 0; | |
a.memory[65357] = a.memory[65357] & 127 | |
} else { | |
cout("Going into double clock speed mode.", 0); | |
a.doubleSpeedShifter = 1; | |
a.memory[65357] = a.memory[65357] | 128 | |
} | |
a.memory[65357] = a.memory[65357] & 254 | |
} else a.handleSTOP(); | |
else a.handleSTOP() | |
}, function (a) { | |
a.registerE = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.registerD = a.memoryRead(a.programCounter + 1 & 65535); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
a.memoryWrite(a.registerD << 8 | a.registerE, a.registerA) | |
}, function (a) { | |
var b = (a.registerD << 8 | a.registerE) + 1; | |
a.registerD = b >> 8 & 255; | |
a.registerE = b & 255 | |
}, function (a) { | |
a.registerD = a.registerD + 1 & 255; | |
a.FZero = a.registerD == 0; | |
a.FHalfCarry = (a.registerD & 15) == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerD = a.registerD - 1 & 255; | |
a.FZero = a.registerD == 0; | |
a.FHalfCarry = (a.registerD & 15) == 15; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerD = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
var b = a.FCarry ? 1 : 0; | |
a.FCarry = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255 | b; | |
a.FZero = a.FSubtract = a.FHalfCarry = false | |
}, function (a) { | |
a.programCounter = a.programCounter + (a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24) + 1 & 65535 | |
}, function (a) { | |
var b = a.registersHL + (a.registerD << 8 | a.registerE); | |
a.FHalfCarry = (a.registersHL & 4095) > (b & 4095); | |
a.FCarry = b > 65535; | |
a.registersHL = b & 65535; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerA = a.memoryRead(a.registerD << 8 | a.registerE) | |
}, function (a) { | |
var b = (a.registerD << 8 | a.registerE) - 1 & 65535; | |
a.registerD = b >> 8; | |
a.registerE = b & 255 | |
}, function (a) { | |
a.registerE = a.registerE + 1 & 255; | |
a.FZero = a.registerE == 0; | |
a.FHalfCarry = (a.registerE & 15) == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerE = a.registerE - 1 & 255; | |
a.FZero = a.registerE == 0; | |
a.FHalfCarry = (a.registerE & 15) == 15; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerE = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
var b = a.FCarry ? 128 : 0; | |
a.FCarry = (a.registerA & 1) == 1; | |
a.registerA = a.registerA >> 1 | b; | |
a.FZero = a.FSubtract = a.FHalfCarry = false | |
}, function (a) { | |
if (a.FZero) a.programCounter = a.programCounter + 1 & 65535; | |
else { | |
a.programCounter = a.programCounter + (a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24) + 1 & 65535; | |
a.CPUTicks = a.CPUTicks + 4 | |
} | |
}, function (a) { | |
a.registersHL = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerA); | |
a.registersHL = a.registersHL + 1 & 65535 | |
}, function (a) { | |
a.registersHL = a.registersHL + 1 & 65535 | |
}, function (a) { | |
var b = (a.registersHL >> 8) + 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 0; | |
a.FSubtract = false; | |
a.registersHL = b << 8 | a.registersHL & 255 | |
}, function (a) { | |
var b = (a.registersHL >> 8) - 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 15; | |
a.FSubtract = true; | |
a.registersHL = b << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.memoryReader[a.programCounter](a, a.programCounter) << 8 | a.registersHL & 255; | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
if (a.FSubtract) if (a.FCarry && a.FHalfCarry) { | |
a.registerA = a.registerA + 154 & 255; | |
a.FHalfCarry = false | |
} else if (a.FCarry) a.registerA = a.registerA + 160 & 255; | |
else { | |
if (a.FHalfCarry) { | |
a.registerA = a.registerA + 250 & 255; | |
a.FHalfCarry = false | |
} | |
} else { | |
if (a.FCarry || a.registerA > 153) { | |
a.registerA = a.registerA + 96 & 255; | |
a.FCarry = true | |
} | |
if (a.FHalfCarry || (a.registerA & 15) > 9) { | |
a.registerA = a.registerA + 6 & 255; | |
a.FHalfCarry = false | |
} | |
} | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
if (a.FZero) { | |
a.programCounter = a.programCounter + (a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24) + 1 & 65535; | |
a.CPUTicks = a.CPUTicks + 4 | |
} else a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.FHalfCarry = (a.registersHL & 4095) > 2047; | |
a.FCarry = a.registersHL > 32767; | |
a.registersHL = a.registersHL << 1 & 65535; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerA = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.registersHL = a.registersHL + 1 & 65535 | |
}, function (a) { | |
a.registersHL = a.registersHL - 1 & 65535 | |
}, function (a) { | |
var b = a.registersHL + 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 0; | |
a.FSubtract = false; | |
a.registersHL = a.registersHL & 65280 | b | |
}, function (a) { | |
var b = a.registersHL - 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 15; | |
a.FSubtract = true; | |
a.registersHL = a.registersHL & 65280 | b | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.registerA = a.registerA ^ 255; | |
a.FSubtract = a.FHalfCarry = true | |
}, function (a) { | |
if (a.FCarry) a.programCounter = a.programCounter + 1 & 65535; | |
else { | |
a.programCounter = a.programCounter + (a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24) + 1 & 65535; | |
a.CPUTicks = a.CPUTicks + 4 | |
} | |
}, function (a) { | |
a.stackPointer = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerA); | |
a.registersHL = a.registersHL - 1 & 65535 | |
}, function (a) { | |
a.stackPointer = a.stackPointer + 1 & 65535 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL) + 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 0; | |
a.FSubtract = false; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b) | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL) - 1 & 255; | |
a.FZero = b == 0; | |
a.FHalfCarry = (b & 15) == 15; | |
a.FSubtract = true; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.programCounter](a, a.programCounter)); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.FCarry = true; | |
a.FSubtract = a.FHalfCarry = false | |
}, function (a) { | |
if (a.FCarry) { | |
a.programCounter = a.programCounter + (a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24) + 1 & 65535; | |
a.CPUTicks = a.CPUTicks + 4 | |
} else a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
var b = a.registersHL + a.stackPointer; | |
a.FHalfCarry = (a.registersHL & 4095) > (b & 4095); | |
a.FCarry = b > 65535; | |
a.registersHL = b & 65535; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerA = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.registersHL = a.registersHL - 1 & 65535 | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535 | |
}, function (a) { | |
a.registerA = a.registerA + 1 & 255; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = (a.registerA & 15) == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.registerA = a.registerA - 1 & 255; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = (a.registerA & 15) == 15; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerA = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.FCarry = !a.FCarry; | |
a.FSubtract = a.FHalfCarry = false | |
}, function () {}, function (a) { | |
a.registerB = a.registerC | |
}, function (a) { | |
a.registerB = a.registerD | |
}, function (a) { | |
a.registerB = a.registerE | |
}, function (a) { | |
a.registerB = a.registersHL >> 8 | |
}, function (a) { | |
a.registerB = a.registersHL & 255 | |
}, function (a) { | |
a.registerB = a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function (a) { | |
a.registerB = a.registerA | |
}, function (a) { | |
a.registerC = a.registerB | |
}, function () {}, function (a) { | |
a.registerC = a.registerD | |
}, function (a) { | |
a.registerC = a.registerE | |
}, function (a) { | |
a.registerC = a.registersHL >> 8 | |
}, function (a) { | |
a.registerC = a.registersHL & 255 | |
}, function (a) { | |
a.registerC = a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function (a) { | |
a.registerC = a.registerA | |
}, function (a) { | |
a.registerD = a.registerB | |
}, function (a) { | |
a.registerD = a.registerC | |
}, function () {}, function (a) { | |
a.registerD = a.registerE | |
}, function (a) { | |
a.registerD = a.registersHL >> 8 | |
}, function (a) { | |
a.registerD = a.registersHL & 255 | |
}, function (a) { | |
a.registerD = a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function (a) { | |
a.registerD = a.registerA | |
}, function (a) { | |
a.registerE = a.registerB | |
}, function (a) { | |
a.registerE = a.registerC | |
}, function (a) { | |
a.registerE = a.registerD | |
}, function () {}, function (a) { | |
a.registerE = a.registersHL >> 8 | |
}, function (a) { | |
a.registerE = a.registersHL & 255 | |
}, function (a) { | |
a.registerE = a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function (a) { | |
a.registerE = a.registerA | |
}, function (a) { | |
a.registersHL = a.registerB << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.registerC << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.registerD << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.registerE << 8 | a.registersHL & 255 | |
}, function () {}, function (a) { | |
a.registersHL = (a.registersHL & 255) * 257 | |
}, function (a) { | |
a.registersHL = a.memoryReader[a.registersHL](a, a.registersHL) << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.registerA << 8 | a.registersHL & 255 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registerB | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registerC | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registerD | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registerE | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registersHL >> 8 | |
}, function () {}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | a.registerA | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerB) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerC) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerD) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerE) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registersHL >> 8) | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registersHL & 255) | |
}, function (a) { | |
(a.interruptsEnabled & a.interruptsRequested & 31) > 0 ? !a.cGBC && !a.usedBootROM ? a.skipPCIncrement = true : a.CPUTicks = a.CPUTicks + 4 : a.calculateHALTPeriod() | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.registerA) | |
}, function (a) { | |
a.registerA = a.registerB | |
}, function (a) { | |
a.registerA = a.registerC | |
}, function (a) { | |
a.registerA = a.registerD | |
}, function (a) { | |
a.registerA = a.registerE | |
}, function (a) { | |
a.registerA = a.registersHL >> 8 | |
}, function (a) { | |
a.registerA = a.registersHL & 255 | |
}, function (a) { | |
a.registerA = a.memoryReader[a.registersHL](a, a.registersHL) | |
}, function () {}, function (a) { | |
var b = a.registerA + a.registerB; | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerC; | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerD; | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerE; | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + (a.registersHL >> 8); | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + (a.registersHL & 255); | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.FHalfCarry = (a.registerA & 8) == 8; | |
a.FCarry = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerB + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (a.registerB & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerC + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (a.registerC & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerD + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (a.registerD & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA + a.registerE + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (a.registerE & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registersHL >> 8, | |
c = a.registerA + b + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (b & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = c > 255; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registersHL & 255, | |
c = a.registerA + b + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (b & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = c > 255; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL), | |
c = a.registerA + b + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (b & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = c > 255; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA << 1 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA << 1 & 30 | (a.FCarry ? 1 : 0)) > 15; | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
var b = a.registerA - a.registerB; | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerC; | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerD; | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerE; | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - (a.registersHL >> 8); | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - (a.registersHL & 255); | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
a.registerA = 0; | |
a.FHalfCarry = a.FCarry = false; | |
a.FZero = a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerB - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (a.registerB & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerC - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (a.registerC & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerD - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (a.registerD & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerE - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (a.registerE & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registersHL >> 8, | |
c = a.registerA - b - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (b & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = c < 0; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - (a.registersHL & 255) - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (a.registersHL & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL), | |
c = a.registerA - b - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (b & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = c < 0; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
if (a.FCarry) { | |
a.FZero = false; | |
a.FSubtract = a.FHalfCarry = a.FCarry = true; | |
a.registerA = 255 | |
} else { | |
a.FHalfCarry = a.FCarry = false; | |
a.FSubtract = a.FZero = true; | |
a.registerA = 0 | |
} | |
}, function (a) { | |
a.registerA = a.registerA & a.registerB; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.registerC; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.registerD; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.registerE; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.registersHL >> 8; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.registersHL; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA & a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registerB; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registerC; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registerD; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registerE; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registersHL >> 8; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.registersHL & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA ^ a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = 0; | |
a.FZero = true; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registerB; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registerC; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registerD; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registerE; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registersHL >> 8; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.registersHL & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.registerA = a.registerA | a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
var b = a.registerA - a.registerB; | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerC; | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerD; | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.registerE; | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - (a.registersHL >> 8); | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - (a.registersHL & 255); | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
var b = a.registerA - a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
a.FHalfCarry = a.FCarry = false; | |
a.FZero = a.FSubtract = true | |
}, function (a) { | |
if (!a.FZero) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.registerC = a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.registerB = a.memoryRead(a.stackPointer + 1 & 65535); | |
a.stackPointer = a.stackPointer + 2 & 65535 | |
}, function (a) { | |
if (a.FZero) a.programCounter = a.programCounter + 2 & 65535; | |
else { | |
a.programCounter = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.CPUTicks = a.CPUTicks + 4 | |
} | |
}, function (a) { | |
a.programCounter = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter) | |
}, function (a) { | |
if (a.FZero) a.programCounter = a.programCounter + 2 & 65535; | |
else { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = b; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registerB); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registerC) | |
}, function (a) { | |
var b = a.registerA + a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FHalfCarry = (b & 15) < (a.registerA & 15); | |
a.FCarry = b > 255; | |
a.registerA = b & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 0 | |
}, function (a) { | |
if (a.FZero) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535 | |
}, function (a) { | |
if (a.FZero) { | |
a.programCounter = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.CPUTicks = a.CPUTicks + 4 | |
} else a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
var b = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.CPUTicks = a.CPUTicks + a.SecondaryTICKTable[b]; | |
a.CBOPCODE[b](a) | |
}, function (a) { | |
if (a.FZero) { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = b; | |
a.CPUTicks = a.CPUTicks + 12 | |
} else a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = b | |
}, function (a) { | |
var b = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
var c = a.registerA + b + (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) + (b & 15) + (a.FCarry ? 1 : 0) > 15; | |
a.FCarry = c > 255; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = false | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 8 | |
}, function (a) { | |
if (!a.FCarry) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.registerE = a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.registerD = a.memoryRead(a.stackPointer + 1 & 65535); | |
a.stackPointer = a.stackPointer + 2 & 65535 | |
}, function (a) { | |
if (a.FCarry) a.programCounter = a.programCounter + 2 & 65535; | |
else { | |
a.programCounter = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.CPUTicks = a.CPUTicks + 4 | |
} | |
}, function () { | |
cout("Illegal op code 0xD3 called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
if (a.FCarry) a.programCounter = a.programCounter + 2 & 65535; | |
else { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = b; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registerD); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registerE) | |
}, function (a) { | |
var b = a.registerA - a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FHalfCarry = (a.registerA & 15) < (b & 15); | |
a.FCarry = b < 0; | |
a.registerA = b & 255; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 16 | |
}, function (a) { | |
if (a.FCarry) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535; | |
a.CPUTicks = a.CPUTicks + 12 | |
} | |
}, function (a) { | |
a.programCounter = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535; | |
a.IRQEnableDelay = a.IRQEnableDelay == 2 || a.memoryReader[a.programCounter](a, a.programCounter) == 118 ? 1 : 2 | |
}, function (a) { | |
if (a.FCarry) { | |
a.programCounter = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.CPUTicks = a.CPUTicks + 4 | |
} else a.programCounter = a.programCounter + 2 & 65535 | |
}, function () { | |
cout("Illegal op code 0xDB called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
if (a.FCarry) { | |
var b = a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 2 & 65535; | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = b; | |
a.CPUTicks = a.CPUTicks + 12 | |
} else a.programCounter = a.programCounter + 2 & 65535 | |
}, function () { | |
cout("Illegal op code 0xDD called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
var b = a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
var c = a.registerA - b - (a.FCarry ? 1 : 0); | |
a.FHalfCarry = (a.registerA & 15) - (b & 15) - (a.FCarry ? 1 : 0) < 0; | |
a.FCarry = c < 0; | |
a.registerA = c & 255; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = true | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 24 | |
}, function (a) { | |
a.memoryHighWrite(a.memoryReader[a.programCounter](a, a.programCounter), a.registerA); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
a.registersHL = a.memoryRead(a.stackPointer + 1 & 65535) << 8 | a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.stackPointer = a.stackPointer + 2 & 65535 | |
}, function (a) { | |
a.memoryHighWriter[a.registerC](a, a.registerC, a.registerA) | |
}, function () { | |
cout("Illegal op code 0xE3 called, pausing emulation.", 2); | |
pause() | |
}, function () { | |
cout("Illegal op code 0xE4 called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registersHL >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registersHL & 255) | |
}, function (a) { | |
a.registerA = a.registerA & a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FZero = a.registerA == 0; | |
a.FHalfCarry = true; | |
a.FSubtract = a.FCarry = false | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 32 | |
}, function (a) { | |
var b = a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24; | |
a.programCounter = a.programCounter + 1 & 65535; | |
var c = a.stackPointer + b & 65535, | |
b = a.stackPointer ^ b ^ c; | |
a.stackPointer = c; | |
a.FCarry = (b & 256) == 256; | |
a.FHalfCarry = (b & 16) == 16; | |
a.FZero = a.FSubtract = false | |
}, function (a) { | |
a.programCounter = a.registersHL | |
}, function (a) { | |
a.memoryWrite(a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter), a.registerA); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function () { | |
cout("Illegal op code 0xEB called, pausing emulation.", 2); | |
pause() | |
}, function () { | |
cout("Illegal op code 0xEC called, pausing emulation.", 2); | |
pause() | |
}, function () { | |
cout("Illegal op code 0xED called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
a.registerA = a.registerA ^ a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FZero = a.registerA == 0; | |
a.FSubtract = a.FHalfCarry = a.FCarry = false | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 40 | |
}, function (a) { | |
a.registerA = a.memoryHighRead(a.memoryReader[a.programCounter](a, a.programCounter)); | |
a.programCounter = a.programCounter + 1 & 65535 | |
}, function (a) { | |
var b = a.memoryReader[a.stackPointer](a, a.stackPointer); | |
a.FZero = b > 127; | |
a.FSubtract = (b & 64) == 64; | |
a.FHalfCarry = (b & 32) == 32; | |
a.FCarry = (b & 16) == 16; | |
a.registerA = a.memoryRead(a.stackPointer + 1 & 65535); | |
a.stackPointer = a.stackPointer + 2 & 65535 | |
}, function (a) { | |
a.registerA = a.memoryHighReader[a.registerC](a, a.registerC) | |
}, function (a) { | |
a.IME = false; | |
a.IRQEnableDelay = 0 | |
}, function () { | |
cout("Illegal op code 0xF4 called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.registerA); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, (a.FZero ? 128 : 0) | (a.FSubtract ? 64 : 0) | (a.FHalfCarry ? 32 : 0) | (a.FCarry ? 16 : 0)) | |
}, function (a) { | |
a.registerA = a.registerA | a.memoryReader[a.programCounter](a, a.programCounter); | |
a.FZero = a.registerA == 0; | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FSubtract = a.FCarry = a.FHalfCarry = false | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 48 | |
}, function (a) { | |
var b = a.memoryReader[a.programCounter](a, a.programCounter) << 24 >> 24; | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.registersHL = a.stackPointer + b & 65535; | |
b = a.stackPointer ^ b ^ a.registersHL; | |
a.FCarry = (b & 256) == 256; | |
a.FHalfCarry = (b & 16) == 16; | |
a.FZero = a.FSubtract = false | |
}, function (a) { | |
a.stackPointer = a.registersHL | |
}, function (a) { | |
a.registerA = a.memoryRead(a.memoryRead(a.programCounter + 1 & 65535) << 8 | a.memoryReader[a.programCounter](a, a.programCounter)); | |
a.programCounter = a.programCounter + 2 & 65535 | |
}, function (a) { | |
a.IRQEnableDelay = a.IRQEnableDelay == 2 || a.memoryReader[a.programCounter](a, a.programCounter) == 118 ? 1 : 2 | |
}, function () { | |
cout("Illegal op code 0xFC called, pausing emulation.", 2); | |
pause() | |
}, function () { | |
cout("Illegal op code 0xFD called, pausing emulation.", 2); | |
pause() | |
}, function (a) { | |
var b = a.registerA - a.memoryReader[a.programCounter](a, a.programCounter); | |
a.programCounter = a.programCounter + 1 & 65535; | |
a.FHalfCarry = (b & 15) > (a.registerA & 15); | |
a.FCarry = b < 0; | |
a.FZero = b == 0; | |
a.FSubtract = true | |
}, function (a) { | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter >> 8); | |
a.stackPointer = a.stackPointer - 1 & 65535; | |
a.memoryWriter[a.stackPointer](a, a.stackPointer, a.programCounter & 255); | |
a.programCounter = 56 | |
}]; | |
GameBoyCore.prototype.CBOPCODE = [function (a) { | |
a.FCarry = a.registerB > 127; | |
a.registerB = a.registerB << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
a.FCarry = a.registerC > 127; | |
a.registerC = a.registerC << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
a.FCarry = a.registerD > 127; | |
a.registerD = a.registerD << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
a.FCarry = a.registerE > 127; | |
a.registerE = a.registerE << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
a.FCarry = a.registersHL > 32767; | |
a.registersHL = a.registersHL << 1 & 65024 | (a.FCarry ? 256 : 0) | a.registersHL & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 128) == 128; | |
a.registersHL = a.registersHL & 65280 | a.registersHL << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FCarry = b > 127; | |
b = b << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
a.FCarry = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
a.FCarry = (a.registerB & 1) == 1; | |
a.registerB = (a.FCarry ? 128 : 0) | a.registerB >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
a.FCarry = (a.registerC & 1) == 1; | |
a.registerC = (a.FCarry ? 128 : 0) | a.registerC >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
a.FCarry = (a.registerD & 1) == 1; | |
a.registerD = (a.FCarry ? 128 : 0) | a.registerD >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
a.FCarry = (a.registerE & 1) == 1; | |
a.registerE = (a.FCarry ? 128 : 0) | a.registerE >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 256) == 256; | |
a.registersHL = (a.FCarry ? 32768 : 0) | a.registersHL >> 1 & 65280 | a.registersHL & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 1) == 1; | |
a.registersHL = a.registersHL & 65280 | (a.FCarry ? 128 : 0) | (a.registersHL & 255) >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FCarry = (b & 1) == 1; | |
b = (a.FCarry ? 128 : 0) | b >> 1; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
a.FCarry = (a.registerA & 1) == 1; | |
a.registerA = (a.FCarry ? 128 : 0) | a.registerA >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
var b = a.registerB > 127; | |
a.registerB = a.registerB << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
var b = a.registerC > 127; | |
a.registerC = a.registerC << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
var b = a.registerD > 127; | |
a.registerD = a.registerD << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
var b = a.registerE > 127; | |
a.registerE = a.registerE << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
var b = a.registersHL > 32767; | |
a.registersHL = a.registersHL << 1 & 65024 | (a.FCarry ? 256 : 0) | a.registersHL & 255; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
var b = (a.registersHL & 128) == 128; | |
a.registersHL = a.registersHL & 65280 | a.registersHL << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL), | |
c = b > 127, | |
b = b << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = c; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
var b = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255 | (a.FCarry ? 1 : 0); | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
var b = (a.registerB & 1) == 1; | |
a.registerB = (a.FCarry ? 128 : 0) | a.registerB >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
var b = (a.registerC & 1) == 1; | |
a.registerC = (a.FCarry ? 128 : 0) | a.registerC >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
var b = (a.registerD & 1) == 1; | |
a.registerD = (a.FCarry ? 128 : 0) | a.registerD >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
var b = (a.registerE & 1) == 1; | |
a.registerE = (a.FCarry ? 128 : 0) | a.registerE >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
var b = (a.registersHL & 256) == 256; | |
a.registersHL = (a.FCarry ? 32768 : 0) | a.registersHL >> 1 & 65280 | a.registersHL & 255; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
var b = (a.registersHL & 1) == 1; | |
a.registersHL = a.registersHL & 65280 | (a.FCarry ? 128 : 0) | (a.registersHL & 255) >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL), | |
c = (b & 1) == 1, | |
b = (a.FCarry ? 128 : 0) | b >> 1; | |
a.FCarry = c; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
var b = (a.registerA & 1) == 1; | |
a.registerA = (a.FCarry ? 128 : 0) | a.registerA >> 1; | |
a.FCarry = b; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
a.FCarry = a.registerB > 127; | |
a.registerB = a.registerB << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
a.FCarry = a.registerC > 127; | |
a.registerC = a.registerC << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
a.FCarry = a.registerD > 127; | |
a.registerD = a.registerD << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
a.FCarry = a.registerE > 127; | |
a.registerE = a.registerE << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
a.FCarry = a.registersHL > 32767; | |
a.registersHL = a.registersHL << 1 & 65024 | a.registersHL & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 128) == 128; | |
a.registersHL = a.registersHL & 65280 | a.registersHL << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FCarry = b > 127; | |
b = b << 1 & 255; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
a.FCarry = a.registerA > 127; | |
a.registerA = a.registerA << 1 & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
a.FCarry = (a.registerB & 1) == 1; | |
a.registerB = a.registerB & 128 | a.registerB >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
a.FCarry = (a.registerC & 1) == 1; | |
a.registerC = a.registerC & 128 | a.registerC >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
a.FCarry = (a.registerD & 1) == 1; | |
a.registerD = a.registerD & 128 | a.registerD >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
a.FCarry = (a.registerE & 1) == 1; | |
a.registerE = a.registerE & 128 | a.registerE >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 256) == 256; | |
a.registersHL = a.registersHL >> 1 & 65280 | a.registersHL & 33023; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 1) == 1; | |
a.registersHL = a.registersHL & 65408 | (a.registersHL & 255) >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FCarry = (b & 1) == 1; | |
b = b & 128 | b >> 1; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b == 0 | |
}, function (a) { | |
a.FCarry = (a.registerA & 1) == 1; | |
a.registerA = a.registerA & 128 | a.registerA >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
a.registerB = (a.registerB & 15) << 4 | a.registerB >> 4; | |
a.FZero = a.registerB == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registerC = (a.registerC & 15) << 4 | a.registerC >> 4; | |
a.FZero = a.registerC == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registerD = (a.registerD & 15) << 4 | a.registerD >> 4; | |
a.FZero = a.registerD == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registerE = (a.registerE & 15) << 4 | a.registerE >> 4; | |
a.FZero = a.registerE == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registersHL = (a.registersHL & 3840) << 4 | (a.registersHL & 61440) >> 4 | a.registersHL & 255; | |
a.FZero = a.registersHL < 256; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registersHL = a.registersHL & 65280 | (a.registersHL & 15) << 4 | (a.registersHL & 240) >> 4; | |
a.FZero = (a.registersHL & 255) == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL), | |
b = (b & 15) << 4 | b >> 4; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b); | |
a.FZero = b == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.registerA = (a.registerA & 15) << 4 | a.registerA >> 4; | |
a.FZero = a.registerA == 0; | |
a.FCarry = a.FHalfCarry = a.FSubtract = false | |
}, function (a) { | |
a.FCarry = (a.registerB & 1) == 1; | |
a.registerB = a.registerB >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerB == 0 | |
}, function (a) { | |
a.FCarry = (a.registerC & 1) == 1; | |
a.registerC = a.registerC >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerC == 0 | |
}, function (a) { | |
a.FCarry = (a.registerD & 1) == 1; | |
a.registerD = a.registerD >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerD == 0 | |
}, function (a) { | |
a.FCarry = (a.registerE & 1) == 1; | |
a.registerE = a.registerE >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerE == 0 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 256) == 256; | |
a.registersHL = a.registersHL >> 1 & 65280 | a.registersHL & 255; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registersHL < 256 | |
}, function (a) { | |
a.FCarry = (a.registersHL & 1) == 1; | |
a.registersHL = a.registersHL & 65280 | (a.registersHL & 255) >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = (a.registersHL & 255) == 0 | |
}, function (a) { | |
var b = a.memoryReader[a.registersHL](a, a.registersHL); | |
a.FCarry = (b & 1) == 1; | |
a.memoryWriter[a.registersHL](a, a.registersHL, b >> 1); | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = b < 2 | |
}, function (a) { | |
a.FCarry = (a.registerA & 1) == 1; | |
a.registerA = a.registerA >> 1; | |
a.FHalfCarry = a.FSubtract = false; | |
a.FZero = a.registerA == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 256) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 1) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 512) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 2) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 1024) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 4) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 2048) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 8) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 4096) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 16) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 8192) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 32) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 16384) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 64) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerB & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerC & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerD & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerE & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 32768) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registersHL & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.memoryReader[a.registersHL](a, a.registersHL) & 128) == 0 | |
}, function (a) { | |
a.FHalfCarry = true; | |
a.FSubtract = false; | |
a.FZero = (a.registerA & 128) == 0 | |
}, function (a) { | |
a.registerB = a.registerB & 254 | |
}, function (a) { | |
a.registerC = a.registerC & 254 | |
}, function (a) { | |
a.registerD = a.registerD & 254 | |
}, function (a) { | |
a.registerE = a.registerE & 254 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65279 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65534 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 254) | |
}, function (a) { | |
a.registerA = a.registerA & 254 | |
}, function (a) { | |
a.registerB = a.registerB & 253 | |
}, function (a) { | |
a.registerC = a.registerC & 253 | |
}, function (a) { | |
a.registerD = a.registerD & 253 | |
}, function (a) { | |
a.registerE = a.registerE & 253 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65023 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65533 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 253) | |
}, function (a) { | |
a.registerA = a.registerA & 253 | |
}, function (a) { | |
a.registerB = a.registerB & 251 | |
}, function (a) { | |
a.registerC = a.registerC & 251 | |
}, function (a) { | |
a.registerD = a.registerD & 251 | |
}, function (a) { | |
a.registerE = a.registerE & 251 | |
}, function (a) { | |
a.registersHL = a.registersHL & 64511 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65531 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 251) | |
}, function (a) { | |
a.registerA = a.registerA & 251 | |
}, function (a) { | |
a.registerB = a.registerB & 247 | |
}, function (a) { | |
a.registerC = a.registerC & 247 | |
}, function (a) { | |
a.registerD = a.registerD & 247 | |
}, function (a) { | |
a.registerE = a.registerE & 247 | |
}, function (a) { | |
a.registersHL = a.registersHL & 63487 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65527 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 247) | |
}, function (a) { | |
a.registerA = a.registerA & 247 | |
}, function (a) { | |
a.registerB = a.registerB & 239 | |
}, function (a) { | |
a.registerC = a.registerC & 239 | |
}, function (a) { | |
a.registerD = a.registerD & 239 | |
}, function (a) { | |
a.registerE = a.registerE & 239 | |
}, function (a) { | |
a.registersHL = a.registersHL & 61439 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65519 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 239) | |
}, function (a) { | |
a.registerA = a.registerA & 239 | |
}, function (a) { | |
a.registerB = a.registerB & 223 | |
}, function (a) { | |
a.registerC = a.registerC & 223 | |
}, function (a) { | |
a.registerD = a.registerD & 223 | |
}, function (a) { | |
a.registerE = a.registerE & 223 | |
}, function (a) { | |
a.registersHL = a.registersHL & 57343 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65503 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 223) | |
}, function (a) { | |
a.registerA = a.registerA & 223 | |
}, function (a) { | |
a.registerB = a.registerB & 191 | |
}, function (a) { | |
a.registerC = a.registerC & 191 | |
}, function (a) { | |
a.registerD = a.registerD & 191 | |
}, function (a) { | |
a.registerE = a.registerE & 191 | |
}, function (a) { | |
a.registersHL = a.registersHL & 49151 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65471 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 191) | |
}, function (a) { | |
a.registerA = a.registerA & 191 | |
}, function (a) { | |
a.registerB = a.registerB & 127 | |
}, function (a) { | |
a.registerC = a.registerC & 127 | |
}, function (a) { | |
a.registerD = a.registerD & 127 | |
}, function (a) { | |
a.registerE = a.registerE & 127 | |
}, function (a) { | |
a.registersHL = a.registersHL & 32767 | |
}, function (a) { | |
a.registersHL = a.registersHL & 65407 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) & 127) | |
}, function (a) { | |
a.registerA = a.registerA & 127 | |
}, function (a) { | |
a.registerB = a.registerB | 1 | |
}, function (a) { | |
a.registerC = a.registerC | 1 | |
}, function (a) { | |
a.registerD = a.registerD | 1 | |
}, function (a) { | |
a.registerE = a.registerE | 1 | |
}, function (a) { | |
a.registersHL = a.registersHL | 256 | |
}, function (a) { | |
a.registersHL = a.registersHL | 1 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 1) | |
}, function (a) { | |
a.registerA = a.registerA | 1 | |
}, function (a) { | |
a.registerB = a.registerB | 2 | |
}, function (a) { | |
a.registerC = a.registerC | 2 | |
}, function (a) { | |
a.registerD = a.registerD | 2 | |
}, function (a) { | |
a.registerE = a.registerE | 2 | |
}, function (a) { | |
a.registersHL = a.registersHL | 512 | |
}, function (a) { | |
a.registersHL = a.registersHL | 2 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 2) | |
}, function (a) { | |
a.registerA = a.registerA | 2 | |
}, function (a) { | |
a.registerB = a.registerB | 4 | |
}, function (a) { | |
a.registerC = a.registerC | 4 | |
}, function (a) { | |
a.registerD = a.registerD | 4 | |
}, function (a) { | |
a.registerE = a.registerE | 4 | |
}, function (a) { | |
a.registersHL = a.registersHL | 1024 | |
}, function (a) { | |
a.registersHL = a.registersHL | 4 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 4) | |
}, function (a) { | |
a.registerA = a.registerA | 4 | |
}, function (a) { | |
a.registerB = a.registerB | 8 | |
}, function (a) { | |
a.registerC = a.registerC | 8 | |
}, function (a) { | |
a.registerD = a.registerD | 8 | |
}, function (a) { | |
a.registerE = a.registerE | 8 | |
}, function (a) { | |
a.registersHL = a.registersHL | 2048 | |
}, function (a) { | |
a.registersHL = a.registersHL | 8 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 8) | |
}, function (a) { | |
a.registerA = a.registerA | 8 | |
}, function (a) { | |
a.registerB = a.registerB | 16 | |
}, function (a) { | |
a.registerC = a.registerC | 16 | |
}, function (a) { | |
a.registerD = a.registerD | 16 | |
}, function (a) { | |
a.registerE = a.registerE | 16 | |
}, function (a) { | |
a.registersHL = a.registersHL | 4096 | |
}, function (a) { | |
a.registersHL = a.registersHL | 16 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 16) | |
}, function (a) { | |
a.registerA = a.registerA | 16 | |
}, function (a) { | |
a.registerB = a.registerB | 32 | |
}, function (a) { | |
a.registerC = a.registerC | 32 | |
}, function (a) { | |
a.registerD = a.registerD | 32 | |
}, function (a) { | |
a.registerE = a.registerE | 32 | |
}, function (a) { | |
a.registersHL = a.registersHL | 8192 | |
}, function (a) { | |
a.registersHL = a.registersHL | 32 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 32) | |
}, function (a) { | |
a.registerA = a.registerA | 32 | |
}, function (a) { | |
a.registerB = a.registerB | 64 | |
}, function (a) { | |
a.registerC = a.registerC | 64 | |
}, function (a) { | |
a.registerD = a.registerD | 64 | |
}, function (a) { | |
a.registerE = a.registerE | 64 | |
}, function (a) { | |
a.registersHL = a.registersHL | 16384 | |
}, function (a) { | |
a.registersHL = a.registersHL | 64 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 64) | |
}, function (a) { | |
a.registerA = a.registerA | 64 | |
}, function (a) { | |
a.registerB = a.registerB | 128 | |
}, function (a) { | |
a.registerC = a.registerC | 128 | |
}, function (a) { | |
a.registerD = a.registerD | 128 | |
}, function (a) { | |
a.registerE = a.registerE | 128 | |
}, function (a) { | |
a.registersHL = a.registersHL | 32768 | |
}, function (a) { | |
a.registersHL = a.registersHL | 128 | |
}, function (a) { | |
a.memoryWriter[a.registersHL](a, a.registersHL, a.memoryReader[a.registersHL](a, a.registersHL) | 128) | |
}, function (a) { | |
a.registerA = a.registerA | 128 | |
}]; | |
GameBoyCore.prototype.TICKTable = [4, 12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4, 4, 12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4, 8, 12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4, 8, 12, 8, 8, 12, 12, 12, 4, 8, 8, 8, 8, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4, 8, 12, 12, 16, 12, 16, 8, 16, 8, 16, 12, 0, 12, 24, 8, 16, 8, 12, 12, 4, 12, 16, 8, 16, 8, 16, 12, 4, 12, 4, 8, 16, 12, 12, 8, 4, 4, 16, 8, 16, 16, 4, 16, 4, 4, 4, 8, 16, 12, 12, 8, 4, 4, 16, 8, 16, 12, 8, 16, 4, 0, 4, 8, 16]; | |
GameBoyCore.prototype.SecondaryTICKTable = [8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8]; | |
GameBoyCore.prototype.saveSRAMState = function () { | |
return !this.cBATT || this.MBCRam.length == 0 ? [] : this.fromTypedArray(this.MBCRam) | |
}; | |
GameBoyCore.prototype.saveRTCState = function () { | |
return this.cTIMER ? [this.lastIteration, this.RTCisLatched, this.latchedSeconds, this.latchedMinutes, this.latchedHours, this.latchedLDays, this.latchedHDays, this.RTCSeconds, this.RTCMinutes, this.RTCHours, this.RTCDays, this.RTCDayOverFlow, this.RTCHALT] : [] | |
}; | |
GameBoyCore.prototype.saveState = function () { | |
return [this.fromTypedArray(this.ROM), this.inBootstrap, this.registerA, this.FZero, this.FSubtract, this.FHalfCarry, this.FCarry, this.registerB, this.registerC, this.registerD, this.registerE, this.registersHL, this.stackPointer, this.programCounter, this.halt, this.IME, this.hdmaRunning, this.CPUTicks, this.doubleSpeedShifter, this.fromTypedArray(this.memory), this.fromTypedArray(this.MBCRam), this.fromTypedArray(this.VRAM), this.currVRAMBank, this.fromTypedArray(this.GBCMemory), this.MBC1Mode, this.MBCRAMBanksEnabled, this.currMBCRAMBank, this.currMBCRAMBankPosition, this.cGBC, this.gbcRamBank, this.gbcRamBankPosition, this.ROMBank1offs, this.currentROMBank, this.cartridgeType, this.name, this.gameCode, this.modeSTAT, this.LYCMatchTriggerSTAT, this.mode2TriggerSTAT, this.mode1TriggerSTAT, this.mode0TriggerSTAT, this.LCDisOn, this.gfxWindowCHRBankPosition, this.gfxWindowDisplay, this.gfxSpriteShow, this.gfxSpriteNormalHeight, this.gfxBackgroundCHRBankPosition, this.gfxBackgroundBankOffset, this.TIMAEnabled, this.DIVTicks, this.LCDTicks, this.timerTicks, this.TACClocker, this.serialTimer, this.serialShiftTimer, this.serialShiftTimerAllocated, this.IRQEnableDelay, this.lastIteration, this.cMBC1, this.cMBC2, this.cMBC3, this.cMBC5, this.cMBC7, this.cSRAM, this.cMMMO1, this.cRUMBLE, this.cCamera, this.cTAMA5, this.cHuC3, this.cHuC1, this.drewBlank, this.fromTypedArray(this.frameBuffer), this.bgEnabled, this.BGPriorityEnabled, this.channel1FrequencyTracker, this.channel1FrequencyCounter, this.channel1totalLength, this.channel1envelopeVolume, this.channel1envelopeType, this.channel1envelopeSweeps, this.channel1envelopeSweepsLast, this.channel1consecutive, this.channel1frequency, this.channel1SweepFault, this.channel1ShadowFrequency, this.channel1timeSweep, this.channel1lastTimeSweep, this.channel1numSweep, this.channel1frequencySweepDivider, this.channel1decreaseSweep, this.channel2FrequencyTracker, this.channel2FrequencyCounter, this.channel2totalLength, this.channel2envelopeVolume, this.channel2envelopeType, this.channel2envelopeSweeps, this.channel2envelopeSweepsLast, this.channel2consecutive, this.channel2frequency, this.channel3canPlay, this.channel3totalLength, this.channel3patternType, this.channel3frequency, this.channel3consecutive, this.fromTypedArray(this.channel3PCM), this.channel4FrequencyPeriod, this.channel4lastSampleLookup, this.channel4totalLength, this.channel4envelopeVolume, this.channel4currentVolume, this.channel4envelopeType, this.channel4envelopeSweeps, this.channel4envelopeSweepsLast, this.channel4consecutive, this.channel4BitRange, this.soundMasterEnabled, this.VinLeftChannelMasterVolume, this.VinRightChannelMasterVolume, this.leftChannel1, this.leftChannel2, this.leftChannel3, this.leftChannel4, this.rightChannel1, this.rightChannel2, this.rightChannel3, this.rightChannel4, this.channel1currentSampleLeft, this.channel1currentSampleRight, this.channel2currentSampleLeft, this.channel2currentSampleRight, this.channel3currentSampleLeft, this.channel3currentSampleRight, this.channel4currentSampleLeft, this.channel4currentSampleRight, this.channel1currentSampleLeftSecondary, this.channel1currentSampleRightSecondary, this.channel2currentSampleLeftSecondary, this.channel2currentSampleRightSecondary, this.channel3currentSampleLeftSecondary, this.channel3currentSampleRightSecondary, this.channel4currentSampleLeftSecondary, this.channel4currentSampleRightSecondary, this.channel1currentSampleLeftTrimary, this.channel1currentSampleRightTrimary, this.channel2currentSampleLeftTrimary, this.channel2currentSampleRightTrimary, this.mixerOutputCache, this.channel1DutyTracker, this.channel1CachedDuty, this.channel2DutyTracker, this.channel2CachedDuty, this.channel1Enabled, this.channel2Enabled, this.channel3Enabled, this.channel4Enabled, this.sequencerClocks, this.sequencePosition, this.channel3Counter, this.channel4Counter, this.cachedChannel3Sample, this.cachedChannel4Sample, this.channel3FrequencyPeriod, this.channel3lastSampleLookup, this.actualScanLine, this.lastUnrenderedLine, this.queuedScanLines, this.RTCisLatched, this.latchedSeconds, this.latchedMinutes, this.latchedHours, this.latchedLDays, this.latchedHDays, this.RTCSeconds, this.RTCMinutes, this.RTCHours, this.RTCDays, this.RTCDayOverFlow, this.RTCHALT, this.usedBootROM, this.skipPCIncrement, this.STATTracker, this.gbcRamBankPositionECHO, this.numRAMBanks, this.windowY, this.windowX, this.fromTypedArray(this.gbcOBJRawPalette), this.fromTypedArray(this.gbcBGRawPalette), this.fromTypedArray(this.gbOBJPalette), this.fromTypedArray(this.gbBGPalette), this.fromTypedArray(this.gbcOBJPalette), this.fromTypedArray(this.gbcBGPalette), this.fromTypedArray(this.gbBGColorizedPalette), this.fromTypedArray(this.gbOBJColorizedPalette), this.fromTypedArray(this.cachedBGPaletteConversion), this.fromTypedArray(this.cachedOBJPaletteConversion), this.fromTypedArray(this.BGCHRBank1), this.fromTypedArray(this.BGCHRBank2), this.haltPostClocks, this.interruptsRequested, this.interruptsEnabled, this.remainingClocks, this.colorizedGBPalettes, this.backgroundY, this.backgroundX, this.CPUStopped] | |
}; | |
GameBoyCore.prototype.returnFromState = function (a) { | |
var b = 0, | |
a = a.slice(0); | |
this.ROM = this.toTypedArray(a[b++], "uint8"); | |
this.ROMBankEdge = Math.floor(this.ROM.length / 16384); | |
this.inBootstrap = a[b++]; | |
this.registerA = a[b++]; | |
this.FZero = a[b++]; | |
this.FSubtract = a[b++]; | |
this.FHalfCarry = a[b++]; | |
this.FCarry = a[b++]; | |
this.registerB = a[b++]; | |
this.registerC = a[b++]; | |
this.registerD = a[b++]; | |
this.registerE = a[b++]; | |
this.registersHL = a[b++]; | |
this.stackPointer = a[b++]; | |
this.programCounter = a[b++]; | |
this.halt = a[b++]; | |
this.IME = a[b++]; | |
this.hdmaRunning = a[b++]; | |
this.CPUTicks = a[b++]; | |
this.doubleSpeedShifter = a[b++]; | |
this.memory = this.toTypedArray(a[b++], "uint8"); | |
this.MBCRam = this.toTypedArray(a[b++], "uint8"); | |
this.VRAM = this.toTypedArray(a[b++], "uint8"); | |
this.currVRAMBank = a[b++]; | |
this.GBCMemory = this.toTypedArray(a[b++], "uint8"); | |
this.MBC1Mode = a[b++]; | |
this.MBCRAMBanksEnabled = a[b++]; | |
this.currMBCRAMBank = a[b++]; | |
this.currMBCRAMBankPosition = a[b++]; | |
this.cGBC = a[b++]; | |
this.gbcRamBank = a[b++]; | |
this.gbcRamBankPosition = a[b++]; | |
this.ROMBank1offs = a[b++]; | |
this.currentROMBank = a[b++]; | |
this.cartridgeType = a[b++]; | |
this.name = a[b++]; | |
this.gameCode = a[b++]; | |
this.modeSTAT = a[b++]; | |
this.LYCMatchTriggerSTAT = a[b++]; | |
this.mode2TriggerSTAT = a[b++]; | |
this.mode1TriggerSTAT = a[b++]; | |
this.mode0TriggerSTAT = a[b++]; | |
this.LCDisOn = a[b++]; | |
this.gfxWindowCHRBankPosition = a[b++]; | |
this.gfxWindowDisplay = a[b++]; | |
this.gfxSpriteShow = a[b++]; | |
this.gfxSpriteNormalHeight = a[b++]; | |
this.gfxBackgroundCHRBankPosition = a[b++]; | |
this.gfxBackgroundBankOffset = a[b++]; | |
this.TIMAEnabled = a[b++]; | |
this.DIVTicks = a[b++]; | |
this.LCDTicks = a[b++]; | |
this.timerTicks = a[b++]; | |
this.TACClocker = a[b++]; | |
this.serialTimer = a[b++]; | |
this.serialShiftTimer = a[b++]; | |
this.serialShiftTimerAllocated = a[b++]; | |
this.IRQEnableDelay = a[b++]; | |
this.lastIteration = a[b++]; | |
this.cMBC1 = a[b++]; | |
this.cMBC2 = a[b++]; | |
this.cMBC3 = a[b++]; | |
this.cMBC5 = a[b++]; | |
this.cMBC7 = a[b++]; | |
this.cSRAM = a[b++]; | |
this.cMMMO1 = a[b++]; | |
this.cRUMBLE = a[b++]; | |
this.cCamera = a[b++]; | |
this.cTAMA5 = a[b++]; | |
this.cHuC3 = a[b++]; | |
this.cHuC1 = a[b++]; | |
this.drewBlank = a[b++]; | |
this.frameBuffer = this.toTypedArray(a[b++], "int32"); | |
this.bgEnabled = a[b++]; | |
this.BGPriorityEnabled = a[b++]; | |
this.channel1FrequencyTracker = a[b++]; | |
this.channel1FrequencyCounter = a[b++]; | |
this.channel1totalLength = a[b++]; | |
this.channel1envelopeVolume = a[b++]; | |
this.channel1envelopeType = a[b++]; | |
this.channel1envelopeSweeps = a[b++]; | |
this.channel1envelopeSweepsLast = a[b++]; | |
this.channel1consecutive = a[b++]; | |
this.channel1frequency = a[b++]; | |
this.channel1SweepFault = a[b++]; | |
this.channel1ShadowFrequency = a[b++]; | |
this.channel1timeSweep = a[b++]; | |
this.channel1lastTimeSweep = a[b++]; | |
this.channel1numSweep = a[b++]; | |
this.channel1frequencySweepDivider = a[b++]; | |
this.channel1decreaseSweep = a[b++]; | |
this.channel2FrequencyTracker = a[b++]; | |
this.channel2FrequencyCounter = a[b++]; | |
this.channel2totalLength = a[b++]; | |
this.channel2envelopeVolume = a[b++]; | |
this.channel2envelopeType = a[b++]; | |
this.channel2envelopeSweeps = a[b++]; | |
this.channel2envelopeSweepsLast = a[b++]; | |
this.channel2consecutive = a[b++]; | |
this.channel2frequency = a[b++]; | |
this.channel3canPlay = a[b++]; | |
this.channel3totalLength = a[b++]; | |
this.channel3patternType = a[b++]; | |
this.channel3frequency = a[b++]; | |
this.channel3consecutive = a[b++]; | |
this.channel3PCM = this.toTypedArray(a[b++], "int8"); | |
this.channel4FrequencyPeriod = a[b++]; | |
this.channel4lastSampleLookup = a[b++]; | |
this.channel4totalLength = a[b++]; | |
this.channel4envelopeVolume = a[b++]; | |
this.channel4currentVolume = a[b++]; | |
this.channel4envelopeType = a[b++]; | |
this.channel4envelopeSweeps = a[b++]; | |
this.channel4envelopeSweepsLast = a[b++]; | |
this.channel4consecutive = a[b++]; | |
this.channel4BitRange = a[b++]; | |
this.soundMasterEnabled = a[b++]; | |
this.VinLeftChannelMasterVolume = a[b++]; | |
this.VinRightChannelMasterVolume = a[b++]; | |
this.leftChannel1 = a[b++]; | |
this.leftChannel2 = a[b++]; | |
this.leftChannel3 = a[b++]; | |
this.leftChannel4 = a[b++]; | |
this.rightChannel1 = a[b++]; | |
this.rightChannel2 = a[b++]; | |
this.rightChannel3 = a[b++]; | |
this.rightChannel4 = a[b++]; | |
this.channel1currentSampleLeft = a[b++]; | |
this.channel1currentSampleRight = a[b++]; | |
this.channel2currentSampleLeft = a[b++]; | |
this.channel2currentSampleRight = a[b++]; | |
this.channel3currentSampleLeft = a[b++]; | |
this.channel3currentSampleRight = a[b++]; | |
this.channel4currentSampleLeft = a[b++]; | |
this.channel4currentSampleRight = a[b++]; | |
this.channel1currentSampleLeftSecondary = a[b++]; | |
this.channel1currentSampleRightSecondary = a[b++]; | |
this.channel2currentSampleLeftSecondary = a[b++]; | |
this.channel2currentSampleRightSecondary = a[b++]; | |
this.channel3currentSampleLeftSecondary = a[b++]; | |
this.channel3currentSampleRightSecondary = a[b++]; | |
this.channel4currentSampleLeftSecondary = a[b++]; | |
this.channel4currentSampleRightSecondary = a[b++]; | |
this.channel1currentSampleLeftTrimary = a[b++]; | |
this.channel1currentSampleRightTrimary = a[b++]; | |
this.channel2currentSampleLeftTrimary = a[b++]; | |
this.channel2currentSampleRightTrimary = a[b++]; | |
this.mixerOutputCache = a[b++]; | |
this.channel1DutyTracker = a[b++]; | |
this.channel1CachedDuty = a[b++]; | |
this.channel2DutyTracker = a[b++]; | |
this.channel2CachedDuty = a[b++]; | |
this.channel1Enabled = a[b++]; | |
this.channel2Enabled = a[b++]; | |
this.channel3Enabled = a[b++]; | |
this.channel4Enabled = a[b++]; | |
this.sequencerClocks = a[b++]; | |
this.sequencePosition = a[b++]; | |
this.channel3Counter = a[b++]; | |
this.channel4Counter = a[b++]; | |
this.cachedChannel3Sample = a[b++]; | |
this.cachedChannel4Sample = a[b++]; | |
this.channel3FrequencyPeriod = a[b++]; | |
this.channel3lastSampleLookup = a[b++]; | |
this.actualScanLine = a[b++]; | |
this.lastUnrenderedLine = a[b++]; | |
this.queuedScanLines = a[b++]; | |
this.RTCisLatched = a[b++]; | |
this.latchedSeconds = a[b++]; | |
this.latchedMinutes = a[b++]; | |
this.latchedHours = a[b++]; | |
this.latchedLDays = a[b++]; | |
this.latchedHDays = a[b++]; | |
this.RTCSeconds = a[b++]; | |
this.RTCMinutes = a[b++]; | |
this.RTCHours = a[b++]; | |
this.RTCDays = a[b++]; | |
this.RTCDayOverFlow = a[b++]; | |
this.RTCHALT = a[b++]; | |
this.usedBootROM = a[b++]; | |
this.skipPCIncrement = a[b++]; | |
this.STATTracker = a[b++]; | |
this.gbcRamBankPositionECHO = a[b++]; | |
this.numRAMBanks = a[b++]; | |
this.windowY = a[b++]; | |
this.windowX = a[b++]; | |
this.gbcOBJRawPalette = this.toTypedArray(a[b++], "uint8"); | |
this.gbcBGRawPalette = this.toTypedArray(a[b++], "uint8"); | |
this.gbOBJPalette = this.toTypedArray(a[b++], "int32"); | |
this.gbBGPalette = this.toTypedArray(a[b++], "int32"); | |
this.gbcOBJPalette = this.toTypedArray(a[b++], "int32"); | |
this.gbcBGPalette = this.toTypedArray(a[b++], "int32"); | |
this.gbBGColorizedPalette = this.toTypedArray(a[b++], "int32"); | |
this.gbOBJColorizedPalette = this.toTypedArray(a[b++], "int32"); | |
this.cachedBGPaletteConversion = this.toTypedArray(a[b++], "int32"); | |
this.cachedOBJPaletteConversion = this.toTypedArray(a[b++], "int32"); | |
this.BGCHRBank1 = this.toTypedArray(a[b++], "uint8"); | |
this.BGCHRBank2 = this.toTypedArray(a[b++], "uint8"); | |
this.haltPostClocks = a[b++]; | |
this.interruptsRequested = a[b++]; | |
this.interruptsEnabled = a[b++]; | |
this.checkIRQMatching(); | |
this.remainingClocks = a[b++]; | |
this.colorizedGBPalettes = a[b++]; | |
this.backgroundY = a[b++]; | |
this.backgroundX = a[b++]; | |
this.CPUStopped = a[b]; | |
this.fromSaveState = true; | |
this.TICKTable = this.toTypedArray(this.TICKTable, "uint8"); | |
this.SecondaryTICKTable = this.toTypedArray(this.SecondaryTICKTable, "uint8"); | |
this.initializeReferencesFromSaveState(); | |
this.memoryReadJumpCompile(); | |
this.memoryWriteJumpCompile(); | |
this.initLCD(); | |
this.initSound(); | |
this.noiseSampleTable = this.channel4BitRange == 32767 ? this.LSFR15Table : this.LSFR7Table; | |
this.channel4VolumeShifter = this.channel4BitRange == 32767 ? 15 : 7 | |
}; | |
GameBoyCore.prototype.returnFromRTCState = function () { | |
if (typeof this.openRTC == "function" && this.cTIMER) { | |
var a = this.openRTC(this.name), | |
b = 0; | |
this.lastIteration = a[b++]; | |
this.RTCisLatched = a[b++]; | |
this.latchedSeconds = a[b++]; | |
this.latchedMinutes = a[b++]; | |
this.latchedHours = a[b++]; | |
this.latchedLDays = a[b++]; | |
this.latchedHDays = a[b++]; | |
this.RTCSeconds = a[b++]; | |
this.RTCMinutes = a[b++]; | |
this.RTCHours = a[b++]; | |
this.RTCDays = a[b++]; | |
this.RTCDayOverFlow = a[b++]; | |
this.RTCHALT = a[b] | |
} | |
}; | |
GameBoyCore.prototype.start = function () { | |
this.initMemory(); | |
this.ROMLoad(); | |
this.initLCD(); | |
this.initSound(); | |
this.run() | |
}; | |
GameBoyCore.prototype.initMemory = function () { | |
this.memory = this.getTypedArray(65536, 0, "uint8"); | |
this.frameBuffer = this.getTypedArray(23040, 16316664, "int32"); | |
this.BGCHRBank1 = this.getTypedArray(2048, 0, "uint8"); | |
this.TICKTable = this.toTypedArray(this.TICKTable, "uint8"); | |
this.SecondaryTICKTable = this.toTypedArray(this.SecondaryTICKTable, "uint8"); | |
this.channel3PCM = this.getTypedArray(32, 0, "int8") | |
}; | |
GameBoyCore.prototype.generateCacheArray = function (a) { | |
for (var b = [], c = 0; c < a;) b[c++] = this.getTypedArray(64, 0, "uint8"); | |
return b | |
}; | |
GameBoyCore.prototype.initSkipBootstrap = function () { | |
for (var a = 255; a >= 0;) { | |
if (a >= 48 && a < 64) this.memoryWrite(65280 | a, this.ffxxDump[a]); | |
else switch (a) { | |
case 0: | |
case 1: | |
case 2: | |
case 5: | |
case 7: | |
case 15: | |
case 255: | |
this.memoryWrite(65280 | a, this.ffxxDump[a]); | |
break; | |
default: | |
this.memory[65280 | a] = this.ffxxDump[a] | |
}--a | |
} | |
if (this.cGBC) { | |
this.memory[65388] = 254; | |
this.memory[65396] = 254 | |
} else { | |
this.memory[65352] = 255; | |
this.memory[65353] = 255; | |
this.memory[65388] = 255; | |
this.memory[65396] = 255 | |
} | |
cout("Starting without the GBC boot ROM.", 0); | |
this.registerA = this.cGBC ? 17 : 1; | |
this.registerB = 0; | |
this.registerC = 19; | |
this.registerD = 0; | |
this.registerE = 216; | |
this.FZero = true; | |
this.FSubtract = false; | |
this.FCarry = this.FHalfCarry = true; | |
this.registersHL = 333; | |
this.LCDCONTROL = this.LINECONTROL; | |
this.IME = false; | |
this.IRQLineMatched = 0; | |
this.interruptsRequested = 225; | |
this.interruptsEnabled = 0; | |
this.hdmaRunning = false; | |
this.CPUTicks = 12; | |
this.STATTracker = 0; | |
this.modeSTAT = 1; | |
this.spriteCount = 252; | |
this.mode0TriggerSTAT = this.mode1TriggerSTAT = this.mode2TriggerSTAT = this.LYCMatchTriggerSTAT = false; | |
this.LCDisOn = true; | |
this.channel1FrequencyTracker = 8192; | |
this.channel1DutyTracker = 0; | |
this.channel1CachedDuty = this.dutyLookup[2]; | |
this.channel1envelopeVolume = this.channel1totalLength = 0; | |
this.channel1envelopeType = false; | |
this.channel1envelopeSweepsLast = this.channel1envelopeSweeps = 0; | |
this.channel1consecutive = true; | |
this.channel1frequency = 1985; | |
this.channel1SweepFault = true; | |
this.channel1ShadowFrequency = 1985; | |
this.channel1timeSweep = 1; | |
this.channel1frequencySweepDivider = this.channel1numSweep = this.channel1lastTimeSweep = 0; | |
this.channel1decreaseSweep = false; | |
this.channel2FrequencyTracker = 8192; | |
this.channel2DutyTracker = 0; | |
this.channel2CachedDuty = this.dutyLookup[2]; | |
this.channel2envelopeVolume = this.channel2totalLength = 0; | |
this.channel2envelopeType = false; | |
this.channel2envelopeSweepsLast = this.channel2envelopeSweeps = 0; | |
this.channel2consecutive = true; | |
this.channel2frequency = 0; | |
this.channel3canPlay = false; | |
this.channel3totalLength = 0; | |
this.channel3patternType = 4; | |
this.channel3frequency = 0; | |
this.channel3consecutive = true; | |
this.channel3Counter = 1048; | |
this.channel4FrequencyPeriod = 8; | |
this.channel4currentVolume = this.channel4envelopeVolume = this.channel4totalLength = 0; | |
this.channel4envelopeType = false; | |
this.channel4envelopeSweepsLast = this.channel4envelopeSweeps = 0; | |
this.channel4consecutive = true; | |
this.channel4BitRange = 32767; | |
this.channel4VolumeShifter = 15; | |
this.channel2FrequencyCounter = this.channel1FrequencyCounter = 512; | |
this.channel3FrequencyPeriod = this.channel3Counter = 2048; | |
this.channel4lastSampleLookup = this.channel3lastSampleLookup = 0; | |
this.VinRightChannelMasterVolume = this.VinLeftChannelMasterVolume = 1; | |
this.rightChannel2 = this.rightChannel1 = this.leftChannel4 = this.leftChannel3 = this.leftChannel2 = this.leftChannel1 = this.soundMasterEnabled = true; | |
this.rightChannel4 = this.rightChannel3 = false; | |
this.DIVTicks = 27044; | |
this.LCDTicks = 160; | |
this.timerTicks = 0; | |
this.TIMAEnabled = false; | |
this.TACClocker = 1024; | |
this.IRQEnableDelay = this.serialShiftTimerAllocated = this.serialShiftTimer = this.serialTimer = 0; | |
this.actualScanLine = 144; | |
this.lastUnrenderedLine = 0; | |
this.gfxSpriteShow = this.gfxWindowDisplay = false; | |
this.BGPriorityEnabled = this.bgEnabled = this.gfxSpriteNormalHeight = true; | |
this.drewBlank = this.windowX = this.windowY = this.gfxBackgroundBankOffset = this.gfxBackgroundCHRBankPosition = this.gfxWindowCHRBankPosition = 0; | |
this.midScanlineOffset = -1; | |
this.currentX = 0 | |
}; | |
GameBoyCore.prototype.initBootstrap = function () { | |
cout("Starting the selected boot ROM.", 0); | |
this.stackPointer = this.programCounter = 0; | |
this.IME = false; | |
this.registerE = this.registerD = this.registerC = this.registerB = this.registerA = this.DIVTicks = this.LCDTicks = 0; | |
this.FZero = this.FSubtract = this.FHalfCarry = this.FCarry = false; | |
this.registersHL = 0; | |
this.rightChannel4 = this.rightChannel3 = this.rightChannel2 = this.rightChannel1 = this.leftChannel4 = this.leftChannel3 = this.leftChannel2 = this.leftChannel1 = false; | |
this.channel2frequency = this.channel1frequency = 0; | |
this.channel4consecutive = this.channel2consecutive = this.channel1consecutive = false; | |
this.VinRightChannelMasterVolume = this.VinLeftChannelMasterVolume = 8; | |
this.memory[65280] = 15 | |
}; | |
GameBoyCore.prototype.ROMLoad = function () { | |
this.ROM = []; | |
this.usedBootROM = settings[1]; | |
var a = this.ROMImage.length; | |
if (a < 16384) throw Error("ROM image size too small."); | |
this.ROM = this.getTypedArray(a, 0, "uint8"); | |
var b = 0; | |
if (this.usedBootROM) if (settings[11]) for (; b < 256; ++b) { | |
this.memory[b] = this.GBBOOTROM[b]; | |
this.ROM[b] = this.ROMImage.charCodeAt(b) & 255 | |
} else { | |
for (; b < 256; ++b) { | |
this.memory[b] = this.GBCBOOTROM[b]; | |
this.ROM[b] = this.ROMImage.charCodeAt(b) & 255 | |
} | |
for (; b < 512; ++b) this.memory[b] = this.ROM[b] = this.ROMImage.charCodeAt(b) & 255; | |
for (; b < 2304; ++b) { | |
this.memory[b] = this.GBCBOOTROM[b - 256]; | |
this.ROM[b] = this.ROMImage.charCodeAt(b) & 255 | |
} | |
this.usedGBCBootROM = true | |
} | |
for (; b < 16384; ++b) this.memory[b] = this.ROM[b] = this.ROMImage.charCodeAt(b) & 255; | |
for (; b < a; ++b) this.ROM[b] = this.ROMImage.charCodeAt(b) & 255; | |
this.ROMBankEdge = Math.floor(this.ROM.length / 16384); | |
this.interpretCartridge(); | |
this.checkIRQMatching() | |
}; | |
GameBoyCore.prototype.getROMImage = function () { | |
if (this.ROMImage.length > 0) return this.ROMImage.length; | |
for (var a = this.ROM.length, b = 0; b < a; b++) this.ROMImage = this.ROMImage + String.fromCharCode(this.ROM[b]); | |
return this.ROMImage | |
}; | |
GameBoyCore.prototype.interpretCartridge = function () { | |
for (var a = 308; a < 319; a++) if (this.ROMImage.charCodeAt(a) > 0) this.name = this.name + this.ROMImage[a]; | |
for (a = 319; a < 323; a++) if (this.ROMImage.charCodeAt(a) > 0) this.gameCode = this.gameCode + this.ROMImage[a]; | |
cout("Game Title: " + this.name + "[" + this.gameCode + "][" + this.ROMImage[323] + "]", 0); | |
cout("Game Code: " + this.gameCode, 0); | |
this.cartridgeType = this.ROM[327]; | |
cout("Cartridge type #" + this.cartridgeType, 0); | |
a = ""; | |
switch (this.cartridgeType) { | |
case 0: | |
if (!settings[9]) { | |
a = "ROM"; | |
break | |
} | |
case 1: | |
this.cMBC1 = true; | |
a = "MBC1"; | |
break; | |
case 2: | |
this.cSRAM = this.cMBC1 = true; | |
a = "MBC1 + SRAM"; | |
break; | |
case 3: | |
this.cBATT = this.cSRAM = this.cMBC1 = true; | |
a = "MBC1 + SRAM + BATT"; | |
break; | |
case 5: | |
this.cMBC2 = true; | |
a = "MBC2"; | |
break; | |
case 6: | |
this.cBATT = this.cMBC2 = true; | |
a = "MBC2 + BATT"; | |
break; | |
case 8: | |
this.cSRAM = true; | |
a = "ROM + SRAM"; | |
break; | |
case 9: | |
this.cBATT = this.cSRAM = true; | |
a = "ROM + SRAM + BATT"; | |
break; | |
case 11: | |
this.cMMMO1 = true; | |
a = "MMMO1"; | |
break; | |
case 12: | |
this.cSRAM = this.cMMMO1 = true; | |
a = "MMMO1 + SRAM"; | |
break; | |
case 13: | |
this.cBATT = this.cSRAM = this.cMMMO1 = true; | |
a = "MMMO1 + SRAM + BATT"; | |
break; | |
case 15: | |
this.cBATT = this.cTIMER = this.cMBC3 = true; | |
a = "MBC3 + TIMER + BATT"; | |
break; | |
case 16: | |
this.cSRAM = this.cBATT = this.cTIMER = this.cMBC3 = true; | |
a = "MBC3 + TIMER + BATT + SRAM"; | |
break; | |
case 17: | |
this.cMBC3 = true; | |
a = "MBC3"; | |
break; | |
case 18: | |
this.cSRAM = this.cMBC3 = true; | |
a = "MBC3 + SRAM"; | |
break; | |
case 19: | |
this.cBATT = this.cSRAM = this.cMBC3 = true; | |
a = "MBC3 + SRAM + BATT"; | |
break; | |
case 25: | |
this.cMBC5 = true; | |
a = "MBC5"; | |
break; | |
case 26: | |
this.cSRAM = this.cMBC5 = true; | |
a = "MBC5 + SRAM"; | |
break; | |
case 27: | |
this.cBATT = this.cSRAM = this.cMBC5 = true; | |
a = "MBC5 + SRAM + BATT"; | |
break; | |
case 28: | |
this.cRUMBLE = true; | |
a = "RUMBLE"; | |
break; | |
case 29: | |
this.cSRAM = this.cRUMBLE = true; | |
a = "RUMBLE + SRAM"; | |
break; | |
case 30: | |
this.cBATT = this.cSRAM = this.cRUMBLE = true; | |
a = "RUMBLE + SRAM + BATT"; | |
break; | |
case 31: | |
this.cCamera = true; | |
a = "GameBoy Camera"; | |
break; | |
case 34: | |
this.cBATT = this.cSRAM = this.cMBC7 = true; | |
a = "MBC7 + SRAM + BATT"; | |
break; | |
case 253: | |
this.cTAMA5 = true; | |
a = "TAMA5"; | |
break; | |
case 254: | |
this.cHuC3 = true; | |
a = "HuC3"; | |
break; | |
case 255: | |
this.cHuC1 = true; | |
a = "HuC1"; | |
break; | |
default: | |
a = "Unknown"; | |
cout("Cartridge type is unknown.", 2); | |
pause() | |
} | |
cout("Cartridge Type: " + a + ".", 0); | |
this.numROMBanks = this.ROMBanks[this.ROM[328]]; | |
cout(this.numROMBanks + " ROM banks.", 0); | |
switch (this.RAMBanks[this.ROM[329]]) { | |
case 0: | |
cout("No RAM banking requested for allocation or MBC is of type 2.", 0); | |
break; | |
case 2: | |
cout("1 RAM bank requested for allocation.", 0); | |
break; | |
case 3: | |
cout("4 RAM banks requested for allocation.", 0); | |
break; | |
case 4: | |
cout("16 RAM banks requested for allocation.", 0); | |
break; | |
default: | |
cout("RAM bank amount requested is unknown, will use maximum allowed by specified MBC type.", 0) | |
} | |
if (this.usedBootROM) { | |
this.cGBC = this.usedGBCBootROM; | |
this.setupRAM(); | |
this.initBootstrap() | |
} else { | |
switch (this.ROM[323]) { | |
case 0: | |
this.cGBC = false; | |
cout("Only GB mode detected.", 0); | |
break; | |
case 50: | |
if (!settings[2] && this.name + this.gameCode + this.ROM[323] == "Game and Watch 50") { | |
this.cGBC = true; | |
cout("Created a boot exception for Game and Watch Gallery 2 (GBC ID byte is wrong on the cartridge).", 1) | |
} else this.cGBC = false; | |
break; | |
case 128: | |
this.cGBC = !settings[2]; | |
cout("GB and GBC mode detected.", 0); | |
break; | |
case 192: | |
this.cGBC = true; | |
cout("Only GBC mode detected.", 0); | |
break; | |
default: | |
this.cGBC = false; | |
cout("Unknown GameBoy game type code #" + this.ROM[323] + ", defaulting to GB mode (Old games don't have a type code).", 1) | |
} | |
this.inBootstrap = false; | |
this.setupRAM(); | |
this.initSkipBootstrap() | |
} | |
this.initializeModeSpecificArrays(); | |
var a = this.ROM[331], | |
b = this.ROM[324] & 65280 | this.ROM[325] & 255; | |
a != 51 ? cout("Old style license code: " + a, 0) : cout("New style license code: " + b, 0); | |
this.ROMImage = "" | |
}; | |
GameBoyCore.prototype.disableBootROM = function () { | |
for (var a = 0; a < 256; ++a) this.memory[a] = this.ROM[a]; | |
if (this.usedGBCBootROM) { | |
for (a = 512; a < 2304; ++a) this.memory[a] = this.ROM[a]; | |
this.cGBC ? this.recompileBootIOWriteHandling() : this.GBCtoGBModeAdjust() | |
} else this.recompileBootIOWriteHandling() | |
}; | |
GameBoyCore.prototype.initializeTiming = function () { | |
this.baseCPUCyclesPerIteration = 4194.304 * settings[6]; | |
this.CPUCyclesTotalRoundoff = this.baseCPUCyclesPerIteration % 4; | |
this.CPUCyclesTotalBase = this.CPUCyclesTotal = this.baseCPUCyclesPerIteration - this.CPUCyclesTotalRoundoff | 0; | |
this.CPUCyclesTotalCurrent = 0 | |
}; | |
GameBoyCore.prototype.setupRAM = function () { | |
if (this.cMBC2) this.numRAMBanks = 0.0625; | |
else if (this.cMBC1 || this.cRUMBLE || this.cMBC3 || this.cHuC3) this.numRAMBanks = 4; | |
else if (this.cMBC5) this.numRAMBanks = 16; | |
else if (this.cSRAM) this.numRAMBanks = 1; | |
if (this.numRAMBanks > 0) { | |
if (!this.MBCRAMUtilized()) this.MBCRAMBanksEnabled = true; | |
var a = typeof this.openMBC == "function" ? this.openMBC(this.name) : []; | |
this.MBCRam = a.length > 0 ? this.toTypedArray(a, "uint8") : this.getTypedArray(this.numRAMBanks * 8192, 0, "uint8") | |
} | |
cout("Actual bytes of MBC RAM allocated: " + this.numRAMBanks * 8192, 0); | |
this.returnFromRTCState(); | |
if (this.cGBC) { | |
this.VRAM = this.getTypedArray(8192, 0, "uint8"); | |
this.GBCMemory = this.getTypedArray(28672, 0, "uint8") | |
} | |
this.memoryReadJumpCompile(); | |
this.memoryWriteJumpCompile() | |
}; | |
GameBoyCore.prototype.MBCRAMUtilized = function () { | |
return this.cMBC1 || this.cMBC2 || this.cMBC3 || this.cMBC5 || this.cMBC7 || this.cRUMBLE | |
}; | |
GameBoyCore.prototype.recomputeDimension = function () { | |
initNewCanvas(); | |
this.onscreenWidth = this.canvas.width; | |
this.onscreenHeight = this.canvas.height; | |
if (window && window.mozRequestAnimationFrame) { | |
this.canvas.width = this.onscreenWidth = !settings[12] ? 160 : this.canvas.width; | |
this.canvas.height = this.onscreenHeight = !settings[12] ? 144 : this.canvas.height | |
} else { | |
this.onscreenWidth = this.canvas.width; | |
this.onscreenHeight = this.canvas.height | |
} | |
this.offscreenWidth = !settings[12] ? 160 : this.canvas.width; | |
this.offscreenHeight = !settings[12] ? 144 : this.canvas.height; | |
this.offscreenRGBCount = this.offscreenWidth * this.offscreenHeight * 4 | |
}; | |
GameBoyCore.prototype.initLCD = function () { | |
this.recomputeDimension(); | |
this.offscreenRGBCount != 92160 ? this.compileResizeFrameBufferFunction() : this.resizer = null; | |
try { | |
this.canvasOffscreen = document.createElement("canvas"); | |
this.canvasOffscreen.width = this.offscreenWidth; | |
this.canvasOffscreen.height = this.offscreenHeight; | |
this.drawContextOffscreen = this.canvasOffscreen.getContext("2d"); | |
this.drawContextOnscreen = this.canvas.getContext("2d"); | |
try { | |
this.canvasBuffer = this.drawContextOffscreen.createImageData(this.offscreenWidth, this.offscreenHeight) | |
} catch (a) { | |
cout('Falling back to the getImageData initialization (Error "' + a.message + '").', 1); | |
this.canvasBuffer = this.drawContextOffscreen.getImageData(0, 0, this.offscreenWidth, this.offscreenHeight) | |
} | |
for (var b = this.offscreenRGBCount; b > 0;) { | |
this.canvasBuffer.data[b = b - 4] = 248; | |
this.canvasBuffer.data[b + 1] = 248; | |
this.canvasBuffer.data[b + 2] = 248; | |
this.canvasBuffer.data[b + 3] = 255 | |
} | |
this.graphicsBlit(); | |
this.canvas.style.visibility = "visible"; | |
if (this.swizzledFrame == null) this.swizzledFrame = this.getTypedArray(69120, 255, "uint8"); | |
this.drewFrame = true; | |
this.requestDraw() | |
} catch (c) { | |
throw Error("HTML5 Canvas support required: " + c.message + "file: " + c.fileName + ", line: " + c.lineNumber); | |
} | |
}; | |
GameBoyCore.prototype.graphicsBlit = function () { | |
if (this.offscreenWidth == this.onscreenWidth && this.offscreenHeight == this.onscreenHeight) this.drawContextOnscreen.putImageData(this.canvasBuffer, 0, 0); | |
else { | |
this.drawContextOffscreen.putImageData(this.canvasBuffer, 0, 0); | |
this.drawContextOnscreen.drawImage(this.canvasOffscreen, 0, 0, this.onscreenWidth, this.onscreenHeight) | |
} | |
}; | |
GameBoyCore.prototype.JoyPadEvent = function (a, b) { | |
if (b) { | |
this.JoyPad = this.JoyPad & (255 ^ 1 << a); | |
if (!this.cGBC && (!this.usedBootROM || !this.usedGBCBootROM)) { | |
this.interruptsRequested = this.interruptsRequested | 16; | |
this.remainingClocks = 0; | |
this.checkIRQMatching() | |
} | |
} else this.JoyPad = this.JoyPad | 1 << a; | |
this.memory[65280] = (this.memory[65280] & 48) + (((this.memory[65280] & 32) == 0 ? this.JoyPad >> 4 : 15) & ((this.memory[65280] & 16) == 0 ? this.JoyPad & 15 : 15)); | |
this.CPUStopped = false | |
}; | |
GameBoyCore.prototype.GyroEvent = function (a, b) { | |
a = a * -100 + 2047; | |
this.highX = a >> 8; | |
this.lowX = a & 255; | |
b = b * -100 + 2047; | |
this.highY = b >> 8; | |
this.lowY = b & 255 | |
}; | |
GameBoyCore.prototype.initSound = function () { | |
this.sampleSize = 4194.304 * settings[6]; | |
this.machineOut = this.audioResamplerFirstPassFactor = Math.floor(95.10893424036281); | |
if (settings[0]) try { | |
this.audioHandle = new XAudioServer(2, 4194304 / this.audioResamplerFirstPassFactor, 0, Math.max(this.sampleSize * settings[8] / this.audioResamplerFirstPassFactor, 8192) << 1, null, settings[13]); | |
this.initAudioBuffer() | |
} catch (a) { | |
cout("Audio system cannot run: " + a.message, 2); | |
settings[0] = false | |
} else if (this.audioHandle) try { | |
this.audioHandle.changeVolume(0) | |
} catch (b) {} | |
}; | |
GameBoyCore.prototype.changeVolume = function () { | |
if (settings[0] && this.audioHandle) try { | |
this.audioHandle.changeVolume(settings[13]) | |
} catch (a) {} | |
}; | |
GameBoyCore.prototype.initAudioBuffer = function () { | |
this.audioIndex = 0; | |
this.bufferContainAmount = Math.max(this.sampleSize * settings[7] / this.audioResamplerFirstPassFactor, 4096) << 1; | |
this.numSamplesTotal = this.sampleSize - this.sampleSize % this.audioResamplerFirstPassFactor | 0; | |
this.currentBuffer = this.getTypedArray(this.numSamplesTotal, 0, "int32"); | |
this.secondaryBuffer = this.getTypedArray((this.numSamplesTotal << 1) / this.audioResamplerFirstPassFactor, 0, "float32") | |
}; | |
GameBoyCore.prototype.intializeWhiteNoise = function () { | |
var a = 1; | |
this.LSFR15Table = this.getTypedArray(524288, 0, "int8"); | |
for (var b = 32767, a = 16383, c = 0; c < 32768; ++c) { | |
a = 1 - (b & 1); | |
this.LSFR15Table[32768 | c] = a; | |
this.LSFR15Table[65536 | c] = a * 2; | |
this.LSFR15Table[98304 | c] = a * 3; | |
this.LSFR15Table[131072 | c] = a * 4; | |
this.LSFR15Table[163840 | c] = a * 5; | |
this.LSFR15Table[196608 | c] = a * 6; | |
this.LSFR15Table[229376 | c] = a * 7; | |
this.LSFR15Table[262144 | c] = a * 8; | |
this.LSFR15Table[294912 | c] = a * 9; | |
this.LSFR15Table[327680 | c] = a * 10; | |
this.LSFR15Table[360448 | c] = a * 11; | |
this.LSFR15Table[393216 | c] = a * 12; | |
this.LSFR15Table[425984 | c] = a * 13; | |
this.LSFR15Table[458752 | c] = a * 14; | |
this.LSFR15Table[491520 | c] = a * 15; | |
a = b >> 1; | |
b = a | ((a ^ b) & 1) << 14 | |
} | |
this.LSFR7Table = this.getTypedArray(2048, 0, "int8"); | |
b = 127; | |
for (c = 0; c < 128; ++c) { | |
a = 1 - (b & 1); | |
this.LSFR7Table[128 | c] = a; | |
this.LSFR7Table[256 | c] = a * 2; | |
this.LSFR7Table[384 | c] = a * 3; | |
this.LSFR7Table[512 | c] = a * 4; | |
this.LSFR7Table[640 | c] = a * 5; | |
this.LSFR7Table[768 | c] = a * 6; | |
this.LSFR7Table[896 | c] = a * 7; | |
this.LSFR7Table[1024 | c] = a * 8; | |
this.LSFR7Table[1152 | c] = a * 9; | |
this.LSFR7Table[1280 | c] = a * 10; | |
this.LSFR7Table[1408 | c] = a * 11; | |
this.LSFR7Table[1536 | c] = a * 12; | |
this.LSFR7Table[1664 | c] = a * 13; | |
this.LSFR7Table[1792 | c] = a * 14; | |
this.LSFR7Table[1920 | c] = a * 15; | |
a = b >> 1; | |
b = a | ((a ^ b) & 1) << 6 | |
} | |
if (!this.noiseSampleTable && this.memory.length == 65536) this.noiseSampleTable = (this.memory[65314] & 8) == 8 ? this.LSFR7Table : this.LSFR15Table | |
}; | |
GameBoyCore.prototype.audioUnderrunAdjustment = function () { | |
if (settings[0]) { | |
var a = this.bufferContainAmount - this.audioHandle.remainingBuffer(); | |
if (a > 0) { | |
this.CPUCyclesTotalCurrent = this.CPUCyclesTotalCurrent + (a >> 1) * this.machineOut; | |
this.recalculateIterationClockLimit() | |
} | |
} | |
}; | |
GameBoyCore.prototype.initializeAudioStartState = function () { | |
this.channel1FrequencyTracker = 8192; | |
this.channel1DutyTracker = 0; | |
this.channel1CachedDuty = this.dutyLookup[2]; | |
this.channel1envelopeVolume = this.channel1totalLength = 0; | |
this.channel1envelopeType = false; | |
this.channel1envelopeSweepsLast = this.channel1envelopeSweeps = 0; | |
this.channel1consecutive = true; | |
this.channel1frequency = 0; | |
this.channel1SweepFault = false; | |
this.channel1ShadowFrequency = 0; | |
this.channel1timeSweep = 1; | |
this.channel1frequencySweepDivider = this.channel1numSweep = this.channel1lastTimeSweep = 0; | |
this.channel1decreaseSweep = false; | |
this.channel2FrequencyTracker = 8192; | |
this.channel2DutyTracker = 0; | |
this.channel2CachedDuty = this.dutyLookup[2]; | |
this.channel2envelopeVolume = this.channel2totalLength = 0; | |
this.channel2envelopeType = false; | |
this.channel2envelopeSweepsLast = this.channel2envelopeSweeps = 0; | |
this.channel2consecutive = true; | |
this.channel2frequency = 0; | |
this.channel3canPlay = false; | |
this.channel3totalLength = 0; | |
this.channel3patternType = 4; | |
this.channel3frequency = 0; | |
this.channel3consecutive = true; | |
this.channel3Counter = 2048; | |
this.channel4FrequencyPeriod = 8; | |
this.channel4currentVolume = this.channel4envelopeVolume = this.channel4totalLength = 0; | |
this.channel4envelopeType = false; | |
this.channel4envelopeSweepsLast = this.channel4envelopeSweeps = 0; | |
this.channel4consecutive = true; | |
this.channel4BitRange = 32767; | |
this.noiseSampleTable = this.LSFR15Table; | |
this.channel4VolumeShifter = 15; | |
this.channel2FrequencyCounter = this.channel1FrequencyCounter = 8192; | |
this.channel3FrequencyPeriod = this.channel3Counter = 2048; | |
this.channel4lastSampleLookup = this.channel3lastSampleLookup = 0; | |
this.VinRightChannelMasterVolume = this.VinLeftChannelMasterVolume = 8; | |
this.mixerOutputCache = 0; | |
this.sequencerClocks = 8192; | |
this.sequencePosition = 0; | |
this.channel4Counter = this.channel4FrequencyPeriod = 8; | |
this.cachedChannel4Sample = this.cachedChannel3Sample = 0; | |
this.channel4canPlay = this.channel2canPlay = this.channel1canPlay = this.channel4Enabled = this.channel3Enabled = this.channel2Enabled = this.channel1Enabled = false; | |
this.channel1OutputLevelCache(); | |
this.channel2OutputLevelCache(); | |
this.channel3OutputLevelCache(); | |
this.channel4OutputLevelCache() | |
}; | |
GameBoyCore.prototype.outputAudio = function () { | |
for (var a = 0, b = 0, c = 0, e = 0, f = 0, g = this.audioResamplerFirstPassFactor * 240, d = 0; d < this.numSamplesTotal;) { | |
for (a = c = e = 0; a < this.audioResamplerFirstPassFactor; ++a) { | |
b = this.currentBuffer[d++]; | |
c = c + (b >> 9); | |
e = e + (b & 511) | |
} | |
this.secondaryBuffer[f++] = c / g - 1; | |
this.secondaryBuffer[f++] = e / g - 1 | |
} | |
this.audioHandle.writeAudioNoCallback(this.secondaryBuffer) | |
}; | |
GameBoyCore.prototype.generateAudio = function (a) { | |
if (this.soundMasterEnabled && !this.CPUStopped) for (var b = 0; a > 0;) { | |
b = a < this.sequencerClocks ? a : this.sequencerClocks; | |
this.sequencerClocks = this.sequencerClocks - b; | |
for (a = a - b; --b > -1;) { | |
this.computeAudioChannels(); | |
this.currentBuffer[this.audioIndex++] = this.mixerOutputCache; | |
if (this.audioIndex == this.numSamplesTotal) { | |
this.audioIndex = 0; | |
this.outputAudio() | |
} | |
} | |
if (this.sequencerClocks == 0) { | |
this.audioComputeSequencer(); | |
this.sequencerClocks = 8192 | |
} | |
} else for (; --a > -1;) { | |
this.currentBuffer[this.audioIndex++] = 0; | |
if (this.audioIndex == this.numSamplesTotal) { | |
this.audioIndex = 0; | |
this.outputAudio() | |
} | |
} | |
}; | |
GameBoyCore.prototype.generateAudioFake = function (a) { | |
if (this.soundMasterEnabled && !this.CPUStopped) for (; --a > -1;) { | |
this.computeAudioChannels(); | |
if (--this.sequencerClocks == 0) { | |
this.audioComputeSequencer(); | |
this.sequencerClocks = 8192 | |
} | |
} | |
}; | |
GameBoyCore.prototype.audioJIT = function () { | |
settings[0] ? this.generateAudio(this.audioTicks) : this.generateAudioFake(this.audioTicks); | |
this.audioTicks = 0 | |
}; | |
GameBoyCore.prototype.audioComputeSequencer = function () { | |
switch (this.sequencePosition++) { | |
case 0: | |
this.clockAudioLength(); | |
break; | |
case 2: | |
this.clockAudioLength(); | |
this.clockAudioSweep(); | |
break; | |
case 4: | |
this.clockAudioLength(); | |
break; | |
case 6: | |
this.clockAudioLength(); | |
this.clockAudioSweep(); | |
break; | |
case 7: | |
this.clockAudioEnvelope(); | |
this.sequencePosition = 0 | |
} | |
}; | |
GameBoyCore.prototype.clockAudioLength = function () { | |
if (this.channel1totalLength > 1)--this.channel1totalLength; | |
else if (this.channel1totalLength == 1) { | |
this.channel1totalLength = 0; | |
this.channel1EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 254 | |
} | |
if (this.channel2totalLength > 1)--this.channel2totalLength; | |
else if (this.channel2totalLength == 1) { | |
this.channel2totalLength = 0; | |
this.channel2EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 253 | |
} | |
if (this.channel3totalLength > 1)--this.channel3totalLength; | |
else if (this.channel3totalLength == 1) { | |
this.channel3totalLength = 0; | |
this.channel3EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 251 | |
} | |
if (this.channel4totalLength > 1)--this.channel4totalLength; | |
else if (this.channel4totalLength == 1) { | |
this.channel4totalLength = 0; | |
this.channel4EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 247 | |
} | |
}; | |
GameBoyCore.prototype.clockAudioSweep = function () { | |
!this.channel1SweepFault && this.channel1timeSweep > 0 && --this.channel1timeSweep == 0 && this.runAudioSweep() | |
}; | |
GameBoyCore.prototype.runAudioSweep = function () { | |
if (this.channel1lastTimeSweep > 0) if (this.channel1frequencySweepDivider > 0) { | |
if (this.channel1numSweep > 0) { | |
--this.channel1numSweep; | |
if (this.channel1decreaseSweep) { | |
this.channel1ShadowFrequency = this.channel1ShadowFrequency - (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider); | |
this.channel1frequency = this.channel1ShadowFrequency & 2047; | |
this.channel1FrequencyTracker = 2048 - this.channel1frequency << 2 | |
} else { | |
this.channel1frequency = this.channel1ShadowFrequency = this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider); | |
if (this.channel1ShadowFrequency <= 2047) { | |
this.channel1FrequencyTracker = 2048 - this.channel1frequency << 2; | |
if (this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider) > 2047) { | |
this.channel1SweepFault = true; | |
this.channel1EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 254 | |
} | |
} else { | |
this.channel1frequency = this.channel1frequency & 2047; | |
this.channel1SweepFault = true; | |
this.channel1EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 254 | |
} | |
} | |
} | |
this.channel1timeSweep = this.channel1lastTimeSweep | |
} else { | |
this.channel1SweepFault = true; | |
this.channel1EnableCheck() | |
} | |
}; | |
GameBoyCore.prototype.channel1AudioSweepPerformDummy = function () { | |
if (this.channel1numSweep > 0 && !this.channel1decreaseSweep) { | |
var a = this.channel1ShadowFrequency + (this.channel1ShadowFrequency >> this.channel1frequencySweepDivider); | |
if (a <= 2047) { | |
if (a + (a >> this.channel1frequencySweepDivider) > 2047) { | |
this.channel1SweepFault = true; | |
this.channel1EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 254 | |
} | |
} else { | |
this.channel1SweepFault = true; | |
this.channel1EnableCheck(); | |
this.memory[65318] = this.memory[65318] & 254 | |
} | |
} | |
}; | |
GameBoyCore.prototype.clockAudioEnvelope = function () { | |
if (this.channel1envelopeSweepsLast > -1) if (this.channel1envelopeSweeps > 0)--this.channel1envelopeSweeps; | |
else if (this.channel1envelopeType) if (this.channel1envelopeVolume < 15) { | |
++this.channel1envelopeVolume; | |
this.channel1envelopeSweeps = this.channel1envelopeSweepsLast; | |
this.channel1OutputLevelCache() | |
} else this.channel1envelopeSweepsLast = -1; | |
else if (this.channel1envelopeVolume > 0) { | |
--this.channel1envelopeVolume; | |
this.channel1envelopeSweeps = this.channel1envelopeSweepsLast; | |
this.channel1OutputLevelCache() | |
} else this.channel1envelopeSweepsLast = -1; | |
if (this.channel2envelopeSweepsLast > -1) if (this.channel2envelopeSweeps > 0)--this.channel2envelopeSweeps; | |
else if (this.channel2envelopeType) if (this.channel2envelopeVolume < 15) { | |
++this.channel2envelopeVolume; | |
this.channel2envelopeSweeps = this.channel2envelopeSweepsLast; | |
this.channel2OutputLevelCache() | |
} else this.channel2envelopeSweepsLast = -1; | |
else if (this.channel2envelopeVolume > 0) { | |
--this.channel2envelopeVolume; | |
this.channel2envelopeSweeps = this.channel2envelopeSweepsLast; | |
this.channel2OutputLevelCache() | |
} else this.channel2envelopeSweepsLast = -1; | |
if (this.channel4envelopeSweepsLast > -1) if (this.channel4envelopeSweeps > 0)--this.channel4envelopeSweeps; | |
else if (this.channel4envelopeType) if (this.channel4envelopeVolume < 15) { | |
this.channel4currentVolume = ++this.channel4envelopeVolume << this.channel4VolumeShifter; | |
this.channel4envelopeSweeps = this.channel4envelopeSweepsLast; | |
this.channel4UpdateCache() | |
} else this.channel4envelopeSweepsLast = -1; | |
else if (this.channel4envelopeVolume > 0) { | |
this.channel4currentVolume = --this.channel4envelopeVolume << this.channel4VolumeShifter; | |
this.channel4envelopeSweeps = this.channel4envelopeSweepsLast; | |
this.channel4UpdateCache() | |
} else this.channel4envelopeSweepsLast = -1 | |
}; | |
GameBoyCore.prototype.computeAudioChannels = function () { | |
if (--this.channel1FrequencyCounter == 0) { | |
this.channel1FrequencyCounter = this.channel1FrequencyTracker; | |
this.channel1DutyTracker = this.channel1DutyTracker + 1 & 7; | |
this.channel1OutputLevelTrimaryCache() | |
} | |
if (--this.channel2FrequencyCounter == 0) { | |
this.channel2FrequencyCounter = this.channel2FrequencyTracker; | |
this.channel2DutyTracker = this.channel2DutyTracker + 1 & 7; | |
this.channel2OutputLevelTrimaryCache() | |
} | |
if (--this.channel3Counter == 0) { | |
if (this.channel3canPlay) this.channel3lastSampleLookup = this.channel3lastSampleLookup + 1 & 31; | |
this.channel3Counter = this.channel3FrequencyPeriod; | |
this.channel3UpdateCache() | |
} | |
if (--this.channel4Counter == 0) { | |
this.channel4lastSampleLookup = this.channel4lastSampleLookup + 1 & this.channel4BitRange; | |
this.channel4Counter = this.channel4FrequencyPeriod; | |
this.channel4UpdateCache() | |
} | |
}; | |
GameBoyCore.prototype.channel1EnableCheck = function () { | |
this.channel1Enabled = (this.channel1consecutive || this.channel1totalLength > 0) && !this.channel1SweepFault && this.channel1canPlay; | |
this.channel1OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel1VolumeEnableCheck = function () { | |
this.channel1canPlay = this.memory[65298] > 7; | |
this.channel1EnableCheck(); | |
this.channel1OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel1OutputLevelCache = function () { | |
this.channel1currentSampleLeft = this.leftChannel1 ? this.channel1envelopeVolume : 0; | |
this.channel1currentSampleRight = this.rightChannel1 ? this.channel1envelopeVolume : 0; | |
this.channel1OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel1OutputLevelSecondaryCache = function () { | |
if (this.channel1Enabled) { | |
this.channel1currentSampleLeftSecondary = this.channel1currentSampleLeft; | |
this.channel1currentSampleRightSecondary = this.channel1currentSampleRight | |
} else this.channel1currentSampleRightSecondary = this.channel1currentSampleLeftSecondary = 0; | |
this.channel1OutputLevelTrimaryCache() | |
}; | |
GameBoyCore.prototype.channel1OutputLevelTrimaryCache = function () { | |
if (this.channel1CachedDuty[this.channel1DutyTracker]) { | |
this.channel1currentSampleLeftTrimary = this.channel1currentSampleLeftSecondary; | |
this.channel1currentSampleRightTrimary = this.channel1currentSampleRightSecondary | |
} else this.channel1currentSampleRightTrimary = this.channel1currentSampleLeftTrimary = 0; | |
this.mixerOutputLevelCache() | |
}; | |
GameBoyCore.prototype.channel2EnableCheck = function () { | |
this.channel2Enabled = (this.channel2consecutive || this.channel2totalLength > 0) && this.channel2canPlay; | |
this.channel2OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel2VolumeEnableCheck = function () { | |
this.channel2canPlay = this.memory[65303] > 7; | |
this.channel2EnableCheck(); | |
this.channel2OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel2OutputLevelCache = function () { | |
this.channel2currentSampleLeft = this.leftChannel2 ? this.channel2envelopeVolume : 0; | |
this.channel2currentSampleRight = this.rightChannel2 ? this.channel2envelopeVolume : 0; | |
this.channel2OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel2OutputLevelSecondaryCache = function () { | |
if (this.channel2Enabled) { | |
this.channel2currentSampleLeftSecondary = this.channel2currentSampleLeft; | |
this.channel2currentSampleRightSecondary = this.channel2currentSampleRight | |
} else this.channel2currentSampleRightSecondary = this.channel2currentSampleLeftSecondary = 0; | |
this.channel2OutputLevelTrimaryCache() | |
}; | |
GameBoyCore.prototype.channel2OutputLevelTrimaryCache = function () { | |
if (this.channel2CachedDuty[this.channel2DutyTracker]) { | |
this.channel2currentSampleLeftTrimary = this.channel2currentSampleLeftSecondary; | |
this.channel2currentSampleRightTrimary = this.channel2currentSampleRightSecondary | |
} else this.channel2currentSampleRightTrimary = this.channel2currentSampleLeftTrimary = 0; | |
this.mixerOutputLevelCache() | |
}; | |
GameBoyCore.prototype.channel3EnableCheck = function () { | |
this.channel3Enabled = this.channel3consecutive || this.channel3totalLength > 0; | |
this.channel3OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel3OutputLevelCache = function () { | |
this.channel3currentSampleLeft = this.leftChannel3 ? this.cachedChannel3Sample : 0; | |
this.channel3currentSampleRight = this.rightChannel3 ? this.cachedChannel3Sample : 0; | |
this.channel3OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel3OutputLevelSecondaryCache = function () { | |
if (this.channel3Enabled) { | |
this.channel3currentSampleLeftSecondary = this.channel3currentSampleLeft; | |
this.channel3currentSampleRightSecondary = this.channel3currentSampleRight | |
} else this.channel3currentSampleRightSecondary = this.channel3currentSampleLeftSecondary = 0; | |
this.mixerOutputLevelCache() | |
}; | |
GameBoyCore.prototype.channel4EnableCheck = function () { | |
this.channel4Enabled = (this.channel4consecutive || this.channel4totalLength > 0) && this.channel4canPlay; | |
this.channel4OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel4VolumeEnableCheck = function () { | |
this.channel4canPlay = this.memory[65313] > 7; | |
this.channel4EnableCheck(); | |
this.channel4OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel4OutputLevelCache = function () { | |
this.channel4currentSampleLeft = this.leftChannel4 ? this.cachedChannel4Sample : 0; | |
this.channel4currentSampleRight = this.rightChannel4 ? this.cachedChannel4Sample : 0; | |
this.channel4OutputLevelSecondaryCache() | |
}; | |
GameBoyCore.prototype.channel4OutputLevelSecondaryCache = function () { | |
if (this.channel4Enabled) { | |
this.channel4currentSampleLeftSecondary = this.channel4currentSampleLeft; | |
this.channel4currentSampleRightSecondary = this.channel4currentSampleRight | |
} else this.channel4currentSampleRightSecondary = this.channel4currentSampleLeftSecondary = 0; | |
this.mixerOutputLevelCache() | |
}; | |
GameBoyCore.prototype.mixerOutputLevelCache = function () { | |
this.mixerOutputCache = ((this.channel1currentSampleLeftTrimary + this.channel2currentSampleLeftTrimary + this.channel3currentSampleLeftSecondary + this.channel4currentSampleLeftSecondary) * this.VinLeftChannelMasterVolume << 9) + (this.channel1currentSampleRightTrimary + this.channel2currentSampleRightTrimary + this.channel3currentSampleRightSecondary + this.channel4currentSampleRightSecondary) * this.VinRightChannelMasterVolume | |
}; | |
GameBoyCore.prototype.channel3UpdateCache = function () { | |
this.cachedChannel3Sample = this.channel3PCM[this.channel3lastSampleLookup] >> this.channel3patternType; | |
this.channel3OutputLevelCache() | |
}; | |
GameBoyCore.prototype.channel3WriteRAM = function (a, b) { | |
this.channel3canPlay && this.audioJIT(); | |
this.memory[65328 | a] = b; | |
a = a << 1; | |
this.channel3PCM[a] = b >> 4; | |
this.channel3PCM[a | 1] = b & 15 | |
}; | |
GameBoyCore.prototype.channel4UpdateCache = function () { | |
this.cachedChannel4Sample = this.noiseSampleTable[this.channel4currentVolume | this.channel4lastSampleLookup]; | |
this.channel4OutputLevelCache() | |
}; | |
GameBoyCore.prototype.run = function () { | |
if ((this.stopEmulator & 2) == 0) if ((this.stopEmulator & 1) == 1) if (this.CPUStopped) { | |
this.audioUnderrunAdjustment(); | |
this.audioTicks = this.audioTicks + this.CPUCyclesTotal; | |
this.audioJIT(); | |
this.stopEmulator = this.stopEmulator | 1 | |
} else { | |
this.stopEmulator = 0; | |
this.drewFrame = false; | |
this.audioUnderrunAdjustment(); | |
this.clockUpdate(); | |
if (this.halt) { | |
this.CPUTicks = 0; | |
this.calculateHALTPeriod(); | |
this.halt ? this.updateCoreFull() : this.executeIteration() | |
} else this.executeIteration(); | |
this.requestDraw() | |
} else { | |
cout("Iterator restarted a faulted core.", 2); | |
pause() | |
} | |
}; | |
GameBoyCore.prototype.executeIteration = function () { | |
for (var a = 0, a = 0; this.stopEmulator == 0;) { | |
switch (this.IRQEnableDelay) { | |
case 1: | |
this.IME = true; | |
this.checkIRQMatching(); | |
case 2: | |
--this.IRQEnableDelay | |
} | |
this.IRQLineMatched > 0 && this.launchIRQ(); | |
a = this.memoryReader[this.programCounter](this, this.programCounter); | |
this.programCounter = this.programCounter + 1 & 65535; | |
if (this.skipPCIncrement) { | |
this.programCounter = this.programCounter - 1 & 65535; | |
this.skipPCIncrement = false | |
} | |
this.CPUTicks = this.TICKTable[a]; | |
this.OPCODE[a](this); | |
this.LCDTicks = this.LCDTicks + (this.CPUTicks >> this.doubleSpeedShifter); | |
this.LCDCONTROL[this.actualScanLine](this); | |
a = this.CPUTicks >> this.doubleSpeedShifter; | |
this.audioTicks = this.audioTicks + a; | |
this.emulatorTicks = this.emulatorTicks + a; | |
this.DIVTicks = this.DIVTicks + this.CPUTicks; | |
if (this.TIMAEnabled) for (this.timerTicks = this.timerTicks + this.CPUTicks; this.timerTicks >= this.TACClocker;) { | |
this.timerTicks = this.timerTicks - this.TACClocker; | |
if (++this.memory[65285] == 256) { | |
this.memory[65285] = this.memory[65286]; | |
this.interruptsRequested = this.interruptsRequested | 4; | |
this.checkIRQMatching() | |
} | |
} | |
if (this.serialTimer > 0) { | |
this.serialTimer = this.serialTimer - this.CPUTicks; | |
if (this.serialTimer <= 0) { | |
this.interruptsRequested = this.interruptsRequested | 8; | |
this.checkIRQMatching() | |
} | |
this.serialShiftTimer = this.serialShiftTimer - this.CPUTicks; | |
if (this.serialShiftTimer <= 0) { | |
this.serialShiftTimer = this.serialShiftTimerAllocated; | |
this.memory[65281] = this.memory[65281] << 1 & 254 | 1 | |
} | |
} | |
this.emulatorTicks >= this.CPUCyclesTotal && this.iterationEndRoutine() | |
} | |
}; | |
GameBoyCore.prototype.iterationEndRoutine = function () { | |
if ((this.stopEmulator & 1) == 0) { | |
this.audioJIT(); | |
this.memory[65284] = this.memory[65284] + (this.DIVTicks >> 8) & 255; | |
this.DIVTicks = this.DIVTicks & 255; | |
this.stopEmulator = this.stopEmulator | 1; | |
this.emulatorTicks = this.emulatorTicks - this.CPUCyclesTotal; | |
this.CPUCyclesTotalCurrent = this.CPUCyclesTotalCurrent + this.CPUCyclesTotalRoundoff; | |
this.recalculateIterationClockLimit() | |
} | |
}; | |
GameBoyCore.prototype.handleSTOP = function () { | |
this.CPUStopped = true; | |
this.iterationEndRoutine(); | |
if (this.emulatorTicks < 0) { | |
this.audioTicks = this.audioTicks - this.emulatorTicks; | |
this.audioJIT() | |
} | |
}; | |
GameBoyCore.prototype.recalculateIterationClockLimit = function () { | |
var a = this.CPUCyclesTotalCurrent % 4; | |
this.CPUCyclesTotal = this.CPUCyclesTotalBase + this.CPUCyclesTotalCurrent - a; | |
this.CPUCyclesTotalCurrent = a | |
}; | |
GameBoyCore.prototype.scanLineMode2 = function () { | |
if (this.STATTracker != 1) { | |
if (this.mode2TriggerSTAT) { | |
this.interruptsRequested = this.interruptsRequested | 2; | |
this.checkIRQMatching() | |
} | |
this.STATTracker = 1; | |
this.modeSTAT = 2 | |
} | |
}; | |
GameBoyCore.prototype.scanLineMode3 = function () { | |
if (this.modeSTAT != 3) { | |
if (this.STATTracker == 0 && this.mode2TriggerSTAT) { | |
this.interruptsRequested = this.interruptsRequested | 2; | |
this.checkIRQMatching() | |
} | |
this.STATTracker = 1; | |
this.modeSTAT = 3 | |
} | |
}; | |
GameBoyCore.prototype.scanLineMode0 = function () { | |
if (this.modeSTAT != 0) { | |
if (this.STATTracker != 2) { | |
if (this.STATTracker == 0) { | |
if (this.mode2TriggerSTAT) { | |
this.interruptsRequested = this.interruptsRequested | 2; | |
this.checkIRQMatching() | |
} | |
this.modeSTAT = 3 | |
} | |
this.incrementScanLineQueue(); | |
this.updateSpriteCount(this.actualScanLine); | |
this.STATTracker = 2 | |
} | |
if (this.LCDTicks >= this.spriteCount) { | |
this.hdmaRunning && this.executeHDMA(); | |
if (this.mode0TriggerSTAT) { | |
this.interruptsRequested = this.interruptsRequested | 2; | |
this.checkIRQMatching() | |
} | |
this.STATTracker = 3; | |
this.modeSTAT = 0 | |
} | |
} | |
}; | |
GameBoyCore.prototype.clocksUntilLYCMatch = function () { | |
return this.memory[65349] != 0 ? this.memory[65349] > this.actualScanLine ? 456 * (this.memory[65349] - this.actualScanLine) : 456 * (154 - this.actualScanLine + this.memory[65349]) : 456 * (this.actualScanLine == 153 && this.memory[65348] == 0 ? 154 : 153 - this.actualScanLine) + 8 | |
}; | |
GameBoyCore.prototype.clocksUntilMode0 = function () { | |
switch (this.modeSTAT) { | |
case 0: | |
if (this.actualScanLine == 143) { | |
this.updateSpriteCount(0); | |
return this.spriteCount + 5016 | |
} | |
this.updateSpriteCount(this.actualScanLine + 1); | |
return this.spriteCount + 456; | |
case 2: | |
case 3: | |
this.updateSpriteCount(this.actualScanLine); | |
return this.spriteCount; | |
case 1: | |
this.updateSpriteCount(0); | |
return this.spriteCount + 456 * (154 - this.actualScanLine) | |
} | |
}; | |
GameBoyCore.prototype.updateSpriteCount = function (a) { | |
this.spriteCount = 252; | |
if (this.cGBC && this.gfxSpriteShow) for (var a = a + 16, b = 0, c = this.gfxSpriteNormalHeight ? 8 : 16, e = 65024; e < 65184 && this.spriteCount < 312; e = e + 4) { | |
b = a - this.memory[e]; | |
if (b > -1 && b < c) this.spriteCount = this.spriteCount + 6 | |
} | |
}; | |
GameBoyCore.prototype.matchLYC = function () { | |
if (this.memory[65348] == this.memory[65349]) { | |
this.memory[65345] = this.memory[65345] | 4; | |
if (this.LYCMatchTriggerSTAT) { | |
this.interruptsRequested = this.interruptsRequested | 2; | |
this.checkIRQMatching() | |
} | |
} else this.memory[65345] = this.memory[65345] & 123 | |
}; | |
GameBoyCore.prototype.updateCore = function () { | |
this.LCDTicks = this.LCDTicks + (this.CPUTicks >> this.doubleSpeedShifter); | |
this.LCDCONTROL[this.actualScanLine](this); | |
var a = this.CPUTicks >> this.doubleSpeedShifter; | |
this.audioTicks = this.audioTicks + a; | |
this.emulatorTicks = this.emulatorTicks + a; | |
this.DIVTicks = this.DIVTicks + this.CPUTicks; | |
if (this.TIMAEnabled) for (this.timerTicks = this.timerTicks + this.CPUTicks; this.timerTicks >= this.TACClocker;) { | |
this.timerTicks = this.timerTicks - this.TACClocker; | |
if (++this.memory[65285] == 256) { | |
this.memory[65285] = this.memory[65286]; | |
this.interruptsRequested = this.interruptsRequested | 4; | |
this.checkIRQMatching() | |
} | |
} | |
if (this.serialTimer > 0) { | |
this.serialTimer = this.serialTimer - this.CPUTicks; | |
if (this.serialTimer <= 0) { | |
this.interruptsRequested = this.interruptsRequested | 8; | |
this.checkIRQMatching() | |
} | |
this.serialShiftTimer = this.serialShiftTimer - this.CPUTicks; | |
if (this.serialShiftTimer <= 0) { | |
this.serialShiftTimer = this.serialShiftTimerAllocated; | |
this.memory[65281] = this.memory[65281] << 1 & 254 | 1 | |
} | |
} | |
}; | |
GameBoyCore.prototype.updateCoreFull = function () { | |
this.updateCore(); | |
this.emulatorTicks >= this.CPUCyclesTotal && this.iterationEndRoutine() | |
}; | |
GameBoyCore.prototype.initializeLCDController = function () { | |
for (var a = 0; a < 154;) { | |
a < 143 ? this.LINECONTROL[a] = function (a) { | |
if (a.LCDTicks < 80) a.scanLineMode2(); | |
else if (a.LCDTicks < 252) a.scanLineMode3(); | |
else if (a.LCDTicks < 456) a.scanLineMode0(); | |
else { | |
a.LCDTicks = a.LCDTicks - 456; | |
if (a.STATTracker != 3) { | |
if (a.STATTracker != 2) { | |
if (a.STATTracker == 0 && a.mode2TriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2; | |
a.incrementScanLineQueue() | |
} | |
a.hdmaRunning && a.executeHDMA(); | |
if (a.mode0TriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2 | |
} | |
a.actualScanLine = ++a.memory[65348]; | |
if (a.actualScanLine == a.memory[65349]) { | |
a.memory[65345] = a.memory[65345] | 4; | |
if (a.LYCMatchTriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2 | |
} else a.memory[65345] = a.memory[65345] & 123; | |
a.checkIRQMatching(); | |
a.STATTracker = 0; | |
a.modeSTAT = 2; | |
a.LINECONTROL[a.actualScanLine](a) | |
} | |
} : a == 143 ? this.LINECONTROL[143] = function (a) { | |
if (a.LCDTicks < 80) a.scanLineMode2(); | |
else if (a.LCDTicks < 252) a.scanLineMode3(); | |
else if (a.LCDTicks < 456) a.scanLineMode0(); | |
else { | |
a.LCDTicks = a.LCDTicks - 456; | |
if (a.STATTracker != 3) { | |
if (a.STATTracker != 2) { | |
if (a.STATTracker == 0 && a.mode2TriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2; | |
a.incrementScanLineQueue() | |
} | |
a.hdmaRunning && a.executeHDMA(); | |
if (a.mode0TriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2 | |
} | |
a.actualScanLine = a.memory[65348] = 144; | |
if (a.memory[65349] == 144) { | |
a.memory[65345] = a.memory[65345] | 4; | |
if (a.LYCMatchTriggerSTAT) a.interruptsRequested = a.interruptsRequested | 2 | |
} else a.memory[65345] = a.memory[65345] & 123; | |
a.STATTracker = 0; | |
a.modeSTAT = 1; | |
a.interruptsRequested = a.interruptsRequested | (a.mode1TriggerSTAT ? 3 : 1); | |
a.checkIRQMatching(); | |
if (a.drewBlank == 0) { | |
if (a.totalLinesPassed < 144 || a.totalLinesPassed == 144 && a.midScanlineOffset > -1) { | |
a.graphicsJITVBlank(); | |
a.prepareFrame() | |
} | |
} else --a.drewBlank; | |
a.LINECONTROL[144](a) | |
} | |
} : a < 153 ? this.LINECONTROL[a] = function (a) { | |
if (a.LCDTicks >= 456) { | |
a.LCDTicks = a.LCDTicks - 456; | |
a.actualScanLine = ++a.memory[65348]; | |
if (a.actualScanLine == a.memory[65349]) { | |
a.memory[65345] = a.memory[65345] | 4; | |
if (a.LYCMatchTriggerSTAT) { | |
a.interruptsRequested = a.interruptsRequested | 2; | |
a.checkIRQMatching() | |
} | |
} else a.memory[65345] = a.memory[65345] & 123; | |
a.LINECONTROL[a.actualScanLine](a) | |
} | |
} : this.LINECONTROL[153] = function (a) { | |
if (a.LCDTicks >= 8) { | |
if (a.STATTracker != 4 && a.memory[65348] == 153) { | |
a.memory[65348] = 0; | |
if (a.memory[65349] == 0) { | |
a.memory[65345] = a.memory[65345] | 4; | |
if (a.LYCMatchTriggerSTAT) { | |
a.interruptsRequested = a.interruptsRequested | 2; | |
a.checkIRQMatching() | |
} | |
} else a.memory[65345] = a.memory[65345] & 123; | |
a.STATTracker = 4 | |
} | |
if (a.LCDTicks >= 456) { | |
a.LCDTicks = a.LCDTicks - 456; | |
a.STATTracker = a.actualScanLine = 0; | |
a.LINECONTROL[0](a) | |
} | |
} | |
}; | |
++a | |
} | |
}; | |
GameBoyCore.prototype.DisplayShowOff = function () { | |
if (this.drewBlank == 0) { | |
this.clearFrameBuffer(); | |
this.drewFrame = true | |
} | |
this.drewBlank = 2 | |
}; | |
GameBoyCore.prototype.executeHDMA = function () { | |
this.DMAWrite(1); | |
if (this.halt) { | |
if (this.LCDTicks - this.spriteCount < (4 >> this.doubleSpeedShifter | 32)) { | |
this.CPUTicks = 4 + (32 + this.spriteCount << this.doubleSpeedShifter); | |
this.LCDTicks = this.spriteCount + (4 >> this.doubleSpeedShifter | 32) | |
} | |
} else this.LCDTicks = this.LCDTicks + (4 >> this.doubleSpeedShifter | 32); | |
if (this.memory[65365] == 0) { | |
this.hdmaRunning = false; | |
this.memory[65365] = 255 | |
} else --this.memory[65365] | |
}; | |
GameBoyCore.prototype.clockUpdate = function () { | |
if (this.cTIMER) { | |
var a = (new Date).getTime(), | |
b = a - this.lastIteration; | |
this.lastIteration = a; | |
if (this.cTIMER && !this.RTCHALT) for (this.RTCSeconds = this.RTCSeconds + b / 1E3; this.RTCSeconds >= 60;) { | |
this.RTCSeconds = this.RTCSeconds - 60; | |
++this.RTCMinutes; | |
if (this.RTCMinutes >= 60) { | |
this.RTCMinutes = this.RTCMinutes - 60; | |
++this.RTCHours; | |
if (this.RTCHours >= 24) { | |
this.RTCHours = this.RTCHours - 24; | |
++this.RTCDays; | |
if (this.RTCDays >= 512) { | |
this.RTCDays = this.RTCDays - 512; | |
this.RTCDayOverFlow = true | |
} | |
} | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.prepareFrame = function () { | |
this.swizzleFrameBuffer(); | |
this.drewFrame = true | |
}; | |
GameBoyCore.prototype.requestDraw = function () { | |
this.drewFrame && this.dispatchDraw() | |
}; | |
GameBoyCore.prototype.dispatchDraw = function () { | |
var a = this.offscreenRGBCount; | |
if (a > 0) { | |
for (var b = a == 92160 ? this.swizzledFrame : this.resizeFrameBuffer(), c = this.canvasBuffer.data, e = 0, f = 0; f < a; ++f) { | |
c[f++] = b[e++]; | |
c[f++] = b[e++]; | |
c[f++] = b[e++] | |
} | |
this.graphicsBlit() | |
} | |
}; | |
GameBoyCore.prototype.swizzleFrameBuffer = function () { | |
for (var a = this.frameBuffer, b = this.swizzledFrame, c = 0, e = 0; e < 69120;) { | |
b[e++] = a[c] >> 16 & 255; | |
b[e++] = a[c] >> 8 & 255; | |
b[e++] = a[c++] & 255 | |
} | |
}; | |
GameBoyCore.prototype.clearFrameBuffer = function () { | |
var a = 0, | |
b = this.swizzledFrame; | |
if (this.cGBC || this.colorizedGBPalettes) for (; a < 69120;) b[a++] = 248; | |
else for (; a < 69120;) { | |
b[a++] = 239; | |
b[a++] = 255; | |
b[a++] = 222 | |
} | |
}; | |
GameBoyCore.prototype.resizeFrameBuffer = function () { | |
return this.resizer.resize(this.swizzledFrame) | |
}; | |
GameBoyCore.prototype.compileResizeFrameBufferFunction = function () { | |
if (this.offscreenRGBCount > 0) this.resizer = new Resize(160, 144, this.offscreenWidth, this.offscreenHeight, false, true) | |
}; | |
GameBoyCore.prototype.renderScanLine = function (a) { | |
this.pixelStart = a * 160; | |
if (this.bgEnabled) { | |
this.pixelEnd = 160; | |
this.BGLayerRender(a); | |
this.WindowLayerRender(a) | |
} else for (var b = (a + 1) * 160, c = this.cGBC || this.colorizedGBPalettes ? 16316664 : 15728606, e = a * 160 + this.currentX; e < b; e++) this.frameBuffer[e] = c; | |
this.SpriteLayerRender(a); | |
this.currentX = 0; | |
this.midScanlineOffset = -1 | |
}; | |
GameBoyCore.prototype.renderMidScanLine = function () { | |
if (this.actualScanLine < 144 && this.modeSTAT == 3) { | |
if (this.midScanlineOffset == -1) this.midScanlineOffset = this.backgroundX & 7; | |
if (this.LCDTicks >= 82) { | |
this.pixelEnd = this.LCDTicks - 74; | |
this.pixelEnd = Math.min(this.pixelEnd - this.midScanlineOffset - this.pixelEnd % 8, 160); | |
if (this.bgEnabled) { | |
this.pixelStart = this.lastUnrenderedLine * 160; | |
this.BGLayerRender(this.lastUnrenderedLine); | |
this.WindowLayerRender(this.lastUnrenderedLine) | |
} else for (var a = this.lastUnrenderedLine * 160 + this.pixelEnd, b = this.cGBC || this.colorizedGBPalettes ? 16316664 : 15728606, c = this.lastUnrenderedLine * 160 + this.currentX; c < a; c++) this.frameBuffer[c] = b; | |
this.currentX = this.pixelEnd | |
} | |
} | |
}; | |
GameBoyCore.prototype.initializeModeSpecificArrays = function () { | |
this.LCDCONTROL = this.LCDisOn ? this.LINECONTROL : this.DISPLAYOFFCONTROL; | |
if (this.cGBC) { | |
this.gbcOBJRawPalette = this.getTypedArray(64, 0, "uint8"); | |
this.gbcBGRawPalette = this.getTypedArray(64, 0, "uint8"); | |
this.gbcOBJPalette = this.getTypedArray(32, 16777216, "int32"); | |
this.gbcBGPalette = this.getTypedArray(64, 0, "int32"); | |
this.BGCHRBank2 = this.getTypedArray(2048, 0, "uint8"); | |
this.BGCHRCurrentBank = this.currVRAMBank > 0 ? this.BGCHRBank2 : this.BGCHRBank1; | |
this.tileCache = this.generateCacheArray(3968) | |
} else { | |
this.gbOBJPalette = this.getTypedArray(8, 0, "int32"); | |
this.BGPalette = this.gbBGPalette = this.getTypedArray(4, 0, "int32"); | |
this.OBJPalette = this.gbOBJPalette; | |
this.tileCache = this.generateCacheArray(1792); | |
this.sortBuffer = this.getTypedArray(256, 0, "uint8"); | |
this.OAMAddressCache = this.getTypedArray(10, 0, "int32") | |
} | |
this.renderPathBuild() | |
}; | |
GameBoyCore.prototype.GBCtoGBModeAdjust = function () { | |
cout("Stepping down from GBC mode.", 0); | |
this.VRAM = this.GBCMemory = this.BGCHRCurrentBank = this.BGCHRBank2 = null; | |
this.tileCache.length = 1792; | |
if (settings[4]) { | |
this.gbBGColorizedPalette = this.getTypedArray(4, 0, "int32"); | |
this.gbOBJColorizedPalette = this.getTypedArray(8, 0, "int32"); | |
this.cachedBGPaletteConversion = this.getTypedArray(4, 0, "int32"); | |
this.cachedOBJPaletteConversion = this.getTypedArray(8, 0, "int32"); | |
this.BGPalette = this.gbBGColorizedPalette; | |
this.OBJPalette = this.gbOBJColorizedPalette; | |
this.gbOBJPalette = this.gbBGPalette = null; | |
this.getGBCColor() | |
} else { | |
this.gbOBJPalette = this.getTypedArray(8, 0, "int32"); | |
this.BGPalette = this.gbBGPalette = this.getTypedArray(4, 0, "int32"); | |
this.OBJPalette = this.gbOBJPalette | |
} | |
this.sortBuffer = this.getTypedArray(256, 0, "uint8"); | |
this.OAMAddressCache = this.getTypedArray(10, 0, "int32"); | |
this.renderPathBuild(); | |
this.memoryReadJumpCompile(); | |
this.memoryWriteJumpCompile() | |
}; | |
GameBoyCore.prototype.renderPathBuild = function () { | |
if (this.cGBC) { | |
this.priorityFlaggingPathRebuild(); | |
this.SpriteLayerRender = this.SpriteGBCLayerRender | |
} else { | |
this.BGLayerRender = this.BGGBLayerRender; | |
this.WindowLayerRender = this.WindowGBLayerRender; | |
this.SpriteLayerRender = this.SpriteGBLayerRender | |
} | |
}; | |
GameBoyCore.prototype.priorityFlaggingPathRebuild = function () { | |
if (this.BGPriorityEnabled) { | |
this.BGLayerRender = this.BGGBCLayerRender; | |
this.WindowLayerRender = this.WindowGBCLayerRender | |
} else { | |
this.BGLayerRender = this.BGGBCLayerRenderNoPriorityFlagging; | |
this.WindowLayerRender = this.WindowGBCLayerRenderNoPriorityFlagging | |
} | |
}; | |
GameBoyCore.prototype.initializeReferencesFromSaveState = function () { | |
this.LCDCONTROL = this.LCDisOn ? this.LINECONTROL : this.DISPLAYOFFCONTROL; | |
var a = 0; | |
if (this.cGBC) { | |
this.BGCHRCurrentBank = this.currVRAMBank > 0 ? this.BGCHRBank2 : this.BGCHRBank1; | |
for (this.tileCache = this.generateCacheArray(3968); a < 6144; a = a + 16) { | |
this.generateGBCTileBank1(a); | |
this.generateGBCTileBank2(a) | |
} | |
} else { | |
if (this.colorizedGBPalettes) { | |
this.BGPalette = this.gbBGColorizedPalette; | |
this.OBJPalette = this.gbOBJColorizedPalette; | |
this.updateGBBGPalette = this.updateGBColorizedBGPalette; | |
this.updateGBOBJPalette = this.updateGBColorizedOBJPalette | |
} else { | |
this.BGPalette = this.gbBGPalette; | |
this.OBJPalette = this.gbOBJPalette | |
} | |
this.tileCache = this.generateCacheArray(1792); | |
for (a = 32768; a < 36864; a = a + 2) this.generateGBOAMTileLine(a); | |
for (a = 36864; a < 38912; a = a + 2) this.generateGBTileLine(a); | |
this.sortBuffer = this.getTypedArray(256, 0, "uint8"); | |
this.OAMAddressCache = this.getTypedArray(10, 0, "int32") | |
} | |
this.renderPathBuild() | |
}; | |
GameBoyCore.prototype.RGBTint = function (a) { | |
var b = a & 31, | |
c = a >> 5 & 31, | |
a = a >> 10 & 31; | |
return b * 13 + c * 2 + a >> 1 << 16 | c * 3 + a << 9 | b * 3 + c * 2 + a * 11 >> 1 | |
}; | |
GameBoyCore.prototype.getGBCColor = function () { | |
for (var a = 0; a < 4; a++) { | |
var b = a << 1; | |
this.cachedBGPaletteConversion[a] = this.RGBTint(this.gbcBGRawPalette[b | 1] << 8 | this.gbcBGRawPalette[b]); | |
this.cachedOBJPaletteConversion[a] = this.RGBTint(this.gbcOBJRawPalette[b | 1] << 8 | this.gbcOBJRawPalette[b]) | |
} | |
for (a = 4; a < 8; a++) { | |
b = a << 1; | |
this.cachedOBJPaletteConversion[a] = this.RGBTint(this.gbcOBJRawPalette[b | 1] << 8 | this.gbcOBJRawPalette[b]) | |
} | |
this.updateGBBGPalette = this.updateGBColorizedBGPalette; | |
this.updateGBOBJPalette = this.updateGBColorizedOBJPalette; | |
this.updateGBBGPalette(this.memory[65351]); | |
this.updateGBOBJPalette(0, this.memory[65352]); | |
this.updateGBOBJPalette(1, this.memory[65353]); | |
this.colorizedGBPalettes = true | |
}; | |
GameBoyCore.prototype.updateGBRegularBGPalette = function (a) { | |
this.gbBGPalette[0] = this.colors[a & 3] | 33554432; | |
this.gbBGPalette[1] = this.colors[a >> 2 & 3]; | |
this.gbBGPalette[2] = this.colors[a >> 4 & 3]; | |
this.gbBGPalette[3] = this.colors[a >> 6] | |
}; | |
GameBoyCore.prototype.updateGBColorizedBGPalette = function (a) { | |
this.gbBGColorizedPalette[0] = this.cachedBGPaletteConversion[a & 3] | 33554432; | |
this.gbBGColorizedPalette[1] = this.cachedBGPaletteConversion[a >> 2 & 3]; | |
this.gbBGColorizedPalette[2] = this.cachedBGPaletteConversion[a >> 4 & 3]; | |
this.gbBGColorizedPalette[3] = this.cachedBGPaletteConversion[a >> 6] | |
}; | |
GameBoyCore.prototype.updateGBRegularOBJPalette = function (a, b) { | |
this.gbOBJPalette[a | 1] = this.colors[b >> 2 & 3]; | |
this.gbOBJPalette[a | 2] = this.colors[b >> 4 & 3]; | |
this.gbOBJPalette[a | 3] = this.colors[b >> 6] | |
}; | |
GameBoyCore.prototype.updateGBColorizedOBJPalette = function (a, b) { | |
this.gbOBJColorizedPalette[a | 1] = this.cachedOBJPaletteConversion[a | b >> 2 & 3]; | |
this.gbOBJColorizedPalette[a | 2] = this.cachedOBJPaletteConversion[a | b >> 4 & 3]; | |
this.gbOBJColorizedPalette[a | 3] = this.cachedOBJPaletteConversion[a | b >> 6] | |
}; | |
GameBoyCore.prototype.updateGBCBGPalette = function (a, b) { | |
if (this.gbcBGRawPalette[a] != b) { | |
this.midScanLineJIT(); | |
this.gbcBGRawPalette[a] = b; | |
b = (a & 6) == 0 ? 33554432 | this.RGBTint(this.gbcBGRawPalette[a | 1] << 8 | this.gbcBGRawPalette[a & 62]) : this.RGBTint(this.gbcBGRawPalette[a | 1] << 8 | this.gbcBGRawPalette[a & 62]); | |
a = a >> 1; | |
this.gbcBGPalette[a] = b; | |
this.gbcBGPalette[32 | a] = 16777216 | b | |
} | |
}; | |
GameBoyCore.prototype.updateGBCOBJPalette = function (a, b) { | |
if (this.gbcOBJRawPalette[a] != b) { | |
this.gbcOBJRawPalette[a] = b; | |
if ((a & 6) > 0) { | |
this.midScanLineJIT(); | |
this.gbcOBJPalette[a >> 1] = 16777216 | this.RGBTint(this.gbcOBJRawPalette[a | 1] << 8 | this.gbcOBJRawPalette[a & 62]) | |
} | |
} | |
}; | |
GameBoyCore.prototype.BGGBLayerRender = function (a) { | |
var b = this.backgroundY + a & 255, | |
c = (b & 7) << 3, | |
b = this.gfxBackgroundCHRBankPosition | (b & 248) << 2, | |
e = this.backgroundX + this.currentX & 255, | |
f = this.pixelStart + this.currentX, | |
a = this.pixelStart + (this.gfxWindowDisplay && a - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd), | |
g = b + (e >> 3), | |
d = this.BGCHRBank1[g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
for (var d = this.tileCache[d], h = e & 7; h < 8 && f < a && e < 256; ++e) this.frameBuffer[f++] = this.BGPalette[d[c | h++]]; | |
for (var i = Math.min(a - f, 256 - e) >> 3, e = e + (i << 3), i = i + g; g < i;) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
d = this.tileCache[d]; | |
h = c; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h]] | |
} | |
if (f < a) { | |
if (e < 256) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
d = this.tileCache[d]; | |
for (h = c - 1; f < a && e < 256; ++e) this.frameBuffer[f++] = this.BGPalette[d[++h]] | |
} | |
for (i = (a - f >> 3) + b; b < i;) { | |
d = this.BGCHRBank1[b++]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
d = this.tileCache[d]; | |
h = c; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h++]]; | |
this.frameBuffer[f++] = this.BGPalette[d[h]] | |
} | |
if (f < a) { | |
d = this.BGCHRBank1[b]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
d = this.tileCache[d]; | |
switch (a - f) { | |
case 7: | |
this.frameBuffer[f + 6] = this.BGPalette[d[c | 6]]; | |
case 6: | |
this.frameBuffer[f + 5] = this.BGPalette[d[c | 5]]; | |
case 5: | |
this.frameBuffer[f + 4] = this.BGPalette[d[c | 4]]; | |
case 4: | |
this.frameBuffer[f + 3] = this.BGPalette[d[c | 3]]; | |
case 3: | |
this.frameBuffer[f + 2] = this.BGPalette[d[c | 2]]; | |
case 2: | |
this.frameBuffer[f + 1] = this.BGPalette[d[c | 1]]; | |
case 1: | |
this.frameBuffer[f] = this.BGPalette[d[c]] | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.BGGBCLayerRender = function (a) { | |
var b = this.backgroundY + a & 255, | |
c = (b & 7) << 3, | |
b = this.gfxBackgroundCHRBankPosition | (b & 248) << 2, | |
e = this.backgroundX + this.currentX & 255, | |
f = this.pixelStart + this.currentX, | |
a = this.pixelStart + (this.gfxWindowDisplay && a - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd), | |
g = b + (e >> 3), | |
d = this.BGCHRBank1[g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
for (var h = this.BGCHRBank2[g], d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d], h = (h & 7) << 2 | (h & 128) >> 2, i = e & 7; i < 8 && f < a && e < 256; ++e) this.frameBuffer[f++] = this.gbcBGPalette[h | d[c | i++]]; | |
for (var j = Math.min(a - f, 256 - e) >> 3, e = e + (j << 3), j = j + g; g < j;) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[g]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2 | (h & 128) >> 2; | |
i = c; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i]] | |
} | |
if (f < a) { | |
if (e < 256) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[g]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2 | (h & 128) >> 2; | |
for (i = c - 1; f < a && e < 256; ++e) this.frameBuffer[f++] = this.gbcBGPalette[h | d[++i]] | |
} | |
for (j = (a - f >> 3) + b; b < j;) { | |
d = this.BGCHRBank1[b]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[b++]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2 | (h & 128) >> 2; | |
i = c; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i]] | |
} | |
if (f < a) { | |
d = this.BGCHRBank1[b]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[b]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2 | (h & 128) >> 2; | |
switch (a - f) { | |
case 7: | |
this.frameBuffer[f + 6] = this.gbcBGPalette[h | d[c | 6]]; | |
case 6: | |
this.frameBuffer[f + 5] = this.gbcBGPalette[h | d[c | 5]]; | |
case 5: | |
this.frameBuffer[f + 4] = this.gbcBGPalette[h | d[c | 4]]; | |
case 4: | |
this.frameBuffer[f + 3] = this.gbcBGPalette[h | d[c | 3]]; | |
case 3: | |
this.frameBuffer[f + 2] = this.gbcBGPalette[h | d[c | 2]]; | |
case 2: | |
this.frameBuffer[f + 1] = this.gbcBGPalette[h | d[c | 1]]; | |
case 1: | |
this.frameBuffer[f] = this.gbcBGPalette[h | d[c]] | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.BGGBCLayerRenderNoPriorityFlagging = function (a) { | |
var b = this.backgroundY + a & 255, | |
c = (b & 7) << 3, | |
b = this.gfxBackgroundCHRBankPosition | (b & 248) << 2, | |
e = this.backgroundX + this.currentX & 255, | |
f = this.pixelStart + this.currentX, | |
a = this.pixelStart + (this.gfxWindowDisplay && a - this.windowY >= 0 ? Math.min(Math.max(this.windowX, 0) + this.currentX, this.pixelEnd) : this.pixelEnd), | |
g = b + (e >> 3), | |
d = this.BGCHRBank1[g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
for (var h = this.BGCHRBank2[g], d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d], h = (h & 7) << 2, i = e & 7; i < 8 && f < a && e < 256; ++e) this.frameBuffer[f++] = this.gbcBGPalette[h | d[c | i++]]; | |
for (var j = Math.min(a - f, 256 - e) >> 3, e = e + (j << 3), j = j + g; g < j;) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[g]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2; | |
i = c; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i]] | |
} | |
if (f < a) { | |
if (e < 256) { | |
d = this.BGCHRBank1[++g]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[g]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2; | |
for (i = c - 1; f < a && e < 256; ++e) this.frameBuffer[f++] = this.gbcBGPalette[h | d[++i]] | |
} | |
for (j = (a - f >> 3) + b; b < j;) { | |
d = this.BGCHRBank1[b]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[b++]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2; | |
i = c; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i++]]; | |
this.frameBuffer[f++] = this.gbcBGPalette[h | d[i]] | |
} | |
if (f < a) { | |
d = this.BGCHRBank1[b]; | |
d < this.gfxBackgroundBankOffset && (d = d | 256); | |
h = this.BGCHRBank2[b]; | |
d = this.tileCache[(h & 8) << 8 | (h & 96) << 4 | d]; | |
h = (h & 7) << 2; | |
switch (a - f) { | |
case 7: | |
this.frameBuffer[f + 6] = this.gbcBGPalette[h | d[c | 6]]; | |
case 6: | |
this.frameBuffer[f + 5] = this.gbcBGPalette[h | d[c | 5]]; | |
case 5: | |
this.frameBuffer[f + 4] = this.gbcBGPalette[h | d[c | 4]]; | |
case 4: | |
this.frameBuffer[f + 3] = this.gbcBGPalette[h | d[c | 3]]; | |
case 3: | |
this.frameBuffer[f + 2] = this.gbcBGPalette[h | d[c | 2]]; | |
case 2: | |
this.frameBuffer[f + 1] = this.gbcBGPalette[h | d[c | 1]]; | |
case 1: | |
this.frameBuffer[f] = this.gbcBGPalette[h | d[c]] | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.WindowGBLayerRender = function (a) { | |
if (this.gfxWindowDisplay) { | |
var b = a - this.windowY; | |
if (b >= 0) { | |
var a = this.windowX > 0 ? this.windowX + this.currentX : this.currentX, | |
c = this.pixelStart + a, | |
e = this.pixelStart + this.pixelEnd; | |
if (c < e) { | |
var f = (b & 7) << 3, | |
b = (this.gfxWindowCHRBankPosition | (b & 248) << 2) + (this.currentX >> 3), | |
g = this.BGCHRBank1[b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
for (var g = this.tileCache[g], d = a - this.windowX & 7, a = Math.min(8, d + e - c); d < a;) this.frameBuffer[c++] = this.BGPalette[g[f | d++]]; | |
for (a = b + (e - c >> 3); b < a;) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
g = this.tileCache[g]; | |
d = f; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d++]]; | |
this.frameBuffer[c++] = this.BGPalette[g[d]] | |
} | |
if (c < e) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
g = this.tileCache[g]; | |
switch (e - c) { | |
case 7: | |
this.frameBuffer[c + 6] = this.BGPalette[g[f | 6]]; | |
case 6: | |
this.frameBuffer[c + 5] = this.BGPalette[g[f | 5]]; | |
case 5: | |
this.frameBuffer[c + 4] = this.BGPalette[g[f | 4]]; | |
case 4: | |
this.frameBuffer[c + 3] = this.BGPalette[g[f | 3]]; | |
case 3: | |
this.frameBuffer[c + 2] = this.BGPalette[g[f | 2]]; | |
case 2: | |
this.frameBuffer[c + 1] = this.BGPalette[g[f | 1]]; | |
case 1: | |
this.frameBuffer[c] = this.BGPalette[g[f]] | |
} | |
} | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.WindowGBCLayerRender = function (a) { | |
if (this.gfxWindowDisplay) { | |
var b = a - this.windowY; | |
if (b >= 0) { | |
var a = this.windowX > 0 ? this.windowX + this.currentX : this.currentX, | |
c = this.pixelStart + a, | |
e = this.pixelStart + this.pixelEnd; | |
if (c < e) { | |
var f = (b & 7) << 3, | |
b = (this.gfxWindowCHRBankPosition | (b & 248) << 2) + (this.currentX >> 3), | |
g = this.BGCHRBank1[b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
for (var d = this.BGCHRBank2[b], g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g], d = (d & 7) << 2 | (d & 128) >> 2, h = a - this.windowX & 7, a = Math.min(8, h + e - c); h < a;) this.frameBuffer[c++] = this.gbcBGPalette[d | g[f | h++]]; | |
for (a = b + (e - c >> 3); b < a;) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
d = this.BGCHRBank2[b]; | |
g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g]; | |
d = (d & 7) << 2 | (d & 128) >> 2; | |
h = f; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h]] | |
} | |
if (c < e) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
d = this.BGCHRBank2[b]; | |
g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g]; | |
d = (d & 7) << 2 | (d & 128) >> 2; | |
switch (e - c) { | |
case 7: | |
this.frameBuffer[c + 6] = this.gbcBGPalette[d | g[f | 6]]; | |
case 6: | |
this.frameBuffer[c + 5] = this.gbcBGPalette[d | g[f | 5]]; | |
case 5: | |
this.frameBuffer[c + 4] = this.gbcBGPalette[d | g[f | 4]]; | |
case 4: | |
this.frameBuffer[c + 3] = this.gbcBGPalette[d | g[f | 3]]; | |
case 3: | |
this.frameBuffer[c + 2] = this.gbcBGPalette[d | g[f | 2]]; | |
case 2: | |
this.frameBuffer[c + 1] = this.gbcBGPalette[d | g[f | 1]]; | |
case 1: | |
this.frameBuffer[c] = this.gbcBGPalette[d | g[f]] | |
} | |
} | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.WindowGBCLayerRenderNoPriorityFlagging = function (a) { | |
if (this.gfxWindowDisplay) { | |
var b = a - this.windowY; | |
if (b >= 0) { | |
var a = this.windowX > 0 ? this.windowX + this.currentX : this.currentX, | |
c = this.pixelStart + a, | |
e = this.pixelStart + this.pixelEnd; | |
if (c < e) { | |
var f = (b & 7) << 3, | |
b = (this.gfxWindowCHRBankPosition | (b & 248) << 2) + (this.currentX >> 3), | |
g = this.BGCHRBank1[b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
for (var d = this.BGCHRBank2[b], g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g], d = (d & 7) << 2, h = a - this.windowX & 7, a = Math.min(8, h + e - c); h < a;) this.frameBuffer[c++] = this.gbcBGPalette[d | g[f | h++]]; | |
for (a = b + (e - c >> 3); b < a;) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
d = this.BGCHRBank2[b]; | |
g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g]; | |
d = (d & 7) << 2; | |
h = f; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h++]]; | |
this.frameBuffer[c++] = this.gbcBGPalette[d | g[h]] | |
} | |
if (c < e) { | |
g = this.BGCHRBank1[++b]; | |
g < this.gfxBackgroundBankOffset && (g = g | 256); | |
d = this.BGCHRBank2[b]; | |
g = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | g]; | |
d = (d & 7) << 2; | |
switch (e - c) { | |
case 7: | |
this.frameBuffer[c + 6] = this.gbcBGPalette[d | g[f | 6]]; | |
case 6: | |
this.frameBuffer[c + 5] = this.gbcBGPalette[d | g[f | 5]]; | |
case 5: | |
this.frameBuffer[c + 4] = this.gbcBGPalette[d | g[f | 4]]; | |
case 4: | |
this.frameBuffer[c + 3] = this.gbcBGPalette[d | g[f | 3]]; | |
case 3: | |
this.frameBuffer[c + 2] = this.gbcBGPalette[d | g[f | 2]]; | |
case 2: | |
this.frameBuffer[c + 1] = this.gbcBGPalette[d | g[f | 1]]; | |
case 1: | |
this.frameBuffer[c] = this.gbcBGPalette[d | g[f]] | |
} | |
} | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.SpriteGBLayerRender = function (a) { | |
if (this.gfxSpriteShow) { | |
for (var a = a + 16, b = 65024, c = 0, b = 1, e = 0, f = 0, g = 0, d = 0, h = null, i = 0, j = 0, q = 0, l = 0, n = 0; b < 168;) this.sortBuffer[b++] = 255; | |
if (this.gfxSpriteNormalHeight) for (q = this.findLowestSpriteDrawable(a, 7); j < q; ++j) { | |
b = this.OAMAddressCache[j]; | |
c = a - this.memory[b] << 3; | |
g = this.memory[b | 3]; | |
d = (g & 16) >> 2; | |
h = this.tileCache[(g & 96) << 4 | this.memory[b | 2]]; | |
n = e = this.memory[b | 1]; | |
f = Math.min(168 - n, 8); | |
b = n > 7 ? 0 : 8 - n; | |
for (l = this.pixelStart + (n > 8 ? n - 8 : 0); b < f; ++b, ++l, ++n) if (this.sortBuffer[n] > e) if (this.frameBuffer[l] >= 33554432) { | |
i = h[c | b]; | |
if (i > 0) { | |
this.frameBuffer[l] = this.OBJPalette[d | i]; | |
this.sortBuffer[n] = e | |
} | |
} else if (this.frameBuffer[l] < 16777216) { | |
i = h[c | b]; | |
if (i > 0 && g < 128) { | |
this.frameBuffer[l] = this.OBJPalette[d | i]; | |
this.sortBuffer[n] = e | |
} | |
} | |
} else for (q = this.findLowestSpriteDrawable(a, 15); j < q; ++j) { | |
b = this.OAMAddressCache[j]; | |
c = a - this.memory[b] << 3; | |
g = this.memory[b | 3]; | |
d = (g & 16) >> 2; | |
h = (g & 64) == (64 & c) ? this.tileCache[(g & 96) << 4 | this.memory[b | 2] & 254] : this.tileCache[(g & 96) << 4 | this.memory[b | 2] | 1]; | |
c = c & 63; | |
n = e = this.memory[b | 1]; | |
f = Math.min(168 - n, 8); | |
b = n > 7 ? 0 : 8 - n; | |
for (l = this.pixelStart + (n > 8 ? n - 8 : 0); b < f; ++b, ++l, ++n) if (this.sortBuffer[n] > e) if (this.frameBuffer[l] >= 33554432) { | |
i = h[c | b]; | |
if (i > 0) { | |
this.frameBuffer[l] = this.OBJPalette[d | i]; | |
this.sortBuffer[n] = e | |
} | |
} else if (this.frameBuffer[l] < 16777216) { | |
i = h[c | b]; | |
if (i > 0 && g < 128) { | |
this.frameBuffer[l] = this.OBJPalette[d | i]; | |
this.sortBuffer[n] = e | |
} | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.findLowestSpriteDrawable = function (a, b) { | |
for (var c = 65024, e = 0, f = 0; c < 65184 && e < 10;) { | |
f = a - this.memory[c]; | |
(f & b) == f && (this.OAMAddressCache[e++] = c); | |
c = c + 4 | |
} | |
return e | |
}; | |
GameBoyCore.prototype.SpriteGBCLayerRender = function (a) { | |
if (this.gfxSpriteShow) { | |
var b = 65024, | |
a = a + 16, | |
c = 0, | |
e = 0, | |
f = 0, | |
g = 0, | |
d = 0, | |
h = 0, | |
i = null, | |
j = c = 0, | |
q = 0; | |
if (this.gfxSpriteNormalHeight) for (; b < 65184 && q < 10; b = b + 4) { | |
c = a - this.memory[b]; | |
if ((c & 7) == c) { | |
e = this.memory[b | 1] - 8; | |
f = Math.min(160, e + 8); | |
d = this.memory[b | 3]; | |
h = (d & 7) << 2; | |
i = this.tileCache[(d & 8) << 8 | (d & 96) << 4 | this.memory[b | 2]]; | |
g = e > 0 ? e : 0; | |
e = e - (c << 3); | |
for (j = this.pixelStart + g; g < f; ++g, ++j) if (this.frameBuffer[j] >= 33554432) { | |
c = i[g - e]; | |
c > 0 && (this.frameBuffer[j] = this.gbcOBJPalette[h | c]) | |
} else if (this.frameBuffer[j] < 16777216) { | |
c = i[g - e]; | |
c > 0 && d < 128 && (this.frameBuffer[j] = this.gbcOBJPalette[h | c]) | |
}++q | |
} | |
} else for (; b < 65184 && q < 10; b = b + 4) { | |
c = a - this.memory[b]; | |
if ((c & 15) == c) { | |
e = this.memory[b | 1] - 8; | |
f = Math.min(160, e + 8); | |
d = this.memory[b | 3]; | |
h = (d & 7) << 2; | |
i = (d & 64) == (64 & c << 3) ? this.tileCache[(d & 8) << 8 | (d & 96) << 4 | this.memory[b | 2] & 254] : this.tileCache[(d & 8) << 8 | (d & 96) << 4 | this.memory[b | 2] | 1]; | |
g = e > 0 ? e : 0; | |
e = e - ((c & 7) << 3); | |
for (j = this.pixelStart + g; g < f; ++g, ++j) if (this.frameBuffer[j] >= 33554432) { | |
c = i[g - e]; | |
c > 0 && (this.frameBuffer[j] = this.gbcOBJPalette[h | c]) | |
} else if (this.frameBuffer[j] < 16777216) { | |
c = i[g - e]; | |
c > 0 && d < 128 && (this.frameBuffer[j] = this.gbcOBJPalette[h | c]) | |
}++q | |
} | |
} | |
} | |
}; | |
GameBoyCore.prototype.generateGBTileLine = function (a) { | |
var b = this.memory[1 | a] << 8 | this.memory[40958 & a], | |
c = this.tileCache[(a & 8176) >> 4], | |
a = (a & 14) << 2; | |
c[a | 7] = (b & 256) >> 7 | b & 1; | |
c[a | 6] = (b & 512) >> 8 | (b & 2) >> 1; | |
c[a | 5] = (b & 1024) >> 9 | (b & 4) >> 2; | |
c[a | 4] = (b & 2048) >> 10 | (b & 8) >> 3; | |
c[a | 3] = (b & 4096) >> 11 | (b & 16) >> 4; | |
c[a | 2] = (b & 8192) >> 12 | (b & 32) >> 5; | |
c[a | 1] = (b & 16384) >> 13 | (b & 64) >> 6; | |
c[a] = (b & 32768) >> 14 | (b & 128) >> 7 | |
}; | |
GameBoyCore.prototype.generateGBCTileLineBank1 = function (a) { | |
var b = this.memory[1 | a] << 8 | this.memory[40958 & a], | |
a = a & 8190, | |
c = this.tileCache[a >> 4], | |
e = this.tileCache[512 | a >> 4], | |
f = this.tileCache[1024 | a >> 4], | |
g = this.tileCache[1536 | a >> 4], | |
a = (a & 14) << 2, | |
d = 56 - a; | |
g[d] = e[a] = f[d | 7] = c[a | 7] = (b & 256) >> 7 | b & 1; | |
g[d | 1] = e[a | 1] = f[d | 6] = c[a | 6] = (b & 512) >> 8 | (b & 2) >> 1; | |
g[d | 2] = e[a | 2] = f[d | 5] = c[a | 5] = (b & 1024) >> 9 | (b & 4) >> 2; | |
g[d | 3] = e[a | 3] = f[d | 4] = c[a | 4] = (b & 2048) >> 10 | (b & 8) >> 3; | |
g[d | 4] = e[a | 4] = f[d | 3] = c[a | 3] = (b & 4096) >> 11 | (b & 16) >> 4; | |
g[d | 5] = e[a | 5] = f[d | 2] = c[a | 2] = (b & 8192) >> 12 | (b & 32) >> 5; | |
g[d | 6] = e[a | 6] = f[d | 1] = c[a | 1] = (b & 16384) >> 13 | (b & 64) >> 6; | |
g[d | 7] = e[a | 7] = f[d] = c[a] = (b & 32768) >> 14 | (b & 128) >> 7 | |
}; | |
GameBoyCore.prototype.generateGBCTileBank1 = function (a) { | |
var b = a >> 4, | |
c = this.tileCache[b], | |
e = this.tileCache[512 | b], | |
f = this.tileCache[1024 | b], | |
g = this.tileCache[1536 | b], | |
d = 0, | |
a = a | 32768, | |
b = 0, | |
h = 56; | |
do { | |
d = this.memory[1 | a] << 8 | this.memory[a]; | |
g[h] = e[b] = f[h | 7] = c[b | 7] = (d & 256) >> 7 | d & 1; | |
g[h | 1] = e[b | 1] = f[h | 6] = c[b | 6] = (d & 512) >> 8 | (d & 2) >> 1; | |
g[h | 2] = e[b | 2] = f[h | 5] = c[b | 5] = (d & 1024) >> 9 | (d & 4) >> 2; | |
g[h | 3] = e[b | 3] = f[h | 4] = c[b | 4] = (d & 2048) >> 10 | (d & 8) >> 3; | |
g[h | 4] = e[b | 4] = f[h | 3] = c[b | 3] = (d & 4096) >> 11 | (d & 16) >> 4; | |
g[h | 5] = e[b | 5] = f[h | 2] = c[b | 2] = (d & 8192) >> 12 | (d & 32) >> 5; | |
g[h | 6] = e[b | 6] = f[h | 1] = c[b | 1] = (d & 16384) >> 13 | (d & 64) >> 6; | |
g[h | 7] = e[b | 7] = f[h] = c[b] = (d & 32768) >> 14 | (d & 128) >> 7; | |
b = b + 8; | |
h = h - 8; | |
a = a + 2 | |
} while (h > -1) | |
}; | |
GameBoyCore.prototype.generateGBCTileLineBank2 = function (a) { | |
var b = this.VRAM[1 | a] << 8 | this.VRAM[8190 & a], | |
c = this.tileCache[2048 | a >> 4], | |
e = this.tileCache[2560 | a >> 4], | |
f = this.tileCache[3072 | a >> 4], | |
g = this.tileCache[3584 | a >> 4], | |
a = (a & 14) << 2, | |
d = 56 - a; | |
g[d] = e[a] = f[d | 7] = c[a | 7] = (b & 256) >> 7 | b & 1; | |
g[d | 1] = e[a | 1] = f[d | 6] = c[a | 6] = (b & 512) >> 8 | (b & 2) >> 1; | |
g[d | 2] = e[a | 2] = f[d | 5] = c[a | 5] = (b & 1024) >> 9 | (b & 4) >> 2; | |
g[d | 3] = e[a | 3] = f[d | 4] = c[a | 4] = (b & 2048) >> 10 | (b & 8) >> 3; | |
g[d | 4] = e[a | 4] = f[d | 3] = c[a | 3] = (b & 4096) >> 11 | (b & 16) >> 4; | |
g[d | 5] = e[a | 5] = f[d | 2] = c[a | 2] = (b & 8192) >> 12 | (b & 32) >> 5; | |
g[d | 6] = e[a | 6] = f[d | 1] = c[a | 1] = (b & 16384) >> 13 | (b & 64) >> 6; | |
g[d | 7] = e[a | 7] = f[d] = c[a] = (b & 32768) >> 14 | (b & 128) >> 7 | |
}; | |
GameBoyCore.prototype.generateGBCTileBank2 = function (a) { | |
var b = a >> 4, | |
c = this.tileCache[2048 | b], | |
e = this.tileCache[2560 | b], | |
f = this.tileCache[3072 | b], | |
g = this.tileCache[3584 | b], | |
d = 0, | |
b = 0, | |
h = 56; | |
do { | |
d = this.VRAM[1 | a] << 8 | this.VRAM[a]; | |
g[h] = e[b] = f[h | 7] = c[b | 7] = (d & 256) >> 7 | d & 1; | |
g[h | 1] = e[b | 1] = f[h | 6] = c[b | 6] = (d & 512) >> 8 | (d & 2) >> 1; | |
g[h | 2] = e[b | 2] = f[h | 5] = c[b | 5] = (d & 1024) >> 9 | (d & 4) >> 2; | |
g[h | 3] = e[b | 3] = f[h | 4] = c[b | 4] = (d & 2048) >> 10 | (d & 8) >> 3; | |
g[h | 4] = e[b | 4] = f[h | 3] = c[b | 3] = (d & 4096) >> 11 | (d & 16) >> 4; | |
g[h | 5] = e[b | 5] = f[h | 2] = c[b | 2] = (d & 8192) >> 12 | (d & 32) >> 5; | |
g[h | 6] = e[b | 6] = f[h | 1] = c[b | 1] = (d & 16384) >> 13 | (d & 64) >> 6; | |
g[h | 7] = e[b | 7] = f[h] = c[b] = (d & 32768) >> 14 | (d & 128) >> 7; | |
b = b + 8; | |
h = h - 8; | |
a = a + 2 | |
} while (h > -1) | |
}; | |
GameBoyCore.prototype.generateGBOAMTileLine = function (a) { | |
var b = this.memory[1 | a] << 8 | this.memory[40958 & a], | |
a = a & 8190, | |
c = this.tileCache[a >> 4], | |
e = this.tileCache[512 | a >> 4], | |
f = this.tileCache[1024 | a >> 4], | |
g = this.tileCache[1536 | a >> 4], | |
a = (a & 14) << 2, | |
d = 56 - a; | |
g[d] = e[a] = f[d | 7] = c[a | 7] = (b & 256) >> 7 | b & 1; | |
g[d | 1] = e[a | 1] = f[d | 6] = c[a | 6] = (b & 512) >> 8 | (b & 2) >> 1; | |
g[d | 2] = e[a | 2] = f[d | 5] = c[a | 5] = (b & 1024) >> 9 | (b & 4) >> 2; | |
g[d | 3] = e[a | 3] = f[d | 4] = c[a | 4] = (b & 2048) >> 10 | (b & 8) >> 3; | |
g[d | 4] = e[a | 4] = f[d | 3] = c[a | 3] = (b & 4096) >> 11 | (b & 16) >> 4; | |
g[d | 5] = e[a | 5] = f[d | 2] = c[a | 2] = (b & 8192) >> 12 | (b & 32) >> 5; | |
g[d | 6] = e[a | 6] = f[d | 1] = c[a | 1] = (b & 16384) >> 13 | (b & 64) >> 6; | |
g[d | 7] = e[a | 7] = f[d] = c[a] = (b & 32768) >> 14 | (b & 128) >> 7 | |
}; | |
GameBoyCore.prototype.graphicsJIT = function () { | |
if (this.LCDisOn) { | |
this.totalLinesPassed = 0; | |
this.graphicsJITScanlineGroup() | |
} | |
}; | |
GameBoyCore.prototype.graphicsJITVBlank = function () { | |
this.totalLinesPassed = this.totalLinesPassed + this.queuedScanLines; | |
this.graphicsJITScanlineGroup() | |
}; | |
GameBoyCore.prototype.graphicsJITScanlineGroup = function () { | |
for (; this.queuedScanLines > 0;) { | |
this.renderScanLine(this.lastUnrenderedLine); | |
this.lastUnrenderedLine < 143 ? ++this.lastUnrenderedLine : this.lastUnrenderedLine = 0; | |
--this.queuedScanLines | |
} | |
}; | |
GameBoyCore.prototype.incrementScanLineQueue = function () { | |
if (this.queuedScanLines < 144)++this.queuedScanLines; | |
else { | |
this.currentX = 0; | |
this.midScanlineOffset = -1; | |
this.lastUnrenderedLine < 143 ? ++this.lastUnrenderedLine : this.lastUnrenderedLine = 0 | |
} | |
}; | |
GameBoyCore.prototype.midScanLineJIT = function () { | |
this.graphicsJIT(); | |
this.renderMidScanLine() | |
}; | |
GameBoyCore.prototype.launchIRQ = function () { | |
var a = 0, | |
b = 1; | |
do { | |
if ((b & this.IRQLineMatched) == b) { | |
this.IME = false; | |
this.interruptsRequested = this.interruptsRequested - b; | |
this.IRQLineMatched = 0; | |
this.CPUTicks = 20; | |
this.stackPointer = this.stackPointer - 1 & 65535; | |
this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter >> 8); | |
this.stackPointer = this.stackPointer - 1 & 65535; | |
this.memoryWriter[this.stackPointer](this, this.stackPointer, this.programCounter & 255); | |
this.programCounter = 64 | a << 3; | |
this.updateCore(); | |
break | |
} | |
b = 1 << ++a | |
} while (a < 5) | |
}; | |
GameBoyCore.prototype.checkIRQMatching = function () { | |
if (this.IME) this.IRQLineMatched = this.interruptsEnabled & this.interruptsRequested & 31 | |
}; | |
GameBoyCore.prototype.calculateHALTPeriod = function () { | |
if (this.halt) a = this.remainingClocks; | |
else { | |
this.halt = true; | |
var a = -1, | |
b = 0; | |
if (this.LCDisOn) { | |
(this.interruptsEnabled & 1) == 1 && (a = 456 * ((this.modeSTAT == 1 ? 298 : 144) - this.actualScanLine) - this.LCDTicks << this.doubleSpeedShifter); | |
if ((this.interruptsEnabled & 2) == 2) { | |
if (this.mode0TriggerSTAT) { | |
b = this.clocksUntilMode0() - this.LCDTicks << this.doubleSpeedShifter; | |
if (b <= a || a == -1) a = b | |
} | |
if (this.mode1TriggerSTAT && (this.interruptsEnabled & 1) == 0) { | |
b = 456 * ((this.modeSTAT == 1 ? 298 : 144) - this.actualScanLine) - this.LCDTicks << this.doubleSpeedShifter; | |
if (b <= a || a == -1) a = b | |
} | |
if (this.mode2TriggerSTAT) { | |
b = (this.actualScanLine >= 143 ? 456 * (154 - this.actualScanLine) : 456) - this.LCDTicks << this.doubleSpeedShifter; | |
if (b <= a || a == -1) a = b | |
} | |
if (this.LYCMatchTriggerSTAT && this.memory[65349] <= 153) { | |
b = this.clocksUntilLYCMatch() - this.LCDTicks << this.doubleSpeedShifter; | |
if (b <= a || a == -1) a = b | |
} | |
} | |
} | |
if (this.TIMAEnabled && (this.interruptsEnabled & 4) == 4) { | |
b = (256 - this.memory[65285]) * this.TACClocker - this.timerTicks; | |
if (b <= a || a == -1) a = b | |
} | |
if (this.serialTimer > 0 && (this.interruptsEnabled & 8) == 8 && (this.serialTimer <= a || a == -1)) a = this.serialTimer | |
} | |
b = this.CPUCyclesTotal - this.emulatorTicks << this.doubleSpeedShifter; | |
if (a >= 0) if (a <= b) { | |
this.CPUTicks = Math.max(a, this.CPUTicks); | |
this.updateCoreFull(); | |
this.halt = false; | |
this.CPUTicks = 0 | |
} else { | |
this.CPUTicks = Math.max(b, this.CPUTicks); | |
this.remainingClocks = a - this.CPUTicks | |
} else this.CPUTicks = this.CPUTicks + b | |
}; | |
GameBoyCore.prototype.memoryRead = function (a) { | |
return this.memoryReader[a](this, a) | |
}; | |
GameBoyCore.prototype.memoryHighRead = function (a) { | |
return this.memoryHighReader[a](this, a) | |
}; | |
GameBoyCore.prototype.memoryReadJumpCompile = function () { | |
for (var a = 0; a <= 65535; a++) if (a < 16384) this.memoryReader[a] = this.memoryReadNormal; | |
else if (a < 32768) this.memoryReader[a] = this.memoryReadROM; | |
else if (a < 38912) this.memoryReader[a] = this.cGBC ? this.VRAMDATAReadCGBCPU : this.VRAMDATAReadDMGCPU; | |
else if (a < 40960) this.memoryReader[a] = this.cGBC ? this.VRAMCHRReadCGBCPU : this.VRAMCHRReadDMGCPU; | |
else if (a >= 40960 && a < 49152) this.memoryReader[a] = this.numRAMBanks == 0.0625 && a < 41472 || this.numRAMBanks >= 1 ? this.cMBC7 ? this.memoryReadMBC7 : this.cMBC3 ? this.memoryReadMBC3 : this.memoryReadMBC : this.memoryReadBAD; | |
else if (a >= 49152 && a < 57344) this.memoryReader[a] = !this.cGBC || a < 53248 ? this.memoryReadNormal : this.memoryReadGBCMemory; | |
else if (a >= 57344 && a < 65024) this.memoryReader[a] = !this.cGBC || a < 61440 ? this.memoryReadECHONormal : this.memoryReadECHOGBCMemory; | |
else if (a < 65184) this.memoryReader[a] = this.memoryReadOAM; | |
else if (this.cGBC && a >= 65184 && a < 65280) this.memoryReader[a] = this.memoryReadNormal; | |
else if (a >= 65280) switch (a) { | |
case 65280: | |
this.memoryHighReader[0] = this.memoryReader[65280] = function (a) { | |
return 192 | a.memory[65280] | |
}; | |
break; | |
case 65281: | |
this.memoryHighReader[1] = this.memoryReader[65281] = function (a) { | |
return a.memory[65282] < 128 ? a.memory[65281] : 255 | |
}; | |
break; | |
case 65282: | |
this.memoryHighReader[2] = this.cGBC ? this.memoryReader[65282] = function (a) { | |
return (a.serialTimer <= 0 ? 124 : 252) | a.memory[65282] | |
} : this.memoryReader[65282] = function (a) { | |
return (a.serialTimer <= 0 ? 126 : 254) | a.memory[65282] | |
}; | |
break; | |
case 65284: | |
this.memoryHighReader[4] = this.memoryReader[65284] = function (a) { | |
a.memory[65284] = a.memory[65284] + (a.DIVTicks >> 8) & 255; | |
a.DIVTicks = a.DIVTicks & 255; | |
return a.memory[65284] | |
}; | |
break; | |
case 65287: | |
this.memoryHighReader[7] = this.memoryReader[65287] = function (a) { | |
return 248 | a.memory[65287] | |
}; | |
break; | |
case 65295: | |
this.memoryHighReader[15] = this.memoryReader[65295] = function (a) { | |
return 224 | a.interruptsRequested | |
}; | |
break; | |
case 65296: | |
this.memoryHighReader[16] = this.memoryReader[65296] = function (a) { | |
return 128 | a.memory[65296] | |
}; | |
break; | |
case 65297: | |
this.memoryHighReader[17] = this.memoryReader[65297] = function (a) { | |
return 63 | a.memory[65297] | |
}; | |
break; | |
case 65299: | |
this.memoryHighReader[19] = this.memoryReader[65299] = this.memoryReadBAD; | |
break; | |
case 65300: | |
this.memoryHighReader[20] = this.memoryReader[65300] = function (a) { | |
return 191 | a.memory[65300] | |
}; | |
break; | |
case 65302: | |
this.memoryHighReader[22] = this.memoryReader[65302] = function (a) { | |
return 63 | a.memory[65302] | |
}; | |
break; | |
case 65304: | |
this.memoryHighReader[24] = this.memoryReader[65304] = this.memoryReadBAD; | |
break; | |
case 65305: | |
this.memoryHighReader[25] = this.memoryReader[65305] = function (a) { | |
return 191 | a.memory[65305] | |
}; | |
break; | |
case 65306: | |
this.memoryHighReader[26] = this.memoryReader[65306] = function (a) { | |
return 127 | a.memory[65306] | |
}; | |
break; | |
case 65307: | |
this.memoryHighReader[27] = this.memoryReader[65307] = this.memoryReadBAD; | |
break; | |
case 65308: | |
this.memoryHighReader[28] = this.memoryReader[65308] = function (a) { | |
return 159 | a.memory[65308] | |
}; | |
break; | |
case 65309: | |
this.memoryHighReader[29] = this.memoryReader[65309] = function () { | |
return 255 | |
}; | |
break; | |
case 65310: | |
this.memoryHighReader[30] = this.memoryReader[65310] = function (a) { | |
return 191 | a.memory[65310] | |
}; | |
break; | |
case 65311: | |
case 65312: | |
this.memoryHighReader[a & 255] = this.memoryReader[a] = this.memoryReadBAD; | |
break; | |
case 65315: | |
this.memoryHighReader[35] = this.memoryReader[65315] = function (a) { | |
return 191 | a.memory[65315] | |
}; | |
break; | |
case 65318: | |
this.memoryHighReader[38] = this.memoryReader[65318] = function (a) { | |
a.audioJIT(); | |
return 112 | a.memory[65318] | |
}; | |
break; | |
case 65319: | |
case 65320: | |
case 65321: | |
case 65322: | |
case 65323: | |
case 65324: | |
case 65325: | |
case 65326: | |
case 65327: | |
this.memoryHighReader[a & 255] = this.memoryReader[a] = this.memoryReadBAD; | |
break; | |
case 65328: | |
case 65329: | |
case 65330: | |
case 65331: | |
case 65332: | |
case 65333: | |
case 65334: | |
case 65335: | |
case 65336: | |
case 65337: | |
case 65338: | |
case 65339: | |
case 65340: | |
case 65341: | |
case 65342: | |
case 65343: | |
this.memoryReader[a] = function (a, c) { | |
return a.channel3canPlay ? a.memory[65280 | a.channel3lastSampleLookup >> 1] : a.memory[c] | |
}; | |
this.memoryHighReader[a & 255] = function (a, c) { | |
return a.channel3canPlay ? a.memory[65280 | a.channel3lastSampleLookup >> 1] : a.memory[65280 | c] | |
}; | |
break; | |
case 65345: | |
this.memoryHighReader[65] = this.memoryReader[65345] = function (a) { | |
return 128 | a.memory[65345] | a.modeSTAT | |
}; | |
break; | |
case 65346: | |
this.memoryHighReader[66] = this.memoryReader[65346] = function (a) { | |
return a.backgroundY | |
}; | |
break; | |
case 65347: | |
this.memoryHighReader[67] = this.memoryReader[65347] = function (a) { | |
return a.backgroundX | |
}; | |
break; | |
case 65348: | |
this.memoryHighReader[68] = this.memoryReader[65348] = function (a) { | |
return a.LCDisOn ? a.memory[65348] : 0 | |
}; | |
break; | |
case 65354: | |
this.memoryHighReader[74] = this.memoryReader[65354] = function (a) { | |
return a.windowY | |
}; | |
break; | |
case 65359: | |
this.memoryHighReader[79] = this.memoryReader[65359] = function (a) { | |
return a.currVRAMBank | |
}; | |
break; | |
case 65365: | |
if (this.cGBC) this.memoryHighReader[85] = this.memoryReader[65365] = function (a) { | |
if (!a.LCDisOn && a.hdmaRunning) { | |
a.DMAWrite((a.memory[65365] & 127) + 1); | |
a.memory[65365] = 255; | |
a.hdmaRunning = false | |
} | |
return a.memory[65365] | |
}; | |
else { | |
this.memoryReader[65365] = this.memoryReadNormal; | |
this.memoryHighReader[85] = this.memoryHighReadNormal | |
} | |
break; | |
case 65366: | |
if (this.cGBC) this.memoryHighReader[86] = this.memoryReader[65366] = function (a) { | |
return 60 | (a.memory[65366] >= 192 ? 2 | a.memory[65366] & 193 : a.memory[65366] & 195) | |
}; | |
else { | |
this.memoryReader[65366] = this.memoryReadNormal; | |
this.memoryHighReader[86] = this.memoryHighReadNormal | |
} | |
break; | |
case 65388: | |
this.memoryHighReader[108] = this.cGBC ? this.memoryReader[65388] = function (a) { | |
return 254 | a.memory[65388] | |
} : this.memoryReader[65388] = this.memoryReadBAD; | |
break; | |
case 65392: | |
this.memoryHighReader[112] = this.cGBC ? this.memoryReader[65392] = function (a) { | |
return 64 | a.memory[65392] | |
} : this.memoryReader[65392] = this.memoryReadBAD; | |
break; | |
case 65397: | |
this.memoryHighReader[117] = this.memoryReader[65397] = function (a) { | |
return 143 | a.memory[65397] | |
}; | |
break; | |
case 65398: | |
case 65399: | |
this.memoryHighReader[a & 255] = this.memoryReader[a] = function () { | |
return 0 | |
}; | |
break; | |
case 65535: | |
this.memoryHighReader[255] = this.memoryReader[65535] = function (a) { | |
return a.interruptsEnabled | |
}; | |
break; | |
default: | |
this.memoryReader[a] = this.memoryReadNormal; | |
this.memoryHighReader[a & 255] = this.memoryHighReadNormal | |
} else this.memoryReader[a] = this.memoryReadBAD | |
}; | |
GameBoyCore.prototype.memoryReadNormal = function (a, b) { | |
return a.memory[b] | |
}; | |
GameBoyCore.prototype.memoryHighReadNormal = function (a, b) { | |
return a.memory[65280 | b] | |
}; | |
GameBoyCore.prototype.memoryReadROM = function (a, b) { | |
return a.ROM[a.currentROMBank + b] | |
}; | |
GameBoyCore.prototype.memoryReadMBC = function (a, b) { | |
return a.MBCRAMBanksEnabled || settings[10] ? a.MBCRam[b + a.currMBCRAMBankPosition] : 255 | |
}; | |
GameBoyCore.prototype.memoryReadMBC7 = function (a, b) { | |
if (a.MBCRAMBanksEnabled || settings[10]) switch (b) { | |
case 40960: | |
case 41056: | |
case 41072: | |
return 0; | |
case 41088: | |
return 0; | |
case 41040: | |
return a.highY; | |
case 41024: | |
return a.lowY; | |
case 41008: | |
return a.highX; | |
case 40992: | |
return a.lowX; | |
default: | |
return a.MBCRam[b + a.currMBCRAMBankPosition] | |
} | |
return 255 | |
}; | |
GameBoyCore.prototype.memoryReadMBC3 = function (a, b) { | |
if (a.MBCRAMBanksEnabled || settings[10]) switch (a.currMBCRAMBank) { | |
case 0: | |
case 1: | |
case 2: | |
case 3: | |
return a.MBCRam[b + a.currMBCRAMBankPosition]; | |
case 8: | |
return a.latchedSeconds; | |
case 9: | |
return a.latchedMinutes; | |
case 10: | |
return a.latchedHours; | |
case 11: | |
return a.latchedLDays; | |
case 12: | |
return (a.RTCDayOverFlow ? 128 : 0) + (a.RTCHALT ? 64 : 0) + a.latchedHDays | |
} | |
return 255 | |
}; | |
GameBoyCore.prototype.memoryReadGBCMemory = function (a, b) { | |
return a.GBCMemory[b + a.gbcRamBankPosition] | |
}; | |
GameBoyCore.prototype.memoryReadOAM = function (a, b) { | |
return a.modeSTAT > 1 ? 255 : a.memory[b] | |
}; | |
GameBoyCore.prototype.memoryReadECHOGBCMemory = function (a, b) { | |
return a.GBCMemory[b + a.gbcRamBankPositionECHO] | |
}; | |
GameBoyCore.prototype.memoryReadECHONormal = function (a, b) { | |
return a.memory[b - 8192] | |
}; | |
GameBoyCore.prototype.memoryReadBAD = function () { | |
return 255 | |
}; | |
GameBoyCore.prototype.VRAMDATAReadCGBCPU = function (a, b) { | |
return a.modeSTAT > 2 ? 255 : a.currVRAMBank == 0 ? a.memory[b] : a.VRAM[b & 8191] | |
}; | |
GameBoyCore.prototype.VRAMDATAReadDMGCPU = function (a, b) { | |
return a.modeSTAT > 2 ? 255 : a.memory[b] | |
}; | |
GameBoyCore.prototype.VRAMCHRReadCGBCPU = function (a, b) { | |
return a.modeSTAT > 2 ? 255 : a.BGCHRCurrentBank[b & 2047] | |
}; | |
GameBoyCore.prototype.VRAMCHRReadDMGCPU = function (a, b) { | |
return a.modeSTAT > 2 ? 255 : a.BGCHRBank1[b & 2047] | |
}; | |
GameBoyCore.prototype.setCurrentMBC1ROMBank = function () { | |
switch (this.ROMBank1offs) { | |
case 0: | |
case 32: | |
case 64: | |
case 96: | |
this.currentROMBank = this.ROMBank1offs % this.ROMBankEdge << 14; | |
break; | |
default: | |
this.currentROMBank = this.ROMBank1offs % this.ROMBankEdge - 1 << 14 | |
} | |
}; | |
GameBoyCore.prototype.setCurrentMBC2AND3ROMBank = function () { | |
this.currentROMBank = Math.max(this.ROMBank1offs % this.ROMBankEdge - 1, 0) << 14 | |
}; | |
GameBoyCore.prototype.setCurrentMBC5ROMBank = function () { | |
this.currentROMBank = this.ROMBank1offs % this.ROMBankEdge - 1 << 14 | |
}; | |
GameBoyCore.prototype.memoryWrite = function (a, b) { | |
this.memoryWriter[a](this, a, b) | |
}; | |
GameBoyCore.prototype.memoryHighWrite = function (a, b) { | |
this.memoryHighWriter[a](this, a, b) | |
}; | |
GameBoyCore.prototype.memoryWriteJumpCompile = function () { | |
for (var a = 0; a <= 65535; a++) if (a < 32768) this.memoryWriter[a] = this.cMBC1 ? a < 8192 ? this.MBCWriteEnable : a < 16384 ? this.MBC1WriteROMBank : a < 24576 ? this.MBC1WriteRAMBank : this.MBC1WriteType : this.cMBC2 ? a < 4096 ? this.MBCWriteEnable : a >= 8448 && a < 8704 ? this.MBC2WriteROMBank : this.cartIgnoreWrite : this.cMBC3 ? a < 8192 ? this.MBCWriteEnable : a < 16384 ? this.MBC3WriteROMBank : a < 24576 ? this.MBC3WriteRAMBank : this.MBC3WriteRTCLatch : this.cMBC5 || this.cRUMBLE || this.cMBC7 ? a < 8192 ? this.MBCWriteEnable : a < 12288 ? this.MBC5WriteROMBankLow : a < 16384 ? this.MBC5WriteROMBankHigh : a < 24576 ? this.cRUMBLE ? this.RUMBLEWriteRAMBank : this.MBC5WriteRAMBank : this.cartIgnoreWrite : this.cHuC3 ? a < 8192 ? this.MBCWriteEnable : a < 16384 ? this.MBC3WriteROMBank : a < 24576 ? this.HuC3WriteRAMBank : this.cartIgnoreWrite : this.cartIgnoreWrite; | |
else if (a < 36864) this.memoryWriter[a] = this.cGBC ? this.VRAMGBCDATAWrite : this.VRAMGBDATAWrite; | |
else if (a < 38912) this.memoryWriter[a] = this.cGBC ? this.VRAMGBCDATAWrite : this.VRAMGBDATAUpperWrite; | |
else if (a < 40960) this.memoryWriter[a] = this.cGBC ? this.VRAMGBCCHRMAPWrite : this.VRAMGBCHRMAPWrite; | |
else if (a < 49152) this.memoryWriter[a] = this.numRAMBanks == 0.0625 && a < 41472 || this.numRAMBanks >= 1 ? this.cMBC3 ? this.memoryWriteMBC3RAM : this.memoryWriteMBCRAM : this.cartIgnoreWrite; | |
else if (a < 57344) this.memoryWriter[a] = this.cGBC && a >= 53248 ? this.memoryWriteGBCRAM : this.memoryWriteNormal; | |
else if (a < 65024) this.memoryWriter[a] = this.cGBC && a >= 61440 ? this.memoryWriteECHOGBCRAM : this.memoryWriteECHONormal; | |
else if (a <= 65184) this.memoryWriter[a] = this.memoryWriteOAMRAM; | |
else if (a < 65280) this.memoryWriter[a] = this.cGBC ? this.memoryWriteNormal : this.cartIgnoreWrite; | |
else { | |
this.memoryWriter[a] = this.memoryWriteNormal; | |
this.memoryHighWriter[a & 255] = this.memoryHighWriteNormal | |
} | |
this.registerWriteJumpCompile() | |
}; | |
GameBoyCore.prototype.MBCWriteEnable = function (a, b, c) { | |
a.MBCRAMBanksEnabled = (c & 15) == 10 | |
}; | |
GameBoyCore.prototype.MBC1WriteROMBank = function (a, b, c) { | |
a.ROMBank1offs = a.ROMBank1offs & 96 | c & 31; | |
a.setCurrentMBC1ROMBank() | |
}; | |
GameBoyCore.prototype.MBC1WriteRAMBank = function (a, b, c) { | |
if (a.MBC1Mode) { | |
a.currMBCRAMBank = c & 3; | |
a.currMBCRAMBankPosition = (a.currMBCRAMBank << 13) - 40960 | |
} else { | |
a.ROMBank1offs = (c & 3) << 5 | a.ROMBank1offs & 31; | |
a.setCurrentMBC1ROMBank() | |
} | |
}; | |
GameBoyCore.prototype.MBC1WriteType = function (a, b, c) { | |
a.MBC1Mode = (c & 1) == 1; | |
if (a.MBC1Mode) { | |
a.ROMBank1offs = a.ROMBank1offs & 31; | |
a.setCurrentMBC1ROMBank() | |
} else { | |
a.currMBCRAMBank = 0; | |
a.currMBCRAMBankPosition = -40960 | |
} | |
}; | |
GameBoyCore.prototype.MBC2WriteROMBank = function (a, b, c) { | |
a.ROMBank1offs = c & 15; | |
a.setCurrentMBC2AND3ROMBank() | |
}; | |
GameBoyCore.prototype.MBC3WriteROMBank = function (a, b, c) { | |
a.ROMBank1offs = c & 127; | |
a.setCurrentMBC2AND3ROMBank() | |
}; | |
GameBoyCore.prototype.MBC3WriteRAMBank = function (a, b, c) { | |
a.currMBCRAMBank = c; | |
if (c < 4) a.currMBCRAMBankPosition = (a.currMBCRAMBank << 13) - 40960 | |
}; | |
GameBoyCore.prototype.MBC3WriteRTCLatch = function (a, b, c) { | |
if (c == 0) a.RTCisLatched = false; | |
else if (!a.RTCisLatched) { | |
a.RTCisLatched = true; | |
a.latchedSeconds = a.RTCSeconds | 0; | |
a.latchedMinutes = a.RTCMinutes; | |
a.latchedHours = a.RTCHours; | |
a.latchedLDays = a.RTCDays & 255; | |
a.latchedHDays = a.RTCDays >> 8 | |
} | |
}; | |
GameBoyCore.prototype.MBC5WriteROMBankLow = function (a, b, c) { | |
a.ROMBank1offs = a.ROMBank1offs & 256 | c; | |
a.setCurrentMBC5ROMBank() | |
}; | |
GameBoyCore.prototype.MBC5WriteROMBankHigh = function (a, b, c) { | |
a.ROMBank1offs = (c & 1) << 8 | a.ROMBank1offs & 255; | |
a.setCurrentMBC5ROMBank() | |
}; | |
GameBoyCore.prototype.MBC5WriteRAMBank = function (a, b, c) { | |
a.currMBCRAMBank = c & 15; | |
a.currMBCRAMBankPosition = (a.currMBCRAMBank << 13) - 40960 | |
}; | |
GameBoyCore.prototype.RUMBLEWriteRAMBank = function (a, b, c) { | |
a.currMBCRAMBank = c & 3; | |
a.currMBCRAMBankPosition = (a.currMBCRAMBank << 13) - 40960 | |
}; | |
GameBoyCore.prototype.HuC3WriteRAMBank = function (a, b, c) { | |
a.currMBCRAMBank = c & 3; | |
a.currMBCRAMBankPosition = (a.currMBCRAMBank << 13) - 40960 | |
}; | |
GameBoyCore.prototype.cartIgnoreWrite = function () {}; | |
GameBoyCore.prototype.memoryWriteNormal = function (a, b, c) { | |
a.memory[b] = c | |
}; | |
GameBoyCore.prototype.memoryHighWriteNormal = function (a, b, c) { | |
a.memory[65280 | b] = c | |
}; | |
GameBoyCore.prototype.memoryWriteMBCRAM = function (a, b, c) { | |
if (a.MBCRAMBanksEnabled || settings[10]) a.MBCRam[b + a.currMBCRAMBankPosition] = c | |
}; | |
GameBoyCore.prototype.memoryWriteMBC3RAM = function (a, b, c) { | |
if (a.MBCRAMBanksEnabled || settings[10]) switch (a.currMBCRAMBank) { | |
case 0: | |
case 1: | |
case 2: | |
case 3: | |
a.MBCRam[b + a.currMBCRAMBankPosition] = c; | |
break; | |
case 8: | |
c < 60 ? a.RTCSeconds = c : cout("(Bank #" + a.currMBCRAMBank + ") RTC write out of range: " + c, 1); | |
break; | |
case 9: | |
c < 60 ? a.RTCMinutes = c : cout("(Bank #" + a.currMBCRAMBank + ") RTC write out of range: " + c, 1); | |
break; | |
case 10: | |
c < 24 ? a.RTCHours = c : cout("(Bank #" + a.currMBCRAMBank + ") RTC write out of range: " + c, 1); | |
break; | |
case 11: | |
a.RTCDays = c & 255 | a.RTCDays & 256; | |
break; | |
case 12: | |
a.RTCDayOverFlow = c > 127; | |
a.RTCHalt = (c & 64) == 64; | |
a.RTCDays = (c & 1) << 8 | a.RTCDays & 255; | |
break; | |
default: | |
cout("Invalid MBC3 bank address selected: " + a.currMBCRAMBank, 0) | |
} | |
}; | |
GameBoyCore.prototype.memoryWriteGBCRAM = function (a, b, c) { | |
a.GBCMemory[b + a.gbcRamBankPosition] = c | |
}; | |
GameBoyCore.prototype.memoryWriteOAMRAM = function (a, b, c) { | |
if (a.modeSTAT < 2 && a.memory[b] != c) { | |
a.graphicsJIT(); | |
a.memory[b] = c | |
} | |
}; | |
GameBoyCore.prototype.memoryWriteECHOGBCRAM = function (a, b, c) { | |
a.GBCMemory[b + a.gbcRamBankPositionECHO] = c | |
}; | |
GameBoyCore.prototype.memoryWriteECHONormal = function (a, b, c) { | |
a.memory[b - 8192] = c | |
}; | |
GameBoyCore.prototype.VRAMGBDATAWrite = function (a, b, c) { | |
if (a.modeSTAT < 3 && a.memory[b] != c) { | |
a.graphicsJIT(); | |
a.memory[b] = c; | |
a.generateGBOAMTileLine(b) | |
} | |
}; | |
GameBoyCore.prototype.VRAMGBDATAUpperWrite = function (a, b, c) { | |
if (a.modeSTAT < 3 && a.memory[b] != c) { | |
a.graphicsJIT(); | |
a.memory[b] = c; | |
a.generateGBTileLine(b) | |
} | |
}; | |
GameBoyCore.prototype.VRAMGBCDATAWrite = function (a, b, c) { | |
if (a.modeSTAT < 3) if (a.currVRAMBank == 0) { | |
if (a.memory[b] != c) { | |
a.graphicsJIT(); | |
a.memory[b] = c; | |
a.generateGBCTileLineBank1(b) | |
} | |
} else { | |
b = b & 8191; | |
if (a.VRAM[b] != c) { | |
a.graphicsJIT(); | |
a.VRAM[b] = c; | |
a.generateGBCTileLineBank2(b) | |
} | |
} | |
}; | |
GameBoyCore.prototype.VRAMGBCHRMAPWrite = function (a, b, c) { | |
if (a.modeSTAT < 3) { | |
b = b & 2047; | |
if (a.BGCHRBank1[b] != c) { | |
a.graphicsJIT(); | |
a.BGCHRBank1[b] = c | |
} | |
} | |
}; | |
GameBoyCore.prototype.VRAMGBCCHRMAPWrite = function (a, b, c) { | |
if (a.modeSTAT < 3) { | |
b = b & 2047; | |
if (a.BGCHRCurrentBank[b] != c) { | |
a.graphicsJIT(); | |
a.BGCHRCurrentBank[b] = c | |
} | |
} | |
}; | |
GameBoyCore.prototype.DMAWrite = function (a) { | |
if (!this.halt) this.CPUTicks = this.CPUTicks + (4 | a << 5 << this.doubleSpeedShifter); | |
var b = this.memory[65361] << 8 | this.memory[65362], | |
c = this.memory[65363] << 8 | this.memory[65364], | |
e = this.memoryReader; | |
this.graphicsJIT(); | |
var f = this.memory; | |
if (this.currVRAMBank == 0) { | |
do { | |
if (c < 6144) { | |
f[32768 | c] = e[b](this, b++); | |
f[32769 | c] = e[b](this, b++); | |
f[32770 | c] = e[b](this, b++); | |
f[32771 | c] = e[b](this, b++); | |
f[32772 | c] = e[b](this, b++); | |
f[32773 | c] = e[b](this, b++); | |
f[32774 | c] = e[b](this, b++); | |
f[32775 | c] = e[b](this, b++); | |
f[32776 | c] = e[b](this, b++); | |
f[32777 | c] = e[b](this, b++); | |
f[32778 | c] = e[b](this, b++); | |
f[32779 | c] = e[b](this, b++); | |
f[32780 | c] = e[b](this, b++); | |
f[32781 | c] = e[b](this, b++); | |
f[32782 | c] = e[b](this, b++); | |
f[32783 | c] = e[b](this, b++); | |
this.generateGBCTileBank1(c); | |
c = c + 16 | |
} else { | |
c = c & 2032; | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
this.BGCHRBank1[c++] = e[b](this, b++); | |
c = c + 6144 & 8176 | |
} | |
b = b & 65520;--a | |
} while (a > 0) | |
} else { | |
var g = this.VRAM; | |
do { | |
if (c < 6144) { | |
g[c] = e[b](this, b++); | |
g[c | 1] = e[b](this, b++); | |
g[c | 2] = e[b](this, b++); | |
g[c | 3] = e[b](this, b++); | |
g[c | 4] = e[b](this, b++); | |
g[c | 5] = e[b](this, b++); | |
g[c | 6] = e[b](this, b++); | |
g[c | 7] = e[b](this, b++); | |
g[c | 8] = e[b](this, b++); | |
g[c | 9] = e[b](this, b++); | |
g[c | 10] = e[b](this, b++); | |
g[c | 11] = e[b](this, b++); | |
g[c | 12] = e[b](this, b++); | |
g[c | 13] = e[b](this, b++); | |
g[c | 14] = e[b](this, b++); | |
g[c | 15] = e[b](this, b++); | |
this.generateGBCTileBank2(c); | |
c = c + 16 | |
} else { | |
c = c & 2032; | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
this.BGCHRBank2[c++] = e[b](this, b++); | |
c = c + 6144 & 8176 | |
} | |
b = b & 65520;--a | |
} while (a > 0) | |
} | |
f[65361] = b >> 8; | |
f[65362] = b & 240; | |
f[65363] = c >> 8; | |
f[65364] = c & 240 | |
}; | |
GameBoyCore.prototype.registerWriteJumpCompile = function () { | |
this.memoryHighWriter[0] = this.memoryWriter[65280] = function (a, b, c) { | |
a.memory[65280] = c & 48 | ((c & 32) == 0 ? a.JoyPad >> 4 : 15) & ((c & 16) == 0 ? a.JoyPad & 15 : 15) | |
}; | |
this.memoryHighWriter[1] = this.memoryWriter[65281] = function (a, b, c) { | |
a.memory[65282] < 128 && (a.memory[65281] = c) | |
}; | |
this.memoryHighWriter[4] = this.memoryWriter[65284] = function (a) { | |
a.DIVTicks = a.DIVTicks & 255; | |
a.memory[65284] = 0 | |
}; | |
this.memoryHighWriter[5] = this.memoryWriter[65285] = function (a, b, c) { | |
a.memory[65285] = c | |
}; | |
this.memoryHighWriter[6] = this.memoryWriter[65286] = function (a, b, c) { | |
a.memory[65286] = c | |
}; | |
this.memoryHighWriter[7] = this.memoryWriter[65287] = function (a, b, c) { | |
a.memory[65287] = c & 7; | |
a.TIMAEnabled = (c & 4) == 4; | |
a.TACClocker = Math.pow(4, (c & 3) != 0 ? c & 3 : 4) << 2 | |
}; | |
this.memoryHighWriter[15] = this.memoryWriter[65295] = function (a, b, c) { | |
a.interruptsRequested = c; | |
a.checkIRQMatching() | |
}; | |
this.memoryHighWriter[16] = this.memoryWriter[65296] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (a.channel1decreaseSweep && (c & 8) == 0 && a.channel1numSweep != a.channel1frequencySweepDivider) a.channel1SweepFault = true; | |
a.channel1lastTimeSweep = (c & 112) >> 4; | |
a.channel1frequencySweepDivider = c & 7; | |
a.channel1decreaseSweep = (c & 8) == 8; | |
a.memory[65296] = c; | |
a.channel1EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[17] = this.memoryWriter[65297] = function (a, b, c) { | |
if (a.soundMasterEnabled || !a.cGBC) { | |
a.soundMasterEnabled ? a.audioJIT() : c = c & 63; | |
a.channel1CachedDuty = a.dutyLookup[c >> 6]; | |
a.channel1totalLength = 64 - (c & 63); | |
a.memory[65297] = c & 192; | |
a.channel1EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[18] = this.memoryWriter[65298] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (a.channel1Enabled && a.channel1envelopeSweeps == 0) { | |
if (((a.memory[65298] ^ c) & 8) == 8) { | |
if ((a.memory[65298] & 8) == 0)(a.memory[65298] & 7) == 7 ? a.channel1envelopeVolume = a.channel1envelopeVolume + 2 : ++a.channel1envelopeVolume; | |
a.channel1envelopeVolume = 16 - a.channel1envelopeVolume & 15 | |
} else if ((a.memory[65298] & 15) == 8) a.channel1envelopeVolume = 1 + a.channel1envelopeVolume & 15; | |
a.channel1OutputLevelCache() | |
} | |
a.channel1envelopeType = (c & 8) == 8; | |
a.memory[65298] = c; | |
a.channel1VolumeEnableCheck() | |
} | |
}; | |
this.memoryHighWriter[19] = this.memoryWriter[65299] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.channel1frequency = a.channel1frequency & 1792 | c; | |
a.channel1FrequencyTracker = 2048 - a.channel1frequency << 2; | |
a.memory[65299] = c | |
} | |
}; | |
this.memoryHighWriter[20] = this.memoryWriter[65300] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.channel1consecutive = (c & 64) == 0; | |
a.channel1frequency = (c & 7) << 8 | a.channel1frequency & 255; | |
a.channel1FrequencyTracker = 2048 - a.channel1frequency << 2; | |
if (c > 127) { | |
a.channel1timeSweep = a.channel1lastTimeSweep; | |
a.channel1numSweep = a.channel1frequencySweepDivider; | |
b = a.memory[65298]; | |
a.channel1envelopeVolume = b >> 4; | |
a.channel1OutputLevelCache(); | |
a.channel1envelopeSweepsLast = (b & 7) - 1; | |
if (a.channel1totalLength == 0) a.channel1totalLength = 64; | |
a.memory[65318] = a.channel1lastTimeSweep > 0 || a.channel1frequencySweepDivider > 0 ? a.memory[65318] | 1 : a.memory[65318] & 254; | |
(c & 64) == 64 && (a.memory[65318] = a.memory[65318] | 1); | |
a.channel1ShadowFrequency = a.channel1frequency; | |
a.channel1SweepFault = false; | |
a.channel1AudioSweepPerformDummy() | |
} | |
a.channel1EnableCheck(); | |
a.memory[65300] = c & 64 | |
} | |
}; | |
this.memoryHighWriter[22] = this.memoryWriter[65302] = function (a, b, c) { | |
if (a.soundMasterEnabled || !a.cGBC) { | |
a.soundMasterEnabled ? a.audioJIT() : c = c & 63; | |
a.channel2CachedDuty = a.dutyLookup[c >> 6]; | |
a.channel2totalLength = 64 - (c & 63); | |
a.memory[65302] = c & 192; | |
a.channel2EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[23] = this.memoryWriter[65303] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (a.channel2Enabled && a.channel2envelopeSweeps == 0) { | |
if (((a.memory[65303] ^ c) & 8) == 8) { | |
if ((a.memory[65303] & 8) == 0)(a.memory[65303] & 7) == 7 ? a.channel2envelopeVolume = a.channel2envelopeVolume + 2 : ++a.channel2envelopeVolume; | |
a.channel2envelopeVolume = 16 - a.channel2envelopeVolume & 15 | |
} else if ((a.memory[65303] & 15) == 8) a.channel2envelopeVolume = 1 + a.channel2envelopeVolume & 15; | |
a.channel2OutputLevelCache() | |
} | |
a.channel2envelopeType = (c & 8) == 8; | |
a.memory[65303] = c; | |
a.channel2VolumeEnableCheck() | |
} | |
}; | |
this.memoryHighWriter[24] = this.memoryWriter[65304] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.channel2frequency = a.channel2frequency & 1792 | c; | |
a.channel2FrequencyTracker = 2048 - a.channel2frequency << 2; | |
a.memory[65304] = c | |
} | |
}; | |
this.memoryHighWriter[25] = this.memoryWriter[65305] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (c > 127) { | |
b = a.memory[65303]; | |
a.channel2envelopeVolume = b >> 4; | |
a.channel2OutputLevelCache(); | |
a.channel2envelopeSweepsLast = (b & 7) - 1; | |
if (a.channel2totalLength == 0) a.channel2totalLength = 64; | |
(c & 64) == 64 && (a.memory[65318] = a.memory[65318] | 2) | |
} | |
a.channel2consecutive = (c & 64) == 0; | |
a.channel2frequency = (c & 7) << 8 | a.channel2frequency & 255; | |
a.channel2FrequencyTracker = 2048 - a.channel2frequency << 2; | |
a.memory[65305] = c & 64; | |
a.channel2EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[26] = this.memoryWriter[65306] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (!a.channel3canPlay && c >= 128) { | |
a.channel3lastSampleLookup = 0; | |
a.channel3UpdateCache() | |
} | |
a.channel3canPlay = c > 127; | |
a.channel3canPlay && (a.memory[65306] > 127 && !a.channel3consecutive) && (a.memory[65318] = a.memory[65318] | 4); | |
a.memory[65306] = c & 128 | |
} | |
}; | |
this.memoryHighWriter[27] = this.memoryWriter[65307] = function (a, b, c) { | |
if (a.soundMasterEnabled || !a.cGBC) { | |
a.soundMasterEnabled && a.audioJIT(); | |
a.channel3totalLength = 256 - c; | |
a.memory[65307] = c; | |
a.channel3EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[28] = this.memoryWriter[65308] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
c = c & 96; | |
a.memory[65308] = c; | |
a.channel3patternType = c == 0 ? 4 : (c >> 5) - 1 | |
} | |
}; | |
this.memoryHighWriter[29] = this.memoryWriter[65309] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.channel3frequency = a.channel3frequency & 1792 | c; | |
a.channel3FrequencyPeriod = 2048 - a.channel3frequency << 1; | |
a.memory[65309] = c | |
} | |
}; | |
this.memoryHighWriter[30] = this.memoryWriter[65310] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (c > 127) { | |
if (a.channel3totalLength == 0) a.channel3totalLength = 256; | |
a.channel3lastSampleLookup = 0; | |
(c & 64) == 64 && (a.memory[65318] = a.memory[65318] | 4) | |
} | |
a.channel3consecutive = (c & 64) == 0; | |
a.channel3frequency = (c & 7) << 8 | a.channel3frequency & 255; | |
a.channel3FrequencyPeriod = 2048 - a.channel3frequency << 1; | |
a.memory[65310] = c & 64; | |
a.channel3EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[32] = this.memoryWriter[65312] = function (a, b, c) { | |
if (a.soundMasterEnabled || !a.cGBC) { | |
a.soundMasterEnabled && a.audioJIT(); | |
a.channel4totalLength = 64 - (c & 63); | |
a.memory[65312] = c | 192; | |
a.channel4EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[33] = this.memoryWriter[65313] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
if (a.channel4Enabled && a.channel4envelopeSweeps == 0) { | |
if (((a.memory[65313] ^ c) & 8) == 8) { | |
if ((a.memory[65313] & 8) == 0)(a.memory[65313] & 7) == 7 ? a.channel4envelopeVolume = a.channel4envelopeVolume + 2 : ++a.channel4envelopeVolume; | |
a.channel4envelopeVolume = 16 - a.channel4envelopeVolume & 15 | |
} else if ((a.memory[65313] & 15) == 8) a.channel4envelopeVolume = 1 + a.channel4envelopeVolume & 15; | |
a.channel4currentVolume = a.channel4envelopeVolume << a.channel4VolumeShifter | |
} | |
a.channel4envelopeType = (c & 8) == 8; | |
a.memory[65313] = c; | |
a.channel4UpdateCache(); | |
a.channel4VolumeEnableCheck() | |
} | |
}; | |
this.memoryHighWriter[34] = this.memoryWriter[65314] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.channel4FrequencyPeriod = Math.max((c & 7) << 4, 8) << (c >> 4); | |
b = c & 8; | |
if (b == 8 && a.channel4BitRange == 32767 || b == 0 && a.channel4BitRange == 127) { | |
a.channel4lastSampleLookup = 0; | |
a.channel4BitRange = b == 8 ? 127 : 32767; | |
a.channel4VolumeShifter = b == 8 ? 7 : 15; | |
a.channel4currentVolume = a.channel4envelopeVolume << a.channel4VolumeShifter; | |
a.noiseSampleTable = b == 8 ? a.LSFR7Table : a.LSFR15Table | |
} | |
a.memory[65314] = c; | |
a.channel4UpdateCache() | |
} | |
}; | |
this.memoryHighWriter[35] = this.memoryWriter[65315] = function (a, b, c) { | |
if (a.soundMasterEnabled) { | |
a.audioJIT(); | |
a.memory[65315] = c; | |
a.channel4consecutive = (c & 64) == 0; | |
if (c > 127) { | |
b = a.memory[65313]; | |
a.channel4envelopeVolume = b >> 4; | |
a.channel4currentVolume = a.channel4envelopeVolume << a.channel4VolumeShifter; | |
a.channel4envelopeSweepsLast = (b & 7) - 1; | |
if (a.channel4totalLength == 0) a.channel4totalLength = 64; | |
(c & 64) == 64 && (a.memory[65318] = a.memory[65318] | 8) | |
} | |
a.channel4EnableCheck() | |
} | |
}; | |
this.memoryHighWriter[36] = this.memoryWriter[65316] = function (a, b, c) { | |
if (a.soundMasterEnabled && a.memory[65316] != c) { | |
a.audioJIT(); | |
a.memory[65316] = c; | |
a.VinLeftChannelMasterVolume = (c >> 4 & 7) + 1; | |
a.VinRightChannelMasterVolume = (c & 7) + 1; | |
a.mixerOutputLevelCache() | |
} | |
}; | |
this.memoryHighWriter[37] = this.memoryWriter[65317] = function (a, b, c) { | |
if (a.soundMasterEnabled && a.memory[65317] != c) { | |
a.audioJIT(); | |
a.memory[65317] = c; | |
a.rightChannel1 = (c & 1) == 1; | |
a.rightChannel2 = (c & 2) == 2; | |
a.rightChannel3 = (c & 4) == 4; | |
a.rightChannel4 = (c & 8) == 8; | |
a.leftChannel1 = (c & 16) == 16; | |
a.leftChannel2 = (c & 32) == 32; | |
a.leftChannel3 = (c & 64) == 64; | |
a.leftChannel4 = c > 127; | |
a.channel1OutputLevelCache(); | |
a.channel2OutputLevelCache(); | |
a.channel3OutputLevelCache(); | |
a.channel4OutputLevelCache() | |
} | |
}; | |
this.memoryHighWriter[38] = this.memoryWriter[65318] = function (a, b, c) { | |
a.audioJIT(); | |
if (!a.soundMasterEnabled && c > 127) { | |
a.memory[65318] = 128; | |
a.soundMasterEnabled = true; | |
a.initializeAudioStartState() | |
} else if (a.soundMasterEnabled && c < 128) { | |
a.memory[65318] = 0; | |
a.soundMasterEnabled = false; | |
for (b = 65296; b < 65318; b++) a.memoryWriter[b](a, b, 0) | |
} | |
}; | |
this.memoryHighWriter[39] = this.memoryWriter[65319] = this.cartIgnoreWrite; | |
this.memoryHighWriter[40] = this.memoryWriter[65320] = this.cartIgnoreWrite; | |
this.memoryHighWriter[41] = this.memoryWriter[65321] = this.cartIgnoreWrite; | |
this.memoryHighWriter[42] = this.memoryWriter[65322] = this.cartIgnoreWrite; | |
this.memoryHighWriter[43] = this.memoryWriter[65323] = this.cartIgnoreWrite; | |
this.memoryHighWriter[44] = this.memoryWriter[65324] = this.cartIgnoreWrite; | |
this.memoryHighWriter[45] = this.memoryWriter[65325] = this.cartIgnoreWrite; | |
this.memoryHighWriter[46] = this.memoryWriter[65326] = this.cartIgnoreWrite; | |
this.memoryHighWriter[47] = this.memoryWriter[65327] = this.cartIgnoreWrite; | |
this.memoryHighWriter[48] = this.memoryWriter[65328] = function (a, b, c) { | |
a.channel3WriteRAM(0, c) | |
}; | |
this.memoryHighWriter[49] = this.memoryWriter[65329] = function (a, b, c) { | |
a.channel3WriteRAM(1, c) | |
}; | |
this.memoryHighWriter[50] = this.memoryWriter[65330] = function (a, b, c) { | |
a.channel3WriteRAM(2, c) | |
}; | |
this.memoryHighWriter[51] = this.memoryWriter[65331] = function (a, b, c) { | |
a.channel3WriteRAM(3, c) | |
}; | |
this.memoryHighWriter[52] = this.memoryWriter[65332] = function (a, b, c) { | |
a.channel3WriteRAM(4, c) | |
}; | |
this.memoryHighWriter[53] = this.memoryWriter[65333] = function (a, b, c) { | |
a.channel3WriteRAM(5, c) | |
}; | |
this.memoryHighWriter[54] = this.memoryWriter[65334] = function (a, b, c) { | |
a.channel3WriteRAM(6, c) | |
}; | |
this.memoryHighWriter[55] = this.memoryWriter[65335] = function (a, b, c) { | |
a.channel3WriteRAM(7, c) | |
}; | |
this.memoryHighWriter[56] = this.memoryWriter[65336] = function (a, b, c) { | |
a.channel3WriteRAM(8, c) | |
}; | |
this.memoryHighWriter[57] = this.memoryWriter[65337] = function (a, b, c) { | |
a.channel3WriteRAM(9, c) | |
}; | |
this.memoryHighWriter[58] = this.memoryWriter[65338] = function (a, b, c) { | |
a.channel3WriteRAM(10, c) | |
}; | |
this.memoryHighWriter[59] = this.memoryWriter[65339] = function (a, b, c) { | |
a.channel3WriteRAM(11, c) | |
}; | |
this.memoryHighWriter[60] = this.memoryWriter[65340] = function (a, b, c) { | |
a.channel3WriteRAM(12, c) | |
}; | |
this.memoryHighWriter[61] = this.memoryWriter[65341] = function (a, b, c) { | |
a.channel3WriteRAM(13, c) | |
}; | |
this.memoryHighWriter[62] = this.memoryWriter[65342] = function (a, b, c) { | |
a.channel3WriteRAM(14, c) | |
}; | |
this.memoryHighWriter[63] = this.memoryWriter[65343] = function (a, b, c) { | |
a.channel3WriteRAM(15, c) | |
}; | |
this.memoryHighWriter[66] = this.memoryWriter[65346] = function (a, b, c) { | |
if (a.backgroundY != c) { | |
a.midScanLineJIT(); | |
a.backgroundY = c | |
} | |
}; | |
this.memoryHighWriter[67] = this.memoryWriter[65347] = function (a, b, c) { | |
if (a.backgroundX != c) { | |
a.midScanLineJIT(); | |
a.backgroundX = c | |
} | |
}; | |
this.memoryHighWriter[68] = this.memoryWriter[65348] = function (a) { | |
if (a.LCDisOn) { | |
a.modeSTAT = 2; | |
a.midScanlineOffset = -1; | |
a.totalLinesPassed = a.currentX = a.queuedScanLines = a.lastUnrenderedLine = a.LCDTicks = a.STATTracker = a.actualScanLine = a.memory[65348] = 0 | |
} | |
}; | |
this.memoryHighWriter[69] = this.memoryWriter[65349] = function (a, b, c) { | |
if (a.memory[65349] != c) { | |
a.memory[65349] = c; | |
a.LCDisOn && a.matchLYC() | |
} | |
}; | |
this.memoryHighWriter[74] = this.memoryWriter[65354] = function (a, b, c) { | |
if (a.windowY != c) { | |
a.midScanLineJIT(); | |
a.windowY = c | |
} | |
}; | |
this.memoryHighWriter[75] = this.memoryWriter[65355] = function (a, b, c) { | |
if (a.memory[65355] != c) { | |
a.midScanLineJIT(); | |
a.memory[65355] = c; | |
a.windowX = c - 7 | |
} | |
}; | |
this.memoryHighWriter[114] = this.memoryWriter[65394] = function (a, b, c) { | |
a.memory[65394] = c | |
}; | |
this.memoryHighWriter[115] = this.memoryWriter[65395] = function (a, b, c) { | |
a.memory[65395] = c | |
}; | |
this.memoryHighWriter[117] = this.memoryWriter[65397] = function (a, b, c) { | |
a.memory[65397] = c | |
}; | |
this.memoryHighWriter[118] = this.memoryWriter[65398] = this.cartIgnoreWrite; | |
this.memoryHighWriter[119] = this.memoryWriter[65399] = this.cartIgnoreWrite; | |
this.memoryHighWriter[255] = this.memoryWriter[65535] = function (a, b, c) { | |
a.interruptsEnabled = c; | |
a.checkIRQMatching() | |
}; | |
this.recompileModelSpecificIOWriteHandling(); | |
this.recompileBootIOWriteHandling() | |
}; | |
GameBoyCore.prototype.recompileModelSpecificIOWriteHandling = function () { | |
if (this.cGBC) { | |
this.memoryHighWriter[2] = this.memoryWriter[65282] = function (a, b, c) { | |
if ((c & 1) == 1) { | |
a.memory[65282] = c & 127; | |
a.serialTimer = (c & 2) == 0 ? 4096 : 128; | |
a.serialShiftTimer = a.serialShiftTimerAllocated = (c & 2) == 0 ? 512 : 16 | |
} else { | |
a.memory[65282] = c; | |
a.serialShiftTimer = a.serialShiftTimerAllocated = a.serialTimer = 0 | |
} | |
}; | |
this.memoryHighWriter[64] = this.memoryWriter[65344] = function (a, b, c) { | |
if (a.memory[65344] != c) { | |
a.midScanLineJIT(); | |
b = c > 127; | |
if (b != a.LCDisOn) { | |
a.LCDisOn = b; | |
a.memory[65345] = a.memory[65345] & 120; | |
a.midScanlineOffset = -1; | |
a.totalLinesPassed = a.currentX = a.queuedScanLines = a.lastUnrenderedLine = a.STATTracker = a.LCDTicks = a.actualScanLine = a.memory[65348] = 0; | |
if (a.LCDisOn) { | |
a.modeSTAT = 2; | |
a.matchLYC(); | |
a.LCDCONTROL = a.LINECONTROL | |
} else { | |
a.modeSTAT = 0; | |
a.LCDCONTROL = a.DISPLAYOFFCONTROL; | |
a.DisplayShowOff() | |
} | |
a.interruptsRequested = a.interruptsRequested & 253 | |
} | |
a.gfxWindowCHRBankPosition = (c & 64) == 64 ? 1024 : 0; | |
a.gfxWindowDisplay = (c & 32) == 32; | |
a.gfxBackgroundBankOffset = (c & 16) == 16 ? 0 : 128; | |
a.gfxBackgroundCHRBankPosition = (c & 8) == 8 ? 1024 : 0; | |
a.gfxSpriteNormalHeight = (c & 4) == 0; | |
a.gfxSpriteShow = (c & 2) == 2; | |
a.BGPriorityEnabled = (c & 1) == 1; | |
a.priorityFlaggingPathRebuild(); | |
a.memory[65344] = c | |
} | |
}; | |
this.memoryHighWriter[65] = this.memoryWriter[65345] = function (a, b, c) { | |
a.LYCMatchTriggerSTAT = (c & 64) == 64; | |
a.mode2TriggerSTAT = (c & 32) == 32; | |
a.mode1TriggerSTAT = (c & 16) == 16; | |
a.mode0TriggerSTAT = (c & 8) == 8; | |
a.memory[65345] = c & 120 | |
}; | |
this.memoryHighWriter[70] = this.memoryWriter[65350] = function (a, b, c) { | |
a.memory[65350] = c; | |
if (c < 224) { | |
var c = c << 8, | |
b = 65024, | |
e = a.modeSTAT, | |
f = a.modeSTAT = 0; | |
do { | |
f = a.memoryReader[c](a, c++); | |
if (f != a.memory[b]) { | |
a.modeSTAT = e; | |
a.graphicsJIT(); | |
a.modeSTAT = 0; | |
a.memory[b++] = f; | |
break | |
} | |
} while (++b < 65184); | |
if (b < 65184) { | |
do { | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++) | |
} while (b < 65184) | |
} | |
a.modeSTAT = e | |
} | |
}; | |
this.memoryHighWriter[77] = this.memoryWriter[65357] = function (a, b, c) { | |
a.memory[65357] = c & 127 | a.memory[65357] & 128 | |
}; | |
this.memoryHighWriter[79] = this.memoryWriter[65359] = function (a, b, c) { | |
a.currVRAMBank = c & 1; | |
a.BGCHRCurrentBank = a.currVRAMBank > 0 ? a.BGCHRBank2 : a.BGCHRBank1 | |
}; | |
this.memoryHighWriter[81] = this.memoryWriter[65361] = function (a, b, c) { | |
a.hdmaRunning || (a.memory[65361] = c) | |
}; | |
this.memoryHighWriter[82] = this.memoryWriter[65362] = function (a, b, c) { | |
a.hdmaRunning || (a.memory[65362] = c & 240) | |
}; | |
this.memoryHighWriter[83] = this.memoryWriter[65363] = function (a, b, c) { | |
a.hdmaRunning || (a.memory[65363] = c & 31) | |
}; | |
this.memoryHighWriter[84] = this.memoryWriter[65364] = function (a, b, c) { | |
a.hdmaRunning || (a.memory[65364] = c & 240) | |
}; | |
this.memoryHighWriter[85] = this.memoryWriter[65365] = function (a, b, c) { | |
if (a.hdmaRunning) if ((c & 128) == 0) { | |
a.hdmaRunning = false; | |
a.memory[65365] = a.memory[65365] | 128 | |
} else a.memory[65365] = c & 127; | |
else if ((c & 128) == 0) { | |
a.DMAWrite((c & 127) + 1); | |
a.memory[65365] = 255 | |
} else { | |
a.hdmaRunning = true; | |
a.memory[65365] = c & 127 | |
} | |
}; | |
this.memoryHighWriter[104] = this.memoryWriter[65384] = function (a, b, c) { | |
a.memory[65385] = a.gbcBGRawPalette[c & 63]; | |
a.memory[65384] = c | |
}; | |
this.memoryHighWriter[105] = this.memoryWriter[65385] = function (a, b, c) { | |
a.updateGBCBGPalette(a.memory[65384] & 63, c); | |
if (a.memory[65384] > 127) { | |
b = a.memory[65384] + 1 & 63; | |
a.memory[65384] = b | 128; | |
a.memory[65385] = a.gbcBGRawPalette[b] | |
} else a.memory[65385] = c | |
}; | |
this.memoryHighWriter[106] = this.memoryWriter[65386] = function (a, b, c) { | |
a.memory[65387] = a.gbcOBJRawPalette[c & 63]; | |
a.memory[65386] = c | |
}; | |
this.memoryHighWriter[107] = this.memoryWriter[65387] = function (a, b, c) { | |
a.updateGBCOBJPalette(a.memory[65386] & 63, c); | |
if (a.memory[65386] > 127) { | |
b = a.memory[65386] + 1 & 63; | |
a.memory[65386] = b | 128; | |
a.memory[65387] = a.gbcOBJRawPalette[b] | |
} else a.memory[65387] = c | |
}; | |
this.memoryHighWriter[112] = this.memoryWriter[65392] = function (a, b, c) { | |
b = a.memory[65361] << 8 | a.memory[65362]; | |
if (!a.hdmaRunning || b < 53248 || b >= 57344) { | |
a.gbcRamBank = Math.max(c & 7, 1); | |
a.gbcRamBankPosition = (a.gbcRamBank - 1 << 12) - 53248; | |
a.gbcRamBankPositionECHO = a.gbcRamBankPosition - 8192 | |
} | |
a.memory[65392] = c | |
}; | |
this.memoryHighWriter[116] = this.memoryWriter[65396] = function (a, b, c) { | |
a.memory[65396] = c | |
} | |
} else { | |
this.memoryHighWriter[2] = this.memoryWriter[65282] = function (a, b, c) { | |
if ((c & 1) == 1) { | |
a.memory[65282] = c & 127; | |
a.serialTimer = 4096; | |
a.serialShiftTimer = a.serialShiftTimerAllocated = 512 | |
} else { | |
a.memory[65282] = c; | |
a.serialShiftTimer = a.serialShiftTimerAllocated = a.serialTimer = 0 | |
} | |
}; | |
this.memoryHighWriter[64] = this.memoryWriter[65344] = function (a, b, c) { | |
if (a.memory[65344] != c) { | |
a.midScanLineJIT(); | |
b = c > 127; | |
if (b != a.LCDisOn) { | |
a.LCDisOn = b; | |
a.memory[65345] = a.memory[65345] & 120; | |
a.midScanlineOffset = -1; | |
a.totalLinesPassed = a.currentX = a.queuedScanLines = a.lastUnrenderedLine = a.STATTracker = a.LCDTicks = a.actualScanLine = a.memory[65348] = 0; | |
if (a.LCDisOn) { | |
a.modeSTAT = 2; | |
a.matchLYC(); | |
a.LCDCONTROL = a.LINECONTROL | |
} else { | |
a.modeSTAT = 0; | |
a.LCDCONTROL = a.DISPLAYOFFCONTROL; | |
a.DisplayShowOff() | |
} | |
a.interruptsRequested = a.interruptsRequested & 253 | |
} | |
a.gfxWindowCHRBankPosition = (c & 64) == 64 ? 1024 : 0; | |
a.gfxWindowDisplay = (c & 32) == 32; | |
a.gfxBackgroundBankOffset = (c & 16) == 16 ? 0 : 128; | |
a.gfxBackgroundCHRBankPosition = (c & 8) == 8 ? 1024 : 0; | |
a.gfxSpriteNormalHeight = (c & 4) == 0; | |
a.gfxSpriteShow = (c & 2) == 2; | |
a.bgEnabled = (c & 1) == 1; | |
a.memory[65344] = c | |
} | |
}; | |
this.memoryHighWriter[65] = this.memoryWriter[65345] = function (a, b, c) { | |
a.LYCMatchTriggerSTAT = (c & 64) == 64; | |
a.mode2TriggerSTAT = (c & 32) == 32; | |
a.mode1TriggerSTAT = (c & 16) == 16; | |
a.mode0TriggerSTAT = (c & 8) == 8; | |
a.memory[65345] = c & 120; | |
if ((!a.usedBootROM || !a.usedGBCBootROM) && a.LCDisOn && a.modeSTAT < 2) { | |
a.interruptsRequested = a.interruptsRequested | 2; | |
a.checkIRQMatching() | |
} | |
}; | |
this.memoryHighWriter[70] = this.memoryWriter[65350] = function (a, b, c) { | |
a.memory[65350] = c; | |
if (c > 127 && c < 224) { | |
var c = c << 8, | |
b = 65024, | |
e = a.modeSTAT, | |
f = a.modeSTAT = 0; | |
do { | |
f = a.memoryReader[c](a, c++); | |
if (f != a.memory[b]) { | |
a.modeSTAT = e; | |
a.graphicsJIT(); | |
a.modeSTAT = 0; | |
a.memory[b++] = f; | |
break | |
} | |
} while (++b < 65184); | |
if (b < 65184) { | |
do { | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++); | |
a.memory[b++] = a.memoryReader[c](a, c++) | |
} while (b < 65184) | |
} | |
a.modeSTAT = e | |
} | |
}; | |
this.memoryHighWriter[71] = this.memoryWriter[65351] = function (a, b, c) { | |
if (a.memory[65351] != c) { | |
a.midScanLineJIT(); | |
a.updateGBBGPalette(c); | |
a.memory[65351] = c | |
} | |
}; | |
this.memoryHighWriter[72] = this.memoryWriter[65352] = function (a, b, c) { | |
if (a.memory[65352] != c) { | |
a.midScanLineJIT(); | |
a.updateGBOBJPalette(0, c); | |
a.memory[65352] = c | |
} | |
}; | |
this.memoryHighWriter[73] = this.memoryWriter[65353] = function (a, b, c) { | |
if (a.memory[65353] != c) { | |
a.midScanLineJIT(); | |
a.updateGBOBJPalette(4, c); | |
a.memory[65353] = c | |
} | |
}; | |
this.memoryHighWriter[77] = this.memoryWriter[65357] = function (a, b, c) { | |
a.memory[65357] = c | |
}; | |
this.memoryHighWriter[79] = this.memoryWriter[65359] = this.cartIgnoreWrite; | |
this.memoryHighWriter[85] = this.memoryWriter[65365] = this.cartIgnoreWrite; | |
this.memoryHighWriter[104] = this.memoryWriter[65384] = this.cartIgnoreWrite; | |
this.memoryHighWriter[105] = this.memoryWriter[65385] = this.cartIgnoreWrite; | |
this.memoryHighWriter[106] = this.memoryWriter[65386] = this.cartIgnoreWrite; | |
this.memoryHighWriter[107] = this.memoryWriter[65387] = this.cartIgnoreWrite; | |
this.memoryHighWriter[108] = this.memoryWriter[65388] = this.cartIgnoreWrite; | |
this.memoryHighWriter[112] = this.memoryWriter[65392] = this.cartIgnoreWrite; | |
this.memoryHighWriter[116] = this.memoryWriter[65396] = this.cartIgnoreWrite | |
} | |
}; | |
GameBoyCore.prototype.recompileBootIOWriteHandling = function () { | |
if (this.inBootstrap) { | |
this.memoryHighWriter[80] = this.memoryWriter[65360] = function (a, b, c) { | |
cout("Boot ROM reads blocked: Bootstrap process has ended.", 0); | |
a.inBootstrap = false; | |
a.disableBootROM(); | |
a.memory[65360] = c | |
}; | |
this.cGBC && (this.memoryHighWriter[108] = this.memoryWriter[65388] = function (a, b, c) { | |
if (a.inBootstrap) { | |
a.cGBC = (c & 1) == 0; | |
if (a.name + a.gameCode + a.ROM[323] == "Game and Watch 50") { | |
a.cGBC = true; | |
cout("Created a boot exception for Game and Watch Gallery 2 (GBC ID byte is wrong on the cartridge).", 1) | |
} | |
cout("Booted to GBC Mode: " + a.cGBC, 0) | |
} | |
a.memory[65388] = c | |
}) | |
} else this.memoryHighWriter[80] = this.memoryWriter[65360] = this.cartIgnoreWrite | |
}; | |
GameBoyCore.prototype.toTypedArray = function (a, b) { | |
try { | |
if (settings[5] || b != "float32" && window.opera && this.checkForOperaMathBug()) return a; | |
if (!a || !a.length) return []; | |
var c = a.length; | |
switch (b) { | |
case "uint8": | |
var e = new Uint8Array(c); | |
break; | |
case "int8": | |
e = new Int8Array(c); | |
break; | |
case "int32": | |
e = new Int32Array(c); | |
break; | |
case "float32": | |
e = new Float32Array(c) | |
} | |
for (var f = 0; f < c; f++) e[f] = a[f]; | |
return e | |
} catch (g) { | |
cout("Could not convert an array to a typed array: " + g.message, 1); | |
return a | |
} | |
}; | |
GameBoyCore.prototype.fromTypedArray = function (a) { | |
try { | |
if (!a || !a.length) return []; | |
for (var b = [], c = 0; c < a.length; ++c) b[c] = a[c]; | |
return b | |
} catch (e) { | |
cout("Conversion from a typed array failed: " + e.message, 1); | |
return a | |
} | |
}; | |
GameBoyCore.prototype.getTypedArray = function (a, b, c) { | |
try { | |
if (settings[5]) throw Error(""); | |
if (c != "float32" && window.opera && this.checkForOperaMathBug()) throw Error(""); | |
switch (c) { | |
case "int8": | |
var e = new Int8Array(a); | |
break; | |
case "uint8": | |
e = new Uint8Array(a); | |
break; | |
case "int32": | |
e = new Int32Array(a); | |
break; | |
case "float32": | |
e = new Float32Array(a) | |
} | |
if (b != 0) for (c = 0; c < a;) e[c++] = b | |
} catch (f) { | |
cout("Could not convert an array to a typed array: " + f.message, 1); | |
e = []; | |
for (c = 0; c < a;) e[c++] = b | |
} | |
return e | |
}; | |
GameBoyCore.prototype.checkForOperaMathBug = function () { | |
var a = new Uint8Array(1); | |
a[0] = -1; | |
a[0] = a[0] >> 0; | |
if (a[0] != 255) { | |
cout("Detected faulty math by your browser.", 2); | |
return true | |
} | |
return false | |
}; | |
var gameboy = null, | |
gbRunInterval = null, | |
settings = [!0, !0, !1, [39, 37, 38, 40, 88, 90, 16, 13], !0, !1, 4, 15, 30, !1, !1, !1, !1, 1]; | |
function start(a, b) { | |
clearLastEmulation(); | |
autoSave(); | |
gameboy = new GameBoyCore(a, b); | |
gameboy.openMBC = openSRAM; | |
gameboy.openRTC = openRTC; | |
gameboy.start(); | |
run() | |
} | |
function run() { | |
if (GameBoyEmulatorInitialized()) if (GameBoyEmulatorPlaying()) cout("The GameBoy core is already running.", 1); | |
else { | |
gameboy.stopEmulator = gameboy.stopEmulator & 1; | |
cout("Starting the iterator.", 0); | |
gameboy.firstIteration = (new Date).getTime(); | |
gameboy.iterations = 0; | |
gbRunInterval = setInterval(function () { | |
!document.hidden && (!document.msHidden && !document.mozHidden && !document.webkitHidden) && gameboy.run() | |
}, settings[6]) | |
} else cout("GameBoy core cannot run while it has not been initialized.", 1) | |
} | |
function pause() { | |
GameBoyEmulatorInitialized() ? GameBoyEmulatorPlaying() ? clearLastEmulation() : cout("GameBoy core has already been paused.", 1) : cout("GameBoy core cannot be paused while it has not been initialized.", 1) | |
} | |
function clearLastEmulation() { | |
if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) { | |
clearInterval(gbRunInterval); | |
gameboy.stopEmulator = gameboy.stopEmulator | 2; | |
cout("The previous emulation has been cleared.", 0) | |
} else cout("No previous emulation was found to be cleared.", 0) | |
} | |
function save() { | |
if (GameBoyEmulatorInitialized()) try { | |
for (var a = 0; findValue("FREEZE_" + gameboy.name + "_" + a) != null;) a++; | |
setValue("FREEZE_" + gameboy.name + "_" + a, gameboy.saveState()); | |
cout("Saved the current state as: FREEZE_" + gameboy.name + "_" + a, 0) | |
} catch (b) { | |
cout('Could not save the current emulation state("' + b.message + '").', 2) | |
} else cout("GameBoy core cannot be saved while it has not been initialized.", 1) | |
} | |
function saveSRAM() { | |
if (GameBoyEmulatorInitialized()) { | |
if (gameboy.cBATT) try { | |
var a = gameboy.saveSRAMState(); | |
if (a.length > 0) { | |
cout("Saving the SRAM...", 0); | |
if (findValue("SRAM_" + gameboy.name) != null) { | |
cout("Deleting the old SRAM save due to outdated format.", 0); | |
deleteValue("SRAM_" + gameboy.name) | |
} | |
setValue("B64_SRAM_" + gameboy.name, arrayToBase64(a)) | |
} else cout("SRAM could not be saved because it was empty.", 1) | |
} catch (b) { | |
cout('Could not save the current emulation state("' + b.message + '").', 2) | |
} else cout("Cannot save a game that does not have battery backed SRAM specified.", 1); | |
saveRTC() | |
} else cout("GameBoy core cannot be saved while it has not been initialized.", 1) | |
} | |
function saveRTC() { | |
if (GameBoyEmulatorInitialized()) { | |
if (gameboy.cTIMER) try { | |
cout("Saving the RTC...", 0); | |
setValue("RTC_" + gameboy.name, gameboy.saveRTCState()) | |
} catch (a) { | |
cout('Could not save the RTC of the current emulation state("' + a.message + '").', 2) | |
} | |
} else cout("GameBoy core cannot be saved while it has not been initialized.", 1) | |
} | |
function autoSave() { | |
if (GameBoyEmulatorInitialized()) { | |
cout("Automatically saving the SRAM.", 0); | |
saveSRAM(); | |
saveRTC() | |
} | |
} | |
function openSRAM(a) { | |
try { | |
if (findValue("B64_SRAM_" + a) != null) { | |
cout("Found a previous SRAM state (Will attempt to load).", 0); | |
return base64ToArray(findValue("B64_SRAM_" + a)) | |
} | |
if (findValue("SRAM_" + a) != null) { | |
cout("Found a previous SRAM state (Will attempt to load).", 0); | |
return findValue("SRAM_" + a) | |
} | |
cout("Could not find any previous SRAM copy for the current ROM.", 0) | |
} catch (b) { | |
cout("Could not open the SRAM of the saved emulation state.", 2) | |
} | |
return [] | |
} | |
function openRTC(a) { | |
try { | |
if (findValue("RTC_" + a) != null) { | |
cout("Found a previous RTC state (Will attempt to load).", 0); | |
return findValue("RTC_" + a) | |
} | |
cout("Could not find any previous RTC copy for the current ROM.", 0) | |
} catch (b) { | |
cout("Could not open the RTC data of the saved emulation state.", 2) | |
} | |
return [] | |
} | |
function openState(a, b) { | |
try { | |
if (findValue(a) != null) try { | |
clearLastEmulation(); | |
cout("Attempting to run a saved emulation state.", 0); | |
gameboy = new GameBoyCore(b, ""); | |
gameboy.savedStateFileName = a; | |
gameboy.returnFromState(findValue(a)); | |
run() | |
} catch (c) { | |
alert(c.message + " file: " + c.fileName + " line: " + c.lineNumber) | |
} else cout("Could not find the save state " + a + '".', 2) | |
} catch (e) { | |
cout("Could not open the saved emulation state.", 2) | |
} | |
} | |
function import_save(a) { | |
if ((a = decodeBlob(a)) && a.blobs) if (a.blobs.length > 0) for (var b = 0; b < a.blobs.length; ++b) { | |
cout('Importing blob "' + a.blobs[b].blobID + '"', 0); | |
a.blobs[b].blobContent ? a.blobs[b].blobID.substring(0, 5) == "SRAM_" ? setValue("B64_" + a.blobs[b].blobID, base64(a.blobs[b].blobContent)) : setValue(a.blobs[b].blobID, JSON.parse(a.blobs[b].blobContent)) : a.blobs[b].blobID ? cout('Save file imported had blob "' + a.blobs[b].blobID + '" with no blob data interpretable.', 2) : cout("Blob chunk information missing completely.", 2) | |
} else cout("Could not decode the imported file.", 2); | |
else cout("Could not decode the imported file.", 2) | |
} | |
function generateBlob(a, b) { | |
var c = "EMULATOR_DATA", | |
c = c + to_little_endian_dword(c.length + 4 + 8 + (1 + a.length + (4 + b.length))), | |
c = c + to_byte(7), | |
c = c + "GameBoy" + to_byte(a.length), | |
c = c + a + to_little_endian_dword(b.length); | |
return c + b | |
} | |
function generateMultiBlob(a) { | |
for (var b = 25, c = to_byte(7), c = c + "GameBoy", e = "", f = "", g = 0; g < a.length; ++g) { | |
e = a[g][0]; | |
f = a[g][1]; | |
c = c + to_byte(e.length); | |
c = c + e; | |
c = c + to_little_endian_dword(f.length); | |
c = c + f; | |
b = b + (1 + e.length + 4 + f.length) | |
} | |
return c = "EMULATOR_DATA" + to_little_endian_dword(b) + c | |
} | |
function decodeBlob(a) { | |
var b = a.length, | |
c = { | |
consoleID: null | |
}, | |
e = -1; | |
c.blobs = []; | |
if (b > 17 && a.substring(0, 13) == "EMULATOR_DATA") { | |
var b = Math.min((a.charCodeAt(16) & 255) << 24 | (a.charCodeAt(15) & 255) << 16 | (a.charCodeAt(14) & 255) << 8 | a.charCodeAt(13) & 255, b), | |
f = a.charCodeAt(17) & 255; | |
if (b > 17 + f) { | |
c.consoleID = a.substring(18, 18 + f); | |
for (var g = 0, g = 0, f = 18 + f; f < b;) { | |
g = a.charCodeAt(f++) & 255; | |
if (f + g < b) { | |
c.blobs[++e] = {}; | |
c.blobs[e].blobID = a.substring(f, f + g); | |
f = f + g; | |
if (f + 4 < b) { | |
g = (a.charCodeAt(f + 3) & 255) << 24 | (a.charCodeAt(f + 2) & 255) << 16 | (a.charCodeAt(f + 1) & 255) << 8 | a.charCodeAt(f) & 255; | |
f = f + 4; | |
if (f + g <= b) { | |
c.blobs[e].blobContent = a.substring(f, f + g); | |
f = f + g | |
} else { | |
cout("Blob length check failed, blob determined to be incomplete.", 2); | |
break | |
} | |
} else { | |
cout("Blob was incomplete, bailing out.", 2); | |
break | |
} | |
} else { | |
cout("Blob was incomplete, bailing out.", 2); | |
break | |
} | |
} | |
} | |
} | |
return c | |
} | |
function matchKey(a) { | |
for (var b = 0; b < settings[3].length; b++) if (settings[3][b] == a) return b; | |
return -1 | |
} | |
function GameBoyEmulatorInitialized() { | |
return typeof gameboy == "object" && gameboy != null | |
} | |
function GameBoyEmulatorPlaying() { | |
return (gameboy.stopEmulator & 2) == 0 | |
} | |
function GameBoyKeyDown(a) { | |
if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) { | |
var b = matchKey(a.keyCode); | |
if (b >= 0 && b < 8) { | |
gameboy.JoyPadEvent(b, true); | |
try { | |
a.preventDefault() | |
} catch (c) {} | |
} | |
} | |
} | |
function GameBoyKeyUp(a) { | |
if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) { | |
var b = matchKey(a.keyCode); | |
if (b >= 0 && b < 8) { | |
gameboy.JoyPadEvent(b, false); | |
try { | |
a.preventDefault() | |
} catch (c) {} | |
} | |
} | |
} | |
function GameBoyGyroSignalHandler(a) { | |
if (GameBoyEmulatorInitialized() && GameBoyEmulatorPlaying()) { | |
a.gamma || a.beta ? gameboy.GyroEvent(a.gamma * Math.PI / 180, a.beta * Math.PI / 180) : gameboy.GyroEvent(a.x, a.y); | |
try { | |
a.preventDefault() | |
} catch (b) {} | |
} | |
} | |
function initNewCanvas() { | |
if (GameBoyEmulatorInitialized()) { | |
gameboy.canvas.width = gameboy.canvas.clientWidth; | |
gameboy.canvas.height = gameboy.canvas.clientHeight | |
} | |
} | |
function initNewCanvasSize() { | |
GameBoyEmulatorInitialized() && (settings[12] ? (gameboy.onscreenWidth != gameboy.canvas.clientWidth || gameboy.onscreenHeight != gameboy.canvas.clientHeight) && gameboy.initLCD() : (gameboy.onscreenWidth != 160 || gameboy.onscreenHeight != 144) && gameboy.initLCD()) | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment