Finished frotz backend :)

This commit is contained in:
HanzZ 2011-09-18 11:48:00 +02:00
parent 64a0a5d6b5
commit a22b6e1490
33 changed files with 603 additions and 347 deletions

View file

@ -1,4 +1,7 @@
cmake_minimum_required(VERSION 2.6)
ADD_SUBDIRECTORY(dfrotz)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum_frotz_backend ${SRC})

View file

@ -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)

View file

@ -0,0 +1,2 @@
This is patched version of dfrotz. frotz_backend won't work with dfrotz from
your distribution.

View file

@ -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) {

View file

@ -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 ();

View file

@ -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) {

View file

@ -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 <signal.h>
#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

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -446,7 +446,7 @@ void ret (zword value)
*
*/
void branch (int flag)
void branch (bool flag)
{
long pc;
zword offset;

View file

@ -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;

View file

@ -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) {

View file

@ -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 */

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -6,7 +6,7 @@
* Copyright 1997, 1998 Alembic Petrofsky <alembic@petrofsky.berkeley.ca.us>.
* Any use permitted provided this notice stays intact.
*/
#include "frotz.h"
#include "../common/frotz.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
@ -14,23 +14,24 @@
#include <ctype.h>
#include <time.h>
#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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -10,162 +10,139 @@
#include "transport/config.h"
#include "transport/networkplugin.h"
#include "frotz.h"
#ifndef MSDOS_16BIT
#define cdecl
#endif
#include <boost/filesystem.hpp>
#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<std::string> getGames() {
std::vector<std::string> 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<std::string> 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 <game>\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<std::string, dfrotz> 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] <config_file.cfg>\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;
}

View file

@ -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 <sys/soundcard.h>

View file

@ -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