diff --git a/example.css b/example.css
new file mode 100644
index 0000000..28df0d7
--- /dev/null
+++ b/example.css
@@ -0,0 +1,78 @@
+/*-------------------------------------------------------------------------
+| SAE - Scripted Amiga Emulator
+| https://github.com/naTmeg/ScriptedAmigaEmulator
+|
+| Copyright (C) 2012-2016 Rupert Hausberger
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+-------------------------------------------------------------------------*/
+
+a:link { color:#24c; text-decoration:none; }
+a:visited { color:#24c; text-decoration:none; }
+a:hover { color:#24c; text-decoration:underline; }
+
+body {
+ top:0;
+ left:0;
+ margin:0;
+ padding:0;
+ font-family:Verdana;
+ font-size:13px;
+ background-color:#f8f8f8;
+ -webkit-touch-callout:none;
+ -webkit-user-select:none;
+ -khtml-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none;
+}
+
+table {
+ white-space:nowrap;
+}
+
+/*---------------------------------*/
+
+.gray { color:gray; }
+.green { color:green; }
+.orange { color:orange; }
+.red { color:red; }
+
+.alt { text-align:left; vertical-align:top; }
+.alm { text-align:left; vertical-align:middle; }
+.alb { text-align:left; vertical-align:bottom; }
+
+.act { text-align:center; vertical-align:top; }
+.acm { text-align:center; vertical-align:middle; }
+.acb { text-align:center; vertical-align:bottom; }
+
+.art { text-align:right; vertical-align:top; }
+.arm { text-align:right; vertical-align:middle; }
+.arb { text-align:right; vertical-align:bottom; }
+
+
+.info {
+ font-size:11px;
+ color:dimgray;
+}
+.warn {
+ font-size:11px;
+ color:red;
+}
+
+.noscript {
+ margin:auto;
+ padding:4px;
+ font-size:17px;
+ font-weight:bold;
+ text-align:center;
+ color:red;
+}
diff --git a/example.htm b/example.htm
new file mode 100644
index 0000000..340cfb5
--- /dev/null
+++ b/example.htm
@@ -0,0 +1,155 @@
+
+
+
+ SAE - Scripted Amiga Emulator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Status |
+
+
+
+ | PWR |
+ HD |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+
+
+ |
+
+
+
+ | Config |
+
+
+ |
+
+
+
+ | Controls |
+
+
+
+ |
+ |
+ |
+ |
+
+
+ |
+
+
+
+ | Output |
+
+
+
+
+
+
+ |
+
+
+
+
+
diff --git a/example.js b/example.js
new file mode 100644
index 0000000..db072a3
--- /dev/null
+++ b/example.js
@@ -0,0 +1,548 @@
+/*-------------------------------------------------------------------------
+| SAE - Scripted Amiga Emulator
+| https://github.com/naTmeg/ScriptedAmigaEmulator
+|
+| Copyright (C) 2012-2016 Rupert Hausberger
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| Note: This file does not contain any emulator-code.
+-------------------------------------------------------------------------*/
+
+var sae = null; /* SAE instance */
+var cfg = null; /* Reference to the config-object */
+var inf = null; /* Reference to the info-object */
+
+var running = false; /* Is the emualtion currently running? */
+var paused = false; /* Is the emualtion currently paused? */
+
+/*-----------------------------------------------------------------------*/
+/* Helpers */
+
+function getSelect(id, asString) {
+ if (typeof asString == "undefined") asString = false;
+ var e = document.getElementById(id);
+ for (var i = 0; i < e.length; i++) {
+ if (e[i].selected)
+ return asString ? e[i].value : Number(e[i].value);
+ }
+ return false;
+}
+
+function setSelect(id, v) {
+ var e = document.getElementById(id);
+ var vs = String(v);
+ for (var i = 0; i < e.length; i++) {
+ if (e[i].value === vs) {
+ e[i].selected = true;
+ return;
+ }
+ }
+}
+
+function styleDisplayInline(id, show) {
+ var e = document.getElementById(id);
+ e.style.display = show ? "inline" : "none";
+}
+
+function switchPauseResume(p) {
+ var e = document.getElementById("controls_pr");
+ if (p) {
+ e.innerHTML = "Resume";
+ e.onclick = function() { pause(false); };
+ } else {
+ e.innerHTML = "Pause";
+ e.onclick = function() { pause(true); };
+ }
+}
+
+function saee2text(err) {
+ switch (err) {
+ case SAEE_AlreadyRunning: return "The emulator is already running.";
+ case SAEE_NotRunning: return "The emulator is not running.";
+ case SAEE_NoTimer: return "No timing-functions avail. Please upgrade your browser.";
+ case SAEE_NoMemory: return "Out of memory.";
+ case SAEE_Internal: return "Internal emulator error.";
+ case SAEE_Config_Invalid: return "Invalid configuration.";
+ case SAEE_CPU_Internal: return "Internal CPU-error.";
+ case SAEE_CPU_Requires68020: return "The selected kickstart-rom does require a 68020 and 32bit address-space";
+ case SAEE_CPU_Requires680EC20: return "The selected kickstart-rom does require a 68020.";
+ case SAEE_CPU_Requires68030: return "The selected kickstart-rom does require a 68030.";
+ case SAEE_CPU_Requires68040: return "The selected kickstart-rom does require a 68040/68060.";
+ case SAEE_Memory_NoKickstartRom: return "The kickstart-rom is missing.";
+ case SAEE_Memory_NoExtendedRom: return "An extended-rom is required but missing.\n\nGo to the ROM-page and select a rom from disk...";
+ case SAEE_Memory_RomSize: return "The kickstart- or extended-rom does have an invalid size.";
+ case SAEE_Memory_RomKey: return "A ROM-keyfile is required. (Cloanto)";
+ case SAEE_Memory_RomDecode: return "Invalid ROM-keyfile. (Cloanto)";
+ case SAEE_Memory_RomChecksum: return "Checksum-error at the kickstart- or extended-rom.";
+ case SAEE_Memory_RomUnknown: return "Unknown ROM.";
+ case SAEE_Video_ElementNotFound: return "Video DIV-element not found. Check 'cfg.video.id'";
+ case SAEE_Video_RequiresCanvas: return "This browser does not support 'Canvas'. Please upgrade to an actual version.";
+ case SAEE_Video_RequiresWegGl: return "This browser does not support 'WebGL'. Please upgrade to an actual version.";
+ case SAEE_Video_ComphileShader: return "Can not compile the required shader-program.";
+ case SAEE_Video_LinkShader: return "Can not link the required shader-program.";
+ case SAEE_Audio_RequiresWebAudio: return "This browser does not support 'WebAudio'. Please upgrade to an actual version.";
+ default: return "("+err+")";
+ }
+}
+
+function loadFile(e, callback) {
+ var reader = new FileReader();
+ reader.onload = callback;
+ reader.readAsBinaryString(e);
+}
+
+/*---------------------------------*/
+/* CRC-32 checksumming */
+
+const crc32Table = (function() {
+ var table = new Uint32Array(256);
+ var n, c, k;
+
+ for (n = 0; n < 256; n++) {
+ c = n;
+ for (k = 0; k < 8; k++)
+ c = ((c >>> 1) ^ (c & 1 ? 0xedb88320 : 0)) >>> 0;
+ table[n] = c;
+ }
+ return table;
+})();
+
+function crc32(data) {
+ var length = data.length;
+ var offset = 0;
+ var crc = 0xffffffff;
+
+ while (length-- > 0)
+ crc = crc32Table[(crc ^ data.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8);
+
+ return (crc ^ 0xffffffff) >>> 0;
+}
+
+if (crc32("The quick brown fox jumps over the lazy dog") != 0x414fa339)
+ alert("CRC32-hash testing failed. SAE will not work. This is an internal bug!?");
+
+/*-----------------------------------------------------------------------*/
+/* Config */
+
+function fixConfig() {
+ /* video */
+ if (cfg.video.enabled) {
+ if (!inf.video.canvas && !inf.video.webGL)
+ cfg.video.enabled = false;
+ else if (SAEV_config.video.api == SAEC_Config_Video_API_WebGL && !inf.video.webGL)
+ SAEV_config.video.api = SAEC_Config_Video_API_Canvas;
+ }
+ /* audio */
+ if (cfg.audio.mode >= SAEC_Config_Audio_Mode_On) {
+ if (!inf.audio.webAudio)
+ cfg.audio.mode = SAEC_Config_Audio_Mode_Off_Emul;
+ }
+}
+
+function setRomName() {
+ var e = document.getElementById("cfg_rom_name");
+ if (cfg.memory.rom.size) {
+ e.className = "";
+ e.innerHTML = cfg.memory.rom.name;
+ styleDisplayInline("cfg_rom_remove", 1);
+ } else {
+ e.className = "red";
+ e.innerHTML = "<unset> (required)";
+ styleDisplayInline("cfg_rom_remove", 0);
+ document.getElementById("cfg_rom_file").value = "";
+ }
+}
+
+function setFloppyName(n) {
+ var e = document.getElementById("cfg_df"+n+"_name");
+ if (cfg.floppy.drive[n].file.size) {
+ e.className = "";
+ e.innerHTML = cfg.floppy.drive[n].file.name;
+ styleDisplayInline("cfg_df"+n+"_eject", 1);
+ } else {
+ e.className = "gray";
+ e.innerHTML = "<unset>";
+ styleDisplayInline("cfg_df"+n+"_eject", 0);
+ document.getElementById("cfg_df"+n+"_file").value = "";
+ }
+}
+
+function setConfig() {
+ fixConfig();
+ setSelect("cfg_ntsc", cfg.chipset.ntsc ? 1 : 0);
+ setRomName();
+ setFloppyName(0);
+ switch (cfg.video.hresolution) {
+ case SAEC_Config_Video_HResolution_LoRes:
+ setSelect("cfg_res", 1);
+ break;
+ case SAEC_Config_Video_HResolution_HiRes:
+ setSelect("cfg_res", 2);
+ break;
+ case SAEC_Config_Video_HResolution_SuperHiRes:
+ setSelect("cfg_res", 3);
+ break;
+ }
+}
+
+/*---------------------------------*/
+
+function getConfig() {
+ var model = SAEC_Model_A2000; /* Default model after page-load*/
+ var modelSubConfig = 0; /* See config.js */
+
+ switch (getSelect("cfg_model", true)) {
+ case "A500": model = SAEC_Model_A500; break;
+ case "A500P": model = SAEC_Model_A500P; break;
+ case "A600": model = SAEC_Model_A600; break;
+ case "A1000": model = SAEC_Model_A1000; break;
+ case "A1200": model = SAEC_Model_A1200; break;
+ case "A2000": model = SAEC_Model_A2000; break;
+ case "A3000": model = SAEC_Model_A3000; break;
+ case "A4000": model = SAEC_Model_A4000; break;
+ case "A4000T": model = SAEC_Model_A4000T; break;
+ /* future. do not use. cd-emulation is not implemented yet.
+ case "CDTV": model = SAEC_Model_CDTV; break;
+ case "CD32": model = SAEC_Model_CD32; break; */
+ }
+ /* Set the defaults for the selected model.
+ ROMs and Floppies are not affected. */
+ sae.setModel(model, modelSubConfig);
+
+ /* After here, you may tweak additional settings */
+
+ cfg.chipset.ntsc = getSelect("cfg_ntsc") == 1;
+
+ cfg.memory.z2FastSize = 2 << 20; /* Give 2mb zorro2 fast-ram */
+
+ /* Do we have rom-data? */
+ if (cfg.memory.rom.size == 0) {
+ alert(saee2text(SAEE_Memory_NoKickstartRom));
+ return false;
+ }
+
+ cfg.floppy.speed = SAEC_Config_Floppy_Speed_Turbo; /* Set speed to turbo. This is not always compatible */
+
+ cfg.video.id = "myVideo"; /* Set the id-name of the desired output-div or output-canvas */
+
+ switch (getSelect("cfg_res")) {
+ case 1: /* Lores */
+ cfg.video.hresolution = SAEC_Config_Video_HResolution_LoRes;
+ cfg.video.vresolution = SAEC_Config_Video_VResolution_NonDouble;
+ cfg.video.size_win.width = SAEC_Video_DEF_AMIGA_WIDTH; /* 360 */
+ cfg.video.size_win.height = SAEC_Video_DEF_AMIGA_HEIGHT; /* 284 */
+ break;
+ case 2: /* Hires */
+ cfg.video.hresolution = SAEC_Config_Video_HResolution_HiRes;
+ cfg.video.vresolution = SAEC_Config_Video_VResolution_Double;
+ cfg.video.size_win.width = SAEC_Video_DEF_AMIGA_WIDTH << 1; /* 720 */
+ cfg.video.size_win.height = SAEC_Video_DEF_AMIGA_HEIGHT << 1; /* 568 */
+ break;
+ case 3: /* SuperHires */
+ cfg.video.hresolution = SAEC_Config_Video_HResolution_SuperHiRes;
+ cfg.video.vresolution = SAEC_Config_Video_VResolution_Double;
+ cfg.video.size_win.width = SAEC_Video_DEF_AMIGA_WIDTH << 2; /* 1440 */
+ cfg.video.size_win.height = SAEC_Video_DEF_AMIGA_HEIGHT << 1; /* 568 */
+ break;
+ }
+
+ /* Set hooks */
+ cfg.hook.log.error = hook_log_error;
+
+ cfg.hook.event.started = hook_event_started;
+ cfg.hook.event.stopped = hook_event_stopped;
+ cfg.hook.event.reseted = hook_event_reseted;
+ cfg.hook.event.paused = hook_event_paused;
+
+ cfg.hook.led.power = hook_led_power;
+ cfg.hook.led.hd = hook_led_hd;
+ cfg.hook.led.df = hook_led_df;
+ cfg.hook.led.fps = hook_led_fps;
+ cfg.hook.led.cpu = hook_led_cpu;
+
+ /* Enable debug-log to developer-console */
+ cfg.debug.level = SAEC_Config_Debug_Level_Log;
+
+ /* NOTE:
+ DO NOT ALTER the config-object while the emulator is running.
+
+ I will release a detailed description of the config-object soon.
+ */
+ return true;
+}
+
+/*---------------------------------*/
+/* Control buttons */
+
+function start() {
+ if (getConfig()) {
+ /* Start the emulator. This does take some time.
+ Once started, the hook SAEV_config.hook.event.started will be called. (new 0.9.1) */
+ var err = sae.start();
+ if (err == SAEE_None) {
+ /* ... */
+ } else
+ alert(saee2text(err));
+ }
+}
+
+function stop() {
+ /* Send stop-request. This does take some time.
+ Once stopped, the hook SAEV_config.hook.event.stopped will be called. (new 0.9.1) */
+ var err = sae.stop();
+ if (err == SAEE_None) {
+ /* ... */
+ } else
+ alert(saee2text(err));
+}
+
+function reset() {
+ /* Send soft-reset request. This does take some time.
+ Once done, the hook SAEV_config.hook.event.reseted will be called. (new 0.9.1) */
+ var hard = false, keyboard = false;
+ var err = sae.reset(hard, keyboard);
+ if (err == SAEE_None) {
+ /* ... */
+ } else
+ alert(saee2text(err));
+}
+
+function pause(p) {
+ /* Send Pause- or Resume-request. This does take some time.
+ Once paused or resumed, the hook SAEV_config.hook.event.paused will be called. (new 0.9.1)
+ true == pause, false == resume */
+ var err = sae.pause(p);
+ if (err == SAEE_None) {
+ /* ... */
+ } else
+ alert(saee2text(err));
+}
+
+function romSelect() {
+ var e = document.getElementById("cfg_rom_file").files[0];
+ if (e) {
+ loadFile(e, function (event) {
+ //cfg.memory.rom.path = e.path; currently unused in SAE
+ cfg.memory.rom.name = e.name; /* filename */
+ cfg.memory.rom.data = event.target.result; /* typeof 'String' or 'Uint8Array' */
+ cfg.memory.rom.size = e.size; /* size in bytes */
+ cfg.memory.rom.crc32 = crc32(event.target.result); /* pre-calculate crc32 for a faster start */
+ setRomName();
+
+ /*ri = new SAEO_RomInfo();
+ var err = sae.getRomInfo(ri, cfg.memory.rom);
+ if (err == SAEE_None) {
+ examine 'ri'...
+ }*/
+ });
+ }
+}
+function romRemove() {
+ cfg.memory.rom.clr();
+ setRomName();
+}
+
+function floppyInsert(n) {
+ var e = document.getElementById("cfg_df"+n+"_file").files[0];
+ if (e) {
+ loadFile(e, function(event) {
+ var file = cfg.floppy.drive[n].file;
+ //file.path = e.path; currently unused in SAE
+ file.name = e.name; /* filename */
+ file.data = event.target.result; /* typeof 'String' or 'Uint8Array' */
+ file.size = e.size; /* size in bytes */
+ file.crc32 = crc32(event.target.result); /* pre-calculate crc32 for a faster start */
+ setFloppyName(n);
+
+ /*var di = new SAEO_DiskInfo();
+ var err = sae.getDiskInfo(di, n);
+ if (err == SAEE_None) {
+ examine 'di'...
+ }*/
+
+ /* If the emulator is running, notify about the disk-change */
+ if (running)
+ sae.insert(n);
+ });
+ }
+}
+function floppyEject(n) {
+ cfg.floppy.drive[n].file.clr();
+ setFloppyName(n);
+
+ /* If the emulator is running, notify about the disk-change */
+ if (running)
+ sae.eject(n);
+}
+
+/*---------------------------------*/
+/* Init-routine, called once on page-load */
+
+function init() {
+ /* Create the emulator */
+ sae = new ScriptedAmigaEmulator();
+
+ /* Get the reference to the info-object.
+ As alternative, you can use the constant 'SAEC_info' directly,
+ defined in amiga.js */
+ inf = sae.getInfo(); /* or */
+ //inf = SAEC_info;
+ //console.dir(inf);
+
+ /* Get the reference to the config-object.
+ As alternative, you can use the variable 'SAEV_config' directly,
+ defined in config.js */
+ cfg = sae.getConfig(); /* or */
+ //cfg = SAEV_config;
+ //console.dir(cfg);
+
+ initLEDs();
+ setConfig();
+}
+
+/*-----------------------------------------------------------------------*/
+/* Hooks (callbacks) */
+
+/*---------------------------------*/
+/* Logging */
+
+/* There is currently only one log-hook, if a fatal error
+ does occure while the emulator is running. */
+
+function hook_log_error(err, msg) {
+ /* err is a number type. See SAEE_* for the error code. */
+ running = false;
+ if (msg.length)
+ alert(msg);
+}
+
+/*---------------------------------*/
+/* Events (new 0.9.1) */
+
+/* Get call after the emulator has finished the starting-process. */
+function hook_event_started() {
+ running = true;
+}
+
+/* Get call after the emulator has finished the stopping-process. */
+function hook_event_stopped() {
+ running = false;
+
+ if (paused) {
+ paused = false;
+ switchPauseResume(paused);
+ }
+ resetLEDs();
+}
+
+/* Get call after the emulator has finished the reset-routine. */
+function hook_event_reseted(hard) {
+ if (paused) {
+ paused = false;
+ switchPauseResume(paused);
+ }
+}
+
+/* Get call after the emulator has finished switching between pause-resume. */
+function hook_event_paused(p) {
+ paused = p;
+ switchPauseResume(p);
+}
+
+/*---------------------------------*/
+/* LEDs */
+
+const COL_GRAY = "#000";
+const COL_GREEN = "#8C8";
+const COL_RED = "#E88";
+const COL_ORANGE = "#CC8";
+
+/* cache elements */
+var e_led_power = null;
+var e_led_hd = null;
+var e_led_df = [null,null,null,null];
+var e_led_fps = null;
+var e_led_cpu = null;
+
+/* Power LED: boolean On/Off */
+function hook_led_power(on) {
+ e_led_power.style.color = on ? COL_GREEN : COL_GRAY;
+}
+
+/* Harddisk-LED */
+function hook_led_hd(rw) {
+ /* rw 0=Off, 1=Read, 2=Write */
+ e_led_hd.style.color = rw == 1 ? COL_GREEN : (rw == 2 ? COL_RED : COL_GRAY);
+}
+
+/* Floppy-LED */
+function hook_led_df(unit, disabled, cylinder, side, rw) {
+ /* unit 0-3 */
+ /* cylinder 0-81 */
+ /* side 0-1 */
+ /* rw 0=Off, 1=Read, 2=Write */
+ if (disabled) {
+ e_led_df[unit].innerHTML = "-";
+ e_led_df[unit].style.color = COL_GRAY;
+ } else {
+ e_led_df[unit].innerHTML = String(cylinder);
+ e_led_df[unit].style.color = rw == 1 ? COL_GREEN : (rw == 2 ? COL_RED : COL_GRAY);
+ }
+}
+
+/* FPS (Frames Per Second) */
+function hook_led_fps(fps, paused) {
+ /* fps is a float-number, 0-50, in frames */
+ e_led_fps.innerHTML = paused ? "0.0" : fps.toFixed(1);
+ e_led_fps.style.color = COL_GRAY;
+}
+
+/* CPU-usage */
+function hook_led_cpu(usage, paused) {
+ /* usage is a float-number, 0-1000, in percent */
+ if (paused) {
+ e_led_cpu.innerHTML = "0%";
+ e_led_cpu.style.color = COL_GRAY;
+ } else {
+ e_led_cpu.innerHTML = usage.toFixed(0) + "%";
+ if (usage < 90)
+ e_led_cpu.style.color = COL_GREEN;
+ else if (usage < 110)
+ e_led_cpu.style.color = COL_ORANGE;
+ else
+ e_led_cpu.style.color = COL_RED;
+ }
+}
+
+function resetLEDs() {
+ hook_led_power(false);
+ hook_led_hd(0);
+ hook_led_df(0, true, 0, 0, 0);
+ hook_led_df(1, true, 0, 0, 0);
+ hook_led_df(2, true, 0, 0, 0);
+ hook_led_df(3, true, 0, 0, 0);
+ hook_led_fps(0, false);
+ hook_led_cpu(0, false);
+}
+
+function initLEDs() {
+ e_led_power = document.getElementById("status_led_power");
+ e_led_hd = document.getElementById("status_led_hd");
+ e_led_df[0] = document.getElementById("status_led_df0");
+ e_led_df[1] = document.getElementById("status_led_df1");
+ e_led_df[2] = document.getElementById("status_led_df2");
+ e_led_df[3] = document.getElementById("status_led_df3");
+ e_led_fps = document.getElementById("status_led_fps");
+ e_led_cpu = document.getElementById("status_led_cpu");
+
+ resetLEDs();
+}
diff --git a/example2.htm b/example2.htm
new file mode 100644
index 0000000..4d7d8db
--- /dev/null
+++ b/example2.htm
@@ -0,0 +1,155 @@
+
+
+
+ SAE - Scripted Amiga Emulator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Status |
+
+
+
+ | PWR |
+ HD |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+ 0 |
+
+
+ |
+
+
+
+ | Config |
+
+
+ |
+
+
+
+ | Controls |
+
+
+
+ |
+ |
+ |
+ |
+
+
+ |
+
+
+
+ | Output |
+
+
+
+
+
+
+ |
+
+
+
+
+
diff --git a/index.js b/index.js
index 8a25aad..0fc4e27 100644
--- a/index.js
+++ b/index.js
@@ -1382,13 +1382,10 @@ function start() {
var s = cache.state();
if (s == S_VALID) { /* all files are downloaded or cached, go! */
freezeButtons(false, true);
- switchBaseEmul(true);
var err = sae.start(); /* this does start the emulator */
- if (err != SAEE_None) {
- switchBaseEmul(false);
+ if (err != SAEE_None)
alert(saee2text(err));
- }
}
else if (s == S_PENDING) { /* files are still downloading, wait... */
setTimeout(start, 250);
@@ -1423,37 +1420,15 @@ function advandedStart() {
}
function stop() {
- sae.stop();
-
- if (paused) {
- paused = false;
- switchPauseResume(paused);
- }
- if (dskchg)
- dskchgClose();
-
- if (mode == MODE_Advanced)
- setAdvandedConfig();
-
- switchBaseEmul(false);
-}
-
-function reset() {
- sae.reset();
-
- if (paused) {
- paused = false;
- switchPauseResume(paused);
- }
- if (dskchg)
- dskchgClose();
+ sae.stop(); /* send stop-request */
}
function pause(p) {
- switchPauseResume(p);
- paused = p;
+ sae.pause(p); /* send pause-request */
+}
- sae.pause(p); /* true == pause, false == resume */
+function reset() {
+ sae.reset(false, false);
}
/*---------------------------------*/
@@ -2472,7 +2447,7 @@ function portUpdate(n) {
}
/*-----------------------------------------------------------------------*/
-/* status hooks */
+/* hooks */
function hook_log_error(err, msg) {
stop();
@@ -2480,6 +2455,42 @@ function hook_log_error(err, msg) {
alert(msg);
}
+/*---------------------------------*/
+
+function hook_event_started() {
+ switchBaseEmul(true);
+}
+
+function hook_event_stopped() {
+ if (paused) {
+ paused = false;
+ switchPauseResume(paused);
+ }
+ if (dskchg)
+ dskchgClose();
+
+ if (mode == MODE_Advanced)
+ setAdvandedConfig();
+
+ switchBaseEmul(false);
+}
+
+function hook_event_reseted(hard) {
+ if (paused) {
+ paused = false;
+ switchPauseResume(paused);
+ }
+ if (dskchg)
+ dskchgClose();
+}
+
+function hook_event_paused(p) {
+ paused = p;
+ switchPauseResume(p);
+}
+
+/*---------------------------------*/
+
const COL_GRAY = "#888";
const COL_GREEN = "#8C8";
const COL_RED = "#E88";
@@ -2547,6 +2558,11 @@ function initHooks() {
function setHooks() {
cfg.hook.log.error = hook_log_error;
+ cfg.hook.event.started = hook_event_started;
+ cfg.hook.event.stopped = hook_event_stopped;
+ cfg.hook.event.reseted = hook_event_reseted;
+ cfg.hook.event.paused = hook_event_paused;
+
cfg.hook.led.power = hook_led_power;
cfg.hook.led.hd = hook_led_hd;
cfg.hook.led.df = hook_led_df;
diff --git a/sae/amiga.js b/sae/amiga.js
index ce8f860..972fbdb 100644
--- a/sae/amiga.js
+++ b/sae/amiga.js
@@ -390,16 +390,25 @@ function ScriptedAmigaEmulator() {
this.start_program = function() {
this.do_start_program();
+
+ if (typeof SAEV_config.hook.event.started === "function")
+ SAEV_config.hook.event.started();
}
this.leave_program = function() {
this.dump();
this.do_leave_program();
+
+ if (typeof SAEV_config.hook.event.stopped === "function")
+ SAEV_config.hook.event.stopped();
}
this.pause_program = function(p) {
this.audio.pauseResume(p);
this.events.pauseResume(p);
+
+ if (typeof SAEV_config.hook.event.paused === "function")
+ SAEV_config.hook.event.paused(p);
}
/*---------------------------------*/
@@ -503,16 +512,16 @@ function ScriptedAmigaEmulator() {
}
};
- this.reset = function(hardreset, keyboardreset) { //uae_reset(hardreset, keyboardreset)
- if (typeof hardreset == "undefined") var hardreset = 1;
- if (typeof keyboardreset == "undefined") var keyboardreset = 0;
+ this.reset = function(hard, keyboard) { //uae_reset(hard, keyboard)
+ if (typeof hard == "undefined") var hard = false;
+ if (typeof keyboard == "undefined") var keyboard = false;
if (this.running) {
- SAEF_info("sae.reset() hard %d, keyboard %d", hardreset, keyboardreset);
+ SAEF_info("sae.reset() hard %d, keyboard %d", hard?1:0, keyboard?1:0);
if (SAEV_command == 0) {
- SAEV_command = -SAEC_command_Reset;
- if (keyboardreset)
+ SAEV_command = -SAEC_command_Reset; /* soft */
+ if (keyboard)
SAEV_command = -SAEC_command_KeyboardReset;
- if (hardreset)
+ if (hard)
SAEV_command = -SAEC_command_HardReset;
}
return SAEE_None;
@@ -576,6 +585,10 @@ function ScriptedAmigaEmulator() {
return SAEE_None;
};
+ this.keyPress = function(e, down) {
+ this.input.keyPress(e, down);
+ }
+
/*---------------------------------*/
SAEF_info("SAE %d.%d.%d", SAEC_Version, SAEC_Revision, SAEC_Patch);
diff --git a/sae/config.js b/sae/config.js
index 478981a..b80aeef 100644
--- a/sae/config.js
+++ b/sae/config.js
@@ -710,7 +710,7 @@ function SAEO_Config() {
this.hook = {
log: {
- error: function (err, msg) {}
+ error: function(err, msg) {}
},
led: {
power: function(on) {},
@@ -718,6 +718,12 @@ function SAEO_Config() {
df: function(unit, dis, cyl, side, rw) {},
fps: function(fps, paused) {},
cpu: function(usage, paused) {}
+ },
+ event: {
+ started: function() {},
+ stopped: function() {},
+ reseted: function(hard) { console.warn("RES", hard); },
+ paused: function(paused) {}
}
};
diff --git a/sae/input.js b/sae/input.js
index 33e8ed3..8574ec9 100644
--- a/sae/input.js
+++ b/sae/input.js
@@ -741,6 +741,10 @@ function SAEO_Keyboard() {
if (keyState[loc][code] != oldstate)
processKey(loc, code, keyState[loc][code]);
};
+
+ this.keyPress = function(e, down) {
+ handleKey(e, down);
+ };
}
function SAEO_Input() {
@@ -772,6 +776,10 @@ function SAEO_Input() {
potgo.count = 0;
};
+ this.keyPress = function (e, down) {
+ this.keyboard.keyPress(e, down);
+ };
+
this.POTGO = function (v) {
//SAEF_log("Input.POTGO() $%04x", v);
potgo.data = v;
diff --git a/sae/m68k.js b/sae/m68k.js
index 127b163..ceab82a 100644
--- a/sae/m68k.js
+++ b/sae/m68k.js
@@ -227,7 +227,6 @@ function SAEO_M68K() {
SAER.memory.clear();
SAEF_log("m68k.m68k_cycle() hardreset, memory cleared.");
}
- cpu_hardreset = false;
if (SAEV_config.audio.mode == 0)
SAER_Events_eventtab[SAEC_Events_EV_AUDIO].active = false;
@@ -237,6 +236,11 @@ function SAEO_M68K() {
//SAER.audio.check_prefs_changed_audio();
//statusline_clear();
+
+ if (typeof SAEV_config.hook.event.reseted === "function")
+ SAEV_config.hook.event.reseted(cpu_hardreset);
+
+ cpu_hardreset = false;
}
if (startup) {
diff --git a/sae/playfield.js b/sae/playfield.js
index 3deba1a..9e0aad1 100644
--- a/sae/playfield.js
+++ b/sae/playfield.js
@@ -2205,7 +2205,7 @@ function SAEO_Playfield() {
switch (gfxvidinfo.drawbuffer.pixbytes) {
case 2:
pfield_do_linetoscr_normal = need_genlock_data ? linetoscr_16_stretch2_aga_genlock : linetoscr_16_stretch2_aga;
- pfield_do_linetoscr_sprite = need_genlock_data ? linetoscr_16_stretch2_aga_spr_genlock : linetoscr_16_stretch2_aga_spr_genlock;
+ pfield_do_linetoscr_sprite = need_genlock_data ? linetoscr_16_stretch2_aga_spr_genlock : linetoscr_16_stretch2_aga_spr;
pfield_do_linetoscr_spriteonly = linetoscr_16_stretch2_aga_spronly;
break;
case 4:
diff --git a/sae/video.js b/sae/video.js
index 163d363..91491f3 100644
--- a/sae/video.js
+++ b/sae/video.js
@@ -92,7 +92,6 @@ function SAEO_Video() {
this.surface = null;
this.div = null;
- this.video = null;
this.shown = false;
this.fullscreen = false;
}
@@ -198,7 +197,12 @@ function SAEO_Video() {
function CreateWindow(left, top, width, height) {
var hWnd = new HWND();
- hWnd.canvas = document.createElement("canvas");
+ var el = document.getElementById(SAEV_config.video.id);
+ if (el.nodeName == "CANVAS")
+ hWnd.canvas = el;
+ else
+ hWnd.canvas = document.createElement("canvas");
+
hWnd.canvas.width = width;
hWnd.canvas.height = height;
hWnd.canvas.style.backgroundColor = sprintf("#%06X", SAEV_config.video.backgroundColor);
@@ -265,40 +269,39 @@ function SAEO_Video() {
const SW_SHOWNORMAL = 1;
//const SW_SHOW = 5;
//const SW_SHOWDEFAULT = 10;
+
function ShowWindow(hWnd, nCmdShow) {
if (nCmdShow == SW_SHOWNORMAL && !hWnd.shown) {
- hWnd.video = document.createElement("div");
- hWnd.video.style.webkitTouchCallout = "none";
- hWnd.video.style.webkitUserSelect = "none";
- hWnd.video.style.khtmlUserSelect = "none";
- hWnd.video.style.mozUserSelect = "none";
- hWnd.video.style.msUserSelect = "none";
- hWnd.video.style.userSelect = "none";
- hWnd.video.appendChild(hWnd.canvas);
+ var el = document.getElementById(SAEV_config.video.id);
+ if (el.nodeName == "DIV") {
+ hWnd.div = el;
+ hWnd.div.style.width = String(currentmode.native_width)+"px";
+ hWnd.div.style.height = String(currentmode.native_height)+"px";
+ hWnd.div.appendChild(hWnd.canvas);
+ } else
+ hWnd.div = null;
- hWnd.div = document.getElementById(SAEV_config.video.id);
- hWnd.div.style.width = String(currentmode.native_width)+"px";
- hWnd.div.style.height = String(currentmode.native_height)+"px";
- hWnd.div.appendChild(hWnd.video);
hWnd.shown = true;
}
else if (nCmdShow == SW_HIDE && hWnd.shown) {
- hWnd.div.removeChild(hWnd.video);
- //hWnd.div.style.width = "0px";
- //hWnd.div.style.height = "0px";
- hWnd.video = null;
+ if (hWnd.div !== null) {
+ hWnd.div.removeChild(hWnd.canvas);
+ hWnd.canvas = null;
+ }
+
hWnd.shown = false;
}
}
function GetWindowRect(hWnd, rect) {
- if (hWnd.shown) {
- var bcr = hWnd.div.getBoundingClientRect();
+ /*if (hWnd.shown) {
+ var bcr = hWnd.canvas.getBoundingClientRect();
rect.left = Math.floor(bcr.left);
rect.top = Math.floor(bcr.top);
rect.right = Math.floor(bcr.right);
rect.bottom = Math.floor(bcr.bottom);
- } else {
+ console.dir(bcr);
+ } else*/ {
rect.left = (screen.width >> 1) - (currentmode.native_width >> 1); if (rect.left < 0) rect.left = 0;
rect.top = (screen.height >> 1) - (currentmode.native_height >> 1); if (rect.top < 0) rect.top = 0;
rect.right = rect.left + currentmode.native_width;
@@ -1804,7 +1807,8 @@ function SAEO_Video() {
if (!SAEV_config.video.enabled)
return SAEE_None;
- if (!document.getElementById(SAEV_config.video.id))
+ var id = document.getElementById(SAEV_config.video.id);
+ if (id === null || (id.nodeName != "DIV" && id.nodeName != "CANVAS"))
return SAEE_Video_ElementNotFound;
if (SAEV_config.video.api == SAEC_Config_Video_API_WebGL && !SAEC_info.video.webGL) {