Update the Amiga Intuition window port (AMII/AMIV) for the 3.7
window_procs API. Key changes:
- Update all window function signatures for 3.7
- Add assembly trampolines for AmigaOS register-based callbacks
- Convert all K&R function definitions to C99
- Add cross-compilation build system (cross-pre1/pre2/post.370)
using bebbo's m68k-amigaos-gcc with -noixemul -std=gnu17 -m68000
- Clipping fixes: viewport centering, simplified ScrollRaster,
duplicate Ctrl-R suppression, glyph buffer invalidation
- Add menucolor support in menu rendering
- Move native txt2iff.c and xpm2iff.c to outdated/
- Add nethack.cnf and README.amiga
This is the second of a series of changes related to save/restore.
No EDITLEVEL bump has been included, because although the code
is changed extensively by this, the content of the savefiles have
not been changed.
Push the use of the structlevel bwrite() and mread() function use
out of the core and into sfstruct.c. This is groundwork for upcoming
changes.
In the core, replace the bwrite() and mread() calls with the
use of type-specific savefile output (Sfo) and savefile
input (Sfi) macros. The macros are defined in a new header file
savefile.h, which also contains the prototypes for the sfo_* and
sfi_* functions that the macros ultimately expand to. The functions
themselves are in src/sfbase.c.
On C99, each Sfo or Sfi macro expansion refers directly to the
corresponding type-specific sfo_* or sfi_* function.
If C23 or later is is use, the majority (all but 3 types) of the
macros refer to a single _Generic output routine sfo(nhfp, dt, tag),
and a single _Generic input routine sfi(nhfp, dt, tag), which handles
the dispatch of the type-specific underlying functions. This was
somewhat experimental, but turned out to be practical because the
compiler would gripe if the type for a variable was not included in
the _Generic when passed as an argument, so it could be fixed.
This alters the savefile verication process by having a common set
return values for the related functions such as uptodate(),
check_version(), etc. The new return values return more information
about savefile incompatibilities, beyond failure/sucess. The
additional information will be useful for an upcoming addition.
The expanded return values are:
SF_UPTODATE (0) everything matched and looks good
SF_OUTDATED (1) savefile is outdated
SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch
SF_DM_IL32LLP64_ON_ILP32LL64 (3) Windows x64 savefile on x86
SF_DM_I32LP64_ON_ILP32LL64 (4) Unix 64 savefile on x86
SF_DM_ILP32LL64_ON_I32LP64 (5) x86 savefile on Unix 64
SF_DM_ILP32LL64_ON_IL32LLP64 (6) x86 savefile on Windows x64
SF_DM_I32LP64_ON_IL32LLP64 (7) Unix 64 savefile on Windows x64
SF_DM_IL32LLP64_ON_I32LP64 (8) Windows x64 savefile on Unix 64
SF_DM_MISMATCH (9) some other mismatch
The callers in the core have been adjusted to deal with the expanded
return values.
Other miscellaneous inclusions:
- go.oracle_loc -> svo.oracle_loc.
- add a bit (1UL << 30) to called SFCTOOL_BIT as groundwork
for changes to follow.
This is the first of several savefile-related changes to
follow later. This one is groundwork for those later changes.
Remove internal compression schemes (RLECOMP and ZEROCOMP)
and discard the savefile_info struct that was primarily used to
convey which internal compression schemes had been in use.
Relocate some struct definitions into appropriate header files
for use by code to come in later changes.
Remove the two struct size-related fields from version_info and
from the nmakedefs_s. Instead, include a series of bytes near the
beginning of the savefile, representing the size of each
struct or base data type that impacts the historical savefile
content. Those are referred to as the "critical bytes".
(Related note: the "you" struct required two bytes, low and high,
due to its size).
Compare those critical bytes in a savefile against the NetHack
build that is reading the savefile. This allows mismatch detection
early in the savefile-reading process, and a clean exit, rather than
proceeding to read nonsensical values from the file. Include some
feedback on what the first mismatch was when encountering
one.
For arrays stored in the savefile, use loop-logic in the core
to write/read the array elements one at a time, rather than in
a single blob. This will be required for changes to follow later.
(impacts artiexist[], artidisco[], svd.dungeons[], svl.level_info[],
svl.level.locations[][], msrooms[] field of mapseen, svb.bases[],
svb.disco[] objects[], svm.mvitals[], svs.spl_book[], svd.doors[],
go.oracle_loc[], utrack[], wgrowtime[])
This also adds data model to the long version information.
This invalidates existing save and bones files due to the changes in
the information at the start of the file.
Add a note about NO_TERMS to include/wintty.h for clarity.
Rename tty_startup and tty_shutdown to term_startup() and
term_shutdown(). They are found in termcap.c for !NO_TERMS
like most of the other term_ routines, as well as having
versions for several of the NO_TERMS platforms. They aren't
part of the tty_interface called from the core. The tty
implementation does call and rely on them.
Remove some conditional #ifdef's around term_shutdown()
(formerly tty_shutdown()) and just ensure that all the
tty platforms have an implementation that they can link
with, even if it is just a stub presently.
Put the protype for nethack_exit in extern.h to reduce
maintenance to a single spot, and remove it from other
locations. A warning in the msdos cross-compile led to
this change.
There was a transcription error in the comments in cstd.h for
the standard list of header files, where only the description
remained for <stdlib.h>, not the name of the file itself.
Remove several extraneous inclusions of the standard C99 headers.
Tested on the following afterwards:
Linux (using hints/linux.370) including tty, curses, qt6, and X11
macOS (using hints/macOS.370) including tty, curses, qt5, and X11
Windows MSYS2 using sys/windows/GNUmakefile
Windows Visual Studio using sys/windows/Makefile.nmake
msdos cross-compile on Ubuntu using djgpp cross-compiler
The g? structs had a mix of variables that were written to
the savefile, and those that were not.
For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.
This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.
Details:
gb.bases -> svb.bases
gb.bbubbles -> svb.bbubbles
gb.branches -> svb.branches
gc.context -> svc.context
gd.disco -> svd.disco
gd.dndest -> svd.dndest
gd.doors -> svd.doors
gd.doors_alloc -> svd.doors_alloc
gd.dungeon_topology -> svd.dungeon_topology
gd.dungeons -> svd.dungeons
ge.exclusion_zones -> sve.exclusion_zones
gh.hackpid -> svh.hackpid
gi.inv_pos -> svi.inv_pos
gk.killer -> svk.killer
gl.lastseentyp -> svl.lastseentyp
gl.level -> svl.level
gl.level_info -> svl.level_info
gm.mapseenchn -> svm.mapseenchn
gm.moves -> svm.moves
gm.mvitals -> svm.mvitals
gn.n_dgns -> svn.n_dgns
gn.n_regions -> svn.n_regions
gn.nroom -> svn.nroom
go.oracle_cnt -> svo.oracle_cnt
gp.pl_character -> svp.pl_character
gp.pl_fruit -> svp.pl_fruit
gp.plname -> svp.plname
gp.program_state -> svp.program_state
gq.quest_status -> svq.quest_status
gr.rooms -> svr.rooms
gs.sp_levchn -> svs.sp_levchn
gs.spl_book -> svs.spl_book
gt.timer_id -> svt.timer_id
gt.tune -> svt.tune
gu.updest -> svu.updest
gx.xmax -> svx.xmax
gx.xmin -> svx.xmin
gy.ymax -> svy.ymax
gy.ymin -> svy.ymin
Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
gf.ftrap, gl.light_base, gt.timer_base
The sysconf EXPLORERS list restricting access to explore mode was being
evaluated and used when a player used the #exploremode command in-game,
or when specifying -X or OPTIONS=playmode:explore on the command line
when resuming a normal game, but not when starting an entirely new game.
When SYSCF is avilable, check for authorization early, similar to debug
mode authorization, to restrict access to explore mode to EXPLORERS
under (hopefully) all circumstances.
When calling panic() or impossible(), create the option
of opening a browser window with most of the fields
already populated. Code for MacOS and linux is included;
other ports are affected by argument change to early_init
which are done but not tested.
To enable, define CRASHREPORT in config.h and set
CRASHREPORTURL in sysconf to (for the moment at least)
http[s]://www.nethack.org/common/contactcr.html
Adds --grep-defined option to makedefs for Makefiles.
Adds "bid" (binary identifier), an MD4 of the main nethack
binary. This is ONLY for helping (in the future) contact.html
to set the "NetHack from" field automatically for our own
binaries. This can be faked, but the user can lie so nothing
lost. There's nothing magic about MD4; other ports can use
anything that prodcues a long apparently random string we can
match against.
- new option --bidshow for us to get the MD4 of a
released binary so I can add it to the website.
Only available in wizard mode and not in nethack.6.
- typo macos -> macosx in hints file
No support for packaging builds as I'm not sure what that
would look like.
Adds a javascript helper for MacOS.
Adds a lua helper for linux (and builds and installs
nhlua).
rename display_gamewindows() to init_sound_and_display_gamewindows()
(I know that's getting pretty long-named).
move activate_chosen_soundlib() into init_sound_and_display_gamewindows()
from moveloop_preamble().
Also included was a missing break in a switch related to sounds.
A number of C compiler suites have a math.h library that includes a yn()
function name that conflicts with NetHack's yn() macro:
"The y0(), y1(), and yn() functions are Bessel functions of the second kind,
for orders 0, 1, and n, respectively. The argument x must be positive. The
argument n should be greater than or equal to zero. If n is less than zero,
there will be a negative exponent in the result."
At one point, isaac64.h included math.h, although that has since been removed.
Some libraries used in NetHack (Qt for one) do include math.h and that required
build work-arounds to avoid the conflict.
Rename the NetHack macro from yn() to y_n() and avoid the math.h conflict
altogether, eliminating the need for that particular work-around.
A recent commit to alloc.c by Keni drew attention to the fact that
there are extern prototypes scattered around in various .c files.
Those can make use of ATTRNORETURN (non-gcc compilers and C23) the
same way the prototypes in extern.h can, and they were overlooked
when ATTRNORETURN was first added.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.
If you want to try building on a platform that doesn't offer those
two functions, these are available:
define NOT_C99 /* to make some non-C99 code available */
define NEED_INDEX /* to define a macro for index() */
define NEED_RINDX /* to define a macro for rindex() */
A new feature, enabled by default to maximize testing, but one which can
be disabled by commenting it out in config.h
With this, some additional information is added to the glyphmap entries
in a new optional substructure called u with these fields:
ucolor RGB color for use with truecolor terminals/platforms.
A ucolor value of zero means "not set." The actual
rgb value of 0 has the 0x1000000 bit set.
u256coloridx 256 color index value for use with 256 color
terminals, the closest color match to ucolor.
utf8str Custom representation via utf-8 string (can be null).
There is a new symset included in the symbols file, called enhanced1.
Some initial code has been added to parse individual
OPTIONS=glyph:glyphid/R-G-B entries in the config file.
The glyphid can, in theory, either be an individual glyph (G_* glyphid)
for a single glyph, or it can be an existing symbol S_ value
(monster, object, or cmap symbol) to store the custom representation for
all the glyphs that match that symbol.
Examples:
OPTIONS=glyph:G_fountain/U+03A8/0-150-255
(Your platform/terminal font needs to be able to include/display the
character, of course.)
The NetHack core code does parsing and storing the customized
entries, and adding them to the glyphmap data structure.
Any window port can utilize the additional information in the glyphinfo
that is passed to them, once code is added to do so.
Also, consolidate some symbol-related code into symbols.c, and remove it from
files.c and options.c
Disclaimer: This is a minimal recipe, just to get someone else
started if they have a desire to get a full cross-compile of
NetHack-3.7 going for the Amiga. Some NetHack code bitrot was
corrected, and it does seem able to compile the game itself
to a point. See caveats below.
- If you want to obtain the cross-compiler and tools/libs for Amiga
https://github.com/bebbo/amiga-gcc
To our knowledge, a pre-built copy isn't available, so you have to
obtain the source via git and build it on your system.
The build prerequisite packages for Ubuntu are easily obtained:
sudo apt install make wget git gcc g++ lhasa libgmp-dev \
libmpfr-dev libmpc-dev flex bison gettext texinfo ncurses-dev \
autoconf rsync
The build prerequisite packages for macOS are apparently easily
obtained via homebrew, but that was not tested:
brew install bash wget make lhasa gmp mpfr libmpc flex gettext \
texinfo gcc make autoconf
After installing the prerequite packages and the cross-compiler
it was a straightforward build:
git clone https://github.com/bebbo/amiga-gcc.git
cd amiga-gcc
make update
[Note that you may have to take ownership of the files in the
bebbo repo via chown before succesfully carrying out the next
steps]
make clean
make clean-prefix
date; make all -j3 >&b.log; date
The compiler pieces are installed in /opt/amiga by default which
was satisfactory for our initial attempt, but if you want you can
alter the prefix before you build if you want. That is all
spelled out on the page at: https://github.com/bebbo/amiga-gcc
The Amiga cross-compile can then be carried out by specifying
CROSS_TO_AMIGA=1 on the make command line.
For example:
make CROSS_TO_AMIGA=1 all
make CROSS_TO_AMIGA=1 package
You can explicitly include tty and curses support if desired, otherwise
you'll end up with a tty-only cross-compile build. The SDL1 pdcurses
support has not been tested.
make WANT_WIN_TTY=1 WANT_WIN_CURSES=1 CROSS_TO_AMIGA=1 all
Also note that building the amiga targets using the make command
above, does not preclude you from building local linux or macOS
targets as well. Just drop the CROSS_TO_AMIGA=1 from the make
command line.
The cross-compiler hints additions are enclosed inside ifdef sections
and won't interfere with the non-cross-compile build in that case.
CAVEATS: The original NetHack Amiga build steps included the source for
some utilities that were built and executed on the amiga: txt2iff and
xpm2iff as part of the NetHack build procedure on amiga. Those did not
compile out-of-the-box on the linux host. They will either have to be:
- ported to build and run on the linux or macOS cross-compile host
or
- their functionality will have to be rolled into amiga NetHack
itself and executed on the target Amiga the first time the game
is run, perhaps.
Good luck amiga aficionados, perhaps you'll be able to take this
initial effort forward and get NetHack-3.7 available on the amiga or
amiga-emulator. Let us know if you do, and we can roll changes in
if you provide them.
A check into github issue 364 confirmed that
ba6edbe5dc
had incorrectly updated the bwrite sizeof entry for sysflags.
The SYSFLAGS and MFLOPPY code is all in the outdated part of the tree, so just
remove it rather than re-correct it.
Closes#364Closes#207
Make some progress on a couple of next minor release checklist
items, hopefully without introducing too many new bugs. This
is just the initial commit, and work continues.
Checklist items:
Savefiles compatible between Windows versions, whether 64-bit
or 32-bit in little-endian field format.
Selection of file formats:
historical (structlevel saves),
lendian (little-endian, fieldlevel saves),
and just for proof-of-concept, ascii fieldlevel saves
(the ascii is huge! 10x bigger than little-endian).
For the fieldlevel save, all complex data structures recursively
get broken down until until it is one of the simple types that
can't be broken down any further, and that gets when it gets
written to the output file.
New files needed for this build:
hand-coded:
include/sfprocs.h
src/sfbase.c - really a dispatcher to one of the
output/input format routines.
src/sflendian.c - little-endian output writer/reader.
src/sfascii.c - ascii text output writer/reader.
auto-coded (generated):
include/sfproto.h
src/sfdata.c
This is just one approach. I'm sure there are countless others
and they have different pros and cons.
For producing the auto-coded files a utility called
universal-ctags, that is actively maintained and evolving,
was used to do all the heavy-lifting of parsing the
NetHack C sources to tabulate the data fields, and store
them in an intermediate file called util/nethack.tags
(not required for building NetHack if you already have a
generated include/sfproto.h and src/sfdata.c)
util/readtags (also not required for building NetHack
itself) will decipher the nethack.tags file and produce
the functions that can deal with the NetHack struct data
fields.
You can obtain the source for universal-ctags by cloning it
from here:
https://github.com/universal-ctags/ctags.git
The combination universal-ctags + util/readtags has been
tried and tested under both Windows and Linux, so it is
not tied to a particular platform.
Note: util/readtags will work only with universal-ctags
output, so other ctags are unlikely to work as-is.
Universal-ctags can be build from source very easily
under Linux, or under Windows using visual studio.
Changes to be committed:
modified: include/winprocs.h
modified: src/options.c
modified: sys/share/pcmain.c
new file: sys/share/safeproc.c
modified: sys/winnt/Makefile.msc
modified: sys/winnt/stubs.c
new file: sys/winnt/windmain.c
modified: sys/winnt/winnt.c
modified: win/win32/vs2017/NetHack.vcxproj
modified: win/win32/vs2017/NetHackW.vcxproj
modified: win/win32/winhack.c
Because multiple window ports are supported on Windows
now, even in the same executable and selectable via
config file in some cases, some adjustments became
necessary. There will likely be some further refining
of this over the next day or two.
List of changes:
Move Windows startup from sys/share/pcmain.c and
into its own sys/winnt/windmain.c so that it can
be modified to fix some current breakage, and
allow altering the order of some things.
There is startup processing code that is common to
all of the Windows WindowPorts, but that startup
processing code needs to have no dependency on
any one of those WindowPorts.
Yet, during startup processing, some of the initialization
routines can end up calling NetHack functions that
expect an active Window port underneath, and if there
isn't one, routines like pline, impossible, panic can
end up invoking null function pointers.
Place a new file sys/share/safeproc.c, in which a complete
window port is available for early startup processing
purposes. It's WindowPort name field is set to
"safe-startup" just for reference. The prototypes in
include/winprocs.h require that SAFEPROCS be
Usage:
windowprocs = get_safe_procs(0);
initializes a set of winprocs function pointers that ensure
none of the function pointers are left null, but that's all it does.
windowprocs = get_safe_procs(1);
initializes a set of winprocs functions pointers that ensure
none of the function pointers are left null, but also
provides some basic output and input functionality using nothing
other than C stdio routines (no platform or OS specific code).
The conditional code related to WIN32 has been removed from
sys/share/pcmain.c
The code common to all of the Windows WindowPorts calls
get_safe_procs() almost immediately to ensure that
there is a set of WindowPort winprocs available.
The Windows graphical version in NetHackW.exe is meant to lock
itself to its own windowtype and ignore the OPTIONS=windowtype
setting in the config file, but the code to perform the lock
only did so if (argc > 1).
Moved the code page 437 mapping table to winnt.c so that it could be
used in window and console clients.
Added check that fonts support unicode values we use from code page 437.
Use unicode to draw text if font supports it otherwise use ASCII.