Building from C sources

## Building A-code games from C sources #### (A-code version 12.85) ### Contents Derived C sources Building an executable from the C sources Console mode Browser mode Single turn mode JavaScript/HTML mode Library mode Appendix: Deprecated text data handling Appendix: Kernel compilation symbols ### Derived C sources A-code games are, naturally enough, written in A-code, which is an IF writing language originally created by David Platt when developing his Adv550 superset of the original Adventure. However, the first step of converting A-code source files into an executable involves translating them into ANSI C. This is done by the acdc A-code to C translator and the process is covered in a separate document. Here I assume that you already have the derived C sources either downloaded as a part of the overall A-code tarball or produced by running the acdc translator yourself. The translator ANSI C sources are also included in the same tarball. ### Building an executable from the C sources A-code games can be built in 5 distinct modes: console, browser, single turn, HTML/JavaScript and library. This document explains the differences between these modes, their respective uses and the ways of building corresponding game versions from C sources. If your system does not have the unistd.h header file, you should add -DNO_UNISTD to all compilation commands given below. An appendix lists and explains all compilation symbols that may be used in compiling A-code game C sources. ### The console mode The console mode is how the original Adventure was initially played. It takes input directly from the player and outputs any responses in plain text to a "computer terminal" – these days most likely a terminal emulator window. Some players still prefer this mode and it is also very handy for debugging. While it still defaults to the dimensions of displays of ancient VDUs (24 lines and 80 fixed font characters per line), other dimensions can be specified on the invocation command line by means of the -s option. The kernel also provides the necessary hooks for a game to permit changes to these defaults while playing. The console mode also offers a unique opportunity to experience an A-code game the way the original Adventure was played in 1970s/80s. The -o command line option allows the output speed to be set to the baud rate of 110 (a teletype), 300 (earliest VDUs), 600, 1200, 2400, 4800 and 9600. Younger players are hereby invited to marvel at the patience required to play at the lower speeds (as we did!). For the full list of console mode command line options, please see the document describing command line invocation of A-code games. If you have the readline and ncurses libraries installed and available for linking (which probably needs a readline development package), all you need to do is to use an ANSI C compiler to compile and link the C files, specifying the console mode: cc -DCONSOLE *.c -lreadline -lncurses -o <game-name> If you do not have those libraries installed, you can still build a console mode executable, which will lack the facility of recalling and editing previous commands. To do so, just tell the compiler not to use readline: cc *.c -DCONSOLE -DNO_READLINE -o <game-name> ### The browser mode In the browser mode, A-code games do not interact with the player directly, but instead invoke a local browser and use that to render game's output and to obtain player's commands. In this mode, an A-code game acts as a very simple HTTP server. Unless otherwise specified, the player's default browser is invoked, but another browser can be specified either on the invocation command line or by modifying the acode.config file created by the A-code kernel. The browser build of an A-code game automatically includes the console build (but not the other way around!). Thus a browser-build game can be invoked in the console mode by adding -C to the invocation command line. Building a browser mode executable is virtually the same as building a console mode one – you just drop the -DCONSOLE from the parameters given to the compiler. When a browser is being used to render game's output, there is no need for the readline library, so the basic browser mode build looks like this: cc *.c -DNO_READLINE -o <game-name> If you want the executable to offer command editing when run in the console mode, you will need to link in the two additional libraries: cc *.c -lreadline -lncurses -o <game-name> *.c ### The single turn mode Originally developed for CGI operation, games build in this mode are only suitable for running in a cloud, via a suitable front-end script, e.g. a cgi-bin or a PHP one. In this mode, the game executable is supplied a single command as a parameter on the invocation command line, sends the text generated in response to standard output and exits. (See the the command line options document for details.) The actual interaction with the player is carried out by the front end script, which repeatedly invokes the executable for successive game turns. The secret sauce is, of course, the player-invisible save and restore of the current state of the game. This mechanism got later adapted for use by other game modes, automatically giving all A-code games a persistent state. In this mode all text output is HTML-formatted, though this can be overridden if necessary. All such text is also prefixed by a single character, which provides information to the wrapper script and is not expected to be displayed to the player. To build a single turn mode executable is very simple: cc *.c -DTURN -o <game-name> In this mode the executable is not responsible for acquiring player commands and thus there is no need to signal the absence of the readline library -- this is assumed automatically. ### The HTML/JavaScript mode Thanks to the magic of emscripten, A-code games can be built as pure (and purely local, with no network dependencies) HTML/JavaScript page, usable by any HTML5 compliant browser. In this mode, A-code games run entirely within the player's browser and use browser's own sand-boxed file system for saving and restoring games. For building games in this mode you will need emscripten installed as well as its dependencies (clang and cmake). Actually building a game involves two steps. Firstly the derived C sources (plus the kernel ones) are converted to JavaScript via this one-line command: emcc -Os -s ASM_JS=1 -s WASM=0 -s ENVIRONMENT=web -DJS adv*.c -Wno-parentheses-equality -lidbfs.js -s "EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']" --memory-init-file 0 -o acode.js -s EXPORTED_FUNCTIONS="['_advturn']" (That's the command line for Emscripten 1.39.6 -- experience suggests that later versions may require a change in some of the arguments.) Secondly, the resulting acode.js file has to be merged into the acode.html template, which can be found in the tools directory to be found in the relevant A-code tarballs. This merging is achieved by (a) replacing all occurrences of the string %NAME% in the template by the name of the game being builds and (b) replacing the line consisting of the single token %JAVASCRIPT% with the contents of the JavaScript file generated by emcc. The resulting HTML file can be called anything you like, but it seems a good idea to replace 'acode' in its name with the actual name of the game. ### The library mode In some cases it is not feasible or appropriate for an A-code game to drive its own commend/response loop. App frameworks generally expect to do so themselves. This situation is handled by compiling derived C sources in the library mode: cc -c *.c -DADVLIB Compiled this way, instead of having a main() routine, the game has an advturn() one, which expects player input to be supplied via its arguments and returns a pointer to a text buffer containing the resulting text. As in the single turn mode, the returned text is prefixed with a single character denoting the nature of the text. A separate document explains the details of the advturn() interface. However, for testing/debugging purposes I had to develop a simple C program, which uses the library mode and can be run in any terminal emulator. It's source, libtest.c can be found in the tools directory of an A-code tarball. ### Appendix 1: Deprecated text data handling By default, since version 12.01 of A-code, all text data is preloaded by the acdc translator into the game C-source, whereas previous versions by default stored text data in a separate .dat file. The current arrangement is the simplest and most sensible one for most machines these days, but a few years ago I still saw some not entirely obsolete machines baulking at the size of adv770 executable with preloaded data. Hence other options are also on offer, even if you don't have access to game A-code sources. Creating the text data file Even though game C sources no longer come with the .dat text data file, this file can get automatically constructed by the game executable. To do this, first build the executable in one of the three ways described below (for preloading, paging or reading of the data file), and then run the resulting executable in the directory containing the C sources. Failing to find the .dat file, but finding adv6.h instead, the game will construct the .dat file from the .h one. From then on the game will run normally, getting its text data from the .dat file, which should be kept in the same place as the executable (but see the separate document on game invocation command options for an alternative). Loading text data on game startup If -DMEMORY is added to any of the C compilation commands suggested above, the text data file will be preloaded into a dynamically allocated buffer on game startup. This used to be the default arrangement in A-code versions 10 and 11. Reading data from the text file If your memory is constrained, but disk I/O is reasonably quick (which it would be unless you are running the game from a floppy disk), you can use the -DFILE compilation flag. This causes the game to read from the data file with no paging of its own, though one hopes that *some* paging will be done by the OS. As a guess, such machines will have no GUI browsers, so -DCONSOLE should also be added to compilation flags. Keeping recent text data in memory If -DSWAP is added to any of the C compilation commands suggested above, all access to the text data file will be through an internal paging system of 32 1KB buffers, paging data in and out on the first-in-first-out basis. The number of swap buffers can be modified by defining the SWAP symbol to have a particular value, e.g. -DSWAP=40. The number of buffers will be coerced into the range from 16 to 128 inclusive. This method is only useful for the oldest and slowest machines. Again, it probably makes sense to add -DCONSOLE as well, since a machine with such a limited amount of memory is unlikely to sport a GUI-based browser. ### Appendix 2: Kernel compilation symbols Compilation symbols listed below can be added to the compilation command line as -D<symbol> when building A-code games. There is a number of other symbols being defined and used by kernel source files, which you should leave well alone. The main mode symbols have been already referenced above. CONSOLE Specifies console-only mode CGI Specifies single turn mode HTTP Specifies combined browser/console mode – this is the default JS Specifies JavaScript/HTML mode ADVLIB Specifies library mode Four additional symbols can be used to control what system routines the game executable needs from the system. NO_UNISTD Signals absence of the unistd.h header file. Use it in all modes if you do not have the unistd library. NO_READLINE Suppresses use of the readline library (only relevant in the console and browser/console modes – ignored otherwise). NO_SLOW Suppresses the ability to slow down game's output (only relevant in the console and browser/console modes – ignored otherwise). PAUSE Prevents immediate exit on game completion (useful when running in console mode in a window which automatically closes on game's exit). Three further symbols which are only required in kernel development work and/or in special builds. IOS Signals iOS build. DEBUG Enables various debug messages from the kernel. DIRECT Prevents the HTTP server being daemonised in the browser mode – makes debugging easier! Finally, there are the deprecated symbols specifying ways of dealing with a separate text data file, if there is one. Note that these symbols override whatever text data arrangement was specified in running acdc to convert A-code sources into C. MEMORY Text data file to be loaded into memory on startup. FILE Text to be retrieved as required directly from the data file. SWAP[=<page_buffers>] Text is to be paged in executables 1KB page buffers. The default is 32 such buffers, but another number can be specified between 16 and 128 inclusive.