GLK: COMPREHEND: Adding initialization defaults for game info

This commit is contained in:
Paul Gilbert 2020-05-28 22:44:51 -07:00
parent 7e7e6a5fab
commit 2dd367aa6f
5 changed files with 341 additions and 225 deletions

View File

@ -31,13 +31,13 @@ namespace Comprehend {
static bool word_match(struct word *word, const char *string)
{
/* Words less than 6 characters must match exactly */
if (strlen(word->word) < 6 && strlen(string) != strlen(word->word))
if (strlen(word->_word) < 6 && strlen(string) != strlen(word->_word))
return false;
return strncmp(word->word, string, strlen(word->word)) == 0;
return strncmp(word->_word, string, strlen(word->_word)) == 0;
}
struct word *dict_find_word_by_string(struct comprehend_game *game,
word *dict_find_word_by_string(struct comprehend_game *game,
const char *string)
{
uint i;
@ -58,8 +58,8 @@ struct word *dict_find_word_by_index_type(struct comprehend_game *game,
uint i;
for (i = 0; i < game->info->nr_words; i++) {
if (game->info->words[i].index == index &&
game->info->words[i].type == type)
if (game->info->words[i]._index == index &&
game->info->words[i]._type == type)
return &game->info->words[i];
}
@ -72,8 +72,8 @@ struct word *find_dict_word_by_index(struct comprehend_game *game,
uint i;
for (i = 0; i < game->info->nr_words; i++) {
if (game->info->words[i].index == index &&
(game->info->words[i].type & type_mask) != 0)
if (game->info->words[i]._index == index &&
(game->info->words[i]._type & type_mask) != 0)
return &game->info->words[i];
}
@ -86,8 +86,8 @@ bool dict_match_index_type(struct comprehend_game *game, const char *word,
uint i;
for (i = 0; i < game->info->nr_words; i++)
if (game->info->words[i].index == index &&
((game->info->words[i].type & type_mask) != 0) &&
if (game->info->words[i]._index == index &&
((game->info->words[i]._type & type_mask) != 0) &&
word_match(&game->info->words[i], word))
return true;

View File

@ -219,7 +219,7 @@ static void dump_action_table(struct comprehend_game *game)
word = find_dict_word_by_index(game, action->word[j],
action->word_type[j]);
if (word)
debugN("%-6s ", word->word);
debugN("%-6s ", word->_word);
else
debugN("%.2x:%.2x ", action->word[j],
action->word_type[j]);
@ -233,9 +233,9 @@ static int word_index_compare(const void *a, const void *b)
{
const word *word_a = (const word *)a, *word_b = (const word *)b;
if (word_a->index > word_b->index)
if (word_a->_index > word_b->_index)
return 1;
if (word_a->index < word_b->index)
if (word_a->_index < word_b->_index)
return -1;
return 0;
}
@ -256,8 +256,8 @@ static void dump_dictionary(struct comprehend_game *game)
debugN("Dictionary (%zd words)\n", game->info->nr_words);
for (i = 0; i < game->info->nr_words; i++) {
words = &dictionary[i];
debugN(" [%.2x] %.2x %s\n", words->index, words->type,
words->word);
debugN(" [%.2x] %.2x %s\n", words->_index, words->_type,
words->_word);
}
free(dictionary);
@ -279,7 +279,7 @@ static void dump_word_map(struct comprehend_game *game)
game, map->word[j].index, map->word[j].type);
if (word[j])
snprintf(str[j], sizeof(str[j]),
"%s", word[j]->word);
"%s", word[j]->_word);
else
snprintf(str[j], sizeof(str[j]), "%.2x:%.2x ",
map->word[j].index, map->word[j].type);
@ -335,9 +335,9 @@ static void dump_items(struct comprehend_game *game)
debugN(" words: ");
for (j = 0; j < game->info->nr_words; j++)
if (game->info->words[j].index == item->word &&
(game->info->words[j].type & WORD_TYPE_NOUN_MASK))
debugN("%s ", game->info->words[j].word);
if (game->info->words[j]._index == item->word &&
(game->info->words[j]._type & WORD_TYPE_NOUN_MASK))
debugN("%s ", game->info->words[j]._word);
debugN("\n");
debugN(" flags=%.2x (takeable=%d, weight=%d)\n",
item->flags, !!(item->flags & ITEMF_CAN_TAKE),

View File

@ -236,10 +236,10 @@ static struct word_index *is_word_pair(comprehend_game *game,
for (i = 0; i < game->info->nr_word_maps; i++) {
map = &game->info->word_map[i];
if (map->word[0].index == word1->index &&
map->word[0].type == word1->type &&
map->word[1].index == word2->index &&
map->word[1].type == word2->type)
if (map->word[0].index == word1->_index &&
map->word[0].type == word1->_type &&
map->word[1].index == word2->_index &&
map->word[1].type == word2->_type)
return &map->word[2];
}
@ -250,7 +250,7 @@ static struct item *get_item_by_noun(comprehend_game *game,
struct word *noun) {
uint i;
if (!noun || !(noun->type & WORD_TYPE_NOUN_MASK))
if (!noun || !(noun->_type & WORD_TYPE_NOUN_MASK))
return NULL;
/*
@ -259,7 +259,7 @@ static struct item *get_item_by_noun(comprehend_game *game,
* to drop the latter because this will match the former.
*/
for (i = 0; i < game->info->header.nr_items; i++)
if (game->info->item[i].word == noun->index)
if (game->info->item[i].word == noun->_index)
return &game->info->item[i];
return NULL;
@ -551,12 +551,12 @@ static void eval_instruction(comprehend_game *game,
case OPCODE_MOVE:
/* Move in the direction dictated by the current verb */
if (verb->index - 1 >= NR_DIRECTIONS)
if (verb->_index - 1 >= NR_DIRECTIONS)
fatal_error("Bad verb %d:%d in move",
verb->index, verb->type);
verb->_index, verb->_type);
if (room->direction[verb->index - 1])
move_to(game, room->direction[verb->index - 1]);
if (room->direction[verb->_index - 1])
move_to(game, room->direction[verb->_index - 1]);
else
console_println(game, string_lookup(game, STRING_CANT_GO));
break;
@ -619,7 +619,7 @@ static void eval_instruction(comprehend_game *game,
for (i = 0; i < game->info->header.nr_items; i++) {
struct item *itemP = &game->info->item[i];
if (itemP->word == noun->index &&
if (itemP->word == noun->_index &&
itemP->room == instr->operand[0]) {
test = true;
break;
@ -727,7 +727,7 @@ static void eval_instruction(comprehend_game *game,
case OPCODE_OBJECT_NOT_VALID:
/* FIXME - should be called OPCODE_CURRENT_OBJECT_NOT_VALID */
func_set_test_result(func_state, !noun ||
(noun->type & WORD_TYPE_NOUN_MASK) == 0);
(noun->_type & WORD_TYPE_NOUN_MASK) == 0);
break;
case OPCODE_CURRENT_IS_OBJECT:
@ -931,11 +931,11 @@ static void eval_instruction(comprehend_game *game,
* FIXME - Not sure what the operand is for,
* maybe capitalisation?
*/
if (noun && (noun->type & WORD_TYPE_NOUN_PLURAL))
if (noun && (noun->_type & WORD_TYPE_NOUN_PLURAL))
game->info->current_replace_word = 3;
else if (noun && (noun->type & WORD_TYPE_FEMALE))
else if (noun && (noun->_type & WORD_TYPE_FEMALE))
game->info->current_replace_word = 0;
else if (noun && (noun->type & WORD_TYPE_MALE))
else if (noun && (noun->_type & WORD_TYPE_MALE))
game->info->current_replace_word = 1;
else
game->info->current_replace_word = 2;
@ -985,9 +985,7 @@ static void eval_instruction(comprehend_game *game,
*/
void eval_function(comprehend_game *game, struct function *func,
struct word *verb, struct word *noun) {
struct function_state func_state = {
true, false, 0, false, false, false
};
struct function_state func_state;
uint i;
func_state.else_result = true;
@ -1084,8 +1082,8 @@ static bool handle_sentence(comprehend_game *game,
* run that action's function.
*/
for (j = 0; j < action->nr_words; j++) {
if (sentence->words[j].index == action->word[j] &&
(sentence->words[j].type & action->word_type[j]))
if (sentence->words[j]._index == action->word[j] &&
(sentence->words[j]._type & action->word_type[j]))
continue;
/* Word didn't match */
@ -1149,9 +1147,9 @@ static void read_sentence(comprehend_game *game, char **line,
&sentence->words[index - 2],
&sentence->words[index - 1]);
if (pair) {
sentence->words[index - 2].index = pair->index;
sentence->words[index - 2].type = pair->type;
strcpy(sentence->words[index - 2].word,
sentence->words[index - 2]._index = pair->index;
sentence->words[index - 2]._type = pair->type;
strcpy(sentence->words[index - 2]._word,
"[PAIR]");
sentence->nr_words--;
}

View File

@ -38,7 +38,102 @@ static char special_charset[] = "[]\n!\"#$%&'(),-/0123456789:;?<>";
static uint16 magic_offset;
static void parse_header_le16(struct file_buf *fb, uint16 *val) {
function_state::function_state() : test_result(true),
else_result(false),
or_count(0),
_and(false),
in_command(false),
executed(false) {
}
/*-------------------------------------------------------*/
room::room() : flags(0),
graphic(0),
string_desc(0) {
Common::fill(&direction[0], &direction[NR_DIRECTIONS], 0);
}
/*-------------------------------------------------------*/
item::item() : string_desc(0),
long_string(0),
room(0),
flags(0),
word(0),
graphic(0) {
}
/*-------------------------------------------------------*/
word::word() : _index(0), _type(0) {
Common::fill(&_word[0], &_word[7], '\0');
}
/*-------------------------------------------------------*/
action::action() : type(0), nr_words(0), function(0) {
Common::fill(&word[0], &word[4], 0);
Common::fill(&word_type[0], &word_type[4], 0);
}
instruction::instruction() : opcode(0), nr_operands(0),
is_command(false) {
Common::fill(&operand[0], &operand[3], 0);
}
/*-------------------------------------------------------*/
string_table::string_table() : nr_strings(0) {
Common::fill(&strings[0], &strings[0xffff], nullptr);
}
/*-------------------------------------------------------*/
game_header::game_header() : magic(0),
room_desc_table(0),
room_flags_table(0),
room_graphics_table(0),
nr_items(0),
addr_item_locations(0),
addr_item_flags(0),
addr_item_word(0),
addr_item_strings(0),
addr_item_graphics(0),
addr_dictionary(0),
addr_word_map(0),
addr_strings(0),
addr_strings_end(0),
addr_actions_vvnn(0),
addr_actions_unknown(0),
addr_actions_vnjn(0),
addr_actions_vjn(0),
addr_actions_vdn(0),
addr_actions_vnn(0),
addr_actions_vn(0),
addr_actions_v(0),
addr_vm(0) // FIXME - functions
{
Common::fill(&room_direction_table[0], &room_direction_table[NR_DIRECTIONS], 0);
}
/*-------------------------------------------------------*/
game_info::game_info() : comprehend_version(0),
start_room(0),
nr_rooms(0),
current_room(0),
words(nullptr),
nr_words(0),
nr_word_maps(0),
nr_actions(0),
nr_functions(0),
nr_replace_words(0),
current_replace_word(0),
update_flags(0) {
}
static void parse_header_le16(struct file_buf * fb, uint16 * val) {
file_buf_get_le16(fb, val);
*val += (uint16)magic_offset;
}
@ -53,8 +148,8 @@ static bool opcode_is_command(uint8 opcode) {
return opcode & 0x80;
}
static uint8 parse_vm_instruction(struct file_buf *fb,
struct instruction *instr) {
static uint8 parse_vm_instruction(struct file_buf * fb,
struct instruction * instr) {
uint i;
/* Get the opcode */
@ -70,12 +165,12 @@ static uint8 parse_vm_instruction(struct file_buf *fb,
return instr->opcode;
}
static void parse_function(struct file_buf *fb, struct function *func) {
static void parse_function(struct file_buf * fb, struct function * func) {
struct instruction *instruction;
uint8 *p, opcode;
p = (uint8 *)memchr(file_buf_data_pointer(fb), 0x00,
fb->size - file_buf_get_pos(fb));
fb->size - file_buf_get_pos(fb));
if (!p)
fatal_error("bad function @ %.4x", file_buf_get_pos(fb));
@ -92,7 +187,7 @@ static void parse_function(struct file_buf *fb, struct function *func) {
}
}
static void parse_vm(struct comprehend_game *game, struct file_buf *fb) {
static void parse_vm(struct comprehend_game * game, struct file_buf * fb) {
struct function *func;
file_buf_set_pos(fb, game->info->header.addr_vm);
@ -107,22 +202,22 @@ static void parse_vm(struct comprehend_game *game, struct file_buf *fb) {
}
}
static void parse_action_table_vvnn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vvnn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 verb, count;
int i, j;
/*
* <verb> <verb> <noun> <noun>
*
* u8: verb1
* u8: count
* u8: verb2
* u8: noun1
* u8: noun2
* le16: action
*/
* <verb> <verb> <noun> <noun>
*
* u8: verb1
* u8: count
* u8: verb2
* u8: noun1
* u8: noun2
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vvnn);
while (1) {
file_buf_get_u8(fb, &verb);
@ -151,22 +246,22 @@ static void parse_action_table_vvnn(struct comprehend_game *game,
}
}
static void parse_action_table_vnjn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vnjn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 join, count;
int i;
/*
* <verb> <noun> <join> <noun>
*
* u8: join
* u8: count
* u8: verb
* u8: noun1
* u8: noun2
* le16: action
*/
* <verb> <noun> <join> <noun>
*
* u8: join
* u8: count
* u8: verb
* u8: noun1
* u8: noun2
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vnjn);
while (1) {
file_buf_get_u8(fb, &join);
@ -196,21 +291,21 @@ static void parse_action_table_vnjn(struct comprehend_game *game,
}
}
static void parse_action_table_vjn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vjn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 join, count;
int i;
/*
* <verb> <join> <noun>
*
* u8: join
* u8: count
* u8: verb
* u8: noun
* le16: action
*/
* <verb> <join> <noun>
*
* u8: join
* u8: count
* u8: verb
* u8: noun
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vjn);
while (1) {
file_buf_get_u8(fb, &join);
@ -237,21 +332,21 @@ static void parse_action_table_vjn(struct comprehend_game *game,
}
}
static void parse_action_table_vdn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vdn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 verb, count;
int i;
/*
* <verb> <dir> <noun>
*
* u8: verb
* u8: count
* u8: dir
* u8: noun
* le16: action
*/
* <verb> <dir> <noun>
*
* u8: verb
* u8: count
* u8: dir
* u8: noun
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vdn);
while (1) {
file_buf_get_u8(fb, &verb);
@ -278,21 +373,21 @@ static void parse_action_table_vdn(struct comprehend_game *game,
}
}
static void parse_action_table_vnn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vnn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 verb, count;
int i;
/*
* <verb> <noun> <noun>
*
* u8: verb
* u8: count
* u8: noun1
* u8: noun2
* le16: action
*/
* <verb> <noun> <noun>
*
* u8: verb
* u8: count
* u8: noun1
* u8: noun2
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vnn);
while (1) {
/* 2-byte header */
@ -320,20 +415,20 @@ static void parse_action_table_vnn(struct comprehend_game *game,
}
}
static void parse_action_table_vn(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_vn(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 verb, count;
int i;
/*
* <verb> <noun>
*
* u8: verb
* u8: count
* u8: noun
* le16: action
*/
* <verb> <noun>
*
* u8: verb
* u8: count
* u8: noun
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_vn);
while (1) {
/* 2-byte header */
@ -359,20 +454,20 @@ static void parse_action_table_vn(struct comprehend_game *game,
}
}
static void parse_action_table_v(struct comprehend_game *game,
struct file_buf *fb, size_t *index) {
static void parse_action_table_v(struct comprehend_game * game,
struct file_buf * fb, size_t * index) {
struct action *action;
uint8 verb, nr_funcs;
uint16 func;
int i;
/*
* <verb> [<noun>]
*
* u8: verb
* u8: count (num actions)
* le16: action
*/
* <verb> [<noun>]
*
* u8: verb
* u8: count (num actions)
* le16: action
*/
file_buf_set_pos(fb, game->info->header.addr_actions_v);
while (1) {
file_buf_get_u8(fb, &verb);
@ -388,9 +483,9 @@ static void parse_action_table_v(struct comprehend_game *game,
action->word_type[0] = WORD_TYPE_VERB;
/*
* Default actions can have more than one function, but only
* the first one actually seems to be used?
*/
* Default actions can have more than one function, but only
* the first one actually seems to be used?
*/
file_buf_get_u8(fb, &nr_funcs);
for (i = 0; i < nr_funcs; i++) {
file_buf_get_le16(fb, &func);
@ -402,8 +497,8 @@ static void parse_action_table_v(struct comprehend_game *game,
}
}
static void parse_action_table(struct comprehend_game *game,
struct file_buf *fb) {
static void parse_action_table(struct comprehend_game * game,
struct file_buf * fb) {
game->info->nr_actions = 0;
if (game->info->comprehend_version == 1) {
@ -420,7 +515,7 @@ static void parse_action_table(struct comprehend_game *game,
parse_action_table_v(game, fb, &game->info->nr_actions);
}
static void parse_dictionary(struct comprehend_game *game, struct file_buf *fb) {
static void parse_dictionary(struct comprehend_game * game, struct file_buf * fb) {
word *words;
uint i, j;
@ -431,19 +526,19 @@ static void parse_dictionary(struct comprehend_game *game, struct file_buf *fb)
for (i = 0; i < game->info->nr_words; i++) {
words = &game->info->words[i];
file_buf_get_data(fb, words->word, 6);
file_buf_get_data(fb, words->_word, 6);
/* Decode */
for (j = 0; j < 6; j++)
words->word[j] ^= 0x8a;
words->word[6] = '\0';
words->_word[j] ^= 0x8a;
words->_word[6] = '\0';
file_buf_get_u8(fb, &words->index);
file_buf_get_u8(fb, &words->type);
file_buf_get_u8(fb, &words->_index);
file_buf_get_u8(fb, &words->_type);
}
}
static void parse_word_map(struct comprehend_game *game, struct file_buf *fb) {
static void parse_word_map(struct comprehend_game * game, struct file_buf * fb) {
struct word_map *map;
uint8 index, type, dummy;
uint i;
@ -452,9 +547,9 @@ static void parse_word_map(struct comprehend_game *game, struct file_buf *fb) {
file_buf_set_pos(fb, game->info->header.addr_word_map);
/*
* Parse the word pair table. Each entry has a pair of dictionary
* index/type values for a first and second word.
*/
* Parse the word pair table. Each entry has a pair of dictionary
* index/type values for a first and second word.
*/
while (1) {
map = &game->info->word_map[game->info->nr_word_maps];
@ -479,10 +574,10 @@ static void parse_word_map(struct comprehend_game *game, struct file_buf *fb) {
file_buf_get_u8(fb, &dummy);
/*
* Parse the target word table. Each entry has a dictionary
* index/type. The first and second words from above map to the
* target word here. E.g. 'go north' -> 'north'.
*/
* Parse the target word table. Each entry has a dictionary
* index/type. The first and second words from above map to the
* target word here. E.g. 'go north' -> 'north'.
*/
for (i = 0; i < game->info->nr_word_maps; i++) {
map = &game->info->word_map[i];
@ -491,7 +586,7 @@ static void parse_word_map(struct comprehend_game *game, struct file_buf *fb) {
}
}
static void parse_items(struct comprehend_game *game, struct file_buf *fb) {
static void parse_items(struct comprehend_game * game, struct file_buf * fb) {
size_t nr_items = game->info->header.nr_items;
/* Item descriptions */
@ -501,7 +596,7 @@ static void parse_items(struct comprehend_game *game, struct file_buf *fb) {
if (game->info->comprehend_version == 2) {
/* Comprehend version 2 adds long string descriptions */
file_buf_set_pos(fb, game->info->header.addr_item_strings +
(game->info->header.nr_items * sizeof(uint16)));
(game->info->header.nr_items * sizeof(uint16)));
file_buf_get_array_le16(fb, 0, game->info->item, long_string, nr_items);
}
@ -522,7 +617,7 @@ static void parse_items(struct comprehend_game *game, struct file_buf *fb) {
file_buf_get_array_u8(fb, 0, game->info->item, graphic, nr_items);
}
static void parse_rooms(struct comprehend_game *game, struct file_buf *fb) {
static void parse_rooms(struct comprehend_game * game, struct file_buf * fb) {
size_t nr_rooms = game->info->nr_rooms;
int i;
@ -530,7 +625,7 @@ static void parse_rooms(struct comprehend_game *game, struct file_buf *fb) {
for (i = 0; i < NR_DIRECTIONS; i++) {
file_buf_set_pos(fb, game->info->header.room_direction_table[i]);
file_buf_get_array_u8(fb, 1, game->info->rooms,
direction[i], nr_rooms);
direction[i], nr_rooms);
}
/* Room string descriptions */
@ -546,7 +641,7 @@ static void parse_rooms(struct comprehend_game *game, struct file_buf *fb) {
file_buf_get_array_u8(fb, 1, game->info->rooms, graphic, nr_rooms);
}
static uint64 string_get_chunk(uint8 *string) {
static uint64 string_get_chunk(uint8 * string) {
uint64 c, val = 0;
int i;
@ -567,11 +662,11 @@ static char decode_string_elem(uint8 c, bool capital, bool special) {
c = charset[c];
if (capital) {
/*
* A capital space means that the character
* is dynamically replaced by at runtime.
* We use the character '@' since it cannot
* otherwise appear in strings.
*/
* A capital space means that the character
* is dynamically replaced by at runtime.
* We use the character '@' since it cannot
* otherwise appear in strings.
*/
if (c == ' ')
return '@';
return c - 0x20;
@ -587,14 +682,14 @@ static char decode_string_elem(uint8 c, bool capital, bool special) {
}
/*
* Game strings are stored using 5-bit characters. By default a character
* value maps to the lower-case letter table. If a character has the value 0x1e
* then the next character is upper-case. An upper-case space is used to
* specify that the character should be replaced at runtime (like a '%s'
* specifier). If a character has the value 0x1f then the next character is
* taken from the symbols table.
*/
static char *parse_string(struct file_buf *fb) {
* Game strings are stored using 5-bit characters. By default a character
* value maps to the lower-case letter table. If a character has the value 0x1e
* then the next character is upper-case. An upper-case space is used to
* specify that the character should be replaced at runtime (like a '%s'
* specifier). If a character has the value 0x1f then the next character is
* taken from the symbols table.
*/
static char *parse_string(struct file_buf * fb) {
bool capital_next = false, special_next = false;
unsigned i, j, k = 0;
uint64 chunk;
@ -628,7 +723,7 @@ static char *parse_string(struct file_buf *fb) {
special_next = true;
} else {
c = decode_string_elem(elem, capital_next,
special_next);
special_next);
special_next = false;
capital_next = false;
string[k++] = c;
@ -643,8 +738,8 @@ done:
return string;
}
static void parse_string_table(struct file_buf *fb, unsigned start_addr,
uint32 end_addr, struct string_table *table) {
static void parse_string_table(struct file_buf * fb, unsigned start_addr,
uint32 end_addr, struct string_table *table) {
file_buf_set_pos(fb, start_addr);
while (1) {
table->strings[table->nr_strings++] = parse_string(fb);
@ -653,14 +748,14 @@ static void parse_string_table(struct file_buf *fb, unsigned start_addr,
}
}
static void parse_variables(struct comprehend_game *game, struct file_buf *fb) {
static void parse_variables(struct comprehend_game * game, struct file_buf * fb) {
int i;
for (i = 0; i < ARRAY_SIZE(game->info->variable); i++)
file_buf_get_le16(fb, &game->info->variable[i]);
}
static void parse_flags(struct comprehend_game *game, struct file_buf *fb) {
static void parse_flags(struct comprehend_game * game, struct file_buf * fb) {
int i, bit, flag_index = 0;
uint8 bitmask;
@ -673,8 +768,8 @@ static void parse_flags(struct comprehend_game *game, struct file_buf *fb) {
}
}
static void parse_replace_words(struct comprehend_game *game,
struct file_buf *fb) {
static void parse_replace_words(struct comprehend_game * game,
struct file_buf * fb) {
uint16 dummy;
size_t len;
bool eof;
@ -700,10 +795,10 @@ static void parse_replace_words(struct comprehend_game *game,
}
/*
* The main game data file header has the offsets for where each bit of
* game data is. The offsets have a magic constant value added to them.
*/
static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
* The main game data file header has the offsets for where each bit of
* game data is. The offsets have a magic constant value added to them.
*/
static void parse_header(struct comprehend_game * game, struct file_buf * fb) {
struct game_header *header = &game->info->header;
uint16 dummy, addr_dictionary_end;
uint8 dummy8;
@ -736,10 +831,10 @@ static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
parse_header_le16(fb, &dummy);
/*
* Action tables.
*
* Layout depends on the comprehend version.
*/
* Action tables.
*
* Layout depends on the comprehend version.
*/
if (game->info->comprehend_version == 1) {
parse_header_le16(fb, &header->addr_actions_vvnn);
parse_header_le16(fb, &header->addr_actions_unknown);
@ -777,10 +872,10 @@ static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
parse_header_le16(fb, &header->room_graphics_table);
/*
* Objects.
*
* Layout is dependent on comprehend version.
*/
* Objects.
*
* Layout is dependent on comprehend version.
*/
if (game->info->comprehend_version == 1) {
parse_header_le16(fb, &header->addr_item_locations);
parse_header_le16(fb, &header->addr_item_flags);
@ -789,7 +884,7 @@ static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
parse_header_le16(fb, &header->addr_item_graphics);
header->nr_items = (header->addr_item_word -
header->addr_item_flags);
header->addr_item_flags);
} else {
parse_header_le16(fb, &header->addr_item_strings);
@ -799,7 +894,7 @@ static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
parse_header_le16(fb, &header->addr_item_graphics);
header->nr_items = (header->addr_item_flags -
header->addr_item_locations);
header->addr_item_locations);
}
parse_header_le16(fb, &header->addr_strings);
@ -814,15 +909,15 @@ static void parse_header(struct comprehend_game *game, struct file_buf *fb) {
parse_flags(game, fb);
game->info->nr_rooms = header->room_direction_table[DIRECTION_SOUTH] -
header->room_direction_table[DIRECTION_NORTH];
header->room_direction_table[DIRECTION_NORTH];
game->info->nr_words = (addr_dictionary_end -
header->addr_dictionary) /
8;
header->addr_dictionary) /
8;
}
static void load_extra_string_file(comprehend_game *game,
string_file *string_file) {
static void load_extra_string_file(comprehend_game * game,
string_file * string_file) {
struct file_buf fb;
unsigned end;
@ -834,12 +929,12 @@ static void load_extra_string_file(comprehend_game *game,
end = fb.size;
parse_string_table(&fb, string_file->base_offset,
end, &game->info->strings2);
end, &game->info->strings2);
file_buf_unmap(&fb);
}
static void load_extra_string_files(comprehend_game *game) {
static void load_extra_string_files(comprehend_game * game) {
int i;
memset(&game->info->strings2, 0, sizeof(game->info->strings2));
@ -857,7 +952,7 @@ static void load_extra_string_files(comprehend_game *game) {
}
}
static void load_game_data(struct comprehend_game *game) {
static void load_game_data(struct comprehend_game * game) {
struct file_buf fb;
memset(game->info, 0, sizeof(*game->info));
@ -870,8 +965,8 @@ static void load_game_data(struct comprehend_game *game) {
parse_word_map(game, &fb);
memset(&game->info->strings, 0, sizeof(game->info->strings));
parse_string_table(&fb, game->info->header.addr_strings,
game->info->header.addr_strings_end,
&game->info->strings);
game->info->header.addr_strings_end,
&game->info->strings);
load_extra_string_files(game);
parse_vm(game, &fb);
parse_action_table(game, &fb);
@ -880,7 +975,7 @@ static void load_game_data(struct comprehend_game *game) {
file_buf_unmap(&fb);
}
void comprehend_load_game(struct comprehend_game *game) {
void comprehend_load_game(struct comprehend_game * game) {
/* Load the main game data file */
load_game_data(game);
@ -895,13 +990,13 @@ void comprehend_load_game(struct comprehend_game *game) {
}
#ifdef TODO
static void patch_string_desc(uint16 *desc) {
static void patch_string_desc(uint16 * desc) {
/*
* String descriptors in the save file sometimes are encoded as a
* table/index value like the instruction opcodes used, and other
* times the are encoded as an absolute index. We fix them up to
* all be the former type.
*/
* String descriptors in the save file sometimes are encoded as a
* table/index value like the instruction opcodes used, and other
* times the are encoded as an absolute index. We fix them up to
* all be the former type.
*/
if (!(*desc & 0x8000) && *desc >= 0x100) {
*desc -= 0x100;
*desc |= 0x8100;
@ -909,7 +1004,7 @@ static void patch_string_desc(uint16 *desc) {
}
#endif
void comprehend_save_game(struct comprehend_game *game, const char *filename) {
void comprehend_save_game(struct comprehend_game * game, const char *filename) {
#ifdef TODO
FILE *fd;
uint8 bitmask;
@ -919,7 +1014,7 @@ void comprehend_save_game(struct comprehend_game *game, const char *filename) {
fd = fopen(filename, "w");
if (!fd) {
printf("Error: Failed to open save file '%s': %s\n",
filename, strerror(errno));
filename, strerror(errno));
return;
}
@ -946,10 +1041,10 @@ void comprehend_save_game(struct comprehend_game *game, const char *filename) {
}
/*
* Re-Comprehend doesn't need this since the number of items is
* determined by the currently loaded game, but the original games
* won't load the file properly without it.
*/
* Re-Comprehend doesn't need this since the number of items is
* determined by the currently loaded game, but the original games
* won't load the file properly without it.
*/
file_buf_put_skip(fd, 0x12c - ftell(fd));
file_buf_put_u8(fd, nr_items);
@ -960,19 +1055,19 @@ void comprehend_save_game(struct comprehend_game *game, const char *filename) {
/* Rooms */
file_buf_put_array_le16(fd, 1, game->info->rooms,
string_desc, nr_rooms);
string_desc, nr_rooms);
for (dir = 0; dir < NR_DIRECTIONS; dir++)
file_buf_put_array_u8(fd, 1, game->info->rooms,
direction[dir], nr_rooms);
direction[dir], nr_rooms);
file_buf_put_array_u8(fd, 1, game->info->rooms, flags, nr_rooms);
file_buf_put_array_u8(fd, 1, game->info->rooms, graphic, nr_rooms);
/*
* Objects
*
* Layout differs depending on Comprehend version. Version 2 also
* has long string descriptions for each object.
*/
* Objects
*
* Layout differs depending on Comprehend version. Version 2 also
* has long string descriptions for each object.
*/
file_buf_put_array_le16(fd, 0, game->info->item, string_desc, nr_items);
if (game->info->comprehend_version == 1) {
file_buf_put_array_u8(fd, 0, game->info->item, room, nr_items);
@ -993,7 +1088,7 @@ void comprehend_save_game(struct comprehend_game *game, const char *filename) {
#endif
}
void comprehend_restore_game(struct comprehend_game *game, const char *filename) {
void comprehend_restore_game(struct comprehend_game * game, const char *filename) {
#ifdef TODO
struct file_buf fb;
size_t nr_rooms, nr_items;
@ -1002,7 +1097,7 @@ void comprehend_restore_game(struct comprehend_game *game, const char *filename)
err = file_buf_map_may_fail(filename, &fb);
if (err) {
printf("Error: Failed to open save file '%s': %s\n",
filename, strerror(-err));
filename, strerror(-err));
return;
}
@ -1026,19 +1121,19 @@ void comprehend_restore_game(struct comprehend_game *game, const char *filename)
/* Restore rooms */
file_buf_get_array_le16(&fb, 1, game->info->rooms,
string_desc, nr_rooms);
string_desc, nr_rooms);
for (dir = 0; dir < NR_DIRECTIONS; dir++)
file_buf_get_array_u8(&fb, 1, game->info->rooms,
direction[dir], nr_rooms);
direction[dir], nr_rooms);
file_buf_get_array_u8(&fb, 1, game->info->rooms, flags, nr_rooms);
file_buf_get_array_u8(&fb, 1, game->info->rooms, graphic, nr_rooms);
/*
* Restore objects
*
* Layout differs depending on Comprehend version. Version 2 also
* has long string descriptions for each object.
*/
* Restore objects
*
* Layout differs depending on Comprehend version. Version 2 also
* has long string descriptions for each object.
*/
file_buf_get_array_le16(&fb, 0, game->info->item, string_desc, nr_items);
if (game->info->comprehend_version == 1) {
file_buf_get_array_u8(&fb, 0, game->info->item, room, nr_items);
@ -1054,9 +1149,9 @@ void comprehend_restore_game(struct comprehend_game *game, const char *filename)
}
/*
* FIXME - The save file has some string descriptors masked with 0x8000.
* Not sure what this means, so just mask it out for now.
*/
* FIXME - The save file has some string descriptors masked with 0x8000.
* Not sure what this means, so just mask it out for now.
*/
for (i = 1; i <= nr_rooms; i++)
patch_string_desc(&game->info->rooms[i].string_desc);
for (i = 0; i < nr_items; i++)

View File

@ -50,6 +50,8 @@ struct function_state {
bool _and;
bool in_command;
bool executed;
function_state();
};
struct room {
@ -57,6 +59,8 @@ struct room {
uint8 flags;
uint8 graphic;
uint16 string_desc;
room();
};
struct item {
@ -66,23 +70,31 @@ struct item {
uint8 flags;
uint8 word;
uint8 graphic;
item();
};
struct word {
char word[7];
uint8 index;
uint8 type;
char _word[7];
uint8 _index;
uint8 _type;
word();
};
struct word_index {
uint8 index;
uint8 type;
word_index() : index(0), type(0) {}
};
struct word_map {
/* <word[0]>, <word[1]> == <word[2]> */
struct word_index word[3];
word_index word[3];
uint8 flags;
word_map() : flags(0) {}
};
struct action {
@ -92,6 +104,8 @@ struct action {
uint8 word[4];
uint8 word_type[4];
uint16 function;
action();
};
struct instruction {
@ -99,16 +113,22 @@ struct instruction {
size_t nr_operands;
uint8 operand[3];
bool is_command;
instruction();
};
struct function {
struct instruction instructions[0x100];
instruction instructions[0x100];
size_t nr_instructions;
function() : nr_instructions(0) {}
};
struct string_table {
char *strings[0xffff];
size_t nr_strings;
string_table();
};
struct game_header {
@ -142,16 +162,18 @@ struct game_header {
uint16 addr_actions_v;
uint16 addr_vm; // FIXME - functions
game_header();
};
struct game_info {
struct game_header header;
game_header header;
unsigned comprehend_version;
uint8 start_room;
struct room rooms[0x100];
room rooms[0x100];
size_t nr_rooms;
uint8 current_room;
@ -183,6 +205,8 @@ struct game_info {
uint8 current_replace_word;
unsigned update_flags;
game_info();
};
struct string_file {
@ -191,8 +215,7 @@ struct string_file {
uint32 end_offset;
string_file() : filename(nullptr), base_offset(0), end_offset(0) {}
string_file(const char *fname, uint32 baseOfs, uint32 endO = 0) :
filename(fname), base_offset(baseOfs), end_offset(endO) {
string_file(const char *fname, uint32 baseOfs, uint32 endO = 0) : filename(fname), base_offset(baseOfs), end_offset(endO) {
}
};