initial helpers
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
Development helpers and tests for libnethack.a and nethack.js.
|
||||||
|
|
||||||
|
Copy these files to the NetHack root directory. Commands include:
|
||||||
|
* run.sh wasm - rebuild makefiles and build nethack.js
|
||||||
|
* run.sh runwasm - simple testing of nethack.js
|
||||||
|
* run.sh lib - rebuild makefiles and build libnethack.a
|
||||||
|
* run.sh runlib - simple testing of libnethack.a
|
||||||
|
* run.sh bin - build the MacOS binary
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* external functions */
|
||||||
|
int nhmain(int argc, char *argv[]);
|
||||||
|
typedef void(*stub_callback_t)(const char *name, void *ret_ptr, const char *fmt, ...);
|
||||||
|
void stub_graphics_set_callback(stub_callback_t cb);
|
||||||
|
|
||||||
|
/* forward declarations */
|
||||||
|
void window_cb(const char *name, void *ret_ptr, const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
stub_graphics_set_callback(window_cb);
|
||||||
|
nhmain(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_cb(const char *name, void *ret_ptr, const char *fmt, ...) {
|
||||||
|
/* TODO -- see windowCallback below for hints */
|
||||||
|
|
||||||
|
/* DO SOMETHING HERE */
|
||||||
|
*ret_ptr = yourFunctionToRenderGraphics(name, va_list args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
function variadicCallback(name, retPtr, fmt, args) {
|
||||||
|
// console.log ("variadicCallback called...");
|
||||||
|
// console.log("typeof name", typeof name);
|
||||||
|
// console.log("typeof fmt", typeof fmt);
|
||||||
|
// console.log("typeof args", typeof args);
|
||||||
|
name = Module.UTF8ToString(name);
|
||||||
|
fmt = Module.UTF8ToString(fmt);
|
||||||
|
// console.log ("name:", name);
|
||||||
|
// console.log ("fmt:", fmt);
|
||||||
|
let argTypes = fmt.split("");
|
||||||
|
let retType = argTypes.shift();
|
||||||
|
// console.log ("arg count:", argTypes.length);
|
||||||
|
// console.log ("arg types:", argTypes);
|
||||||
|
// console.log ("ret type:", retType);
|
||||||
|
|
||||||
|
let jsArgs = [];
|
||||||
|
for (let i = 0; i < argTypes.length; i++) {
|
||||||
|
let ptr = args + (4*i);
|
||||||
|
let val = typeLookup(argTypes[i], ptr);
|
||||||
|
jsArgs.push(val);
|
||||||
|
}
|
||||||
|
console.log(`graphics callback: ${name} [${jsArgs}]`);
|
||||||
|
setReturn(retPtr, retType);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReturn(ptr, type, value = 0) {
|
||||||
|
switch (type) {
|
||||||
|
case "p":
|
||||||
|
throw new Error("not implemented");
|
||||||
|
case "s":
|
||||||
|
value=value?value:"(no value)";
|
||||||
|
var strPtr = Module.getValue(ptr, "i32");
|
||||||
|
Module.stringToUTF8(value, strPtr, 1024);
|
||||||
|
break;
|
||||||
|
case "i":
|
||||||
|
Module.setValue(ptr, value, "i32");
|
||||||
|
break;
|
||||||
|
case "c":
|
||||||
|
Module.setValue(ptr, value, "i8"); // 'Z'
|
||||||
|
break;
|
||||||
|
case "f":
|
||||||
|
// XXX: I'm not sure why 'double' works and 'float' doesn't
|
||||||
|
Module.setValue(ptr, value, "double");
|
||||||
|
break;
|
||||||
|
case "d":
|
||||||
|
Module.setValue(ptr, value, "double");
|
||||||
|
break;
|
||||||
|
case "v":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("unknown type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeLookup(type, ptr) {
|
||||||
|
switch(type) {
|
||||||
|
case "s": // string
|
||||||
|
return Module.UTF8ToString(Module.getValue(ptr, "*"));
|
||||||
|
case "p": // pointer
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "*");
|
||||||
|
case "c": // char
|
||||||
|
return String.fromCharCode(Module.getValue(Module.getValue(ptr, "*"), "i8"));
|
||||||
|
case "0": /* 2^0 = 1 byte */
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i8");
|
||||||
|
case "1": /* 2^1 = 2 bytes */
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i16");
|
||||||
|
case "2": /* 2^2 = 4 bytes */
|
||||||
|
case "i": // integer
|
||||||
|
case "n": // number
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i32");
|
||||||
|
case "f": // float
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "float");
|
||||||
|
case "d": // double
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "double");
|
||||||
|
default:
|
||||||
|
throw new TypeError ("unknown type:" + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* 0 */
|
||||||
Executable
+40
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash -x
|
||||||
|
|
||||||
|
if [ x$1 == "xlib" ]; then
|
||||||
|
echo Doing lib...
|
||||||
|
make spotless
|
||||||
|
cd sys/lib
|
||||||
|
./setup.sh hints/macOS.2020
|
||||||
|
cd ../..
|
||||||
|
make
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x$1 == "xrunlib" ]; then
|
||||||
|
LIBS="-Lsrc -lnethack -Llib/lua -llua -lm"
|
||||||
|
BADLIBS="-lncurses"
|
||||||
|
gcc -o nhlibtest libtest.c $LIBS $BADLIBS
|
||||||
|
./nhlibtest
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x$1 == "xwasm" ]; then
|
||||||
|
echo Doing wasm...
|
||||||
|
make spotless
|
||||||
|
cd sys/lib
|
||||||
|
./setup.sh hints/wasm
|
||||||
|
cd ../..
|
||||||
|
make
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x$1 == "xrunwasm" ]; then
|
||||||
|
node test.js
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x$1 == "xbin" ]; then
|
||||||
|
echo Doing bin...
|
||||||
|
make spotless
|
||||||
|
cd sys/unix
|
||||||
|
./setup.sh hints/macOS.2020
|
||||||
|
cd ../..
|
||||||
|
make
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
const util = require("util");
|
||||||
|
|
||||||
|
// Emscripten Module config
|
||||||
|
let Module = {
|
||||||
|
// noInitialRun: true,
|
||||||
|
onRuntimeInitialized: function () {
|
||||||
|
setGraphicsCallback();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var factory = require("./src/nethack.js");
|
||||||
|
|
||||||
|
// load and run the module
|
||||||
|
factory(Module);
|
||||||
|
|
||||||
|
function setGraphicsCallback() {
|
||||||
|
console.log("setting callback function");
|
||||||
|
let cb = Module.addFunction(windowCallback, "viiii");
|
||||||
|
|
||||||
|
console.log("doing call");
|
||||||
|
Module.ccall(
|
||||||
|
"stub_graphics_set_callback", // C function name
|
||||||
|
null, // return type
|
||||||
|
["number"], // arg types
|
||||||
|
[cb], // arg values
|
||||||
|
{async: true} // options
|
||||||
|
);
|
||||||
|
|
||||||
|
/* TODO: removeFunction */
|
||||||
|
}
|
||||||
|
|
||||||
|
function windowCallback(name, retPtr, fmt, args) {
|
||||||
|
// console.log ("variadicCallback called...");
|
||||||
|
// console.log("typeof name", typeof name);
|
||||||
|
// console.log("typeof fmt", typeof fmt);
|
||||||
|
// console.log("typeof args", typeof args);
|
||||||
|
name = Module.UTF8ToString(name);
|
||||||
|
fmt = Module.UTF8ToString(fmt);
|
||||||
|
// console.log ("name:", name);
|
||||||
|
// console.log ("fmt:", fmt);
|
||||||
|
let argTypes = fmt.split("");
|
||||||
|
let retType = argTypes.shift();
|
||||||
|
// console.log ("arg count:", argTypes.length);
|
||||||
|
// console.log ("arg types:", argTypes);
|
||||||
|
// console.log ("ret type:", retType);
|
||||||
|
|
||||||
|
let jsArgs = [];
|
||||||
|
for (let i = 0; i < argTypes.length; i++) {
|
||||||
|
let ptr = args + (4*i);
|
||||||
|
let val = typeLookup(argTypes[i], ptr);
|
||||||
|
jsArgs.push(val);
|
||||||
|
}
|
||||||
|
console.log(`graphics callback: ${name} [${jsArgs}]`);
|
||||||
|
let retVal = doGraphics(name, ... jsArgs);
|
||||||
|
setReturn(name, retPtr, retType, retVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeLookup(type, ptr) {
|
||||||
|
switch(type) {
|
||||||
|
case "s": // string
|
||||||
|
return Module.UTF8ToString(Module.getValue(ptr, "*"));
|
||||||
|
case "p": // pointer
|
||||||
|
ptr = Module.getValue(ptr, "*");
|
||||||
|
if(!ptr) return 0; // null pointer
|
||||||
|
return Module.getValue(ptr, "*");
|
||||||
|
case "c": // char
|
||||||
|
return String.fromCharCode(Module.getValue(Module.getValue(ptr, "*"), "i8"));
|
||||||
|
case "0": /* 2^0 = 1 byte */
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i8");
|
||||||
|
case "1": /* 2^1 = 2 bytes */
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i16");
|
||||||
|
case "2": /* 2^2 = 4 bytes */
|
||||||
|
case "i": // integer
|
||||||
|
case "n": // number
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "i32");
|
||||||
|
case "f": // float
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "float");
|
||||||
|
case "d": // double
|
||||||
|
return Module.getValue(Module.getValue(ptr, "*"), "double");
|
||||||
|
default:
|
||||||
|
throw new TypeError ("unknown type:" + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReturn(name, ptr, type, value = 0) {
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "p":
|
||||||
|
throw new Error("not implemented");
|
||||||
|
case "s":
|
||||||
|
if(typeof value !== "string")
|
||||||
|
throw new TypeError(`expected ${name} return type to be string`);
|
||||||
|
value=value?value:"(no value)";
|
||||||
|
var strPtr = Module.getValue(ptr, "i32");
|
||||||
|
Module.stringToUTF8(value, strPtr, 1024);
|
||||||
|
break;
|
||||||
|
case "i":
|
||||||
|
if(typeof value !== "number" || !Number.isInteger(value))
|
||||||
|
throw new TypeError(`expected ${name} return type to be integer`);
|
||||||
|
Module.setValue(ptr, value, "i32");
|
||||||
|
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`);
|
||||||
|
Module.setValue(ptr, value, "i8");
|
||||||
|
break;
|
||||||
|
case "f":
|
||||||
|
if(typeof value !== "number" || isFloat(value))
|
||||||
|
throw new TypeError(`expected ${name} return type to be float`);
|
||||||
|
// XXX: I'm not sure why 'double' works and 'float' doesn't
|
||||||
|
Module.setValue(ptr, value, "double");
|
||||||
|
break;
|
||||||
|
case "d":
|
||||||
|
if(typeof value !== "number" || isFloat(value))
|
||||||
|
throw new TypeError(`expected ${name} return type to be float`);
|
||||||
|
Module.setValue(ptr, value, "double");
|
||||||
|
break;
|
||||||
|
case "v":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("unknown type");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFloat(n){
|
||||||
|
return n === +n && n !== (n|0) && !Number.isInteger(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let winCount = 0;
|
||||||
|
function doGraphics(name, ... args) {
|
||||||
|
switch(name) {
|
||||||
|
case "shim_create_nhwindow":
|
||||||
|
winCount++;
|
||||||
|
console.log("creating window", args, "returning", winCount);
|
||||||
|
return winCount;
|
||||||
|
case "shim_yn_function":
|
||||||
|
case "shim_message_menu":
|
||||||
|
return 121; // 'y'
|
||||||
|
case "shim_nhgetch":
|
||||||
|
case "shim_nh_poskey":
|
||||||
|
return 46;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// var Module = null;
|
||||||
|
// factory(Module).then((ret) => {
|
||||||
|
// if(ret !== Module) {
|
||||||
|
// console.log("ret and Module are not the same");
|
||||||
|
// } else {
|
||||||
|
// console.log("ret and Module are the same");
|
||||||
|
// }
|
||||||
|
// // console.log("Module", util.inspect(Module, {depth: null, showHidden: true}));
|
||||||
|
// // TODO:
|
||||||
|
// // stub_graphics_set_callback();
|
||||||
|
|
||||||
|
// // options:
|
||||||
|
// // https://emscripten.org/docs/api_reference/module.html
|
||||||
|
// // logReadFiles
|
||||||
|
// // printWithColors
|
||||||
|
// // noInitialRun
|
||||||
|
// // onRuntimeInitialized
|
||||||
|
// console.log("doing run");
|
||||||
|
// // Module.run();
|
||||||
|
|
||||||
|
// // // main loop
|
||||||
|
// // console.log("creating function");
|
||||||
|
// // let fn = Module.addFunction(wasmCallback, "vii");
|
||||||
|
|
||||||
|
// // console.log("doing call");
|
||||||
|
// // Module.ccall(
|
||||||
|
// // "mainloop", // C function name
|
||||||
|
// // null, // return type
|
||||||
|
// // ["number"], // arg types
|
||||||
|
// // [fn], // arg values
|
||||||
|
// // {async: true} // options
|
||||||
|
// // );
|
||||||
|
// // // TODO: removeFunction(fn)
|
||||||
|
|
||||||
|
// // var i = 0;
|
||||||
|
// // setInterval(function() {
|
||||||
|
// // console.log("interval", i++);
|
||||||
|
// // },1000);
|
||||||
|
// });
|
||||||
|
|
||||||
Reference in New Issue
Block a user