246 lines
7.4 KiB
HTML
246 lines
7.4 KiB
HTML
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<script src="js/util.js"></script>
|
|
<script src="js/core.js"></script>
|
|
<script src="js/arm.js"></script>
|
|
<script src="js/thumb.js"></script>
|
|
<script src="js/mmu.js"></script>
|
|
<script src="js/io.js"></script>
|
|
<script src="js/audio.js"></script>
|
|
<script src="js/video.js"></script>
|
|
<script src="js/video/proxy.js"></script>
|
|
<script src="js/video/software.js"></script>
|
|
<script src="js/irq.js"></script>
|
|
<script src="js/keypad.js"></script>
|
|
<script src="js/sio.js"></script>
|
|
<script src="js/savedata.js"></script>
|
|
<script src="js/gpio.js"></script>
|
|
<script src="js/gba.js"></script>
|
|
|
|
<script src="resources/xhr.js"></script>
|
|
<script src="resources/console.js"></script>
|
|
<link href="resources/console.css" rel="stylesheet">
|
|
<script>
|
|
function runTest(r) {
|
|
core.setRom(r);
|
|
core.DEBUG("ROM loaded: " + core.rom.title + " [" + core.rom.code + "] (" + r.byteLength + " bytes)");
|
|
gbaCon.memory.refreshAll();
|
|
gbaCon.run()
|
|
}
|
|
|
|
function loadRomFromFile(romFile) {
|
|
var reader = new FileReader();
|
|
reader.onload = function(e) { runTest(e.target.result); }
|
|
reader.readAsArrayBuffer(romFile);
|
|
};
|
|
|
|
function setLogLevel(level, enabled) {
|
|
core.logLevel &= ~level;
|
|
core.logLevel |= enabled && level;
|
|
}
|
|
|
|
function screenshot() {
|
|
var canvas = document.getElementById('screen');
|
|
window.open(canvas.toDataURL('image/png'), 'screenshot');
|
|
};
|
|
|
|
function savestate() {
|
|
gbaCon.pause();
|
|
var state = core.freeze();
|
|
console.log(state);
|
|
Serializer.serializePNG(Serializer.serialize(state), document.getElementById('screen'), function(url) {
|
|
var img = document.getElementById('saveState');
|
|
img.setAttribute('src', url);
|
|
});
|
|
};
|
|
var globalState;
|
|
function savestateDirct() {
|
|
gbaCon.pause();
|
|
var state = core.freeze();
|
|
console.log(state);
|
|
globalState = Serializer.serialize(state)
|
|
}
|
|
function loadState() {
|
|
if (globalState) {
|
|
Serializer.deserialize(globalState, function (state) {
|
|
console.log(state);
|
|
core.defrost(state);
|
|
});
|
|
}
|
|
}
|
|
function loadSavestate(state) {
|
|
Serializer.deserializePNG(state, function (result) {
|
|
core.defrost(result);
|
|
core.DEBUG('Loaded state');
|
|
});
|
|
}
|
|
|
|
var core = new GameBoyAdvance();
|
|
setLogLevel(core.LOG_DEBUG, true);
|
|
var rom = null;
|
|
|
|
var gbaCon;
|
|
core.cpu.resetCPU(0);
|
|
|
|
|
|
function downloadFileRemote(fileName, registrationHandler) {
|
|
var ajax = new XMLHttpRequest();
|
|
ajax.onload = registrationHandler;
|
|
ajax.open("GET", fileName, true);
|
|
ajax.responseType = "arraybuffer";
|
|
ajax.overrideMimeType("text/plain; charset=x-user-defined");
|
|
ajax.send(null);
|
|
}
|
|
|
|
|
|
function processDownload(parentObj, attachHandler) {
|
|
try {
|
|
attachHandler(parentObj.response);
|
|
}
|
|
catch (error) {
|
|
var data = parentObj.responseText;
|
|
var length = data.length;
|
|
var dataArray = [];
|
|
for (var index = 0; index < length; index++) {
|
|
dataArray[index] = data.charCodeAt(index) & 0xFF;
|
|
}
|
|
attachHandler(dataArray);
|
|
}
|
|
}
|
|
window.onload = function() {
|
|
var canvas = document.getElementById('screen');
|
|
core.setCanvas(canvas);
|
|
|
|
gbaCon = new Console(core);
|
|
core.DEBUG("Logging begun!");
|
|
core.DEBUG("Loading BIOS...");
|
|
loadRom('resources/bios.bin', function(bios) {
|
|
core.setBios(bios, false);
|
|
core.DEBUG("BIOS loaded!");
|
|
gbaCon.memory.refreshAll();
|
|
var path = "resources/metalslug.gba"
|
|
downloadFileRemote(path, function () {
|
|
processDownload(this, runTest);
|
|
});
|
|
});
|
|
};
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<section id="top">
|
|
<section id="consoleContainer">
|
|
<div id="consoleControls">
|
|
<label><input type="checkbox" checked onclick="setLogLevel(core.LOG_ERROR, this.checked)">ERROR</label>
|
|
<label><input type="checkbox" checked onclick="setLogLevel(core.LOG_WARN, this.checked)">WARN</label>
|
|
<label><input type="checkbox" onclick="setLogLevel(core.LOG_STUB, this.checked)">STUB</label>
|
|
<label><input type="checkbox" onclick="setLogLevel(core.LOG_INFO, this.checked)">INFO</label>
|
|
<label><input type="checkbox" checked onclick="setLogLevel(core.LOG_DEBUG, this.checked)">DEBUG</label>
|
|
</div>
|
|
<ul id="console"></ul>
|
|
<img id="saveState">
|
|
</section>
|
|
<section id="main">
|
|
<section id="display">
|
|
<canvas id="screen" width="240" height="160"></canvas>
|
|
</section>
|
|
<section id="controls">
|
|
<button onclick="gbaCon.step()">Step</button>
|
|
<button onclick="gbaCon.runVisible()">Run slowly</button>
|
|
<button onclick="gbaCon.runFrame()">Next frame</button>
|
|
<button onclick="gbaCon.run()">Run quickly</button>
|
|
<button onclick="gbaCon.pause()">Pause</button>
|
|
</section>
|
|
<section id="loading">
|
|
Load ROM:
|
|
<input type="file" id="uploadRom" onchange="loadRomFromFile(this.files[0])">
|
|
</section>
|
|
<section id="saving">
|
|
<button onclick="document.getElementById('uploadSave').click()">Load savedata</button>
|
|
<input type="file" id="uploadSave" onchange="core.loadSavedataFromFile(this.files[0])" style="display: none">
|
|
<button onclick="core.downloadSavedata()">Download savedata</button>
|
|
<button onclick="core.storeSavedata()">保存</button>
|
|
<button onclick="core.retrieveSavedata()">读取</button>
|
|
<button onclick="screenshot()">Take screenshot</button>
|
|
<button onclick="savestate()">Freeze</button>
|
|
<input type="file" id="uploadSavestate" onchange="loadSavestate(this.files[0])" style="display: none">
|
|
<button onclick="document.getElementById('uploadSavestate').click()">Defrost</button>
|
|
<button onclick="savestateDirct()">Freeze2</button>
|
|
<button onclick="loadState()">Defrost2</button>
|
|
</section>
|
|
<section id="registers">
|
|
<div>
|
|
<h3>GPRs</h3>
|
|
<ol id="gprs">
|
|
<li id="r0">0x00000000</li>
|
|
<li id="r1">0x00000000</li>
|
|
<li id="r2">0x00000000</li>
|
|
<li id="r3">0x00000000</li>
|
|
<li id="r4">0x00000000</li>
|
|
<li id="r5">0x00000000</li>
|
|
<li id="r6">0x00000000</li>
|
|
<li id="r7">0x00000000</li>
|
|
<li id="r8">0x00000000</li>
|
|
<li id="r9">0x00000000</li>
|
|
<li id="r10">0x00000000</li>
|
|
<li id="r11">0x00000000</li>
|
|
<li id="r12">0x00000000</li>
|
|
<li id="r13">0x00000000</li>
|
|
<li id="r14">0x00000000</li>
|
|
<li id="r15">0x00000000</li>
|
|
</ol>
|
|
</div>
|
|
<div>
|
|
<h3>Status bits</h3>
|
|
<ol id="psr">
|
|
<li id="cpsrN">N</li>
|
|
<li id="cpsrZ">Z</li>
|
|
<li id="cpsrC">C</li>
|
|
<li id="cpsrV">V</li>
|
|
<li id="cpsrI">I</li>
|
|
<li id="cpsrT">T</li>
|
|
<li>Mode: <span id="mode">SYSTEM</span></li>
|
|
</ol>
|
|
</div>
|
|
</section>
|
|
<section id="breakpoints">
|
|
<div id="breakpointControls">
|
|
Add breakpoint:
|
|
<input type="text" onchange="gbaCon.addBreakpoint(parseInt(this.value, 16))">
|
|
</div>
|
|
<ul id="breakpointView">
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
<section id="memory">
|
|
<div id="memoryControls">
|
|
<h3>Jump to:</h3>
|
|
<ul>
|
|
<li>
|
|
Region:
|
|
<select onchange="gbaCon.memory.scrollTo(this.options[this.selectedIndex].value * 0x01000000)">
|
|
<option value="0">0x00000000: BIOS</option>
|
|
<option value="2">0x02000000: On-Board RAM</option>
|
|
<option value="3">0x03000000: In-Chip RAM</option>
|
|
<option value="4">0x04000000: I/O</option>
|
|
<option value="5">0x05000000: Palette</option>
|
|
<option value="6">0x06000000: VRAM</option>
|
|
<option value="7">0x07000000: OAM</option>
|
|
<option value="8">0x08000000: Gamepak WS 0</option>
|
|
<option value="10">0x0A000000: Gamepak WS 1</option>
|
|
<option value="12">0x0C000000: Gamepak WS 2</option>
|
|
<option value="14">0x0E000000: Gamepak SRAM</option>
|
|
</select>
|
|
</li>
|
|
<li>
|
|
Address:
|
|
<input type="text" onchange="gbaCon.memory.scrollTo(parseInt(this.value, 16))">
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<ul id="memoryView"></ul>
|
|
</section>
|
|
</section>
|
|
</body>
|
|
</html>
|