WASM fixes
This commit is contained in:
@@ -482,6 +482,9 @@ extern struct nomakedefs_s nomakedefs;
|
||||
#if !defined(CROSS_TO_WASM) /* no popen in WASM */
|
||||
#define PANICTRACE_GDB
|
||||
#endif
|
||||
#ifdef CROSS_TO_WASM
|
||||
#undef COMPRESS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Supply nethack_enter macro if not supplied by port */
|
||||
|
||||
@@ -2175,7 +2175,7 @@ genl_player_selection(void)
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
|
||||
#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS)
|
||||
/* ['#else' far below] */
|
||||
|
||||
staticfn boolean reset_role_filtering(void);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <func_tab.h>
|
||||
#ifndef O_RDONLY
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
@@ -174,6 +175,12 @@ nhmain(int argc, char *argv[])
|
||||
chdirx(dir, 1);
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
js_helpers_init();
|
||||
js_constants_init();
|
||||
js_globals_init();
|
||||
#endif
|
||||
|
||||
#ifdef _M_UNIX
|
||||
check_sco_console();
|
||||
#endif
|
||||
@@ -201,11 +208,6 @@ nhmain(int argc, char *argv[])
|
||||
process_options(argc, argv); /* command line options */
|
||||
#ifdef WINCHAIN
|
||||
commit_windowchain();
|
||||
#endif
|
||||
#ifdef __EMSCRIPTEN__
|
||||
js_helpers_init();
|
||||
js_constants_init();
|
||||
js_globals_init();
|
||||
#endif
|
||||
init_nhwindows(&argc, argv); /* now we can set up window system */
|
||||
#ifdef _M_UNIX
|
||||
@@ -781,9 +783,9 @@ EM_JS(void, js_helpers_init, (), {
|
||||
globalThis.nethackGlobal = globalThis.nethackGlobal || {};
|
||||
globalThis.nethackGlobal.helpers = globalThis.nethackGlobal.helpers || {};
|
||||
|
||||
installHelper(displayInventory);
|
||||
installHelper(getPointerValue);
|
||||
installHelper(setPointerValue);
|
||||
installHelper(displayInventory, "displayInventory");
|
||||
installHelper(getPointerValue, "getPointerValue");
|
||||
installHelper(setPointerValue, "setPointerValue");
|
||||
|
||||
// used by update_inventory
|
||||
function displayInventory() {
|
||||
@@ -804,6 +806,8 @@ EM_JS(void, js_helpers_init, (), {
|
||||
return getValue(ptr, "*");
|
||||
case "c": // char
|
||||
return String.fromCharCode(getValue(ptr, "i8"));
|
||||
case "b":
|
||||
return getValue(ptr, "i8") == 1;
|
||||
case "0": /* 2^0 = 1 byte */
|
||||
return getValue(ptr, "i8");
|
||||
case "1": /* 2^1 = 2 bytes */
|
||||
@@ -816,8 +820,8 @@ EM_JS(void, js_helpers_init, (), {
|
||||
return getValue(ptr, "float");
|
||||
case "d": // double
|
||||
return getValue(ptr, "double");
|
||||
case "o": // overloaded: multiple types
|
||||
return ptr;
|
||||
case "v": // void
|
||||
return undefined;
|
||||
default:
|
||||
throw new TypeError ("unknown type:" + type);
|
||||
}
|
||||
@@ -828,7 +832,8 @@ EM_JS(void, js_helpers_init, (), {
|
||||
// console.log("setPointerValue", name, "0x" + ptr.toString(16), type, value);
|
||||
switch (type) {
|
||||
case "p":
|
||||
throw new Error("not implemented");
|
||||
setValue(ptr, value, "*");
|
||||
break;
|
||||
case "s":
|
||||
if(typeof value !== "string")
|
||||
throw new TypeError(`expected ${name} return type to be string`);
|
||||
@@ -841,6 +846,11 @@ EM_JS(void, js_helpers_init, (), {
|
||||
throw new TypeError(`expected ${name} return type to be integer`);
|
||||
setValue(ptr, value, "i32");
|
||||
break;
|
||||
case "1":
|
||||
if(typeof value !== "number" || !Number.isInteger(value))
|
||||
throw new TypeError(`expected ${name} return type to be integer`);
|
||||
setValue(ptr, value, "i16");
|
||||
break;
|
||||
case "c":
|
||||
if(typeof value !== "number" || value < 0 || value > 128)
|
||||
throw new TypeError(`expected ${name} return type to be integer representing an ASCII character`);
|
||||
@@ -857,6 +867,10 @@ EM_JS(void, js_helpers_init, (), {
|
||||
throw new TypeError(`expected ${name} return type to be double`);
|
||||
setValue(ptr, value, "double");
|
||||
break;
|
||||
case "b":
|
||||
if (typeof value !== "boolean")
|
||||
throw new TypeError(`expected ${name} return type to be boolean`);
|
||||
setValue(ptr, value ? 1 : 0, "i8");
|
||||
case "v":
|
||||
break;
|
||||
default:
|
||||
@@ -896,11 +910,19 @@ EM_JS(void, set_const_str, (char *scope_str, char *name_str, char *input_str), {
|
||||
globalThis.nethackGlobal.constants[scope] = globalThis.nethackGlobal.constants[scope] || {};
|
||||
globalThis.nethackGlobal.constants[scope][name] = str;
|
||||
});
|
||||
#define SET_POINTER(name) set_const_ptr(#name, (void *)&name);
|
||||
EM_JS(void, set_const_ptr, (char *name_str, void* ptr), {
|
||||
let name = UTF8ToString(name_str);
|
||||
|
||||
globalThis.nethackGlobal.pointers = globalThis.nethackGlobal.pointers || {};
|
||||
globalThis.nethackGlobal.pointers[name] = ptr;
|
||||
});
|
||||
|
||||
void js_constants_init() {
|
||||
EM_ASM({
|
||||
globalThis.nethackGlobal = globalThis.nethackGlobal || {};
|
||||
globalThis.nethackGlobal.constants = globalThis.nethackGlobal.constants || {};
|
||||
globalThis.nethackGlobal.pointers = globalThis.nethackGlobal.pointers || {};
|
||||
});
|
||||
|
||||
// create_nhwindow
|
||||
@@ -989,8 +1011,7 @@ void js_constants_init() {
|
||||
// copyright
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_A);
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_B);
|
||||
// XXX: not set for cross-compile
|
||||
//SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_C);
|
||||
set_const_str("COPYRIGHT", "COPYRIGHT_BANNER_C", (char*) COPYRIGHT_BANNER_C);
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_D);
|
||||
|
||||
// glyphs
|
||||
@@ -1042,6 +1063,119 @@ void js_constants_init() {
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_BLINK);
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_INVERSE);
|
||||
SET_CONSTANT("COLOR_ATTR", BL_ATTCLR_MAX);
|
||||
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_BAREH);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_BLIND);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_BUSY);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_CONF);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_DEAF);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_ELF_IRON);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_FLY);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_FOODPOIS);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_GLOWHANDS);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_GRAB);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_HALLU);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_HELD);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_ICY);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_INLAVA);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_LEV);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_PARLYZ);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_RIDE);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_SLEEPING);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_SLIME);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_SLIPPERY);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_STONE);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_STRNGL);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_STUN);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_SUBMERGED);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_TERMILL);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_TETHERED);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_TRAPPED);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_UNCONSC);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_WOUNDEDL);
|
||||
SET_CONSTANT("BL_MASK", BL_MASK_HOLDING);
|
||||
|
||||
SET_CONSTANT("ROLE_RACEMASK", MH_HUMAN);
|
||||
SET_CONSTANT("ROLE_RACEMASK", MH_ELF);
|
||||
SET_CONSTANT("ROLE_RACEMASK", MH_DWARF);
|
||||
SET_CONSTANT("ROLE_RACEMASK", MH_GNOME);
|
||||
SET_CONSTANT("ROLE_RACEMASK", MH_ORC);
|
||||
|
||||
SET_CONSTANT("ROLE_GENDMASK", ROLE_MALE);
|
||||
SET_CONSTANT("ROLE_GENDMASK", ROLE_FEMALE);
|
||||
SET_CONSTANT("ROLE_GENDMASK", ROLE_NEUTER);
|
||||
|
||||
SET_CONSTANT("ROLE_ALIGNMASK", ROLE_LAWFUL);
|
||||
SET_CONSTANT("ROLE_ALIGNMASK", ROLE_NEUTRAL);
|
||||
SET_CONSTANT("ROLE_ALIGNMASK", ROLE_CHAOTIC);
|
||||
|
||||
SET_CONSTANT("blconditions", bl_bareh);
|
||||
SET_CONSTANT("blconditions", bl_blind);
|
||||
SET_CONSTANT("blconditions", bl_busy);
|
||||
SET_CONSTANT("blconditions", bl_conf);
|
||||
SET_CONSTANT("blconditions", bl_deaf);
|
||||
SET_CONSTANT("blconditions", bl_elf_iron);
|
||||
SET_CONSTANT("blconditions", bl_fly);
|
||||
SET_CONSTANT("blconditions", bl_foodpois);
|
||||
SET_CONSTANT("blconditions", bl_glowhands);
|
||||
SET_CONSTANT("blconditions", bl_grab);
|
||||
SET_CONSTANT("blconditions", bl_hallu);
|
||||
SET_CONSTANT("blconditions", bl_held);
|
||||
SET_CONSTANT("blconditions", bl_icy);
|
||||
SET_CONSTANT("blconditions", bl_inlava);
|
||||
SET_CONSTANT("blconditions", bl_lev);
|
||||
SET_CONSTANT("blconditions", bl_parlyz);
|
||||
SET_CONSTANT("blconditions", bl_ride);
|
||||
SET_CONSTANT("blconditions", bl_sleeping);
|
||||
SET_CONSTANT("blconditions", bl_slime);
|
||||
SET_CONSTANT("blconditions", bl_slippery);
|
||||
SET_CONSTANT("blconditions", bl_stone);
|
||||
SET_CONSTANT("blconditions", bl_strngl);
|
||||
SET_CONSTANT("blconditions", bl_stun);
|
||||
SET_CONSTANT("blconditions", bl_submerged);
|
||||
SET_CONSTANT("blconditions", bl_termill);
|
||||
SET_CONSTANT("blconditions", bl_tethered);
|
||||
SET_CONSTANT("blconditions", bl_trapped);
|
||||
SET_CONSTANT("blconditions", bl_unconsc);
|
||||
SET_CONSTANT("blconditions", bl_woundedl);
|
||||
SET_CONSTANT("blconditions", bl_holding);
|
||||
SET_CONSTANT("blconditions", CONDITION_COUNT);
|
||||
|
||||
SET_CONSTANT("HL", HL_UNDEF);
|
||||
SET_CONSTANT("HL", HL_NONE);
|
||||
SET_CONSTANT("HL", HL_BOLD);
|
||||
SET_CONSTANT("HL", HL_DIM);
|
||||
SET_CONSTANT("HL", HL_ITALIC);
|
||||
SET_CONSTANT("HL", HL_ULINE);
|
||||
SET_CONSTANT("HL", HL_BLINK);
|
||||
SET_CONSTANT("HL", HL_INVERSE);
|
||||
|
||||
SET_CONSTANT("MG", MG_HERO);
|
||||
SET_CONSTANT("MG", MG_CORPSE);
|
||||
SET_CONSTANT("MG", MG_INVIS);
|
||||
SET_CONSTANT("MG", MG_DETECT);
|
||||
SET_CONSTANT("MG", MG_PET);
|
||||
SET_CONSTANT("MG", MG_RIDDEN);
|
||||
SET_CONSTANT("MG", MG_STATUE);
|
||||
SET_CONSTANT("MG", MG_OBJPILE);
|
||||
SET_CONSTANT("MG", MG_BW_LAVA);
|
||||
SET_CONSTANT("MG", MG_BW_ICE);
|
||||
SET_CONSTANT("MG", MG_BW_SINK);
|
||||
SET_CONSTANT("MG", MG_BW_ENGR);
|
||||
SET_CONSTANT("MG", MG_NOTHING);
|
||||
SET_CONSTANT("MG", MG_UNEXPL);
|
||||
SET_CONSTANT("MG", MG_MALE);
|
||||
SET_CONSTANT("MG", MG_FEMALE);
|
||||
|
||||
SET_POINTER(extcmdlist);
|
||||
SET_POINTER(conditions);
|
||||
SET_POINTER(condtests);
|
||||
|
||||
/* roles/races/genders/alignments */
|
||||
SET_POINTER(roles);
|
||||
SET_POINTER(races);
|
||||
SET_POINTER(genders);
|
||||
SET_POINTER(aligns);
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -1073,6 +1207,20 @@ void js_globals_init() {
|
||||
CREATE_GLOBAL(WIN_MESSAGE, "i");
|
||||
CREATE_GLOBAL(WIN_INVEN, "i");
|
||||
CREATE_GLOBAL(WIN_STATUS, "i");
|
||||
|
||||
/* instance flags */
|
||||
CREATE_GLOBAL(iflags.window_inited, "b");
|
||||
CREATE_GLOBAL(iflags.wc2_hitpointbar, "b");
|
||||
CREATE_GLOBAL(iflags.wc_hilite_pet, "b");
|
||||
CREATE_GLOBAL(iflags.hilite_pile, "b");
|
||||
|
||||
/* flags */
|
||||
CREATE_GLOBAL(flags.initrole, "i");
|
||||
CREATE_GLOBAL(flags.initrace, "i");
|
||||
CREATE_GLOBAL(flags.initgend, "i");
|
||||
CREATE_GLOBAL(flags.initalign, "i");
|
||||
CREATE_GLOBAL(flags.showexp, "b");
|
||||
CREATE_GLOBAL(flags.time, "b");
|
||||
}
|
||||
|
||||
EM_JS(void, create_global, (char *name_str, void *ptr, char *type_str), {
|
||||
|
||||
@@ -216,7 +216,7 @@ ifdef CROSS_TO_WASM
|
||||
# originally from https://github.com/NetHack/NetHack/pull/385
|
||||
#===============-=================================================
|
||||
#
|
||||
WASM_DEBUG = 1
|
||||
#WASM_DEBUG = 1
|
||||
WASM_DATA_DIR = $(TARGETPFX)wasm-data
|
||||
WASM_TARGET = $(TARGETPFX)nethack.js
|
||||
EMCC_LFLAGS =
|
||||
@@ -227,10 +227,13 @@ EMCC_LFLAGS += -s ALLOW_TABLE_GROWTH
|
||||
EMCC_LFLAGS += -s ASYNCIFY -s ASYNCIFY_IMPORTS='["local_callback"]'
|
||||
EMCC_LFLAGS += -O3
|
||||
EMCC_LFLAGS += -s MODULARIZE
|
||||
EMCC_LFLAGS += -s EXPORTED_FUNCTIONS='["_main", "_shim_graphics_set_callback", "_display_inventory"]'
|
||||
EMCC_LFLAGS += -s EXPORTED_FUNCTIONS='["_main", "_shim_graphics_set_callback", "_display_inventory", "_malloc"]'
|
||||
EMCC_LFLAGS += -s EXPORTED_RUNTIME_METHODS='["cwrap", "ccall", "addFunction", \
|
||||
"removeFunction", "UTF8ToString", "getValue", "setValue"]'
|
||||
"removeFunction", "UTF8ToString", "stringToUTF8", "getValue", \
|
||||
"setValue", "ENV", "FS", "IDBFS"]'
|
||||
EMCC_LFLAGS += -s ERROR_ON_UNDEFINED_SYMBOLS=0
|
||||
EMCC_LFLAGS += -s EXPORT_ES6=1
|
||||
EMCC_LFLAGS += -lidbfs.js
|
||||
# XXX: the "@/" at the end of "--embed-file" tells emscripten to embed the files
|
||||
# in the root directory, otherwise they will end up in the $(WASM_DATA_DIR) path
|
||||
EMCC_LFLAGS += --embed-file $(WASM_DATA_DIR)@/
|
||||
|
||||
@@ -115,7 +115,7 @@ void name fn_args { \
|
||||
#endif /* __EMSCRIPTEN__ */
|
||||
|
||||
VDECLCB(shim_init_nhwindows,(int *argcp, char **argv), "vpp", P2V argcp, P2V argv)
|
||||
VDECLCB(shim_player_selection,(void), "v")
|
||||
DECLCB(boolean, shim_player_selection_or_tty,(void), "b")
|
||||
VDECLCB(shim_askname,(void), "v")
|
||||
VDECLCB(shim_get_nh_event,(void), "v")
|
||||
VDECLCB(shim_exit_nhwindows,(const char *str), "vs", P2V str)
|
||||
@@ -123,33 +123,33 @@ VDECLCB(shim_suspend_nhwindows,(const char *str), "vs", P2V str)
|
||||
VDECLCB(shim_resume_nhwindows,(void), "v")
|
||||
DECLCB(winid, shim_create_nhwindow, (int type), "ii", A2P type)
|
||||
VDECLCB(shim_clear_nhwindow,(winid window), "vi", A2P window)
|
||||
VDECLCB(shim_display_nhwindow,(winid window, boolean blocking), "vii", A2P window, A2P blocking)
|
||||
VDECLCB(shim_display_nhwindow,(winid window, boolean blocking), "vib", A2P window, A2P blocking)
|
||||
VDECLCB(shim_destroy_nhwindow,(winid window), "vi", A2P window)
|
||||
VDECLCB(shim_curs,(winid a, int x, int y), "viii", A2P a, A2P x, A2P y)
|
||||
VDECLCB(shim_putstr,(winid w, int attr, const char *str), "viis", A2P w, A2P attr, P2V str)
|
||||
VDECLCB(shim_display_file,(const char *name, boolean complain), "vsi", P2V name, A2P complain)
|
||||
VDECLCB(shim_display_file,(const char *name, boolean complain), "vsb", P2V name, A2P complain)
|
||||
VDECLCB(shim_start_menu,(winid window, unsigned long mbehavior), "vii", A2P window, A2P mbehavior)
|
||||
VDECLCB(shim_add_menu,
|
||||
(winid window, const glyph_info *glyphinfo, const ANY_P *identifier, char ch, char gch, int attr, int clr, const char *str, unsigned int itemflags),
|
||||
"vippiiiisi",
|
||||
"vipi00iisi",
|
||||
A2P window, P2V glyphinfo, P2V identifier, A2P ch, A2P gch, A2P attr, A2P clr, P2V str, A2P itemflags)
|
||||
VDECLCB(shim_end_menu,(winid window, const char *prompt), "vis", A2P window, P2V prompt)
|
||||
/* XXX: shim_select_menu menu_list is an output */
|
||||
DECLCB(int, shim_select_menu,(winid window, int how, MENU_ITEM_P **menu_list), "iiio", A2P window, A2P how, P2V menu_list)
|
||||
DECLCB(int, shim_select_menu,(winid window, int how, MENU_ITEM_P **menu_list), "iiip", A2P window, A2P how, P2V menu_list)
|
||||
DECLCB(char, shim_message_menu,(char let, int how, const char *mesg), "ciis", A2P let, A2P how, P2V mesg)
|
||||
VDECLCB(shim_mark_synch,(void), "v")
|
||||
VDECLCB(shim_wait_synch,(void), "v")
|
||||
VDECLCB(shim_cliparound,(int x, int y), "vii", A2P x, A2P y)
|
||||
VDECLCB(shim_update_positionbar,(char *posbar), "vp", P2V posbar)
|
||||
VDECLCB(shim_print_glyph,(winid w, coordxy x, coordxy y, const glyph_info *glyphinfo, const glyph_info *bkglyphinfo), "viiipp", A2P w, A2P x, A2P y, P2V glyphinfo, P2V bkglyphinfo)
|
||||
VDECLCB(shim_update_positionbar,(char *posbar), "vs", P2V posbar)
|
||||
VDECLCB(shim_print_glyph,(winid w, coordxy x, coordxy y, const glyph_info *glyphinfo, const glyph_info *bkglyphinfo), "vi11pp", A2P w, A2P x, A2P y, P2V glyphinfo, P2V bkglyphinfo)
|
||||
VDECLCB(shim_raw_print,(const char *str), "vs", P2V str)
|
||||
VDECLCB(shim_raw_print_bold,(const char *str), "vs", P2V str)
|
||||
DECLCB(int, shim_nhgetch,(void), "i")
|
||||
DECLCB(int, shim_nh_poskey,(coordxy *x, coordxy *y, int *mod), "iooo", P2V x, P2V y, P2V mod)
|
||||
DECLCB(int, shim_nh_poskey,(coordxy *x, coordxy *y, int *mod), "ippp", P2V x, P2V y, P2V mod)
|
||||
VDECLCB(shim_nhbell,(void), "v")
|
||||
DECLCB(int, shim_doprev_message,(void),"iv")
|
||||
DECLCB(char, shim_yn_function,(const char *query, const char *resp, char def), "cssi", P2V query, P2V resp, A2P def)
|
||||
VDECLCB(shim_getlin,(const char *query, char *bufp), "vso", P2V query, P2V bufp)
|
||||
DECLCB(char, shim_yn_function,(const char *query, const char *resp, char def), "css0", P2V query, P2V resp, A2P def)
|
||||
VDECLCB(shim_getlin,(const char *query, char *bufp), "vsp", P2V query, P2V bufp)
|
||||
DECLCB(int,shim_get_ext_cmd,(void),"iv")
|
||||
VDECLCB(shim_number_pad,(int state), "vi", A2P state)
|
||||
VDECLCB(shim_delay_output,(void), "v")
|
||||
@@ -162,17 +162,17 @@ DECLCB(char *,shim_get_color_string,(void),"sv")
|
||||
VDECLCB(shim_start_screen, (void), "v")
|
||||
VDECLCB(shim_end_screen, (void), "v")
|
||||
VDECLCB(shim_preference_update, (const char *pref), "vp", P2V pref)
|
||||
DECLCB(char *,shim_getmsghistory, (boolean init), "si", A2P init)
|
||||
VDECLCB(shim_putmsghistory, (const char *msg, boolean restoring_msghist), "vsi", P2V msg, A2P restoring_msghist)
|
||||
DECLCB(char *,shim_getmsghistory, (boolean init), "sb", A2P init)
|
||||
VDECLCB(shim_putmsghistory, (const char *msg, boolean restoring_msghist), "vsb", P2V msg, A2P restoring_msghist)
|
||||
VDECLCB(shim_status_init, (void), "v")
|
||||
VDECLCB(shim_status_enablefield,
|
||||
(int fieldidx, const char *nm, const char *fmt, boolean enable),
|
||||
"vippi",
|
||||
"vippb",
|
||||
A2P fieldidx, P2V nm, P2V fmt, A2P enable)
|
||||
/* XXX: the second argument to shim_status_update is sometimes an integer and sometimes a pointer */
|
||||
VDECLCB(shim_status_update,
|
||||
(int fldidx, genericptr_t ptr, int chg, int percent, int color, unsigned long *colormasks),
|
||||
"vioiiip",
|
||||
"vipiiip",
|
||||
A2P fldidx, P2V ptr, A2P chg, A2P percent, A2P color, P2V colormasks)
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@@ -183,6 +183,14 @@ void shim_update_inventory(int a1 UNUSED) {
|
||||
display_inventory(NULL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void shim_player_selection() {
|
||||
boolean do_genl_player_setup = shim_player_selection_or_tty();
|
||||
if (do_genl_player_setup) {
|
||||
genl_player_setup(80);
|
||||
}
|
||||
}
|
||||
|
||||
win_request_info *
|
||||
shim_ctrl_nhwindow(
|
||||
winid window UNUSED,
|
||||
@@ -203,6 +211,7 @@ struct window_procs shim_procs = {
|
||||
WPID(shim),
|
||||
(0
|
||||
| WC_ASCII_MAP
|
||||
| WC_MOUSE_SUPPORT
|
||||
| WC_COLOR | WC_HILITE_PET | WC_INVERSE | WC_EIGHT_BIT_IN),
|
||||
(0
|
||||
#if defined(SELECTSAVED)
|
||||
@@ -262,7 +271,7 @@ EM_JS(void, local_callback, (const char *cb_name, const char *shim_name, void *r
|
||||
// unrolling and it crashes. Thus we use Asyncify.handleSleep() and wakeUp() to make sure that async doesn't break
|
||||
// Asyncify. For details, see: https://emscripten.org/docs/porting/asyncify.html#optimizing
|
||||
Asyncify.handleSleep(wakeUp => {
|
||||
// convert callback arguments to proper JavaScript varaidic arguments
|
||||
// convert callback arguments to proper JavaScript variadic arguments
|
||||
let name = UTF8ToString(shim_name);
|
||||
let fmt = UTF8ToString(fmt_str);
|
||||
let cbName = UTF8ToString(cb_name);
|
||||
@@ -287,40 +296,25 @@ EM_JS(void, local_callback, (const char *cb_name, const char *shim_name, void *r
|
||||
|
||||
// do the callback
|
||||
let userCallback = globalThis[cbName];
|
||||
runJsEventLoop(() => userCallback.call(this, name, ... jsArgs)).then((retVal) => {
|
||||
userCallback.call(this, name, ... jsArgs).then((retVal) => {
|
||||
// save the return value
|
||||
setPointerValue(name, ret_ptr, retType, retVal);
|
||||
// return
|
||||
setTimeout(() => {
|
||||
reentryMutexUnlock();
|
||||
reentryMutexUnlock();
|
||||
try {
|
||||
wakeUp();
|
||||
}, 0);
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
function getArg(name, ptr, type) {
|
||||
return (type === "o")?ptr:getPointerValue(name, getValue(ptr, "*"), type);
|
||||
}
|
||||
|
||||
// setTimeout() with value of '0' is similar to setImmediate() (but setImmediate isn't standard)
|
||||
// this lets the JS loop run for a tick so that other events can occur
|
||||
// XXX: I also tried replacing the for(;;) in allmain.c:moveloop() with emscripten_set_main_loop()
|
||||
// unfortunately that won't work -- if the simulate_infinite_loop arg is false, it falls through
|
||||
// and the program ends;
|
||||
// if is true, it throws an exception to break out of main(), but doesn't get caught because
|
||||
// the stack isn't running under main() anymore...
|
||||
// I think this is suboptimal, but we will have to live with it (for now?)
|
||||
async function runJsEventLoop(cb) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve(cb());
|
||||
}, 0);
|
||||
});
|
||||
return (type === "p") ? getValue(ptr, "*") : getPointerValue(name, getValue(ptr, "*"), type);
|
||||
}
|
||||
|
||||
function reentryMutexLock(name) {
|
||||
globalThis.nethackGlobal = globalThis.nethackGlobal || {};
|
||||
if(globalThis.nethackGlobal.shimFunctionRunning) {
|
||||
throw new Error(`'${name}' attempting second call to 'local_callback' before '${globalThis.nethackGlobal.shimFunctionRunning}' has finished, will crash emscripten Asyncify. For details see: emscripten.org/docs/porting/asyncify.html#reentrancy`);
|
||||
console.error(`'${name}' attempting second call to 'local_callback' before '${globalThis.nethackGlobal.shimFunctionRunning}' has finished, will crash emscripten Asyncify. For details see: emscripten.org/docs/porting/asyncify.html#reentrancy`);
|
||||
}
|
||||
globalThis.nethackGlobal.shimFunctionRunning = name;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user