mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-12 03:29:31 +00:00
zmachine: working on status bar window
This commit is contained in:
parent
0f19983654
commit
caabcb8196
|
@ -575,6 +575,13 @@ div.asset_toolbar {
|
||||||
user-select: text;
|
user-select: text;
|
||||||
font-family: Verdana, Geneva, sans-serif;
|
font-family: Verdana, Geneva, sans-serif;
|
||||||
}
|
}
|
||||||
|
.transcript-split {
|
||||||
|
padding: 0.5em;
|
||||||
|
background: #eee;
|
||||||
|
box-shadow: 0 8px 6px -6px RGBA(0,0,0,0.3);
|
||||||
|
z-index: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
.transcript-line {
|
.transcript-line {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
|
|
|
@ -31,82 +31,129 @@ declare var ZVM;
|
||||||
// https://inform-fiction.org/zmachine/standards/z1point0/sect15.html#read_char
|
// https://inform-fiction.org/zmachine/standards/z1point0/sect15.html#read_char
|
||||||
// https://manpages.debian.org/testing/inform6-compiler/inform6.1.en.html
|
// https://manpages.debian.org/testing/inform6-compiler/inform6.1.en.html
|
||||||
|
|
||||||
class GlkWindow {
|
|
||||||
//area: HTMLElement;
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IFZVM {
|
interface IFZVM {
|
||||||
start();
|
start();
|
||||||
run();
|
run();
|
||||||
version : number;
|
version: number;
|
||||||
pc : number;
|
pc: number;
|
||||||
ram : DataView;
|
ram: DataView;
|
||||||
stack : DataView;
|
stack: DataView;
|
||||||
read_data : {buffer?};
|
read_data: { buffer?};
|
||||||
handle_line_input(len:number);
|
handle_line_input(len: number);
|
||||||
handle_char_input(charcode:number);
|
handle_char_input(charcode: number);
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlkImpl {
|
class GlkWindow {
|
||||||
vm : IFZVM;
|
|
||||||
page: HTMLElement;
|
page: HTMLElement;
|
||||||
input: HTMLInputElement;
|
stream: number;
|
||||||
|
|
||||||
curline: HTMLElement;
|
curline: HTMLElement;
|
||||||
curstyle: number;
|
curstyle: number;
|
||||||
reverse: boolean;
|
reverse: boolean;
|
||||||
waitingfor: "line" | "char" | null;
|
col: number;
|
||||||
focused = false;
|
row: number;
|
||||||
exited = false;
|
|
||||||
|
|
||||||
constructor(page: HTMLElement, input: HTMLInputElement) {
|
constructor(page: HTMLElement, stream: number) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.input = input;
|
this.stream = stream;
|
||||||
this.reset();
|
|
||||||
}
|
|
||||||
reset() {
|
|
||||||
this.exited = false;
|
|
||||||
this.clear();
|
this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.curline = null;
|
this.curline = null;
|
||||||
this.curstyle = 0;
|
this.curstyle = 0;
|
||||||
this.reverse = false;
|
this.reverse = false;
|
||||||
// keep from losing input handlers
|
this.col = 0;
|
||||||
this.hideinput();
|
this.row = -1;
|
||||||
$(this.page).empty();
|
$(this.page).empty();
|
||||||
}
|
}
|
||||||
|
ensureline() {
|
||||||
|
if (this.curline == null) {
|
||||||
|
this.curline = $('<div class="transcript-line"/>')[0];
|
||||||
|
this.page.appendChild(this.curline);
|
||||||
|
this.row++;
|
||||||
|
this.col = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flushline() {
|
||||||
|
this.curline = null;
|
||||||
|
}
|
||||||
|
// TODO: support fixed-width window (use CSS grid?)
|
||||||
|
addtext(line: string, style: number) {
|
||||||
|
this.ensureline();
|
||||||
|
if (line.length) {
|
||||||
|
var span = $("<span/>").text(line).appendTo(this.curline);
|
||||||
|
for (var i = 0; i < 8; i++) {
|
||||||
|
if (style & (1 << i))
|
||||||
|
span.addClass("transcript-style-" + (1 << i));
|
||||||
|
}
|
||||||
|
if (this.reverse) span.addClass("transcript-reverse");
|
||||||
|
//span.data('vmip', this.vm.pc);
|
||||||
|
this.col += line.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put_jstring(val: string) {
|
||||||
|
var lines = val.split("\n");
|
||||||
|
for (var i = 0; i < lines.length; i++) {
|
||||||
|
if (i > 0) this.flushline();
|
||||||
|
this.addtext(lines[i], this.curstyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move_cursor(col, row) {
|
||||||
|
// TODO
|
||||||
|
if (row == this.row && col > this.col) {
|
||||||
|
for (var i=this.col; i<col; i++)
|
||||||
|
this.addtext(' ', this.curstyle);
|
||||||
|
}
|
||||||
|
this.col = col;
|
||||||
|
this.row = row;
|
||||||
|
if (row == 0 && col == 0)
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GlkImpl {
|
||||||
|
vm: IFZVM;
|
||||||
|
input: HTMLInputElement;
|
||||||
|
curwnd: GlkWindow;
|
||||||
|
windows: { [win: number]: GlkWindow };
|
||||||
|
windowcount: number;
|
||||||
|
waitingfor: "line" | "char" | null;
|
||||||
|
focused = false;
|
||||||
|
exited = false;
|
||||||
|
|
||||||
|
constructor(page: HTMLElement, input: HTMLInputElement, upper: HTMLElement) {
|
||||||
|
this.windows = {
|
||||||
|
1: new GlkWindow(page, 1),
|
||||||
|
2: new GlkWindow(upper, 2),
|
||||||
|
3: new GlkWindow(null, 3), // fake window for resizing
|
||||||
|
};
|
||||||
|
this.input = input;
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
reset() {
|
||||||
|
this.windowcount = 0;
|
||||||
|
this.exited = false;
|
||||||
|
this.curwnd = this.windows[1];
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
clear() {
|
||||||
|
this.curwnd.clear();
|
||||||
|
}
|
||||||
init(options) {
|
init(options) {
|
||||||
this.vm = options.vm;
|
this.vm = options.vm;
|
||||||
this.vm.start();
|
this.vm.start();
|
||||||
}
|
}
|
||||||
fatal_error(s:string) {
|
fatal_error(s: string) {
|
||||||
throw new EmuHalt(s);
|
throw new EmuHalt(s);
|
||||||
}
|
}
|
||||||
update() {
|
update() {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
glk_exit() {
|
|
||||||
this.exited = true;
|
|
||||||
this.flushline();
|
|
||||||
this.addtext("** Game exited **", 1);
|
|
||||||
}
|
|
||||||
glk_window_clear(win) {
|
|
||||||
console.log('glk_window_clear', arguments);
|
|
||||||
this.clear();
|
|
||||||
}
|
|
||||||
glk_request_line_event_uni(win, buf, initlen) {
|
|
||||||
this.waitingfor = 'line';
|
|
||||||
this.focusinput();
|
|
||||||
}
|
|
||||||
glk_request_char_event_uni(win, buf, initlen) {
|
|
||||||
this.waitingfor = 'char';
|
|
||||||
this.focusinput();
|
|
||||||
}
|
|
||||||
focusinput() {
|
focusinput() {
|
||||||
this.ensureline();
|
this.ensureline();
|
||||||
// don't steal focus while editing
|
// don't steal focus while editing
|
||||||
$(this.input).appendTo(this.curline).show()[0].scrollIntoView();
|
$(this.input).appendTo(this.curwnd.curline).show()[0].scrollIntoView();
|
||||||
if (this.focused) {
|
if (this.focused) {
|
||||||
$(this.input).focus();
|
$(this.input).focus();
|
||||||
}
|
}
|
||||||
|
@ -117,7 +164,7 @@ class GlkImpl {
|
||||||
$(this.input).removeClass('transcript-input-char')
|
$(this.input).removeClass('transcript-input-char')
|
||||||
}
|
}
|
||||||
hideinput() {
|
hideinput() {
|
||||||
$(this.input).appendTo($(this.page).parent()).hide();
|
$(this.input).appendTo($(this.curwnd.page).parent()).hide();
|
||||||
}
|
}
|
||||||
clearinput() {
|
clearinput() {
|
||||||
this.input.value = '';
|
this.input.value = '';
|
||||||
|
@ -129,13 +176,12 @@ class GlkImpl {
|
||||||
this.sendinput(this.input.value.toString());
|
this.sendinput(this.input.value.toString());
|
||||||
}
|
}
|
||||||
} else if (this.waitingfor == 'char') {
|
} else if (this.waitingfor == 'char') {
|
||||||
this.vm.handle_char_input(e.keyCode);
|
this.sendchar(e.keyCode);
|
||||||
this.vm.run();
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendinput(s: string) {
|
sendinput(s: string) {
|
||||||
this.addtext(s, Const.style_Input);
|
this.curwnd.addtext(s, Const.style_Input);
|
||||||
this.flushline();
|
this.flushline();
|
||||||
if (this.vm.read_data.buffer) {
|
if (this.vm.read_data.buffer) {
|
||||||
for (var i = 0; i < s.length; i++) {
|
for (var i = 0; i < s.length; i++) {
|
||||||
|
@ -144,43 +190,59 @@ class GlkImpl {
|
||||||
this.vm.handle_line_input(s.length);
|
this.vm.handle_line_input(s.length);
|
||||||
}
|
}
|
||||||
this.clearinput();
|
this.clearinput();
|
||||||
|
this.hideinput(); // keep from losing input handlers
|
||||||
|
this.vm.run();
|
||||||
|
}
|
||||||
|
sendchar(code: number) {
|
||||||
|
this.vm.handle_char_input(code);
|
||||||
|
this.hideinput(); // keep from losing input handlers
|
||||||
this.vm.run();
|
this.vm.run();
|
||||||
}
|
}
|
||||||
ensureline() {
|
ensureline() {
|
||||||
$(this.input).hide();
|
$(this.input).hide();
|
||||||
if (this.curline == null) {
|
this.curwnd.ensureline();
|
||||||
this.curline = $('<div class="transcript-line"/>')[0];
|
|
||||||
this.page.appendChild(this.curline);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
flushline() {
|
flushline() {
|
||||||
this.curline = null;
|
this.curwnd.flushline();
|
||||||
}
|
}
|
||||||
addtext(line: string, style: number) {
|
|
||||||
this.ensureline();
|
glk_exit() {
|
||||||
if (line.length) {
|
this.exited = true;
|
||||||
var span = $("<span/>").text(line).appendTo(this.curline);
|
this.flushline();
|
||||||
for (var i=0; i<8; i++) {
|
this.windows[1].addtext("** Game exited **", 1);
|
||||||
if (style & (1<<i))
|
|
||||||
span.addClass("transcript-style-" + (1<<i));
|
|
||||||
}
|
|
||||||
if (this.reverse) span.addClass("transcript-reverse");
|
|
||||||
span.data('vmip', this.vm.pc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
glk_window_clear(win) {
|
||||||
|
console.log('glk_window_clear', arguments);
|
||||||
|
this.windows[win].clear();
|
||||||
|
}
|
||||||
|
glk_request_line_event_uni(win, buf, initlen) {
|
||||||
|
this.waitingfor = 'line';
|
||||||
|
this.focusinput();
|
||||||
|
}
|
||||||
|
glk_request_char_event_uni(win, buf, initlen) {
|
||||||
|
this.waitingfor = 'char';
|
||||||
|
this.focusinput();
|
||||||
|
}
|
||||||
|
|
||||||
glk_put_jstring(val: string, allbytes) {
|
glk_put_jstring(val: string, allbytes) {
|
||||||
var lines = val.split("\n");
|
//console.log('glk_put_jstring', arguments);
|
||||||
for (var i = 0; i < lines.length; i++) {
|
this.curwnd.put_jstring(val);
|
||||||
if (i > 0) this.flushline();
|
|
||||||
this.addtext(lines[i], this.curstyle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
glk_put_jstring_stream(stream: number, val: string) {
|
||||||
|
//console.log('glk_put_jstring_stream', arguments);
|
||||||
|
this.windows[stream].put_jstring(val);
|
||||||
|
}
|
||||||
|
glk_put_char_stream_uni(stream: number, ch: number) {
|
||||||
|
//console.log('glk_put_char_stream_uni', arguments);
|
||||||
|
this.windows[stream].put_jstring(String.fromCharCode(ch));
|
||||||
|
}
|
||||||
|
glk_set_style(val) {
|
||||||
|
this.curwnd.curstyle = val;
|
||||||
|
}
|
||||||
|
/*
|
||||||
glk_put_char(ch) {
|
glk_put_char(ch) {
|
||||||
console.log('glk_put_char', arguments);
|
console.log('glk_put_char', arguments);
|
||||||
}
|
}
|
||||||
glk_put_char_stream(str, ch) {
|
|
||||||
console.log('glk_put_char_stream', arguments);
|
|
||||||
}
|
|
||||||
glk_put_string(val) {
|
glk_put_string(val) {
|
||||||
console.log('glk_put_string', arguments);
|
console.log('glk_put_string', arguments);
|
||||||
}
|
}
|
||||||
|
@ -193,9 +255,6 @@ class GlkImpl {
|
||||||
glk_put_buffer_stream(str, arr) {
|
glk_put_buffer_stream(str, arr) {
|
||||||
console.log('glk_put_buffer_stream', arguments);
|
console.log('glk_put_buffer_stream', arguments);
|
||||||
}
|
}
|
||||||
glk_set_style(val) {
|
|
||||||
this.curstyle = val;
|
|
||||||
}
|
|
||||||
glk_set_style_stream(str, val) {
|
glk_set_style_stream(str, val) {
|
||||||
console.log('glk_set_style_stream', arguments);
|
console.log('glk_set_style_stream', arguments);
|
||||||
}
|
}
|
||||||
|
@ -208,6 +267,7 @@ class GlkImpl {
|
||||||
glk_get_buffer_stream(str, buf) {
|
glk_get_buffer_stream(str, buf) {
|
||||||
console.log('glk_get_buffer_stream', arguments);
|
console.log('glk_get_buffer_stream', arguments);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
glk_char_to_lower(val) {
|
glk_char_to_lower(val) {
|
||||||
if (val >= 0x41 && val <= 0x5A)
|
if (val >= 0x41 && val <= 0x5A)
|
||||||
return val + 0x20;
|
return val + 0x20;
|
||||||
|
@ -223,10 +283,10 @@ class GlkImpl {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
glk_stylehint_set(wintype, styl, hint, value) {
|
glk_stylehint_set(wintype, styl, hint, value) {
|
||||||
console.log('glk_stylehint_set', arguments);
|
//console.log('glk_stylehint_set', arguments);
|
||||||
}
|
}
|
||||||
glk_stylehint_clear(wintype, styl, hint) {
|
glk_stylehint_clear(wintype, styl, hint) {
|
||||||
console.log('glk_stylehint_clear', arguments);
|
//console.log('glk_stylehint_clear', arguments);
|
||||||
}
|
}
|
||||||
glk_style_distinguish(win, styl1, styl2) {
|
glk_style_distinguish(win, styl1, styl2) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -241,40 +301,58 @@ class GlkImpl {
|
||||||
}
|
}
|
||||||
glk_window_open(splitwin, method, size, wintype, rock) {
|
glk_window_open(splitwin, method, size, wintype, rock) {
|
||||||
console.log('glk_window_open', arguments);
|
console.log('glk_window_open', arguments);
|
||||||
if (splitwin) console.log("split windows are not supported");
|
if (splitwin) {
|
||||||
return splitwin ? 0 : 1; // 0 = no window, 1 = main window
|
// only support status lines for now
|
||||||
|
if (method != 0x12 || wintype != 4 || size != 1) return 0;
|
||||||
|
$(this.windows[2].page).show();
|
||||||
|
}
|
||||||
|
return ++this.windowcount;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
glk_window_close(win) {
|
glk_window_close(win) {
|
||||||
console.log('glk_window_close', arguments);
|
console.log('glk_window_close', arguments);
|
||||||
this.windows.pop(); // TODO
|
if (win == 2) $(this.windows[win].page).hide();
|
||||||
}
|
}
|
||||||
glk_window_get_parent(win) {
|
glk_window_get_parent(win) {
|
||||||
console.log('glk_window_get_parent', arguments);
|
console.log('glk_window_get_parent', arguments);
|
||||||
|
if (win == 1) return 0;
|
||||||
|
else return 1;
|
||||||
}
|
}
|
||||||
glk_window_set_arrangement(win) {
|
glk_window_move_cursor(win, col, row) {
|
||||||
|
console.log('glk_window_move_cursor', arguments);
|
||||||
|
this.windows[win].move_cursor(col, row);
|
||||||
|
}
|
||||||
|
glk_window_set_arrangement(win, method, size, unknown) {
|
||||||
console.log('glk_window_set_arrangement', arguments);
|
console.log('glk_window_set_arrangement', arguments);
|
||||||
|
// TODO?
|
||||||
}
|
}
|
||||||
glk_window_get_stream(win) {
|
glk_window_get_stream(win) {
|
||||||
console.log('glk_window_get_stream', arguments);
|
console.log('glk_window_get_stream', arguments);
|
||||||
|
return this.windows[win].stream;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
glk_set_window(win) {
|
glk_set_window(win) {
|
||||||
console.log('glk_set_window', arguments);
|
console.log('glk_set_window', arguments);
|
||||||
//if (!win) gli_currentstr = null;
|
this.curwnd = this.windows[win];
|
||||||
//else gli_currentstr = win.str;
|
if (this.curwnd == null) this.fatal_error("no window " + win);
|
||||||
}
|
}
|
||||||
glk_window_get_size(win, widthref, heightref) {
|
glk_window_get_size(win, widthref: RefBox, heightref: RefBox) {
|
||||||
console.log('glk_window_get_size', arguments);
|
console.log('glk_window_get_size', arguments);
|
||||||
|
// TODO: made up sizes, only status line supported
|
||||||
|
if (widthref) widthref.set_value(40);
|
||||||
|
if (heightref) heightref.set_value(win == 1 ? 25 : 1);
|
||||||
}
|
}
|
||||||
garglk_set_reversevideo(val) {
|
garglk_set_reversevideo(val) {
|
||||||
this.reverse = !!val;
|
console.log('garglk_set_reversevideo', arguments);
|
||||||
|
this.curwnd.reverse = !!val;
|
||||||
|
}
|
||||||
|
garglk_set_reversevideo_stream(win, val) {
|
||||||
|
console.log('garglk_set_reversevideo_stream', arguments);
|
||||||
|
this.windows[win].reverse = !!val; // TODO: per window
|
||||||
}
|
}
|
||||||
glk_gestalt(sel, val) {
|
glk_gestalt(sel, val) {
|
||||||
return this.glk_gestalt_ext(sel, val, null);
|
return this.glk_gestalt_ext(sel, val, null);
|
||||||
}
|
}
|
||||||
glk_gestalt_ext(sel, val, arr) {
|
glk_gestalt_ext(sel, val, arr) {
|
||||||
console.log('glk_gestalt_ext', arguments);
|
//console.log('glk_gestalt_ext', arguments);
|
||||||
switch (sel) {
|
switch (sel) {
|
||||||
|
|
||||||
case 0: // gestalt_Version
|
case 0: // gestalt_Version
|
||||||
|
@ -403,52 +481,57 @@ class GlkImpl {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RefBox: Simple class used for "call-by-reference" Glk arguments. The object
|
|
||||||
is just a box containing a single value, which can be written and read.
|
|
||||||
*/
|
|
||||||
RefBox = function () {
|
|
||||||
this.value = undefined;
|
|
||||||
this.set_value = function (val) {
|
|
||||||
this.value = val;
|
|
||||||
}
|
|
||||||
this.get_value = function () {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RefStruct: Used for struct-type Glk arguments. After creating the
|
|
||||||
object, you should call push_field() the appropriate number of times,
|
|
||||||
to set the initial field values. Then set_field() can be used to
|
|
||||||
change them, and get_fields() retrieves the list of all fields.
|
|
||||||
|
|
||||||
(The usage here is loose, since Javascript is forgiving about arrays.
|
|
||||||
Really the caller could call set_field() instead of push_field() --
|
|
||||||
or skip that step entirely, as long as the Glk function later calls
|
|
||||||
set_field() for each field. Which it should.)
|
|
||||||
*/
|
|
||||||
RefStruct = function (numels) {
|
|
||||||
this.fields = [];
|
|
||||||
this.push_field = function (val) {
|
|
||||||
this.fields.push(val);
|
|
||||||
}
|
|
||||||
this.set_field = function (pos, val) {
|
|
||||||
this.fields[pos] = val;
|
|
||||||
}
|
|
||||||
this.get_field = function (pos) {
|
|
||||||
return this.fields[pos];
|
|
||||||
}
|
|
||||||
this.get_fields = function () {
|
|
||||||
return this.fields;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dummy return value, which means that the Glk call is still in progress,
|
/* Dummy return value, which means that the Glk call is still in progress,
|
||||||
or will never return at all. This is used by glk_exit(), glk_select(),
|
or will never return at all. This is used by glk_exit(), glk_select(),
|
||||||
and glk_fileref_create_by_prompt().
|
and glk_fileref_create_by_prompt().
|
||||||
*/
|
*/
|
||||||
DidNotReturn = { dummy: 'Glk call has not yet returned' };
|
DidNotReturn = { dummy: 'Glk call has not yet returned' };
|
||||||
|
RefBox = RefBox;
|
||||||
|
RefStruct = RefStruct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* RefBox: Simple class used for "call-by-reference" Glk arguments. The object
|
||||||
|
is just a box containing a single value, which can be written and read.
|
||||||
|
*/
|
||||||
|
class RefBox {
|
||||||
|
value;
|
||||||
|
set_value(val) {
|
||||||
|
this.value = val;
|
||||||
|
}
|
||||||
|
get_value() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RefStruct: Used for struct-type Glk arguments. After creating the
|
||||||
|
object, you should call push_field() the appropriate number of times,
|
||||||
|
to set the initial field values. Then set_field() can be used to
|
||||||
|
change them, and get_fields() retrieves the list of all fields.
|
||||||
|
|
||||||
|
(The usage here is loose, since Javascript is forgiving about arrays.
|
||||||
|
Really the caller could call set_field() instead of push_field() --
|
||||||
|
or skip that step entirely, as long as the Glk function later calls
|
||||||
|
set_field() for each field. Which it should.)
|
||||||
|
*/
|
||||||
|
class RefStruct {
|
||||||
|
constructor(numels) {
|
||||||
|
}
|
||||||
|
fields = [];
|
||||||
|
push_field(val) {
|
||||||
|
this.fields.push(val);
|
||||||
|
}
|
||||||
|
set_field(pos, val) {
|
||||||
|
this.fields[pos] = val;
|
||||||
|
}
|
||||||
|
get_field(pos) {
|
||||||
|
return this.fields[pos];
|
||||||
|
}
|
||||||
|
get_fields() {
|
||||||
|
return this.fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const has_canvas = typeof window === 'object';
|
const has_canvas = typeof window === 'object';
|
||||||
|
|
||||||
const Const = {
|
const Const = {
|
||||||
|
@ -600,7 +683,7 @@ const Const = {
|
||||||
|
|
||||||
class ZmachinePlatform implements Platform {
|
class ZmachinePlatform implements Platform {
|
||||||
mainElement: HTMLElement;
|
mainElement: HTMLElement;
|
||||||
zfile : Uint8Array;
|
zfile: Uint8Array;
|
||||||
zvm;
|
zvm;
|
||||||
glk;
|
glk;
|
||||||
focused = false;
|
focused = false;
|
||||||
|
@ -612,16 +695,14 @@ class ZmachinePlatform implements Platform {
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
await loadScript('./lib/zvm/ifvms.min.js');
|
await loadScript('./lib/zvm/ifvms.min.js');
|
||||||
//await loadScript('./lib/zvm/glkote.min.js');
|
|
||||||
//await loadScript('./lib/zvm/glkapi.js');
|
|
||||||
//await loadScript('./lib/zvm/parchment.debug.js');
|
|
||||||
|
|
||||||
// create divs
|
// create divs
|
||||||
var parent = this.mainElement;
|
var parent = this.mainElement;
|
||||||
var gameport = $('<div id="gameport"/>').appendTo(parent);
|
var gameport = $('<div id="gameport"/>').appendTo(parent);
|
||||||
|
var upperwnd = $('<div id="upperport" class="transcript transcript-split transcript-style-2"/>').insertBefore(parent).hide();
|
||||||
var windowport = $('<div id="windowport" class="transcript"/>').appendTo(gameport);
|
var windowport = $('<div id="windowport" class="transcript"/>').appendTo(gameport);
|
||||||
var inputline = $('<input class="transcript-input" type="text"/>').appendTo(gameport).hide();
|
var inputline = $('<input class="transcript-input" type="text"/>').appendTo(gameport).hide();
|
||||||
this.glk = new GlkImpl(windowport[0], inputline[0] as HTMLInputElement);
|
this.glk = new GlkImpl(windowport[0], inputline[0] as HTMLInputElement, upperwnd[0]);
|
||||||
inputline.on('keypress', (e) => {
|
inputline.on('keypress', (e) => {
|
||||||
this.glk.sendkey(e);
|
this.glk.sendkey(e);
|
||||||
});
|
});
|
||||||
|
@ -643,9 +724,6 @@ class ZmachinePlatform implements Platform {
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
if (this.zfile == null) return;
|
if (this.zfile == null) return;
|
||||||
//this.glk = Glk;
|
|
||||||
//this.glk = new Object();
|
|
||||||
//Object.setPrototypeOf(this.glk, Glk);
|
|
||||||
this.zvm = new ZVM();
|
this.zvm = new ZVM();
|
||||||
this.zvm.prepare(this.zfile.slice(0), {
|
this.zvm.prepare(this.zfile.slice(0), {
|
||||||
Glk: this.glk,
|
Glk: this.glk,
|
||||||
|
@ -669,6 +747,7 @@ class ZmachinePlatform implements Platform {
|
||||||
getPC() {
|
getPC() {
|
||||||
return this.zvm.pc;
|
return this.zvm.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
loadState(state): void {
|
loadState(state): void {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
|
@ -683,7 +762,7 @@ class ZmachinePlatform implements Platform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
isRunning(): boolean {
|
isRunning(): boolean {
|
||||||
return this.zvm != null && !this.glk.exited;
|
return this.zvm != null && !this.glk.exited;
|
||||||
}
|
}
|
||||||
|
@ -699,7 +778,7 @@ class ZmachinePlatform implements Platform {
|
||||||
getDefaultExtension(): string {
|
getDefaultExtension(): string {
|
||||||
return ".inf";
|
return ".inf";
|
||||||
}
|
}
|
||||||
showHelp(tool:string, ident?:string) {
|
showHelp(tool: string, ident?: string) {
|
||||||
switch (tool) {
|
switch (tool) {
|
||||||
case 'inform6': window.open("https://www.inform-fiction.org/manual/html/contents.html"); break;
|
case 'inform6': window.open("https://www.inform-fiction.org/manual/html/contents.html"); break;
|
||||||
}
|
}
|
||||||
|
@ -709,7 +788,7 @@ class ZmachinePlatform implements Platform {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Z machine is big endian!!
|
// TODO: Z machine is big endian!!
|
||||||
inspect(ident:string) {
|
inspect(ident: string) {
|
||||||
return inspectSymbol(this, ident);
|
return inspectSymbol(this, ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +815,7 @@ class ZmachinePlatform implements Platform {
|
||||||
var tree = {};
|
var tree = {};
|
||||||
// TODO: better way?
|
// TODO: better way?
|
||||||
try {
|
try {
|
||||||
for (let child=0; child<65536; child++) {
|
for (let child = 0; child < 65536; child++) {
|
||||||
if (this.zvm.get_parent(child) == 0) {
|
if (this.zvm.get_parent(child) == 0) {
|
||||||
this.addObjectToTree(tree, child);
|
this.addObjectToTree(tree, child);
|
||||||
}
|
}
|
||||||
|
@ -766,28 +845,28 @@ class ZmachinePlatform implements Platform {
|
||||||
*/
|
*/
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
getFlagList(obj:number) {
|
getFlagList(obj: number) {
|
||||||
var attrlookup = this.getDebugLookup('attribute');
|
var attrlookup = this.getDebugLookup('attribute');
|
||||||
var set_attrs = [];
|
var set_attrs = [];
|
||||||
for (var i=0; i<32; i++) {
|
for (var i = 0; i < 32; i++) {
|
||||||
if (this.zvm.test_attr(obj, i)) {
|
if (this.zvm.test_attr(obj, i)) {
|
||||||
set_attrs.push(attrlookup[i] || "#"+i);
|
set_attrs.push(attrlookup[i] || "#" + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return set_attrs;
|
return set_attrs;
|
||||||
}
|
}
|
||||||
getPropList(obj:number) {
|
getPropList(obj: number) {
|
||||||
var proplookup = this.getDebugLookup('property');
|
var proplookup = this.getDebugLookup('property');
|
||||||
var set_props = [];
|
var set_props = [];
|
||||||
var addr = 0;
|
var addr = 0;
|
||||||
for (var i=0; i<50; i++) {
|
for (var i = 0; i < 50; i++) {
|
||||||
addr = this.zvm.find_prop(obj, 0, addr);
|
addr = this.zvm.find_prop(obj, 0, addr);
|
||||||
if (addr == 0) break;
|
if (addr == 0) break;
|
||||||
set_props.push(proplookup[addr] || "%"+addr);
|
set_props.push(proplookup[addr] || "%" + addr);
|
||||||
}
|
}
|
||||||
return set_props;
|
return set_props;
|
||||||
}
|
}
|
||||||
getDebugLookup(key : 'object'|'property'|'attribute'|'constant'|'global-variable') : {} {
|
getDebugLookup(key: 'object' | 'property' | 'attribute' | 'constant' | 'global-variable'): {} {
|
||||||
var debugsym = (this as Platform).debugSymbols;
|
var debugsym = (this as Platform).debugSymbols;
|
||||||
return (debugsym && debugsym.debuginfo && debugsym.debuginfo[key]) || {};
|
return (debugsym && debugsym.debuginfo && debugsym.debuginfo[key]) || {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user