aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/create_lure/create_lure_dat.cpp716
-rw-r--r--tools/create_lure/create_lure_dat.h34
-rw-r--r--tools/create_lure/process_actions.cpp131
3 files changed, 608 insertions, 273 deletions
diff --git a/tools/create_lure/create_lure_dat.cpp b/tools/create_lure/create_lure_dat.cpp
index cc53c751f4..6992d0075a 100644
--- a/tools/create_lure/create_lure_dat.cpp
+++ b/tools/create_lure/create_lure_dat.cpp
@@ -21,15 +21,10 @@
* $URL$
* $Id$
*
- * This is a utility for extracting needed resource data from the Lure of the Temptress
- * lure.exe file into a new file lure.dat - this file is required for the ScummVM
- * Lure of the Temptress module to work properly
- *
- * TODO:
- * Some of the field values, such as hotspot tick proc offsets, will vary with
- * different language versions. These will need to be remapped to a language independant
- * value once I've fully implemented the English version.
- * Some areas of the data segment are still to be decoded
+ * This is a utility for extracting needed resource data from different language
+ * version of the Lure of the Temptress lure.exe executable files into a new file
+ * lure.dat - this file is required for the ScummVM Lure of the Temptress module
+ * to work properly
*/
#include <stdio.h>
@@ -37,13 +32,28 @@
#include <string.h>
#include "create_lure_dat.h"
-File lure_exe;
+using namespace Common;
+
+File outputFile, lureExe;
+Common::Language language;
+uint16 dataSegment;
+
+#define NUM_BYTES_VALIDATE 1024
+#define ENGLISH_FILE_CHECKSUM 0xFD70
+#define ITALIAN_FILE_CHECKSUM 0x109AD
+Common::Language processedLanguages[100];
+int langIndex = 0;
uint16 animOffsets[MAX_NUM_ANIM_RECORDS];
int animIndex = 0;
uint16 actionOffsets[MAX_NUM_ACTION_RECORDS];
int actionIndex = 0;
+#define TALK_NUM_ENTRIES 28
+#define MAX_TALK_LISTS 300
+
+uint16 talkOffsets[MAX_TALK_LISTS];
+int talkOffsetIndex = 0;
void add_anim_record(uint16 offset) {
for (int ctr = 0; ctr < animIndex; ++ctr)
@@ -67,9 +77,12 @@ void add_action_list(uint16 offset) {
void read_basic_palette(byte *&data, uint16 &totalSize) {
totalSize = PALETTE_SIZE;
- lure_exe.seek(PALETTE_OFFSET);
- data = (byte *) malloc(PALETTE_SIZE);
- lure_exe.read(data, totalSize);
+ uint16 dataStart = 0xC0A7;
+ if (language == IT_ITA) dataStart = 0xC107;
+
+ lureExe.seek(dataStart);
+ data = (byte *) malloc(totalSize);
+ lureExe.read(data, totalSize);
}
#define ALT_PALETTE_1 0x1757
@@ -81,24 +94,30 @@ void read_replacement_palette(byte *&data, uint16 &totalSize) {
totalSize = ALT_PALETTE_1_SIZE + ALT_PALETTE_2_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.seek(DATA_SEGMENT + ALT_PALETTE_1);
- lure_exe.read(data, ALT_PALETTE_1_SIZE);
- lure_exe.seek(DATA_SEGMENT + ALT_PALETTE_2);
- lure_exe.read(data + ALT_PALETTE_1_SIZE, ALT_PALETTE_2_SIZE);
+ lureExe.seek(dataSegment + ALT_PALETTE_1);
+ lureExe.read(data, ALT_PALETTE_1_SIZE);
+ lureExe.seek(dataSegment + ALT_PALETTE_2);
+ lureExe.read(data + ALT_PALETTE_1_SIZE, ALT_PALETTE_2_SIZE);
}
void read_dialog_data(byte *&data, uint16 &totalSize) {
+ uint32 segmentStart = 0x1dcb0;
+ if (language == IT_ITA) segmentStart = 0x1ddd0;
+
totalSize = DIALOG_SIZE;
- lure_exe.seek(DIALOG_OFFSET);
- data = (byte *) malloc(DIALOG_SIZE);
- lure_exe.read(data, totalSize);
+ lureExe.seek(segmentStart);
+ data = (byte *) malloc(totalSize);
+ lureExe.read(data, totalSize);
}
void read_talk_dialog_data(byte *&data, uint16 &totalSize) {
+ uint32 segmentStart = 0x1de00;
+ if (language == IT_ITA) segmentStart = 0x1df20;
+
totalSize = TALK_DIALOG_SIZE;
- lure_exe.seek(TALK_DIALOG_OFFSET, SEEK_SET);
- data = (byte *) malloc(TALK_DIALOG_SIZE);
- lure_exe.read(data, totalSize);
+ lureExe.seek(segmentStart);
+ data = (byte *) malloc(totalSize);
+ lureExe.read(data, totalSize);
}
void read_room_data(byte *&data, uint16 &totalSize)
@@ -113,10 +132,17 @@ void read_room_data(byte *&data, uint16 &totalSize)
RoomHeaderEntry headerEntry;
RoomRectIn bounds;
+ uint16 dataStart = 0xbf40;
+ uint16 walkAreaOffset = 0x2eb1;
+ if (language == IT_ITA) {
+ dataStart = 0xc000;
+ walkAreaOffset = 0x2ec0;
+ }
+
for (int index = 0; index < ROOM_NUM_ENTRIES; ++index) {
- lure_exe.seek(DATA_SEGMENT + ROOM_TABLE + index * 9);
- lure_exe.read(&headerEntry, sizeof(RoomHeaderEntry));
+ lureExe.seek(dataSegment + dataStart + index * 9);
+ lureExe.read(&headerEntry, sizeof(RoomHeaderEntry));
if ((FROM_LE_16(headerEntry.offset) != 0) &&
(FROM_LE_16(headerEntry.offset) != 0xffff) &&
@@ -125,8 +151,8 @@ void read_room_data(byte *&data, uint16 &totalSize)
*offsetPtr++ = TO_LE_16(offset);
// Copy over basic room details
- lure_exe.seek(DATA_SEGMENT + headerEntry.offset);
- lure_exe.read(&buffer, sizeof(RoomResource));
+ lureExe.seek(dataSegment + headerEntry.offset);
+ lureExe.read(&buffer, sizeof(RoomResource));
RoomResourceOutput *rec = (RoomResourceOutput *) (data + offset);
rec->hdrFlags = headerEntry.hdrFlags;
rec->actions = FROM_LE_32(buffer.actions);
@@ -147,7 +173,7 @@ void read_room_data(byte *&data, uint16 &totalSize)
// Copy over room exits
for (;;) {
RoomResourceExit1 *p = (RoomResourceExit1 *) (data + offset);
- lure_exe.read(p, sizeof(RoomResourceExit1));
+ lureExe.read(p, sizeof(RoomResourceExit1));
if (FROM_LE_16(p->xs) == 0xffff) break;
rec->numExits = TO_LE_16(FROM_LE_16(rec->numExits) + 1);
@@ -159,7 +185,7 @@ void read_room_data(byte *&data, uint16 &totalSize)
RoomResourceExit2 *p2 = (RoomResourceExit2 *) (data + offset);
if (FROM_LE_16(p->sequenceOffset) == 0xffff) {
- lure_exe.read(p2, sizeof(RoomResourceExit2));
+ lureExe.read(p2, sizeof(RoomResourceExit2));
p2->newRoomX = TO_LE_16(FROM_LE_16(p2->newRoomX) - 0x80);
p2->newRoomY = TO_LE_16(FROM_LE_16(p2->newRoomY) - 0x80);
} else {
@@ -173,9 +199,10 @@ void read_room_data(byte *&data, uint16 &totalSize)
}
// Handle the random destination walk bounds for the room
- lure_exe.seek(DATA_SEGMENT + WALK_AREAS_OFFSET +
+
+ lureExe.seek(dataSegment + walkAreaOffset +
buffer.walkBoundsIndex * sizeof(RoomRectIn));
- lure_exe.read(&bounds, sizeof(RoomRectIn));
+ lureExe.read(&bounds, sizeof(RoomRectIn));
rec->walkBounds.xs = TO_LE_16(FROM_LE_16(bounds.xs) - 0x80);
rec->walkBounds.xe = TO_LE_16(FROM_LE_16(bounds.xe) - 0x80);
rec->walkBounds.ys = TO_LE_16(FROM_LE_16(bounds.ys) - 0x80);
@@ -183,11 +210,11 @@ void read_room_data(byte *&data, uint16 &totalSize)
// If the room has a default pixel blocks list, add the references
if (buffer.pixelListOffset != 0) {
- lure_exe.seek(DATA_SEGMENT + FROM_LE_16(buffer.pixelListOffset));
- pixelOffset = lure_exe.readWord();
+ lureExe.seek(dataSegment + FROM_LE_16(buffer.pixelListOffset));
+ pixelOffset = lureExe.readWord();
while (pixelOffset != 0) {
add_anim_record(pixelOffset);
- pixelOffset = lure_exe.readWord();
+ pixelOffset = lureExe.readWord();
}
}
}
@@ -197,9 +224,30 @@ void read_room_data(byte *&data, uint16 &totalSize)
totalSize = offset;
}
+uint16 englishTickProcOffsets[] = {
+ 0x41BD, 0x4f82, 0x5e44, 0x625e, 0x6571, 0x7207, 0x7c14, 0x7c24, 0x7efa, 0x7f02,
+ 0x7F37, 0x7f3a, 0x7f54, 0x7f69, 0x7fa1, 0x8009, 0x80c6, 0x813f, 0x8180, 0x81b3,
+ 0x81f3, 0x820e, 0x8241, 0x82a0, 0x85ce, 0x862d, 0x865A, 0x86FA, 0x86FF, 0x871E,
+ 0x873D, 0x8742, 0x8747, 0x87B3, 0x87EC, 0x882A, 0x8ABD, 0x982D, 0x98B6,
+ 0xffff
+};
+
+uint16 italianTickProcOffsets[] = {
+ 0x4205, 0x4fca, 0x5e8c, 0x62a6, 0x65b9, 0x724f, 0x7c5c, 0x7c6c, 0x7f58, 0x7f60,
+ 0x7f95, 0x7f98, 0x7fb2, 0x7fc7, 0x7fff, 0x8019, 0x8067, 0x8124, 0x819d, 0x81de,
+ 0x8211, 0x8251, 0x826c, 0x829f, 0x82fe, 0x862c, 0x868b, 0x8758, 0x875D, 0x877C,
+ 0x879B, 0x87a0, 0x87a5, 0x8811, 0x884a, 0x8888, 0x8b20, 0x988f, 0x9918,
+ 0xffff
+};
+
+uint16 englishOffsets[4] = {0x5d98, 0x5eb8, 0x623e, 0x63b1};
+uint16 italianOffsets[4] = {0x5e58, 0x5f78, 0x62fe, 0x6471};
+
+uint16 englishLoadOffsets[] = {0x3afe, 0x41BD, 0x7167, 0x7172, 0x8617, 0x88ac, 0};
+uint16 italianLoadOffsets[] = {0x3b46, 0x4205, 0x71af, 0x71ba, 0x8675, 0x890a, 0};
+
void read_hotspot_data(byte *&data, uint16 &totalSize)
{
- uint16 offsets[4] = {0x5d98, 0x5eb8, 0x623e, 0x63b1};
uint16 startId[4] = {0x3e8, 0x408, 0x2710, 0x7530};
int walkNumEntries = 0;
int walkCtr;
@@ -212,21 +260,34 @@ void read_hotspot_data(byte *&data, uint16 &totalSize)
HotspotResourceOutput *r;
CurrentActionInput action;
+ // Set up list pointers for various languages
+ uint16 *offsets = &englishOffsets[0];
+ uint16 *procList = &englishTickProcOffsets[0];
+ uint16 *loadOffsets = &englishLoadOffsets[0];
+ uint16 walkToOffset = 0xBC4B;
+ if (language == IT_ITA) {
+ offsets = &italianOffsets[0];
+ procList = &italianTickProcOffsets[0];
+ walkToOffset = 0xBD0B;
+ loadOffsets = &italianLoadOffsets[0];
+ }
+
// Allocate enough space for output hotspot list
data = (byte *) malloc(MAX_HOTSPOTS * sizeof(HotspotResourceOutput));
// Determine number of hotspot walk to entries
- lure_exe.seek(DATA_SEGMENT + HOTSPOT_WALK_TO_OFFSET);
+
+ lureExe.seek(dataSegment + walkToOffset);
do {
++walkNumEntries;
- lure_exe.read(&rec, sizeof(HotspotWalkToRecord));
+ lureExe.read(&rec, sizeof(HotspotWalkToRecord));
} while (TO_LE_16(rec.hotspotId) != 0);
--walkNumEntries;
dataSize = walkNumEntries * sizeof(HotspotWalkToRecord);
walkList = (HotspotWalkToRecord *) malloc(dataSize);
- lure_exe.seek(DATA_SEGMENT + HOTSPOT_WALK_TO_OFFSET);
- lure_exe.read(walkList, sizeof(HotspotWalkToRecord) * walkNumEntries);
+ lureExe.seek(dataSegment + walkToOffset);
+ lureExe.read(walkList, sizeof(HotspotWalkToRecord) * walkNumEntries);
// Main code for creating the hotspot list
@@ -236,20 +297,24 @@ void read_hotspot_data(byte *&data, uint16 &totalSize)
for (int tableNum = 0; tableNum < 4; ++tableNum) {
uint16 hotspotIndex = 0;
for (;;) {
- lure_exe.seek(DATA_SEGMENT + offsets[tableNum] + hotspotIndex * 9);
- lure_exe.read(&entryHeader, sizeof(HotspotHeaderEntry));
+ lureExe.seek(dataSegment + offsets[tableNum] + hotspotIndex * 9);
+ lureExe.read(&entryHeader, sizeof(HotspotHeaderEntry));
if (FROM_LE_16(entryHeader.offset) == 0xffff) break;
+ if (FROM_LE_16(entryHeader.offset) == 0) {
+ ++hotspotIndex;
+ continue;
+ }
memset(r, 0, sizeof(HotspotResourceOutput));
r->hotspotId = TO_LE_16(startId[tableNum] + hotspotIndex);
r->nameId = entryHeader.resourceId;
- r->descId = entryHeader.descId; //TO_LE_16(FROM_LE_16(entryHeader.descId) & 0x1fff);
- r->descId2 = entryHeader.descId2; //TO_LE_16(FROM_LE_16(entryHeader.descId2) & 0x1fff);
+ r->descId = entryHeader.descId;
+ r->descId2 = entryHeader.descId2;
r->hdrFlags = entryHeader.hdrFlags;
// Get the hotspot data
- lure_exe.seek(DATA_SEGMENT + entryHeader.offset);
- lure_exe.read(&entry, sizeof(HotspotResource));
+ lureExe.seek(dataSegment + entryHeader.offset);
+ lureExe.read(&entry, sizeof(HotspotResource));
r->actions = entry.actions;
r->roomNumber = entry.roomNumber;
@@ -268,18 +333,60 @@ void read_hotspot_data(byte *&data, uint16 &totalSize)
r->tickSequenceOffset = entry.tickSequenceOffset;
r->layer = entry.layer;
- r->scriptLoadFlag = entry.scriptLoadFlag;
- r->loadOffset = entry.loadOffset;
r->colourOffset = entry.colourOffset;
r->hotspotScriptOffset = entry.hotspotScriptOffset;
r->talkScriptOffset = entry.talkScriptOffset;
- r->tickProcOffset = entry.tickProcOffset;
r->flags = entry.flags;
+ // Handle any necessary translation of script load offsets
+
+ r->scriptLoadFlag = entry.scriptLoadFlag;
+ if (r->scriptLoadFlag || (tableNum == 3))
+ // Load offset is in script segment, so leave as is
+ r->loadOffset = entry.loadOffset;
+ else {
+ // Translate load offset to an index
+ int loadIndex = 0;
+ while ((loadOffsets[loadIndex] != FROM_LE_16(entry.loadOffset)) &&
+ (loadOffsets[loadIndex] != 0))
+ ++loadIndex;
+
+ if (loadOffsets[loadIndex] == 0) {
+ printf("Unknown load offset encountered for hotspot %xh offset %xh\n",
+ startId[tableNum] + hotspotIndex,
+ FROM_LE_16(entry.loadOffset));
+ exit(1);
+ }
+
+ r->loadOffset = TO_LE_16(loadIndex + 1);
+ }
+
+ if (tableNum == 3)
+ r->tickProcId = 0;
+ else {
+ // Scan through the proc list for the correct offset
+ int procIndex = 0;
+ while ((procList[procIndex] != FROM_LE_16(entry.tickProcOffset)) &&
+ (procList[procIndex] != 0xffff))
+ ++procIndex;
+
+ if (procList[procIndex] == 0xffff) {
+ if ((FROM_LE_16(entry.tickProcOffset) != 0xe00) &&
+ (FROM_LE_16(entry.tickProcOffset) != 2))
+ printf("Could not find a tick proc handler for hotspot %xh offset %xh\n",
+ startId[tableNum] + hotspotIndex,
+ FROM_LE_16(entry.tickProcOffset));
+ r->tickProcId = 0;
+ }
+ else
+ r->tickProcId = TO_LE_16(procIndex + 1);
+ }
+
// Special check for the tinderbox hotspot to set it's room number correctly - the original
// game used this as a backup against people trying to hack the copy protection
if (startId[tableNum] + hotspotIndex == 0x271C)
r->roomNumber = TO_LE_16(28);
+if (startId[tableNum] + hotspotIndex == 0x46b) r->tickProcId = 1;
// Find the walk-to coordinates for the hotspot
uint16 findId = FROM_LE_16(r->hotspotId);
@@ -315,8 +422,8 @@ void read_hotspot_data(byte *&data, uint16 &totalSize)
r->npcSchedule = 0;
} else {
// Check for an NPC schedule
- lure_exe.seek(DATA_SEGMENT + entryHeader.offset + 0x63);
- lure_exe.read(&action, sizeof(CurrentActionInput));
+ lureExe.seek(dataSegment + entryHeader.offset + 0x63);
+ lureExe.read(&action, sizeof(CurrentActionInput));
if (action.action != 2)
r->npcSchedule = 0;
@@ -345,22 +452,22 @@ void read_hotspot_data(byte *&data, uint16 &totalSize)
void read_hotspot_override_data(byte *&data, uint16 &totalSize)
{
- lure_exe.seek(DATA_SEGMENT + HOTSPOT_OVERRIDE_OFFSET);
+ lureExe.seek(dataSegment + HOTSPOT_OVERRIDE_OFFSET);
int numOverrides = 0;
HotspotOverride rec;
// Determine number of hotspot overrides
do {
++numOverrides;
- lure_exe.read(&rec, sizeof(HotspotOverride));
+ lureExe.read(&rec, sizeof(HotspotOverride));
} while (FROM_LE_16(rec.hotspotId) != 0);
--numOverrides;
// Prepare output data and read in all entries at once
totalSize = numOverrides * sizeof(HotspotOverride) + 2;
data = (byte *) malloc(totalSize);
- lure_exe.seek(DATA_SEGMENT + HOTSPOT_OVERRIDE_OFFSET);
- lure_exe.read(data, totalSize - 2);
+ lureExe.seek(dataSegment + HOTSPOT_OVERRIDE_OFFSET);
+ lureExe.read(data, totalSize - 2);
WRITE_LE_UINT16(data + totalSize - 2, 0xffff);
// Post-process the coordinates
@@ -380,9 +487,12 @@ void read_room_exits(byte *&data, uint16 &totalSize) {
int roomCtr;
totalSize = (NUM_ROOM_EXITS + 1) * sizeof(uint16);
- lure_exe.seek(DATA_SEGMENT + ROOM_EXITS_OFFSET);
+ uint16 dataStart = 0x2F61;
+ if (language == IT_ITA) dataStart = 0x2f70;
+
+ lureExe.seek(dataSegment + dataStart);
for (roomCtr = 0; roomCtr < NUM_ROOM_EXITS; ++roomCtr)
- offsets[roomCtr] = lure_exe.readWord();
+ offsets[roomCtr] = lureExe.readWord();
// First loop to find total of room exit records there are
for (roomCtr = 0; roomCtr < NUM_ROOM_EXITS; ++roomCtr) {
@@ -390,12 +500,12 @@ void read_room_exits(byte *&data, uint16 &totalSize) {
if (offsets[roomCtr] == 0) continue;
// Get number of exits for the room
- lure_exe.seek(DATA_SEGMENT + offsets[roomCtr]);
- lure_exe.read(&rec, sizeof(RoomExitHotspotRecord));
+ lureExe.seek(dataSegment + offsets[roomCtr]);
+ lureExe.read(&rec, sizeof(RoomExitHotspotRecord));
while (FROM_LE_16(rec.xs) != 0) {
totalSize += sizeof(RoomExitHotspotOutputRecord);
numEntries[roomCtr]++;
- lure_exe.read(&rec, sizeof(RoomExitHotspotRecord));
+ lureExe.read(&rec, sizeof(RoomExitHotspotRecord));
}
totalSize += sizeof(uint16); // save room for room list end flag
}
@@ -418,10 +528,10 @@ void read_room_exits(byte *&data, uint16 &totalSize) {
RoomExitHotspotOutputRecord *destP = (RoomExitHotspotOutputRecord *)
(data + destIndex);
- lure_exe.seek(DATA_SEGMENT + offsets[roomCtr]);
+ lureExe.seek(dataSegment + offsets[roomCtr]);
for (entryCtr = 0; entryCtr < numEntries[roomCtr]; ++entryCtr, ++destP) {
- lure_exe.read(&rec, sizeof(RoomExitHotspotRecord));
+ lureExe.read(&rec, sizeof(RoomExitHotspotRecord));
// Copy over the record
destP->xs = TO_LE_16(FROM_LE_16(rec.xs) - 0x80);
@@ -443,14 +553,16 @@ void read_room_exits(byte *&data, uint16 &totalSize) {
void read_room_exit_joins(byte *&data, uint16 &totalSize) {
RoomExitHotspotJoinRecord rec, *p;
- lure_exe.seek(DATA_SEGMENT + ROOM_EXIT_JOINS_OFFSET);
int numRecords = 0;
uint32 unused;
- lure_exe.seek(DATA_SEGMENT + ROOM_EXIT_JOINS_OFFSET);
+ uint16 dataStart = 0xce30;
+ if (language == IT_ITA) dataStart = 0xcef0;
+ lureExe.seek(dataSegment + dataStart);
+
do {
- lure_exe.read(&rec, sizeof(RoomExitHotspotJoinRecord));
- lure_exe.read(&unused, sizeof(uint32));
+ lureExe.read(&rec, sizeof(RoomExitHotspotJoinRecord));
+ lureExe.read(&unused, sizeof(uint32));
++numRecords;
} while (FROM_LE_16(rec.hotspot1Id) != 0);
--numRecords;
@@ -458,54 +570,73 @@ void read_room_exit_joins(byte *&data, uint16 &totalSize) {
// Allocate the data and read in all the records
totalSize = (numRecords * sizeof(RoomExitHotspotJoinRecord)) + 2;
data = (byte *) malloc(totalSize);
- lure_exe.seek(DATA_SEGMENT + ROOM_EXIT_JOINS_OFFSET);
+ lureExe.seek(dataSegment + dataStart);
p = (RoomExitHotspotJoinRecord *) data;
for (int recordCtr = 0; recordCtr < numRecords; ++recordCtr)
{
- lure_exe.read(p, sizeof(RoomExitHotspotJoinRecord));
- lure_exe.read(&unused, sizeof(uint32));
+ lureExe.read(p, sizeof(RoomExitHotspotJoinRecord));
+ lureExe.read(&unused, sizeof(uint32));
++p;
}
+
WRITE_LE_UINT16(p, 0xffff);
}
-// This next method reads in the animation and movement data. At the moment I
-// figure out which animations have valid movement record sets by finding
-// animations whose four direction offsets are near each other. There's
-// probably a better method than this, but it'll do for now
+// This next method reads in the animation and movement data
+
+#define NUM_LANGUAGES 2
+struct AnimListRecord {
+ uint16 languages[NUM_LANGUAGES];
+};
+
+AnimListRecord animDataList[] = {
+ {0x1830, 0x1830}, // Copy protection header
+ {0x1839, 0x1839}, // Copy protection wording header
+ {0x1842, 0x1842}, // Copy protection numbers
+ {0x184B, 0x184B}, // Restart/Restore buttons
+ {0x55C0, 0x5680}, // Player midswing animation
+ {0x55C9, 0x5689}, // Player mid-level defend
+ {0x55D2, 0x5692}, // Player high-level strike
+ {0x55DB, 0x569B}, // Player high-level defend
+ {0x55E4, 0x56A4}, // Player low-level strike
+ {0x55ED, 0x56AD}, // Player low-level defend
+ {0x55F6, 0x56B6}, // Player fight animation
+ {0x55FF, 0x56BF}, // Pig fight animation
+ {0x5611, 0x56D1}, // Player mid-level strike
+ {0x5623, 0x56E3}, // Pig fight animation
+ {0x562C, 0x56EC}, // Misc fight animation
+ {0x5635, 0x56F5}, // Pig fight animation
+ {0x563E, 0x56FE}, // Player recoiling from hit
+ {0x5647, 0x5707}, // Pig recoiling from hit
+ {0x5650, 0x5710}, // Pig dies
+ {0x5810, 0x58D0}, // Voice bubble
+ {0x5915, 0x59D5}, // Blacksmith hammering
+ {0x59ED, 0x5AAD}, // Ewan's alternate animation
+ {0x59FF, 0x5ABF}, // Dragon breathing fire
+ {0x5A08, 0x5AC8}, // Dragon breathing fire 2
+ {0x5A11, 0x5AD1}, // Dragon breathing fire 3
+ {0x5A1A, 0x5ADA}, // Player turning winch in room #48
+ {0x5A59, 0x5B19}, // Player pulling lever in room #48
+ {0x5A62, 0x5B22}, // Minnow pulling lever in room #48
+ {0x5AAA, 0x5B6A}, // Goewin mixing potion
+ {0x5C95, 0x5D55},
+ {0x5CAA, 0x5D6A}, // Selena animation
+ {0x5CE9, 0x5DA9}, // Blacksmith in bar?
+ {0x5D28, 0x5DE8}, // Goewin animation
+ {0, 0}
+};
void read_anim_data(byte *&data, uint16 &totalSize) {
// Add special pixel records
- add_anim_record(0x184B); // Restart/Restore buttons
- add_anim_record(0x55C0); // Player midswing animation
- add_anim_record(0x55C9); // Player mid-level defend
- add_anim_record(0x55D2); // Player high-level strike
- add_anim_record(0x55DB); // Player high-level defend
- add_anim_record(0x55E4); // Player low-level strike
- add_anim_record(0x55ED); // Player low-level defend
- add_anim_record(0x55F6); // Player fight animation
- add_anim_record(0x55FF); // Pig fight animation
- add_anim_record(0x5611); // Player mid-level strike
- add_anim_record(0x5623); // Pig fight animation
- add_anim_record(0x562C); // Misc fight animation
- add_anim_record(0x5635); // Pig fight animation
- add_anim_record(0x563E); // Player recoiling from hit
- add_anim_record(0x5647); // Pig recoiling from hit
- add_anim_record(0x5650); // Pig dies
- add_anim_record(0x5915); // Blacksmith hammering
- add_anim_record(0x59ED); // Ewan's alternate animation
- add_anim_record(0x59FF); // Dragon breathing fire
- add_anim_record(0x5A08); // Dragon breathing fire 2
- add_anim_record(0x5A11); // Dragon breathing fire 3
- add_anim_record(0x5A1A); // Player turning winch in room #48
- add_anim_record(0x5A59); // Player pulling lever in room #48
- add_anim_record(0x5A62); // Minnow pulling lever in room #48
- add_anim_record(0x5AAA); // Goewin mixing potion
- add_anim_record(0x5C95);
- add_anim_record(0x5CAA); // Selena animation
- add_anim_record(0x5CE9); // Blacksmith in bar?
- add_anim_record(0x5D28); // Goewin animation
+ int index = 0;
+ if (language == IT_ITA) index = 1;
+
+ AnimListRecord *p = &animDataList[0];
+ while (p->languages[index] != 0) {
+ add_anim_record(p->languages[index]);
+ ++p;;
+ }
// Get the animation data records
AnimRecord inRec;
@@ -519,8 +650,8 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
// Loop to figure out the total number of movement records there are
for (ctr = 0; ctr < animIndex; ++ctr) {
- lure_exe.seek(DATA_SEGMENT + animOffsets[ctr]);
- lure_exe.read(&inRec, sizeof(AnimRecord));
+ lureExe.seek(dataSegment + animOffsets[ctr]);
+ lureExe.read(&inRec, sizeof(AnimRecord));
if ((FROM_LE_16(inRec.leftOffset) < 0x5000) ||
(FROM_LE_16(inRec.rightOffset) < 0x5000) ||
@@ -547,12 +678,12 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
}
if (offset != 0) {
- lure_exe.seek(DATA_SEGMENT + offset);
- lure_exe.read(&move, sizeof(MovementRecord));
+ lureExe.seek(dataSegment + offset);
+ lureExe.read(&move, sizeof(MovementRecord));
while (FROM_LE_16(move.frameNumber) != 0xffff) {
movementSize += sizeof(MovementRecord);
- lure_exe.read(&move, sizeof(MovementRecord));
+ lureExe.read(&move, sizeof(MovementRecord));
}
movementSize += 2;
}
@@ -567,8 +698,8 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
// Loop to get in the animation records
for (ctr = 0; ctr < animIndex; ++ctr, ++rec) {
- lure_exe.seek(DATA_SEGMENT + animOffsets[ctr]);
- lure_exe.read(&inRec, sizeof(AnimRecord));
+ lureExe.seek(dataSegment + animOffsets[ctr]);
+ lureExe.read(&inRec, sizeof(AnimRecord));
rec->animRecordId = animOffsets[ctr];
rec->animId = inRec.animId;
@@ -599,8 +730,8 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
} else {
startOffset = moveOffset;
- lure_exe.seek(DATA_SEGMENT + offset);
- lure_exe.read(&move, sizeof(MovementRecord));
+ lureExe.seek(dataSegment + offset);
+ lureExe.read(&move, sizeof(MovementRecord));
destMove = (MovementRecord *) (data + moveOffset);
while (FROM_LE_16(move.frameNumber) != 0xffff) {
@@ -610,7 +741,7 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
moveOffset += sizeof(MovementRecord);
++destMove;
- lure_exe.read(&move, sizeof(MovementRecord));
+ lureExe.read(&move, sizeof(MovementRecord));
}
destMove->frameNumber = TO_LE_16(0xffff);
@@ -627,34 +758,38 @@ void read_anim_data(byte *&data, uint16 &totalSize) {
}
void read_script_data(byte *&data, uint16 &totalSize) {
- lure_exe.seek(SCRIPT_SEGMENT);
+ uint32 scriptSegment = 0x1df00;
+ if (language == IT_ITA) scriptSegment = 0x1e020;
+ lureExe.seek(scriptSegment);
totalSize = SCRIPT_SEGMENT_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
void read_script2_data(byte *&data, uint16 &totalSize) {
- lure_exe.seek(SCRIPT2_SEGMENT);
+ uint32 scriptSegment = 0x19c70;
+ if (language == IT_ITA) scriptSegment = 0x19D90;
+ lureExe.seek(scriptSegment);
totalSize = SCRIPT2_SEGMENT_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
void read_hotspot_script_offsets(byte *&data, uint16 &totalSize) {
- lure_exe.seek(DATA_SEGMENT + HOTSPOT_SCRIPT_LIST);
+ lureExe.seek(dataSegment + HOTSPOT_SCRIPT_LIST);
totalSize = HOTSPOT_SCRIPT_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
void read_messages_segment(byte *&data, uint16 &totalSize) {
- lure_exe.seek(MESSAGES_SEGMENT);
+ lureExe.seek(MESSAGES_SEGMENT);
totalSize = MESSAGES_SEGMENT_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
// Reads in the list of actions used
@@ -670,13 +805,13 @@ void read_actions_list(byte *&data, uint16 &totalSize) {
header->offset = offset;
++header;
- lure_exe.seek(DATA_SEGMENT + actionOffsets[ctr]);
+ lureExe.seek(dataSegment + actionOffsets[ctr]);
uint16 *numItems = (uint16 *) (data + offset);
- lure_exe.read(numItems, sizeof(uint16));
+ lureExe.read(numItems, sizeof(uint16));
offset += 2;
if (READ_UINT16(numItems) > 0) {
- lure_exe.read(data + offset, READ_UINT16(numItems) * 3);
+ lureExe.read(data + offset, READ_UINT16(numItems) * 3);
offset += READ_UINT16(numItems) * 3;
}
}
@@ -685,13 +820,6 @@ void read_actions_list(byte *&data, uint16 &totalSize) {
// Reads in the talk data
-#define TALK_OFFSET 0x505c
-#define TALK_NUM_ENTRIES 28
-#define MAX_TALK_LISTS 300
-
-uint16 talkOffsets[MAX_TALK_LISTS];
-int talkOffsetIndex = 0;
-
void add_talk_offset(uint16 offset) {
for (int ctr = 0; ctr < talkOffsetIndex; ++ctr)
if (talkOffsets[ctr] == offset) return;
@@ -713,8 +841,10 @@ void read_talk_headers(byte *&data, uint16 &totalSize) {
uint16 sortedOffsets[TALK_NUM_ENTRIES+1];
int entryCtr, subentryCtr;
- lure_exe.seek(DATA_SEGMENT + TALK_OFFSET);
- lure_exe.read(&entries[0], sizeof(TalkEntry) * TALK_NUM_ENTRIES);
+ uint16 dataStart = 0x505c;
+ if (language == IT_ITA) dataStart = 0x511C;
+ lureExe.seek(dataSegment + dataStart);
+ lureExe.read(&entries[0], sizeof(TalkEntry) * TALK_NUM_ENTRIES);
// Sort the entry offsets into a list - this is used to figure out each entry's size
int currVal, prevVal = 0;
@@ -754,10 +884,10 @@ void read_talk_headers(byte *&data, uint16 &totalSize) {
exit(1);
// Read in line entries into the data
- lure_exe.seek(DATA_SEGMENT + startOffset);
+ lureExe.seek(dataSegment + startOffset);
int size = nextOffset - startOffset;
uint16 *talkOffset = (uint16 *) (data + offset);
- lure_exe.read(talkOffset, size);
+ lureExe.read(talkOffset, size);
while (size > 0) {
if (READ_UINT16(talkOffset) != 0)
@@ -784,13 +914,17 @@ struct TalkRecord {
uint16 responsesOffset;
};
-uint16 giveTalkIds[6] = {0xCF5E, 0xCF14, 0xCF90, 0xCFAA, 0xCFD0, 0xCFF6};
+uint16 englishGiveTalkIds[7] = {0xCF5E, 0xCF14, 0xCF90, 0xCFAA, 0xCFD0, 0xCFF6, 0xf010};
+uint16 italianGiveTalkIds[7] = {0xD01E, 0xCFD4, 0xD050, 0xD06A, 0xD090, 0xD0B6, 0xf0d0};
void read_talk_data(byte *&data, uint16 &totalSize) {
uint16 responseOffset;
int talkCtr, subentryCtr;
uint16 size;
+ uint16 *giveTalkIds = &englishGiveTalkIds[0];
+ if (language == IT_ITA) giveTalkIds = &italianGiveTalkIds[0];
+
for (talkCtr = 0; talkCtr < 6; ++talkCtr)
add_talk_offset(giveTalkIds[talkCtr]);
@@ -815,7 +949,7 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
sortedList[talkCtr] = currVal;
prevVal = currVal;
}
- sortedList[talkCtr] = 0xf010;
+ sortedList[talkCtr] = giveTalkIds[6];
int numTalks = talkCtr;
// Loop through the talk list
@@ -827,8 +961,8 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
header->recordId = startOffset;
header->listOffset = offset;
- lure_exe.seek(DATA_SEGMENT + startOffset);
- responseOffset = lure_exe.readWord();
+ lureExe.seek(dataSegment + startOffset);
+ responseOffset = lureExe.readWord();
startOffset += 2;
// Special handling for entry at 0d930h
@@ -843,12 +977,12 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
size = responseOffset - startOffset;
if ((size % 6) == 2) size -= 2;
if ((size % 6) != 0) {
- printf("Failure reading talk data\n");
+ printf("Failure reading talk data: size=%d\n", size);
exit(1);
}
// Read in the list of talk entries
- lure_exe.read(data + offset, size);
+ lureExe.read(data + offset, size);
offset += size;
memset(data + offset, 0xff, 2);
offset += 2;
@@ -871,7 +1005,7 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
}
}
if (nextOffset < responseOffset) {
- printf("Failure reading talk data\n");
+ printf("Failure reading talk data: no response found\n");
exit(1);
}
@@ -879,11 +1013,11 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
if ((size % 6) != 0) size -= (size % 6);
if ((size % 6) != 0) {
- printf("Failure reading talk data\n");
+ printf("Failure reading talk data: newSize=%d\n", size);
exit(1);
}
- lure_exe.read(data + offset, size);
+ lureExe.read(data + offset, size);
offset += size;
WRITE_LE_UINT16(data + offset, 0xffff);
offset += 2;
@@ -897,11 +1031,13 @@ void read_talk_data(byte *&data, uint16 &totalSize) {
}
void read_room_pathfinding_data(byte *&data, uint16 &totalSize) {
- lure_exe.seek(DATA_SEGMENT + PATHFIND_OFFSET);
+ uint16 dataStart = 0x984A;
+ if (language == IT_ITA) dataStart = 0x990A;
+ lureExe.seek(dataSegment + dataStart);
totalSize = PATHFIND_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
void read_room_exit_coordinate_data(byte *&data, uint16 &totalSize)
@@ -913,13 +1049,13 @@ void read_room_exit_coordinate_data(byte *&data, uint16 &totalSize)
totalSize = EXIT_COORDINATES_NUM_ROOMS * sizeof(RoomExitCoordinateEntryOutputResource) + 2;
data = (byte *) malloc(totalSize);
- lure_exe.seek(DATA_SEGMENT + EXIT_COORDINATES_OFFSET);
+ lureExe.seek(dataSegment + EXIT_COORDINATES_OFFSET);
WRITE_LE_UINT16(data + totalSize - 2, 0xffff);
// Post process the list to adjust data
RoomExitCoordinateEntryOutputResource *rec = (RoomExitCoordinateEntryOutputResource *) data;
for (roomNum = 1; roomNum <= EXIT_COORDINATES_NUM_ROOMS; ++roomNum, ++rec) {
- lure_exe.read(&dataIn, sizeof(RoomExitCoordinateEntryInputResource));
+ lureExe.read(&dataIn, sizeof(RoomExitCoordinateEntryInputResource));
for (entryNum = 0; entryNum < ROOM_EXIT_COORDINATES_NUM_ENTRIES; ++entryNum) {
x = FROM_LE_16(dataIn.entries[entryNum].x);
@@ -950,13 +1086,16 @@ void read_room_exit_hotspots_data(byte *&data, uint16 &totalSize) {
data = (byte *) malloc(MAX_DATA_SIZE);
RoomExitIndexedHotspotResource *rec = (RoomExitIndexedHotspotResource *) data;
- lure_exe.seek(DATA_SEGMENT + EXIT_HOTSPOTS_OFFSET);
-
- lure_exe.read(rec, sizeof(RoomExitIndexedHotspotResource));
+
+ uint16 dataStart = 0x2E57;
+ if (language == IT_ITA) dataStart = 0x2E66;
+ lureExe.seek(dataSegment + dataStart);
+
+ lureExe.read(rec, sizeof(RoomExitIndexedHotspotResource));
while (FROM_LE_16(rec->roomNumber) != 0) {
++rec;
totalSize += sizeof(RoomExitIndexedHotspotResource);
- lure_exe.read(rec, sizeof(RoomExitIndexedHotspotResource));
+ lureExe.read(rec, sizeof(RoomExitIndexedHotspotResource));
}
WRITE_LE_UINT16(rec, 0xffff);
@@ -964,30 +1103,49 @@ void read_room_exit_hotspots_data(byte *&data, uint16 &totalSize) {
}
void save_fight_segment(byte *&data, uint16 &totalSize) {
- lure_exe.seek(FIGHT_SEGMENT);
+ uint16 fightSegment = 0x1C400;
+ if (language == IT_ITA) fightSegment = 0x1c520;
+ lureExe.seek(fightSegment);
totalSize = FIGHT_SEGMENT_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
-#define NUM_TEXT_ENTRIES 40
-const char *text_strings[NUM_TEXT_ENTRIES] = {
+#define NUM_TEXT_ENTRIES 49
+const char *englishTextStrings[NUM_TEXT_ENTRIES] = {
"Get", NULL, "Push", "Pull", "Operate", "Open", "Close", "Lock", "Unlock", "Use",
"Give", "Talk to", "Tell", "Buy", "Look", "Look at", "Look through", "Ask", NULL,
"Drink", "Status", "Go to", "Return", "Bribe", "Examine",
"Credits", "Restart game", "Save game", "Restore game", "Quit", "Fast Text", "Slow Text",
- "Sound on", "Sound off", "(nothing)", " for ", " to ", " on ", "and then", "finish"};
+ "Sound on", "Sound off", "(nothing)", " for ", " to ", " on ", "and then", "finish",
+ "Are you sure (y/n)?",
+ "a ", "the ", "a ", "a ", "an ", "an ", "an ", "an "
+};
+const char *italianTextStrings[NUM_TEXT_ENTRIES] = {
+ "Prendi", NULL, "Spingi", "Tira", "Aziona", "Apri", "Chiudi", "Blocca",
+ "Sblocca", "Usa", "Dai", "Parla con", "Ordina a", "Buy", "Guarda", "Osserva",
+ "Guarda tra", "Chiedi", NULL, "Bevi", "Stato", "Vai a", "Ritorna",
+ "Corrompi", "Esamina",
+ "Inform", "Reavvia", "Salva gioco", "Ripristina", "Abbandona", "Testo lento",
+ "Testo veloce", "Sonoro acceso", "Sonoro spento",
+ "(niente)", " per ", " a ", " su ",
+ "e poi", "finito", "Sei sicuro (s/n)?",
+ NULL, "l' ", "la ", NULL, "le ", "i ", "il ", NULL
+};
void save_text_strings(byte *&data, uint16 &totalSize) {
int index;
+ const char **textStrings = &englishTextStrings[0];
+ if (language == IT_ITA) textStrings = &italianTextStrings[0];
+
// Calculate the total needed space
totalSize = sizeof(uint16);
for (index = 0; index < NUM_TEXT_ENTRIES; ++index) {
- if (text_strings[index] != NULL)
- totalSize += strlen(text_strings[index]);
+ if (textStrings[index] != NULL)
+ totalSize += strlen(textStrings[index]);
++totalSize;
}
@@ -997,27 +1155,123 @@ void save_text_strings(byte *&data, uint16 &totalSize) {
char *p = (char *) data + sizeof(uint16);
for (index = 0; index < NUM_TEXT_ENTRIES; ++index) {
- if (text_strings[index] == NULL)
+ if (textStrings[index] == NULL)
*p++ = '\0';
else {
- strcpy(p, text_strings[index]);
+ strcpy(p, textStrings[index]);
p += strlen(p) + 1;
}
}
}
void save_sound_desc_data(byte *&data, uint16 &totalSize) {
- lure_exe.seek(DATA_SEGMENT + SOUND_1_OFFSET);
+ uint16 dataStart = 0x5671;
+ if (language == IT_ITA) dataStart = 0x5731;
+ lureExe.seek(dataSegment + dataStart);
- totalSize = SOUND_1_SIZE;
+ totalSize = SOUND_DESCS_SIZE;
data = (byte *) malloc(totalSize);
- lure_exe.read(data, totalSize);
+ lureExe.read(data, totalSize);
}
-void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size)
-{
- resourceId = 0x3f01 + entryIndex;
+struct DecoderEntry {
+ char *sequence;
+ char character;
+};
+
+const DecoderEntry englishDecoders[] = {
+ {"00", ' '}, {"0100", 'e'}, {"0101", 'o'}, {"0110", 't'}, {"01110", 'a'},
+ {"01111", 'n'}, {"1000", 's'}, {"1001", 'i'}, {"1010", 'r'}, {"10110", 'h'},
+ {"101110", 'u'}, {"1011110", 'l'}, {"1011111", 'd'}, {"11000", 'y'},
+ {"110010", 'g'}, {"110011", '\0'}, {"110100", 'w'}, {"110101", 'c'},
+ {"110110", 'f'}, {"1101110", '.'}, {"1101111", 'm'}, {"111000", 'p'},
+ {"111001", 'b'}, {"1110100", ','}, {"1110101", 'k'}, {"1110110", '\''},
+ {"11101110", 'I'}, {"11101111", 'v'}, {"1111000", '!'}, {"1111001", '\xb4'},
+ {"11110100", 'T'}, {"11110101", '\xb5'}, {"11110110", '?'}, {"111101110", '\xb2'},
+ {"111101111", '\xb3'}, {"11111000", 'W'}, {"111110010", 'H'}, {"111110011", 'A'},
+ {"111110100", '\xb1'}, {"111110101", 'S'}, {"111110110", 'Y'}, {"1111101110", 'G'},
+ {"11111011110", 'M'}, {"11111011111", 'N'}, {"111111000", 'O'}, {"1111110010", 'E'},
+ {"1111110011", 'L'}, {"1111110100", '-'}, {"1111110101", 'R'}, {"1111110110", 'B'},
+ {"11111101110", 'D'}, {"11111101111", '\xa6'}, {"1111111000", 'C'},
+ {"11111110010", 'x'}, {"11111110011", 'j'}, {"1111111010", '\xac'},
+ {"11111110110", '\xa3'}, {"111111101110", 'P'}, {"111111101111", 'U'},
+ {"11111111000", 'q'}, {"11111111001", '\xad'}, {"111111110100", 'F'},
+ {"111111110101", '1'}, {"111111110110", '\xaf'}, {"1111111101110", ';'},
+ {"1111111101111", 'z'}, {"111111111000", '\xa5'}, {"1111111110010", '2'},
+ {"1111111110011", '\xb0'}, {"111111111010", 'K'}, {"1111111110110", '%'},
+ {"11111111101110", '\xa2'}, {"11111111101111", '5'}, {"1111111111000", ':'},
+ {"1111111111001", 'J'}, {"1111111111010", 'V'}, {"11111111110110", '6'},
+ {"11111111110111", '3'}, {"1111111111100", '\xab'}, {"11111111111010", '\xae'},
+ {"111111111110110", '0'}, {"111111111110111", '4'}, {"11111111111100", '7'},
+ {"111111111111010", '9'}, {"111111111111011", '"'}, {"111111111111100", '8'},
+ {"111111111111101", '\xa7'}, {"1111111111111100", '/'}, {"1111111111111101", 'Q'},
+ {"11111111111111100", '\xa8'}, {"11111111111111101", '('}, {"111111111111111100", ')'},
+ {"111111111111111101", '\x99'}, {"11111111111111111", '\xa9'},
+ {NULL, '\0'}
+};
+
+const DecoderEntry italianDecoders[] = {
+ {"00", ' '}, {"010", 0x69}, {"0110", 0x6F}, {"01110", 0x61}, {"01111", 0x65},
+ {"1000", 0x72}, {"1001", 0x6E}, {"1010", 0x74}, {"10110", 0x73}, {"101110", 0x6C},
+ {"101111", 0x63}, {"11000", 0x75}, {"110010", 0x70}, {"110011", 0x64}, {"110100", 0},
+ {"110101", 0x6D}, {"110110", 0x67}, {"1101110", 0x2E}, {"1101111", 0x76},
+ {"111000", 0x68}, {"1110010", 0x2C}, {"1110011", 0x62}, {"1110100", 0x66},
+ {"1110101", 0x21}, {"1110110", 0xB5}, {"11101110", 0xB1}, {"111011110", 0xB3},
+ {"111011111", 0x7A}, {"1111000", 0xB4}, {"11110010", 0x27}, {"111100110", 0x4E},
+ {"111100111", 0x4C}, {"11110100", 0x3F}, {"111101010", 0x85}, {"111101011", 0x53},
+ {"11110110", 0x43}, {"111101110", 0x4D}, {"1111011110", 0xAC}, {"1111011111", 0x49},
+ {"11111000", 0x45}, {"111110010", 0x41}, {"1111100110", 0x54}, {"1111100111", 0xB2},
+ {"111110100", 0x71}, {"111110101", 0x4F}, {"111110110", 0x47}, {"1111101110", 0xAB},
+ {"11111011110", 0x50}, {"11111011111", 0x44}, {"111111000", 0x81},
+ {"1111110010", 0x55}, {"11111100110", 0xAE}, {"11111100111", 0x52},
+ {"1111110100", 0xA6}, {"1111110101", 0x56}, {"1111110110", 0xA8},
+ {"11111101110", 0x42}, {"111111011110", 0x51}, {"111111011111", 0xB0},
+ {"1111111000", 0x95}, {"11111110010", 0x48}, {"11111110011", 0x2D},
+ {"11111110100", 0xA9}, {"11111110101", 0x8A}, {"11111110110", 0xA3},
+ {"111111101110", 0x46}, {"111111101111", 0xA7}, {"11111111000", 0x8D},
+ {"11111111001", 0x77}, {"11111111010", 0x79}, {"111111110110", 0x7F},
+ {"1111111101110", 0x6B}, {"1111111101111", 0x31}, {"111111111000", 0x3B},
+ {"111111111001", 0xA5}, {"111111111010", 0x57}, {"1111111110110", 0x32},
+ {"11111111101110", 0xAF}, {"11111111101111", 0x35}, {"1111111111000", 0xA2},
+ {"1111111111001", 0xAD}, {"1111111111010", 0x25}, {"11111111110110", 0x36},
+ {"11111111110111", 0x3A}, {"1111111111100", 0x5A}, {"11111111111010", 0x33},
+ {"11111111111011", 0x30}, {"11111111111100", 0x34}, {"111111111111010", 0x39},
+ {"111111111111011", 0x37}, {"111111111111100", 0x38}, {"111111111111101", 0x2F},
+ {"1111111111111100", 0x4B}, {"1111111111111101", 0x22}, {"111111111111111000", 0x09},
+ {"111111111111111001", 0x28}, {"11111111111111101", 0x29}, {"111111111111111100", 0x4A},
+ {"111111111111111101", 0x59}, {"11111111111111111", 0x78},
+ {NULL, '\0'}
+};
+
+void save_string_decoder_data(byte *&data, uint16 &totalSize) {
+ const DecoderEntry *list = &englishDecoders[0];
+ if (language == IT_ITA) list = &italianDecoders[0];
+
+ totalSize = 1;
+ const DecoderEntry *pSrc = list;
+ while (pSrc->sequence != NULL) {
+ totalSize += strlen(pSrc->sequence) + 2;
+ ++pSrc;
+ }
+
+ data = (byte *) malloc(totalSize);
+ char *pDest = (char *)data;
+
+ pSrc = list;
+ while (pSrc->sequence != NULL) {
+ *pDest++ = pSrc->character;
+ strcpy(pDest, pSrc->sequence);
+ pDest += strlen(pSrc->sequence) + 1;
+ ++pSrc;
+ }
+
+ *pDest = 0xff;
+}
+
+void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size) {
+ resourceId = 0x3f01 + entryIndex;
+printf("Get resource #%d\n", entryIndex);
switch (entryIndex)
{
case 0:
@@ -1139,6 +1393,11 @@ void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size)
// Save the sound header desc data
save_sound_desc_data(data, size);
break;
+
+ case 24:
+ // Save the decoder sequence list
+ save_string_decoder_data(data, size);
+ break;
default:
data = NULL;
@@ -1148,25 +1407,57 @@ void getEntry(uint8 entryIndex, uint16 &resourceId, byte *&data, uint16 &size)
}
}
+void openOutputFile(const char *outFilename) {
+ outputFile.open(outFilename, kFileWriteMode);
+
+ // Write header
+ outputFile.write("lure", 4);
+ outputFile.writeWord(0);
+
+ outputFile.seek(0xBF * 8);
+ FileEntry fileVersion;
+ memset(&fileVersion, 0xff, sizeof(FileEntry));
+ fileVersion.unused = VERSION_MAJOR;
+ fileVersion.sizeExtension = VERSION_MINOR;
+ outputFile.write(&fileVersion, sizeof(FileEntry));
+}
+
+void closeOutputFile() {
+ outputFile.seek(6 + 5 * langIndex);
+ outputFile.writeByte(0xff);
+ outputFile.close();
+}
+
void createFile(const char *outFilename)
{
FileEntry rec;
uint32 startOffset, numBytes;
+ uint32 outputStart;
uint16 resourceId;
uint16 resourceSize;
byte *resourceData;
bool resourceFlag;
byte tempBuffer[32];
- File f;
- f.open(outFilename, kFileWriteMode);
memset(tempBuffer, 0, 32);
- // Write header
- f.write("heywow", 6);
- f.writeWord(0);
-
+ // Reset list counters
+ outputStart = ((outputFile.pos() + 0xff) / 0x100) * 0x100;
startOffset = 0x600;
+ animIndex = 0;
+ actionIndex = 0;
+ talkOffsetIndex = 0;
+
+ // Write out the position of the next language set
+ outputFile.seek(6 + 5 * (langIndex - 1));
+ outputFile.writeByte(language);
+ outputFile.writeLong(outputStart);
+
+ // Write out start header
+ outputFile.seek(outputStart);
+ outputFile.write("heywow", 6);
+ outputFile.writeWord(0);
+
resourceFlag = true;
for (int resIndex=0; resIndex<0xBE; ++resIndex)
{
@@ -1178,7 +1469,7 @@ void createFile(const char *outFilename)
getEntry(resIndex, resourceId, resourceData, resourceSize);
// Write out the next header entry
- f.seek(8 + resIndex * 8);
+ outputFile.seek(outputStart + (resIndex + 1) * 8);
if (resourceSize == 0)
{
// Unused entry
@@ -1194,13 +1485,13 @@ void createFile(const char *outFilename)
rec.unused = 0xff;
}
- f.write(&rec, sizeof(FileEntry));
+ outputFile.write(&rec, sizeof(FileEntry));
// Write out the resource
if (resourceFlag)
{
- f.seek(startOffset);
- f.write(resourceData, resourceSize);
+ outputFile.seek(outputStart + startOffset);
+ outputFile.write(resourceData, resourceSize);
startOffset += resourceSize;
free(resourceData); // Free the data block
@@ -1208,21 +1499,14 @@ void createFile(const char *outFilename)
numBytes = 0x20 * ((startOffset + 0x1f) / 0x20) - startOffset;
if (numBytes != 0)
{
- f.write(tempBuffer, numBytes);
+ outputFile.write(tempBuffer, numBytes);
startOffset += numBytes;
}
}
}
- // Store file version in final file slot
- f.seek(0xBF * 8);
- FileEntry fileVersion;
- memset(&fileVersion, 0xff, sizeof(FileEntry));
- fileVersion.unused = VERSION_MAJOR;
- fileVersion.sizeExtension = VERSION_MINOR;
- f.write(&fileVersion, sizeof(FileEntry));
-
- f.close();
+ // Move to the end of the written file
+ outputFile.seek(0, SEEK_END);
}
// validate_executable
@@ -1230,36 +1514,58 @@ void createFile(const char *outFilename)
// resource file. Eventually the resource file creator will need to work
// with the other language executables, but for now just make
-#define NUM_BYTES_VALIDATE 1024
-#define FILE_CHECKSUM 64880
-
-void validate_executable() {
+bool validate_executable() {
uint32 sumTotal = 0;
byte buffer[NUM_BYTES_VALIDATE];
- lure_exe.read(buffer, NUM_BYTES_VALIDATE);
+ lureExe.read(buffer, NUM_BYTES_VALIDATE);
for (int ctr = 0; ctr < NUM_BYTES_VALIDATE; ++ctr)
sumTotal += buffer[ctr];
- if (sumTotal != FILE_CHECKSUM) {
- printf("Lure executable not correct English version\n");
- exit(1);
+ if (sumTotal == ENGLISH_FILE_CHECKSUM) {
+ language = EN_ANY;
+ dataSegment = 0xAC50;
+ printf("Detected English version\n");
+ } else if (sumTotal == ITALIAN_FILE_CHECKSUM) {
+ language = IT_ITA;
+ dataSegment = 0xACB0;
+ printf("Detected Italian version\n");
+ } else {
+ printf("Lure executable version not recognised. Checksum = %xh\n", sumTotal);
+ return false;
}
+
+ // Double-check that the given language has not already been done
+ for (int index = 0; index < langIndex; ++index) {
+ if (processedLanguages[index] == language) {
+ printf("Identical language executable listed multiple times\n");
+ return false;
+ }
+ }
+
+ processedLanguages[langIndex++] = language;
+ return true;
}
int main(int argc, char *argv[]) {
- // FIXME: This is not portable
- const char *inFilename = (argc >= 2) ? argv[1] : "c:\\games\\lure\\lure.exe";
- const char *outFilename = (argc == 3) ? argv[2] : "c:\\games\\lure\\lure.dat";
+ const char *inFilename, *outFilename;
- if (!lure_exe.open(inFilename)) {
- if (argc == 1)
- printf("Format: %s input_exe_filename output_filename\n", argv[0]);
- else
- printf("Could not open file: %s\n", inFilename);
- } else {
- validate_executable();
- createFile(outFilename);
- lure_exe.close();
+ if (argc == 1) {
+ printf("Format: %s output_filename [lureExecutable ..]\n", argv[0]);
+ exit(0);
}
+
+ openOutputFile(argv[1]);
+
+ for (int argi = 2; argi < argc; ++argi) {
+ if (!lureExe.open(argv[argi]))
+ printf("Could not open file: %s\n", argv[argi]);
+ else {
+ if (validate_executable())
+ createFile(outFilename);
+ lureExe.close();
+ }
+ }
+
+ closeOutputFile();
}
diff --git a/tools/create_lure/create_lure_dat.h b/tools/create_lure/create_lure_dat.h
index 20b67000d7..6e8adde742 100644
--- a/tools/create_lure/create_lure_dat.h
+++ b/tools/create_lure/create_lure_dat.h
@@ -27,32 +27,24 @@
#define __CREATELURE_DAT__
#include "common/endian.h"
+#include "common/util.h"
#define VERSION_MAJOR 1
-#define VERSION_MINOR 21
-#define ENGLISH_LURE
+#define VERSION_MINOR 22
-#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 FIGHT_SEGMENT 0x1C400
#define FIGHT_SEGMENT_SIZE 0x1850
#define HOTSPOT_SCRIPT_LIST 0x57e0
@@ -61,9 +53,7 @@
#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
@@ -71,24 +61,16 @@
#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 33
-#define RANDOM_ACTIONS_OFFSET 0x4D10
#define RANDOM_ROOM_NUM_ENTRIES 41
-#define WALK_AREAS_OFFSET 0x2EB1
-
-#define EXIT_HOTSPOTS_OFFSET 0x2E57
-
-#define SOUND_1_OFFSET 0x5671
-#define SOUND_1_SIZE 265
+#define SOUND_DESCS_SIZE 265
#include "common/pack-start.h" // START STRUCT PACKING
@@ -190,7 +172,7 @@ struct HotspotResourceOutput {
uint16 animRecordId;
uint16 hotspotScriptOffset;
uint16 talkScriptOffset;
- uint16 tickProcOffset;
+ uint16 tickProcId;
uint16 tickTimeout;
uint16 tickSequenceOffset;
uint16 npcSchedule;
@@ -427,9 +409,15 @@ public:
uint32 vTemp = TO_LE_32(v);
write(&vTemp, sizeof(uint32));
}
+ uint32 pos() {
+ return ftell(f);
+ }
};
-extern File lure_exe;
+extern File lureExe;
extern void add_talk_offset(uint16 offset);
+extern Common::Language language;
+extern uint16 dataSegment;
+
#endif
diff --git a/tools/create_lure/process_actions.cpp b/tools/create_lure/process_actions.cpp
index a4de8c8fe3..bb2348ff67 100644
--- a/tools/create_lure/process_actions.cpp
+++ b/tools/create_lure/process_actions.cpp
@@ -24,8 +24,11 @@
*/
#include "common/scummsys.h"
+#include "common/util.h"
#include "create_lure_dat.h"
+using namespace Common;
+
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,
@@ -51,10 +54,18 @@ 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, 1, 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
+
+struct JumpOffsetsRecord {
+ Common::Language language;
+ uint16 jumpOffsets[2];
+};
+
+JumpOffsetsRecord jumpOffsets[] = {
+ {EN_ANY, {0x87be, 0x881c}},
+ {IT_ITA, {0x881c, 0x887a}},
+ {UNK_LANG, {0, 0}}
+};
#define MAX_BUFFER_ENTRIES 63
#define MAX_INSTRUCTION_ENTRIES 300
@@ -110,13 +121,27 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
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 == 0x76ec) { startOffset = 0x734a; maxOffset = 0x77a2; }
-#endif
+
+ 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;
+ }
+
//printf("Start=%xh max=%xh\n", startOffset, maxOffset);
SymbolTableEntry symbolTable[MAX_INSTRUCTION_ENTRIES];
uint16 numSymbols = 0;
@@ -127,8 +152,9 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
uint16 params[5];
uint16 index;
uint16 *pOut = (uint16 *) data;
+ JumpOffsetsRecord *jmpOffset;
- lure_exe.seek(DATA_SEGMENT + startOffset);
+ lureExe.seek(dataSegment + startOffset);
rec.numInstructions = 0;
for (;;) {
@@ -150,13 +176,13 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
}
// Get in the next action
- actionNum = lure_exe.readWord();
+ actionNum = lureExe.readWord();
-// printf("%xh - action=%d", offset, actionNum);
+//printf("%xh - action=%d", offset, actionNum);
if (actionNum == 0) {
// At end of script block
-// printf("\n");
+//printf("\n");
break;
}
else if (actionNum > NPC_JUMP_ADDRESS) {
@@ -169,7 +195,7 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
// Read in any action parameters
for (int paramCtr = 0; paramCtr < numParams[actionNum]; ++paramCtr)
- params[paramCtr] = lure_exe.readWord();
+ params[paramCtr] = lureExe.readWord();
switch(actionNum) {
case NPC_SET_ROOM_AND_BLOCKED_OFFSET:
@@ -195,15 +221,17 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
case NPC_JUMP_ADDRESS:
// Make sure the address is in the known list
+ jmpOffset = &jumpOffsets[0];
+ while (jmpOffset->language != language) ++jmpOffset;
index = 0;
- while ((index < NUM_JUMP_OFFSETS) && (jumpOffsets[index] != params[0]))
+ while ((index < NUM_JUMP_OFFSETS) && (jmpOffset->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]);
+ printf("\nEncountered unrecognised NPC code jump point: %xh\n", params[0]);
exit(1);
}
break;
@@ -223,9 +251,9 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
for (paramIndex = 0; paramIndex < numParams[actionNum]; ++paramIndex)
{
*pOut++ = TO_LE_16(params[paramIndex]);
-// printf(" %xh", TO_LE_16(params[paramIndex]));
+//printf(" %xh", TO_LE_16(params[paramIndex]));
}
-// printf("\n");
+//printf("\n");
// Increase size
totalSize += (numParams[actionNum] + 1) * sizeof(uint16);
@@ -293,7 +321,6 @@ struct RoomRandomActionSet {
void read_action_sequence(byte *&data, uint16 &totalSize)
{
- const uint16 hsOffset = 0x5d98;
uint16 hotspotIndex;
HotspotHeaderEntry entryHeader;
CurrentActionInput action;
@@ -305,19 +332,20 @@ void read_action_sequence(byte *&data, uint16 &totalSize)
// 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);
+ lureExe.seek(dataSegment + TABLED_ACTIONS_OFFSET, SEEK_SET);
for (index = 0; index < NUM_TABLED_ACTION_BLOCKS; ++index)
- offsetList[index] = lure_exe.readWord();
+ offsetList[index] = lureExe.readWord();
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];
-
+
// Get a list of the offsets for each room
- lure_exe.seek(DATA_SEGMENT + RANDOM_ACTIONS_OFFSET, SEEK_SET);
- for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex)
- {
- randomActions[roomIndex].offset = lure_exe.readWord();
+ uint16 raOffset = 0x4D10;
+ if (language == IT_ITA) raOffset = 0x4dc0;
+ lureExe.seek(dataSegment + raOffset, SEEK_SET);
+ for (roomIndex = 0; roomIndex < RANDOM_ROOM_NUM_ENTRIES; ++roomIndex) {
+ randomActions[roomIndex].offset = lureExe.readWord();
randomActions[roomIndex].numEntries = 0;
randomActions[roomIndex].entries = NULL;
}
@@ -328,8 +356,8 @@ void read_action_sequence(byte *&data, uint16 &totalSize)
if (randomActions[roomIndex].offset == 0)
continue;
- lure_exe.seek(DATA_SEGMENT + randomActions[roomIndex].offset, SEEK_SET);
- randomActions[roomIndex].numEntries = lure_exe.readByte();
+ lureExe.seek(dataSegment + randomActions[roomIndex].offset, SEEK_SET);
+ randomActions[roomIndex].numEntries = lureExe.readByte();
assert(randomActions[roomIndex].numEntries <= 8);
randomActions[roomIndex].entries = new RoomRandomActionEntry[randomActions[roomIndex].numEntries];
@@ -337,15 +365,15 @@ void read_action_sequence(byte *&data, uint16 &totalSize)
uint16 offset = randomActions[roomIndex].offset + 1;
for (uint8 entryCtr = 0; entryCtr < randomActions[roomIndex].numEntries; ++entryCtr)
{
- randomActions[roomIndex].entries[entryCtr].repeatable = lure_exe.readWord() == 1;
+ randomActions[roomIndex].entries[entryCtr].repeatable = lureExe.readWord() == 1;
offset += 2;
- uint16 firstCommand = lure_exe.readWord();
+ uint16 firstCommand = lureExe.readWord();
randomActions[roomIndex].entries[entryCtr].offset =
(firstCommand == 0xfffe) ? 0 : offset;
offset += sizeof(uint16);
- while (lure_exe.readWord() != 0xffff)
+ while (lureExe.readWord() != 0xffff)
offset += sizeof(uint16);
offset += sizeof(uint16);
}
@@ -361,15 +389,25 @@ void read_action_sequence(byte *&data, uint16 &totalSize)
// 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); // RETURN sequence
- process_entry(0xbb95, data, totalSize); // Exit blocked sequence
- process_entry(0x7060, data, totalSize); // Jump proc #2 - go to castle basement
- process_entry(0x728a, data, totalSize);
- process_entry(0x76ec, data, totalSize);
- process_entry(0x4ebb, data, totalSize); // Goewin as a follower in cave
- process_entry(0x7D9D, data, totalSize); // Goewin standard handler
-#endif
+ 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
+ process_entry(0x728a, data, totalSize);
+ process_entry(0x76ec, data, totalSize);
+ 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;
+ default:
+ printf("Unknown language\n");
+ exit(1);
+ }
// Process the script engine list
@@ -379,17 +417,20 @@ void read_action_sequence(byte *&data, uint16 &totalSize)
// Next process each of the character hotspots
+ uint16 hsOffset = 0x5d98;
+ if (language == IT_ITA) hsOffset = 0x5e58;
+
hotspotIndex = 0;
for (;;) {
- lure_exe.seek(DATA_SEGMENT + hsOffset +
+ lureExe.seek(dataSegment + hsOffset +
hotspotIndex * sizeof(HotspotHeaderEntry));
- lure_exe.read(&entryHeader, sizeof(HotspotHeaderEntry));
+ lureExe.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));
+ lureExe.seek(dataSegment + entryHeader.offset + 0x63);
+ lureExe.read(&action, sizeof(CurrentActionInput));
if (FROM_LE_16(action.action) == 2)
process_entry(FROM_LE_16(action.dataOffset), data, totalSize);
}