Initial commit of tool to create lure.dat file
svn-id: r23578
This commit is contained in:
parent
1ec5d56780
commit
9780117a77
4 changed files with 1893 additions and 0 deletions
4
tools/create_lure/Makefile
Normal file
4
tools/create_lure/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# $Id$
|
||||||
|
|
||||||
|
all:
|
||||||
|
g++ -I../.. create_lure_dat.cpp process_actions.cpp -o create_lure
|
1147
tools/create_lure/create_lure_dat.cpp
Normal file
1147
tools/create_lure/create_lure_dat.cpp
Normal file
File diff suppressed because it is too large
Load diff
401
tools/create_lure/create_lure_dat.h
Normal file
401
tools/create_lure/create_lure_dat.h
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2005-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __createlure_dat__
|
||||||
|
#define __createlure_dat__
|
||||||
|
|
||||||
|
#include "common/stdafx.h"
|
||||||
|
#include "common/endian.h"
|
||||||
|
|
||||||
|
#define VERSION_MAJOR 1
|
||||||
|
#define VERSION_MINOR 10
|
||||||
|
#define ENGLISH_LURE
|
||||||
|
|
||||||
|
#define DATA_SEGMENT 0xac50
|
||||||
|
|
||||||
|
#define DIALOG_OFFSET 0x1dcb0
|
||||||
|
#define DIALOG_SIZE 0x150
|
||||||
|
|
||||||
|
#define TALK_DIALOG_OFFSET 0x1de00
|
||||||
|
#define TALK_DIALOG_SIZE 0x30
|
||||||
|
|
||||||
|
#define PALETTE_OFFSET 0xc0a7
|
||||||
|
#define PALETTE_SIZE 0x300
|
||||||
|
|
||||||
|
#define ROOM_TABLE 0xbf40
|
||||||
|
#define ROOM_NUM_ENTRIES 51
|
||||||
|
|
||||||
|
#define HOTSPOT_OVERRIDE_OFFSET 0x2A01
|
||||||
|
|
||||||
|
#define SCRIPT_SEGMENT 0x1df00
|
||||||
|
#define SCRIPT_SEGMENT_SIZE 0x2c57
|
||||||
|
#define SCRIPT2_SEGMENT 0x19c70
|
||||||
|
#define SCRIPT2_SEGMENT_SIZE 0x2800
|
||||||
|
|
||||||
|
#define HOTSPOT_SCRIPT_LIST 0x57e0
|
||||||
|
#define HOTSPOT_SCRIPT_SIZE 0x30
|
||||||
|
|
||||||
|
#define MAX_NUM_ANIM_RECORDS 0x200
|
||||||
|
#define MAX_NUM_ACTION_RECORDS 0x100
|
||||||
|
|
||||||
|
#define ROOM_EXITS_OFFSET 0x2f61
|
||||||
|
#define NUM_ROOM_EXITS 50
|
||||||
|
#define ROOM_EXIT_JOINS_OFFSET 0xce30
|
||||||
|
|
||||||
|
#define MESSAGES_SEGMENT 0x20b60
|
||||||
|
#define MESSAGES_SEGMENT_SIZE 0x490
|
||||||
|
|
||||||
|
#define MAX_HOTSPOTS 0x100
|
||||||
|
#define MAX_DATA_SIZE 0x4000
|
||||||
|
|
||||||
|
#define PATHFIND_OFFSET 0x984A
|
||||||
|
#define PATHFIND_SIZE (120 * ROOM_NUM_ENTRIES)
|
||||||
|
|
||||||
|
#define HOTSPOT_WALK_TO_OFFSET 0xBC4B
|
||||||
|
#define EXIT_COORDINATES_OFFSET 0x1929
|
||||||
|
#define EXIT_COORDINATES_NUM_ROOMS 49
|
||||||
|
|
||||||
|
#define TABLED_ACTIONS_OFFSET 0x1380
|
||||||
|
#define NUM_TABLED_ACTION_BLOCKS 18
|
||||||
|
|
||||||
|
#define WALK_AREAS_OFFSET 0x2EB1
|
||||||
|
|
||||||
|
#define EXIT_HOTSPOTS_OFFSET 0x2E57
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
// Rect currently copied from common/rect.h - if I try directly including it,
|
||||||
|
// the link complains about an unresolved external token Common.String.__dtor
|
||||||
|
|
||||||
|
struct Rect {
|
||||||
|
int16 top, left; //!< The point at the top left of the rectangle (part of the rect).
|
||||||
|
int16 bottom, right; //!< The point at the bottom right of the rectangle (not part of the rect).
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FileEntry {
|
||||||
|
uint16 id;
|
||||||
|
byte unused;
|
||||||
|
byte sizeExtension;
|
||||||
|
uint16 size;
|
||||||
|
uint16 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomHeaderEntry {
|
||||||
|
uint16 offset;
|
||||||
|
uint16 roomNumber;
|
||||||
|
uint16 descId;
|
||||||
|
byte unused[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotHeaderEntry {
|
||||||
|
uint16 offset;
|
||||||
|
uint16 resourceId;
|
||||||
|
uint16 descId, descId2;
|
||||||
|
byte hdrFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotResource {
|
||||||
|
uint32 actions;
|
||||||
|
uint16 actionsOffset;
|
||||||
|
uint16 roomNumber;
|
||||||
|
byte scriptLoadFlag;
|
||||||
|
uint16 loadOffset;
|
||||||
|
uint16 unused;
|
||||||
|
uint16 startX;
|
||||||
|
uint16 startY;
|
||||||
|
uint16 width;
|
||||||
|
uint16 height;
|
||||||
|
byte layer;
|
||||||
|
byte flags;
|
||||||
|
uint16 tickProcOffset;
|
||||||
|
uint16 widthCopy;
|
||||||
|
uint16 heightCopy;
|
||||||
|
uint16 yCorrection;
|
||||||
|
uint16 tickTimeout;
|
||||||
|
uint16 animOffset;
|
||||||
|
byte colourOffset;
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
byte unknown4[15];
|
||||||
|
int8 talkX;
|
||||||
|
int8 talkY;
|
||||||
|
byte unused5[11];
|
||||||
|
uint16 delayCtr;
|
||||||
|
uint8 characterMode;
|
||||||
|
uint16 tickSequenceOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurrentActionInput {
|
||||||
|
uint8 action;
|
||||||
|
uint16 dataOffset;
|
||||||
|
uint16 roomNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotResourceOutput {
|
||||||
|
uint16 hotspotId;
|
||||||
|
uint16 nameId;
|
||||||
|
uint16 descId;
|
||||||
|
uint16 descId2;
|
||||||
|
uint32 actions;
|
||||||
|
uint16 actionsOffset;
|
||||||
|
uint16 roomNumber;
|
||||||
|
byte layer;
|
||||||
|
byte scriptLoadFlag;
|
||||||
|
uint16 loadOffset;
|
||||||
|
uint16 startX;
|
||||||
|
uint16 startY;
|
||||||
|
uint16 width;
|
||||||
|
uint16 height;
|
||||||
|
uint16 widthCopy;
|
||||||
|
uint16 heightCopy;
|
||||||
|
uint16 yCorrection;
|
||||||
|
int16 walkX;
|
||||||
|
uint16 walkY;
|
||||||
|
int8 talkX;
|
||||||
|
int8 talkY;
|
||||||
|
uint16 colourOffset;
|
||||||
|
uint16 animRecordId;
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
uint16 tickProcOffset;
|
||||||
|
uint16 tickTimeout;
|
||||||
|
uint16 tickSequenceOffset;
|
||||||
|
uint16 npcSchedule;
|
||||||
|
uint16 characterMode;
|
||||||
|
uint16 delayCtr;
|
||||||
|
byte flags;
|
||||||
|
byte hdrFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomResource {
|
||||||
|
byte unknown1[6];
|
||||||
|
uint16 pixelListOffset;
|
||||||
|
byte numLayers;
|
||||||
|
uint16 layers[4];
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
byte unknown3[5];
|
||||||
|
uint8 walkBoundsIndex;
|
||||||
|
int16 clippingXStart;
|
||||||
|
int16 clippingXEnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomRectIn {
|
||||||
|
uint16 xs, xe;
|
||||||
|
uint16 ys, ye;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomRectOut {
|
||||||
|
int16 xs, xe;
|
||||||
|
int16 ys, ye;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomResourceOutput {
|
||||||
|
uint16 roomNumber;
|
||||||
|
uint16 descId;
|
||||||
|
uint16 numLayers;
|
||||||
|
uint16 layers[4];
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
int16 clippingXStart;
|
||||||
|
int16 clippingXEnd;
|
||||||
|
RoomRectOut walkBounds;
|
||||||
|
uint16 numExits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomResourceExit1 {
|
||||||
|
int16 xs, xe, ys, ye;
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomResourceExit2 {
|
||||||
|
uint8 newRoom;
|
||||||
|
uint8 direction;
|
||||||
|
int16 newRoomX, newRoomY;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotOverride {
|
||||||
|
uint16 hotspotId;
|
||||||
|
uint16 xs, xe, ys, ye;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimRecord {
|
||||||
|
uint16 animId;
|
||||||
|
uint8 flags;
|
||||||
|
uint8 unused[6];
|
||||||
|
uint16 upOffset;
|
||||||
|
uint16 downOffset;
|
||||||
|
uint16 leftOffset;
|
||||||
|
uint16 rightOffset;
|
||||||
|
uint8 upFrame;
|
||||||
|
uint8 downFrame;
|
||||||
|
uint8 leftFrame;
|
||||||
|
uint8 rightFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimRecordOutput {
|
||||||
|
uint16 animRecordId;
|
||||||
|
uint16 animId;
|
||||||
|
uint16 flags;
|
||||||
|
uint16 upOffset;
|
||||||
|
uint16 downOffset;
|
||||||
|
uint16 leftOffset;
|
||||||
|
uint16 rightOffset;
|
||||||
|
uint8 upFrame;
|
||||||
|
uint8 downFrame;
|
||||||
|
uint8 leftFrame;
|
||||||
|
uint8 rightFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MovementRecord {
|
||||||
|
uint16 frameNumber;
|
||||||
|
int16 xChange;
|
||||||
|
int16 yChange;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomExitHotspotRecord {
|
||||||
|
int16 xs, xe;
|
||||||
|
int16 ys, ye;
|
||||||
|
uint16 cursorNum;
|
||||||
|
uint16 hotspotId;
|
||||||
|
uint16 destRoomNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomExitHotspotOutputRecord {
|
||||||
|
uint16 hotspotId;
|
||||||
|
int16 xs, xe;
|
||||||
|
int16 ys, ye;
|
||||||
|
uint16 cursorNum;
|
||||||
|
uint16 destRoomNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomExitHotspotJoinRecord {
|
||||||
|
uint16 hotspot1Id;
|
||||||
|
byte h1CurrentFrame;
|
||||||
|
byte h1DestFrame;
|
||||||
|
byte h1OpenSound;
|
||||||
|
byte h1CloseSound;
|
||||||
|
uint16 hotspot2Id;
|
||||||
|
byte h2CurrentFrame;
|
||||||
|
byte h2DestFrame;
|
||||||
|
byte h2OpenSound;
|
||||||
|
byte h2CloseSound;
|
||||||
|
byte blocked;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotActionSequenceRecord {
|
||||||
|
byte actionNumber;
|
||||||
|
uint16 sequenceOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotActionsRecord {
|
||||||
|
uint16 recordId;
|
||||||
|
uint16 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomExitCoordinateResource {
|
||||||
|
int16 x;
|
||||||
|
int16 y;
|
||||||
|
uint16 roomNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotWalkToRecord {
|
||||||
|
uint16 hotspotId;
|
||||||
|
int16 x;
|
||||||
|
uint16 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RoomExitIndexedHotspotResource {
|
||||||
|
uint8 roomNumber;
|
||||||
|
uint8 hotspotIndex;
|
||||||
|
uint16 hotspotId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6
|
||||||
|
#define ROOM_EXIT_COORDINATES_ENTRY_NUM_ROOMS 52
|
||||||
|
|
||||||
|
struct RoomExitCoordinateEntryResource {
|
||||||
|
RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES];
|
||||||
|
uint8 roomIndex[ROOM_EXIT_COORDINATES_ENTRY_NUM_ROOMS];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CurrentAction {NO_ACTION, START_WALKING, DISPATCH_ACTION, EXEC_HOTSPOT_SCRIPT,
|
||||||
|
PROCESSING_PATH, WALKING};
|
||||||
|
|
||||||
|
extern void read_action_sequence(byte *&data, uint16 &totalSize);
|
||||||
|
|
||||||
|
extern uint16 get_sequence_index(uint16 offset, int supportIndex = -1);
|
||||||
|
|
||||||
|
enum AccessMode {
|
||||||
|
kFileReadMode = 1,
|
||||||
|
kFileWriteMode = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
class File {
|
||||||
|
private:
|
||||||
|
FILE *f;
|
||||||
|
public:
|
||||||
|
bool open(const char *filename, AccessMode mode = kFileReadMode) {
|
||||||
|
f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb");
|
||||||
|
return (f != NULL);
|
||||||
|
}
|
||||||
|
void close() {
|
||||||
|
fclose(f);
|
||||||
|
f = NULL;
|
||||||
|
}
|
||||||
|
int seek(int32 offset, int whence = SEEK_SET) {
|
||||||
|
return fseek(f, offset, whence);
|
||||||
|
}
|
||||||
|
long read(void *buffer, int len) {
|
||||||
|
return fread(buffer, 1, len, f);
|
||||||
|
}
|
||||||
|
void write(const void *buffer, int len) {
|
||||||
|
fwrite(buffer, 1, len, f);
|
||||||
|
}
|
||||||
|
byte readByte() {
|
||||||
|
byte v;
|
||||||
|
read(&v, sizeof(byte));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
uint16 readWord() {
|
||||||
|
uint16 v;
|
||||||
|
read(&v, sizeof(uint16));
|
||||||
|
return FROM_LE_16(v);
|
||||||
|
}
|
||||||
|
uint16 readLong() {
|
||||||
|
uint32 v;
|
||||||
|
read(&v, sizeof(uint32));
|
||||||
|
return FROM_LE_32(v);
|
||||||
|
}
|
||||||
|
void writeByte(byte v) {
|
||||||
|
write(&v, sizeof(byte));
|
||||||
|
}
|
||||||
|
void writeWord(uint16 v) {
|
||||||
|
uint16 vTemp = TO_LE_16(v);
|
||||||
|
write(&vTemp, sizeof(uint16));
|
||||||
|
}
|
||||||
|
void writeLong(uint32 v) {
|
||||||
|
uint32 vTemp = TO_LE_32(v);
|
||||||
|
write(&vTemp, sizeof(uint32));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern File lure_exe;
|
||||||
|
|
||||||
|
#endif
|
341
tools/create_lure/process_actions.cpp
Normal file
341
tools/create_lure/process_actions.cpp
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2005-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/stdafx.h"
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
#include "create_lure_dat.h"
|
||||||
|
|
||||||
|
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,
|
||||||
|
NPC_SET_ROOM_AND_BLOCKED_OFFSET = 28, NPC_UNKNOWN1 = 29, NPC_EXEC_SCRIPT = 30,
|
||||||
|
NPC_UNKNOWN2 = 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_UNKNOWN3 = 37, NPC_UNKNOWN4 = 38,
|
||||||
|
NPC_START_TALKING = 39, NPC_JUMP_ADDRESS = 40,
|
||||||
|
NONE = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurrentActionOutput {
|
||||||
|
uint8 action;
|
||||||
|
uint8 hsAction;
|
||||||
|
uint16 roomNumber;
|
||||||
|
uint16 hotspotId;
|
||||||
|
uint16 usedId;
|
||||||
|
};
|
||||||
|
|
||||||
|
int numParams[NPC_JUMP_ADDRESS+1] = {0,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1,
|
||||||
|
0, 1, 1, 1, 1, 0, 0, 2, 0, 1, 0, 0, 1, 1, 2, 2, 5, 2, 2, 1};
|
||||||
|
|
||||||
|
#ifdef ENGLISH_LURE
|
||||||
|
#define NUM_JUMP_OFFSETS 2
|
||||||
|
uint16 jumpOffsets[2] = {0x87be, 0x881c};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_BUFFER_ENTRIES 50
|
||||||
|
#define MAX_INSTRUCTION_ENTRIES 300
|
||||||
|
#define SCHEDULE_DATA_OFFSET 0x60
|
||||||
|
|
||||||
|
struct SupportStructure {
|
||||||
|
uint16 offset;
|
||||||
|
int numInstructions;
|
||||||
|
uint16 instructionOffsets[MAX_INSTRUCTION_ENTRIES];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index <= numSupportEntries; ++index) {
|
||||||
|
SupportStructure &rec = supportList[index];
|
||||||
|
|
||||||
|
if ((rec.numInstructions > 0) &&
|
||||||
|
(offset >= rec.instructionOffsets[0]) &&
|
||||||
|
(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;
|
||||||
|
#ifdef ENGLISH_LURE
|
||||||
|
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 == 0x734a) maxOffset = 0x77a2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
lure_exe.seek(DATA_SEGMENT + startOffset);
|
||||||
|
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
|
||||||
|
actionNum = lure_exe.readWord();
|
||||||
|
|
||||||
|
// printf("%xh - action=%d", offset, actionNum);
|
||||||
|
|
||||||
|
if (actionNum == 0) {
|
||||||
|
// At end of script block
|
||||||
|
// printf("\n");
|
||||||
|
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)
|
||||||
|
params[paramCtr] = lure_exe.readWord();
|
||||||
|
|
||||||
|
switch(actionNum) {
|
||||||
|
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
|
||||||
|
if ((params[paramIndex] > offset) &&
|
||||||
|
(params[paramIndex] < offset + FORWARD_JUMP_ALLOWANCE) &&
|
||||||
|
(params[paramIndex] > maxOffset)) {
|
||||||
|
maxOffset = params[paramIndex];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NPC_JUMP_ADDRESS:
|
||||||
|
// Make sure the address is in the known list
|
||||||
|
index = 0;
|
||||||
|
while ((index < NUM_JUMP_OFFSETS) && (jumpOffsets[index] != params[0]))
|
||||||
|
++index;
|
||||||
|
|
||||||
|
if (index != NUM_JUMP_OFFSETS)
|
||||||
|
// Replace code offset with an index
|
||||||
|
params[0] = index;
|
||||||
|
else {
|
||||||
|
printf("Encountered unrecognised NPC code jump point: %xh\n", params[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output parameters
|
||||||
|
for (paramIndex = 0; paramIndex < numParams[actionNum]; ++paramIndex)
|
||||||
|
*pOut++ = TO_LE_16(params[paramIndex]);
|
||||||
|
|
||||||
|
// Increase size
|
||||||
|
totalSize += (numParams[actionNum] + 1) * sizeof(uint16);
|
||||||
|
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) {
|
||||||
|
if (READ_LE_UINT16(symbolTable[symbolCtr].p) == 0)
|
||||||
|
// No Id special constant
|
||||||
|
WRITE_LE_UINT16(symbolTable[symbolCtr].p, 0xffff);
|
||||||
|
else {
|
||||||
|
// Handle resolving the constant
|
||||||
|
index = get_sequence_index(READ_LE_UINT16(symbolTable[symbolCtr].p),
|
||||||
|
symbolTable[symbolCtr].globalNeeded ? -1 : supportIndex);
|
||||||
|
//printf("Symbol %xh => %xh\n", *symbolTable[symbolCtr].p, index);
|
||||||
|
if (index != 0xffff) {
|
||||||
|
// Jump found - so replace symbol entry with it
|
||||||
|
WRITE_LE_UINT16(symbolTable[symbolCtr].p, index);
|
||||||
|
} else {
|
||||||
|
printf("Sequence contained unknown offset %xh\n",
|
||||||
|
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;
|
||||||
|
//printf("process_entry index=%d, offset=%xh\n", numSupportEntries + 1, offset);
|
||||||
|
totalSize += process_action_sequence_entry(numSupportEntries,
|
||||||
|
data + totalSize, MAX_DATA_SIZE - totalSize);
|
||||||
|
|
||||||
|
++numSupportEntries;
|
||||||
|
if (numSupportEntries == MAX_BUFFER_ENTRIES) {
|
||||||
|
printf("Ran out of buffer space in processing NPC schedules\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_action_sequence(byte *&data, uint16 &totalSize)
|
||||||
|
{
|
||||||
|
const uint16 hsOffset = 0x5d98;
|
||||||
|
const uint16 hsStartId = 0x3e8;
|
||||||
|
uint16 hotspotIndex;
|
||||||
|
HotspotHeaderEntry entryHeader;
|
||||||
|
CurrentActionInput action;
|
||||||
|
uint16 *pHeader;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
lure_exe.seek(DATA_SEGMENT + TABLED_ACTIONS_OFFSET, SEEK_SET);
|
||||||
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
||||||
|
offsetList[index] = lure_exe.readWord();
|
||||||
|
|
||||||
|
totalSize = SCHEDULE_DATA_OFFSET;
|
||||||
|
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
|
||||||
|
#ifdef ENGLISH_LURE
|
||||||
|
process_entry(0x13c2, data, totalSize);
|
||||||
|
process_entry(0xbb95, data, totalSize);
|
||||||
|
process_entry(0x7060, data, totalSize);
|
||||||
|
process_entry(0x728a, data, totalSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Process the script engine list
|
||||||
|
|
||||||
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
||||||
|
process_entry(offsetList[index], data, totalSize);
|
||||||
|
|
||||||
|
// Next process each of the character hotspots
|
||||||
|
|
||||||
|
hotspotIndex = 0;
|
||||||
|
for (;;) {
|
||||||
|
lure_exe.seek(DATA_SEGMENT + hsOffset +
|
||||||
|
hotspotIndex * sizeof(HotspotHeaderEntry));
|
||||||
|
lure_exe.read(&entryHeader, sizeof(HotspotHeaderEntry));
|
||||||
|
if (FROM_LE_16(entryHeader.offset) == 0xffff) break;
|
||||||
|
++hotspotIndex;
|
||||||
|
|
||||||
|
// Move to the action sequence area of the hotspot
|
||||||
|
lure_exe.seek(DATA_SEGMENT + entryHeader.offset + 0x63);
|
||||||
|
lure_exe.read(&action, sizeof(CurrentActionInput));
|
||||||
|
if (FROM_LE_16(action.action) == 2)
|
||||||
|
process_entry(FROM_LE_16(action.dataOffset), data, totalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output the list used in the script engine
|
||||||
|
|
||||||
|
pHeader = (uint16 *) data;
|
||||||
|
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
|
||||||
|
*pHeader++ = TO_LE_16(get_sequence_index(offsetList[index]));
|
||||||
|
*pHeader++ = 0xffff;
|
||||||
|
|
||||||
|
// Output the offsets of each action set
|
||||||
|
|
||||||
|
for (index = 0; index < numSupportEntries; ++index)
|
||||||
|
*pHeader++ = TO_LE_16(supportList[index].resourceOffset);
|
||||||
|
*pHeader++ = 0xffff;
|
||||||
|
|
||||||
|
if ((int) ((byte *) pHeader - data) > SCHEDULE_DATA_OFFSET) {
|
||||||
|
printf("SCHEDULE_DATA_OFFSET was not high enough\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue