Browse Source

libnethack pr385

roll parts of pr385 into source tree

This does not take the PR as is.

Unlike the PR, this streamlines and minimizes the integration somewhat:

- use hints/include mechanism instead of creating alternative
  Makefile.dat, Makefile.src, Makefile.top, Makefile.utl in sys/lib;
  those would have been a maintenance nightmare.

- don't have alternative mkmkfile.sh and setup.sh in sys/lib.

- sys/lib/libnethackmain.c differed from sys/unix/unixmain.c by
  very little, so just place a small bit of conditional code at the
  top of sys/unix/unixmain.c instead.

- changed the conditional code bits from __EMSCRIPTEN__ to
  CROSS_TO_WASM.

- You should be able to build the wasm result by:
    cd sys/unix ; sh setup.sh hints/linux.2020 ; cd ../..
    make fetch-lua    (<-one time)
    make WANT_LIBNH all

- You should be able to build LIBNBH by:
    cd sys/unix ; sh setup.sh hints/linux.2020 ; cd ../..
    make fetch-lua    (<-one time)
    make CROSS_TO_WASM=1 all

As it is currently coded, winshim.c requires C99.
NetHack-3.7
Adam Powers 1 year ago
committed by nhmall
parent
commit
dc2d757399
  1. 8
      .gitignore
  2. 2
      doc/fixes37.0
  3. 11
      include/global.h
  4. 2
      include/unixconf.h
  5. 2
      src/mdlib.c
  6. 39
      src/rip.c
  7. 2
      src/version.c
  8. 95
      sys/lib/README.md
  9. 360
      sys/lib/hints/macOS.2020
  10. 77
      sys/lib/hints/wasm
  11. 95
      sys/lib/npm-package/LICENSE.md
  12. 47
      sys/lib/npm-package/README.md
  13. 20
      sys/lib/npm-package/package.json
  14. 49
      sys/lib/npm-package/src/nethackShim.js
  15. 150
      sys/lib/sysconf
  16. 8
      sys/lib/test/README.md
  17. 115
      sys/lib/test/libtest.c
  18. 41
      sys/lib/test/run.sh
  19. 8
      sys/unix/Makefile.src
  20. 2
      sys/unix/Makefile.top
  21. 50
      sys/unix/hints/include/cross-post.2020
  22. 116
      sys/unix/hints/include/cross-pre.2020
  23. 4
      sys/unix/hints/include/multiw-2.2020
  24. 10
      sys/unix/hints/linux.2020
  25. 13
      sys/unix/hints/macOS.2020
  26. 12
      sys/unix/unixmain.c
  27. 8
      util/makedefs.c
  28. 331
      win/shim/winshim.c

8
.gitignore

