aboutsummaryrefslogtreecommitdiff
path: root/devtools/create_neverhood/create_neverhood.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/create_neverhood/create_neverhood.cpp')
-rw-r--r--devtools/create_neverhood/create_neverhood.cpp105
1 files changed, 67 insertions, 38 deletions
diff --git a/devtools/create_neverhood/create_neverhood.cpp b/devtools/create_neverhood/create_neverhood.cpp
index 323066d8b1..a37ff99ca9 100644
--- a/devtools/create_neverhood/create_neverhood.cpp
+++ b/devtools/create_neverhood/create_neverhood.cpp
@@ -30,12 +30,18 @@
#undef main
#endif // main
-#include <vector>
#include "create_neverhood.h"
+#include <vector>
+#include "md5.h"
#include "tables.h"
const int DAT_VERSION = 0;
+// The MD5 hash of the nhc.exe used to extract the tables from
+const uint8 kNhcExeMd5[16] = {
+ 0x37, 0xD6, 0x54, 0xA2, 0xA7, 0xBB, 0xB0, 0x1F,
+ 0x8C, 0x41, 0x9A, 0xB8, 0x49, 0xFF, 0x29, 0xD4};
+
uint32 dataSize;
byte *data;
uint32 dataStart = 0x004AE000;
@@ -48,12 +54,33 @@ class NavigationList;
void addMessageList(uint32 messageListCount, uint32 messageListOffset);
-void loadExe(const char *filename) {
+bool loadExe(const char *filename) {
FILE *exe = fopen(filename, "rb");
+ if (!exe) {
+ printf("Could not open nhc.exe for reading! Quitting...\n");
+ return false;
+ }
dataSize = fileSize(exe);
data = new byte[dataSize];
fread(data, dataSize, 1, exe);
fclose(exe);
+ return true;
+}
+
+bool validateMd5() {
+ uint8 digest[16];
+
+ md5_buffer(data, dataSize, digest);
+
+ printf("MD5 of nhc.exe is %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
+ digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
+
+ if (memcmp(kNhcExeMd5, digest, 16)) {
+ printf("MD5 hash of nhc.exe doesn't match the expected value! Quitting...\n");
+ return false;
+ }
+ return true;
}
byte *getData(uint32 offset) {
@@ -85,7 +112,7 @@ uint32 calcHash(const char *value) {
struct HitRect {
int16 x1, y1, x2, y2;
uint16 messageNum;
-
+
void load(uint32 offset) {
byte *item = getData(offset);
x1 = READ_LE_UINT16(item + 0);
@@ -93,7 +120,7 @@ struct HitRect {
x2 = READ_LE_UINT16(item + 4);
y2 = READ_LE_UINT16(item + 6);
messageNum = READ_LE_UINT16(item + 8);
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, x1);
@@ -102,11 +129,11 @@ struct HitRect {
writeUint16LE(fd, y2);
writeUint16LE(fd, messageNum);
}
-
+
int getItemSize() const {
return 10;
}
-
+
};
struct MessageItem {
@@ -114,22 +141,22 @@ struct MessageItem {
uint32 messageParam;
MessageItem() {}
MessageItem(uint16 msgNum, uint32 msgParam) : messageNum(msgNum), messageParam(msgParam) {}
-
+
void load(uint32 offset) {
byte *item = getData(offset);
messageNum = READ_LE_UINT16(item + 0);
messageParam = READ_LE_UINT32(item + 4);
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, messageNum);
writeUint32LE(fd, messageParam);
}
-
+
int getItemSize() const {
return 8;
}
-
+
};
struct SubRectItem {
@@ -148,7 +175,7 @@ struct SubRectItem {
// Add the message to the message list
addMessageList(messageListCount, messageListOffset);
}
-
+
void save(FILE *fd) {
writeUint16LE(fd, x1);
writeUint16LE(fd, y1);
@@ -156,11 +183,11 @@ struct SubRectItem {
writeUint16LE(fd, y2);
writeUint32LE(fd, messageListOffset);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct RectItem {
@@ -185,7 +212,7 @@ struct RectItem {
subItemOffset += 16;
subRectItems.push_back(subRectItem);
}
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, x1);
@@ -196,11 +223,11 @@ struct RectItem {
for (uint32 j = 0; j < subRectItems.size(); j++)
subRectItems[j].save(fd);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct NavigationItem {
@@ -211,10 +238,10 @@ struct NavigationItem {
byte interactive;
byte middleFlag;
uint32 mouseCursorFileHash;
-
+
void load(uint32 offset) {
byte *item = getData(offset);
- fileHash = READ_LE_UINT32(item + 0);
+ fileHash = READ_LE_UINT32(item + 0);
leftSmackerFileHash = READ_LE_UINT32(item + 4);
rightSmackerFileHash = READ_LE_UINT32(item + 8);
middleSmackerFileHash = READ_LE_UINT32(item + 12);
@@ -236,7 +263,7 @@ struct NavigationItem {
int getItemSize() const {
return 24;
}
-
+
};
struct SceneInfo140Item {
@@ -320,24 +347,24 @@ struct SceneInfo2700Item {
template<class ITEMCLASS>
class StaticDataList {
public:
- uint32 id;
+ uint32 id;
std::vector<ITEMCLASS> items;
-
+
virtual ~StaticDataList() {
}
-
+
void add(ITEMCLASS item) {
items.push_back(item);
}
-
+
int getCount() const {
return items.size();
}
-
+
ITEMCLASS *getListItem(int index) {
return &items[index];
}
-
+
virtual bool specialLoadList(uint32 count, uint32 offset) {
return false;
}
@@ -371,7 +398,7 @@ class RectList : public StaticDataList<RectItem> {
};
class MessageList : public StaticDataList<MessageItem> {
-public:
+public:
virtual bool specialLoadList(uint32 count, uint32 offset) {
// Special code for message lists which are set at runtime (but otherwise constant)
@@ -428,7 +455,7 @@ public:
}
return false;
}
-
+
};
class NavigationList : public StaticDataList<NavigationItem> {
@@ -438,11 +465,11 @@ template<class LISTCLASS>
class StaticDataListVector {
public:
std::vector<LISTCLASS*> lists;
-
+
void add(LISTCLASS *list) {
lists.push_back(list);
}
-
+
void loadListVector(const uint32 *offsets) {
for (int i = 0; offsets[i] != 0; i += 2) {
LISTCLASS *list = new LISTCLASS();
@@ -459,7 +486,7 @@ public:
lists.push_back(list);
}
}
-
+
void saveListVector(FILE *fd) {
writeUint32LE(fd, lists.size());
for (typename std::vector<LISTCLASS*>::iterator it = lists.begin(); it != lists.end(); it++) {
@@ -473,7 +500,7 @@ template<class ITEMCLASS>
class StaticDataVector {
public:
std::vector<ITEMCLASS> items;
-
+
void loadVector(const uint32 *offsets) {
for (int i = 0; offsets[i] != 0; i++) {
ITEMCLASS item;
@@ -481,7 +508,7 @@ public:
items.push_back(item);
}
}
-
+
void saveVector(FILE *fd) {
writeUint32LE(fd, items.size());
for (typename std::vector<ITEMCLASS>::iterator it = items.begin(); it != items.end(); it++) {
@@ -495,8 +522,8 @@ StaticDataListVector<HitRectList> hitRectLists;
StaticDataListVector<RectList> rectLists;
StaticDataListVector<MessageList> messageLists;
StaticDataListVector<NavigationList> navigationLists;
-StaticDataVector<SceneInfo140Item> sceneInfo140Items;
-StaticDataVector<SceneInfo2700Item> sceneInfo2700Items;
+StaticDataVector<SceneInfo140Item> sceneInfo140Items;
+StaticDataVector<SceneInfo2700Item> sceneInfo2700Items;
void addMessageList(uint32 messageListCount, uint32 messageListOffset) {
MessageList *messageList = new MessageList();
@@ -506,9 +533,11 @@ void addMessageList(uint32 messageListCount, uint32 messageListOffset) {
int main(int argc, char *argv[]) {
- FILE *datFile;
+ if (!loadExe("nhc.exe") ||
+ !validateMd5())
+ return 1;
- loadExe("nhc.exe");
+ FILE *datFile;
hitRectLists.loadListVector(hitRectListOffsets);
rectLists.loadListVector(rectListOffsets);
@@ -516,12 +545,12 @@ int main(int argc, char *argv[]) {
navigationLists.loadListVector(navigationListOffsets);
sceneInfo140Items.loadVector(sceneInfo140Offsets);
sceneInfo2700Items.loadVector(sceneInfo2700Offsets);
-
+
datFile = fopen("neverhood.dat", "wb");
writeUint32LE(datFile, 0x11223344); // Some magic
writeUint32LE(datFile, DAT_VERSION);
-
+
messageLists.saveListVector(datFile);
rectLists.saveListVector(datFile);
hitRectLists.saveListVector(datFile);