diff options
author | Paul Gilbert | 2018-11-12 10:54:59 -0800 |
---|---|---|
committer | Paul Gilbert | 2018-12-08 19:05:59 -0800 |
commit | 7a52f21c0bb267d6851ede650298b1d084493ef6 (patch) | |
tree | bbc154228f0b19486d242d3aa1c22e6fb5472aa4 /engines/gargoyle/frotz | |
parent | 2c37a949136e4bd6a38daf420eb4638ce8d5f4ae (diff) | |
download | scummvm-rg350-7a52f21c0bb267d6851ede650298b1d084493ef6.tar.gz scummvm-rg350-7a52f21c0bb267d6851ede650298b1d084493ef6.tar.bz2 scummvm-rg350-7a52f21c0bb267d6851ede650298b1d084493ef6.zip |
GLK: FROTZ: Added script/record/transcript/replay methods
Diffstat (limited to 'engines/gargoyle/frotz')
-rw-r--r-- | engines/gargoyle/frotz/processor.cpp | 3 | ||||
-rw-r--r-- | engines/gargoyle/frotz/processor.h | 101 | ||||
-rw-r--r-- | engines/gargoyle/frotz/processor_input.cpp | 40 | ||||
-rw-r--r-- | engines/gargoyle/frotz/processor_streams.cpp | 306 |
4 files changed, 414 insertions, 36 deletions
diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp index 934101332d..ac18a23593 100644 --- a/engines/gargoyle/frotz/processor.cpp +++ b/engines/gargoyle/frotz/processor.cpp @@ -136,7 +136,8 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) : _finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0), zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0), _randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false), - _bufPos(0), _locked(false), _prevC('\0') { + _bufPos(0), _locked(false), _prevC('\0'), script_width(0), + sfp(nullptr), rfp(nullptr), pfp(nullptr) { static const Opcode OP0_OPCODES[16] = { &Processor::z_rtrue, &Processor::z_rfalse, diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h index f9352ec19c..50c951a589 100644 --- a/engines/gargoyle/frotz/processor.h +++ b/engines/gargoyle/frotz/processor.h @@ -79,6 +79,10 @@ private: Opcode op1_opcodes[16]; static Opcode var_opcodes[64]; static Opcode ext_opcodes[64]; + + // Stream related fields + int script_width; + strid_t sfp, rfp, pfp; private: /** * \defgroup General support methods @@ -358,7 +362,102 @@ private: */ void script_close(); - /**@}*/ + /** + * Write a newline to the transscript file. + */ + void script_new_line(); + + /** + * Write a single character to the transscript file. + */ + void script_char(zchar c); + + /** + * Write a string to the transscript file. + */ + void script_word(const zchar *s); + + /** + * Send an input line to the transscript file. + */ + void script_write_input(const zchar *buf, zchar key); + + /** + * Remove an input line from the transscript file. + */ + void script_erase_input(const zchar *buf); + + /** + * Start sending a "debugging" message to the transscript file. + */ + void script_mssg_on(); + + /** + * Stop writing a "debugging" message. + */ + void script_mssg_off(); + + /** + * Open a file to record the player's input. + */ + void record_open(); + + /** + * Stop recording the player's input. + */ + void record_close(); + + /** + * Helper function for record_char. + */ + void record_code(int c, bool force_encoding); + + /** + * Write a character to the command file. + */ + void record_char(zchar c); + + /** + * Copy a keystroke to the command file. + */ + void record_write_key(zchar key); + + /** + * Copy a line of input to a command file. + */ + void record_write_input(const zchar *buf, zchar key); + + /** + * Open a file of commands for playback. + */ + void replay_open(); + + /** + * Stop playback of commands. + */ + void replay_close(); + + /* + * Helper function for replay_key and replay_line. + */ + int replay_code(); + + /** + * Read a character from the command file. + */ + zchar replay_char(); + + /** + * Read a keystroke from a command file. + */ + zchar replay_read_key(); + + /* + * Read a line of input from a command file. + */ + zchar replay_read_input(zchar *buf); + + /**@}*/ /** * \defgroup Text support methods diff --git a/engines/gargoyle/frotz/processor_input.cpp b/engines/gargoyle/frotz/processor_input.cpp index 48951d2402..89aa1889fd 100644 --- a/engines/gargoyle/frotz/processor_input.cpp +++ b/engines/gargoyle/frotz/processor_input.cpp @@ -31,13 +31,6 @@ static zword os_read_mouse() { return 0; } #define INPUT_BUFFER_SIZE 200 -void Processor::z_make_menu() { - // This opcode was only used for the Macintosh version of Journey. - // It controls menus with numbers greater than 2 (menus 0, 1 and 2 - // are system menus). - branch (false); -} - bool Processor::read_yes_or_no(const char *s) { zchar key; @@ -65,6 +58,39 @@ void Processor::read_string(int max, zchar *buffer) { } while (key != ZC_RETURN); } +bool Processor::is_terminator(zchar key) { + if (key == ZC_TIME_OUT) + return true; + if (key == ZC_RETURN) + return true; + if (key >= ZC_HKEY_MIN && key <= ZC_HKEY_MAX) + return true; + + if (h_terminating_keys != 0) { + if (key >= ZC_ARROW_MIN && key <= ZC_MENU_CLICK) { + + zword addr = h_terminating_keys; + zbyte c; + + do { + LOW_BYTE(addr, c); + if (c == 255 || key == translate_from_zscii(c)) + return true; + addr++; + } while (c != 0); + } + } + + return false; +} + +void Processor::z_make_menu() { + // This opcode was only used for the Macintosh version of Journey. + // It controls menus with numbers greater than 2 (menus 0, 1 and 2 + // are system menus). + branch(false); +} + int Processor::read_number() { zchar buffer[6]; int value = 0; diff --git a/engines/gargoyle/frotz/processor_streams.cpp b/engines/gargoyle/frotz/processor_streams.cpp index 44062757ef..95205a58bd 100644 --- a/engines/gargoyle/frotz/processor_streams.cpp +++ b/engines/gargoyle/frotz/processor_streams.cpp @@ -28,30 +28,15 @@ namespace Frotz { // TODO: Implement method stubs static void os_scrollback_char(zchar) {} static void os_scrollback_erase(zword) {} -static void script_mssg_on() {} -static void script_mssg_off() {} -static void script_char(zchar) {} -static void script_word(const zchar *) {} -static void script_new_line() {} -static void script_erase_input(const zchar *) {} -static void script_write_input(zchar *, char) {} static void memory_open(zword, zword, bool) {} static void memory_close() {} static void memory_word(const zchar *) {} static void memory_new_line() {} -static void replay_open() {} -static void replay_close() {} -static zchar replay_read_key() { return 0; } -static zchar replay_read_input(zchar *) { return 0; } static zchar console_read_key(zword) { return 0; } static zchar console_read_input(uint, zchar *, uint, bool) { return 0; } -static void record_open() {} -static void record_close() {} -static void record_write_key(zchar) {} -static void record_write_input(zchar *, zchar) {} -void Processor::scrollback_char (zchar c) { +void Processor::scrollback_char(zchar c) { if (c == ZC_INDENT) { scrollback_char (' '); scrollback_char (' '); scrollback_char (' '); return; } if (c == ZC_GAP) @@ -219,13 +204,282 @@ continue_input: } void Processor::script_open() { - // TODO + h_flags &= ~SCRIPTING_FLAG; + + frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, + filemode_WriteAppend); + sfp = glk_stream_open_file(fref, filemode_WriteAppend); + + if (sfp != nullptr) { + sfp->setPosition(0, seekmode_End); + + h_flags |= SCRIPTING_FLAG; + + script_valid = true; + ostream_script = true; + + script_width = 0; + } else { + print_string("Cannot open file\n"); + } + + SET_WORD(H_FLAGS, h_flags); } void Processor::script_close() { - // TODO + h_flags &= ~SCRIPTING_FLAG; + SET_WORD(H_FLAGS, h_flags); + + glk_stream_close(sfp); + ostream_script = false; +} + +void Processor::script_new_line() { + script_char('\n'); + script_width = 0; +} + +void Processor::script_char(zchar c) { + if (c == ZC_INDENT && script_width != 0) + c = ' '; + + if (c == ZC_INDENT) { + script_char(' '); + script_char(' '); + script_char(' '); + return; + } + if (c == ZC_GAP) { + script_char(' '); + script_char(' '); + return; + } + + sfp->putCharUni(c); + script_width++; +} + +void Processor::script_word(const zchar *s) { + int width; + int i; + + if (*s == ZC_INDENT && script_width != 0) + script_char(*s++); + + for (i = 0, width = 0; s[i] != 0; i++) { + if (s[i] == ZC_NEW_STYLE || s[i] == ZC_NEW_FONT) + i++; + else if (s[i] == ZC_GAP) + width += 3; + else if (s[i] == ZC_INDENT) + width += 2; + else + width += 1; + } + + if (_script_cols != 0 && script_width + width > _script_cols) { + if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP) + s++; + + script_new_line(); + } + + for (i = 0; s[i] != 0; i++) { + if (s[i] == ZC_NEW_FONT || s[i] == ZC_NEW_STYLE) + i++; + else + script_char(s[i]); + } +} + +void Processor::script_write_input(const zchar *buf, zchar key) { + int width; + int i; + + for (i = 0, width = 0; buf[i] != 0; i++) + width++; + + if (_script_cols != 0 && script_width + width > _script_cols) + script_new_line(); + + for (i = 0; buf[i] != 0; i++) + script_char(buf[i]); + + if (key == ZC_RETURN) + script_new_line(); +} + +void Processor::script_erase_input(const zchar *buf) { + int width; + int i; + + for (i = 0, width = 0; buf[i] != 0; i++) + width++; + + sfp->setPosition(-width, seekmode_Current); + script_width -= width; +} + +void Processor::script_mssg_on() { + if (script_width != 0) + script_new_line(); + + script_char(ZC_INDENT); +} + +void Processor::script_mssg_off() { + script_new_line(); +} + +void Processor::record_open() { + frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Write); + if ((rfp = glk_stream_open_file(fref, filemode_Write)) != nullptr) + ostream_record = true; + else + print_string("Cannot open file\n"); +} + +void Processor::record_close() { + glk_stream_close(rfp); + ostream_record = false; +} + +void Processor::record_code(int c, bool force_encoding) { + if (force_encoding || c == '[' || c < 0x20 || c > 0x7e) { + int i; + + rfp->putChar('['); + + for (i = 10000; i != 0; i /= 10) + if (c >= i || i == 1) + rfp->putChar('0' + (c / i) % 10); + + rfp->putChar(']'); + } else { + rfp->putChar(c); + } +} + +void Processor::record_char(zchar c) { + if (c != ZC_RETURN) { + if (c < ZC_HKEY_MIN || c > ZC_HKEY_MAX) { + record_code(translate_to_zscii(c), false); + if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) { + record_code(mouse_x, true); + record_code(mouse_y, true); + } + } else { + record_code(1000 + c - ZC_HKEY_MIN, true); + } + } +} + +void Processor::record_write_key(zchar key) { + record_char(key); + rfp->putChar('\n'); +} + +void Processor::record_write_input(const zchar *buf, zchar key) { + zchar c; + + while ((c = *buf++) != 0) + record_char(c); + + record_write_key(key); +} + +void Processor::replay_open() { + frefid_t fref = glk_fileref_create_by_prompt(fileusage_Transcript, filemode_Read); + if ((pfp = glk_stream_open_file(fref, filemode_Read)) != nullptr) + istream_replay = true; + else + print_string("Cannot open file\n"); +} + +void Processor::replay_close() { + glk_stream_close(pfp); + istream_replay = false; } +int Processor::replay_code() { + int c; + + if ((c = pfp->getChar()) == '[') { + int c2; + + c = 0; + + while ((c2 = pfp->getChar()) != EOF && c2 >= '0' && c2 <= '9') + c = 10 * c + c2 - '0'; + + return (c2 == ']') ? c : EOF; + } else { + return c; + } +} + +zchar Processor::replay_char() { + int c; + + if ((c = replay_code()) != EOF) { + if (c != '\n') { + if (c < 1000) { + + c = translate_from_zscii(c); + + if (c == ZC_SINGLE_CLICK || c == ZC_DOUBLE_CLICK) { + mouse_x = replay_code(); + mouse_y = replay_code(); + } + + return c; + } else { + return ZC_HKEY_MIN + c - 1000; + } + } + + pfp->unputBuffer("\n", 1); + return ZC_RETURN; + + } else { + return ZC_BAD; + } +} + +zchar Processor::replay_read_key() { + zchar key = replay_char(); + + if (pfp->getChar() != '\n') { + replay_close(); + return ZC_BAD; + } else { + return key; + } +} + +zchar Processor::replay_read_input(zchar *buf) { + zchar c; + + for (;;) { + c = replay_char(); + + if (c == ZC_BAD || is_terminator(c)) + break; + + *buf++ = c; + } + + *buf = 0; + + if (pfp->getChar() != '\n') { + replay_close(); + return ZC_BAD; + } else { + return c; + } +} + + void Processor::z_input_stream() { flush_buffer(); @@ -260,7 +514,7 @@ void Processor::z_output_stream() { } } -void Processor::z_restart(void) { +void Processor::z_restart() { flush_buffer(); os_restart_game(RESTART_BEGIN); @@ -293,8 +547,7 @@ void Processor::z_restart(void) { os_restart_game(RESTART_END); } - -void Processor::z_save(void) { +void Processor::z_save() { #ifdef TODO bool success = false; @@ -310,8 +563,7 @@ void Processor::z_save(void) { glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]); - stream_result_t result; - glk_stream_close(f, &result); + glk_stream_close(f); } else { long pc; @@ -430,8 +682,8 @@ void Processor::z_restore() { release = (unsigned) fgetc (gfp) << 8; release |= fgetc (gfp); - (void) fgetc (gfp); - (void) fgetc (gfp); + () fgetc (gfp); + () fgetc (gfp); /* Check the release number */ @@ -460,7 +712,7 @@ void Processor::z_restore() { for (i = 0; i < skip; i++) zmp[addr++] = fgetc (story_fp); zmp[addr] = fgetc (gfp); - (void) fgetc (story_fp); + () fgetc (story_fp); } /* Check for errors */ @@ -519,7 +771,7 @@ finished: #endif } -void Processor::z_verify(void) { +void Processor::z_verify() { zword checksum = 0; // Sum all bytes in story file except header bytes |