/*------------------------------------------------------------------------- | 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. -------------------------------------------------------------------------*/ /* global constants */ const SAEC_LITTLE_ENDIAN = (function() { var buffer = new ArrayBuffer(2); new DataView(buffer).setInt16(0, 256, true); return new Int16Array(buffer)[0] === 256; /* read is LE */ })(); //console.log("Little endian system: "+(SAEC_LITTLE_ENDIAN ? "Yes" : "No")); /*-----------------------------------------------------------------------*/ /* byte-swapping */ function SAEF_bswap16(v) { return ((v & 0x00ff) << 8) | ((v & 0xff00) >> 8); } function SAEF_bswap32(v) { return (((v & 0x000000ff) << 24) | ((v & 0x0000ff00) << 8) | ((v & 0x00ff0000) >>> 8) | ((v & 0xff000000) >>> 24)) >>> 0; } function SAEF_be16toh(v) { if (SAEC_LITTLE_ENDIAN) return ((v & 0x00ff) << 8) | ((v & 0xff00) >> 8); else return v; } function SAEF_be32toh(v) { if (SAEC_LITTLE_ENDIAN) return (((v & 0x000000ff) << 24) | ((v & 0x0000ff00) << 8) | ((v & 0x00ff0000) >>> 8) | ((v & 0xff000000) >>> 24)) >>> 0; else return v; } function SAEF_le32toh(v) { if (SAEC_LITTLE_ENDIAN) return v; else return (((v & 0x000000ff) << 24) | ((v & 0x0000ff00) << 8) | ((v & 0x00ff0000) >>> 8) | ((v & 0xff000000) >>> 24)) >>> 0; } function SAEF_le16toh(v) { if (SAEC_LITTLE_ENDIAN) return v; else return ((v & 0x00ff) << 8) | ((v & 0xff00) >> 8); } /*-----------------------------------------------------------------------*/ /* moving average */ function SAEO_MAvg(size) { var values = new Array(size); var size = size; var usage = 0; var offset = 0; var average = 0; this.clr = function () { usage = 0; offset = 0; average = 0; }; this.get = function() { return average / usage; /* return as float */ } this.set = function(newval) { if (usage < size) { values[usage++] = newval; average += newval; } else { average -= values[offset]; values[offset] = newval; average += newval; if (++offset >= size) offset -= size; } return average / usage; /* return as float */ } } /*-----------------------------------------------------------------------*/ /* CRC checksumming */ var SAEV_crc32Table = new Uint32Array(256); var SAEV_crc16Table = new Uint16Array(256); { var c, w; var n, k; for (n = 0; n < 256; n++) { c = n; w = n << 8; for (k = 0; k < 8; k++) { c = ((c >>> 1) ^ (c & 1 ? 0xedb88320 : 0)) >>> 0; w = ((w << 1) & 0xffff) ^ ((w & 0x8000) ? 0x1021 : 0); } SAEV_crc32Table[n] = c; SAEV_crc16Table[n] = w; } } function SAEF_crc32(buf,bufo, len) { var crc = 0xffffffff; if (typeof buf === "string") { while (len-- > 0) crc = SAEV_crc32Table[(crc ^ buf.charCodeAt(bufo++)) & 0xff] ^ (crc >>> 8); } else { while (len-- > 0) crc = SAEV_crc32Table[(crc ^ buf[bufo++]) & 0xff] ^ (crc >>> 8); } return (crc ^ 0xffffffff) >>> 0; } function SAEF_crc16(buf,bufo, len) { var crc = 0xffff; while (len-- > 0) crc = ((crc << 8) & 0xffff) ^ SAEV_crc16Table[((crc >> 8) ^ buf[bufo++]) & 0xff]; return crc; } /*-----------------------------------------------------------------------*/ /* Date/Time conversion */ function SAEF_gettimeofday(tv, tz) { var now = performance.now(); now += performance.timing.navigationStart; now = Math.floor(now * 1000); tv.tv_sec = Math.floor(now / 1000000); tv.tv_usec = now % 1000000; } function SAEF_timeval_to_amiga(tv, amiga, tickcount) { /* tv.tv_sec is secs since 1-1-1970 */ /* days since 1-1-1978 */ /* mins since midnight */ /* ticks past minute @ 50Hz */ const msecs_per_day = 24 * 60 * 60 * 1000; var t = tv.tv_sec * 1000 + Math.floor(tv.tv_usec / 1000); t -= (8 * 365 + 2) * 24 * 60 * 60 * 1000; if (t < 0) t = 0; amiga.days = Math.floor(t / msecs_per_day); t -= amiga.days * msecs_per_day; amiga.mins = Math.floor(t / (60 * 1000)); t -= amiga.mins * (60 * 1000); amiga.ticks = Math.floor(t / (1000 / tickcount)); } /*function SAEF_amiga_to_timeval(tv, days, mins, ticks, tickcount) { if (days < 0) days = 0; if (days > 9900 * 365) days = 9900 * 365; // in future far enough? if (mins < 0 || mins >= 24 * 60) mins = 0; if (ticks < 0 || ticks >= 60 * tickcount) ticks = 0; var t = ticks * 20; t += mins * 60 * 1000; t += days * 24 * 60 * 60 * 1000; t += (8 * 365 + 2) * 24 * 60 * 60 * 1000; tv.tv_sec = Math.floor(t / 1000); tv.tv_usec = (t % 1000) * 1000; }*/ /*-----------------------------------------------------------------------*/ function SAEF_memset(dst,dsto, value, length) { for (var i = dsto, j = dsto + length; i < j; i++) dst[i] = value; } function SAEF_memcpy(dst,dsto, src,srco, length) { for (var i = 0; i < length; i++) dst[dsto + i] = src[srco + i]; } /*-----------------------------------------------------------------------*/ function SAEF_Array2String(array, start, end) { if (typeof end == "undefined") end = array.length; if (typeof start == "undefined") start = 0; var string = ""; for (var i = start; i < end; i++) string += String.fromCharCode(array[i]); return string; } function SAEF_String2Array(string, start, end) { if (typeof end == "undefined") end = string.length; if (typeof start == "undefined") start = 0; var array = new Uint8Array(end - start); for (var i = start; i < end; i++) array[i - start] = string.charCodeAt(i); return array; } /*function SAEF_CopyArray(dst_array, src_array, src_end) { if (typeof src_end == "undefined") src_end = src_array.length; for (var i = 0; i < src_end; i++) { if (typeof dst_array[i] === 'undefined' || typeof src_array[i] === 'undefined') return 1; dst_array[i] = src_array[i]; } return 0; }*/ function SAEF_CompareArray(array1, array2, end2) { if (typeof end2 == "undefined") end2 = array2.length; for (var i = 0; i < end2; i++) { if (typeof array1[i] === 'undefined' || typeof array2[i] === 'undefined') return 1; if (array1[i] != array2[i]) return 1; } return 0; } function SAEF_CompareArrayAfter(array1, start1, array2, end2) { if (typeof end2 == "undefined") end2 = array2.length; for (var i = 0; i < end2; i++) { if (typeof array1[start1 + i] === 'undefined' || typeof array2[i] === 'undefined') return 1; if (array1[start1 + i] != array2[i]) return 1; } return 0; } /*-----------------------------------------------------------------------*/ /* Javascript sprintf - http://www.webtoolkit.info This is the only function that does not correspond to the global name space */ var sprintfWrapper = { init: function () { if (typeof arguments == "undefined") { return null; } if (arguments.length < 1) { return null; } if (typeof arguments[0] != "string") { return null; } if (typeof RegExp == "undefined") { return null; } var string = arguments[0]; var exp = new RegExp(/(%([%]|(\-)?(\+|\x20)?(0)?(\d+)?(\.(\d)?)?([bcdfosxX])))/g); var matches = []; var strings = []; var convCount = 0; var stringPosStart = 0; var stringPosEnd = 0; var matchPosEnd = 0; var newString = ""; var match; while (match = exp.exec(string)) { if (match[9]) { convCount += 1; } stringPosStart = matchPosEnd; stringPosEnd = exp.lastIndex - match[0].length; strings[strings.length] = string.substring(stringPosStart, stringPosEnd); matchPosEnd = exp.lastIndex; matches[matches.length] = { match: match[0], left: match[3] ? true : false, sign: match[4] || "", pad: match[5] || " ", min: match[6] || 0, precision: match[8], code: match[9] || "%", negative: !!(parseInt(arguments[convCount]) < 0), argument: String(arguments[convCount]) }; } strings[strings.length] = string.substring(matchPosEnd); if (matches.length == 0) { return string; } if ((arguments.length - 1) < convCount) { return null; } for (var i = 0; i < matches.length; i++) { var substitution; if (matches[i].code == "%") { substitution = "%" } else if (matches[i].code == "b") { matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(2)); substitution = sprintfWrapper.convert(matches[i], true); } else if (matches[i].code == "c") { matches[i].argument = String(String.fromCharCode(parseInt(Math.abs(parseInt(matches[i].argument))))); substitution = sprintfWrapper.convert(matches[i], true); } else if (matches[i].code == "d") { matches[i].argument = String(Math.abs(parseInt(matches[i].argument))); substitution = sprintfWrapper.convert(matches[i]); } else if (matches[i].code == "f") { matches[i].argument = String(Math.abs(parseFloat(matches[i].argument)).toFixed(matches[i].precision ? matches[i].precision : 6)); substitution = sprintfWrapper.convert(matches[i]); } else if (matches[i].code == "o") { matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(8)); substitution = sprintfWrapper.convert(matches[i]); } else if (matches[i].code == "s") { matches[i].argument = matches[i].argument.substring(0, matches[i].precision ? matches[i].precision : matches[i].argument.length); substitution = sprintfWrapper.convert(matches[i], true); } else if (matches[i].code == "x") { matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16)); substitution = sprintfWrapper.convert(matches[i]); } else if (matches[i].code == "X") { matches[i].argument = String(Math.abs(parseInt(matches[i].argument)).toString(16)); substitution = sprintfWrapper.convert(matches[i]).toUpperCase(); } else { substitution = matches[i].match; } newString += strings[i]; newString += substitution; } newString += strings[i]; return newString; }, convert: function (match, nosign) { if (nosign) { match.sign = ""; } else { match.sign = match.negative ? "-" : match.sign; } var l = match.min - match.argument.length + 1 - match.sign.length; var pad = new Array(l < 0 ? 0 : l).join(match.pad); if (!match.left) { if (match.pad == "0" || nosign) { return match.sign + pad + match.argument; } else { return pad + match.sign + match.argument; } } else { if (match.pad == "0" || nosign) { return match.sign + match.argument + pad.replace(/0/g, " "); } else { return match.sign + match.argument + pad; } } } }; var sprintf = sprintfWrapper.init; /*-----------------------------------------------------------------------*/ /* Z wrapper */ const SEEK_SET = 0; /* set file offset to offset */ const SEEK_CUR = 1; /* set file offset to current plus offset */ const SEEK_END = 2; /* set file offset to EOF plus offset */ /*struct zfile { TCHAR *name; TCHAR *originalname; uae_u8 *data; // unpacked data int dataseek; // use seek position even if real file uae_s64 size; // real size uae_s64 datasize; // available size (not yet unpacked completely?) uae_s64 allocsize; // memory allocated before realloc() needed again uae_s64 seek; // seek position int opencnt; };*/ function SAEO_ZFile() { this.name = ""; this.originalname = ""; this.data = null; // unpacked data this.dataseek = 0; // use seek position even if real file this.size = 0; // real size this.datasize = 0; // available size (not yet unpacked completely?) this.allocsize = 0; // memory allocated before realloc() needed again this.seek = 0; // seek position this.opencnt = 0; } /*---------------------------------*/ function SAEF_ZFile_create(prev, originalname) { var z = new SAEO_ZFile(); z.opencnt = 1; if (prev !== null && prev.originalname) z.originalname = prev.originalname; else if (originalname.length) z.originalname = originalname; return z; } function SAEF_ZFile_free(f) { f.name = ""; f.originalname = ""; f.data = null; } /*---------------------------------*/ function SAEF_ZFile_fopen_empty(prev, name, size) { var l = SAEF_ZFile_create(prev, ""); l.name = name.length ? name : ""; if (size) { l.data = new Uint8Array(size); /*if (!l.data) { xfree(l); return null; }*/ l.size = size; l.datasize = size; l.allocsize = size; } else { l.data = new Uint8Array(1000); l.size = 0; l.allocsize = 1000; } return l; } function SAEF_ZFile_fopen_load_zfile(f) { var l = SAEF_ZFile_fopen_empty(f, f.name, f.size); if (l === null) return null; SAEF_ZFile_fseek(f, 0, SEEK_SET); SAEF_ZFile_fread(l.data,0, f.size, 1, f); return l; } /*function SAEF_ZFile_fopen_data(name, size, data) { if (size) { var l = SAEF_ZFile_create(null, name); l.name = name.length ? name : ""; if (1) { // ptr l.data = data; } else { l.data = new Uint8Array(size); l.data.set(data); //memcpy(l.data, data, size); } l.size = size; l.datasize = size; l.allocsize = size; //OWN return l; } return null; }*/ function SAEF_ZFile_fopen_file(file) { if (file.size) { var l = SAEF_ZFile_create(null, file.name); l.name = file.name.length ? file.name : ""; if (0) { /* reference-mode. do not enable */ l.data = file.data; } else { l.data = new Uint8Array(file.size); //memcpy(l.data, data, size); if (typeof file.data === "string") l.data.set(SAEF_String2Array(file.data, 0, file.size)); else l.data.set(file.data); } l.size = file.size; l.datasize = file.size; l.allocsize = file.size; //OWN var magic = ((l.data[0] << 24) | (l.data[1] << 16) | (l.data[2] << 8) | (l.data[3])) >>> 0; //SAEF_log("SAEF_ZFile_fopen_file() opening '%s', %d/%d bytes, crc32 0x%08x, magic %08x", l.name, l.size, l.data.length, file.crc32 !== false ? file.crc32 : 0, magic); if (magic == 0x04034B50 || magic == 0x504B0304) SAEF_fatal(SAEE_Config_Compressed, "A ZIP file was detected. Compressed files are not yet supported."); //if (l.data[0] == 68 && l.data[1] == 77 && l.data[2] == 83 && l.data[3] == 33) { /* DMS! */ if (SAEF_CompareArray(l.data, SAEF_String2Array("DMS!"), 4) == 0) { var dms = new SAEO_DMS(); var f = dms.DMS2ADF(l); if (f !== null) { var data = SAEF_ZFile_getdata(f, 0, -1); file.name = SAEF_ZFile_getname(f); file.data = SAEF_Array2String(data); file.size = SAEF_ZFile_size(f); file.prot = false; return f; } } else if (SAEF_CompareArray(l.data, [0x00,0x00,0x03,0xf3,0x00,0x00,0x00,0x00], 8) == 0) { var f = SAER.disk.EXE2ADF(l); if (f !== null) { var data = SAEF_ZFile_getdata(f, 0, -1); file.name = SAEF_ZFile_getname(f); file.data = SAEF_Array2String(data); file.size = SAEF_ZFile_size(f); file.prot = false; return f; } } return l; } return null; } function SAEF_ZFile_fclose(f) { if (!f) return; if (f.opencnt < 0) { SAEF_warn("SAEF_ZFile_fclose() tried to free already closed filehandle!"); return; } f.opencnt--; if (f.opencnt > 0) return; f.opencnt = -100; SAEF_ZFile_free(f); } /*---------------------------------*/ function SAEF_ZFile_iscompressed(z) { return false; //z.data !== null ? 1 : 0; //ATT } /*---------------------------------*/ /*function SAEF_ZFile_truncate(z, size) { if (size < z.size) { z.size = size; if (z.size < z.datasize) z.datasize = z.size; if (z.size < z.seek) z.seek = z.size; return 1; } return 0; }*/ function SAEF_ZFile_resize(z, newsize) { //OWN if (newsize > z.allocsize) { z.allocsize = newsize; SAEF_log("SAEF_ZFile_resize() increase %d -> %d bytes", z.size, z.allocsize); var tmp = new Uint8Array(z.allocsize); tmp.set(z.data); z.data = tmp; z.datasize = z.size = newsize; return 1; } if (newsize < z.allocsize) { z.allocsize = newsize; SAEF_log("SAEF_ZFile_resize() decrease %d -> %d bytes", z.size, z.allocsize); var tmp = new Uint8Array(z.allocsize); tmp.set(z.data.subarray(0, z.allocsize)); z.data = tmp; z.datasize = z.size = newsize; return 1; } return 0; } function SAEF_ZFile_size(z) { return z.size; } /*---------------------------------*/ function SAEF_ZFile_ftell(z) { return z.seek; } function SAEF_ZFile_fseek(z, offset, mode) { var ret = 0; switch (mode) { case SEEK_SET: z.seek = offset; break; case SEEK_CUR: z.seek += offset; break; case SEEK_END: z.seek = z.size + offset; break; } if (z.seek < 0) { z.seek = 0; ret = 1; } if (z.seek > z.size) { z.seek = z.size; ret = 1; } return ret; } /*---------------------------------*/ /*function SAEF_ZFile_fread(b,bo, l1, l2, z) { var l = l1 * l2; if (z.datasize < z.size && z.seek + l > z.datasize) { SAEF_warn("SAEF_ZFile_fread() read beyond size"); return 0; } if (z.seek + l > z.size) { l2 = l1 ? Math.truncate((z.size - z.seek) / l1) : 0; if (l2 < 0) l2 = 0; l = l1 * l2; } //memcpy(b, z.data + z.seek, l1 * l2); if (typeof b === "string") { SAEF_warn("SAEF_ZFile_fread() string"); return 0; } else { var o = z.seek; if (typeof z.data === "string") { while (l-- > 0) b[bo++] = z.data.charCodeAt(o++); } else { while (l-- > 0) b[bo++] = z.data[o++]; } } z.seek += l1 * l2; return l2; } function SAEF_ZFile_fwrite(b,bo, l1, l2, z) { var off = z.seek + l1 * l2; if (z.allocsize == 0) { SAEF_warn("SAEF_ZFile_fwrite() allocsize == 0, aborting..."); return 0; } if (off > z.allocsize) { //if (z.allocsize < off) z.allocsize = off; z.allocsize += Math.floor(z.size / 2); if (z.allocsize < 10000) z.allocsize = 10000; SAEF_log("SAEF_ZFile_fwrite() relocate %d -> %d bytes", z.size, z.allocsize); var tmp = new Uint8Array(z.allocsize); tmp.cpy(z.data, z.size); z.data = tmp; z.datasize = z.size = off; } //memcpy(z.data + z.seek, b, l1 * l2); if (typeof b === "string") { SAEF_warn("SAEF_ZFile_fwrite() string"); return 0; } else { var l = l1 * l2; if (typeof z.data === "string") { var txt = "", len = l; while (l-- > 0) txt += String.fromCharCode(b[bo++]); var tmp = z.data.substr(0, z.seek) + txt + z.data.substr(z.seek + len); z.data = tmp; } else { var o = z.seek; while (l-- > 0) z.data[o++] = b[bo++]; } } z.seek += l1 * l2; if (z.seek > z.size) z.size = z.seek; if (z.size > z.datasize) z.datasize = z.size; return l2; }*/ function SAEF_ZFile_fread(b,bo, l1, l2, z) { if (z.datasize < z.size && z.seek + l1 * l2 > z.datasize) { SAEF_warn("SAEF_ZFile_fread() read beyond size"); return 0; } if (z.seek + l1 * l2 > z.size) { l2 = l1 ? Math.truncate((z.size - z.seek) / l1) : 0; if (l2 < 0) l2 = 0; } b.set(z.data.subarray(z.seek, z.seek + l1 * l2), bo); //memcpy (b, z.data + z.offset + z.seek, l1 * l2); z.seek += l1 * l2; return l2; } function SAEF_ZFile_fwrite(b,bo, l1, l2, z) { var off = z.seek + l1 * l2; //s64 if (z.allocsize == 0) { SAEF_warn("SAEF_ZFile_fwrite() allocsize == 0, aborting..."); return 0; } if (off > z.allocsize) { if (z.allocsize < off) z.allocsize = off; z.allocsize += (z.size >> 1); if (z.allocsize < 10000) z.allocsize = 10000; //z.data = xrealloc (uae_u8, z.data, z.allocsize); SAEF_log("SAEF_ZFile_fwrite() relocate %d -> %d bytes", z.size, z.allocsize); var tmp = new Uint8Array(z.allocsize); tmp.set(z.data); z.data = tmp; z.datasize = z.size = off; } z.data.set(b.subarray(bo, bo + l1 * l2), z.seek); //memcpy (z.data + z.seek, b, l1 * l2); z.seek += l1 * l2; if (z.seek > z.size) z.size = z.seek; if (z.size > z.datasize) z.datasize = z.size; return l2; } /*---------------------------------*/ /*function SAEF_ZFile_ferror(z) { return 0; }*/ function SAEF_ZFile_getdata(z, offset, len) { var pos = SAEF_ZFile_ftell(z); if (len < 0) { SAEF_ZFile_fseek(z, 0, SEEK_END); len = SAEF_ZFile_ftell(z); SAEF_ZFile_fseek(z, 0, SEEK_SET); } var b = new Uint8Array(len); SAEF_ZFile_fseek(z, offset, SEEK_SET); SAEF_ZFile_fread(b,0, len, 1, z); SAEF_ZFile_fseek(z, pos, SEEK_SET); return b; } function SAEF_ZFile_getname(f) { return f ? f.name : null; } function SAEF_ZFile_getoriginalname(f) { return f ? f.originalname : null; } function SAEF_ZFile_getfilename(f) { /*if (!f.name.length) return null; for (var i = f.name.length - 1; i >= 0; i--) { if (f.name[i] == '\\' || f.name[i] == '/' || f.name[i] == ':') { i++; return &f.name[i]; } }*/ return f.name; } /*---------------------------------*/ function SAEF_ZFile_crc32(f) { if (f === null) return 0; //if (f.dataBuffer) return SAEF_crc32(f.data,0, f.size); /*var pos = SAEF_ZFile_ftell (f); SAEF_ZFile_fseek (f, 0, SEEK_END); var size = SAEF_ZFile_ftell (f); var p = xmalloc (uae_u8, size); if (!p) return 0; memset (p, 0, size); SAEF_ZFile_fseek (f, 0, SEEK_SET); SAEF_ZFile_fread (p, 1, size, f); SAEF_ZFile_fseek (f, pos, SEEK_SET); var crc = p.crc32(size); xfree (p); return crc;*/ } /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* some testing stuff */ function CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) { var hEvent = new uae_sem_t(); hEvent.manual = bManualReset != 0; hEvent.signaled = bInitialState != 0; return hEvent; } function SetEvent(hEvent) { hEvent.signaled = true; return true; } function ResetEvent(hEvent) { hEvent.signaled = false; return true; } const INFINITE = 0xFFFFFFFF; const WAIT_ABANDONED = 0x00000080; const WAIT_OBJECT_0 = 0x00000000; const WAIT_TIMEOUT = 0x00000102; const WAIT_FAILED = 0xFFFFFFFF; function WaitForSingleObject(hEvent, dwMilliseconds) { if (!hEvent.signaled) { if (dwMilliseconds == INFINITE) { var cnt = 0; while (!hEvent.signaled && cnt++ < 200) SAEF_sleep(5); } else if (dwMilliseconds > 0) SAEF_sleep(dwMilliseconds); } if (hEvent.signaled) { if (!hEvent.manual) //&& waiting > 0 ResetEvent(hEvent); return WAIT_OBJECT_0; } return WAIT_TIMEOUT; } /*---------------------------------*/ function uae_sem_init(event, manual_reset, initial_state) { if (event.handle) { if (initial_state) SetEvent(event.handle); else ResetEvent(event.handle); } else event.handle = CreateEvent(null, manual_reset, initial_state, null); } function uae_sem_wait(event) { WaitForSingleObject(event.handle, INFINITE); } function uae_sem_post(event) { SetEvent(event.handle); } /*function uae_sem_trywait(event) { return WaitForSingleObject(event.handle, 0) == WAIT_OBJECT_0 ? 0 : -1; }*/ /*function uae_sem_destroy(event) { if (event.handle) { //CloseHandle(event); event.handle = null; } }*/ /*---------------------------------*/ //typedef HANDLE uae_sem_t; //typedef HANDLE uae_thread_id; function uae_sem_t() { this.value = null; this.manual = false; this.signaled = false; } /*typedef union { int i; uae_u32 u32; void *pv; } uae_pt;*/ function smp_comm_pipe() { //this.lock = new uae_sem_t(); //this.reader_wait = new uae_sem_t(); //this.writer_wait = new uae_sem_t(); this.lock = { handle:null }; this.reader_wait = { handle:null }; this.writer_wait = { handle:null }; this.data = null; //uae_pt * this.dataView = null; //OWN this.size = 0; this.chunks = 0; this.rdp = 0; //volatile this.wrp = 0; //volatile this.reader_waiting = 0; //volatile this.writer_waiting = 0; //volatile } function init_comm_pipe(p, size, chunks) { //p.data = (uae_pt *)malloc (size*sizeof (uae_pt)); p.lock = { handle:null }; p.reader_wait = { handle:null }; p.writer_wait = { handle:null }; p.data = new ArrayBuffer(size * 4); p.dataView = new DataView(p.data); p.size = size; p.chunks = chunks; p.rdp = p.wrp = 0; p.reader_waiting = 0; p.writer_waiting = 0; uae_sem_init(p.lock, 0, 1); uae_sem_init(p.reader_wait, 0, 0); uae_sem_init(p.writer_wait, 0, 0); } /*function destroy_comm_pipe(p) { uae_sem_destroy(p.lock); uae_sem_destroy(p.reader_wait); uae_sem_destroy(p.writer_wait); }*/ /*function comm_pipe_has_data(p) { return p.rdp != p.wrp; }*/ function read_comm_pipe_pt_blocking(p, type) { var data; uae_sem_wait(p.lock); if (p.rdp == p.wrp) { /* Pipe empty */ p.reader_waiting = 1; uae_sem_post(p.lock); uae_sem_wait(p.reader_wait); uae_sem_wait(p.lock); } switch (type) { case 1: data = p.dataView.getInt32(p.rdp << 2, false); break; case 2: case 3: data = p.dataView.getUint32(p.rdp << 2, false); break; } p.rdp = (p.rdp + 1) % p.size; /* We ignore chunks here. If this is a problem, make the size bigger in the init call. */ if (p.writer_waiting) { p.writer_waiting = 0; uae_sem_post(p.writer_wait); } uae_sem_post(p.lock); return data; } function read_comm_pipe_int_blocking(p) { //var foo = read_comm_pipe_pt_blocking(p); return foo.i; return read_comm_pipe_pt_blocking(p, 1); } function read_comm_pipe_u32_blocking(p) { //var foo = read_comm_pipe_pt_blocking(p); return foo.u32; return read_comm_pipe_pt_blocking(p, 2); } function read_comm_pipe_pvoid_blocking(p) { //var foo = read_comm_pipe_pt_blocking(p); return foo.pv; return read_comm_pipe_pt_blocking(p, 3); } function maybe_wake_reader(p, no_buffer) { if (p.reader_waiting && (no_buffer || ((p.wrp - p.rdp + p.size) % p.size) >= p.chunks)) { p.reader_waiting = 0; uae_sem_post(p.reader_wait); } } function write_comm_pipe_pt(p, type, data, no_buffer) { var nxwrp = (p.wrp + 1) % p.size; if (p.reader_waiting) { /* No need to do all the locking */ switch (type) { case 1: p.dataView.setInt32(p.wrp << 2, data, SAEC_LITTLE_ENDIAN); break; case 2: case 3: p.dataView.setUint32(p.wrp << 2, data, SAEC_LITTLE_ENDIAN); break; } p.wrp = nxwrp; maybe_wake_reader(p, no_buffer); return; } uae_sem_wait(p.lock); if (nxwrp == p.rdp) { /* Pipe full */ p.writer_waiting = 1; uae_sem_post(p.lock); uae_sem_wait(p.writer_wait); uae_sem_wait(p.lock); } switch (type) { case 1: p.dataView.setInt32(p.wrp << 2, data, SAEC_LITTLE_ENDIAN); break; case 2: case 3: p.dataView.setUint32(p.wrp << 2, data, SAEC_LITTLE_ENDIAN); break; } p.wrp = nxwrp; maybe_wake_reader(p, no_buffer); uae_sem_post(p.lock); } function write_comm_pipe_int(p, data, no_buffer) { //var foo; foo.i = data; write_comm_pipe_pt(p, foo, no_buffer); write_comm_pipe_pt(p, 1, data, no_buffer); } function write_comm_pipe_u32(p, data, no_buffer) { //var foo; foo.u32 = data; write_comm_pipe_pt(p, foo, no_buffer); write_comm_pipe_pt(p, 2, data, no_buffer); } function write_comm_pipe_pvoid (p, data, no_buffer) { //var foo; foo.pv = data; write_comm_pipe_pt(p, foo, no_buffer); write_comm_pipe_pt(p, 3, data, no_buffer); } /*-----------------------------------------------------------------------*/ //extern HANDLE AVTask; //typedef unsigned (__stdcall *BEGINTHREADEX_FUNCPTR)(void *); /*struct thparms { void *(*f)(void*); void *arg; }; static unsigned __stdcall thread_init (void *f) { struct thparms *thp = (struct thparms*)f; void *(*fp)(void*) = thp->f; void *arg = thp->arg; xfree (f); __try { fp (arg); } __except (WIN32_ExceptionFilter (GetExceptionInformation (), GetExceptionCode ())) {} return 0; } void uae_end_thread (uae_thread_id *tid) { if (tid) { CloseHandle (*tid); *tid = NULL; } } STATIC_INLINE void uae_wait_thread (uae_thread_id tid) { WaitForSingleObject (tid, INFINITE); CloseHandle (tid); } int uae_start_thread (const TCHAR *name, void *(*f)(void *), void *arg, uae_thread_id *tid) { HANDLE hThread; int result = 1; unsigned foo; struct thparms *thp; thp = xmalloc (struct thparms, 1); thp->f = f; thp->arg = arg; hThread = (HANDLE)_beginthreadex (NULL, 0, thread_init, thp, 0, &foo); if (hThread) { if (name) { //write_log (_T("Thread '%s' started (%d)\n"), name, hThread); if (!AVTask) { SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST); } else { AvSetMmThreadPriority(AVTask, AVRT_PRIORITY_HIGH); } } } else { result = 0; write_log (_T("Thread '%s' failed to start!?\n"), name ? name : _T("")); } if (tid) *tid = hThread; else CloseHandle (hThread); return result; }*/ /*int uae_start_thread_fast (void *(*f)(void *), void *arg, uae_thread_id *tid) { int v = uae_start_thread (NULL, f, arg, tid); if (*tid) { if (!AVTask) { SetThreadPriority (*tid, THREAD_PRIORITY_HIGHEST); } else { AvSetMmThreadPriority(AVTask, AVRT_PRIORITY_HIGH); } } return v; }*/ /*DWORD_PTR cpu_affinity = 1, cpu_paffinity = 1; void uae_set_thread_priority (uae_thread_id *tid, int pri) { #if 0 int pri2; HANDLE th; if (tid) th = *tid; else th = GetCurrentThread (); pri2 = GetThreadPriority (th); if (pri2 == THREAD_PRIORITY_ERROR_RETURN) pri2 = 0; if (pri > 0) pri2 = THREAD_PRIORITY_HIGHEST; else pri2 = THREAD_PRIORITY_ABOVE_NORMAL; pri2 += pri; if (pri2 > 1) pri2 = 1; if (pri2 < -1) pri2 = -1; SetThreadPriority (th, pri2); #endif if (!AVTask) { if (!SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); } else { AvSetMmThreadPriority(AVTask, AVRT_PRIORITY_HIGH); } }*/ /*-----------------------------------------------------------------------*/