External windowing interfaces

+--------------+                          +------------+
|              |                          |            |
|              | wfd                    0 | Windowing  |
|  Game core   |------------------------->| interface  | 2
|              | rfd                    1 |            |----> stderr
|  setuid/gid  |<-------------------------| No special |
|              |                          | privileges |
|              |  Double, unnammed pipes  |            |
+--------------+                          +------------+

Overview

The game core would be fully sychronous (as it is now). There would be one function which would deal with reading and writing to the external windowing interface.

As far as the game core is concerned we have just added a new windowing interface, called "ext" (for lack of anything better).

Initialisation

A new window_proc function is defined, call it choose. Existing windowing interfaces set this to NULL.

choose_windows() is modified so that in addition to its current behaviour it will also call any choose functions that are non-NULL and pass in the name of the window type requested. choose functions can indicate that they support this window type by returning ok.

The choose function of the ext interface, ext_choose(), checks that an executable of the right name exists and runs it after dropping privileges and creating the unnammed pipes.

If all goes well, windowprocs is set to point at ext, if not ext_choice() fails and choose_windows() gives the normal error message.

Glue functions

The ext interface has a completely standard window_procs structure and a set of glue functions to populate it with.

The glue functions pack the function ID and the parameters up into a linear memory buffer and call ext_main_loop() to pass the function data to the external interface and return the result.

Main loop

ext_main_loop() writes the packet to wfd and blocks reading rfd.

When it reads a correctly formed packet, ext_main_loop() checks the ID:

Notes

All communication between the game core and the windowing interface would be in platform independant format to allow for the possibility of the windowing interface being written in a different language. It would be possible to base a binary platform independant format on the (unfinished) NHXDR format, see nhbasic.c for details.

IDs would be unsigned shorts (ie., at least 16 bits). Half of these would be reseved for standard functions and half for interface defined functions.

Standard windowing interface functions include the functions in window_procs.

Standard core functions might include a function to read a file (including dlb files), functions to end the game, functions to set and get player options, display_inventory(), doredraw(), cmap_to_glyph(), glyph2tile, back_to_glyph() etc. A full list of the core symbols (functions and variables) referenced by the UNIX windowing interfaces in Slash'EM is available here.

Extensibility

In theory, a windowing interface might be able to be written without any support inside the game core code, but most interfaces would also have support in the core code, as they do now.

There are two main means of allowing such extensions:

  1. The core code can call an extended windowing interface function in exactly the same way as it can currently call a non-standard windowing interface function (no vanilla NetHack windowing interfaces do this, but the GTK interface uses GTK_init_nhwindows2() for example).
  2. The windowing interface can call a core function not handled by ext_main_loop() by defining it as an interface specific function. ext_main_loop() will call an interface defined function to deal with such IDs.

J. Ali Harlow, ali@juiblex.co.uk