From ea1d34267e36e3b095e221f36ac3336914d739a7 Mon Sep 17 00:00:00 2001 From: Rupert Hausberger Date: Sat, 30 Jul 2016 01:31:36 +0200 Subject: [PATCH] update 0.9.0 --- example.css | 78 +++++++ example.htm | 155 ++++++++++++++ example.js | 548 +++++++++++++++++++++++++++++++++++++++++++++++ example2.htm | 155 ++++++++++++++ index.js | 80 ++++--- sae/amiga.js | 27 ++- sae/config.js | 8 +- sae/input.js | 8 + sae/m68k.js | 6 +- sae/playfield.js | 2 +- sae/video.js | 48 +++-- 11 files changed, 1051 insertions(+), 64 deletions(-) create mode 100644 example.css create mode 100644 example.htm create mode 100644 example.js create mode 100644 example2.htm 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 + + + + + + + + + + + +
PWRHD000000
+
Config + + + + + + + + + + + + + + + + + +
Amiga Model + +
Resolution + + +
Kickstart ROM + + <unset> (required) + + +
Floppy (DF0) + + <empty> + + +
+
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 + + + + + + + + + + + +
PWRHD000000
+
Config + + + + + + + + + + + + + + + + + +
Amiga Model + +
Resolution + + +
Kickstart ROM + + <unset> (required) + + +
Floppy (DF0) + + <empty> + + +
+
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) {