mirror of
https://github.com/fernandotcl/TinyEMU.git
synced 2025-10-17 15:13:13 +08:00
281 lines
8.8 KiB
JavaScript
281 lines
8.8 KiB
JavaScript
/*
|
|
* JS emulator library
|
|
*
|
|
* Copyright (c) 2017 Fabrice Bellard
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
mergeInto(LibraryManager.library, {
|
|
console_write: function(opaque, buf, len)
|
|
{
|
|
var str;
|
|
/* Note: we really send byte values. It would be up to the
|
|
* terminal to support UTF-8 */
|
|
str = String.fromCharCode.apply(String, HEAPU8.subarray(buf, buf + len));
|
|
term.write(str);
|
|
},
|
|
|
|
console_get_size: function(pw, ph)
|
|
{
|
|
var w, h, r;
|
|
r = term.getSize();
|
|
HEAPU32[pw >> 2] = r[0];
|
|
HEAPU32[ph >> 2] = r[1];
|
|
},
|
|
|
|
fs_export_file: function(filename, buf, buf_len)
|
|
{
|
|
var _filename = Pointer_stringify(filename);
|
|
// console.log("exporting " + _filename);
|
|
var data = HEAPU8.subarray(buf, buf + buf_len);
|
|
var file = new Blob([data], { type: "application/octet-stream" });
|
|
var url = URL.createObjectURL(file);
|
|
var a = document.createElement("a");
|
|
a.href = url;
|
|
a.setAttribute("download", _filename);
|
|
a.innerHTML = "downloading";
|
|
document.body.appendChild(a);
|
|
/* click on the link and remove it */
|
|
setTimeout(function() {
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
}, 50);
|
|
},
|
|
|
|
emscripten_async_wget3_data: function(url, request, user, password, post_data, post_data_len, arg, free, onload, onerror, onprogress) {
|
|
var _url = Pointer_stringify(url);
|
|
var _request = Pointer_stringify(request);
|
|
var _user;
|
|
var _password;
|
|
|
|
var http = new XMLHttpRequest();
|
|
|
|
if (user)
|
|
_user = Pointer_stringify(user);
|
|
else
|
|
_user = null;
|
|
if (password)
|
|
_password = Pointer_stringify(password);
|
|
else
|
|
_password = null;
|
|
|
|
http.open(_request, _url, true);
|
|
http.responseType = 'arraybuffer';
|
|
if (_user) {
|
|
http.setRequestHeader("Authorization", "Basic " + btoa(_user + ':' + _password));
|
|
}
|
|
|
|
var handle = Browser.getNextWgetRequestHandle();
|
|
|
|
// LOAD
|
|
http.onload = function http_onload(e) {
|
|
if (http.status == 200 || _url.substr(0,4).toLowerCase() != "http") {
|
|
var byteArray = new Uint8Array(http.response);
|
|
var buffer = _malloc(byteArray.length);
|
|
HEAPU8.set(byteArray, buffer);
|
|
if (onload) Runtime.dynCall('viiii', onload, [handle, arg, buffer, byteArray.length]);
|
|
if (free) _free(buffer);
|
|
} else {
|
|
if (onerror) Runtime.dynCall('viiii', onerror, [handle, arg, http.status, http.statusText]);
|
|
}
|
|
delete Browser.wgetRequests[handle];
|
|
};
|
|
|
|
// ERROR
|
|
http.onerror = function http_onerror(e) {
|
|
if (onerror) {
|
|
Runtime.dynCall('viiii', onerror, [handle, arg, http.status, http.statusText]);
|
|
}
|
|
delete Browser.wgetRequests[handle];
|
|
};
|
|
|
|
// PROGRESS
|
|
http.onprogress = function http_onprogress(e) {
|
|
if (onprogress) Runtime.dynCall('viiii', onprogress, [handle, arg, e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total : 0]);
|
|
};
|
|
|
|
// ABORT
|
|
http.onabort = function http_onabort(e) {
|
|
delete Browser.wgetRequests[handle];
|
|
};
|
|
|
|
// Useful because the browser can limit the number of redirection
|
|
try {
|
|
if (http.channel instanceof Ci.nsIHttpChannel)
|
|
http.channel.redirectionLimit = 0;
|
|
} catch (ex) { /* whatever */ }
|
|
|
|
if (_request == "POST") {
|
|
var _post_data = HEAPU8.subarray(post_data, post_data + post_data_len);
|
|
//Send the proper header information along with the request
|
|
http.setRequestHeader("Content-type", "application/octet-stream");
|
|
http.setRequestHeader("Content-length", post_data_len);
|
|
http.setRequestHeader("Connection", "close");
|
|
http.send(_post_data);
|
|
} else {
|
|
http.send(null);
|
|
}
|
|
|
|
Browser.wgetRequests[handle] = http;
|
|
|
|
return handle;
|
|
},
|
|
|
|
fs_wget_update_downloading: function (flag)
|
|
{
|
|
update_downloading(Boolean(flag));
|
|
},
|
|
|
|
fb_refresh: function(opaque, data, x, y, w, h, stride)
|
|
{
|
|
var i, j, v, src, image_data, dst_pos, display, dst_pos1, image_stride;
|
|
|
|
display = graphic_display;
|
|
/* current x = 0 and w = width for all refreshes */
|
|
// console.log("fb_refresh: x=" + x + " y=" + y + " w=" + w + " h=" + h);
|
|
image_data = display.image.data;
|
|
image_stride = display.width * 4;
|
|
dst_pos1 = (y * display.width + x) * 4;
|
|
for(i = 0; i < h; i = (i + 1) | 0) {
|
|
src = data;
|
|
dst_pos = dst_pos1;
|
|
for(j = 0; j < w; j = (j + 1) | 0) {
|
|
v = HEAPU32[src >> 2];
|
|
image_data[dst_pos] = (v >> 16) & 0xff;
|
|
image_data[dst_pos + 1] = (v >> 8) & 0xff;
|
|
image_data[dst_pos + 2] = v & 0xff;
|
|
image_data[dst_pos + 3] = 0xff; /* XXX: do it once */
|
|
src = (src + 4) | 0;
|
|
dst_pos = (dst_pos + 4) | 0;
|
|
}
|
|
data = (data + stride) | 0;
|
|
dst_pos1 = (dst_pos1 + image_stride) | 0;
|
|
}
|
|
display.ctx.putImageData(display.image, 0, 0, x, y, w, h);
|
|
},
|
|
|
|
net_recv_packet: function(bs, buf, buf_len)
|
|
{
|
|
if (net_state) {
|
|
net_state.recv_packet(HEAPU8.subarray(buf, buf + buf_len));
|
|
}
|
|
},
|
|
|
|
/* file buffer API */
|
|
file_buffer_get_new_handle: function()
|
|
{
|
|
var h;
|
|
if (typeof Browser.fbuf_table == "undefined") {
|
|
Browser.fbuf_table = new Object();
|
|
Browser.fbuf_next_handle = 1;
|
|
}
|
|
for(;;) {
|
|
h = Browser.fbuf_next_handle;
|
|
Browser.fbuf_next_handle++;
|
|
if (Browser.fbuf_next_handle == 0x80000000)
|
|
Browser.fbuf_next_handle = 1;
|
|
if (typeof Browser.fbuf_table[h] == "undefined") {
|
|
// console.log("new handle=" + h);
|
|
return h;
|
|
}
|
|
}
|
|
},
|
|
|
|
file_buffer_init: function(bs)
|
|
{
|
|
var h;
|
|
HEAPU32[bs >> 2] = 0;
|
|
HEAPU32[(bs + 4) >> 2] = 0;
|
|
},
|
|
|
|
file_buffer_resize__deps: ['file_buffer_get_new_handle'],
|
|
file_buffer_resize: function(bs, new_size)
|
|
{
|
|
var h, size, new_data, size1, i, data;
|
|
h = HEAPU32[bs >> 2];
|
|
size = HEAPU32[(bs + 4) >> 2];
|
|
if (new_size == 0) {
|
|
if (h != 0) {
|
|
delete Browser.fbuf_table[h];
|
|
h = 0;
|
|
}
|
|
} else if (size == 0) {
|
|
h = _file_buffer_get_new_handle();
|
|
new_data = new Uint8Array(new_size);
|
|
Browser.fbuf_table[h] = new_data;
|
|
} else if (size != new_size) {
|
|
data = Browser.fbuf_table[h];
|
|
new_data = new Uint8Array(new_size);
|
|
if (new_size > size) {
|
|
new_data.set(data, 0);
|
|
} else {
|
|
for(i = 0; i < new_size; i = (i + 1) | 0)
|
|
new_data[i] = data[i];
|
|
}
|
|
Browser.fbuf_table[h] = new_data;
|
|
}
|
|
HEAPU32[bs >> 2] = h;
|
|
HEAPU32[(bs + 4) >> 2] = new_size;
|
|
return 0;
|
|
},
|
|
|
|
file_buffer_reset: function(bs)
|
|
{
|
|
_file_buffer_resize(bs, 0);
|
|
_file_buffer_init(bs);
|
|
},
|
|
|
|
file_buffer_write: function(bs, offset, buf, size)
|
|
{
|
|
var h, data, i;
|
|
h = HEAPU32[bs >> 2];
|
|
if (h) {
|
|
data = Browser.fbuf_table[h];
|
|
for(i = 0; i < size; i = (i + 1) | 0) {
|
|
data[offset + i] = HEAPU8[buf + i];
|
|
}
|
|
}
|
|
},
|
|
|
|
file_buffer_read: function(bs, offset, buf, size)
|
|
{
|
|
var h, data, i;
|
|
h = HEAPU32[bs >> 2];
|
|
if (h) {
|
|
data = Browser.fbuf_table[h];
|
|
for(i = 0; i < size; i = (i + 1) | 0) {
|
|
HEAPU8[buf + i] = data[offset + i];
|
|
}
|
|
}
|
|
},
|
|
|
|
file_buffer_set: function(bs, offset, val, size)
|
|
{
|
|
var h, data, i;
|
|
h = HEAPU32[bs >> 2];
|
|
if (h) {
|
|
data = Browser.fbuf_table[h];
|
|
for(i = 0; i < size; i = (i + 1) | 0) {
|
|
data[offset + i] = val;
|
|
}
|
|
}
|
|
},
|
|
|
|
});
|