@ -37,7 +37,7 @@ Release/
binary/
build/
ipch/
lib/
lib/*
Nethack.sln
Nethack.sdf
Nethack.opensdf
@ -81,3 +81,9 @@ win/share/monthin.txt
win/share/objthin.txt
win/share/oththin.txt
# end of ms-dos
#libnethack
targets/*
#test.js
#sys/lib/npm-package/build/nethack.js
#sys/lib/npm-package/build/nethack.wasm

2
doc/fixes37.0

@ -597,6 +597,8 @@ fix the "stuck pets" issue (github #329)
allow themed room subrooms to be filled (github #347)
allow rereading spellbooks to refresh memory at any time (github #261)
allow themed rooms constrained by level difficulty (github #344)
add a varied form of LIBNH nethack library contribution (github #385)
add cross-compile to WASM (github #385)
Code Cleanup and Reorganization

11
include/global.h

@ -399,11 +399,14 @@ struct savefile_info {
#ifdef UNIX
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
/* see end.c */
#if !defined(CROSS_TO_WASM)
#ifndef PANICTRACE
#define PANICTRACE
#endif
#endif
#endif
#endif /* PANICTRACE */
#endif /* CROSS_TO_WASM */
#endif /* NH_DEVEL_STATUS != NH_STATUS_RELEASED */
#endif /* UNIX */
/* The following are meaningless if PANICTRACE is not defined: */
#if defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2)
#define PANICTRACE_LIBC
@ -412,8 +415,10 @@ struct savefile_info {
#define PANICTRACE_LIBC
#endif
#ifdef UNIX
#if !defined(CROSS_TO_WASM) /* no popen in WASM */
#define PANICTRACE_GDB
#endif
#endif
/* Supply nethack_enter macro if not supplied by port */
#ifndef nethack_enter

2
include/unixconf.h

@ -389,7 +389,7 @@
#endif /* LINUX */
#endif /* GNOME_GRAPHICS */
#ifdef MACOSX
#if defined(MACOSX) && !defined(LIBNH)
# define RUNTIME_PASTEBUF_SUPPORT
#endif

2
src/mdlib.c

@ -131,7 +131,7 @@ static struct win_info window_opts[] = {
{ "mswin", "Windows GUI", TRUE },
#endif
#ifdef SHIM_GRAPHICS
{ "shim", "Nethack Library Windowing Shim", TRUE },
{ "shim", "NetHack Library Windowing Shim", TRUE },
#endif
#if 0 /* remainder have been retired */

39
src/rip.c

@ -1,4 +1,4 @@
/* NetHack 3.7 rip.c $NHDT-Date: 1596498204 2020/08/03 23:43:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.32 $ */
/* NetHack 3.7 rip.c $NHDT-Date: 1597967808 2020/08/20 23:56:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.33 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2017. */
/* NetHack may be freely redistributed. See license for details. */
@ -6,7 +6,8 @@
#include "hack.h"
#if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) \
|| defined(MSWIN_GRAPHICS) || defined(DUMPLOG) || defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS)
|| defined(MSWIN_GRAPHICS) || defined(DUMPLOG) \
|| defined(CURSES_GRAPHICS) || defined(SHIM_GRAPHICS)
#define TEXT_TOMBSTONE
#endif
#if defined(mac) || defined(__BEOS__) || defined(WIN32_GRAPHICS)
@ -60,12 +61,10 @@ static const char *rip_txt[] = {
};
#define STONE_LINE_CENT 19 /* char[] element of center of stone face */
#endif /* NH320_DEDICATION */
#define STONE_LINE_LEN \
16 /* # chars that fit on one line \
* (note 1 ' ' border) \
*/
#define NAME_LINE 6 /* *char[] line # for player name */
#define GOLD_LINE 7 /* *char[] line # for amount of gold */
#define STONE_LINE_LEN 16 /* # chars that fit on one line
* (note 1 ' ' border) */
#define NAME_LINE 6 /* *char[] line # for player name */
#define GOLD_LINE 7 /* *char[] line # for amount of gold */
#define DEATH_LINE 8 /* *char[] line # for death description */
#define YEAR_LINE 12 /* *char[] line # for year */
@ -90,9 +89,9 @@ time_t when;
register char **dp;
register char *dpx;
char buf[BUFSZ];
long year;
register int x;
int line;
int line, year;
long cash;
g.rip = dp = (char **) alloc(sizeof(rip_txt));
for (x = 0; rip_txt[x]; ++x)
@ -100,13 +99,15 @@ time_t when;
dp[x] = (char *) 0;
/* Put name on stone */
Sprintf(buf, "%s", g.plname);
buf[STONE_LINE_LEN] = 0;
Sprintf(buf, "%.*s", (int) STONE_LINE_LEN, g.plname);
center(NAME_LINE, buf);
/* Put $ on stone */
Sprintf(buf, "%ld Au", g.done_money);
buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
cash = max(g.done_money, 0L);
/* arbitrary upper limit; practical upper limit is quite a bit less */
if (cash > 999999999L)
cash = 999999999L;
Sprintf(buf, "%ld Au", cash);
center(GOLD_LINE, buf);
/* Put together death description */
@ -114,11 +115,11 @@ time_t when;
/* Put death type on stone */
for (line = DEATH_LINE, dpx = buf; line < YEAR_LINE; line++) {
register int i, i0;
char tmpchar;
int i, i0 = (int) strlen(dpx);
if ((i0 = strlen(dpx)) > STONE_LINE_LEN) {
for (i = STONE_LINE_LEN; ((i0 > STONE_LINE_LEN) && i); i--)
if (i0 > STONE_LINE_LEN) {
for (i = STONE_LINE_LEN; (i > 0) && (i0 > STONE_LINE_LEN); --i)
if (dpx[i] == ' ')
i0 = i;
if (!i)
@ -135,8 +136,8 @@ time_t when;
}
/* Put year on stone */
year = yyyymmdd(when) / 10000L;
Sprintf(buf, "%4ld", year);
year = (int) ((yyyymmdd(when) / 10000L) % 10000L);
Sprintf(buf, "%4d", year);
center(YEAR_LINE, buf);
#ifdef DUMPLOG

2
src/version.c

@ -265,7 +265,7 @@ boolean pastebuf;
raw_printf("%s", buf2);
if (pastebuf) {
#ifdef RUNTIME_PASTEBUF_SUPPORT
#if defined(RUNTIME_PASTEBUF_SUPPORT) && !defined(LIBNH)
/*
* Call a platform/port-specific routine to insert the
* version information into a paste buffer. Useful for

95
sys/lib/README.md

@ -0,0 +1,95 @@
# About
This creates a library for NetHack that can be incorporated into other programs. There are two different libraries that are currently available:
* libnethack.a - a binary Unix library
* nethack.js / nethack.wasm - a [WebAssembly / WASM](https://webassembly.org/) library for use in JavaScript programs (both nodejs and browser)
## Build
This library has only been built on MacOS, but should work on Linux and other unix-ish platforms. If you have problems, start by stealing hints files from the `sys/unix/hints` for your platform. Contributions for other platforms are happily accepted.
Building the WASM module requires that you have the [emscripten toolchain / sdk installed](https://emscripten.org/docs/getting_started/downloads.html).
Generally the build is the same as the unix build:
1. `cd sys/lib`
2. For `libnethack.a`: `./setup.sh hints/macOS.2020`; for `nethack.js`: `./setup.sh hints/wasm`
3. `cd ../..`
4. `make`
Resulting libaries will be in the `src` directory.
WASM also has a npm module that can be published out of `sys/lib/npm-library`. After building the `nethack.js` it can be published by:
1. `cd sys/lib/npm-library`
2. `npm publish`
## API: libnethack.a
The API is two functions:
* `nhmain(int argc, char *argv[])` - The main function for NetHack that configures the program and runs the `moveloop()` until the game is over. The arguments to this function are the [command line arguments](https://nethackwiki.com/wiki/Options) to NetHack.
* `shim_graphics_set_callback(shim_callback_t cb)` - A single function that sets a callback to gather graphics events: write a string to screen, get user input, etc. Your job is to pass in a callback and handle all the requested rendering events to show NetHack on the scrren. The callback is `void shim_callback_t(const char *name, void *ret_ptr, const char *fmt, ...)`
* `name` is the name of the [window function](https://github.com/NetHack/NetHack/blob/NetHack-3.7/doc/window.doc) that needs to be handled
* `ret_ptr` is a pointer to a memory space for the return value. The type expected to be returned in this pointer is described by the first character of the `fmt` string.
* `fmt` is a string that describes the signature of the callback. The first character in the string is the return type and any additional characters describe the variable arguments: `i` for integer, `s` for string, `p` for pointer, `c` for character, `v` for void. For example, if format is "vis" the callback will have no return (void), the first argument will be an integer, and the second argument will be a string. If format is "iii" the callback must return an integer, and both the arguments passed in will be integers.
* [Variadic arguments](https://www.gnu.org/software/libc/manual/html_node/Variadic-Example.html): a variable number and type of arguments depending on the `window function` that is being called. The arguments associated with each `name` are described in the [NetHack window.doc](https://github.com/NetHack/NetHack/blob/NetHack-3.7/doc/window.doc).
Where is the header file for the API you ask? There isn't one. It's three functions, just drop the forward declarations at the top of your file (or create your own header). It's more work figuring out how to install and copy around header files than it's worth for such a small API. If you disagree, feel free to sumbit a PR to fix it. :)
## API: nethack.js
The WebAssembly API has a similar signature to `libnethack.a` with minor syntactic differences:
* `main(int argc, char argv[])` - The main function for NetHack
* `shim_graphics_set_callback(char *cbName)` - A `String` representing a name of a callback function. The callback function be registered as `globalThis[cbName] = function yourCallback(name, ... args) { /* your stuff */ }`. Note that [globalThis](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) points to `window` in browsers and `global` in node.js.
* `name` is the name of the [window function](https://github.com/NetHack/NetHack/blob/NetHack-3.7/doc/window.doc) that needs to be handled
* `... args` is a variable number and type of arguments depending on the `window function` that is being called. The arguments associated with each `name` are described in the [NetHack window.doc](https://github.com/NetHack/NetHack/blob/NetHack-3.7/doc/window.doc)
* The function must return the value expected for the specified `name`
## API Stability
The "shim graphics" API should generally be stable. I aspire to replace the command line arguments (argc / argv) with a structure of options, so the `nhmain()` and `main()` functions may change at some point.
## libnethack.a example
``` c
#include <stdio.h>
int nhmain(int argc, char *argv[]);
typedef void(*shim_callback_t)(const char *name, void *ret_ptr, const char *fmt, ...);
void shim_graphics_set_callback(shim_callback_t cb);
void window_cb(const char *name, void *ret_ptr, const char *fmt, ...) {
/* TODO */
}
int main(int argc, char *argv[]) {
shim_graphics_set_callback(window_cb);
nhmain(argc, argv);
}
```
## nethack.js example
``` js
const path = require("path");
// starts nethack
function nethackStart(cb, inputModule = {}) {
// set callback
let cbName = cb.name;
if (cbName === "") cbName = "__anonymousNetHackCallback";
let userCallback = globalThis[cbName] = cb;
// Emscripten Module config
let Module = inputModule;
savedOnRuntimeInitialized = Module.onRuntimeInitialized;
Module.onRuntimeInitialized = function (... args) {
// after the WASM is loaded, add the shim graphics callback function
Module.ccall(
"shim_graphics_set_callback", // C function name
null, // return type
["string"], // arg types
[cbName], // arg values
{async: true} // options
);
};
// load and run the module
var factory = require(path.join(__dirname, "../build/nethack.js"));
factory(Module);
}
nethackStart(yourCallbackFunction);
```

360
sys/lib/hints/macOS.2020

@ -0,0 +1,360 @@
# NetHack 3.7 macOS.2020 $NHDT-Date: 1597704793 2020/08/17 22:53:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.69 $
# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2015.
# NetHack may be freely redistributed. See license for details.
#
#---------------------------------------------------------------------
# MacOS hints file with support for multiple window ports (interfaces)
# Tested on:
# - MacOS Catalina 10.15
#
# If this doesn't work for some other version of Mac OS X, consider
# making a new hints file it, rather than changing this one.
# And let us know about it.
# Useful info: http://www.opensource.apple.com/darwinsource/index.html
#-PRE xxxx
# macOS X hints file
#
# 5. Other
#-----------------------------------------------------------------------------
# You shouldn't need to change anything below here (in the hints file; if
# you're reading this in Makefile augmented by hints, that may not be true).
#
AR=ar rcu
RANLIB=ranlib
# XXX -g vs -O should go here, -I../include goes in the makefile
CFLAGS+=-g -I../include -DNOTPARMDECL
CFLAGS+=-Wno-missing-field-initializers -Wimplicit -Wreturn-type -Wformat -Wswitch -Wshadow -Wwrite-strings
CFLAGS+=-DGCC_WARN
# NetHack sources control
CFLAGS+=-DDLB
CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
CFLAGS+=-DDLB
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
#CFLAGS+=-DTIMED_DELAY
#CFLAGS+=-DDUMPLOG
#CFLAGS+=-DCONFIG_ERROR_SECURE=FALSE
CFLAGS+=-DGREPPATH=\"/usr/bin/grep\"
#CFLAGS+=-DCOMPRESS=\"/bin/gzip\" -DCOMPRESS_EXTENSION=\".gz\"
# older binaries use NOCLIPPING, but that disables SIGWINCH
#CFLAGS+=-DNOCLIPPING
CFLAGS+=-DNOMAIL
#CFLAGS+=-DEXTRA_SANITY_CHECKS
#CFLAGS+=-DEDIT_GETLIN
#CFLAGS+=-DSCORE_ON_BOTL
#CFLAGS+=-DMSGHANDLER
#CFLAGS+=-DTTY_TILES_ESCCODES
#CFLAGS+=-DTTY_SOUND_ESCCODES
CFLAGS+=-DDEFAULT_WINDOW_SYS=\"shim\" -DNOTTYGRAPHICS -DLIBNH
CFLAGS+= $(WINCFLAGS) #WINCFLAGS set from multiw-2.2020
VARDATND =
VARDATND0 =
CURSESLIB =
ifdef WANT_WIN_CHAIN
HINTSRC=$(CHAINSRC)
HINTOBJ=$(CHAINOBJ)
endif # WANT_WIN_CHAIN
LINK=$(CC)
# prevent duplicate tile.o in WINOBJ
WINOBJ = $(sort $(WINOBJ0))
# prevent duplicates in VARDATND if both X11 and Qt are being supported
VARDATND += $(sort $(VARDATND0))
WANT_BUNDLE=1
ifdef WANT_SHARE_INSTALL
# if $GAMEUID is root, we install into roughly proper Mac locations, otherwise
# we install into ~/nethackdir
ifeq ($(GAMEUID),root)
PREFIX:=/Library/NetHack
SHELLDIR=/usr/local/bin
HACKDIR=$(PREFIX)/nethackdir
CHOWN=chown
CHGRP=chgrp
# We run sgid so the game has access to both HACKDIR and user preferences.
GAMEPERM = 02755
else # ! root
PREFIX:=/Users/$(GAMEUID)
SHELLDIR=$(PREFIX)/bin
HACKDIR=$(PREFIX)/Library/NetHack/nethackdir
CHOWN=/usr/bin/true
CHGRP=/usr/bin/true
GAMEPERM = 0500
endif # ! root
VARFILEPERM = 0664
VARDIRPERM = 0775
ROOTCHECK= [[ `id -u` == 0 ]] || ( echo "Must run install with sudo."; exit 1)
# XXX it's nice we don't write over sysconf, but we've already erased it
# make sure we have group GAMEUID and group GAMEGRP
PREINSTALL= . sys/unix/hints/macosx.sh user2 $(GAMEUID); \
. sys/unix/hints/macosx.sh group2 $(GAMEGRP); \
mkdir $(SHELLDIR); chown $(GAMEUID) $(SHELLDIR)
POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf; \
$(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; \
$(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; \
chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
else ifdef WANT_SOURCE_INSTALL
PREFIX=$(abspath $(NHSROOT))
# suppress nethack.sh
#SHELLDIR=
HACKDIR=$(PREFIX)/playground
CHOWN=/usr/bin/true
CHGRP=/usr/bin/true
GAMEPERM = 0700
VARFILEPERM = 0600
VARDIRPERM = 0700
POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf;
# We can use "make all" to build the whole thing - but it misses some things:
MOREALL=$(MAKE) install
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"$(HACKDIR)/sysconf\" -DSECURE
else # !WANT_SOURCE_INSTALL
PREFIX:=$(wildcard ~)
SHELLDIR=$(PREFIX)/bin
HACKDIR=$(PREFIX)/nethackdir
CHOWN=/usr/bin/true
CHGRP=/usr/bin/true
GAMEPERM = 0700
VARFILEPERM = 0600
VARDIRPERM = 0700
ifdef ($(WANT_DEFAULT),X11)
# install nethack.rc as ~/.nethackrc if no ~/.nethackrc exists
PREINSTALL= cp -n win/X11/nethack.rc ~/.nethackrc || true
endif # WANT_DEFAULT X11
POSTINSTALL+= sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(HACKDIR)/sysconf; \
$(CHOWN) $(GAMEUID) $(HACKDIR)/sysconf; \
$(CHGRP) $(GAMEGRP) $(HACKDIR)/sysconf; \
chmod $(VARFILEPERM) $(HACKDIR)/sysconf;
ifdef WANT_BUNDLE
#
# Bundle
#
# $(HACKDIR)/$(GAME).app/
# Contents/
# Frameworks/
# Info.plist
# MacOS/
# $(GAME)
# PkgInfo/
# PlugIns/
# Resources/
# SharedFrameWorks/
#
BUNDLE = mkdir -p $(HACKDIR)/nethack.app/Contents/MacOS; \
sys/unix/hints/macosx.sh infoplist > $(HACKDIR)/nethack.app/Contents/Info.plist; \
mv $(HACKDIR)/nethack $(HACKDIR)/nethack.app/Contents/MacOS/nethack;
ifdef WANT_SHARE_INSTALL
BUNDLE+= chmod $(GAMEPERM) $(HACKDIR)/nethack.app/Contents/MacOS/nethack;
endif
POSTINSTALL+= $(BUNDLE)
POSTINSTALL+= if test -f $(SHELLDIR)/$(GAME); then \
sed -i '' 's;HACKDIR/$(GAME);HACKDIR/$(GAME).app/Contents/MacOS/$(GAME);' $(SHELLDIR)/$(GAME) ; fi;
endif # WANT_BUNDLE
endif # !WANT_SHARE_INSTALL
INSTDIR=$(HACKDIR)
VARDIR=$(HACKDIR)
# ~/Library/Preferences/NetHack Defaults
# OPTIONS=name:player,number_pad,menustyle:partial,!time,showexp
# OPTIONS=hilite_pet,toptenwin,msghistory:200,windowtype:Qt
#
# Install.Qt mentions a patch for macos - it's not there (it seems to be in the Qt binary
# package under the docs directory).
#-POST
ifdef MAKEFILE_TOP
###
### Packaging
###
# Notes:
# 1) The Apple developer utilities must be installed in the default location.
# 2) Do a normal build before trying to package the game.
# 3) This matches the 3.4.3 Term package, but there are some things that
# should be changed.
#
# Packages that are being distributed must be signed by a Developer ID
# Installer certificate. Set DEVELOPER_CERT to the name of the certificate
# if you wish for your package to be signed for distribution.
#
# If building a package for signing, you must use sudo approriately.
# the binaries and package using sudo but you DO NOT use sudo to sign the
# package. If you use sudo to sign the package, it will fail.
#
# sudo make all
# sudo make build_tty_pkg
# make sign_tty_pkg
#
ifdef WANT_WIN_TTY
DEVUTIL=/Developer/Applications/Utilities
SVS=$(shell $(NHSROOT)/util/makedefs --svs)
SVSDOT=$(shell $(NHSROOT)/util/makedefs --svs .)
PKGROOT_UG = PKGROOT/$(PREFIX)
PKGROOT_UGLN = PKGROOT/$(HACKDIR)
PKGROOT_BIN = PKGROOT/$(SHELLDIR)
#DEVELOPER_CERT = Developer ID Installer: Bart House
DEVELOPER_CERT = NONE
spotless::
rm -rf RESOURCES
rm -rf PKG
rm -rf PKGSCRIPTS
rm -rf PKGROOT
rm -f Info.plist
rm -f Distribution.xml
rm -f NetHack-*-mac-Term*
build_tty_pkg:
ifneq (,$(WANT_WIN_X11)$(WANT_WIN_QT))
-echo build_tty_pkg only works for a tty-only build
exit 1
else
rm -rf NetHack-$(SVS)-mac-Term.pkg NetHack-$(SVS)-mac-Term.dmg
$(MAKE) build_package_root
rm -rf RESOURCES
mkdir RESOURCES
#enscript --language=rtf -o - < dat/license >RESOURCES/License.rtf
sys/unix/hints/macosx.sh descplist > RESOURCES/Description.plist
sys/unix/hints/macosx.sh infoplist > Info.plist
mkdir PKGROOT/Applications
#osacompile -o NetHackQt/NetHackQt.app/nethackdir/NetHackRecover.app \
# win/macosx/NetHackRecover.applescript
#cp win/macosx/recover.pl NetHackQt/NetHackQt.app/nethackdir
osacompile -o PKGROOT/Applications/NetHackRecover.app \
win/macosx/NetHackRecover.applescript
cp win/macosx/recover.pl $(PKGROOT_UGLN)
osacompile -o PKGROOT/Applications/NetHackTerm.app \
win/macosx/NetHackTerm.applescript
# XXX integrate into Makefile.doc
(cd doc; cat Guidebook.mn | ../util/makedefs --grep --input - --output - \
| tbl tmac.n - | groff | pstopdf -i -o Guidebook.pdf)
cp doc/Guidebook.pdf $(PKGROOT_UG)/doc/NetHackGuidebook.pdf
osacompile -o PKGROOT/Applications/NetHackGuidebook.app \
win/macosx/NetHackGuidebook.applescript
mkdir -p PKG
pkgbuild --root PKGROOT --identifier org.nethack.term --scripts PKGSCRIPTS PKG/NH-Term.pkg
productbuild --synthesize --product Info.plist --package PKG/NH-Term.pkg Distribution.xml
productbuild --distribution Distribution.xml --resources RESOURCES --package-path PKG NetHack-$(SVS)-mac-Term-unsigned.pkg
ifeq ($(DEVELOPER_CERT),NONE)
cp NetHack-$(SVS)-mac-Term-unsigned.pkg NetHack-$(SVS)-mac-Term.pkg
hdiutil create -verbose -srcfolder NetHack-$(SVS)-mac-Term-unsigned.pkg NetHack-$(SVS)-mac-Term-unsigned.dmg
@echo -------------------------------------------
@echo PACKAGE IS NOT SIGNED FOR DISTRIBUTION!!!!!
@echo ===========================================
else
@echo "run 'make sign_tty_pkg' to complete package"
endif
sign_tty_pkg:
productsign --timestamp=none --sign "$(DEVELOPER_CERT)" NetHack-$(SVS)-mac-Term-unsigned.pkg NetHack-$(SVS)-mac-Term.pkg || (echo "Package signing failed"; exit 1)
spctl -a -v --type install NetHack-$(SVS)-mac-Term.pkg || (echo "Package not signed properly"; exit 1)
hdiutil create -verbose -srcfolder NetHack-$(SVS)-mac-Term.pkg NetHack-$(SVS)-mac-Term.dmg
build_package_root:
cd src/.. # make sure we are at TOP
rm -rf PKGROOT
mkdir -p $(PKGROOT_UG)/lib $(PKGROOT_BIN) $(PKGROOT_UG)/man/man6 $(PKGROOT_UG)/doc $(PKGROOT_UGLN)
install -p src/nethack $(PKGROOT_BIN)
# XXX should this be called nethackrecover?
install -p util/recover $(PKGROOT_BIN)
install -p doc/nethack.6 $(PKGROOT_UG)/man/man6
install -p doc/recover.6 $(PKGROOT_UG)/man/man6
install -p doc/Guidebook $(PKGROOT_UG)/doc
install -p dat/nhdat $(PKGROOT_UGLN)
sys/unix/hints/macosx.sh editsysconf sys/unix/sysconf $(PKGROOT_UGLN)/sysconf
cd dat; install -p $(DATNODLB) ../$(PKGROOT_UGLN)
# XXX these files should be somewhere else for good Mac form
touch $(PKGROOT_UGLN)/perm $(PKGROOT_UGLN)/record $(PKGROOT_UGLN)/logfile $(PKGROOT_UGLN)/xlogfile
mkdir $(PKGROOT_UGLN)/save
# XXX what about a news file?
mkdir -p PKGSCRIPTS
echo '#!/bin/sh' > PKGSCRIPTS/postinstall
echo dseditgroup -o create -r '"Games Group"' -s 3600 $(GAMEGRP) >> PKGSCRIPTS/postinstall
echo $(CHOWN) $(GAMEUID) $(HACKDIR) >> PKGSCRIPTS/postinstall
echo $(CHOWN) $(GAMEUID) $(HACKDIR)/* >> PKGSCRIPTS/postinstall
echo $(CHGRP) $(GAMEGRP) $(HACKDIR) >> PKGSCRIPTS/postinstall
echo $(CHGRP) $(GAMEGRP) $(HACKDIR)/* >> PKGSCRIPTS/postinstall
echo $(CHOWN) $(GAMEUID) $(SHELLDIR)/nethack >> PKGSCRIPTS/postinstall
echo $(CHGRP) $(GAMEGRP) $(SHELLDIR)/nethack >> PKGSCRIPTS/postinstall
echo $(CHOWN) $(GAMEUID) $(SHELLDIR)/recover >> PKGSCRIPTS/postinstall
echo $(CHGRP) $(GAMEGRP) $(SHELLDIR)/recover >> PKGSCRIPTS/postinstall
echo chmod $(VARDIRPERM) $(HACKDIR) >> PKGSCRIPTS/postinstall
echo chmod $(VARDIRPERM) $(HACKDIR)/save >> PKGSCRIPTS/postinstall
echo chmod $(FILEPERM) $(HACKDIR)/license >> PKGSCRIPTS/postinstall
echo chmod $(FILEPERM) $(HACKDIR)/nhdat >> PKGSCRIPTS/postinstall
echo chmod $(FILEPERM) $(HACKDIR)/symbols >> PKGSCRIPTS/postinstall
echo chmod $(VARFILEPERM) $(HACKDIR)/perm >> PKGSCRIPTS/postinstall
echo chmod $(VARFILEPERM) $(HACKDIR)/record >> PKGSCRIPTS/postinstall
echo chmod $(VARFILEPERM) $(HACKDIR)/logfile >> PKGSCRIPTS/postinstall
echo chmod $(VARFILEPERM) $(HACKDIR)/xlogfile >> PKGSCRIPTS/postinstall
echo chmod $(VARFILEPERM) $(HACKDIR)/sysconf >> PKGSCRIPTS/postinstall
echo chmod $(GAMEPERM) $(SHELLDIR)/nethack >> PKGSCRIPTS/postinstall
echo chmod $(EXEPERM) $(SHELLDIR)/recover >> PKGSCRIPTS/postinstall
chmod 0775 PKGSCRIPTS/postinstall
endif # end of build_tty_pkg
endif # WANT_WIN_TTY for packaging
ifdef WANT_WIN_QT
# XXX untested and incomplete (see below)
build_qt_pkg:
ifneq (,$(WANT_WIN_X11)$(WANT_WIN_TTY))
-echo build_qt_pkg only works for a qt-only build
exit 1
else
$(MAKE) build_package_root
rm -rf NetHackQt
mkdir -p NetHackQt/NetHackQt.app/nethackdir/save
mkdir NetHackQt/Documentation
cp doc/Guidebook.txt doc/nethack.txt doc/recover.txt NetHackQt/Documentation
osacompile -o NetHackQt/NetHackQt.app/nethackdir/NetHackRecover.app \
win/macosx/NetHackRecover.applescript
cp win/macosx/recover.pl NetHackQt/NetHackQt.app/nethackdir
mkdir -p NetHackQt/NetHackQt.app/Contents/Frameworks
cp $(QTDIR)/libqt-mt.3.dylib NetHackQt/NetHackQt.app/Contents/Frameworks
mkdir NetHackQt/NetHackQt.app/Contents/MacOS
mv PKGROOT/nethack NetHackQt/NetHackQt.app/Contents/MacOS
mv PKGROOT/lib/nethackdir NetHackQt/NetHackQt.app/nethackdir
# XXX still missing:
#NetHackQt/NetHackQt.app
# /Contents
# Info.plist
# Resources/nethack.icns
#NetHackQt/Documentation
#NetHackQtRecover.txt
#NetHack Defaults.txt
#changes.patch XXX is this still needed? why isn't it part of the tree?
# doesn't go here
hdiutil create -verbose -srcfolder NetHackQt NetHack-$(SVS)-macosx-qt.dmg
endif # end of build_qt_pkg
endif # WANT_WIN_QT for packaging
endif # MAKEFILE_TOP

77
sys/lib/hints/wasm

@ -0,0 +1,77 @@
#-PRE xxxx
# enscripten WebAssembly config
WANT_WASM=1
WASM_DEBUG=1
WASM_DATA_DIR=$(NHSROOT)/src/wasm-data
# toolchain
EMCC=emcc
EMAR=emar rcu
EMRANLIB=emranlib
# link flags
EMCC_LFLAGS=-s SINGLE_FILE=1
EMCC_LFLAGS=-s WASM=1
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"]'
EMCC_LFLAGS+=-s EXPORTED_RUNTIME_METHODS='["cwrap", "ccall", "addFunction", "removeFunction", "UTF8ToString", "getValue", "setValue"]'
EMCC_LFLAGS+=-s ERROR_ON_UNDEFINED_SYMBOLS=0
EMCC_LFLAGS+=--embed-file wasm-data@/
# For a list of EMCC settings:
# https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
# WASM C flags
EMCC_CFLAGS=
EMCC_CFLAGS+=-Wall
EMCC_CFLAGS+=-Werror
#EMCC_CFLAGS+=-s DISABLE_EXCEPTION_CATCHING=0
EMCC_DEBUG_CFLAGS+=-s ASSERTIONS=1
#EMCC_DEBUG_CFLAGS+=-s ASSERTIONS=2
EMCC_DEBUG_CFLAGS+=-s STACK_OVERFLOW_CHECK=2
EMCC_DEBUG_CFLAGS+=-s SAFE_HEAP=1
EMCC_DEBUG_CFLAGS+=-s LLD_REPORT_UNDEFINED=1
#EMCC_DEBUG_CFLAGS+=-s EXCEPTION_DEBUG=1
#EMCC_DEBUG_CFLAGS+=-fsanitize=undefined -fsanitize=address -fsanitize=leak
#EMCC_DEBUG_CFLAGS+=-s EXIT_RUNTIME
EMCC_PROD_CFLAGS+=-O3
# Nethack C flags
CFLAGS+=-DSYSCF -DSYSCF_FILE=\"/sysconf\" -DSECURE
CFLAGS+=-g -I../include -DNOTPARMDECL
CFLAGS+=-Wall
CFLAGS+=-Werror
CFLAGS+=-DGCC_WARN
# NetHack sources control
CFLAGS+=-DDLB
CFLAGS+=-DHACKDIR=\"$(HACKDIR)\"
CFLAGS+=-DDLB
#CFLAGS+=-DGREPPATH=\"/usr/bin/grep\"
CFLAGS+=-DNOMAIL
ifdef WASM_DEBUG
EMCC_CFLAGS+=$(EMCC_DEBUG_CFLAGS)
else
EMCC_CFLAGS+=$(EMCC_PROD_CFLAGS)
endif
# installation config
# hackdir is the wasm / emscripten embed data root directory
HACKDIR=/
CHOWN=/usr/bin/true
CHGRP=/usr/bin/true
GAMEPERM = 0700
VARFILEPERM = 0600
VARDIRPERM = 0700
INSTDIR=$(HACKDIR)
VARDIR=$(HACKDIR)
#-POST
# no post

95
sys/lib/npm-package/LICENSE.md

@ -0,0 +1,95 @@
NETHACK GENERAL PUBLIC LICENSE
(Copyright 1989 M. Stephenson)
(Based on the BISON general public license,
copyright 1988 Richard M. Stallman)
Everyone is permitted to copy and distribute verbatim copies of this
license, but changing it is not allowed. You can also use this wording to
make the terms for other programs.
The license agreements of most software companies keep you at the mercy of
those companies. By contrast, our general public license is intended to give
everyone the right to share NetHack. To make sure that you get the rights we
want you to have, we need to make restrictions that forbid anyone to deny you
these rights or to ask you to surrender the rights. Hence this license
agreement.
Specifically, we want to make sure that you have the right to give away
copies of NetHack, that you receive source code or else can get it if you
want it, that you can change NetHack or use pieces of it in new free
programs, and that you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to
deprive anyone else of these rights. For example, if you distribute copies
of NetHack, you must give the recipients all the rights that you have. You
must make sure that they, too, receive or can get the source code. And you
must tell them their rights.
Also, for our own protection, we must make certain that everyone finds out
that there is no warranty for NetHack. If NetHack is modified by someone
else and passed on, we want its recipients to know that what they have is
not what we distributed.
Therefore we (Mike Stephenson and other holders of NetHack copyrights) make
the following terms which say what you must do to be allowed to distribute or
change NetHack.
COPYING POLICIES
1. You may copy and distribute verbatim copies of NetHack source code as
you receive it, in any medium, provided that you keep intact the notices on
all files that refer to copyrights, to this License Agreement, and to the
absence of any warranty; and give any other recipients of the NetHack
program a copy of this License Agreement along with the program.
2. You may modify your copy or copies of NetHack or any portion of it, and
copy and distribute such modifications under the terms of Paragraph 1 above
(including distributing this License Agreement), provided that you also do the
following:
a) cause the modified files to carry prominent notices stating that you
changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that in
whole or in part contains or is a derivative of NetHack or any part
thereof, to be licensed at no charge to all third parties on terms
identical to those contained in this License Agreement (except that you
may choose to grant more extensive warranty protection to some or all
third parties, at your option)
c) You may charge a distribution fee for the physical act of
transferring a copy, and you may at your option offer warranty protection
in exchange for a fee.
3. You may copy and distribute NetHack (or a portion or derivative of it,
under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete machine-readable source code, which
must be distributed under the terms of Paragraphs 1 and 2 above; or,
b) accompany it with full information as to how to obtain the complete
machine-readable source code from an appropriate archive site. (This
alternative is allowed only for noncommercial distribution.)
For these purposes, complete source code means either the full source
distribution as originally released over Usenet or updated copies of the
files in this distribution used to create the object code or executable.
4. You may not copy, sublicense, distribute or transfer NetHack except as
expressly provided under this License Agreement. Any attempt otherwise to
copy, sublicense, distribute or transfer NetHack is void and your rights to
use the program under this License agreement shall be automatically
terminated. However, parties who have received computer software programs
from you with this License Agreement will not have their licenses terminated
so long as such parties remain in full compliance.
Stated plainly: You are permitted to modify NetHack, or otherwise use parts
of NetHack, provided that you comply with the conditions specified above;
in particular, your modified NetHack or program containing parts of NetHack
must remain freely available as provided in this License Agreement. In
other words, go ahead and share NetHack, but don't try to stop anyone else
from sharing it farther.

47
sys/lib/npm-package/README.md

@ -0,0 +1,47 @@
# NetHack
This is the ACTUAL NetHack game, originally written in 1982 and one of the longest-standing open source collaborations. This isn't a wrapper around the binary NetHack, but the game itself compiled into [WebAssembly](https://webassembly.org/) (WASM) using [emscripten](https://emscripten.org/). This module should run [anywhere WebAssembly is supported](https://developer.mozilla.org/en-US/docs/WebAssembly#Browser_compatibility) including node.js and modern browsers.
Since NetHack typically uses the [TTY](https://en.wikipedia.org/wiki/Computer_terminal#Text_terminals) to show depictions of the game and that won't work for WebAssembly, you are required to implement the graphics portion of NetHack to make this work. This allows a wide variety of UIs to be created, both text and graphics based as well as using keyboard and mouse to control the game. The API for implementing graphics is described below.
## Install
``` sh
npm install nethack
```
## API
The main module returns a setup function: `startNethack(uiCallback, moduleOptions)`.
* `uiCallback(name, ... args)` - Your callback function that will handle rendering NetHack on the screen of your choice. The `name` argument is one of the UI functions of the [NetHack Window Interface](https://github.com/NetHack/NetHack/blob/NetHack-3.7/doc/window.doc) and the `args` are corresponding to the window interface function that is being called. You are required to return the correct type of data for the function that is implemented. The `uiCallback` may be an `async` function.
* `moduleOptions` - An optional [emscripten Module object](https://emscripten.org/docs/api_reference/module.html) for configuring the WASM that will be run.
* `Module.arguments` - Of note is the [arguments property](https://emscripten.org/docs/api_reference/module.html#Module.arguments) which gets passed to NetHack as its [command line parameters](https://nethackwiki.com/wiki/Options).
## Example
``` js
let nethackStart = require("nethack");
nethackStart(doGraphics);
let winCount = 0;
async function doGraphics(name, ... args) {
console.log(`shim graphics: ${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; // return 'y' to all questions
case "shim_nhgetch":
case "shim_nh_poskey":
return 0; // simulates a mouse click on "exit up the stairs"
default:
return 0;
}
}
```
## Other Notes
* This module isn't small -- the WASM code is about 10MB. It may be slow to load over non-broadband connections. There are some emscripten build optimizations that may help with browser builds (such as dynamic loading), but those aren't currently part of this package. Pull requests are always welcome. :)
* This hasn't been tested on browsers. If you get this to work on a browser, please let me know and I will add notes. Or if anyone wants to help setup automated browser testing, that would be supremely appreciated.

20
sys/lib/npm-package/package.json

@ -0,0 +1,20 @@
{
"name": "@neth4ck/neth4ck",
"version": "1.0.0",
"description": "The original NetHack rogue-like game built as a WebAssembly module",
"main": "src/nethackShim.js",
"scripts": {
"test": "node test/test.js",
"clean": "rm ./build/nethack.js; rm ./build/nethack.wasm; true",
"build": "cp ../../../src/nethack.js ../../../src/nethack.wasm ./build",
"prepack": "npm run build"
},
"keywords": [
"nethack",
"rogue",
"rogue-like",
"game"
],
"author": "Adam Powers <apowers@ato.ms>",
"license": "SEE LICENSE IN LICENSE.md"
}

49
sys/lib/npm-package/src/nethackShim.js

@ -0,0 +1,49 @@
const path = require("path");
let Module;
let userCallback;
let savedOnRuntimeInitialized;
// starts nethack
function nethackStart(cb, inputModule = {}) {
if(typeof cb !== "string" && typeof cb !== "function") throw new TypeError("expected first argument to be 'Function' or 'String' representing global callback function name");
if(typeof inputModule !== "object") throw new TypeError("expected second argument to be object");
let cbName;
if(typeof cb === "function") {
cbName = cb.name;
if (cbName === "") cbName = "__anonymousNetHackCallback";
if (globalThis[cbName] === undefined) globalThis[cbName] = cb;
else if (globalThis[cbName] !== cb) throw new Error (`'globalThis["${cbName}"]' is not the same as specified callback`);
}
/* global globalThis */
userCallback = globalThis[cbName];
if(typeof userCallback !== "function") throw new TypeError(`expected 'globalThis["${cbName}"]' to be a function`);
// if(userCallback.constructor.name !== "AsyncFunction") throw new TypeError(`expected 'globalThis["${cbName}"]' to be an async function`);
// Emscripten Module config
Module = inputModule;
savedOnRuntimeInitialized = Module.onRuntimeInitialized;
Module.onRuntimeInitialized = function (... args) {
// after the WASM is loaded, add the shim graphics callback function
Module.ccall(
"shim_graphics_set_callback", // C function name
null, // return type
["string"], // arg types
[cbName], // arg values
{async: true} // options
);
// if the user had their own onRuntimeInitialized(), call it now
if (savedOnRuntimeInitialized) savedOnRuntimeInitialized(... args);
};
// load and run the module
var factory = require(path.join(__dirname, "../build/nethack.js"));
factory(Module);
}
// TODO: ES6 'import' style module
module.exports = nethackStart;

150
sys/lib/sysconf

@ -0,0 +1,150 @@
# NetHack 3.7 sysconf $NHDT-Date: 1596498296 2020/08/03 23:44:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.39 $
# Copyright (c) 2015 by Kenneth Lorber, Kensington, Maryland
# NetHack may be freely redistributed. See license for details.
#
# Sample sysconf file.
# The sysconf file is only used if NetHack is compiled with SYSCF defined.
# It can be used to augment or override certain settings compiled into the
# program.
#
# This file can also be used to set local system defaults for run-time
# options, using the same syntax as an individual user's ./nethackrc file.
# Which users can use debug mode (aka wizard mode; accessed via '-D' command
# line flag or OPTIONS=playmode:debug in the runtime options config file).
# A value of * allows anyone to enter debugging mode.
WIZARDS=root games
# Which users can use explore mode (aka discover mode; accessed via '-X'
# command line flag or OPTIONS=playmode:explore in runtime options file or
# via '#exploremode' command during normal play). Same syntax as WIZARDS.
EXPLORERS=*
# Users allowed to use the '!' (shell escape) and '^Z' (suspend process)
# commands to temporarily leave the game and enter a shell process.
# (To resume play, use the shell command 'exit' (for most shells) to
# return from '!' or the shell command 'fg' to return from '^Z'.
# For the typical multi-user system where players have access to a shell
# prompt when logged in and run the game from their own username, a value
# of 'SHELLERS=*' is appropriate. However, some inexperienced players
# occasionally get stuck outside the game by accidentally typing '!' or
# '^Z' during play and not knowing how to go back.)
# Uses the same syntax as the WIZARDS and EXPLORERS options above.
#SHELLERS=
# If the user name is found in this list, prompt for username instead.
# Uses the same syntax as the WIZARDS option above.
# A public server should probably disable this.
# ["ec2-user" is the default user name on Amazon Linux]
GENERICUSERS=play player game games nethack nethacker ec2-user
# Use the player name for matching WIZARDS, EXPLORERS and SHELLERS,
# instead of the user's login name.
#CHECK_PLNAME=1
# Limit the number of simultaneous games (see also nethack.sh).
# Valid values are 0-25.
# Commenting this out or setting the value to 0 constructs lock files
# with UID and playername, so each user may have one game at a time,
# but number of different players is not limited.
# Setting this to any other value constructs the lock files with
# letter and "lock" (eg. alock, block, ...)
MAXPLAYERS=10
# If not null, added to string "To get local support, " in the support
# information help.
#SUPPORT=call Izchak at extension 42.
# If not null, displayed at the end of a panic-save sequence.
#RECOVER=Run the recover program.
# Uncomment the next line to disable the SEDUCE option, causing succubi and
# incubi to use nymphs' charm behavior rather than their own seduce behavior.
#SEDUCE=0
# Uncomment the next line to enable some accessibility features such
# as S_hero_override and S_pet_override symbols for screen readers
# in the user config file.
#ACCESSIBILITY=1
# Uncomment to disable savefile UID checking.
#CHECK_SAVE_UID=0
# Record (high score) file options.
# CAUTION: changing these after people have started playing games can
# lead to lost high scores!
# Maximum entries for one person.
#PERSMAX=10
# Maximum entries in the record file.
#ENTRYMAX=100
# Minimum points to get an entry.
#POINTSMIN=1
# Determine identity of "person" in the score file with name (0) or
# numeric (1) user id.
#PERS_IS_UID=1
# Maximum number of score file entries to use for random statue names
#MAX_STATUENAME_RANK=10
# Show debugging information originating from these source files.
# Use '*' for all, or list source files separated by spaces.
# Only available if game has been compiled with DEBUG, and can be
# overridden via DEBUGFILES environment variable.
#DEBUGFILES=*
# Save end of game dump log to this file.
# Only available if NetHack was compiled with DUMPLOG
# Allows following placeholders:
# %% literal '%'
# %v version (eg. "3.7.0-0")
# %u game UID
# %t game start time, UNIX timestamp format
# %T current time, UNIX timestamp format
# %d game start time, YYYYMMDDhhmmss format
# %D current time, YYYYMMDDhhmmss format
# %n player name
# %N first character of player name
#DUMPLOGFILE=/tmp/nethack.%n.%d.log
# Number of bones file pools.
# The pool you belong to is determined at game start. You will
# load and save bones only from that pool. Generally useful
# for public servers only.
# Changing this might make existing bones inaccessible.
# Disabled by setting to 0, or commenting out.
#BONES_POOLS=10
# Try to get more info in case of a program bug or crash. Only used
# if the program is built with the PANICTRACE compile-time option enabled.
# By default PANICTRACE is enabled if (NH_DEVEL_STATUS != NH_STATUS_RELEASED),
# otherwise disabled.
# Using GDB can get more information and works on more systems but requires
# 'gdb' be available; using LIBC only works if NetHack is linked with a
# libc that supports the backtrace(3) API. Both require certain compilation
# options. See src/end.c and sys/unix/hints/* for more information.
#GDBPATH=/usr/bin/gdb
#GREPPATH=/bin/grep
# Values are priorities: 0 - do not use this method, 1 - low priority,
# 2 - high priority. Non-zero priority methods are tried in order.
PANICTRACE_GDB=0
PANICTRACE_LIBC=0
# 'portable_device_paths' is only supported for Windows. Starting with
# 3.6.3, nethack on Windows treats the folder containing nethack.exe and
# nethackW.exe as read-only and puts data files which are generated or
# modified during play or by the user in assorted folders derived from
# user name. 3.6.4 added PORTABLE_DEVICE_PATHS to allow reverting to
# the old behavior of having the run-time configuration file and other
# data in the same directory as the executable so that the whole thing
# can be moved from one machine to another (flash drive or perhaps cloud)
# without updating folder paths.
#PORTABLE_DEVICE_PATHS=0
# Ordinary run-time options can be set here to override the builtin-in
# default values. Unlike all the SYSCF values above, individual users
# can override the overridden options set here by choosing their own
# option settings via NETHACKOPTIONS in their environment or via
# ~/.nethackrc run-time configuration file.
#OPTIONS=!autopickup,fruit:tomato,symset:DECgraphics
#eof

8
sys/lib/test/README.md

@ -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

115
sys/lib/test/libtest.c

@ -0,0 +1,115 @@
#include <stdio.h>
#include <stdarg.h>
/* external functions */
int nhmain(int argc, char *argv[]);
typedef void(*stub_callback_t)(const char *name, void *ret_ptr, const char *fmt, ...);
void shim_graphics_set_callback(stub_callback_t cb);
/* forward declarations */
void window_cb(const char *name, void *ret_ptr, const char *fmt, ...);
void *yourFunctionToRenderGraphics(const char *name, va_list args);
int main(int argc, char *argv[]) {
shim_graphics_set_callback(window_cb);
nhmain(argc, argv);
}
void *yourFunctionToRenderGraphics(const char *name, va_list args) {
printf("yourFunctionToRenderGraphics name %s\n", name);
/* DO SOMETHING HERE */
return NULL;
}
void window_cb(const char *name, void *ret_ptr, const char *fmt, ...) {
void *ret;
va_list args;
/* TODO -- see windowCallback below for hints */
va_start(args, fmt);
ret = yourFunctionToRenderGraphics(name, args);
// *((int *)ret_ptr = *((int *)ret); // e.g. yourFunctionToRenderGraphics returns an int
va_end(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 */

41
sys/lib/test/run.sh

@ -0,0 +1,41 @@
#!/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"
rm nhlibtest
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
cd sys/lib/npm-package && node test/test.js
fi
if [ x$1 == "xbin" ]; then
echo Doing bin...
make spotless
cd sys/unix
./setup.sh hints/macOS.2020
cd ../..
make
fi

8
sys/unix/Makefile.src

@ -300,6 +300,12 @@ WINGNOMEOBJ =
WINGEMSRC =
WINGEMOBJ =
# Files for Shim windowing interface for libnethack -- doesn't do anything,
# just passes along the API calls to the library
#
WINSHIMSRC = ../win/shim/winshim.c
WINSHIMOBJ = winshim.o
#
# Files for a BeOS InterfaceKit port -- not ready for prime time
WINBESRC =
@ -524,7 +530,7 @@ SYSCXXSRC = ../sys/share/cppregex.cpp
GENCSRC = vis_tab.c #tile.c
# all windowing-system-dependent .c (for dependencies and such)
WINCSRC = $(WINTTYSRC) $(WINCURSESSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC)
WINCSRC = $(WINTTYSRC) $(WINCURSESSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC) $(WINSHIMSRC)
# all windowing-system-dependent .cpp (for dependencies and such)
WINCXXSRC = $(WINQTSRC) $(WINQT3SRC) $(WINBESRC)

2
sys/unix/Makefile.top

@ -318,7 +318,7 @@ clean:
# 'make spotless' returns the source tree to near-distribution condition.
# it removes .o files, executables, and compiled data files
spotless::
spotless:: clean
( cd src ; $(MAKE) spotless )
( cd util ; $(MAKE) spotless )
( cd dat ; $(MAKE) spotless )

50
sys/unix/hints/include/cross-post.2020

@ -18,9 +18,9 @@ $(TARGETPFX)vidvesa.o : ../sys/msdos/vidvesa.c ../sys/msdos/portio.h \
$(TARGETPFX)vidstub.o : ../sys/msdos/vidvesa.c ../sys/msdos/portio.h \
$(HACK_H)
$(TARGETPFX)tile.o : tile.c
$(GAMEBIN) : $(HOBJ)
$(GAMEBIN) : $(HOBJ) $(LUACROSSLIB)
$(TARGET_LINK) $(TARGET_LFLAGS) -o $(GAMEBIN) \
$(HOBJ) $(WINLIB) $(TARGET_LIBS) $(LUALIB)
$(HOBJ) $(WINLIB) $(TARGET_LIBS)
#
.PHONY: dospkg
dospkg: $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp
@ -81,9 +81,9 @@ $(TARGETPFX)monsters.iff: ../win/share/monsters.txt ../util/txt2iff
../util/txt2iff ../win/share/monsters.txt $@
$(TARGETPFX)other.iff: ../win/share/other.txt ../util/txt2iff
../util/txt2iff ../win/share/other.txt $@
$(GAMEBIN) : $(HOBJ)
$(GAMEBIN) : $(HOBJ) $(LUACROSSLIB)
$(TARGET_LINK) $(TARGET_LFLAGS) -o $(GAMEBIN) \
$(HOBJ) $(WINLIB) $(TARGET_LIBS) $(LUALIB)
$(HOBJ) $(WINLIB) $(TARGET_LIBS)
#
.PHONY: amigapkg
amigapkg: $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp
@ -119,6 +119,34 @@ amigapkg: $(GAMEBIN) $(TARGETPFX)recover.exe ../dat/nhtiles.bmp
@echo amiga package zip file $(TARGETPFX)NH370AMI.ZIP
endif # CROSS_TO_AMIGA
ifdef CROSS_TO_WASM
$(WASM_TARGET): $(HOBJ) $(LUACROSSLIB) Makefile $(WASM_DATA_DIR)
-rm $@
$(TARGET_CC) $(EMCC_LFLAGS) $(EMCC_CFLAGS) -o $@ \
$(HOBJ) $(TARGET_LIBS)
$(WASM_DATA_DIR):
-mkdir -p $(WASM_DATA_DIR)
touch $(WASM_DATA_DIR)/perm
touch $(WASM_DATA_DIR)/record
touch $(WASM_DATA_DIR)/logfile
touch $(WASM_DATA_DIR)/xlogfile
( cd ..; $(MAKE) dlb )
( cd ..; $(MAKE) dofiles-dlb )
cp ../sys/lib/sysconf $(WASM_DATA_DIR)/sysconf
#
.PHONY: wasmpkg
wasmpkg:
@echo "$(WASM_TARGET) done."
$(TARGETPFX)unixmain.o : ../sys/unix/unixmain.c $(HACK_H)
$(TARGETPFX)unixres.o : ../sys/unix/unixres.c $(HACK_H)
$(TARGETPFX)unixunix.o : ../sys/unix/unixunix.c $(HACK_H)
$(TARGETPFX)ioctl.o : ../sys/share/ioctl.c $(HACK_H)
$(TARGETPFX)unixtty.o : ../sys/share/unixtty.c $(HACK_H)
$(TARGETPFX)winshim.o : ../win/shim/winshim.c $(HACK_H)
endif # CROSS_TO_WASM
#
ifdef CROSS_SHARED
# shared file dependencies
$(TARGETPFX)pcmain.o : ../sys/share/pcmain.c $(HACK_H)
@ -141,12 +169,9 @@ $(LUACROSSLIB): $(LUALIBOBJS)
$(TARGET_AR) rcS $@ $(LUAOBJFILES2)
$(TARGET_AR) rcS $@ $(LUAOBJFILES3)
$(TARGET_AR) rcs $@ $(LUAOBJFILES4)
ifdef WANT_WIN_CURSES
$(TARGETPFX)pdclib.a : $(PDCLIBOBJS) $(PDCOBJS)
if [ -f $@ ]; then rm $@; fi;
$(TARGET_AR) rcs $@ $(PDCLIBOBJS) $(PDCOBJS)
endif
#
# $(TARGET_AR) rcs $@ $(LUALIBOBJS)
# Lua src
$(TARGETPFX)lapi.o : $(LUATOP)/src/lapi.c
$(TARGETPFX)lauxlib.o : $(LUATOP)/src/lauxlib.c
@ -184,6 +209,11 @@ $(TARGETPFX)lzio.o : $(LUATOP)/src/lzio.c
endif # BUILD_LUA
ifdef BUILD_PDCURSES
ifdef WANT_WIN_CURSES
$(TARGETPFX)pdclib.a : $(PDCLIBOBJS) $(PDCOBJS)
if [ -f $@ ]; then rm $@; fi;
$(TARGET_AR) rcs $@ $(PDCLIBOBJS) $(PDCOBJS)
endif
# PDCurses src
$(TARGETPFX)addch.o : $(PDCTOP)/pdcurses/addch.c
$(TARGETPFX)addchstr.o : $(PDCTOP)/pdcurses/addchstr.c

116
sys/unix/hints/include/cross-pre.2020

@ -24,6 +24,14 @@ override TARGETPFX = $(TARGETDIR)/
override TARGET_LIBS=
endif
ifdef CROSS_TO_WASM
BUILD_LUA=1
override TARGET = wasm
override TARGETDIR=../targets/$(TARGET)
override TARGETPFX = $(TARGETDIR)/
override TARGET_LIBS=
endif
ifdef BUILD_LUA
#===============-=================================================
# LUA library
@ -51,7 +59,7 @@ LUAOBJFILES4 = $(TARGETPFX)lstring.o $(TARGETPFX)lstrlib.o \
$(TARGETPFX)ltm.o $(TARGETPFX)lundump.o \
$(TARGETPFX)lutf8lib.o $(TARGETPFX)lvm.o $(TARGETPFX)lzio.o
LUALIBOBJS = $(LUAOBJFILES1) $(LUAOBJFILES2) $(LUAOBJFILES3) $(LUAOBJFILES4)
LUACROSSLIB = $(TARGETPFX)$(O)lua$(subst .,,$(LUA_VERSION)).a
LUACROSSLIB = $(TARGETPFX)lua$(subst .,,$(LUA_VERSION)).a
LUAINCL = -I$(LUASRCDIR)
BUILDMORE += $(LUACROSSLIB)
override TARGET_LIBS += $(LUACROSSLIB) -lm
@ -255,8 +263,8 @@ override WINLIB=
override LUALIB=
override GAMEBIN = $(TARGETPFX)nethack
override PACKAGE= amigapkg
PREGAME = mkdir -p ../targets/amiga
CLEANMORE += rm -r ../targets/amiga
PREGAME = mkdir -p $(TARGETDIR)
CLEANMORE += rm -r $(TARGETDIR)
# ../util/txt2iff
#
ifdef WANT_WIN_CURSES
@ -269,20 +277,98 @@ $(TARGETPFX)%.o : ../outdated/sys/amiga/%.c
$(TARGET_CC) $(TARGET_CFLAGS) -o$@ $<
endif # CROSS_TO_AMIGA
#=================================================================
ifdef CROSS_SHARED
ifdef WANT_WIN_CURSES
# rules for pdcurses dos-specific files
$(TARGETPFX)%.o : $(PDCTOP)/sdl1/%.c
$(TARGET_CC) $(PDCINCL) $(TARGET_CFLAGS) -o$@ $<
endif # WANT_WIN_CURSES
# Rule for LUA files
$(TARGETPFX)%.o : $(LUATOP)/src/%.c
$(TARGET_CC) $(TARGET_CFLAGS) $(LUA_FLAGS) -o$@ $<
ifdef CROSS_TO_WASM
#===============-=================================================
# WASM
# originally from https://github.com/NetHack/NetHack/pull/385
#===============-=================================================
#
WASM_DATA_DIR = $(TARGETPFX)wasm-data/
WASM_TARGET = $(TARGETPFX)nethack.js
EMCC_LFLAGS = -s SINGLE_FILE=1
EMCC_LFLAGS += -s WASM=1
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"]'
EMCC_LFLAGS += -s EXPORTED_RUNTIME_METHODS='["cwrap", "ccall", "addFunction", \
"removeFunction", "UTF8ToString", "getValue", "setValue"]'
EMCC_LFLAGS += -s ERROR_ON_UNDEFINED_SYMBOLS=0
EMCC_LFLAGS += --embed-file $(WASM_DATA_DIR)
# For a list of EMCC settings:
# https://github.com/emscripten-core/emscripten/blob/master/src/settings.js
#
# WASM C flags
EMCC_CFLAGS=
EMCC_CFLAGS += -Wall
EMCC_CFLAGS += -Werror
#EMCC_CFLAGS += -s DISABLE_EXCEPTION_CATCHING=0
EMCC_DEBUG_CFLAGS += -s ASSERTIONS=1
#EMCC_DEBUG_CFLAGS += -s ASSERTIONS=2
EMCC_DEBUG_CFLAGS += -s STACK_OVERFLOW_CHECK=2
EMCC_DEBUG_CFLAGS += -s SAFE_HEAP=1
EMCC_DEBUG_CFLAGS += -s LLD_REPORT_UNDEFINED=1
#EMCC_DEBUG_CFLAGS += -s EXCEPTION_DEBUG=1
#EMCC_DEBUG_CFLAGS += -fsanitize=undefined -fsanitize=address -fsanitize=leak
#EMCC_DEBUG_CFLAGS += -s EXIT_RUNTIME
EMCC_PROD_CFLAGS += -O3
ifdef WASM_DEBUG
EMCC_CFLAGS += $(EMCC_DEBUG_CFLAGS)
else
EMCC_CFLAGS += $(EMCC_PROD_CFLAGS)
endif
#
# Override the build tools and some obj files to
# reflect emscripten
override TARGET_CC = emcc
override TARGET_CXX = emcc
override TARGET_AR = emar
override TARGET_CFLAGS = $(EMCC_CFLAGS) -c \
-I../include \
$(LUAINCL) -DDLB $(PDCURSESDEF) \
-DNOTTYGRAPHICS -DSHIM_GRAPHICS -DDEFAULT_WINDOW_SYS=\"shim\" \
-DCROSSCOMPILE -DCROSSCOMPILE_TARGET -DCROSS_TO_WASM -DLIBNH
override TARGET_CXXFLAGS = $(TARGET_CFLAGS)
override TARGET_LINK = $(TARGET_CC)
override TARGET_LFLAGS= $(EMCC_LFLAGS)
override SYSSRC = ../sys/unix/unixmain.c \
../sys/share/ioctl.c ../sys/share/unixtty.c \
../sys/unix/unixunix.c ../sys/unix/unixres.c \
../win/shim/winshim.c
override SYSOBJ= $(TARGETPFX)unixmain.o \
$(TARGETPFX)ioctl.o $(TARGETPFX)unixtty.o \
$(TARGETPFX)unixunix.o $(TARGETPFX)unixres.o \
$(TARGETPFX)winshim.o
override WINLIB = emranlib
override LUALIB=
override PACKAGE= wasmpkg
override REGEXOBJ = $(TARGETPFX)posixregex.o
RANLIB=$(EMRANLIB)
#VARDATND += nhtiles.bmp
override GAME=
MOREALL += ( cd src ; $(MAKE) pregame ; $(MAKE) $(WASM_TARGET) )
PREGAME = mkdir -p $(TARGETDIR)
CLEANMORE += rm -f -r $(TARGETDIR)
# Rule for file in sys/unix
$(TARGETPFX)%.o : ../sys/unix/%.c
$(TARGET_CC) $(TARGET_CFLAGS) -c -o$@ $<
# Rule for files in win/shim
$(TARGETPFX)%.o : ../win/shim/%.c
$(TARGET_CC) $(TARGET_CFLAGS) -c -o$@ $<
endif # CROSS_TO_WASM
#=================================================================
ifdef WANT_WIN_CURSES
ifdef BUILD_PDCURSES
# Rules for PDCurses files
$(TARGETPFX)%.o : $(PDCTOP)/pdcurses/%.c
$(TARGET_CC) $(PDCINCL) $(TARGET_CFLAGS) -o$@ $<
endif # BUILD_PDCURSES
endif # WANT_WIN_CURSES
ifdef CROSS_SHARED
# Rules for win/share files
$(TARGETPFX)%.o : ../win/share/%.c
$(TARGET_CC) $(TARGET_CFLAGS) -o$@ $<
@ -290,6 +376,12 @@ $(TARGETPFX)%.o : ../win/share/%.c
$(TARGETPFX)%.o : ../util/%.c
$(TARGET_CC) $(TARGET_CFLAGS) -o$@ $<
endif # CROSS_SHARED
ifdef BUILD_LUA
# Rule for LUA files
$(TARGETPFX)%.o : $(LUATOP)/src/%.c
$(TARGET_CC) $(TARGET_CFLAGS) $(LUA_FLAGS) -o$@ $<
endif # BUILD_LUA
#
# End of cross-compiling -PRE section
#===============-=================================================

4
sys/unix/hints/include/multiw-2.2020

@ -47,6 +47,10 @@ endif
endif
endif
ifdef WANT_LIBNH
WANT_DEFAULT=shim
endif
# Make sure that a default interface is specified; this doesn't guarantee
# sanity for something like 'make WANT_WIN_CURSES=1 WANT_DEFAULT=X11' but
# 'makedefs -v' would notice, complain, and quit causing 'make' to quit.

10
sys/unix/hints/linux.2020

@ -164,6 +164,16 @@ WINOBJ = $(sort $(WINOBJ0))
# prevent duplicates in VARDATND if both X11 and Qt are being supported
VARDATND += $(sort $(VARDATND0))
ifdef WANT_LIBNH
CFLAGS += -DSHIM_GRAPHICS -DNOTTYGRAPHICS -DNOSHELL -DLIBNH
WINOBJ = winshim.o
MOREALL += ( cd src ; $(MAKE) pregame ; $(MAKE) libnethack.a )
libnethack.a: $(HOBJ) $(SYSOBJ) $(WINOBJ) ../lib/lua/liblua.a
$(AR) rcs $@ $(HOBJ) $(WINOBJ) ../lib/lua/liblua.a
@echo "$@ built."
winshim.o : ../win/shim/winshim.c $(HACK_H)
$(CC) $(CFLAGS) -c -o$@ $<
endif # BUILD_LIBNH
#PREFIX=/usr
PREFIX=$(wildcard ~)/nh/install

13
sys/unix/hints/macOS.2020

@ -62,6 +62,7 @@ endif
CFLAGS=$(CCFLAGS) -I../include -DNOTPARMDECL
ifndef WANT_WIN_QT
ifndef WANT_LIBNH
# these are normally used when compiling nethack's core
CFLAGS+=-ansi -pedantic -Wno-long-long
# but -ansi forces -std=c90 for C or -std=c++98 for C++;
@ -70,6 +71,8 @@ CFLAGS+=-ansi -pedantic -Wno-long-long
#.../qt5/include/QtCore/qcompilerdetection.h:561:6:
# error Qt requires a C++11 compiler and yours does not seem to be that.
# so we suppress -ansi when the build includes Qt
#LIBNH's winshim requires C99 for the way it is currently coded
endif
endif
# As of LLVM build 2336.1.00, this gives dozens of spurious messages, so
# leave it out by default.
@ -168,6 +171,16 @@ WINOBJ = $(sort $(WINOBJ0))
# prevent duplicates in VARDATND if both X11 and Qt are being supported
VARDATND += $(sort $(VARDATND0))
ifdef WANT_LIBNH
CFLAGS += -DSHIM_GRAPHICS -DNOTTYGRAPHICS -DNOSHELL -DLIBNH
WINOBJ = winshim.o
MOREALL += ( cd src ; $(MAKE) pregame ; $(MAKE) libnethack.a )
libnethack.a: $(HOBJ) $(SYSOBJ) $(WINOBJ) ../lib/lua/liblua.a
$(AR) rcs $@ $(HOBJ) $(WINOBJ) ../lib/lua/liblua.a
@echo "$@ built."
winshim.o : ../win/shim/winshim.c $(HACK_H)
$(CC) $(CFLAGS) -c -o$@ $<
endif # BUILD_LIBNH
WANT_BUNDLE=1
ifdef WANT_SHARE_INSTALL

12
sys/unix/unixmain.c

@ -45,7 +45,17 @@ static void NDECL(wd_message);
static boolean wiz_error_flag = FALSE;
static struct passwd *NDECL(get_unix_pw);
int
#if defined(CROSSCOMPILE_TARGET) && defined(CROSS_TO_WASM)
/* for cross-compiling to WebAssembly (WASM) */
#include <emscripten/emscripten.h>
/* if WebAssembly, export this API and don't optimize it out */
#define KEEP EMSCRIPTEN_KEEPALIVE
#else
#define KEEP
#endif
int KEEP
main(argc, argv)
int argc;
char *argv[];

8
util/makedefs.c

@ -1267,10 +1267,18 @@ do_date()
#endif
Fprintf(ofp, "#define VERSION_SANITY1 0x%08lx%s\n", version.entity_count,
ul_sfx);
#ifndef __EMSCRIPTEN__
Fprintf(ofp, "#define VERSION_SANITY2 0x%08lx%s\n", version.struct_sizes1,
ul_sfx);
Fprintf(ofp, "#define VERSION_SANITY3 0x%08lx%s\n", version.struct_sizes2,
ul_sfx);
#else /* __EMSCRIPTEN__ */
Fprintf(ofp, "#define VERSION_SANITY2 0x%08llx%s\n", version.struct_sizes1,
ul_sfx);
Fprintf(ofp, "#define VERSION_SANITY3 0x%08llx%s\n", version.struct_sizes2,
ul_sfx);
#endif /* !__EMSCRIPTEN__ */
Fprintf(ofp, "\n");
Fprintf(ofp, "#define VERSION_STRING \"%s\"\n", version_string(buf, "."));
Fprintf(ofp, "#define VERSION_ID \\\n \"%s\"\n",

331
win/shim/winshim.c

@ -5,14 +5,98 @@
/* not an actual windowing port, but a fake win port for libnethack */
#include "hack.h"
#include <string.h>
#ifdef SHIM_GRAPHICS
#include <stdarg.h>
/* for cross-compiling to WebAssembly (WASM) */
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
#undef SHIM_DEBUG