mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-04 08:17:40 +00:00
b8ad54b3af
svn-id: r14090
350 lines
11 KiB
C++
350 lines
11 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2001-2004 The ScummVM project
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
// Resource file routines for Simon1/Simon2
|
|
#include "stdafx.h"
|
|
#include "common/file.h"
|
|
#include "simon/simon.h"
|
|
#include "simon/intern.h"
|
|
|
|
namespace Simon {
|
|
|
|
// Script opcodes to load into memory
|
|
static const char *const opcode_arg_table_simon1win[256] = {
|
|
" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
|
|
"II ", "I ", "I ", "II ", "II ", "IBB ", "BIB ", "BB ", "B ", "BI ", "IB ", "B ", "B ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BN ", "BN ", "BB ", "BB ", "BN ", "BB ", "BN ", "B ", "I ", "IB ",
|
|
"IB ", "II ", "I ", "I ", "IN ", "B ", "T ", "T ", "NNNNNB ", "BT ", "BTS ", "T ", " ", "B ",
|
|
"N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ",
|
|
"IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NBNNN ", "N ",
|
|
" ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ",
|
|
"IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ",
|
|
"NN ", "N ", "N ", "Ban ", "BB ", " ", " ", " ", " ", "IB ", "B ", " ", "II ", " ", "BI ", "N ",
|
|
"I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "B ", "B ", "B ", "B ",
|
|
"IBB ", "IBN ", "IB ", "B ", "BNBN ", "BBTS ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ", "T ",
|
|
"T ", "B ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", " ", " ", "N ", "N ", " ",
|
|
" ",
|
|
};
|
|
|
|
static const char *const opcode_arg_table_simon1dos[256] = {
|
|
" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
|
|
"II ", "I ", "I ", "II ", "II ", "IBB ", "BIB ", "BB ", "B ", "BI ", "IB ", "B ", "B ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BN ", "BN ", "BB ", "BB ", "BN ", "BB ", "BN ", "B ", "I ", "IB ",
|
|
"IB ", "II ", "I ", "I ", "IN ", "B ", "T ", "T ", "NNNNNB ", "BT ", "BT ", "T ", " ", "B ",
|
|
"N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ",
|
|
"IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NBNNN ", "N ",
|
|
" ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ",
|
|
"IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ",
|
|
"NN ", "N ", "N ", "Ban ", "BB ", " ", " ", " ", " ", "IB ", "B ", " ", "II ", " ", "BI ", "N ",
|
|
"I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "B ", "B ", "B ", "B ",
|
|
"IBB ", "IBN ", "IB ", "B ", "BNBN ", "BBT ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ", "T ",
|
|
"T ", "B ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", " ", " ", "N ", "N ", " ",
|
|
" ",
|
|
};
|
|
|
|
static const char *const opcode_arg_table_simon2win[256] = {
|
|
" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
|
|
"II ", "I ", "I ", "II ", "II ", "IBB ", "BIB ", "BB ", "B ", "BI ", "IB ", "B ", "B ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BN ", "BN ", "BB ", "BB ", "BN ", "BB ", "BN ", "B ", "I ", "IB ",
|
|
"IB ", "II ", "I ", "I ", "IN ", "B ", "T ", "T ", "NNNNNB ", "BT ", "BTS ", "T ", " ", "B ",
|
|
"N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ",
|
|
"IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NNBNNN ", "NN ",
|
|
" ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ",
|
|
"IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ",
|
|
"NNB ", "N ", "N ", "Ban ", "BB ", " ", " ", " ", " ", "IB ", "B ", " ", "II ", " ", "BI ",
|
|
"N ", "I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "B ", "B ", "B ",
|
|
"B ", "IBB ", "IBN ", "IB ", "B ", "BNBN ", "BBTS ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ",
|
|
"T ", "T ", "B ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", " ", " ", "N ", "N ",
|
|
" ", " ", "BT ", " ", "B "
|
|
};
|
|
|
|
static const char *const opcode_arg_table_simon2dos[256] = {
|
|
" ", "I ", "I ", "I ", "I ", "I ", "I ", "II ", "II ", "II ", "II ", "B ", "B ", "BN ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BB ", "BB ", "II ", "II ", "N ", "I ", "I ", "I ", "IN ", "IB ",
|
|
"II ", "I ", "I ", "II ", "II ", "IBB ", "BIB ", "BB ", "B ", "BI ", "IB ", "B ", "B ", "BN ",
|
|
"BN ", "BN ", "BB ", "BB ", "BN ", "BN ", "BB ", "BB ", "BN ", "BB ", "BN ", "B ", "I ", "IB ",
|
|
"IB ", "II ", "I ", "I ", "IN ", "B ", "T ", "T ", "NNNNNB ", "BT ", "BT ", "T ", " ", "B ",
|
|
"N ", "IBN ", "I ", "I ", "I ", "NN ", " ", " ", "IT ", "II ", "I ", "B ", " ", "IB ", "IBB ",
|
|
"IIB ", "T ", " ", " ", "IB ", "IB ", "IB ", "B ", "BB ", "IBB ", "NB ", "N ", "NNBNNN ", "NN ",
|
|
" ", "BNNNNNN ", "B ", " ", "B ", "B ", "BB ", "NNNNNIN ", "N ", "N ", "N ", "NNN ", "NBNN ",
|
|
"IBNN ", "IB ", "IB ", "IB ", "IB ", "N ", "N ", "N ", "BI ", " ", " ", "N ", "I ", "IBB ",
|
|
"NNB ", "N ", "N ", "Ban ", "BB ", " ", " ", " ", " ", "IB ", "B ", " ", "II ", " ", "BI ",
|
|
"N ", "I ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "IB ", "BI ", "BB ", "B ", "B ", "B ",
|
|
"B ", "IBB ", "IBN ", "IB ", "B ", "BNBN ", "BBT ", "N ", " ", "Ian ", "B ", "B ", "B ", "B ",
|
|
"T ", "T ", "B ", " ", "I ", " ", " ", "BBI ", "NNBB ", "BBB ", " ", " ", " ", " ", "N ", "N ",
|
|
" ", " ", "BT ", " ", "B "
|
|
};
|
|
|
|
void SimonEngine::loadGamePcFile(const char *filename) {
|
|
File in;
|
|
int num_inited_objects;
|
|
int i, file_size;
|
|
|
|
/* read main gamepc file */
|
|
in.open(filename);
|
|
if (in.isOpen() == false) {
|
|
char *filename2;
|
|
filename2 = (char *)malloc(strlen(filename) + 2);
|
|
strcpy(filename2, filename);
|
|
strcat(filename2, ".");
|
|
in.open(filename2);
|
|
free(filename2);
|
|
if (in.isOpen() == false)
|
|
error("Can't open gamepc file '%s' or '%s.'", gss->gamepc_filename, gss->gamepc_filename);
|
|
}
|
|
|
|
num_inited_objects = allocGamePcVars(&in);
|
|
|
|
loginPlayer();
|
|
readGamePcText(&in);
|
|
|
|
for (i = 2; i < num_inited_objects; i++) {
|
|
readItemFromGamePc(&in, _itemarray_ptr[i]);
|
|
}
|
|
|
|
readSubroutineBlock(&in);
|
|
|
|
in.close();
|
|
|
|
/* Read list of TABLE resources */
|
|
in.open("TBLLIST");
|
|
if (in.isOpen() == false) {
|
|
in.open("TBLLIST.");
|
|
if (in.isOpen() == false)
|
|
error("Can't open table resources file 'TBLLIST' or 'TBLLIST.'");
|
|
}
|
|
|
|
file_size = in.size();
|
|
|
|
_tbl_list = (byte *)malloc(file_size);
|
|
if (_tbl_list == NULL)
|
|
error("Out of memory for strip table list");
|
|
in.read(_tbl_list, file_size);
|
|
in.close();
|
|
|
|
/* Remember the current state */
|
|
_subroutine_list_org = _subroutine_list;
|
|
_tablesheap_ptr_org = _tablesheap_ptr;
|
|
_tablesheap_curpos_org = _tablesheap_curpos;
|
|
|
|
/* Read list of TEXT resources */
|
|
if (_game == GAME_SIMON1ACORN)
|
|
in.open("STRIPPED");
|
|
else
|
|
in.open("STRIPPED.TXT");
|
|
if (in.isOpen() == false)
|
|
error("Can't open text resources file 'STRIPPED.TXT'");
|
|
|
|
file_size = in.size();
|
|
_stripped_txt_mem = (byte *)malloc(file_size);
|
|
if (_stripped_txt_mem == NULL)
|
|
error("Out of memory for strip text list");
|
|
in.read(_stripped_txt_mem, file_size);
|
|
in.close();
|
|
}
|
|
|
|
void SimonEngine::readGamePcText(File *in) {
|
|
uint text_size;
|
|
byte *text_mem;
|
|
|
|
_text_size = text_size = in->readUint32BE();
|
|
text_mem = (byte *)malloc(text_size);
|
|
if (text_mem == NULL)
|
|
error("Out of text memory");
|
|
|
|
in->read(text_mem, text_size);
|
|
|
|
setupStringTable(text_mem, _stringtab_num);
|
|
}
|
|
|
|
void SimonEngine::readItemFromGamePc(File *in, Item *item) {
|
|
uint32 type;
|
|
|
|
item->unk2 = in->readUint16BE();
|
|
item->unk1 = in->readUint16BE();
|
|
item->unk3 = in->readUint16BE();
|
|
item->sibling = (uint16)fileReadItemID(in);
|
|
item->child = (uint16)fileReadItemID(in);
|
|
item->parent = (uint16)fileReadItemID(in);
|
|
in->readUint16BE();
|
|
item->unk4 = in->readUint16BE();
|
|
item->children = NULL;
|
|
|
|
type = in->readUint32BE();
|
|
while (type) {
|
|
type = in->readUint16BE();
|
|
if (type != 0)
|
|
readItemChildren(in, item, type);
|
|
}
|
|
}
|
|
|
|
void SimonEngine::readItemChildren(File *in, Item *item, uint type) {
|
|
if (type == 1) {
|
|
uint fr1 = in->readUint16BE();
|
|
uint fr2 = in->readUint16BE();
|
|
uint i, size;
|
|
uint j, k;
|
|
Child1 *child;
|
|
|
|
size = CHILD1_SIZE;
|
|
for (i = 0, j = fr2; i != 6; i++, j >>= 2)
|
|
if (j & 3)
|
|
size += sizeof(child->array[0]);
|
|
|
|
child = (Child1 *)allocateChildBlock(item, 1, size);
|
|
child->subroutine_id = fr1;
|
|
child->fr2 = fr2;
|
|
|
|
for (i = k = 0, j = fr2; i != 6; i++, j >>= 2)
|
|
if (j & 3)
|
|
child->array[k++] = (uint16)fileReadItemID(in);
|
|
} else if (type == 2) {
|
|
uint32 fr = in->readUint32BE();
|
|
uint i, k, size;
|
|
Child2 *child;
|
|
|
|
size = CHILD2_SIZE;
|
|
for (i = 0; i != 16; i++)
|
|
if (fr & (1 << i))
|
|
size += sizeof(child->array[0]);
|
|
|
|
child = (Child2 *)allocateChildBlock(item, 2, size);
|
|
child->avail_props = fr;
|
|
|
|
k = 0;
|
|
if (fr & 1) {
|
|
child->array[k++] = (uint16)in->readUint32BE();
|
|
}
|
|
for (i = 1; i != 16; i++)
|
|
if (fr & (1 << i))
|
|
child->array[k++] = in->readUint16BE();
|
|
|
|
child->string_id = (uint16)in->readUint32BE();
|
|
} else {
|
|
error("readItemChildren: invalid mode");
|
|
}
|
|
}
|
|
|
|
uint fileReadItemID(File *in) {
|
|
uint32 val = in->readUint32BE();
|
|
if (val == 0xFFFFFFFF)
|
|
return 0;
|
|
return val + 2;
|
|
}
|
|
|
|
byte *SimonEngine::readSingleOpcode(File *in, byte *ptr) {
|
|
int i, l;
|
|
const char *string_ptr;
|
|
uint val;
|
|
|
|
const char *const *table;
|
|
|
|
if ((_game & GF_SIMON2) && (_game & GF_TALKIE))
|
|
table = opcode_arg_table_simon2win;
|
|
else if (_game & GF_SIMON2)
|
|
table = opcode_arg_table_simon2dos;
|
|
else if (_game & GF_TALKIE)
|
|
table = opcode_arg_table_simon1win;
|
|
else
|
|
table = opcode_arg_table_simon1dos;
|
|
|
|
i = 0;
|
|
|
|
string_ptr = table[*ptr++];
|
|
if (!string_ptr)
|
|
error("Unable to locate opcode table. Perhaps you are using the wrong game target?");
|
|
|
|
for (;;) {
|
|
if (string_ptr[i] == ' ')
|
|
return ptr;
|
|
|
|
l = string_ptr[i++];
|
|
switch (l) {
|
|
case 'N':
|
|
case 'S':
|
|
case 'a':
|
|
case 'n':
|
|
case 'p':
|
|
case 'v':
|
|
val = in->readUint16BE();
|
|
*ptr++ = val >> 8;
|
|
*ptr++ = val & 255;
|
|
break;
|
|
|
|
case 'B':
|
|
*ptr++ = in->readByte();
|
|
if (ptr[-1] == 0xFF) {
|
|
*ptr++ = in->readByte();
|
|
}
|
|
break;
|
|
|
|
case 'I':
|
|
val = in->readUint16BE();
|
|
switch (val) {
|
|
case 1:
|
|
val = 0xFFFF;
|
|
break;
|
|
case 3:
|
|
val = 0xFFFD;
|
|
break;
|
|
case 5:
|
|
val = 0xFFFB;
|
|
break;
|
|
case 7:
|
|
val = 0xFFF9;
|
|
break;
|
|
case 9:
|
|
val = 0xFFF7;
|
|
break;
|
|
default:
|
|
val = fileReadItemID(in);;
|
|
}
|
|
*ptr++ = val >> 8;
|
|
*ptr++ = val & 255;
|
|
break;
|
|
|
|
case 'T':
|
|
val = in->readUint16BE();
|
|
switch (val) {
|
|
case 0:
|
|
val = 0xFFFF;
|
|
break;
|
|
case 3:
|
|
val = 0xFFFD;
|
|
break;
|
|
default:
|
|
val = (uint16)in->readUint32BE();
|
|
break;
|
|
}
|
|
*ptr++ = val >> 8;
|
|
*ptr++ = val & 255;
|
|
break;
|
|
default:
|
|
error("Bad cmd table entry %c", l);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace Simon
|