--------------- TECHNICAL GUIDE --------------- Although "Frotz" was written for MS-DOS only, it shouldn't be too difficult to port the interpreter to other operating systems. You are invited to write front-ends for other systems, but before you do so you should email me to avoid double efforts: jokisch@ls7.informatik.uni-dortmund.de Frotz is freeware. It may be used and distributed freely provided no commercial profit is involved. (c) 1995, 1996 Stefan Jokisch ~~~ (1) Manifest ~~~ The source code consists of the following files: BUFFER.C -- word wrapping routines; set_colour, set_text_style, set_font are also implemented here FASTMEM.C -- memory management: undo, restart, save, restore and verify; change this file if you want to use virtual memory HOTKEY.C -- generic functions which are called after a so-called hot key was pressed (e.g. multiple undo, playback...) INPUT.C -- high-level input routines; implements read_char and read opcodes MAIN.C -- the main routine of the interpreter; global variables are all defined here MATH.C -- arithmetic, boolean and comparison opcodes; pretty harmless stuff MENU.C -- some day this module might implement make_menu; up to now it contains only a dummy function OBJECT.C -- object and property manipulation opcodes (get_prop, put_prop, get_parent, get_child and so on) [*] PROCESS.C -- this is the heart of the Z-machine; interpreter main routine and controlling opcodes (call, jump etc.) [*] RANDOM.C -- implements the random opcode using stdlib functions rand and srand SCREEN.C -- generic screen manipulation routines; this module is now able to work in terms of screen units SOUND.C -- implementation of the sound_effect opcode; primitive, most of the work is passed to interface routines STREAM.C -- all file-related IO streams such as input recording, input playback and output transscription TABLE.C -- opcodes to manipulate table structures: loadb, loadw, storeb, storew, copy_table, scan_table TEXT.C -- high-level output routines; text encoding and decoding; tokenise opcode [*] VARIABLE.C -- implementation of opcodes which handle variables and the stack [*] BORLAND.C -- Borland C specific IO interface; replace this one with your own interface FROTZ.H -- include file used by all the modules mentioned above; global constants, variable declarations and prototypes GETOPT.C -- replacement for a Unix-style getopt function; quite useful for writing the os_process_arguments function [*] These modules should be optimized for speed. All other modules may be optimized for size. This strategy was used to build the DOS executable. ~~~ (2) Porting Frotz ~~~ To port "Frotz" you have to write a new IO interface to replace the DOS interface borland.c. All functions named os_*** are required to build the program; the comments in borland.c briefly specify the correct behaviour. For a quick start, you might try the following generic definitions: os_display_char: if (cwin == 0) putchar (c); os_char_width: return 1; os_string_width: return strlen (s); os_read: gets (buffer); return 13; os_scroll_area: if (cwin == 0) putchar ('\n'); os_process_arguments: story_name = "story.dat"; os_init_screen: h_screen_width = 79; h_screen_height = 25; os_fatal: fprintf (stderr, "Fatal: %s\n", s); exit (1); All other interface routines should do nothing. This will suffice to play a simple V3 game (which must be named story.dat). Of course, this is a very primitive interface that has a lot of serious limitations; there is still a lot of work to do. The only symbol you might need during compilation is MAX_FILE_NAME, which defaults to 32 when it is undefined. ~~~ (3) Changes since version 1.01 ~~~ This is a (hopefully) complete list of all changes that porters should be aware of. Although it looks alarmingly long, it is rather harmless. A few extensions were necessary to support V6 games; a few changes have been made to improve the design of the program. Most recent changes are listed first. * Generic macros The header file finally contains generic definitions for my notorious macros. I haven't tested them yet, but I'm confident that they should work for every OS which doesn't suffer from 64KB limitations like DOS. * Extensions for Amiga For the benefit of the Amiga port, following changes are available when AMIGA is set: - an additional function resize_screen in screen.c, - a call to CheckReset after every restart, - more efficient macros in frotz.h (let's hope they work), - beyond_zork_flag/german_zork_flag are no longer set by load_header. * Width of characters and strings os_text_length has been re-named to os_string_width. Its defintion has been changed several times, so take a look at the latest version in borland.c. There is also a new interface function os_char_width that returns the width of a given character. This function should be fast as Frotz makes frequent use of it. * Reading the cursor position The interface routine os_get_cursor has vanished. * Primitive memory management os_init can set the long variable reserve_mem to reserve any arbitrary number of bytes for later use; otherwise Frotz may allocate memory for multiple undo which would be needed for other purposes (such as loading a sound file, opening a file requester etc.) later on. * Character output routines A new interface routine os_display_string was introduced to display a string of characters on the screen. It may pass all the characters to os_display_char. Important: os_read may use os_display_string, it may no longer use display_string. The same applies to os_more_prompt. Other routines (e.g. os_get_file_name) should use the display_*** routines. Note that display_string is able to handle newlines, e.g.: display_string ("Enter a file name:\n") * More colours The colour scheme has been enhanced. In addition to the Z-machine colours, the interface can define the colours from 16 to 255 for its own use. This is particular important for the new interface routine os_peek_colour which returns the colour of the pixel at the current cursor position. This function is mostly used to write text on top of pictures; however, pictures may consist of non-standard colours. There are also a few more standard colours. For MS-DOS only, there is a GREY_COLOUR. For Amiga only, there is LIGHT-, MEDIUM-, and DARKGREY_ COLOUR. No extra colours for the rest of the world. * Messages (os_message_start) For those who have copied the code from borland.c: The condition in os_message_start that decides whether we need to insert a newline must be replaced by (get_line_width (cwin) != get_units_left ()). * Input routine os_read got a new argument: It gives the number of screen units in which the input line (including the cursor) must fit. * Picture support os_picture_data and os_draw_picture are needed for pictures; see borland.c for details. * Mouse windows A new interface function os_mouse_area has been added to restrict the movement of the mouse cursor. This is only used by Arthur (when the map is selected); the interpreter need not implement it. * No support for menus Make sure os_init clears the MENU_FLAG. * More modules There are three new modules: VARIABLE.C, RANDOM.C and MENU.C. * Bells and whistles There is a new option_left_margin that does the obvious thing (and usually fails in V6). There are also new hot keys: HOT_KEY_RESTART (Alt-N == new game) and HOT_KEY_QUIT (Alt-X == exit game). Another new option is the option_piracy. When this variable is set, the piracy opcode does not branch (which would make the game believe it was a pirated copy). In practice, this opcode wasn't used, and therefore it is pretty pointless to set the flag. DOS Frotz provided an undocumented command line switch to set the option, anyway. Equally useless is the header entry h_user_name. This array can hold a user name of up to 8 letters. It can be set by os_init_screen, but it won't have any effect. * Indentations os_display_char, os_display_string, os_char_width and os_string_width must be able to cope with with characters 9 (paragraph indentation) and 11 (gap between two sentences). * Making the cursor [in]visible Two new interface routines: os_cursor_on and os_cursor_off. Note that the cursor need only be visible during input actions. * European characters First, new constants EURO_MIN (155) and EURO_MAX (223) have been added. Second, the array euro_substitute (STREAM.C) is no longer static. This might be helpful for any OS that cannot display European characters. * Tandy flag The interface is now responsible for setting the Tandy flag; the global variable option_tandy_bit has been removed. If your interface shall support the Tandy bit then you should add a line to os_init_screen that looks like if (h_version == V3 && user_wants_tandy_bit != 0) h_config |= CONFIG_TANDY; * Scrolling up and down os_scroll_area has got an additional argument giving the number of screen units to scroll. In theory, the area must scroll down when this value is negative. In practice, negative values don't happen. * Screen units instead of character grid positions Frotz is now able to work with screen units. You don't have to set the header entries "h_font_width" and "h_font_height" to 1 if you want to use pixels rather than character grid positions. In addition, if you are still using character grid positions, then you don't have to set these two variables at all (because they default to 1). Furthermore, os_set_font has got two additional pointer arguments: The font width and height must be stored in these variables. Once again, both values default to 1 if you don't set them at all. * File naming All arrays that store file names (script_name, command_name, save_name and auxilary_name) are no longer "static", just in case the interface wants to provide more intelligent default file names than "story.scr", "story.cmd" and so on. * Vanishing constants The constants LOWER_WINDOW (0), UPPER_WINDOW (1) and ROMAN_STYLE (0) have been removed. * Text style The specification of os_set_text_style has changed. You don't have to combine the flags of the old style with the flags of the new style as the new style contains all the flags that are currently active. In particular, Frotz takes care to select the FIXED_WIDTH_STYLE whenever the fixed font bit is set or when the upper window is active in V1-V5.