2007-05-30 21:56:52 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
2006-07-23 13:08:22 +00:00
|
|
|
*
|
|
|
|
* 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
|
2008-01-05 12:45:14 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2006-07-23 13:08:22 +00:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-10-30 22:44:15 +00:00
|
|
|
// Disable symbol overrides so that we can use system headers.
|
|
|
|
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
#include "common/scummsys.h"
|
2007-09-23 22:05:50 +00:00
|
|
|
#include "common/util.h"
|
2006-07-23 13:08:22 +00:00
|
|
|
#include "create_lure_dat.h"
|
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
using namespace Common;
|
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
enum Action {
|
|
|
|
GET = 1, PUSH = 3, PULL = 4, OPERATE = 5, OPEN = 6, CLOSE = 7, LOCK = 8,
|
|
|
|
UNLOCK = 9, USE = 10, GIVE = 11, TALK_TO = 12, TELL = 13, BUY = 14,
|
|
|
|
LOOK = 15, LOOK_AT = 16, LOOK_THROUGH = 17, ASK = 18, DRINK = 20,
|
|
|
|
STATUS = 21, GO_TO = 22, RETURN = 23, BRIBE = 24, EXAMINE = 25,
|
2008-01-27 19:47:41 +00:00
|
|
|
NPC_SET_ROOM_AND_BLOCKED_OFFSET = 28, NPC_HEY_SIR = 29, NPC_EXEC_SCRIPT = 30,
|
|
|
|
NPC_RESET_PAUSED_LIST = 31, NPC_SET_RAND_DEST = 32, NPC_WALKING_CHECK = 33,
|
|
|
|
NPC_SET_SUPPORT_OFFSET = 34, NPC_SUPPORT_OFFSET_COND = 35,
|
|
|
|
NPC_DISPATCH_ACTION = 36, NPC_TALK_NPC_TO_NPC = 37, NPC_PAUSE = 38,
|
2006-07-23 13:08:22 +00:00
|
|
|
NPC_START_TALKING = 39, NPC_JUMP_ADDRESS = 40,
|
|
|
|
NONE = 0
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CurrentActionOutput {
|
|
|
|
uint8 action;
|
|
|
|
uint8 hsAction;
|
|
|
|
uint16 roomNumber;
|
|
|
|
uint16 hotspotId;
|
|
|
|
uint16 usedId;
|
|
|
|
};
|
|
|
|
|
2008-01-27 19:47:41 +00:00
|
|
|
int numParams[NPC_JUMP_ADDRESS+1] = {0,
|
2006-07-23 13:08:22 +00:00
|
|
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1,
|
2007-02-22 06:24:48 +00:00
|
|
|
0, 1, 1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 1, 2, 2, 5, 2, 2, 1};
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
#define NUM_JUMP_OFFSETS 2
|
2007-09-23 22:05:50 +00:00
|
|
|
|
|
|
|
struct JumpOffsetsRecord {
|
|
|
|
Common::Language language;
|
|
|
|
uint16 jumpOffsets[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
JumpOffsetsRecord jumpOffsets[] = {
|
|
|
|
{EN_ANY, {0x87be, 0x881c}},
|
|
|
|
{IT_ITA, {0x881c, 0x887a}},
|
2007-11-22 10:15:20 +00:00
|
|
|
{FR_FRA, {0x8bbf, 0x8c18}},
|
|
|
|
{DE_DEU, {0x8c1c, 0x8c75}},
|
2007-11-28 10:40:46 +00:00
|
|
|
{ES_ESP, {0x8882, 0x88e0}},
|
2007-09-23 22:05:50 +00:00
|
|
|
{UNK_LANG, {0, 0}}
|
|
|
|
};
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
#define MAX_BUFFER_ENTRIES 63
|
2006-07-23 13:08:22 +00:00
|
|
|
#define MAX_INSTRUCTION_ENTRIES 300
|
2007-02-22 06:24:48 +00:00
|
|
|
#define SCHEDULE_DATA_OFFSET 0x80
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
struct SupportStructure {
|
|
|
|
uint16 offset;
|
|
|
|
int numInstructions;
|
2008-01-27 19:47:41 +00:00
|
|
|
uint16 instructionOffsets[MAX_INSTRUCTION_ENTRIES];
|
2006-07-23 13:08:22 +00:00
|
|
|
uint16 resourceOffset;
|
|
|
|
};
|
|
|
|
|
|
|
|
SupportStructure supportList[MAX_BUFFER_ENTRIES];
|
|
|
|
uint16 numSupportEntries = 0;
|
|
|
|
|
|
|
|
#define FORWARD_JUMP_ALLOWANCE 0x30
|
|
|
|
|
|
|
|
uint16 get_sequence_index(uint16 offset, int supportIndex) {
|
|
|
|
int index;
|
|
|
|
|
|
|
|
if (supportIndex != -1) {
|
|
|
|
// Within a sequence, so if an offset is within it, it's a local jump
|
|
|
|
for (index = 0; index < supportList[supportIndex].numInstructions; ++index) {
|
|
|
|
if (supportList[supportIndex].instructionOffsets[index] == offset)
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-28 07:58:11 +00:00
|
|
|
for (index = 0; index < numSupportEntries; ++index) {
|
2006-07-23 13:08:22 +00:00
|
|
|
SupportStructure &rec = supportList[index];
|
|
|
|
|
|
|
|
if ((rec.numInstructions > 0) &&
|
2008-01-27 19:47:41 +00:00
|
|
|
(offset >= rec.instructionOffsets[0]) &&
|
2006-07-23 13:08:22 +00:00
|
|
|
(offset <= rec.instructionOffsets[rec.numInstructions - 1])) {
|
|
|
|
// Scan through the entry's insruction list
|
|
|
|
for (int iIndex = 0; iIndex < rec.numInstructions; ++iIndex) {
|
|
|
|
if (rec.instructionOffsets[iIndex] == offset) {
|
|
|
|
return ((index + 1) << 10) | iIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct SymbolTableEntry {
|
|
|
|
uint16 *p;
|
|
|
|
bool globalNeeded;
|
|
|
|
};
|
|
|
|
|
|
|
|
uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remainingSize) {
|
|
|
|
SupportStructure &rec = supportList[supportIndex];
|
|
|
|
uint16 startOffset = rec.offset;
|
|
|
|
uint16 maxOffset = 0;
|
2007-09-23 22:05:50 +00:00
|
|
|
|
|
|
|
switch (language) {
|
|
|
|
case EN_ANY:
|
|
|
|
if (startOffset == 0x7dcb) { startOffset = 0x7d9d; maxOffset = 0x7dcb; }
|
|
|
|
if (startOffset == 0x7248) { startOffset = 0x71ce; maxOffset = 0x7248; }
|
|
|
|
if (startOffset == 0x79a8) { startOffset = 0x785c; maxOffset = 0x79a8; }
|
|
|
|
if (startOffset == 0x6f4f) { startOffset = 0x6e5d; maxOffset = 0x6fe5; }
|
|
|
|
if (startOffset == 0x76ec) { startOffset = 0x734a; maxOffset = 0x77a2; }
|
|
|
|
break;
|
|
|
|
case IT_ITA:
|
|
|
|
if (startOffset == 0x7e8b) { startOffset = 0x7e5d; maxOffset = 0x7eb5; }
|
|
|
|
if (startOffset == 0x7a68) { startOffset = 0x791c; maxOffset = 0x7a92; }
|
|
|
|
if (startOffset == 0x7308) { startOffset = 0x7308; maxOffset = 0x7362; }
|
|
|
|
if (startOffset == 0x7308) { startOffset = 0x728e; maxOffset = 0x7362; }
|
|
|
|
if (startOffset == 0x700f) { startOffset = 0x700f; maxOffset = 0x7083; }
|
|
|
|
if (startOffset == 0x700f) { startOffset = 0x6f1d; maxOffset = 0x70a5; }
|
|
|
|
if (startOffset == 0x7866) { startOffset = 0x740a; maxOffset = 0x7876; }
|
|
|
|
if (startOffset == 0x3600) { startOffset = 0x35c6; maxOffset = 0x3622; }
|
|
|
|
break;
|
2007-11-22 10:15:20 +00:00
|
|
|
case FR_FRA:
|
|
|
|
if (startOffset == 0x7eab) { startOffset = 0x7e7d; maxOffset = 0x7ed5; }
|
|
|
|
if (startOffset == 0x7a88) { startOffset = 0x793c; maxOffset = 0x7ab2; }
|
|
|
|
if (startOffset == 0x7328) { startOffset = 0x72ae; maxOffset = 0x7382; }
|
|
|
|
if (startOffset == 0x702f) { startOffset = 0x6f3d; maxOffset = 0x70a3; }
|
|
|
|
if (startOffset == 0x7886) { startOffset = 0x742a; maxOffset = 0x7896; }
|
2013-07-15 08:51:57 +00:00
|
|
|
break;
|
2007-11-22 10:15:20 +00:00
|
|
|
case DE_DEU:
|
|
|
|
if (startOffset == 0x7edb) { startOffset = 0x7ead; maxOffset = 0x7f05; }
|
|
|
|
if (startOffset == 0x7ab8) { startOffset = 0x796c; maxOffset = 0x7ae2; }
|
|
|
|
if (startOffset == 0x7358) { startOffset = 0x72de; maxOffset = 0x73b2; }
|
|
|
|
if (startOffset == 0x705f) { startOffset = 0x6f6d; maxOffset = 0x70d3; }
|
|
|
|
if (startOffset == 0x78b6) { startOffset = 0x745a; maxOffset = 0x78c6; }
|
|
|
|
break;
|
2007-09-24 01:46:45 +00:00
|
|
|
default:
|
2007-11-28 10:40:46 +00:00
|
|
|
if (startOffset == 0x7eab) { startOffset = 0x7e7d; maxOffset = 0x7ed5; }
|
|
|
|
if (startOffset == 0x7a88) { startOffset = 0x793c; maxOffset = 0x7ab2; }
|
|
|
|
if (startOffset == 0x7328) { startOffset = 0x72ae; maxOffset = 0x7382; }
|
|
|
|
if (startOffset == 0x702f) { startOffset = 0x702f; maxOffset = 0x70a3; }
|
|
|
|
if (startOffset == 0x702f) { startOffset = 0x6f3d; maxOffset = 0x70c5; }
|
|
|
|
if (startOffset == 0x7886) { startOffset = 0x742a; maxOffset = 0x7896; }
|
2007-09-24 01:46:45 +00:00
|
|
|
break;
|
2007-09-23 22:05:50 +00:00
|
|
|
}
|
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
//printf("Start=%xh max=%xh\n", startOffset, maxOffset);
|
2006-07-23 13:08:22 +00:00
|
|
|
SymbolTableEntry symbolTable[MAX_INSTRUCTION_ENTRIES];
|
|
|
|
uint16 numSymbols = 0;
|
|
|
|
uint16 offset = startOffset;
|
|
|
|
uint16 totalSize = 0;
|
|
|
|
uint16 actionNum = 0;
|
|
|
|
uint16 paramIndex;
|
|
|
|
uint16 params[5];
|
|
|
|
uint16 index;
|
|
|
|
uint16 *pOut = (uint16 *) data;
|
2007-09-23 22:05:50 +00:00
|
|
|
JumpOffsetsRecord *jmpOffset;
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.seek(dataSegment + startOffset);
|
2006-07-23 13:08:22 +00:00
|
|
|
rec.numInstructions = 0;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (remainingSize < 10) {
|
|
|
|
printf("Ran out of space to process NPC action sequences\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for end of sequence set with prior instruction
|
|
|
|
if ((actionNum == NPC_SET_SUPPORT_OFFSET) && ((maxOffset == 0) ||
|
|
|
|
(offset > maxOffset)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Mark the offset of the next instruction
|
|
|
|
rec.instructionOffsets[rec.numInstructions++] = offset;
|
|
|
|
if (rec.numInstructions == MAX_INSTRUCTION_ENTRIES) {
|
|
|
|
printf("A method exceeded the maximum allowable number of instructions\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get in the next action
|
2007-09-23 22:05:50 +00:00
|
|
|
actionNum = lureExe.readWord();
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
//printf("%xh - action=%d", offset, actionNum);
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
if (actionNum == 0) {
|
|
|
|
// At end of script block
|
2007-09-23 22:05:50 +00:00
|
|
|
//printf("\n");
|
2006-07-23 13:08:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (actionNum > NPC_JUMP_ADDRESS) {
|
|
|
|
// Unknown action code - halt execution
|
|
|
|
printf("%xh - unknown action %d\n", offset, actionNum);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
*pOut++ = TO_LE_16(actionNum);
|
|
|
|
|
|
|
|
// Read in any action parameters
|
|
|
|
for (int paramCtr = 0; paramCtr < numParams[actionNum]; ++paramCtr)
|
2007-09-23 22:05:50 +00:00
|
|
|
params[paramCtr] = lureExe.readWord();
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2009-09-30 16:16:53 +00:00
|
|
|
switch (actionNum) {
|
2006-07-23 13:08:22 +00:00
|
|
|
case NPC_SET_ROOM_AND_BLOCKED_OFFSET:
|
|
|
|
case NPC_SET_SUPPORT_OFFSET:
|
|
|
|
case NPC_SUPPORT_OFFSET_COND:
|
|
|
|
case NPC_DISPATCH_ACTION:
|
|
|
|
// These instructions have a support record parameter. Store the
|
|
|
|
// offset the parameter will be in the output data so we can come
|
|
|
|
// back at the end and resolve it
|
|
|
|
paramIndex = (actionNum == NPC_SET_SUPPORT_OFFSET) ? 0 : 1;
|
|
|
|
symbolTable[numSymbols].globalNeeded = actionNum == NPC_SET_ROOM_AND_BLOCKED_OFFSET;
|
|
|
|
symbolTable[numSymbols].p = pOut + paramIndex;
|
|
|
|
++numSymbols;
|
|
|
|
|
|
|
|
// Special check for forward references - it's considered to be in
|
|
|
|
// the same block if it's forward within 100h blocks
|
2008-01-27 19:47:41 +00:00
|
|
|
if ((params[paramIndex] > offset) &&
|
2006-07-23 13:08:22 +00:00
|
|
|
(params[paramIndex] < offset + FORWARD_JUMP_ALLOWANCE) &&
|
|
|
|
(params[paramIndex] > maxOffset)) {
|
|
|
|
maxOffset = params[paramIndex];
|
2008-01-27 19:47:41 +00:00
|
|
|
}
|
2006-07-23 13:08:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NPC_JUMP_ADDRESS:
|
|
|
|
// Make sure the address is in the known list
|
2007-09-23 22:05:50 +00:00
|
|
|
jmpOffset = &jumpOffsets[0];
|
|
|
|
while (jmpOffset->language != language) ++jmpOffset;
|
2006-07-23 13:08:22 +00:00
|
|
|
index = 0;
|
2007-09-23 22:05:50 +00:00
|
|
|
while ((index < NUM_JUMP_OFFSETS) && (jmpOffset->jumpOffsets[index] != params[0]))
|
2006-07-23 13:08:22 +00:00
|
|
|
++index;
|
2008-01-27 19:47:41 +00:00
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
if (index != NUM_JUMP_OFFSETS)
|
2008-01-27 19:47:41 +00:00
|
|
|
// Replace code offset with an index
|
2006-07-23 13:08:22 +00:00
|
|
|
params[0] = index;
|
|
|
|
else {
|
2011-11-26 16:40:00 +00:00
|
|
|
printf("\nEncountered unrecognized NPC code jump point: %xh\n", params[0]);
|
2006-07-23 13:08:22 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2007-02-26 02:46:32 +00:00
|
|
|
case NPC_HEY_SIR:
|
2008-01-27 19:47:41 +00:00
|
|
|
// The 'Hey Sir' opcode causes the NPC to request your attention, and sets the active talk
|
2007-02-26 02:46:32 +00:00
|
|
|
// record to a designated offset. So any offset occurances need to be saved so that it can
|
|
|
|
// be included in the resource for talk records
|
|
|
|
add_talk_offset(params[0]);
|
|
|
|
break;
|
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output parameters
|
|
|
|
for (paramIndex = 0; paramIndex < numParams[actionNum]; ++paramIndex)
|
2007-02-22 06:24:48 +00:00
|
|
|
{
|
2006-07-23 13:08:22 +00:00
|
|
|
*pOut++ = TO_LE_16(params[paramIndex]);
|
2007-09-23 22:05:50 +00:00
|
|
|
//printf(" %xh", TO_LE_16(params[paramIndex]));
|
2007-02-22 06:24:48 +00:00
|
|
|
}
|
2007-09-23 22:05:50 +00:00
|
|
|
//printf("\n");
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
// Increase size
|
2008-01-27 19:47:41 +00:00
|
|
|
totalSize += (numParams[actionNum] + 1) * sizeof(uint16);
|
2006-07-23 13:08:22 +00:00
|
|
|
offset = startOffset + totalSize;
|
|
|
|
remainingSize -= (numParams[actionNum] + 1) * sizeof(uint16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flag an end of the sequence
|
|
|
|
*pOut++ = 0;
|
|
|
|
totalSize += sizeof(uint16);
|
|
|
|
|
|
|
|
// handle post-processing of the symbol list
|
|
|
|
|
|
|
|
for (int symbolCtr = 0; symbolCtr < numSymbols; ++symbolCtr) {
|
2008-01-27 19:47:41 +00:00
|
|
|
if (READ_LE_UINT16(symbolTable[symbolCtr].p) == 0)
|
2006-07-23 13:08:22 +00:00
|
|
|
// No Id special constant
|
|
|
|
WRITE_LE_UINT16(symbolTable[symbolCtr].p, 0xffff);
|
|
|
|
else {
|
|
|
|
// Handle resolving the constant
|
2008-01-27 19:47:41 +00:00
|
|
|
index = get_sequence_index(READ_LE_UINT16(symbolTable[symbolCtr].p),
|
2006-07-23 13:08:22 +00:00
|
|
|
symbolTable[symbolCtr].globalNeeded ? -1 : supportIndex);
|
|
|
|
//printf("Symbol %xh => %xh\n", *symbolTable[symbolCtr].p, index);
|
|
|
|
if (index != 0xffff) {
|
2008-01-27 19:47:41 +00:00
|
|
|
// Jump found - so replace symbol entry with it
|
2006-07-23 13:08:22 +00:00
|
|
|
WRITE_LE_UINT16(symbolTable[symbolCtr].p, index);
|
|
|
|
} else {
|
2008-01-27 19:47:41 +00:00
|
|
|
printf("Sequence contained unknown offset %xh\n",
|
2006-07-23 13:08:22 +00:00
|
|
|
READ_LE_UINT16(symbolTable[symbolCtr].p));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return totalSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void process_entry(uint16 offset, byte *data, uint16 &totalSize) {
|
|
|
|
if (get_sequence_index(offset) == 0xffff) {
|
|
|
|
// Process the next entry
|
|
|
|
supportList[numSupportEntries].offset = offset;
|
|
|
|
supportList[numSupportEntries].numInstructions = 0;
|
|
|
|
supportList[numSupportEntries].resourceOffset = totalSize;
|
|
|
|
|
|
|
|
++numSupportEntries;
|
|
|
|
if (numSupportEntries == MAX_BUFFER_ENTRIES) {
|
|
|
|
printf("Ran out of buffer space in processing NPC schedules\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2007-09-28 07:58:11 +00:00
|
|
|
|
|
|
|
//printf("process_entry index=%d, offset=%xh\n", numSupportEntries, offset);
|
2008-01-27 19:47:41 +00:00
|
|
|
totalSize += process_action_sequence_entry(numSupportEntries - 1,
|
2007-09-28 07:58:11 +00:00
|
|
|
data + totalSize, MAX_DATA_SIZE - totalSize);
|
2006-07-23 13:08:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
struct RoomRandomActionEntry {
|
|
|
|
bool repeatable;
|
|
|
|
uint16 offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RoomRandomActionSet {
|
|
|
|
uint16 offset;
|
|
|
|
uint8 numEntries;
|
|
|
|
RoomRandomActionEntry *entries;
|
|
|
|
};
|
|
|
|
|
2009-10-02 14:42:24 +00:00
|
|
|
void read_action_sequence(byte *&data, uint16 &totalSize) {
|
2006-07-23 13:08:22 +00:00
|
|
|
uint16 hotspotIndex;
|
|
|
|
HotspotHeaderEntry entryHeader;
|
|
|
|
CurrentActionInput action;
|
|
|
|
uint16 *pHeader;
|
2007-02-22 06:24:48 +00:00
|
|
|
int index, roomIndex;
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
// Allocate enough space for output sequence list
|
|
|
|
data = (byte *) malloc(MAX_DATA_SIZE);
|
|
|
|
|
|
|
|
// Get a list of offsets used in the script engine
|
|
|
|
uint16 offsetList[NUM_TABLED_ACTION_BLOCKS];
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.seek(dataSegment + TABLED_ACTIONS_OFFSET, SEEK_SET);
|
2006-07-23 13:08:22 +00:00
|
|
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
2007-09-23 22:05:50 +00:00
|
|
|
offsetList[index] = lureExe.readWord();
|
2007-02-22 06:24:48 +00:00
|
|
|
totalSize = sizeof(uint16) * (NUM_TABLED_ACTION_BLOCKS + 1);
|
|
|
|
|
|
|
|
/* Process the list of random actions that your follower can do in each room */
|
|
|
|
RoomRandomActionSet *randomActions = new RoomRandomActionSet[RANDOM_ROOM_NUM_ENTRIES];
|
2008-01-27 19:47:41 +00:00
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
// Get a list of the offsets for each room
|
2007-09-23 22:05:50 +00:00
|
|
|
uint16 raOffset = 0x4D10;
|
|
|
|
if (language == IT_ITA) raOffset = 0x4dc0;
|
2007-11-22 10:15:20 +00:00
|
|
|
else if (language == FR_FRA) raOffset = 0x4df0;
|
|
|
|
else if (language == DE_DEU) raOffset = 0x4de0;
|
2007-11-28 10:40:46 +00:00
|
|
|
else if (language == ES_ESP) raOffset = 0x4dc0;
|
2007-11-22 10:15:20 +00:00
|
|
|
else if (language != EN_ANY) errorExit("read_action_sequence: Unknown language");
|
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.seek(dataSegment + raOffset, SEEK_SET);
|
|
|
|
for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex) {
|
|
|
|
randomActions[roomIndex].offset = lureExe.readWord();
|
2007-02-22 06:24:48 +00:00
|
|
|
randomActions[roomIndex].numEntries = 0;
|
|
|
|
randomActions[roomIndex].entries = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next get the set of offsetes for the start of each sequence
|
2009-10-02 14:42:24 +00:00
|
|
|
for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex) {
|
2007-02-22 06:24:48 +00:00
|
|
|
if (randomActions[roomIndex].offset == 0)
|
|
|
|
continue;
|
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.seek(dataSegment + randomActions[roomIndex].offset, SEEK_SET);
|
|
|
|
randomActions[roomIndex].numEntries = lureExe.readByte();
|
2007-02-22 06:24:48 +00:00
|
|
|
assert(randomActions[roomIndex].numEntries <= 8);
|
|
|
|
randomActions[roomIndex].entries = new RoomRandomActionEntry[randomActions[roomIndex].numEntries];
|
|
|
|
|
|
|
|
// Loop through the entries
|
|
|
|
uint16 offset = randomActions[roomIndex].offset + 1;
|
2009-10-02 14:42:24 +00:00
|
|
|
for (uint8 entryCtr = 0; entryCtr < randomActions[roomIndex].numEntries; ++entryCtr) {
|
2007-09-23 22:05:50 +00:00
|
|
|
randomActions[roomIndex].entries[entryCtr].repeatable = lureExe.readWord() == 1;
|
2007-02-22 06:24:48 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
uint16 firstCommand = lureExe.readWord();
|
2008-01-27 19:47:41 +00:00
|
|
|
randomActions[roomIndex].entries[entryCtr].offset =
|
2007-02-22 06:24:48 +00:00
|
|
|
(firstCommand == 0xfffe) ? 0 : offset;
|
2008-01-27 19:47:41 +00:00
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
offset += sizeof(uint16);
|
2008-01-27 19:47:41 +00:00
|
|
|
while (lureExe.readWord() != 0xffff)
|
2007-02-22 06:24:48 +00:00
|
|
|
offset += sizeof(uint16);
|
|
|
|
offset += sizeof(uint16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust the total size to accomodate random action data in the output
|
|
|
|
totalSize += sizeof(uint16) * randomActions[roomIndex].numEntries +
|
|
|
|
(sizeof(uint16) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
totalSize += sizeof(uint16) + MAX_BUFFER_ENTRIES * sizeof(uint16);
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
numSupportEntries = 0;
|
|
|
|
|
|
|
|
// Handle required initial entries - the Lure engine refers to them directly by
|
|
|
|
// index, so they need to be first, and in that order
|
2007-09-23 22:05:50 +00:00
|
|
|
switch (language) {
|
|
|
|
case EN_ANY:
|
|
|
|
process_entry(0x13c2, data, totalSize); // RETURN sequence
|
|
|
|
process_entry(0xbb95, data, totalSize); // Exit blocked sequence
|
|
|
|
process_entry(0x706c, data, totalSize); // Jump proc #2 - go to castle basement
|
2008-01-27 19:47:41 +00:00
|
|
|
process_entry(0x728a, data, totalSize);
|
|
|
|
process_entry(0x76ec, data, totalSize);
|
2007-09-23 22:05:50 +00:00
|
|
|
process_entry(0x4ebb, data, totalSize); // Goewin as a follower in cave
|
|
|
|
process_entry(0x7D9D, data, totalSize); // Goewin standard handler
|
|
|
|
break;
|
|
|
|
case IT_ITA:
|
|
|
|
process_entry(0x13c2, data, totalSize);
|
|
|
|
process_entry(0xbc55, data, totalSize);
|
|
|
|
process_entry(0x712c, data, totalSize);
|
|
|
|
break;
|
2007-11-22 10:15:20 +00:00
|
|
|
case FR_FRA:
|
|
|
|
process_entry(0x13c2, data, totalSize);
|
|
|
|
process_entry(0xbc75, data, totalSize);
|
|
|
|
process_entry(0x714c, data, totalSize);
|
|
|
|
break;
|
|
|
|
case DE_DEU:
|
|
|
|
process_entry(0x13c2, data, totalSize);
|
|
|
|
process_entry(0xbca5, data, totalSize);
|
|
|
|
process_entry(0x717c, data, totalSize);
|
|
|
|
break;
|
2007-11-28 10:40:46 +00:00
|
|
|
case ES_ESP:
|
|
|
|
process_entry(0x13c2, data, totalSize);
|
|
|
|
process_entry(0xbc75, data, totalSize);
|
|
|
|
process_entry(0x714c, data, totalSize);
|
|
|
|
break;
|
2007-09-23 22:05:50 +00:00
|
|
|
default:
|
2007-11-22 10:15:20 +00:00
|
|
|
errorExit("read_action_sequence: Unknown language");
|
2007-09-23 22:05:50 +00:00
|
|
|
}
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2008-01-27 19:47:41 +00:00
|
|
|
// Process the script engine list
|
|
|
|
|
|
|
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
2007-02-22 06:24:48 +00:00
|
|
|
if (offsetList[index] != 0)
|
|
|
|
process_entry(offsetList[index], data, totalSize);
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
// Next process each of the character hotspots
|
|
|
|
|
2007-09-23 22:05:50 +00:00
|
|
|
uint16 hsOffset = 0x5d98;
|
|
|
|
if (language == IT_ITA) hsOffset = 0x5e58;
|
2007-11-22 10:15:20 +00:00
|
|
|
else if (language == FR_FRA) hsOffset = 0x5e78;
|
|
|
|
else if (language == DE_DEU) hsOffset = 0x5ea8;
|
2007-11-28 10:40:46 +00:00
|
|
|
else if (language == ES_ESP) hsOffset = 0x5e78;
|
2007-11-22 10:15:20 +00:00
|
|
|
else if (language != EN_ANY) errorExit("read_action_sequence: Unknown language");
|
2007-09-23 22:05:50 +00:00
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
hotspotIndex = 0;
|
|
|
|
for (;;) {
|
2008-01-27 19:47:41 +00:00
|
|
|
lureExe.seek(dataSegment + hsOffset +
|
2006-07-23 13:08:22 +00:00
|
|
|
hotspotIndex * sizeof(HotspotHeaderEntry));
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.read(&entryHeader, sizeof(HotspotHeaderEntry));
|
2006-07-23 13:08:22 +00:00
|
|
|
if (FROM_LE_16(entryHeader.offset) == 0xffff) break;
|
|
|
|
++hotspotIndex;
|
|
|
|
|
|
|
|
// Move to the action sequence area of the hotspot
|
2007-09-23 22:05:50 +00:00
|
|
|
lureExe.seek(dataSegment + entryHeader.offset + 0x63);
|
|
|
|
lureExe.read(&action, sizeof(CurrentActionInput));
|
2008-01-27 19:47:41 +00:00
|
|
|
if (FROM_LE_16(action.action) == 2)
|
2006-07-23 13:08:22 +00:00
|
|
|
process_entry(FROM_LE_16(action.dataOffset), data, totalSize);
|
|
|
|
}
|
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
// Finally process each of the random room actions
|
|
|
|
|
2009-10-02 14:42:24 +00:00
|
|
|
for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex) {
|
|
|
|
for (index = 0; index < randomActions[roomIndex].numEntries; ++index) {
|
|
|
|
if (randomActions[roomIndex].entries[index].offset != 0xfffe) {
|
2007-11-22 10:15:20 +00:00
|
|
|
//printf("room=%d entry=%xh\n", roomIndex+1, randomActions[roomIndex].entries[index].offset);
|
2007-02-22 06:24:48 +00:00
|
|
|
process_entry(randomActions[roomIndex].entries[index].offset, data, totalSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-23 13:08:22 +00:00
|
|
|
// Output the list used in the script engine
|
|
|
|
|
|
|
|
pHeader = (uint16 *) data;
|
2008-01-27 19:47:41 +00:00
|
|
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
2007-02-22 06:24:48 +00:00
|
|
|
if (offsetList[index] == 0)
|
|
|
|
*pHeader++ = 0;
|
|
|
|
else
|
|
|
|
*pHeader++ = TO_LE_16(get_sequence_index(offsetList[index]));
|
|
|
|
*pHeader++ = TO_LE_16(0xffff);
|
|
|
|
|
|
|
|
// Output the data for the random room actions
|
|
|
|
|
2009-10-02 14:42:24 +00:00
|
|
|
for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex) {
|
2007-02-22 06:24:48 +00:00
|
|
|
if (randomActions[roomIndex].numEntries == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
*pHeader++ = TO_LE_16(roomIndex + 1); // Save the room number
|
|
|
|
|
|
|
|
// Create a word containing the number of available actions and a bit flag set
|
|
|
|
// specifying which of the actions are repeatable (as opposed to once only)
|
|
|
|
uint16 v = randomActions[roomIndex].numEntries;
|
|
|
|
for (int entryCtr = 0; entryCtr < randomActions[roomIndex].numEntries; ++entryCtr)
|
|
|
|
if (randomActions[roomIndex].entries[entryCtr].repeatable)
|
|
|
|
v |= (0x100 << entryCtr);
|
|
|
|
*pHeader++ = TO_LE_16(v);
|
|
|
|
|
|
|
|
// Loop through the entries storing the action set to use
|
|
|
|
for (int entryCtr = 0; entryCtr < randomActions[roomIndex].numEntries; ++entryCtr)
|
|
|
|
if (randomActions[roomIndex].entries[entryCtr].offset == 0)
|
|
|
|
*pHeader++ = 0;
|
|
|
|
else
|
|
|
|
*pHeader++ = TO_LE_16(get_sequence_index(randomActions[roomIndex].entries[entryCtr].offset));
|
|
|
|
}
|
|
|
|
*pHeader++ = TO_LE_16(0xffff);
|
2006-07-23 13:08:22 +00:00
|
|
|
|
|
|
|
// Output the offsets of each action set
|
|
|
|
|
2008-01-27 19:47:41 +00:00
|
|
|
for (index = 0; index < numSupportEntries; ++index)
|
2006-07-23 13:08:22 +00:00
|
|
|
*pHeader++ = TO_LE_16(supportList[index].resourceOffset);
|
2007-02-22 06:24:48 +00:00
|
|
|
*pHeader++ = TO_LE_16(0xffff);
|
2006-07-23 13:08:22 +00:00
|
|
|
|
2007-02-22 06:24:48 +00:00
|
|
|
// Free up the random room action array
|
2009-10-02 14:42:24 +00:00
|
|
|
for (roomIndex = 0; roomIndex < 1; ++roomIndex) {
|
2007-02-22 06:24:48 +00:00
|
|
|
if (randomActions[roomIndex].entries != NULL)
|
2009-10-02 14:42:24 +00:00
|
|
|
delete[] randomActions[roomIndex].entries;
|
2006-07-23 13:08:22 +00:00
|
|
|
}
|
2009-10-02 14:42:24 +00:00
|
|
|
delete[] randomActions;
|
2008-01-27 19:47:41 +00:00
|
|
|
}
|