mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-24 02:36:27 +00:00
107073537e
svn-id: r22588
874 lines
18 KiB
C++
874 lines
18 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2006 The ScummVM project
|
|
*
|
|
* Copyright (C) 1999-2002 Sarien Team
|
|
*
|
|
* This program 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.
|
|
|
|
* This program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "common/stdafx.h"
|
|
|
|
#include "agi/agi.h"
|
|
#include "agi/graphics.h"
|
|
#include "agi/sprite.h"
|
|
#include "agi/text.h"
|
|
#include "agi/keyboard.h"
|
|
#include "agi/opcodes.h"
|
|
#include "agi/console.h"
|
|
|
|
namespace Agi {
|
|
|
|
#ifdef USE_CONSOLE
|
|
|
|
/*
|
|
* The main interpreter engine has not been designed to have a console, and a few
|
|
* kludges were needed to make the console work. First of all, the main
|
|
* interpreter loop works at cycle level, not instruction level. To keep
|
|
* the illusion that the console is threaded, a console updating function
|
|
* is called from loops inside instructions such as get.string().
|
|
*/
|
|
|
|
#define CONSOLE_LINES_ONSCREEN 20
|
|
#define CONSOLE_PROMPT "$"
|
|
#define CONSOLE_CURSOR_HOLLOW 1
|
|
#define CONSOLE_CURSOR_SOLID 2
|
|
#define CONSOLE_CURSOR_EMPTY 3
|
|
#define CONSOLE_COLOR 14
|
|
#define CONSOLE_SCROLLUP_KEY KEY_PGUP
|
|
#define CONSOLE_SCROLLDN_KEY KEY_PGDN
|
|
#define CONSOLE_START_KEY KEY_HOME
|
|
#define CONSOLE_END_KEY KEY_END
|
|
#define CONSOLE_INPUT_SIZE 39
|
|
|
|
struct console_command {
|
|
char cmd[8];
|
|
char dsc[40];
|
|
void (*handler) (void);
|
|
};
|
|
|
|
struct agi_console console;
|
|
struct agi_debug debug_;
|
|
|
|
/* This used to be a linked list, but we reduce total memory footprint
|
|
* by implementing it as a statically allocated array.
|
|
*/
|
|
#define MAX_CCMD 16
|
|
static struct console_command ccmd_list[MAX_CCMD];
|
|
static int num_ccmd = 0;
|
|
|
|
static uint8 has_console = 0;
|
|
static uint8 console_input = 0;
|
|
|
|
static char *_p0, *_p1, *_p2, *_p3, *_p4, *_p5; /* FIXME: array */
|
|
static char _p[80];
|
|
static int _pn;
|
|
|
|
/*
|
|
* Console line management
|
|
*/
|
|
|
|
static int first_line = 0;
|
|
|
|
static void add_console_line(char *s) {
|
|
int last_line;
|
|
|
|
last_line = (CONSOLE_LINES_BUFFER - 1 + first_line) % CONSOLE_LINES_BUFFER;
|
|
|
|
strncpy(console.line[last_line], s, CONSOLE_LINE_SIZE);
|
|
first_line %= CONSOLE_LINES_BUFFER;
|
|
}
|
|
|
|
static char *get_console_line(int n) {
|
|
return console.line[(n + first_line) % CONSOLE_LINES_BUFFER];
|
|
}
|
|
|
|
static char *get_last_console_line() {
|
|
int last_line = (CONSOLE_LINES_BUFFER - 1 + first_line) % CONSOLE_LINES_BUFFER;
|
|
|
|
return console.line[last_line];
|
|
}
|
|
|
|
/*
|
|
* Console command parsing
|
|
* 'o' commands added by Shaun Jackman <sjackman@shaw.ca>, 11 Apr 2002
|
|
*/
|
|
|
|
static int console_parse(char *b) {
|
|
struct console_command *d;
|
|
int i;
|
|
|
|
for (; *b && *b == ' '; b++) {
|
|
} /* eat spaces */
|
|
for (; *b && b[strlen(b) - 1] == ' '; b[strlen(b) - 1] = 0) {
|
|
}
|
|
if (!*b)
|
|
return 0;
|
|
|
|
/* get or set flag/var/obj values */
|
|
if ((b[0] == 'f' || b[0] == 'v' || b[0] == 'o') && isdigit(b[1])) {
|
|
char *e;
|
|
int f = (int)strtoul(&b[1], &e, 10);
|
|
if (*e == 0) {
|
|
if (f >= 0 && f <= 255) {
|
|
switch (b[0]) {
|
|
case 'f':
|
|
report(getflag(f) ? "true\n" : "false\n");
|
|
break;
|
|
case 'v':
|
|
report("%3d\n", getvar(f));
|
|
break;
|
|
case 'o':
|
|
report("%3d]%-24s(%3d)\n", f, object_name(f), object_get_location(f));
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
return -1;
|
|
} else if (*e == '=') {
|
|
int n = (int)strtoul(e + 1, NULL, 0);
|
|
switch (b[0]) {
|
|
case 'f':
|
|
setflag(f, !!n);
|
|
break;
|
|
case 'v':
|
|
setvar(f, n);
|
|
break;
|
|
case 'o':
|
|
object_set_location(f, n);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* tokenize the input line */
|
|
if (strchr(b, ' '))
|
|
strcpy(_p, strchr(b, ' ') + 1);
|
|
_p0 = strtok(b, " ");
|
|
_p1 = strtok(NULL, " ");
|
|
_p2 = strtok(NULL, " ");
|
|
_p3 = strtok(NULL, " ");
|
|
_p4 = strtok(NULL, " ");
|
|
_p5 = strtok(NULL, " ");
|
|
|
|
/* set number of parameters. ugh, must rewrite this later */
|
|
_pn = 5;
|
|
if (!_p5)
|
|
_pn = 4;
|
|
if (!_p4)
|
|
_pn = 3;
|
|
if (!_p3)
|
|
_pn = 2;
|
|
if (!_p2)
|
|
_pn = 1;
|
|
if (!_p1)
|
|
_pn = 0;
|
|
|
|
debugC(5, kDebugLevelMain, "number of parameters: %d", _pn);
|
|
|
|
for (i = 0; i < num_ccmd; i++) {
|
|
d = &ccmd_list[i];
|
|
if (!strcmp(_p0, d->cmd) && d->handler) {
|
|
d->handler();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; logic_names_cmd[i].name; i++) {
|
|
if (!strcmp(_p0, logic_names_cmd[i].name)) {
|
|
uint8 p[16];
|
|
if (_pn != logic_names_cmd[i].num_args) {
|
|
report("AGI command wants %d arguments\n", logic_names_cmd[i].num_args);
|
|
return 0;
|
|
}
|
|
p[0] = _p1 ? (char)strtoul(_p1, NULL, 0) : 0;
|
|
p[1] = _p2 ? (char)strtoul(_p2, NULL, 0) : 0;
|
|
p[2] = _p3 ? (char)strtoul(_p3, NULL, 0) : 0;
|
|
p[3] = _p4 ? (char)strtoul(_p4, NULL, 0) : 0;
|
|
p[4] = _p5 ? (char)strtoul(_p5, NULL, 0) : 0;
|
|
|
|
debugC(5, kDebugLevelMain, "ccmd: %s %d %d %d", logic_names_cmd[i].name, p[0], p[1], p[2]);
|
|
|
|
execute_agi_command(i, p);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Console commands
|
|
*/
|
|
|
|
static void ccmd_help() {
|
|
int i;
|
|
|
|
if (!_p1) {
|
|
report("Command Description\n");
|
|
report("------- --------------------------------\n");
|
|
for (i = 0; i < num_ccmd; i++)
|
|
report("%-8s%s\n", ccmd_list[i].cmd, ccmd_list[i].dsc);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < num_ccmd; i++) {
|
|
if (!strcmp(ccmd_list[i].cmd, _p1) && ccmd_list[i].handler) {
|
|
report("%s\n", ccmd_list[i].dsc);
|
|
return;
|
|
}
|
|
}
|
|
|
|
report("Unknown command or no help available\n");
|
|
|
|
return;
|
|
}
|
|
|
|
static void ccmd_ver() {
|
|
report(VERSION "\n");
|
|
return;
|
|
}
|
|
|
|
static void ccmd_crc() {
|
|
char name[80];
|
|
report("0x%05x\n", game.crc);
|
|
if (match_crc(game.crc, name, 80))
|
|
report("%s\n", name);
|
|
else
|
|
report("Unknown game\n");
|
|
return;
|
|
}
|
|
|
|
static void ccmd_quit() {
|
|
deinit_video();
|
|
/* deinit_machine (); */
|
|
exit(0);
|
|
}
|
|
|
|
#if 0
|
|
static void ccmd_exec() {
|
|
if (game.state < STATE_LOADED) {
|
|
report("No game loaded.\n");
|
|
return;
|
|
}
|
|
|
|
if (game.state >= STATE_RUNNING) {
|
|
report("Game already running.\n");
|
|
return;
|
|
}
|
|
|
|
report("Executing AGI game.\n");
|
|
game.state = STATE_RUNNING;
|
|
}
|
|
#endif
|
|
|
|
#ifdef USE_HIRES
|
|
|
|
static void ccmd_hires() {
|
|
if (_pn != 1 || (strcmp(_p1, "on") && strcmp(_p1, "off"))) {
|
|
report("Usage: hires on|off\n");
|
|
return;
|
|
}
|
|
|
|
opt.hires = !strcmp(_p1, "on");
|
|
erase_both();
|
|
show_pic();
|
|
blit_both();
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
static void ccmd_agiver() {
|
|
int ver, maj, min;
|
|
|
|
ver = agi_get_release();
|
|
maj = (ver >> 12) & 0xf;
|
|
min = ver & 0xfff;
|
|
|
|
report(maj <= 2 ? "%x.%03x\n" : "%x.002.%03x\n", maj, min);
|
|
return;
|
|
}
|
|
|
|
static void ccmd_flags() {
|
|
int i, j;
|
|
|
|
report(" ");
|
|
for (j = 0; j < 10; j++)
|
|
report("%d ", j);
|
|
report("\n");
|
|
|
|
for (i = 0; i < 255;) {
|
|
report("%3d ", i);
|
|
for (j = 0; j < 10; j++, i++) {
|
|
report("%c ", getflag(i) ? 'T' : 'F');
|
|
}
|
|
report("\n");
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void ccmd_vars() {
|
|
int i, j;
|
|
|
|
for (i = 0; i < 255;) {
|
|
for (j = 0; j < 5; j++, i++) {
|
|
report("%03d:%3d ", i, getvar(i));
|
|
}
|
|
report("\n");
|
|
}
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
|
|
static void ccmd_say() {
|
|
setflag(F_entered_cli, true);
|
|
dictionary_words(_p);
|
|
}
|
|
|
|
static void ccmd_inv() {
|
|
unsigned int i, j;
|
|
|
|
for (j = i = 0; i < game.num_objects; i++) {
|
|
if (object_get_location(i) == EGO_OWNED) {
|
|
report("%3d]%-16.16s", i, object_name(i));
|
|
if (j % 2)
|
|
report("\n");
|
|
j++;
|
|
}
|
|
}
|
|
if (j == 0) {
|
|
report("none\n");
|
|
return;
|
|
}
|
|
if (j % 2)
|
|
report("\n");
|
|
}
|
|
|
|
#endif
|
|
|
|
static void ccmd_objs() {
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < game.num_objects; i++) {
|
|
report("%3d]%-24s(%3d)\n", i, object_name(i), object_get_location(i));
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void ccmd_opcode() {
|
|
if (_pn != 1 || (strcmp(_p1, "on") && strcmp(_p1, "off"))) {
|
|
report("Usage: opcode on|off\n");
|
|
return;
|
|
}
|
|
|
|
debug_.opcodes = !strcmp(_p1, "on");
|
|
return;
|
|
}
|
|
|
|
static void ccmd_logic0() {
|
|
if (_pn != 1 || (strcmp(_p1, "on") && strcmp(_p1, "off"))) {
|
|
report("Usage: logic0 on|off\n");
|
|
return;
|
|
}
|
|
|
|
debug_.logic0 = !strcmp(_p1, "on");
|
|
return;
|
|
}
|
|
|
|
static void ccmd_trigger() {
|
|
if (_pn != 1 || (strcmp(_p1, "on") && strcmp(_p1, "off"))) {
|
|
report("Usage: trigger on|off\n");
|
|
return;
|
|
}
|
|
|
|
debug_.ignoretriggers = strcmp(_p1, "on");
|
|
return;
|
|
}
|
|
|
|
static void ccmd_step() {
|
|
debug_.enabled = 1;
|
|
|
|
if (_pn == 0) {
|
|
debug_.steps = 1;
|
|
return;
|
|
}
|
|
|
|
debug_.steps = strtoul(_p1, NULL, 0);
|
|
return;
|
|
}
|
|
|
|
static void ccmd_debug() {
|
|
debug_.enabled = 1;
|
|
debug_.steps = 0;
|
|
return;
|
|
}
|
|
|
|
static void ccmd_cont() {
|
|
debug_.enabled = 0;
|
|
debug_.steps = 0;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Register console commands
|
|
*/
|
|
static void console_cmd(char *cmd, char *dsc, void (*handler) (void)) {
|
|
assert(num_ccmd < MAX_CCMD);
|
|
|
|
strcpy(ccmd_list[num_ccmd].cmd, cmd);
|
|
strcpy(ccmd_list[num_ccmd].dsc, dsc);
|
|
ccmd_list[num_ccmd].handler = handler;
|
|
|
|
num_ccmd++;
|
|
}
|
|
|
|
/* Console reporting */
|
|
|
|
/* A slightly modified strtok() for report() */
|
|
static char *get_token(char *s, char d) {
|
|
static char *x;
|
|
char *n, *m;
|
|
|
|
if (s)
|
|
x = s;
|
|
|
|
m = x;
|
|
n = strchr(x, d);
|
|
|
|
if (n) {
|
|
*n = 0;
|
|
x = n + 1;
|
|
} else {
|
|
x = strchr(x, 0);
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
static void build_console_lines(int n) {
|
|
int j, y1;
|
|
char *line;
|
|
|
|
clear_console_screen(GFX_HEIGHT - n * 10);
|
|
|
|
for (j = CONSOLE_LINES_ONSCREEN - n; j < CONSOLE_LINES_ONSCREEN; j++) {
|
|
line = get_console_line(console.first_line + j);
|
|
print_text_console(line, 0, j, strlen(line) + 1, CONSOLE_COLOR, 0);
|
|
}
|
|
|
|
y1 = console.y - n * 10;
|
|
if (y1 < 0)
|
|
y1 = 0;
|
|
|
|
/* CM:
|
|
* This will cause blinking when using menus+console, but this
|
|
* function is called by report() which can be called from any
|
|
* point with or without sprites placed. If we protect the
|
|
* flush_block() call with redraw/release sprites cloning will
|
|
* happen when activating the console. This could be fixed by
|
|
* keeping a control flag in redraw/release to not do the
|
|
* actions twice, but I don't want to do that -- not yet.
|
|
*/
|
|
flush_block(0, y1, GFX_WIDTH - 1, console.y);
|
|
}
|
|
|
|
/*
|
|
* Public functions
|
|
*/
|
|
|
|
int console_init() {
|
|
console_cmd("agiver", "Show emulated Sierra AGI version", ccmd_agiver);
|
|
console_cmd("cont", "Resume interpreter execution", ccmd_cont);
|
|
console_cmd("debug", "Stop interpreter execution", ccmd_debug);
|
|
console_cmd("crc", "Show AGI game CRC", ccmd_crc);
|
|
#if 0
|
|
console_cmd("exec", "Execute loaded AGI game", ccmd_exec);
|
|
#endif
|
|
console_cmd("flags", "Dump all AGI flags", ccmd_flags);
|
|
console_cmd("help", "List available commands", ccmd_help);
|
|
#ifdef USE_HIRES
|
|
console_cmd("hires", "Turn hi-res mode on/off", ccmd_hires);
|
|
#endif
|
|
console_cmd("logic0", "Turn logic 0 debugging on/off", ccmd_logic0);
|
|
console_cmd("objs", "List all objects and locations", ccmd_objs);
|
|
console_cmd("opcode", "Turn opcodes on/off in debug", ccmd_opcode);
|
|
console_cmd("quit", "Quit the interpreter", ccmd_quit);
|
|
#if 0
|
|
console_cmd("inv", "List current inventory", ccmd_inv);
|
|
console_cmd("say", "Pass argument to the AGI parser", ccmd_say);
|
|
#endif
|
|
console_cmd("step", "Execute the next AGI instruction", ccmd_step);
|
|
console_cmd("trigger", "Turn trigger lines on/off", ccmd_trigger);
|
|
console_cmd("vars", "Dump all AGI variables", ccmd_vars);
|
|
console_cmd("ver", "Show interpreter version", ccmd_ver);
|
|
|
|
console.active = 1;
|
|
console.input_active = 1;
|
|
console.index = 0;
|
|
console.max_y = 150;
|
|
console.y = console.max_y;
|
|
console.first_line = CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN;
|
|
|
|
debug_.enabled = 0;
|
|
debug_.opcodes = 0;
|
|
debug_.logic0 = 1;
|
|
debug_.priority = 0;
|
|
|
|
has_console = 1;
|
|
clear_screen(0);
|
|
|
|
return err_OK;
|
|
}
|
|
|
|
static void build_console_layer() {
|
|
build_console_lines(console.max_y / 10);
|
|
}
|
|
|
|
void report(char *message, ...) {
|
|
char x[512], y[512], z[64], *msg, *n;
|
|
va_list args;
|
|
int i, s, len;
|
|
|
|
if (!has_console)
|
|
return;
|
|
|
|
va_start(args, message);
|
|
#ifdef HAVE_VSNPRINTF
|
|
vsnprintf(y, 510, (char *)message, args);
|
|
#else
|
|
vsprintf(y, (char *)message, args);
|
|
#endif
|
|
va_end(args);
|
|
|
|
if (console_input) {
|
|
strcpy(z, get_last_console_line());
|
|
strcpy(x, ">");
|
|
} else {
|
|
strcpy(x, get_last_console_line());
|
|
}
|
|
|
|
strcat(x, y);
|
|
|
|
len = 40;
|
|
msg = n = word_wrap_string(x, &len);
|
|
|
|
for (s = 1; *n; n++)
|
|
if (*n == '\n')
|
|
s++;
|
|
|
|
add_console_line(get_token(msg, '\n'));
|
|
for (i = 1; i < s; i++) {
|
|
first_line++;
|
|
n = get_token(NULL, '\n');
|
|
add_console_line(n);
|
|
}
|
|
|
|
console.first_line = CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN;
|
|
|
|
if (console_input) {
|
|
add_console_line(z);
|
|
}
|
|
|
|
/* Build layer */
|
|
if (console.y) {
|
|
if (s > 1)
|
|
build_console_layer();
|
|
else
|
|
build_console_lines(1);
|
|
}
|
|
|
|
free(msg);
|
|
|
|
do_update();
|
|
}
|
|
|
|
void console_cycle() {
|
|
static int old_y = 0;
|
|
static int blink = 0;
|
|
static char cursor[] = " ";
|
|
|
|
/* If no game has been loaded, keep the console visible! */
|
|
if (game.state < STATE_RUNNING) {
|
|
console.active = 1;
|
|
console.count = 10;
|
|
}
|
|
|
|
/* Initial console auto-hide timer */
|
|
if (console.count > 0)
|
|
console.count--;
|
|
if (console.count == 0) {
|
|
console.active = 0;
|
|
console.count = -1;
|
|
}
|
|
|
|
if (console.active) {
|
|
if (console.y < console.max_y)
|
|
console.y += 15;
|
|
else
|
|
console.y = console.max_y;
|
|
} else {
|
|
console.count = -1;
|
|
|
|
if (console.y > 0)
|
|
console.y -= 15;
|
|
else
|
|
console.y = 0;
|
|
}
|
|
|
|
/* console shading animation */
|
|
if (old_y != console.y) {
|
|
int y = console.y;
|
|
if (old_y > console.y) {
|
|
/* going up */
|
|
y = old_y;
|
|
}
|
|
flush_block(0, 0, GFX_WIDTH - 1, y);
|
|
old_y = console.y;
|
|
}
|
|
|
|
blink++;
|
|
blink %= 16;
|
|
if (console.input_active) {
|
|
*cursor = blink < 8 ?
|
|
CONSOLE_CURSOR_SOLID : CONSOLE_CURSOR_EMPTY;
|
|
} else {
|
|
*cursor = CONSOLE_CURSOR_HOLLOW;
|
|
}
|
|
if (console.y > 0
|
|
&& console.first_line ==
|
|
CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN) {
|
|
int16 y1 = console.y - 10, y2 = console.y - 1;
|
|
if (y1 < 0)
|
|
y1 = 0;
|
|
if (y2 < 0)
|
|
y2 = 0;
|
|
print_text_console(cursor, (1 + console.index), 19, 2, CONSOLE_COLOR, 0);
|
|
flush_block((1 + console.index) * 8, y1, (1 + console.index) * 8 + 7, y2 - 1);
|
|
}
|
|
|
|
do_update();
|
|
}
|
|
|
|
/* Return true if key was handled */
|
|
int console_keyhandler(int k) {
|
|
static char buffer[CONSOLE_INPUT_SIZE];
|
|
int16 y1, y2;
|
|
char m[2];
|
|
|
|
#ifdef USE_MOUSE
|
|
/* Right button switches console on/off */
|
|
if (!opt.agimouse) /* AGI Mouse uses right button */
|
|
if (k == BUTTON_RIGHT)
|
|
k = CONSOLE_ACTIVATE_KEY;
|
|
#endif
|
|
|
|
if (!console.active) {
|
|
if (k == CONSOLE_ACTIVATE_KEY) {
|
|
console.active = 1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (!console.input_active) {
|
|
if (k == CONSOLE_SWITCH_KEY) {
|
|
console.input_active = 1;
|
|
return true;
|
|
}
|
|
if (k == CONSOLE_ACTIVATE_KEY) {
|
|
console.active = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
y1 = console.y - 10;
|
|
y2 = console.y - 1;
|
|
|
|
if (y1 < 0)
|
|
y1 = 0;
|
|
if (y2 < 0)
|
|
y2 = 0;
|
|
|
|
#ifdef USE_MOUSE
|
|
/* Ignore left button in console */
|
|
if (k == BUTTON_LEFT)
|
|
return true;
|
|
#endif
|
|
|
|
/* this code breaks scrolling up, maybe it shoud only be executed
|
|
* in the default case?
|
|
*/
|
|
if (k) {
|
|
/* make sure it's not enter or a scroll key */
|
|
if ((k != KEY_ENTER) && (k != CONSOLE_SCROLLUP_KEY) && (k != CONSOLE_SCROLLDN_KEY)
|
|
&& (k != CONSOLE_START_KEY)) {
|
|
/* on any other input reset the console to the bottom */
|
|
if (console.first_line != CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN) {
|
|
console.first_line = CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN;
|
|
build_console_layer();
|
|
}
|
|
console.count = -1;
|
|
}
|
|
}
|
|
|
|
switch (k) {
|
|
case KEY_ENTER:
|
|
console_lock();
|
|
console.index = 0;
|
|
report("\n");
|
|
|
|
if (console_parse(buffer) != 0)
|
|
report("What? Where?\n");
|
|
|
|
buffer[0] = 0;
|
|
console_prompt();
|
|
break;
|
|
case KEY_BACKSPACE:{
|
|
char *x;
|
|
if (!console.index)
|
|
break;
|
|
x = get_last_console_line();
|
|
x[console.index] = 0;
|
|
*m = CONSOLE_CURSOR_EMPTY;
|
|
print_text_console(m, (console.index + 1), 19, 2, CONSOLE_COLOR, 0);
|
|
flush_block((console.index + 1) * CHAR_COLS, y1, (console.index + 1 + 1) * CHAR_COLS - 1, y2);
|
|
console.index--;
|
|
buffer[console.index] = 0;
|
|
}
|
|
break;
|
|
case CONSOLE_ACTIVATE_KEY:
|
|
console.active = !console.active;
|
|
if (console.active)
|
|
build_console_layer();
|
|
break;
|
|
case CONSOLE_SWITCH_KEY:
|
|
console.count = -1;
|
|
if (console.y)
|
|
console.input_active = !console.input_active;
|
|
break;
|
|
case CONSOLE_SCROLLUP_KEY:
|
|
console.count = -1;
|
|
if (!console.y)
|
|
break;
|
|
if (console.first_line > (CONSOLE_LINES_ONSCREEN / 2))
|
|
console.first_line -= CONSOLE_LINES_ONSCREEN / 2;
|
|
else
|
|
console.first_line = 0;
|
|
build_console_layer();
|
|
break;
|
|
case CONSOLE_SCROLLDN_KEY:
|
|
console.count = -1;
|
|
if (!console.y)
|
|
break;
|
|
if (console.first_line < (CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN - CONSOLE_LINES_ONSCREEN / 2))
|
|
console.first_line += CONSOLE_LINES_ONSCREEN / 2;
|
|
else
|
|
console.first_line = CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN;
|
|
build_console_layer();
|
|
break;
|
|
case CONSOLE_START_KEY:
|
|
console.count = -1;
|
|
if (console.y)
|
|
console.first_line = 0;
|
|
break;
|
|
case CONSOLE_END_KEY:
|
|
console.count = -1;
|
|
if (console.y)
|
|
console.first_line = CONSOLE_LINES_BUFFER - CONSOLE_LINES_ONSCREEN;
|
|
break;
|
|
default:
|
|
if (k >= 0x20 && k <= 0x7f && (console.index < CONSOLE_INPUT_SIZE - 2)) {
|
|
char l[42];
|
|
buffer[console.index] = k;
|
|
*m = k;
|
|
m[1] = 0;
|
|
console.index++;
|
|
|
|
sprintf(l, "%s%c", get_last_console_line(), k);
|
|
strncpy(get_last_console_line(), l, CONSOLE_LINE_SIZE);
|
|
|
|
buffer[console.index] = 0;
|
|
print_text_console(m, console.index, 19, 2, CONSOLE_COLOR, 0);
|
|
flush_block(console.index * 8, y1, console.index * 8 + 7, y2);
|
|
}
|
|
break;
|
|
}
|
|
|
|
do_update();
|
|
|
|
return true;
|
|
}
|
|
|
|
void console_prompt() {
|
|
report(CONSOLE_PROMPT);
|
|
console_input = 1;
|
|
}
|
|
|
|
void console_lock() {
|
|
console_input = 0;
|
|
}
|
|
|
|
#else
|
|
|
|
void *debug;
|
|
|
|
void report(char *message, ...) {
|
|
/* dummy */
|
|
}
|
|
|
|
int console_init() {
|
|
return 0;
|
|
}
|
|
|
|
/* Date: Sun, 14 Oct 2001 23:02:02 -0700
|
|
* From: Vasyl Tsvirkunov <vasyl@pacbell.net>
|
|
*
|
|
* This one was rather harmless and affected only builds without console.
|
|
* In SQ1&2 (and likely some others) name entry screen did not update
|
|
* properly. The bug caused by implicit assumption in cycle.c that
|
|
* console_cycle() updates the screen. Well, it does, if console is enabled.
|
|
* The fix is simple. In the second version of console_cycle() in console.c
|
|
* (the "dummy" one) add call to do_update(). The thing raises some
|
|
* questions about overall architecture of main cycle, but otherwise the fix
|
|
* works just fine.
|
|
*/
|
|
void console_cycle() {
|
|
do_update();
|
|
}
|
|
|
|
void console_lock() {
|
|
/* dummy */
|
|
}
|
|
|
|
void console_prompt() {
|
|
/* dummy */
|
|
}
|
|
|
|
int console_keyhandler(int i) {
|
|
return false;
|
|
}
|
|
|
|
#endif /* USE_CONSOLE */
|
|
|
|
} // End of namespace Agi
|