1
====================================================================
2
AGILITY: THE (MOSTLY) UNIVERSAL AGT INTERPRETER Version 1.1.1
3
MAGX: MAKE AGX, AGT-COMPATIBLE COMPILER Version 0.6.5 (beta)
4
====================================================================
6
This file contains notes on compiling and porting AGiliTy and Magx. See
7
'readme.agility' or 'readme.magx' for an introduction to the program.
8
The two programs are separate packages, but they have a fairly large
9
base of common code, so I've decided to merge their porting notes.
11
This software may be freely redistributed under the terms of the GNU
12
General Public License, version 2. Since this is free software, there
13
is NO WARRANTY of any kind.
15
The author, Robert Masenten, can be reached at
17
Please tell me if you find any bugs or have any problems porting it
24
This document has the following sections:
26
1.0 LIST OF MAJOR CHANGES...
27
1.1 ...TO AGILITY SINCE VERSION 0.8.4
28
1.2 ...TO MAGX SINCE VERSION 0.4
30
2.1 COMMON SOURCE FILES
31
2.2 AGILITY-SPECIFIC SOURCE FILES
32
2.3 MAGX-SPECIFIC SOURCE FILES
36
4.0 PORTING NOTES FOR BOTH SYSTEMS
37
4.1 CONFIG.H: PLATFORM SPECIFIC #DEFINES
38
4.2 VARIABLES AND FUNCTIONS DEFINED BY THE INTERPRETER
39
4.3 FILENAME.C: OVERVIEW
40
4.4 FILENAME.C: DATA TYPES
41
4.5 FILENAME.C: FUNCTIONS
42
5.0 FURTHER NOTES ON PORTING AGILITY
43
5.1 OS_*.C: THE PLATFORM-SPECIFIC INTERFACE
44
5.2 VARIABLES AND FUNCTIONS DEFINED BY THE INTERPRETER
45
5.3 OTHER FUNCTIONS THAT CAN OPTIONALLY BE SPECIFIED
46
5.4 GRAPHICS, FONT, AND SOUND FUNCTIONS
50
-------------------------------
51
1.0 LIST OF MAJOR CHANGES...
52
-------------------------------
54
Theses are lists of the changes most likely to be relevant to
55
porters; all of the changes are more extensivly documented in the body
56
of this file and in the file 'changes.txt'.
59
----------------------------------------
60
1.1 ...TO AGILITY SINCE VERSION 0.8.4
61
----------------------------------------
62
--os_linux.c has been renamed os_termcap.c; os_curses.c has become
63
the main Linux display module.
64
--replay_fast flag has been added; this should be checked by
65
agt_delay() and agt_newline().
66
--Filename handling has been completely overhauled. All file I/O now
67
goes through the new file "filename.c". This has the following effects
69
1) filename.c needs to be compiled and linked with everything.
70
2) agt_globalfile() and get_user_file() now have return-type
71
'genfile'. (genfile is typedef'd to FILE* by default, so this
72
shouldn't break anything.)
73
3) 'scriptfile' is now of type genfile. See comment 2.
74
4) start_interface() now takes an argument of type 'fc_type'
75
instead of 'char*', as does set_default_filenames()
76
If you are using the default filename.c, then you can get
77
the old value by looking at "fc->gamename".
78
5) If you're replacing main(), the call to run_game() now requires
79
a file context instead of a game name. (See notes on main()).
80
See section 4.5 for more information.
81
--Added fixed font formatting code as well as FIXED_FONT
83
--Platform dependent information has been broken off into a seperate
84
include file, config.h, which is #included in agility.h
85
--Changed source code filenames to improve readability:
86
agtread.h-->agility.h; uagt.h-->interp.h;
87
agtdata.c-->gamedata.c; agtdbg.c-->disassemble.c;
88
agttest.c-->agtout.c; rmem.c-->util.c
89
--Converted bool to rbool to avoid conflicts with other libraries and
91
--Documentation of agt_textcolor() fixed.
94
-----------------------------------
95
1.2 ...TO MAGX SINCE VERSION 0.4
96
-----------------------------------
97
--New source file, objcomp.c, split off of compile.c.
98
--Platform dependent information has been broken off into a seperate
99
include file, config.h, which is #included in agility.h.
100
--Changed source code filenames to improve readability:
101
agtread.h-->agility.h; agtdata.c-->gamedata.c; rmem.c-->util.c
102
--Converted to using filename.c for file operations. See porting.txt
104
--Converted bool to rbool to avoid conflicts with other libraries and
105
systems and eliminated occurances of 'class'.
111
This lists the source files that should be in this package.
114
--------------------------
115
2.1 COMMON SOURCE FILES
116
--------------------------
117
config.g -- Platform specific #defines.
118
agility.h -- The header for all of the above files.
120
filename.c -- Functions for finding and opening files; this may
121
need to be edited or replaced on some platforms.
123
agxfile.c -- Routines to read and write AGX game files.
124
auxfile.c -- Routines to read in various additional AGT files.
125
gamedata.c -- Static data structures and dictionary management routines
126
util.c -- Miscellaneous utilities including string functions, wrappers
127
for dynamic allocation routines, and file I/O.
128
agilstub.c -- This contains the basic output function used by the
129
utility programs; not part of the interpreter.
132
------------------------------------
133
2.2 AGILITY-SPECIFIC SOURCE FILES
134
------------------------------------
135
interp.h -- Header for the interpreter files; contains things used by the
136
interpreter but not by agtread.c.
137
exec.h -- Header for the verb execution files (exec.c, runverb.c,
138
metacommand.c, and debugcmd.c).
140
os_none.c, os_termcap.c, os_dos.c, os_curses.c --
141
platform specific functions, including the lowest level terminal
142
I/O routines. os_none.c provides a minimal interface that uses
143
only ANSI C library functions; it is intended mainly as a template.
144
os_termcap.c and os_curses.c are two alternative unix backends;
145
they were developed under Linux but should work under most
146
*nix variants. (Please e-mail me about any portability problems.)
148
agtread.c -- Routines for reading AGT game files.
149
agil.c -- Initialization and the main program loop for the interpreter.
150
parser.c-- The parser and the menu system.
151
exec.c-- The top-level function for running player commands,
152
end-of-turn routines and miscellaneous utilities used during turn
154
metacommand.c-- Metacommand execution core.
155
token.c-- Decoding and execution of the actual metacommand tokens.
156
runverb.c-- Routines for executing verbs and the main routine
157
for executing player commands.
158
object.c -- Functions for manipulating the rooms, nouns, and creatures
159
debugcmd.c-- Routines for executing the debugging verbs.
160
interface.c -- The user interface for the interpreter and other semi-platform
161
dependent things including main()
162
disassemble.c -- Routines to print out the metacommand execution trace.
163
(Basically a disassembler for metacommands)
164
savegame.c -- Functions for saving and restoring the game state; used by
165
RESTART and UNDO as well as SAVE and RESTORE.
166
agtout.c -- Dumps out 'disassembled' AGT game files (originally written
167
as a test for agtread.c)
168
agt2agx.c -- Converts from AGT to AGX format.
171
---------------------------------
172
2.3 MAGX-SPECIFIC SOURCE FILES
173
---------------------------------
174
comp.h -- Header for all compiler-specific files.
176
compstub.c -- Interface routines, main(), error reporting routine,
177
and stubs for routines not used by the compiler.
178
compile.c -- Core routines for compiling file.
179
objcomp.c -- Routines to compile rooms, nouns, and creatures.
180
command.c -- Routines to compile metacommands.
181
symbol.c -- Routines to manipulate labels and check ranges.
182
preproc.c -- Code for the Magx preprocessor.
183
opdump.c -- Program to print out the list of meta-command tokens.
190
For all of the following, you should define your platform either from
191
the compiler or by adding a line to the top of config.h (e.g. #define
192
LINUX). Currently LINUX, SUN, HPUX, NEXT, AMIGA, MSDOS, and PLAIN are
193
supported, although some may require an appropriate os_<whatever>.c
194
file to compile AGiliTY. (For example, AMIGA requires David Kinder's
195
os_amiga.c file which is not included). For Magx, only LINUX and
196
MSDOS have actually been tested.
198
The following sections list the files that need to be compiled and
199
linked to make each of the possible programs.
202
----------------------
204
----------------------
205
AGTOut (AGT file dumper)
206
util.c, filename.c, gamedata.c, auxfile.c, agxfile.c,
207
agilstub.c, agtread.c, disassemble.c, agtout.c
209
AGT2AGX (AGT to AGX conversion utility)
210
util.c, filename.c, gamedata.c, auxfile.c, agxfile.c,
211
agilstub.c, agtread.c, agt2agx.c
213
AGiliTy (AGT/AGX interpreter)
214
util.c, filename.c, gamedata.c, auxfile.c, agxfile.c,
215
agtread.c, disassemble.c, agil.c, parser.c, object.c,
216
exec.c, runverb.c, metacommand.c, token.c, debugcmd.c,
217
savegame.c, interface.c, os_<whatever>.c
218
(Filling in <whatever> according to your platform.)
220
os_curses.c uses curses.c; it has been written and tested on Linux
221
with ncurses, but should work on other *nix platforms. Use of ncurses
222
is recommended. Please e-mail me about any portability problems.
224
os_termcap.c is termcap-based and in principal should work on any
225
UNIX platform with termcap, although I recommend instead using
226
os_curses. os_termcap.c has compiled and run successfully on both my
227
Linux box and a Sun workstation, but usually requires minor tweaks
228
between platforms, given the variation in terminal ioctrls between
231
os_none.c is intended mainly as a template for use by those trying
232
to port AGiliTy to a new platform. It should work on any platform
233
supporting ANSI C and a command line at the expense of having a status
234
line. (See PORTING below for details)
236
os_dos.c was written to work with Borland C; I have no idea how it
237
will work under other libraries or with other compilers. This should
238
be compiled under the Huge memory model.
244
OpDump (Prints list of metacommands and their argument types)
245
util.c, filename.c, gamedata.c, agilstub.c, opdump.c
248
util.c, filename.c, gamedata.c, auxfile.c, agxfile.c,
249
compile.c, command.c, symbol.c, preproc.c
254
-------------------------------------
255
4.0 PORTING NOTES FOR BOTH SYSTEMS
256
-------------------------------------
257
If you are interested in porting AGiliTy or Magx to another platform
258
you should contact me to avoid duplicated effort; my e-mail address is
259
rcm-math@pacbell.net.
260
Also feel free to write if you run into any difficulties.
262
The source code makes the following assumptions:
263
--ANSI C: it uses enums, typedefs, ANSI-style prototypes, etc.
264
--Text is encoded as ASCII.
265
--long ints are at least 32 bits.
266
--Negative numbers are represented in two's-complement.
270
In an ideal world, you should only need to change "config.h",
271
"os_<whatever>.c", and possibly "filename.c". Then you could upgrade
272
your port to a new version of AGiliTy by just replacing the default
273
versions of these files with your own. (Any changes to the interface
274
defined by these three files will be listed in the "Changes" section
277
In the real world, you may also need to tweak the memory allocation
278
routines in util.c, the higher level output routines defined in
279
interface.c, or the main() routines for any of the secondary programs.
280
If you need to change more than this, please send me a note so I can
281
try to fix whatever problem you ran into.
285
It should compile and work "out of the box" on any system with a
286
command line that obeys the above assumptions and for which config.h
287
and filename.c have been set up correctly.
289
All of the user interface routines (message output, argument
290
parsing, main(), etc.) are in compstub.c, so this is the only file
291
that should need to be edited to (e.g.) put a GUI front-end on the
295
---------------------------------
296
4.1 PLATFORM SPECIFIC #DEFINES
297
---------------------------------
298
To begin with, you need to determine the appropriate settings for the
299
various platform-specific #define statements in config.h. Many of
300
these #define's are only needed for one system or the other.
301
The following symbols can be defined:
303
PORTSTR: The string describing this particular port.
304
e.g. #define PORTSTR "OrfDOS Port by R.J. Wright"
306
NEED_STR_CMP, NEED_STRN_CMP: These should be defined if your C library
307
doesn't have strcasecmp() and strncasecmp(), respectively.
308
These are case insensitive string compare operations.
310
HAVE_STRDUP: Set this if strdup() is defined by your C library.
312
fix_ascii: Set this equal to 1 if your platform doesn't support IBM's
313
extended ASCII character set (unless you want to write os_*.c
314
to deal with the extended character set). [AGiliTy only]
316
FAST_FIXSIGN: This speeds the program up but assumes 16-bit shorts and
319
MAXSTRUCT: The largest size a single data structure can be. It
320
defaults to 1 MB. This should be at least as large as CBUF_SIZE,
321
BUFF_SIZE, and DESCR_BUFFSIZE; it should also be at least 32K.
323
BUFF_SIZE: Sets the maximum size of the file buffer used to read in
324
the game files at the beginning. The buffer is allocated
325
dynamically and will not be made larger than the size of the file
326
regardless of the setting of this variable. It will also not be
327
set smaller than an individual record size (which depends on the
328
file). So you can choose to have minimal buffering by setting this
329
to 0 or choose to buffer the whole file by making this
330
sufficiently large (The Linux port uses 1MB, for example).
331
The larger this is the faster files will load but the more
332
memory will be used in the meantime. The default is 32K.
334
CBUF_SIZE: This is the buffer size used when loading in Master's edition
335
'.DA6' (code) files, measured in 2-byte units. (So the actual size
336
is twice CBUF_SIZE). Nothing above 20,000 makes sense. [AGiliTy
339
DESCR_BUFFSIZE: The maximum size of the description text block before
340
the interpreter will read it from disk rather than storing it in
341
memory during play; it defaults to 0 (i.e. always use the disk).
342
It should not be any larger than MAXSTRUCT. At the moment this
343
only affects AGX games; games in the 'D$$' format will always
345
Setting this option will speed up text output during play
346
at the expense of a longer loading time (and more memory used).
347
(See also the buff_maxmem variable, below).
348
In practice, game description blocks range from around 50K to
349
around 440K (for Shades of Gray), with most around 100K.
352
DOHASH: Define this to use hash tables for dictionary searches.
353
This speeds up loading and compiling dramatically at a small
354
increase in memory usage.
356
UNIX_IO: If you have Unix-like low level file I/O functions.
357
(MS-DOS, for example, does). This speeds up the reading
358
of the large game data files on some platforms. If you set this,
359
you will also need to set values for FILE_PERM, READFLAG, and
360
WRITEFLAG; see the top of util.c.
362
OPEN_AS_TEXT This causes text files to be opened as text files.
363
Normally they are opened as binary files and end-of-line
364
translation is done by hand, but if you have an operating
365
system for which this doesn't work you might need to define this.
366
If you define this, the variable open_as_binary can be set to
367
cause text files to be opened as binary files, anyhow.
368
(Which can be useful when trying to compile a file uploaded
369
from another system.)
371
REPLACE_MENU: Define this if you replace the function agt_menu() which
372
creates menus for the player when a game is in menu mode. See 5.3.
375
REPLACE_MAIN: Define this if you replace main(). See 5.3. [AGiliTy only]
377
REPLACE_GETFILE: Define this if you replace the function get_user_file(),
378
say to allow the user to pick files from a menu. See 5.3 for
379
details. [AGiliTy only]
381
REPLACE_FC: Indicates you want to redefine the fc_type type.
382
See the section 4.3 on the filename interface.
384
pTTL, pINS, pVOC, pHNT, pCFG, pAGX [Both systems]
385
DA1, DA2, DA3, DA4, DA5, DA6, DSS, pOPT [AGiliTy only]
386
pAGT, pDAT, pMSG, pCMD, pSTD [Magx only]
387
These should be defined to be the extensions to the various files
388
that make up an AGT game. By default they will be ".da1", ".da2",
389
".da3", ".da4", ".da5", ".da6", ".d$$", ".ttl", ".ins", ".voc",
390
".opt", ".hnt", ".cfg", ".agx", ".agt", ".dat". "msg", ".cmd", and
391
".std" which are the extensions under MS-DOS.
392
(Although not all of them are used by both programs, don't delete
393
the unused defaults as that will keep filename.c from compiling.)
394
If you are replacing filename.c, you don't need to define these.
396
pSAV,pSCR,pLOG: These are the default extension for save, script, and
397
log files respectivly (by default they are ".sav", ".scr", and ".log").
398
These are only used if REPLACE_GETFILE is not defined. [AGiliTy only]
400
AGTpSTD: This should be the file name of the generic error message
401
file, which the compiler looks for if the game doesn't have its
402
own. (By default, this will be "agt.std".) You don't need to
403
define this if you are replacing filename.c. [Magx Only]
405
PREFIX_EXT Put file name extensions before the base file name rather
406
than after. You don't need to worry about this if you are
407
replacing filename.c.
409
PATH_SEP Define to be a string containing characters that could
410
separate the directory path from the filename. If not defined,
411
then AGiliTy will assume there are none and will not try
412
to extract the path from filenames.
413
You don't need to worry about this if you are replacing
416
pathtest(s) This is a macro (although you could rewrite it as a function)
417
that should check whether the given string is an absolute
418
path (e.g. in Unix, paths starting with a slash.)
419
If this is left undefined, then _all_ paths will be
420
treated as absolute. You don't need to define this if you are
421
replacing filename.c.
423
(There are also a handful of symbols specific to particular
424
os_<platform>.c files; see the relevant files for details).
427
---------------------------------------------------------
428
4.2 FUNCTIONS DEFINED BY THE INTERPRETER
429
---------------------------------------------------------
430
These are defined in util.c; you are welcome to use them
431
(and in unusual circumstances you might need to change them).
433
void *rmalloc(long size)
434
void *rrealloc(void *ptr,long size)
435
void r_free(void *ptr)
437
char *rstrdup(const char *s)
438
These are interpreter's own internal memory allocation routines;
439
these are wrappers around the usual functions that catch out-of-memory
440
conditions (and exit the program if neccessary). Note that <size> is
441
of type <long>, not <size_t>.
442
<rfree()> is a macro that calls <r_free()> and then sets <ptr> to NULL.
443
<rstrdup> creates a duplicate copy of a string s, using
447
---------------------------
448
4.3 FILENAME.C: OVERVIEW
449
---------------------------
450
You may not meed to change filename.c at all; the default interface
451
is fairly flexible and should work on most systems. In particular, if
452
your system has the following properties, then the original filename.c
453
should be adequate (and you can skip ahead to chapter 5):
455
i) Files are labeled by filenames. In particular, the file name
456
(including extension) and path are enough to find the file
458
ii) File names can be split into a path (which says where the file
459
is) and a filename, and the separator symbol(s) can't occur in
461
iii) The file "type" of the AGT files is indicated by an extension
462
(or prefix) to the filename.
463
iv) The ANSI file functions are all supported.
465
If one or more of these conditions is broken (or if you want to do
466
something unusual, like read files straight out of ZIP archives), then
467
you will need to either edit or replace filename.c. All code for
468
dealing with filenames and file I/O goes through this file; by
469
changing it, you can radically alter the way AGiliTy and Magx find and
472
If you make major changes to the filename system, you will
473
probably also need to replace get_user_file() and
474
set_default_filenames(); these are logically part of the filename
475
interface, but have been put in interface.c since they shouldn't be
476
linked into Magx or the various secondary programs.
479
-----------------------------
480
4.4 FILENAME.C: DATA TYPES
481
-----------------------------
482
There are a handful of definitions and typedefs in config.h; they
483
are listed here with their default settings. You can change any of
484
these (except for the filetype enum) and it won't break anything
485
outside of filename.c, get_user_file(), and the various
486
os_<whatever>.c files.
488
typdef FILE* genfile;
489
The basic file object.
491
#define BAD_TEXTFILE NULL
492
#define BAD_BINFILE NULL
493
These define the value of genfile that means "this doesn't point to
496
typedef char *file_id_type
497
Created by writeopen() for use by by binremove(). In the default
498
filename.c, this is just the filename. It must be a pointer type.
500
typedef file_context_rec *fc_type;
501
This is in agility.h, but it can be redefined by #defining
502
"REPLACE_FC" in config.h. Nothing in the core system depends on the
503
internal structure of fc_type. (The only reason file_context_rec is in
504
agility.h at all is so that os_<whatever>.c can use it.) This
505
specifies a "file context", basically a glorified (and generalized)
507
The file context should contain whatever information is required
508
to allow the various routines in filename.c to find the neccessary
510
Although the default filename.c version is based around file names,
511
this isn't required (at least if you're willing to replace filename.c,
512
main(), and get_user_file()).
517
fDA1 the info(DA1) file
518
fDA2 the room(DA2) file
519
fDA3 the noun(DA3) file
520
fDA4 the creature(DA4) file
521
fDA5 the metacommand(DA5) file
522
fDA6 the metacommand code(DA6) file
523
fDSS the string(DSS) file
524
fHNT the pophint file (not used yet)
525
fOPT the options file
530
fAGX the AGX data file
531
fINS the instruction file
532
fVOC the vocabulary file (used for menuing)
533
fCFG the game-specific configuration file
534
fAGT,fDAT,fMSG,fCMD,fSTD AGT source files
535
fAGT_STD The standard error message file
537
These are all of the various file types that the file system can
541
----------------------------
542
4.4 FILENAME.C: FUNCTIONS
543
----------------------------
544
The following are all of the routines that must be defined by
545
filename.c. Several of these are macros by default (these are all
546
defined at the end of config.h).
548
fc_type init_file_context(const char *name, filetype ft);
549
This creates a file context based on the given name and
550
on the file class 'ft'. The file class here doesn't refer to
551
a particular file type but rather to how the context will be used;
552
the following values of are used by AGiliTy (this is specific to
553
init_file_context; elsewhere the filetype denotes actual types of
554
files, not the broader classes here):
555
fDA1: "name" is the name of a game; the context will be used to
556
load the game data files.
557
(AGX, DA1, DA2, ... DSS, CFG, TTL, VOC,... etc.).
558
fNONE: As in fDA1, but gamepath hasn't been set yet, so
559
don't integrate path information until fix_file_context() is
561
fSAV: "name" will be used to access a save file.
562
fSCR: "name" will be used to access a script file.
563
fLOG: "name" will be used to access a log file.
564
fAGX: "name" is name of an AGX file that is about to be written
565
to (agt2agx and Magx only).
566
fAGT: The context will be used to read source code. (Magx only)
567
This is called from main() and get_user_file() so if you replace
568
both of these (and the corresponding sections of agt2agx and
569
agtout), then you don't need to implement this function.
570
(Although you still need some way to create a file context to
571
pass to run_game() and the SAVE/RESTORE/LOG/SCRIPT routines.)
573
void fix_file_context(fc_type fc, filetype ft);
574
Similar to creat_file_context, this is called after path information
575
has been read in. It should adjust the file context to take advantage
576
of that information. (On a port that doesn't support gamepath, this
577
doesn't do anything.)
579
fc_type convert_file_context(fc_type fc,filetype ft,const char *name)
580
This creates a new file context based on fc and name, but possibly
581
altered in some ways, depending on the file type.
582
If name is NULL, then this routine should copy fc, making appropriate
583
changes. If name is not NULL, then the routine should build a file
584
context based on name, but possibly with information from fc.
585
This is used for two purposes:
586
i) To create save/script/log file contexts from a game name context.
587
(in which case name will be NULL).
588
E.g. converting "mygame.agx" to "mygame.sav"
589
ii) To create contexts for new files in the same location as
590
the context fc refers to. (For example, font files, include files,
591
etc.-- which may not have the game name in their filename.)
592
e.g. converting "/usr/local/spelunker/spelunk.agx"
593
to "/usr/local/spelunker/cavepic.pcx"
595
void release_file_context(fc_type *pfc);
596
Free the file context pointed to by pfc.
598
char *formal_name(fc_type fc, filetype ft);
599
Return a user-readable string refering to the file associated with
600
the given file context and type. This string will be used for
601
reporting errors and other messages. The string should have been
602
allocated with rmalloc.
604
genfile badfile(filetype ft);
605
Return the bad file marker for files of type ft.
606
In the default filname.c, this always returns NULL.
608
rbool fileexist(fc_type fc, filetype ft)
609
Returns true if the file referred to by fc and ft exists.
611
genfile readopen(fc_type fc, filetype ft, char **errstr);
612
Open the file associated with the given file context and type for
613
reading. If there is an error, *errstr should be set to point to
614
an rmalloc'd error message; otherwise it should be set to NULL.
616
genfile writeopen(fc_type fc, filetype ft,
617
file_id_type *pfileid, char **errstr);
618
Open the file associated with the given context and type for
619
writing. Set *pfileid to whatever information is needed
620
for binremove() to work; *set errstr as in readopen.
622
rbool filevalid(genfile f, filetype ft);
623
Return true if f refers to a valid file (as opposed to being NULL,
624
say). ft contains the filetype of the given file, which can be
625
useful if genfile is a union of several different datatypes.
627
void readclose(genfile f);
628
Close a file that was opened using readopen.
630
void writeclose(genfile f, file_id_type fileid);
631
Close a file that was opened using writeopen and (if neccessary)
632
free any data pointed to by fileid.
634
void binremove(genfile f, file_id_type fileid);
635
Remove a file opened by writeopen.
637
void binseek(genfile f, long offset);
638
Seek to the location <offset> in the given file.
640
rbool binread(genfile f, void *buff, long recsize, long recnum,
642
Read a block of <recnum> records each of size <recsize> from the
643
given file into the buffer <buff>. *errstr should be set as for
644
binopen(). Return true on success, false on failure.
645
Hitting the end-of-file counts as an error.
647
rbool binwrite(genfile f, void *buff, long recsize, long recnum,
649
Write a block of <recnum> records each of size <recsize> from
650
buffer <buff> into the given file. In the event of an error,
651
abort the program if 'ferr' is true; otherwise just return 0.
652
Return true on success, false on failure.
654
long binsize(genfile f);
655
Return the size of an open binary file.
657
rbool textrewind(genfile f);
658
Rewind the given text file to the beginning.
660
int textgetc(genfile f);
661
Wrapper around fgetc(f).
663
void textungetc(genfile f, char c);
664
Wrapper around ungetc(c,f).
665
(Note the reversal of the order of arguments, done for internal
666
consistency: all filename.c functions that require a file have it
667
as their first argument.)
669
int texteof(genfile f);
670
Indicate if the given text file is at the end-of-file.
672
void textgets(genfile f, char *buff, long leng);
673
Wrapper around fgets(buff,leng,f).
675
void textputs(genfile f, const char *s);
676
Wrapper around fputs(buff,f).
679
The default version of filename.c exports one additional function,
680
which is only used by os_dos.c, os_termcap.c, and os_curses.c
681
(although you are free to use it in your os_<whatever>.c file, too)
682
and so doesn't need to be defined if you're writing both your own
683
filename.c and os_<whatever>.c:
685
char *assemble_filename(const char *path, const char *root,
687
Concacate path, root, and ext and return the resulting
693
----------------------------------------
694
5.0 FURTHER NOTES ON PORTING AGILITY
695
----------------------------------------
696
The rest of this file discusses the details of writing a new port of
697
AGiliTy. If you have any sort of command line, you may want to start
698
by getting os_none.c to work (it uses only ANSI functions) and then
701
Keep in mind that the current Linux and DOS ports have had a lot of
702
bells and whistles added; the interface doesn't need to be as
703
complicated as they have become. (The original os_dos.c was under 400
707
---------------------------------------------
708
5.1 OS_*.C: THE PLATFORM-SPECIFIC INTERFACE
709
---------------------------------------------
710
To port AGiliTy to another platform, you also need to create the
711
platform specific os_*.c file, which handles the platform
712
specific tasks of the interpreter.
715
It is the responsibility of os_*.c to call for the updating
716
of the status line by calling the function print_statline(void)
717
periodically (it puts together the status line and then prints it out
718
by calling agt_statline() ). At the very least, it should be called
719
anytime the player is asked for input and should probably also be
720
called before delay().
722
Output should be in a fixed-pitch font, ideally 80 columns
723
wide. Some AGT games depend on both of these to format text vertically
724
(e.g. both Shades of Gray and Cosmoserve).
726
os_*.c must contain the definitions of the following
727
functions (some of them can be empty functions, of course, and many of
728
them only require a few lines of code; os_none.c is both a template
729
and an example of a minimal os_*.c).
731
void agt_delay(int n)
732
Wait n seconds. (If fast_replay is true, don't wait at all.)
734
int agt_rand(int a,int b)
735
Return a random number from a to b, inclusive.
736
If stable_random is set, the random number generator should have been
737
initialized in a consistent way so the same numbers will be generated
738
each time the program is run.
740
void init_interface(int argc,char *argv)
741
void start_interface(fc_type fc)
742
These should initialize the interface. init_interface() is called at
743
the very beginning of the program, before the game or any
744
configuration files have been read. It is passed the the command line
745
arguments. If you replace main() then you don't need to define
746
init_interface() but you need to provide similar functionality from
747
within your new main().
748
start_interface() is called after the game has been read in and
749
needs to finish the initialization. You may assume only agt_newline(),
750
agt_puts(), and agt_option() will be called before start_interface(),
751
to print out diagnostic information.
752
In addition they need to set screen_width, screen_height,
753
status_width, and curr_x.(See below for what all of these are). They
754
also needs to set script_on=center_on=par_fill_on=0, after which the
755
interface can safely ignore the last two of the variables. It _is_ the
756
responsibility of the os_* code to echo everything to the script file
758
These are two functions so that start_interface() can use
759
information from the game file (perhaps parsed by agt_option). If you
760
aren't doing this, you can just put all of the initialization in
761
init_interface() and leave start_interface() empty.
763
void close_interface(void):
764
This should do any cleanup necessary.
766
char *agt_input(int in_type)
767
This should read a line of input from the player and return it in a
768
malloc'd buffer. (The routine calling agt_input is responsible for
769
freeing this buffer).
770
in_type specifies the type of input being asked for:
773
2: the answer to a question
774
3: a string (e.g. asking for the player's name)
776
5: 'RESTART, RESTORE, UNDO, or QUIT?'
778
char agt_getkey(rbool echo_char)
779
Get a single key-press from the keyboard. Echo it to the screen if
782
void agt_puts(const char *s)
783
Output the string s. You may assume that s contains no newline
784
characters and that the string itself will not wrap (at least as long
785
as screen_width and curr_x have been correctly maintained). curr_x
786
should be incremented by the length of s. (It *is* possible for
787
characters to be output all the way to the rightmost column, which
788
could cause the *cursor* to wrap)
790
void agt_newline(void)
791
Generate a newline, scrolling the screen up if necessary.
793
void agt_clrscr(void)
794
Clear the screen and position the cursor in the upper left-hand
797
void agt_statline(const char *s)
798
Display the string s on the status line. This should be printed
799
in a fixed-pitch font.
801
void agt_textcolor(int c)
802
This really handles *all* of the details of text appearance, not
804
0-6,9 are colors; see os_none.c for details.
805
7= Normal: turn off all blinking, bold, color, etc. and restore
806
the text to its default appearance.
807
8= Turn on blinking. (Which can only be turned off by c=7)
808
10= Turn on fixed-pitch font.
809
11= Turn off fixed-pitch font.
810
-1= Turn on emphasized text("Bold").
811
-2= Turn off emphasized text.
812
None of these are toggles-- if any occur twice in a row, the second
813
should just be ignored.
814
If you are interested in implementing a proportional font interpreter,
815
you should also look at the description of font_status in 5.2.
818
void agt_tone(int hz,int ms)
819
Create a tone at a frequency of hz hertz for ms milliseconds.
820
This routine should check the sound_on variable; if it is 0, then the
821
routine shouldn't do anything.
824
void agt_makebox(int width,int height,unsigned long flags);
825
This creates a text box of the given width and height. (These only
826
include the text inside and do *not* include any border). The text
827
will be output by using agt_puts() and agt_qnewline().
828
Flags can have the following bits set:
829
TB_TTL, if the title is being printed (the box should be
830
vertically centered in this case).
831
TB_BORDER, Print a border around the box.
832
TB_NOCENT, don't center the box horizontally; print it left justified
833
Other bits are reserved for future use.
834
The actual text of the box will be printed out using the regular
835
agt_puts() function interspersed with calls to the box-specific
836
agt_qnewline() (the 'q' stands for 'Quote').
837
You may assume that _exactly_ *width* characters of text will be
838
printed out on each line (but possibly in multiple agt_puts()
839
statements). agt_qnewline() will be called between lines, but will
840
not be called after the last line (agt_endbox() will be called,
841
instead). You may also assume that exactly *height* lines will be
843
On the other hand, it is legal for agt_textcolor() to be called
844
during the output of text in a box (which is one reason why there may be
845
multiple agt_puts() commands per line).
846
Text boxes should also be printed out in a fixed-pitch font.
848
void agt_qnewline(void);
849
This is used instead of agt_newline() when text inside a box is
850
being printed out. See agt_makebox() for details.
852
void agt_endbox(void);
853
This is used at the end of a box. See agt_makebox() for details.
854
It should leave the cursor in the left-most column on the line below
857
genfile agt_globalfile(int fid); /* When fid=0, return global config file */
858
When fid=0, this should return an open file descripter to the global
859
configuration file for the interpreter.
860
For example, in MS-DOS, this will be the file AGIL.CFG in the same
861
directory as the interpreter; in Linux it is the file '$HOME/.agilrc'.
862
For other values of fid, return NULL.
864
rbool agt_option(int optnum,char *optstr[],rbool setflag);
865
As the interpreter parses the configuration files, it will pass any
866
options it doesn't understand to this function; this can be used to
867
support platform-specific configuration options.
868
The line will have been parsed into whitespace-separated words.
869
*optnum*=number of words, *optstr[]* is the array contain pointers to all
870
of them. optstr[0] will be the first word on the line (and hence the
872
*setflag* will be 1 unless the option name was prefixed by 'NO_'
873
(inverting its meaning) in which case it will be 0 (and the 'NO_'
874
prefix will have been stripped off).
875
Return 1 if agt_option() recognized the option, 0 otherwise
876
(which will cause a warning to be printed).
879
---------------------------------------------------------
880
5.2 VARIABLES AND FUNCTIONS DEFINED BY THE INTERPRETER
881
---------------------------------------------------------
883
The following variables are defined elsewhere, but need to be set and
884
updated by the routines in os_*.c as they are used for
885
line-break information and to format the status line:
887
int screen_width: the width of the screen
889
int status_width: the width of the status line (on most systems this
890
will be the same as screen_width).
892
int curr_x: The current x position (starting at 0).
894
int screen_height: The height of the screen.
895
Currently the only routine that uses this is the title printing
898
rbool script_on: This should be set to zero by init_interface() and
899
does not need to be changed by the interface code after that.
900
If it is 1 then all input and output should be echoed to the file
901
associated with scriptfile.
903
genfile scriptfile: The file script output should go to. This is set
907
rbool sound_on: This is set to 1 initially; if it is 0, then agt_tone()
908
shouldn't do anything. os_* may change this.
910
char **gamepath: This is a pointer to a NULL-terminated array of
911
pointers to strings, each of with gives a possible path for the game
912
files. This is set to NULL initially, but you can set this to
913
a list of game file search paths if you want. It needs to be set
914
by init_interface() or agt_option() to have any effect.
915
If this is not NULL, the directories is lists will be searched
916
in order, *before* the current directory is checked. If you want
917
the current directory to be searched first, make sure that
918
gamepath[0] is the empty string "".
920
rbool DEBUG_AGT_CMD: By default, this is set by main() according
921
to command line options but you can change it if you want.
922
It can also be set by the player using the AGILDEBUG command.
923
This determines whether metacommand debugging information is
926
rbool DEBUG_OUT: This should be set by init_interface(). If it is 0,
927
metacommand debugging output will go to the screen (using
928
agt_puts() and agt_newline()). If it is 1, debugging output will
929
be sent to debugfile and the interface code should also echo
930
everything to debugfile. Whether there is any debugging output
931
in the first place is determined by DEBUG_AGT_CMD.
933
FILE *debugfile: This is the file where metacommand debugging output
934
will be sent if DEBUG_OUT is true. It should be set by init_interface().
936
(The Linux port, e.g., always sets debugfile to stderr and checks to
937
see if stderr and stdout refer to the same underlying file; if they
938
do it sets DEBUG_OUT to 0; if they are different, then it sets
939
DEBUG_OUT to 1. Thus if stderr is redirected by the user, then
940
a complete debugging log file will be written without cluttering
941
the screen. If it is not redirected then debugging output will be
942
sent to the screen through agt_puts().)
945
stable_random: When this is set, the random number generator should
946
behave consistantly so as to give the same set of values each time the
949
BATCH_MODE: We are running the game with a fixed script and so
950
output can be supressed.
952
menu_mode: If true, menu input will be used instead of the usual
953
command line. This variable is managed automatically by the
954
interpreter, but you can change it if you want.
957
compass_rose: This is an unsigned short with a bit set for each
958
direction the player can go; a fancy port of the interpreter could
959
use this to print something out below the status line (or even draw
960
an honest compass rose). There are 12 bits used; starting with the least
961
significant bit they represent N, S, E, W, NE, NW, SE, SW, U, D, IN,
964
descr_maxmem: This is set to DESCR_BUFFSIZE at the beginning of the
965
program, but you could change it based on the amount of memory
966
available at runtime. It must be set before the game file is
967
read in from memory (after init_interface() but before
969
It sets the upper limit on the size of the description block
970
before the interpreter will just leave it on disk rather than trying
971
to load it into memory at once.
973
font_status: This is set by the interpreter; it tells whether a
974
proportional font can be use, or whether the interface must
975
use a fixed pitch font. There are three possible values:
976
0 -- The interpreter doesn't know whether proportional fonts
977
are allowed or not; it's up to the interface (or the user)
978
to make this decision. This is the setting for original AGT
979
games and early Magx games.
980
1 -- Fixed font needs to be on by default.
981
2 -- Fixed font doesn't need to be on by default.
982
See also agt_textcolor().
984
rbool fast_replay Set by the interpreter, this is true if the
985
user is doing a fast replay from a log file. In this case,
986
delays should be supressed and text scrolling should not be
987
stopped each screen to wait for the user.
989
The following functions are defined by the interpreter but can be
994
void agt_restore(void)
996
These save, restore, and quit the game, respectivly. They can be called
997
asyncronously (although the quit or restore won't actually occur until
998
the end of the current turn). These are intended mainly for use in
1000
(These haven't been tested extensively)
1003
void agt_newgame(fc_type fc)
1004
This loads a new game, replacing the current one; like the function
1005
above, it doesn't take effect until the end of the current turn.
1006
During the start of a new game, start_interface() (but not
1007
init_interface) will be called again. This is intended mainly for use
1008
in event-driven GUIs.
1009
(This hasn't been tested at all)
1012
-------------------------------------------------------
1013
5.3 OTHER FUNCTIONS THAT CAN OPTIONALLY BE SPECIFIED
1014
-------------------------------------------------------
1015
The following functions may also, optionally, be defined in
1016
os_*.c, but you must insert appropriate #define statements
1017
into config.h to prevent the default versions from being created
1018
(see above). The default versions of all of these functions are in
1021
genfile get_user_file(int ft) /* 0=script, 1=save, 2=restore,
1022
3=log(read) 4=log(write) */
1023
This gets a file name from the user, opens it, and returns the
1024
appropriate data structure. If you redefine this then define
1025
REPLACE_GET_FILE in config.h. You might want to redefine
1026
this to allow the user to pick files from a menu, for example.
1027
ft tells what sort of file the user is being asked for: 0=script,
1028
1=save, 2=restore, 3=log file(read), 4=log file(write).
1029
This is logically part of the filename system; see 4.5.
1031
void set_default_filenames(fc_type fc)
1032
This is part of get_user_file and will also be left undefined
1033
if REPLACE_GET_FILE is defined in config.h.
1035
int agt_menu(char *header,int size,int width,menuentry *menu);
1036
This prints out a menu and gets a choice from the user. This is used
1037
by a few games to get menu-driven input. You should define
1038
REPLACE_MENU if you want to redefine this.
1039
*header* is the header for the menu; e.g. 'PUT TUBA IN ?'
1040
*size* is the number of entries in the menu
1041
*width* is the width (in characters) of the widest one.
1042
*menu[]* is the array of menu entries; menu entires are strings of
1043
length MENU_WIDTH (currently 50).
1044
(In interp.h: typedef char menuentry[MENU_WIDTH]; )
1045
Return the index corresponding to the menu entry chosen or -1 if
1046
something strange happened (e.g. the player turned off menuing by
1051
By putting #define REPLACE_MAIN in config.h, you will prevent
1052
main() from being defined in interface.c so that os_*.c can
1053
define its own main function (on some platforms, this may be called
1054
something other than 'main()').
1055
The main function needs to do the following:
1056
--Call set_default_options() to make sure that all of the options are
1057
initialized to the correct defaults.
1058
--Set the various options, either from the command line or by other means
1059
--Get the file name of the agt game being played (from the command line or
1061
--Do basic initialization of the interface (enough so that writestr()
1062
and writeln() will work for diagnostic messages)
1063
See the comments on init_interface() above.
1064
--Call run_game( fc_type fc ), where fc is the file context of the
1065
game file(s). If you're using the default filename.c, you can
1066
get this context by calling init_file_context(gamename,fNONE).
1072
------------------------------------------
1073
5.4 GRAPHICS, FONT, AND SOUND FUNCTIONS
1074
------------------------------------------
1075
Master's Edition games included support for graphics and sound,
1076
although only a very few games were made that made any use of these
1077
features. The DOS and Linux ports support fonts and graphics; I don't
1078
know of any ports that support sound, but the core interpreter
1079
implements the necessary hooks.
1081
If you actually want to implement these, you'll want to track down
1082
the documentation for the Master's Edition which discusses the file
1083
naming conventions and file formats used for these. (You will also
1084
want to get your hands on the game HURRY! HURRY! which demonstrates
1087
Stub versions of these functions are currently defined at the
1088
beginning of interface.c; you'll need to comment out those functions
1089
that you are replacing.
1092
void fontcmd(int cmd,int font)
1093
0=Load font, the name is fontlist[font]
1094
1=Restore original (startup) font
1095
2=Set game's initial font (<gamename>.FNT)
1096
This sets the font used for all output text. Under DOS, the fonts
1097
are stored in a file name <name>.FNT. The data seems to be stored
1098
simply as a collection of binary bitmaps, 8x8 pixels, with eight bytes
1099
for each of the 256 characters in the font set (giving one byte per
1100
row). There doesn't seem to be any sort of header or other
1104
void pictcmd(int cmd,int pict)
1105
1=Show global picture, name is pictlist[pict]
1106
2=Show room picture, name is pixlist[pict]
1107
3=Show title picture (usually <gamename>.pcx)
1108
Display the picture requested on the screen until the user presses
1109
a key. Pictures are stored in the PCX file format, but with nonstandard
1110
filename extensions which indicate the PC video mode the image was
1111
supposed to be viewed in.
1112
Animations are stored in the FLI format.
1115
int musiccmd(int cmd,int song)
1116
1=play song, name is in songlist[song]
1117
2=play song repeatedly, name is in songlist[song]
1122
7=clean-up sound system (called just before interpreter exits)
1125
-1=Is a song playing? (0=false, 1=true)
1126
-2=Is the sound on? (0=false, 1=true)
1127
Songs are stored in the MUC file format:
1128
The file format includes no header, but is a collection of
1129
six-byte records. Each record consists of three unsigned 16-bit
1130
numbers (stored little-endian like all numbers under AGT: the least
1131
significant byte comes first): the frequency (in Hertz); the length of
1132
time of the tone (in milliseconds); and a delay between tones (also in
1134
At least in theory, songs may also be stored in the VOC, MID, or CMF