From a22b6e1490637370a16cb6df5b1511a855aa00cc Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 18 Sep 2011 11:48:00 +0200 Subject: [PATCH] Finished frotz backend :) --- backends/frotz/CMakeLists.txt | 3 + backends/frotz/dfrotz/CMakeLists.txt | 9 + backends/frotz/dfrotz/README | 2 + backends/frotz/{ => dfrotz/common}/buffer.c | 4 +- backends/frotz/{ => dfrotz/common}/err.c | 0 backends/frotz/{ => dfrotz/common}/fastmem.c | 2 +- backends/frotz/{ => dfrotz/common}/files.c | 10 +- backends/frotz/{ => dfrotz/common}/frotz.h | 45 +- backends/frotz/{ => dfrotz/common}/getopt.c | 0 backends/frotz/{ => dfrotz/common}/hotkey.c | 22 +- backends/frotz/{ => dfrotz/common}/input.c | 10 +- backends/frotz/dfrotz/common/main.c | 197 ++++++++ backends/frotz/{ => dfrotz/common}/math.c | 0 backends/frotz/{ => dfrotz/common}/object.c | 0 backends/frotz/{ => dfrotz/common}/process.c | 2 +- backends/frotz/{ => dfrotz/common}/quetzal.c | 4 +- backends/frotz/{ => dfrotz/common}/random.c | 0 backends/frotz/{ => dfrotz/common}/redirect.c | 2 +- backends/frotz/{ => dfrotz/common}/screen.c | 18 +- backends/frotz/{ => dfrotz/common}/setup.h | 0 backends/frotz/{ => dfrotz/common}/sound.c | 4 +- backends/frotz/{ => dfrotz/common}/stream.c | 14 +- backends/frotz/{ => dfrotz/common}/table.c | 0 backends/frotz/{ => dfrotz/common}/text.c | 9 +- backends/frotz/{ => dfrotz/common}/variable.c | 0 backends/frotz/{ => dfrotz/dumb}/dumb_frotz.h | 17 +- backends/frotz/{ => dfrotz/dumb}/dumb_init.c | 9 +- backends/frotz/{ => dfrotz/dumb}/dumb_input.c | 44 +- .../frotz/{ => dfrotz/dumb}/dumb_output.c | 71 ++- backends/frotz/{ => dfrotz/dumb}/dumb_pic.c | 2 +- backends/frotz/main.cpp | 437 +++++++++++------- backends/frotz/soundcard.h | 10 - spectrum/src/sample.cfg | 3 +- 33 files changed, 603 insertions(+), 347 deletions(-) create mode 100644 backends/frotz/dfrotz/CMakeLists.txt create mode 100644 backends/frotz/dfrotz/README rename backends/frotz/{ => dfrotz/common}/buffer.c (97%) rename backends/frotz/{ => dfrotz/common}/err.c (100%) rename backends/frotz/{ => dfrotz/common}/fastmem.c (99%) rename backends/frotz/{ => dfrotz/common}/files.c (97%) rename backends/frotz/{ => dfrotz/common}/frotz.h (96%) rename backends/frotz/{ => dfrotz/common}/getopt.c (100%) rename backends/frotz/{ => dfrotz/common}/hotkey.c (92%) rename backends/frotz/{ => dfrotz/common}/input.c (96%) create mode 100644 backends/frotz/dfrotz/common/main.c rename backends/frotz/{ => dfrotz/common}/math.c (100%) rename backends/frotz/{ => dfrotz/common}/object.c (100%) rename backends/frotz/{ => dfrotz/common}/process.c (99%) rename backends/frotz/{ => dfrotz/common}/quetzal.c (99%) rename backends/frotz/{ => dfrotz/common}/random.c (100%) rename backends/frotz/{ => dfrotz/common}/redirect.c (98%) rename backends/frotz/{ => dfrotz/common}/screen.c (98%) rename backends/frotz/{ => dfrotz/common}/setup.h (100%) rename backends/frotz/{ => dfrotz/common}/sound.c (98%) rename backends/frotz/{ => dfrotz/common}/stream.c (96%) rename backends/frotz/{ => dfrotz/common}/table.c (100%) rename backends/frotz/{ => dfrotz/common}/text.c (99%) rename backends/frotz/{ => dfrotz/common}/variable.c (100%) rename backends/frotz/{ => dfrotz/dumb}/dumb_frotz.h (72%) rename backends/frotz/{ => dfrotz/dumb}/dumb_init.c (98%) rename backends/frotz/{ => dfrotz/dumb}/dumb_input.c (92%) rename backends/frotz/{ => dfrotz/dumb}/dumb_output.c (91%) rename backends/frotz/{ => dfrotz/dumb}/dumb_pic.c (98%) delete mode 100644 backends/frotz/soundcard.h diff --git a/backends/frotz/CMakeLists.txt b/backends/frotz/CMakeLists.txt index 3275480c..82403ab7 100644 --- a/backends/frotz/CMakeLists.txt +++ b/backends/frotz/CMakeLists.txt @@ -1,4 +1,7 @@ cmake_minimum_required(VERSION 2.6) + +ADD_SUBDIRECTORY(dfrotz) + FILE(GLOB SRC *.c *.cpp) ADD_EXECUTABLE(spectrum_frotz_backend ${SRC}) diff --git a/backends/frotz/dfrotz/CMakeLists.txt b/backends/frotz/dfrotz/CMakeLists.txt new file mode 100644 index 00000000..3c1b722a --- /dev/null +++ b/backends/frotz/dfrotz/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.6) +FILE(GLOB SRC common/*.c dumb/*.c) + +ADD_EXECUTABLE(dfrotz ${SRC}) + +# target_link_libraries(dfrotz) + +INSTALL(TARGETS dfrotz RUNTIME DESTINATION bin) + diff --git a/backends/frotz/dfrotz/README b/backends/frotz/dfrotz/README new file mode 100644 index 00000000..3176a842 --- /dev/null +++ b/backends/frotz/dfrotz/README @@ -0,0 +1,2 @@ +This is patched version of dfrotz. frotz_backend won't work with dfrotz from +your distribution. \ No newline at end of file diff --git a/backends/frotz/buffer.c b/backends/frotz/dfrotz/common/buffer.c similarity index 97% rename from backends/frotz/buffer.c rename to backends/frotz/dfrotz/common/buffer.c index 86b9ab3a..298ac69c 100644 --- a/backends/frotz/buffer.c +++ b/backends/frotz/dfrotz/common/buffer.c @@ -38,7 +38,7 @@ static zchar prev_c = 0; void flush_buffer (void) { - static int locked = FALSE; + static bool locked = FALSE; /* Make sure we stop when flush_buffer is called from flush_buffer. Note that this is difficult to avoid as we might print a newline @@ -79,7 +79,7 @@ void flush_buffer (void) void print_char (zchar c) { - static int flag = FALSE; + static bool flag = FALSE; if (message || ostream_memory || enable_buffering) { diff --git a/backends/frotz/err.c b/backends/frotz/dfrotz/common/err.c similarity index 100% rename from backends/frotz/err.c rename to backends/frotz/dfrotz/common/err.c diff --git a/backends/frotz/fastmem.c b/backends/frotz/dfrotz/common/fastmem.c similarity index 99% rename from backends/frotz/fastmem.c rename to backends/frotz/dfrotz/common/fastmem.c index 72a0220f..fa23cfff 100644 --- a/backends/frotz/fastmem.c +++ b/backends/frotz/dfrotz/common/fastmem.c @@ -524,7 +524,7 @@ void storew (zword addr, zword value) void z_restart (void) { - static int first_restart = TRUE; + static bool first_restart = TRUE; flush_buffer (); diff --git a/backends/frotz/files.c b/backends/frotz/dfrotz/common/files.c similarity index 97% rename from backends/frotz/files.c rename to backends/frotz/dfrotz/common/files.c index 7a7df757..0e864d58 100644 --- a/backends/frotz/files.c +++ b/backends/frotz/dfrotz/common/files.c @@ -28,11 +28,11 @@ #define SEEK_END 2 #endif -extern void set_more_prompts (int); +extern void set_more_prompts (bool); -extern int is_terminator (zchar); +extern bool is_terminator (zchar); -extern int read_yes_or_no (const char *); +extern bool read_yes_or_no (const char *); char script_name[MAX_FILE_NAME + 1] = DEFAULT_SCRIPT_NAME; char command_name[MAX_FILE_NAME + 1] = DEFAULT_COMMAND_NAME; @@ -63,7 +63,7 @@ static FILE *pfp = NULL; void script_open (void) { - static int script_valid = FALSE; + static bool script_valid = FALSE; char new_name[MAX_FILE_NAME + 1]; @@ -325,7 +325,7 @@ void record_close (void) * */ -static void record_code (int c, int force_encoding) +static void record_code (int c, bool force_encoding) { if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) { diff --git a/backends/frotz/frotz.h b/backends/frotz/dfrotz/common/frotz.h similarity index 96% rename from backends/frotz/frotz.h rename to backends/frotz/dfrotz/common/frotz.h index 5a83b8ef..c7f27535 100644 --- a/backends/frotz/frotz.h +++ b/backends/frotz/dfrotz/common/frotz.h @@ -5,7 +5,7 @@ * */ -/* Unfortunately, frotz's int definition conflicts with that of curses. +/* Unfortunately, frotz's bool definition conflicts with that of curses. But since no os_* function uses it, it's safe to let the frotz core see this definition, but have the unix port see the curses version. */ @@ -13,10 +13,7 @@ #ifndef __UNIX_PORT_FILE #include - -#ifdef __cplusplus -extern "C" { -#endif +typedef int bool; #ifndef TRUE #define TRUE 1 @@ -355,12 +352,12 @@ extern zword frame_count; extern zword zargs[8]; extern int zargc; -extern int ostream_screen; -extern int ostream_script; -extern int ostream_memory; -extern int ostream_record; -extern int istream_replay; -extern int message; +extern bool ostream_screen; +extern bool ostream_script; +extern bool ostream_memory; +extern bool ostream_record; +extern bool istream_replay; +extern bool message; extern int cwin; extern int mwin; @@ -368,10 +365,10 @@ extern int mwin; extern int mouse_x; extern int mouse_y; -extern int enable_wrapping; -extern int enable_scripting; -extern int enable_scrolling; -extern int enable_buffering; +extern bool enable_wrapping; +extern bool enable_scripting; +extern bool enable_scrolling; +extern bool enable_buffering; extern char *option_zcode_path; /* dg */ @@ -578,7 +575,7 @@ void stream_mssg_off (void); void ret (zword); void store (zword); -void branch (int); +void branch (bool); void storeb (zword, zbyte); void storew (zword, zword); @@ -617,20 +614,4 @@ int os_string_width (const zchar *); void os_init_setup (void); int os_speech_output(const zchar *); -void init_buffer(void); -void init_process(void); -void init_sound(void); -void init_memory(void); -void init_undo(void); -void interpret(void); -void reset_memory(void); - -char *frotz_get_array(); -void frotz_reset_array(); -void dumb_show_screen(int show_cursor); - #include "setup.h" - -#ifdef __cplusplus -} -#endif diff --git a/backends/frotz/getopt.c b/backends/frotz/dfrotz/common/getopt.c similarity index 100% rename from backends/frotz/getopt.c rename to backends/frotz/dfrotz/common/getopt.c diff --git a/backends/frotz/hotkey.c b/backends/frotz/dfrotz/common/hotkey.c similarity index 92% rename from backends/frotz/hotkey.c rename to backends/frotz/dfrotz/common/hotkey.c index e115b478..bde1d63e 100644 --- a/backends/frotz/hotkey.c +++ b/backends/frotz/dfrotz/common/hotkey.c @@ -24,7 +24,7 @@ extern int restore_undo (void); extern int read_number (void); -extern int read_yes_or_no (const char *); +extern bool read_yes_or_no (const char *); extern void replay_open (void); extern void replay_close (void); @@ -40,7 +40,7 @@ extern void seed_random (int); * */ -static int hot_key_debugging (void) +static bool hot_key_debugging (void) { print_string ("Debugging options\n"); @@ -62,7 +62,7 @@ static int hot_key_debugging (void) * */ -static int hot_key_help (void) { +static bool hot_key_help (void) { print_string ("Help\n"); @@ -88,7 +88,7 @@ static int hot_key_help (void) { * */ -static int hot_key_playback (void) +static bool hot_key_playback (void) { print_string ("Playback on\n"); @@ -107,7 +107,7 @@ static int hot_key_playback (void) * */ -static int hot_key_recording (void) +static bool hot_key_recording (void) { if (istream_replay) { @@ -132,7 +132,7 @@ static int hot_key_recording (void) * */ -static int hot_key_seed (void) +static bool hot_key_seed (void) { print_string ("Seed random numbers\n"); @@ -151,7 +151,7 @@ static int hot_key_seed (void) * */ -static int hot_key_undo (void) +static bool hot_key_undo (void) { print_string ("Undo one turn\n"); @@ -181,7 +181,7 @@ static int hot_key_undo (void) * */ -static int hot_key_restart (void) +static bool hot_key_restart (void) { print_string ("New game\n"); @@ -202,7 +202,7 @@ static int hot_key_restart (void) * */ -static int hot_key_quit (void) +static bool hot_key_quit (void) { print_string ("Exit game\n"); @@ -224,12 +224,12 @@ static int hot_key_quit (void) * */ -int handle_hot_key (zchar key) +bool handle_hot_key (zchar key) { if (cwin == 0) { - int aborting; + bool aborting; aborting = FALSE; diff --git a/backends/frotz/input.c b/backends/frotz/dfrotz/common/input.c similarity index 96% rename from backends/frotz/input.c rename to backends/frotz/dfrotz/common/input.c index abc46b01..e4dad62d 100644 --- a/backends/frotz/input.c +++ b/backends/frotz/dfrotz/common/input.c @@ -22,10 +22,10 @@ extern int save_undo (void); -extern zchar stream_read_key (zword, zword, int); -extern zchar stream_read_input (int, zchar *, zword, zword, int, int); +extern zchar stream_read_key (zword, zword, bool); +extern zchar stream_read_input (int, zchar *, zword, zword, bool, bool); -extern void tokenise_line (zword, zword, zword, int); +extern void tokenise_line (zword, zword, zword, bool); /* * is_terminator @@ -34,7 +34,7 @@ extern void tokenise_line (zword, zword, zword, int); * */ -int is_terminator (zchar key) +bool is_terminator (zchar key) { if (key == ZC_TIME_OUT) @@ -90,7 +90,7 @@ void z_make_menu (void) * */ -int read_yes_or_no (const char *s) +bool read_yes_or_no (const char *s) { zchar key; diff --git a/backends/frotz/dfrotz/common/main.c b/backends/frotz/dfrotz/common/main.c new file mode 100644 index 00000000..f9486b0a --- /dev/null +++ b/backends/frotz/dfrotz/common/main.c @@ -0,0 +1,197 @@ +/* main.c - Frotz V2.40 main function + * Copyright (c) 1995-1997 Stefan Jokisch + * + * This file is part of Frotz. + * + * Frotz is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Frotz is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* + * This is an interpreter for Infocom V1 to V6 games. It also supports + * the recently defined V7 and V8 games. Please report bugs to + * + * s.jokisch@avu.de + * + */ + +#include "frotz.h" + +#ifndef MSDOS_16BIT +#define cdecl +#endif + +extern void interpret (void); +extern void init_memory (void); +extern void init_undo (void); +extern void reset_memory (void); + +/* Story file name, id number and size */ + +char *story_name = 0; + +enum story story_id = UNKNOWN; +long story_size = 0; + +/* Story file header data */ + +zbyte h_version = 0; +zbyte h_config = 0; +zword h_release = 0; +zword h_resident_size = 0; +zword h_start_pc = 0; +zword h_dictionary = 0; +zword h_objects = 0; +zword h_globals = 0; +zword h_dynamic_size = 0; +zword h_flags = 0; +zbyte h_serial[6] = { 0, 0, 0, 0, 0, 0 }; +zword h_abbreviations = 0; +zword h_file_size = 0; +zword h_checksum = 0; +zbyte h_interpreter_number = 0; +zbyte h_interpreter_version = 0; +zbyte h_screen_rows = 0; +zbyte h_screen_cols = 0; +zword h_screen_width = 0; +zword h_screen_height = 0; +zbyte h_font_height = 1; +zbyte h_font_width = 1; +zword h_functions_offset = 0; +zword h_strings_offset = 0; +zbyte h_default_background = 0; +zbyte h_default_foreground = 0; +zword h_terminating_keys = 0; +zword h_line_width = 0; +zbyte h_standard_high = 1; +zbyte h_standard_low = 0; +zword h_alphabet = 0; +zword h_extension_table = 0; +zbyte h_user_name[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +zword hx_table_size = 0; +zword hx_mouse_x = 0; +zword hx_mouse_y = 0; +zword hx_unicode_table = 0; + +/* Stack data */ + +zword stack[STACK_SIZE]; +zword *sp = 0; +zword *fp = 0; +zword frame_count = 0; + +/* IO streams */ + +bool ostream_screen = TRUE; +bool ostream_script = FALSE; +bool ostream_memory = FALSE; +bool ostream_record = FALSE; +bool istream_replay = FALSE; +bool message = FALSE; + +/* Current window and mouse data */ + +int cwin = 0; +int mwin = 0; + +int mouse_y = 0; +int mouse_x = 0; + +/* Window attributes */ + +bool enable_wrapping = FALSE; +bool enable_scripting = FALSE; +bool enable_scrolling = FALSE; +bool enable_buffering = FALSE; + +/* User options */ + +/* +int option_attribute_assignment = 0; +int option_attribute_testing = 0; +int option_context_lines = 0; +int option_object_locating = 0; +int option_object_movement = 0; +int option_left_margin = 0; +int option_right_margin = 0; +int option_ignore_errors = 0; +int option_piracy = 0; +int option_undo_slots = MAX_UNDO_SLOTS; +int option_expand_abbreviations = 0; +int option_script_cols = 80; +int option_save_quetzal = 1; +*/ + +int option_sound = 1; +char *option_zcode_path; + + +/* Size of memory to reserve (in bytes) */ + +long reserve_mem = 0; + +/* + * z_piracy, branch if the story file is a legal copy. + * + * no zargs used + * + */ + +void z_piracy (void) +{ + + branch (!f_setup.piracy); + +}/* z_piracy */ + +/* + * main + * + * Prepare and run the game. + * + */ + +int cdecl main (int argc, char *argv[]) +{ + + os_init_setup (); + + os_process_arguments (argc, argv); + + init_buffer (); + + init_err (); + + init_memory (); + + init_process (); + + init_sound (); + + os_init_screen (); + + init_undo (); + + z_restart (); + + interpret (); + + reset_memory (); + + os_reset_screen (); + + return 0; + +}/* main */ diff --git a/backends/frotz/math.c b/backends/frotz/dfrotz/common/math.c similarity index 100% rename from backends/frotz/math.c rename to backends/frotz/dfrotz/common/math.c diff --git a/backends/frotz/object.c b/backends/frotz/dfrotz/common/object.c similarity index 100% rename from backends/frotz/object.c rename to backends/frotz/dfrotz/common/object.c diff --git a/backends/frotz/process.c b/backends/frotz/dfrotz/common/process.c similarity index 99% rename from backends/frotz/process.c rename to backends/frotz/dfrotz/common/process.c index e067eb22..99ad82ca 100644 --- a/backends/frotz/process.c +++ b/backends/frotz/dfrotz/common/process.c @@ -446,7 +446,7 @@ void ret (zword value) * */ -void branch (int flag) +void branch (bool flag) { long pc; zword offset; diff --git a/backends/frotz/quetzal.c b/backends/frotz/dfrotz/common/quetzal.c similarity index 99% rename from backends/frotz/quetzal.c rename to backends/frotz/dfrotz/common/quetzal.c index 5d60ebca..f7ccacd7 100644 --- a/backends/frotz/quetzal.c +++ b/backends/frotz/dfrotz/common/quetzal.c @@ -99,7 +99,7 @@ static zword frames[STACK_SIZE/4+1]; (write_byte (fp, 0) && write_byte (fp, (run))) /* Read one word from file; return TRUE if OK. */ -static int read_word (FILE *f, zword *result) +static bool read_word (FILE *f, zword *result) { int a, b; @@ -111,7 +111,7 @@ static int read_word (FILE *f, zword *result) } /* Read one long from file; return TRUE if OK. */ -static int read_long (FILE *f, zlong *result) +static bool read_long (FILE *f, zlong *result) { int a, b, c, d; diff --git a/backends/frotz/random.c b/backends/frotz/dfrotz/common/random.c similarity index 100% rename from backends/frotz/random.c rename to backends/frotz/dfrotz/common/random.c diff --git a/backends/frotz/redirect.c b/backends/frotz/dfrotz/common/redirect.c similarity index 98% rename from backends/frotz/redirect.c rename to backends/frotz/dfrotz/common/redirect.c index be832d85..d81776db 100644 --- a/backends/frotz/redirect.c +++ b/backends/frotz/dfrotz/common/redirect.c @@ -40,7 +40,7 @@ static struct { * */ -void memory_open (zword table, zword xsize, int buffering) +void memory_open (zword table, zword xsize, bool buffering) { if (++depth < MAX_NESTING) { diff --git a/backends/frotz/screen.c b/backends/frotz/dfrotz/common/screen.c similarity index 98% rename from backends/frotz/screen.c rename to backends/frotz/dfrotz/common/screen.c index b9548414..713ec292 100644 --- a/backends/frotz/screen.c +++ b/backends/frotz/dfrotz/common/screen.c @@ -42,10 +42,10 @@ static struct { static int font_height = 1; static int font_width = 1; -static int input_redraw = FALSE; -static int more_prompts = TRUE; -static int discarding = FALSE; -static int cursor = TRUE; +static bool input_redraw = FALSE; +static bool more_prompts = TRUE; +static bool discarding = FALSE; +static bool cursor = TRUE; static int input_window = 0; @@ -157,7 +157,7 @@ static void reset_cursor (zword win) * */ -void set_more_prompts (int flag) +void set_more_prompts (bool flag) { if (flag && !more_prompts) @@ -439,7 +439,7 @@ void screen_erase_input (const zchar *buf) * */ -zchar console_read_input (int max, zchar *buf, zword timeout, int continued) +zchar console_read_input (int max, zchar *buf, zword timeout, bool continued) { zchar key; int i; @@ -795,7 +795,7 @@ void restart_screen (void) * */ -int validate_click (void) +bool validate_click (void) { if (mwin >= 0) { @@ -1156,7 +1156,7 @@ void z_picture_data (void) int height, width; int i; - int avail = os_picture_data (pic, &height, &width); + bool avail = os_picture_data (pic, &height, &width); for (i = 0; mapper[i].story_id != UNKNOWN; i++) @@ -1581,7 +1581,7 @@ void z_show_status (void) zword global2; zword addr; - int brief = FALSE; + bool brief = FALSE; /* One V5 game (Wishbringer Solid Gold) contains this opcode by accident, so just return if the version number does not fit */ diff --git a/backends/frotz/setup.h b/backends/frotz/dfrotz/common/setup.h similarity index 100% rename from backends/frotz/setup.h rename to backends/frotz/dfrotz/common/setup.h diff --git a/backends/frotz/sound.c b/backends/frotz/dfrotz/common/sound.c similarity index 98% rename from backends/frotz/sound.c rename to backends/frotz/dfrotz/common/sound.c index 04c61119..ea0e3570 100644 --- a/backends/frotz/sound.c +++ b/backends/frotz/dfrotz/common/sound.c @@ -36,8 +36,8 @@ static zword routine = 0; static int next_sample = 0; static int next_volume = 0; -static int locked = FALSE; -static int playing = FALSE; +static bool locked = FALSE; +static bool playing = FALSE; /* * init_sound diff --git a/backends/frotz/stream.c b/backends/frotz/dfrotz/common/stream.c similarity index 96% rename from backends/frotz/stream.c rename to backends/frotz/dfrotz/common/stream.c index ce735260..4ccb4445 100644 --- a/backends/frotz/stream.c +++ b/backends/frotz/dfrotz/common/stream.c @@ -20,13 +20,13 @@ #include "frotz.h" -extern int handle_hot_key (zchar); +extern bool handle_hot_key (zchar); -extern int validate_click (void); +extern bool validate_click (void); extern void replay_open (void); extern void replay_close (void); -extern void memory_open (zword, zword, int); +extern void memory_open (zword, zword, bool); extern void memory_close (void); extern void record_open (void); extern void record_close (void); @@ -55,7 +55,7 @@ extern void screen_mssg_off (void); extern zchar replay_read_key (void); extern zchar replay_read_input (zchar *); extern zchar console_read_key (zword); -extern zchar console_read_input (int, zchar *, zword, int); +extern zchar console_read_input (int, zchar *, zword, bool); extern int direct_call (zword); @@ -232,7 +232,7 @@ void z_input_stream (void) */ zchar stream_read_key ( zword timeout, zword routine, - int hot_keys ) + bool hot_keys ) { zchar key = ZC_BAD; @@ -296,8 +296,8 @@ continue_input: zchar stream_read_input ( int max, zchar *buf, zword timeout, zword routine, - int hot_keys, - int no_scripting ) + bool hot_keys, + bool no_scripting ) { zchar key = ZC_BAD; diff --git a/backends/frotz/table.c b/backends/frotz/dfrotz/common/table.c similarity index 100% rename from backends/frotz/table.c rename to backends/frotz/dfrotz/common/table.c diff --git a/backends/frotz/text.c b/backends/frotz/dfrotz/common/text.c similarity index 99% rename from backends/frotz/text.c rename to backends/frotz/dfrotz/common/text.c index f9a3d7a0..8145cfea 100644 --- a/backends/frotz/text.c +++ b/backends/frotz/dfrotz/common/text.c @@ -572,7 +572,6 @@ void z_print_addr (void) void z_print_char (void) { - print_char (translate_from_zscii (zargs[0])); }/* z_print_char */ @@ -589,7 +588,7 @@ void z_print_form (void) zword count; zword addr = zargs[0]; - int first = TRUE; + bool first = TRUE; for (;;) { @@ -791,7 +790,7 @@ static zword lookup_text (int padding, zword dct) int entry_number; int lower, upper; int i; - int sorted; + bool sorted; encode_text (padding); @@ -873,7 +872,7 @@ static zword lookup_text (int padding, zword dct) * */ -static void tokenise_text (zword text, zword length, zword from, zword parse, zword dct, int flag) +static void tokenise_text (zword text, zword length, zword from, zword parse, zword dct, bool flag) { zword addr; zbyte token_max, token_count; @@ -911,7 +910,7 @@ static void tokenise_text (zword text, zword length, zword from, zword parse, zw * */ -void tokenise_line (zword text, zword token, zword dct, int flag) +void tokenise_line (zword text, zword token, zword dct, bool flag) { zword addr1; zword addr2; diff --git a/backends/frotz/variable.c b/backends/frotz/dfrotz/common/variable.c similarity index 100% rename from backends/frotz/variable.c rename to backends/frotz/dfrotz/common/variable.c diff --git a/backends/frotz/dumb_frotz.h b/backends/frotz/dfrotz/dumb/dumb_frotz.h similarity index 72% rename from backends/frotz/dumb_frotz.h rename to backends/frotz/dfrotz/dumb/dumb_frotz.h index 0ef49630..b965412a 100644 --- a/backends/frotz/dumb_frotz.h +++ b/backends/frotz/dfrotz/dumb/dumb_frotz.h @@ -6,7 +6,7 @@ * Copyright 1997, 1998 Alembic Petrofsky . * Any use permitted provided this notice stays intact. */ -#include "frotz.h" +#include "../common/frotz.h" #include #include #include @@ -14,23 +14,24 @@ #include #include +#define VERSION "1.0" + /* from ../common/setup.h */ extern f_setup_t f_setup; -extern void spectrum_get_line(char *s); /* From input.c. */ -int is_terminator (zchar); +bool is_terminator (zchar); /* dumb-input.c */ -int dumb_handle_setting(const char *setting, int show_cursor, int startup); +bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup); void dumb_init_input(void); /* dumb-output.c */ void dumb_init_output(void); -int dumb_output_handle_setting(const char *setting, int show_cursor, - int startup); -void dumb_show_screen(int show_cursor); -void dumb_show_prompt(int show_cursor, char line_type); +bool dumb_output_handle_setting(const char *setting, bool show_cursor, + bool startup); +void dumb_show_screen(bool show_cursor); +void dumb_show_prompt(bool show_cursor, char line_type); void dumb_dump_screen(void); void dumb_display_user_input(char *); void dumb_discard_old_input(int num_chars); diff --git a/backends/frotz/dumb_init.c b/backends/frotz/dfrotz/dumb/dumb_init.c similarity index 98% rename from backends/frotz/dumb_init.c rename to backends/frotz/dfrotz/dumb/dumb_init.c index 32f1e202..7ed8dec0 100644 --- a/backends/frotz/dumb_init.c +++ b/backends/frotz/dfrotz/dumb/dumb_init.c @@ -7,8 +7,6 @@ #include "dumb_frotz.h" -#define VERSION 1.0 - f_setup_t f_setup; #define INFORMATION "\ @@ -96,16 +94,15 @@ error: }/* zgetopt */ static int user_screen_width = 75; -static int user_screen_height = 100; +static int user_screen_height = 24; static int user_interpreter_number = -1; static int user_random_seed = -1; static int user_tandy_bit = 0; static char *graphics_filename = NULL; -static int plain_ascii = FALSE; +static bool plain_ascii = FALSE; void os_process_arguments(int argc, char *argv[]) { - return; int c; /* Parse the options */ @@ -198,7 +195,7 @@ void os_restart_game (int stage) {} void os_fatal (const char *s) { fprintf(stderr, "\nFatal error: %s\n", s); -// exit(1); + exit(1); } FILE *os_path_open(const char *name, const char *mode) diff --git a/backends/frotz/dumb_input.c b/backends/frotz/dfrotz/dumb/dumb_input.c similarity index 92% rename from backends/frotz/dumb_input.c rename to backends/frotz/dfrotz/dumb/dumb_input.c index ebbf1129..9fcfb78c 100644 --- a/backends/frotz/dumb_input.c +++ b/backends/frotz/dfrotz/dumb/dumb_input.c @@ -54,7 +54,7 @@ static char runtime_usage[] = ; static float speed = 1; -static int do_more_prompts = FALSE; +static bool do_more_prompts = FALSE; enum input_type { INPUT_CHAR, @@ -81,7 +81,19 @@ static int xgetchar(void) * other places where I'm not so careful). */ static void getline_(char *s) { - spectrum_get_line(s); + fflush(stdout); + int c; + char *p = s; + while (p < s + INPUT_BUFFER_SIZE - 1) + if ((*p++ = xgetchar()) == '\n') { + *p = '\0'; + return; + } + p[-1] = '\n'; + p[0] = '\0'; + while ((c = xgetchar()) != '\n') + ; + printf("Line too long, truncated to %s\n", s - INPUT_BUFFER_SIZE); } /* Translate in place all the escape characters in s. */ @@ -131,7 +143,7 @@ static int time_ahead = 0; * a previous call to dumb_read_line. * Returns TRUE if we should timeout rather than use the read-ahead. * (because the user is further ahead than the timeout). */ -static int check_timeout(int timeout) +static bool check_timeout(int timeout) { if ((timeout == 0) || (timeout > time_ahead)) time_ahead = 0; @@ -141,13 +153,13 @@ static int check_timeout(int timeout) } /* If val is '0' or '1', set *var accordingly, otherwise toggle it. */ -static void toggle(int *var, char val) +static void toggle(bool *var, char val) { *var = val == '1' || (val != '0' && !*var); } /* Handle input-related user settings and call dumb_output_handle_setting. */ -int dumb_handle_setting(const char *setting, int show_cursor, int startup) +bool dumb_handle_setting(const char *setting, bool show_cursor, bool startup) { if (!strncmp(setting, "sf", 2)) { speed = atof(&setting[2]); @@ -169,12 +181,12 @@ int dumb_handle_setting(const char *setting, int show_cursor, int startup) * (that isn't the start of a special character)), and write the * first non-command to s. * Return true if timed-out. */ -static int dumb_read_line(char *s, char *prompt, int show_cursor, +static bool dumb_read_line(char *s, char *prompt, bool show_cursor, int timeout, enum input_type type, zchar *continued_line_chars) { time_t start_time; - + if (timeout) { if (time_ahead >= timeout) { time_ahead -= timeout; @@ -185,6 +197,7 @@ static int dumb_read_line(char *s, char *prompt, int show_cursor, } time_ahead = 0; + dumb_show_screen(show_cursor); for (;;) { char *command; if (prompt) @@ -284,7 +297,7 @@ static char read_key_buffer[INPUT_BUFFER_SIZE]; /* Similar. Useful for using function key abbreviations. */ static char read_line_buffer[INPUT_BUFFER_SIZE]; -zchar os_read_key (int timeout, int show_cursor) +zchar os_read_key (int timeout, bool show_cursor) { char c; int timed_out; @@ -318,7 +331,7 @@ zchar os_read_line (int max, zchar *buf, int timeout, int width, int continued) { char *p; int terminator; - static int timed_out_last_time; + static bool timed_out_last_time; int timed_out; /* Discard any keys read for single key input. */ @@ -370,7 +383,6 @@ zchar os_read_line (int max, zchar *buf, int timeout, int width, int continued) int os_read_file_name (char *file_name, const char *default_name, int flag) { - return FALSE; char buf[INPUT_BUFFER_SIZE], prompt[INPUT_BUFFER_SIZE]; FILE *fp; @@ -384,12 +396,12 @@ int os_read_file_name (char *file_name, const char *default_name, int flag) strcpy (file_name, buf[0] ? buf : default_name); /* Warn if overwriting a file. */ - if ((flag == FILE_SAVE || flag == FILE_SAVE_AUX || flag == FILE_RECORD) - && ((fp = fopen(file_name, "rb")) != NULL)) { - fclose (fp); - dumb_read_misc_line(buf, "Overwrite existing file? "); - return(tolower(buf[0]) == 'y'); - } +// if ((flag == FILE_SAVE || flag == FILE_SAVE_AUX || flag == FILE_RECORD) +// && ((fp = fopen(file_name, "rb")) != NULL)) { +// fclose (fp); +// dumb_read_misc_line(buf, "Overwrite existing file? "); +// return(tolower(buf[0]) == 'y'); +// } return TRUE; } diff --git a/backends/frotz/dumb_output.c b/backends/frotz/dfrotz/dumb/dumb_output.c similarity index 91% rename from backends/frotz/dumb_output.c rename to backends/frotz/dfrotz/dumb/dumb_output.c index a9cc83c1..1faafea9 100644 --- a/backends/frotz/dumb_output.c +++ b/backends/frotz/dfrotz/dumb/dumb_output.c @@ -9,11 +9,11 @@ f_setup_t f_setup; -static int show_line_numbers = FALSE; -static int show_line_types = -1; -static int show_pictures = TRUE; -static int visual_bell = TRUE; -static int plain_ascii = FALSE; +static bool show_line_numbers = FALSE; +static bool show_line_types = -1; +static bool show_pictures = TRUE; +static bool visual_bell = TRUE; +static bool plain_ascii = FALSE; static char latin1_to_ascii[] = " ! c L >o< Y | S '' C a << not - R _ " @@ -72,24 +72,6 @@ static char *dumb_changes_row(int r) return screen_changes + r * h_screen_cols; } -static char array[15000]; -static char *array_ptr = &array; - -char *frotz_get_array() { - return &array; -} - -void frotz_reset_array() { - array_ptr = &array; - *array_ptr = 0; -} - -static void myputchar(char c) { - *array_ptr = c; - array_ptr++; - *array_ptr = 0; -} - int os_char_width (zchar z) { if (plain_ascii && z >= ZC_LATIN1_MIN && z <= ZC_LATIN1_MAX) { @@ -257,26 +239,26 @@ static void show_cell(cell cel) char c = cell_char(cel); switch (cell_style(cel)) { case 0: - myputchar(c); + putchar(c); break; case PICTURE_STYLE: - myputchar(show_pictures ? c : ' '); + putchar(show_pictures ? c : ' '); break; case REVERSE_STYLE: if (c == ' ') - myputchar(rv_blank_char); + putchar(rv_blank_char); else switch (rv_mode) { - case RV_NONE: myputchar(c); break; - case RV_CAPS: myputchar(toupper(c)); break; - case RV_UNDERLINE: myputchar('_'); myputchar('\b'); myputchar(c); break; - case RV_DOUBLESTRIKE: myputchar(c); myputchar('\b'); myputchar(c); break; + case RV_NONE: putchar(c); break; + case RV_CAPS: putchar(toupper(c)); break; + case RV_UNDERLINE: putchar('_'); putchar('\b'); putchar(c); break; + case RV_DOUBLESTRIKE: putchar(c); putchar('\b'); putchar(c); break; } break; } } -static int will_print_blank(cell c) +static bool will_print_blank(cell c) { return (((cell_style(c) == PICTURE_STYLE) && !show_pictures) || ((cell_char(c) == ' ') @@ -288,10 +270,10 @@ static void show_line_prefix(int row, char c) if (show_line_numbers) printf((row == -1) ? ".." : "%02d", (row + 1) % 100); if (show_line_types) - myputchar(c); + putchar(c); /* Add a separator char (unless there's nothing to separate). */ if (show_line_numbers || show_line_types) - myputchar(' '); + putchar(' '); } /* Print a row to stdout. */ @@ -311,13 +293,12 @@ static void show_row(int r) for (c = 0; c <= last; c++) show_cell(dumb_row(r)[c]); } - myputchar('\n'); + putchar('\n'); } /* Print the part of the cursor row before the cursor. */ -void dumb_show_prompt(int show_cursor, char line_type) +void dumb_show_prompt(bool show_cursor, char line_type) { -return; int i; show_line_prefix(show_cursor ? cursor_row : -1, line_type); if (show_cursor) @@ -332,7 +313,7 @@ static void mark_all_unchanged(void) /* Check if a cell is a blank or will display as one. * (Used to help decide if contents are worth printing.) */ -static int is_blank(cell c) +static bool is_blank(cell c) { return ((cell_char(c) == ' ') || ((cell_style(c) == PICTURE_STYLE) && !show_pictures)); @@ -345,11 +326,11 @@ static int is_blank(cell c) * last nonblank character on the last line that would be shown, then * don't show that line (because it will be redundant with the prompt * line just below it). */ -void dumb_show_screen(int show_cursor) +void dumb_show_screen(bool show_cursor) { int r, c, first, last; char changed_rows[0x100]; - printf("show_screen\n"); + /* Easy case */ if (compression_mode == COMPRESSION_NONE) { for (r = hide_lines; r < h_screen_rows; r++) @@ -434,7 +415,7 @@ void os_beep (int volume) if (visual_bell) printf("[%s-PITCHED BEEP]\n", (volume == 1) ? "HIGH" : "LOW"); else - myputchar('\a'); /* so much for dumb. */ + putchar('\a'); /* so much for dumb. */ } @@ -447,13 +428,13 @@ void os_stop_sample (int a) {} /* if val is '0' or '1', set *var accordingly, else toggle it. */ -static void toggle(int *var, char val) +static void toggle(bool *var, char val) { *var = val == '1' || (val != '0' && !*var); } -int dumb_output_handle_setting(const char *setting, int show_cursor, - int startup) +bool dumb_output_handle_setting(const char *setting, bool show_cursor, + bool startup) { char *p; int i; @@ -504,7 +485,7 @@ int dumb_output_handle_setting(const char *setting, int show_cursor, rv_names[rv_mode], rv_blank_char); for (p = "sample reverse text"; *p; p++) show_cell(make_cell(REVERSE_STYLE, *p)); - myputchar('\n'); + putchar('\n'); for (i = 0; i < screen_cells; i++) screen_changes[i] = (cell_style(screen_data[i]) == REVERSE_STYLE); dumb_show_screen(show_cursor); @@ -521,7 +502,7 @@ int dumb_output_handle_setting(const char *setting, int show_cursor, rv_names[rv_mode], rv_blank_char); for (p = "sample reverse text"; *p; p++) show_cell(make_cell(REVERSE_STYLE, *p)); - myputchar('\n'); + putchar('\n'); } else return FALSE; return TRUE; diff --git a/backends/frotz/dumb_pic.c b/backends/frotz/dfrotz/dumb/dumb_pic.c similarity index 98% rename from backends/frotz/dumb_pic.c rename to backends/frotz/dfrotz/dumb/dumb_pic.c index 33eab037..c309522c 100644 --- a/backends/frotz/dumb_pic.c +++ b/backends/frotz/dfrotz/dumb/dumb_pic.c @@ -101,7 +101,7 @@ static int z_num_to_index(int n) return -1; } -int os_picture_data(int num, int *height, int *width) +bool os_picture_data(int num, int *height, int *width) { int index; diff --git a/backends/frotz/main.cpp b/backends/frotz/main.cpp index 2b6af624..2fb06551 100644 --- a/backends/frotz/main.cpp +++ b/backends/frotz/main.cpp @@ -10,162 +10,139 @@ #include "transport/config.h" #include "transport/networkplugin.h" -#include "frotz.h" - -#ifndef MSDOS_16BIT -#define cdecl -#endif - +#include +#include "unistd.h" +#include "signal.h" +#include "sys/wait.h" +#include "sys/signal.h" Swift::SimpleEventLoop *loop_; -extern "C" void spectrum_get_line(char *s); - -char input[15000]; - -void send_array(); - -void spectrum_get_line(char *s) { - std::cout << "running event loop\n"; - dumb_show_screen(FALSE); - send_array(); -// while(strlen(input) == 0) { - loop_->run(); -// } - strcpy(s, input); - strcpy(input, ""); - std::cout << "got message " << s << "\n"; -} - using namespace boost::program_options; using namespace Transport; -extern void interpret (void); -extern void init_memory (void); -extern void init_undo (void); -extern void reset_memory (void); - -/* Story file name, id number and size */ - -char *story_name = "zork.z5"; - -enum story story_id = UNKNOWN; -long story_size = 0; - -/* Story file header data */ - -zbyte h_version = 0; -zbyte h_config = 0; -zword h_release = 0; -zword h_resident_size = 0; -zword h_start_pc = 0; -zword h_dictionary = 0; -zword h_objects = 0; -zword h_globals = 0; -zword h_dynamic_size = 0; -zword h_flags = 0; -zbyte h_serial[6] = { 0, 0, 0, 0, 0, 0 }; -zword h_abbreviations = 0; -zword h_file_size = 0; -zword h_checksum = 0; -zbyte h_interpreter_number = 0; -zbyte h_interpreter_version = 0; -zbyte h_screen_rows = 0; -zbyte h_screen_cols = 0; -zword h_screen_width = 0; -zword h_screen_height = 0; -zbyte h_font_height = 1; -zbyte h_font_width = 1; -zword h_functions_offset = 0; -zword h_strings_offset = 0; -zbyte h_default_background = 0; -zbyte h_default_foreground = 0; -zword h_terminating_keys = 0; -zword h_line_width = 0; -zbyte h_standard_high = 1; -zbyte h_standard_low = 0; -zword h_alphabet = 0; -zword h_extension_table = 0; -zbyte h_user_name[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -zword hx_table_size = 0; -zword hx_mouse_x = 0; -zword hx_mouse_y = 0; -zword hx_unicode_table = 0; - -/* Stack data */ - -zword stack[STACK_SIZE]; -zword *sp = 0; -zword *fp = 0; -zword frame_count = 0; - -/* IO streams */ - -int ostream_screen = TRUE; -int ostream_script = FALSE; -int ostream_memory = FALSE; -int ostream_record = FALSE; -int istream_replay = FALSE; -int message = FALSE; - -/* Current window and mouse data */ - -int cwin = 0; -int mwin = 0; - -int mouse_y = 0; -int mouse_x = 0; - -/* Window attributes */ - -int enable_wrapping = FALSE; -int enable_scripting = FALSE; -int enable_scrolling = FALSE; -int enable_buffering = FALSE; - -/* User options */ - -/* -int option_attribute_assignment = 0; -int option_attribute_testing = 0; -int option_context_lines = 0; -int option_object_locating = 0; -int option_object_movement = 0; -int option_left_margin = 0; -int option_right_margin = 0; -int option_ignore_errors = 0; -int option_piracy = 0; -int option_undo_slots = MAX_UNDO_SLOTS; -int option_expand_abbreviations = 0; -int option_script_cols = 80; -int option_save_quetzal = 1; -*/ - -int option_sound = 1; -char *option_zcode_path; - - -/* Size of memory to reserve (in bytes) */ - -long reserve_mem = 0; - -/* - * z_piracy, branch if the story file is a legal copy. - * - * no zargs used - * - */ - -void z_piracy (void) -{ - - branch (!f_setup.piracy); - -}/* z_piracy */ - class FrotzNetworkPlugin; FrotzNetworkPlugin * np = NULL; +#define PARENT_READ p.readpipe[0] +#define CHILD_WRITE p.readpipe[1] +#define CHILD_READ p.writepipe[0] +#define PARENT_WRITE p.writepipe[1] + +typedef struct dfrotz_ { + pid_t pid; + std::string game; + int readpipe[2]; + int writepipe[2]; +} dfrotz; + +using namespace boost::filesystem; + +static const char *howtoplay = "To move around, just type the direction you want to go. Directions can be\n" +"abbreviated: NORTH to N, SOUTH to S, EAST to E, WEST to W, NORTHEAST to\n" +"NE, NORTHWEST to NW, SOUTHEAST to SE, SOUTHWEST to SW, UP to U, and DOWN\n" +"to D. IN and OUT will also work in certain places.\n" +"\n" +"There are many differnet kinds of sentences used in Interactive Fiction.\n" +"Here are some examples:\n" +"\n" +"> WALK TO THE NORTH\n" +"> WEST\n" +"> NE\n" +"> DOWN\n" +"> TAKE THE BIRDCAGE\n" +"> READ ABOUT DIMWIT FLATHEAD\n" +"> LOOK UP MEGABOZ IN THE ENCYCLOPEDIA\n" +"> LIE DOWN IN THE PINK SOFA\n" +"> EXAMINE THE SHINY COIN\n" +"> PUT THE RUSTY KEY IN THE CARDBOARD BOX\n" +"> SHOW MY BOW TIE TO THE BOUNCER\n" +"> HIT THE CRAWLING CRAB WITH THE GIANT NUTCRACKER\n" +"> ASK THE COWARDLY KING ABOUT THE CROWN JEWELS\n" +"\n" +"You can use multiple objects with certain verbs if you separate them by\n" +"the word \"AND\" or by a comma. Here are some examples:\n" +"\n" +"> TAKE THE BOOK AND THE FROG\n" +"> DROP THE JAR OF PEANUT BUTTER, THE SPOON, AND THE LEMMING FOOD\n" +"> PUT THE EGG AND THE PENCIL IN THE CABINET\n" +"\n" +"You can include several inputs on one line if you separate them by the\n" +"word \"THEN\" or by a period. Each input will be handled in order, as\n" +"though you had typed them individually at seperate prompts. For example,\n" +"you could type all of the following at once, before pressing the ENTER (or\n" +"RETURN) key:\n" +"\n" +"> TURN ON THE LIGHT. TAKE THE BOOK THEN READ ABOUT THE JESTER IN THE BOOK\n" +"\n" +"If the story doesn't understand one of the sentences on your input line,\n" +"or if an unusual event occurs, it will ignore the rest of your input line.\n" +"\n" +"The words \"IT\" and \"ALL\" can be very useful. For example:\n" +"\n" +"> EXAMINE THE APPLE. TAKE IT. EAT IT\n" +"> CLOSE THE HEAVY METAL DOOR. LOCK IT\n" +"> PICK UP THE GREEN BOOT. SMELL IT. PUT IT ON.\n" +"> TAKE ALL\n" +"> TAKE ALL THE TOOLS\n" +"> DROP ALL THE TOOLS EXCEPT THE WRENCH AND MINIATURE HAMMER\n" +"> TAKE ALL FROM THE CARTON\n" +"> GIVE ALL BUT THE RUBY SLIPPERS TO THE WICKED WITCH\n" +"\n" +"The word \"ALL\" refers to every visible object except those inside\n" +"something else. If there were an apple on the ground and an orange inside\n" +"a cabinet, \"TAKE ALL\" would take the apple but not the orange.\n" +"\n" +"There are three kinds of questions you can ask: \"WHERE IS (something)\",\n" +"\"WHAT IS (something)\", and \"WHO IS (someone)\". For example:\n" +"\n" +"> WHO IS LORD DIMWIT?\n" +"> WHAT IS A GRUE?\n" +"> WHERE IS EVERYBODY?\n" +"\n" +"When you meet intelligent creatures, you can talk to them by typing their\n" +"name, then a comma, then whatever you want to say to them. Here are some\n" +"examples:\n" +"\n" +"> JESTER, HELLO\n" +"> GUSTAR WOOMAX, TELL ME ABOUT THE COCONUT\n" +"> UNCLE OTTO, GIVE ME YOUR WALLET\n" +"> HORSE, WHERE IS YOUR SADDLE?\n" +"> BOY, RUN HOME THEN CALL THE POLICE\n" +"> MIGHTY WIZARD, TAKE THIS POISONED APPLE. EAT IT\n" +"\n" +"Notice that in the last two examples, you are giving the characters more\n" +"than one command on the same input line. Keep in mind, however, that many\n" +"creatures don't care for idle chatter; your actions will speak louder than\n" +"your words. \n"; + + +static void start_dfrotz(dfrotz &p, const std::string &game) { +// p.writepipe[0] = -1; + + if (pipe(p.readpipe) < 0 || pipe(p.writepipe) < 0) { + } + + std::cout << "dfrotz -p " << game << "\n"; + + if ((p.pid = fork()) < 0) { + /* FATAL: cannot fork child */ + } + else if (p.pid == 0) { + close(PARENT_WRITE); + close(PARENT_READ); + + dup2(CHILD_READ, 0); close(CHILD_READ); + dup2(CHILD_WRITE, 1); close(CHILD_WRITE); + + execlp("dfrotz", "-p", game.c_str(), NULL); + + } + else { + close(CHILD_READ); + close(CHILD_WRITE); + } +} + class FrotzNetworkPlugin : public NetworkPlugin { public: FrotzNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin(loop, host, port) { @@ -173,22 +150,128 @@ class FrotzNetworkPlugin : public NetworkPlugin { } void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { - m_user = user; np->handleConnected(user); Swift::StatusShow status; - np->handleBuddyChanged(user, "zork", "Zork", "Games", status.getType()); - sleep(1); - np->handleMessage(np->m_user, "zork", first_msg); + np->handleBuddyChanged(user, "zcode", "ZCode", "ZCode", status.getType()); +// sleep(1); +// np->handleMessage(np->m_user, "zork", first_msg); } void handleLogoutRequest(const std::string &user, const std::string &legacyName) { - exit(0); + if (games.find(user) != games.end()) { + kill(games[user].pid, SIGTERM); + games.erase(user); + } +// exit(0); + } + + void readMessage(const std::string &user) { + static char buf[15000]; + buf[0] = 0; + int repeated = 0; + while (strlen(buf) == 0) { + ssize_t len = read(games[user].readpipe[0], buf, 15000); + if (len > 0) { + buf[len] = 0; + } + usleep(1000); + repeated++; + if (repeated > 30) + return; + } + np->handleMessage(user, "zcode", buf); + + std::string msg = "save\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + + msg = user + "_" + games[user].game + ".save\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + ignoreMessage(user); + } + + void ignoreMessage(const std::string &user) { + usleep(1000000); + static char buf[15000]; + buf[0] = 0; + int repeated = 0; + while (strlen(buf) == 0) { + ssize_t len = read(games[user].readpipe[0], buf, 15000); + if (len > 0) { + buf[len] = 0; + } + usleep(1000); + repeated++; + if (repeated > 30) + return; + } + + std::cout << "ignoring: " << buf << "\n"; + } + + std::vector getGames() { + std::vector games; + path p("."); + directory_iterator end_itr; + for (directory_iterator itr(p); itr != end_itr; ++itr) { + if (extension(itr->path()) == ".z5") { + games.push_back(itr->path().leaf().string()); + } + } + return games; } void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) { - std::string msg = message + "\n"; - strcpy(input, msg.c_str()); - loop_->stop(); + if (message.find("start") == 0) { + std::string game = message.substr(6); + std::vector lst = getGames(); + if (std::find(lst.begin(), lst.end(), game) == lst.end()) { + np->handleMessage(user, "zcode", "Unknown game"); + return; + } + np->handleMessage(user, "zcode", "Starting the game"); + + dfrotz d; + d.game = game; + start_dfrotz(d, game); + games[user] = d; + fcntl(games[user].readpipe[0], F_SETFL, O_NONBLOCK); + + if (boost::filesystem::exists(user + "_" + games[user].game + ".save")) { + + std::string msg = "restore\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + + msg = user + "_" + games[user].game + ".save\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + + ignoreMessage(user); + + msg = "l\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + } + + readMessage(user); + } + else if (message == "stop" && games.find(user) != games.end()) { + kill(games[user].pid, SIGTERM); + games.erase(user); + np->handleMessage(user, "zcode", "Game stopped"); + } + else if (message == "howtoplay") { + np->handleMessage(user, "zcode", howtoplay); + } + else if (games.find(user) != games.end()) { + std::string msg = message + "\n"; + write(games[user].writepipe[1], msg.c_str(), msg.size()); + readMessage(user); + } + else { + std::string games; + BOOST_FOREACH(const std::string &game, getGames()) { + games += game + "\n"; + } + np->handleMessage(user, "zcode", "Games are saved/loaded automatically. Use \"restart\" to restart existing game. Emulator commands are:\nstart \nstop\nhowtoplay\n\nList of games:\n" + games); + } } void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { @@ -197,25 +280,38 @@ class FrotzNetworkPlugin : public NetworkPlugin { void handleLeaveRoomRequest(const std::string &user, const std::string &room) { } - std::string m_user; + std::map games; std::string first_msg; private: Config *config; }; -void send_array() { - if (np->first_msg.empty()) - np->first_msg = frotz_get_array(); - else - np->handleMessage(np->m_user, "zork", frotz_get_array()); - frotz_reset_array(); +static void spectrum_sigchld_handler(int sig) +{ + int status; + pid_t pid; + + do { + pid = waitpid(-1, &status, WNOHANG); + } while (pid != 0 && pid != (pid_t)-1); + + if ((pid == (pid_t) - 1) && (errno != ECHILD)) { + char errmsg[BUFSIZ]; + snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid); + perror(errmsg); + } } + int main (int argc, char* argv[]) { std::string host; int port; + if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) { + std::cout << "SIGCHLD handler can't be set\n"; + return -1; + } boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nAllowed options"); desc.add_options() @@ -264,20 +360,7 @@ int main (int argc, char* argv[]) { Swift::SimpleEventLoop eventLoop; loop_ = &eventLoop; np = new FrotzNetworkPlugin(&config, &eventLoop, host, port); - - os_init_setup (); - os_process_arguments (argc, argv); - init_buffer (); - init_err (); - init_memory (); - init_process (); - init_sound (); - os_init_screen (); - init_undo (); - z_restart (); - interpret (); - reset_memory (); - os_reset_screen (); + loop_->run(); return 0; } diff --git a/backends/frotz/soundcard.h b/backends/frotz/soundcard.h deleted file mode 100644 index 8bceb24b..00000000 --- a/backends/frotz/soundcard.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This file automatically generated by findsound.sh which run by the - * Makefile found in the Unix Frotz 2.43 source distribution. - * Copying this nasty hack to find headers which may be in any of several - * places is not recommended. I don't want to use autoconf just yet for - * this project. - * - */ - -#include diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 005bb0bf..00e79b7d 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -11,7 +11,8 @@ admin_password=test #cert=server.pfx #patch to PKCS#12 certificate #cert_password=test #password to that certificate if any users_per_backend=10 -backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum_libpurple_backend +#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum_libpurple_backend +backend=/home/hanzz/code/libtransport/backends/frotz/spectrum_frotz_backend #backend=../../backends/libircclient-qt/spectrum_libircclient-qt_backend #protocol=prpl-msn protocol=any