aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/create_neverhood/create_neverhood.cpp487
1 files changed, 269 insertions, 218 deletions
diff --git a/devtools/create_neverhood/create_neverhood.cpp b/devtools/create_neverhood/create_neverhood.cpp
index 25ef67651d..14dd32db3d 100644
--- a/devtools/create_neverhood/create_neverhood.cpp
+++ b/devtools/create_neverhood/create_neverhood.cpp
@@ -41,6 +41,13 @@ byte *data;
uint32 dataStart = 0x004AE000;
uint32 fileStart = 0x000AC600;
+class HitRectList;
+class RectList;
+class MessageList;
+class NavigationList;
+
+void addMessageList(uint32 messageListCount, uint32 messageListOffset);
+
void loadExe(const char *filename) {
FILE *exe = fopen(filename, "rb");
dataSize = fileSize(exe);
@@ -49,38 +56,131 @@ void loadExe(const char *filename) {
fclose(exe);
}
+byte *getData(uint32 offset) {
+ return data + offset - dataStart + fileStart;
+}
+
struct HitRect {
int16 x1, y1, x2, y2;
uint16 messageNum;
+
+ void load(uint32 offset) {
+ byte *item = getData(offset);
+ x1 = READ_LE_UINT16(item + 0);
+ y1 = READ_LE_UINT16(item + 2);
+ 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);
+ writeUint16LE(fd, y1);
+ writeUint16LE(fd, x2);
+ writeUint16LE(fd, y2);
+ writeUint16LE(fd, messageNum);
+ }
+
+ int getItemSize() const {
+ return 10;
+ }
+
};
-typedef std::vector<HitRect> HitRects;
+struct MessageItem {
+ uint16 messageNum;
+ 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 {
int16 x1, y1, x2, y2;
uint32 messageListCount;
uint32 messageListOffset;
-};
-typedef std::vector<SubRectItem> SubRectItems;
+ void load(uint32 offset) {
+ byte *item = getData(offset);
+ x1 = READ_LE_UINT16(item + 0);
+ y1 = READ_LE_UINT16(item + 2);
+ x2 = READ_LE_UINT16(item + 4);
+ y2 = READ_LE_UINT16(item + 6);
+ messageListCount = READ_LE_UINT32(item + 8);
+ messageListOffset = READ_LE_UINT32(item + 12);
+ // Add the message to the message list
+ addMessageList(messageListCount, messageListOffset);
+ }
+
+ void save(FILE *fd) {
+ writeUint16LE(fd, x1);
+ writeUint16LE(fd, y1);
+ writeUint16LE(fd, x2);
+ writeUint16LE(fd, y2);
+ writeUint32LE(fd, messageListOffset);
+ }
+
+ int getItemSize() const {
+ return 16;
+ }
+
+};
struct RectItem {
int16 x1, y1, x2, y2;
uint32 subRectListCount;
uint32 subRectListOffset;
- SubRectItems subRectItems;
-};
+ std::vector<SubRectItem> subRectItems;
-typedef std::vector<RectItem> RectItems;
-
-struct MessageItem {
- uint16 messageNum;
- uint32 messageParam;
- MessageItem(uint16 msgNum, uint32 msgParam) : messageNum(msgNum), messageParam(msgParam) {}
+ void load(uint32 offset) {
+ byte *item = getData(offset);
+ uint32 subItemOffset;
+ x1 = READ_LE_UINT16(item + 0);
+ y1 = READ_LE_UINT16(item + 2);
+ x2 = READ_LE_UINT16(item + 4);
+ y2 = READ_LE_UINT16(item + 6);
+ subRectListCount = READ_LE_UINT32(item + 8);
+ subRectListOffset = READ_LE_UINT32(item + 12);
+ subItemOffset = subRectListOffset;
+ for (uint32 j = 0; j < subRectListCount; j++) {
+ SubRectItem subRectItem;
+ subRectItem.load(subItemOffset);
+ subItemOffset += 16;
+ subRectItems.push_back(subRectItem);
+ }
+ }
+
+ void save(FILE *fd) {
+ writeUint16LE(fd, x1);
+ writeUint16LE(fd, y1);
+ writeUint16LE(fd, x2);
+ writeUint16LE(fd, y2);
+ writeUint32LE(fd, subRectItems.size());
+ for (uint32 j = 0; j < subRectItems.size(); j++)
+ subRectItems[j].save(fd);
+ }
+
+ int getItemSize() const {
+ return 16;
+ }
+
};
-typedef std::vector<MessageItem> MessageItems;
-
struct NavigationItem {
uint32 fileHash;
uint32 leftSmackerFileHash;
@@ -89,149 +189,172 @@ struct NavigationItem {
byte interactive;
byte middleFlag;
uint32 mouseCursorFileHash;
-};
+
+ void load(uint32 offset) {
+ byte *item = getData(offset);
+ fileHash = READ_LE_UINT32(item + 0);
+ leftSmackerFileHash = READ_LE_UINT32(item + 4);
+ rightSmackerFileHash = READ_LE_UINT32(item + 8);
+ middleSmackerFileHash = READ_LE_UINT32(item + 12);
+ interactive = item[16];
+ middleFlag = item[17];
+ mouseCursorFileHash = READ_LE_UINT32(item + 20);
+ }
-typedef std::vector<NavigationItem> NavigationItems;
+ void save(FILE *fd) {
+ writeUint32LE(fd, fileHash);
+ writeUint32LE(fd, leftSmackerFileHash);
+ writeUint32LE(fd, rightSmackerFileHash);
+ writeUint32LE(fd, middleSmackerFileHash);
+ writeByte(fd, interactive);
+ writeByte(fd, middleFlag);
+ writeUint32LE(fd, mouseCursorFileHash);
+ }
-struct HitRectList {
- uint32 id;
- HitRects hitRects;
+ int getItemSize() const {
+ return 24;
+ }
+
};
-struct RectList {
+template<class ITEMCLASS>
+class StaticDataList {
+public:
uint32 id;
- RectItems rectItems;
+ 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;
+ }
+
+ void loadList(uint32 count, uint32 offset) {
+ id = offset;
+ if (!specialLoadList(count, offset)) {
+ for (uint32 i = 0; i < count; i++) {
+ ITEMCLASS listItem;
+ listItem.load(offset);
+ offset += listItem.getItemSize();
+ add(listItem);
+ }
+ }
+ }
+
+ void saveList(FILE *fd) {
+ writeUint32LE(fd, id);
+ writeUint32LE(fd, getCount());
+ for (int i = 0; i < getCount(); i++) {
+ items[i].save(fd);
+ }
+ }
+
+};
+
+class HitRectList : public StaticDataList<HitRect> {
};
-struct MessageList {
- uint32 id;
- MessageItems messageItems;
+class RectList : public StaticDataList<RectItem> {
};
-struct NavigationList {
- uint32 id;
- NavigationItems navigationItems;
+class MessageList : public StaticDataList<MessageItem> {
+public:
+
+ virtual bool specialLoadList(uint32 count, uint32 offset) {
+ // Special code for message lists which are set at runtime (but otherwise constant)
+ switch (offset) {
+ // Scene 1002 rings
+ case 0x004B4200:
+ add(MessageItem(0x4800, 258));
+ add(MessageItem(0x100D, 0x4A845A00));
+ add(MessageItem(0x4805, 1));
+ return true;
+ case 0x004B4218:
+ add(MessageItem(0x4800, 297));
+ add(MessageItem(0x100D, 0x43807801));
+ add(MessageItem(0x4805, 2));
+ return true;
+ case 0x004B4230:
+ add(MessageItem(0x4800, 370));
+ add(MessageItem(0x100D, 0x46C26A01));
+ return true;
+ case 0x004B4240:
+ add(MessageItem(0x4800, 334));
+ add(MessageItem(0x100D, 0x468C7B11));
+ add(MessageItem(0x4805, 1));
+ return true;
+ case 0x004B4258:
+ add(MessageItem(0x4800, 425));
+ add(MessageItem(0x100D, 0x42845B19));
+ add(MessageItem(0x4805, 1));
+ return true;
+ }
+ return false;
+ }
+
};
-std::vector<HitRectList*> hitRectLists;
-std::vector<RectList*> rectLists;
-std::vector<MessageList*> messageLists;
-std::vector<NavigationList*> navigationLists;
+class NavigationList : public StaticDataList<NavigationItem> {
-byte *getData(uint32 offset) {
- return data + offset - dataStart + fileStart;
-}
+};
-void addHitRect(uint32 count, uint32 offset) {
- HitRectList *hitRectList = new HitRectList();
- hitRectList->id = offset;
- byte *item = getData(offset);
- for (uint32 i = 0; i < count; i++) {
- HitRect hitRect;
- hitRect.x1 = READ_LE_UINT16(item + 0);
- hitRect.y1 = READ_LE_UINT16(item + 2);
- hitRect.x2 = READ_LE_UINT16(item + 4);
- hitRect.y2 = READ_LE_UINT16(item + 6);
- hitRect.messageNum = READ_LE_UINT16(item + 8);
- item += 10;
- //printf("(%d, %d, %d, %d) -> %04X\n", hitRect.x1, hitRect.y1, hitRect.x2, hitRect.y2, hitRect.messageNum);
- hitRectList->hitRects.push_back(hitRect);
+template<class LISTCLASS>
+class StaticDataListVector {
+public:
+ std::vector<LISTCLASS*> lists;
+
+ void add(LISTCLASS *list) {
+ lists.push_back(list);
}
- hitRectLists.push_back(hitRectList);
-}
-
-void addMessage(uint32 count, uint32 offset) {
- MessageList *messageList = new MessageList();
- messageList->id = offset;
- // Special code for message lists which are set at runtime (but otherwise constant)
- switch (offset) {
- // Scene 1002 rings
- case 0x004B4200:
- messageList->messageItems.push_back(MessageItem(0x4800, 258));
- messageList->messageItems.push_back(MessageItem(0x100D, 0x4A845A00));
- messageList->messageItems.push_back(MessageItem(0x4805, 1));
- break;
- case 0x004B4218:
- messageList->messageItems.push_back(MessageItem(0x4800, 297));
- messageList->messageItems.push_back(MessageItem(0x100D, 0x43807801));
- messageList->messageItems.push_back(MessageItem(0x4805, 2));
- break;
- case 0x004B4230:
- messageList->messageItems.push_back(MessageItem(0x4800, 370));
- messageList->messageItems.push_back(MessageItem(0x100D, 0x46C26A01));
- break;
- case 0x004B4240:
- messageList->messageItems.push_back(MessageItem(0x4800, 334));
- messageList->messageItems.push_back(MessageItem(0x100D, 0x468C7B11));
- messageList->messageItems.push_back(MessageItem(0x4805, 1));
- break;
- case 0x004B4258:
- messageList->messageItems.push_back(MessageItem(0x4800, 425));
- messageList->messageItems.push_back(MessageItem(0x100D, 0x42845B19));
- messageList->messageItems.push_back(MessageItem(0x4805, 1));
- break;
- default:
- // Read message list from the exe
- byte *item = getData(offset);
- for (uint32 i = 0; i < count; i++) {
- messageList->messageItems.push_back(MessageItem(READ_LE_UINT16(item + 0), READ_LE_UINT32(item + 4)));
- item += 8;
+
+ void loadListVector(const uint32 *offsets) {
+ for (int i = 0; offsets[i] != 0; i += 2) {
+ LISTCLASS *list = new LISTCLASS();
+ list->loadList(offsets[i], offsets[i + 1]);
+ bool doAppend = true;
+ // Bad
+ for (typename std::vector<LISTCLASS*>::iterator it = lists.begin(); it != lists.end(); it++) {
+ if ((*it)->id == list->id) {
+ doAppend = false;
+ break;
+ }
+ }
+ if (doAppend)
+ lists.push_back(list);
}
}
- messageLists.push_back(messageList);
-}
-
-void addRect(uint32 count, uint32 offset) {
- RectList *rectList = new RectList();
- rectList->id = offset;
- byte *item = getData(offset);
- for (uint32 i = 0; i < count; i++) {
- RectItem rectItem;
- byte *subItem;
- rectItem.x1 = READ_LE_UINT16(item + 0);
- rectItem.y1 = READ_LE_UINT16(item + 2);
- rectItem.x2 = READ_LE_UINT16(item + 4);
- rectItem.y2 = READ_LE_UINT16(item + 6);
- rectItem.subRectListCount = READ_LE_UINT32(item + 8);
- rectItem.subRectListOffset = READ_LE_UINT32(item + 12);
- //printf("(%d, %d, %d, %d), %d, %08X\n", rectItem.x1, rectItem.y1, rectItem.x2, rectItem.y2, rectItem.subRectListCount, rectItem.subRectListOffset);
- subItem = getData(rectItem.subRectListOffset);
- for (uint32 j = 0; j < rectItem.subRectListCount; j++) {
- SubRectItem subRectItem;
- subRectItem.x1 = READ_LE_UINT16(subItem + 0);
- subRectItem.y1 = READ_LE_UINT16(subItem + 2);
- subRectItem.x2 = READ_LE_UINT16(subItem + 4);
- subRectItem.y2 = READ_LE_UINT16(subItem + 6);
- subRectItem.messageListCount = READ_LE_UINT32(subItem + 8);
- subRectItem.messageListOffset = READ_LE_UINT32(subItem + 12);
- subItem += 16;
- //printf("(%d, %d, %d, %d), %d, %08X\n", subRectItem.x1, subRectItem.y1, subRectItem.x2, subRectItem.y2, subRectItem.messageListCount, subRectItem.messageListOffset);
- addMessage(subRectItem.messageListCount, subRectItem.messageListOffset);
- rectItem.subRectItems.push_back(subRectItem);
+
+ void saveListVector(FILE *fd) {
+ writeUint32LE(fd, lists.size());
+ for (typename std::vector<LISTCLASS*>::iterator it = lists.begin(); it != lists.end(); it++) {
+ (*it)->saveList(fd);
}
- item += 16;
- rectList->rectItems.push_back(rectItem);
}
- rectLists.push_back(rectList);
-}
-void addNavigation(uint32 count, uint32 offset) {
- NavigationList *navigationList = new NavigationList();
- navigationList->id = offset;
- byte *item = getData(offset);
- for (uint32 i = 0; i < count; i++) {
- NavigationItem navigationItem;
- navigationItem.fileHash = READ_LE_UINT32(item + 0);
- navigationItem.leftSmackerFileHash = READ_LE_UINT32(item + 4);
- navigationItem.rightSmackerFileHash = READ_LE_UINT32(item + 8);
- navigationItem.middleSmackerFileHash = READ_LE_UINT32(item + 12);
- navigationItem.interactive = item[16];
- navigationItem.middleFlag = item[17];
- navigationItem.mouseCursorFileHash = READ_LE_UINT32(item + 20);
- item += 24;
- navigationList->navigationItems.push_back(navigationItem);
- }
- navigationLists.push_back(navigationList);
+};
+
+StaticDataListVector<HitRectList> hitRectLists;
+StaticDataListVector<RectList> rectLists;
+StaticDataListVector<MessageList> messageLists;
+StaticDataListVector<NavigationList> navigationLists;
+
+void addMessageList(uint32 messageListCount, uint32 messageListOffset) {
+ MessageList *messageList = new MessageList();
+ messageList->loadList(messageListCount, messageListOffset);
+ messageLists.add(messageList);
}
int main(int argc, char *argv[]) {
@@ -240,96 +363,24 @@ int main(int argc, char *argv[]) {
loadExe("nhc.exe");
- for (int i = 0; hitRectListOffsets[i] != 0; i += 2) {
- addHitRect(hitRectListOffsets[i], hitRectListOffsets[i + 1]);
- }
-
- for (int i = 0; rectListOffsets[i] != 0; i += 2) {
- addRect(rectListOffsets[i], rectListOffsets[i + 1]);
- }
-
- for (int i = 0; messageListOffsets[i] != 0; i += 2) {
- addMessage(messageListOffsets[i], messageListOffsets[i + 1]);
- }
-
- for (int i = 0; navigationListOffsets[i] != 0; i += 2) {
- addNavigation(navigationListOffsets[i], navigationListOffsets[i + 1]);
- }
-
+ hitRectLists.loadListVector(hitRectListOffsets);
+ rectLists.loadListVector(rectListOffsets);
+ messageLists.loadListVector(messageListOffsets);
+ navigationLists.loadListVector(navigationListOffsets);
+
datFile = fopen("neverhood.dat", "wb");
writeUint32LE(datFile, 0x11223344); // Some magic
writeUint32LE(datFile, DAT_VERSION);
// Write all message lists
- writeUint32LE(datFile, messageLists.size());
- for (std::vector<MessageList*>::iterator it = messageLists.begin(); it != messageLists.end(); it++) {
- MessageList *messageList = *it;
- writeUint32LE(datFile, messageList->id);
- writeUint32LE(datFile, messageList->messageItems.size());
- for (uint32 i = 0; i < messageList->messageItems.size(); i++) {
- writeUint16LE(datFile, messageList->messageItems[i].messageNum);
- writeUint32LE(datFile, messageList->messageItems[i].messageParam);
- }
- }
-
+ messageLists.saveListVector(datFile);
// Write all rect lists
- writeUint32LE(datFile, rectLists.size());
- for (std::vector<RectList*>::iterator it = rectLists.begin(); it != rectLists.end(); it++) {
- RectList *rectList = *it;
- writeUint32LE(datFile, rectList->id);
- writeUint32LE(datFile, rectList->rectItems.size());
- for (uint32 i = 0; i < rectList->rectItems.size(); i++) {
- const RectItem &rectItem = rectList->rectItems[i];
- writeUint16LE(datFile, rectItem.x1);
- writeUint16LE(datFile, rectItem.y1);
- writeUint16LE(datFile, rectItem.x2);
- writeUint16LE(datFile, rectItem.y2);
- writeUint32LE(datFile, rectItem.subRectItems.size());
- for (uint32 j = 0; j < rectItem.subRectItems.size(); j++) {
- const SubRectItem &subRectItem = rectItem.subRectItems[j];
- writeUint16LE(datFile, subRectItem.x1);
- writeUint16LE(datFile, subRectItem.y1);
- writeUint16LE(datFile, subRectItem.x2);
- writeUint16LE(datFile, subRectItem.y2);
- writeUint32LE(datFile, subRectItem.messageListOffset);
- }
- }
- }
-
+ rectLists.saveListVector(datFile);
// Write all hit rect lists
- writeUint32LE(datFile, hitRectLists.size());
- for (std::vector<HitRectList*>::iterator it = hitRectLists.begin(); it != hitRectLists.end(); it++) {
- HitRectList *hitRectList = *it;
- writeUint32LE(datFile, hitRectList->id);
- writeUint32LE(datFile, hitRectList->hitRects.size());
- for (uint32 i = 0; i < hitRectList->hitRects.size(); i++) {
- const HitRect &hitRect = hitRectList->hitRects[i];
- writeUint16LE(datFile, hitRect.x1);
- writeUint16LE(datFile, hitRect.y1);
- writeUint16LE(datFile, hitRect.x2);
- writeUint16LE(datFile, hitRect.y2);
- writeUint16LE(datFile, hitRect.messageNum);
- }
- }
-
+ hitRectLists.saveListVector(datFile);
// Write all navigation lists
- writeUint32LE(datFile, navigationLists.size());
- for (std::vector<NavigationList*>::iterator it = navigationLists.begin(); it != navigationLists.end(); it++) {
- NavigationList *navigationList = *it;
- writeUint32LE(datFile, navigationList->id);
- writeUint32LE(datFile, navigationList->navigationItems.size());
- for (uint32 i = 0; i < navigationList->navigationItems.size(); i++) {
- const NavigationItem &navigationItem = navigationList->navigationItems[i];
- writeUint32LE(datFile, navigationItem.fileHash);
- writeUint32LE(datFile, navigationItem.leftSmackerFileHash);
- writeUint32LE(datFile, navigationItem.rightSmackerFileHash);
- writeUint32LE(datFile, navigationItem.middleSmackerFileHash);
- writeByte(datFile, navigationItem.interactive);
- writeByte(datFile, navigationItem.middleFlag);
- writeUint32LE(datFile, navigationItem.mouseCursorFileHash);
- }
- }
+ navigationLists.saveListVector(datFile);
fclose(datFile);