aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/kyra3.cpp225
-rw-r--r--engines/kyra/kyra3.h16
-rw-r--r--engines/kyra/screen.cpp10
-rw-r--r--engines/kyra/screen.h7
4 files changed, 252 insertions, 6 deletions
diff --git a/engines/kyra/kyra3.cpp b/engines/kyra/kyra3.cpp
index bd94d62eb4..9557d3ef65 100644
--- a/engines/kyra/kyra3.cpp
+++ b/engines/kyra/kyra3.cpp
@@ -47,6 +47,7 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system) : KyraEngine(system) {
_unkBuffer17 = 0;
_itemBuffer1 = _itemBuffer2 = 0;
_mouseSHPBuf = 0;
+ _tableBuffer1 = _tableBuffer2 = 0;
}
KyraEngine_v3::~KyraEngine_v3() {
@@ -116,8 +117,9 @@ int KyraEngine_v3::init() {
_shapePoolBuffer = new uint8[300000];
assert(_shapePoolBuffer);
+ memset(_shapePoolBuffer, 0, 300000);
- // XXX game_setUnkBuffer(_shapePoolBuffer)
+ initTableBuffer(_shapePoolBuffer, 300000);
_unkBuffer17 = new uint8[1850];
assert(_unkBuffer17);
@@ -532,6 +534,219 @@ void KyraEngine_v3::realInit() {
debugC(9, kDebugLevelMain, "KyraEngine::realInit()");
}
+#pragma mark -
+
+int KyraEngine_v3::initTableBuffer(uint8 *buf, int size) {
+ debugC(9, kDebugLevelMain, "KyraEngine::initTableBuffer(%p, %d)", (void*)buf, size);
+
+ if (!buf || size < 6320)
+ return 0;
+
+ if (_tableBuffer2 != _tableBuffer1 && _tableBuffer2 && _tableBuffer1) {
+ // no idea if this *should* be called
+ memmove(_tableBuffer2, _tableBuffer1, 6320);
+ }
+
+ _tableBuffer1 = buf;
+ size -= 6320;
+
+ *((uint16*)(_tableBuffer1)) = 0;
+ *((uint16*)(_tableBuffer1 + 2)) = 1;
+ *((uint16*)(_tableBuffer1 + 4)) = 1;
+ *((uint32*)(_tableBuffer1 + 6)) = size >> 4;
+ *((uint16*)(_tableBuffer1 + 10)) = 1;
+ *((uint32*)(_tableBuffer1 + 16)) = 6320;
+ *((uint32*)(_tableBuffer1 + 22)) = size >> 4;
+
+ _tableBuffer2 = buf;
+
+ return 1;
+}
+
+void KyraEngine_v3::updateTableBuffer(uint8 *buf) {
+ debugC(9, kDebugLevelMain, "KyraEngine::updateTableBuffer(%p)", (void*)buf);
+
+ if (_tableBuffer2 == buf)
+ return;
+
+ if (_tableBuffer1 != _tableBuffer2)
+ memmove(_tableBuffer2, _tableBuffer1, 6320);
+
+ _tableBuffer2 = _tableBuffer1 = buf;
+}
+
+int KyraEngine_v3::addShapeToTable(uint8 *buf, int id, int shapeNum) {
+ debugC(9, kDebugLevelMain, "KyraEngine::addShapeToTable(%p, %d, %d)", (void*)buf, id, shapeNum);
+
+ if (!buf)
+ return 0;
+
+ uint8 *shapePtr = _screen->getPtrToShape(buf, shapeNum);
+ if (!shapePtr)
+ return 0;
+
+ int shapeSize = _screen->getShapeSize(shapePtr);
+
+ if (getTableSize(_shapePoolBuffer) < shapeSize) {
+ // XXX
+ error("[1] unimplemented table handling");
+ }
+
+ uint8 *ptr = allocTableSpace(_shapePoolBuffer, shapeSize, id);
+
+ if (!ptr) {
+ // XXX
+ error("[2] unimplemented table handling");
+ }
+
+ if (!ptr) {
+ warning("adding shape %d to _shapePoolBuffer not possible, not enough space left\n", id);
+ return shapeSize;
+ }
+
+ memcpy(ptr, shapePtr, shapeSize);
+ return shapeSize;
+}
+
+int KyraEngine_v3::getTableSize(uint8 *buf) {
+ debugC(9, kDebugLevelMain, "KyraEngine::getTableSize(%p)", (void*)buf);
+ updateTableBuffer(buf);
+
+ if (*((uint16*)(_tableBuffer1 + 4)) >= 450)
+ return 0;
+
+ return (*((uint32*)(_tableBuffer1 + 6)) << 4);
+}
+
+uint8 *KyraEngine_v3::allocTableSpace(uint8 *buf, int size, int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::allocTableSpace(%p, %d, %d)", (void*)buf, size, id);
+
+ if (!buf || !size)
+ return 0;
+
+ updateTableBuffer(buf);
+
+ int entries = *(uint16*)(_tableBuffer1 + 4);
+
+ if (entries >= 450)
+ return 0;
+
+ size += 0xF;
+ size &= 0xFFFFFFF0;
+
+ uint size2 = size >> 4;
+
+ if (*(uint32*)(_tableBuffer1 + 6) < size2)
+ return 0;
+
+ int unk1 = *(uint16*)(_tableBuffer1);
+ int usedEntry = unk1;
+ int ok = 0;
+
+ for (; usedEntry < entries; ++usedEntry) {
+ if (size2 <= *(uint32*)(_tableBuffer1 + usedEntry * 14 + 22)) {
+ ok = 1;
+ break;
+ }
+ }
+
+ if (!ok)
+ return 0;
+
+ ok = 0;
+ int unk3 = unk1 - 1;
+ while (ok <= unk3) {
+ int temp = (ok + unk3) >> 1;
+
+ if (*(uint32*)(_tableBuffer1 + temp * 14 + 12) >= (uint)id) {
+ if (*(uint32*)(_tableBuffer1 + temp * 14 + 12) <= (uint)id) {
+ return 0;
+ } else {
+ unk3 = temp - 1;
+ continue;
+ }
+ }
+
+ ok = temp + 1;
+ }
+
+ uint8 *buf2 = _tableBuffer1 + usedEntry * 14;
+
+ uint unkValue1 = *(uint32*)(buf2 + 16);
+ uint unkValue2 = *(uint32*)(buf2 + 22);
+
+ if (size2 < unkValue2) {
+ *(uint32*)(buf2 + 22) = unkValue2 - size2;
+ *(uint32*)(buf2 + 16) = unkValue1 + size;
+ memcpy(_tableBuffer1 + entries * 14 + 12, _tableBuffer1 + unk1 * 14 + 12, 14);
+ } else {
+ if (usedEntry > unk1) {
+ memcpy(buf2 + 12, _tableBuffer1 + unk1 * 14 + 12, 14);
+ }
+ int temp = *(uint16*)(_tableBuffer1 + 2) - 1;
+ *(uint16*)(_tableBuffer1 + 2) = temp;
+ temp = *(uint16*)(_tableBuffer1 + 4) - 1;
+ *(uint16*)(_tableBuffer1 + 4) = temp;
+ }
+
+ for (int i = unk1; i > ok; --i) {
+ memcpy(_tableBuffer1 + i * 14 + 12, _tableBuffer1 + (i-1) * 14 + 12, 14);
+ }
+
+ buf2 = _tableBuffer1 + ok * 14;
+
+ *(uint32*)(buf2 + 12) = id;
+ *(uint32*)(buf2 + 16) = unkValue1;
+ *(uint32*)(buf2 + 20) = (_system->getMillis() / 60) >> 4;
+ *(uint32*)(buf2 + 22) = size2;
+
+ int temp = *(uint16*)(_tableBuffer1) + 1;
+ *(uint16*)(_tableBuffer1) = temp;
+ temp = *(uint16*)(_tableBuffer1 + 4) + 1;
+ *(uint16*)(_tableBuffer1 + 4) = temp;
+
+ if (temp > *(uint16*)(_tableBuffer1 + 10)) {
+ *(uint16*)(_tableBuffer1 + 10) = temp;
+ if (temp > _unkTableValue)
+ _unkTableValue = temp;
+ }
+
+ temp = *(uint32*)(_tableBuffer1 + 6) - size2;
+ *(uint32*)(_tableBuffer1 + 6) = temp;
+
+ return _tableBuffer2 + unkValue1;
+}
+
+namespace {
+int tableIdCompare(const void *l, const void *r) {
+ int lV = *(uint32*)(l);
+ int rV = *(uint32*)(r);
+
+ return CLIP(lV - rV, -1, 1);
+}
+}
+
+uint8 *KyraEngine_v3::findIdInTable(uint8 *buf, int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::findIdInTable(%p, %d)", (void*)buf, id);
+
+ updateTableBuffer(buf);
+
+ uint32 idVal = id;
+ uint8 *ptr = (uint8*)bsearch(&idVal, _tableBuffer1 + 12, *(uint16*)(_tableBuffer1), 14, &tableIdCompare);
+
+ if (!ptr) {
+ return 0;
+ }
+
+ return _tableBuffer2 + *(uint32*)(ptr + 4);
+}
+
+uint8 *KyraEngine_v3::findShapeInTable(int id) {
+ debugC(9, kDebugLevelMain, "KyraEngine::findShapeInTable(%d)", id);
+
+ return findIdInTable(_shapePoolBuffer, id);
+}
+
#pragma mark - items
void KyraEngine_v3::initItems() {
@@ -539,10 +754,16 @@ void KyraEngine_v3::initItems() {
_screen->loadBitmap("ITEMS.CSH", 3, 3, 0);
- // XXX
+ for (int i = 248; i <= 319; ++i) {
+ addShapeToTable(_screen->getPagePtr(3), i, i-248);
+ }
_screen->loadBitmap("ITEMS2.CSH", 3, 3, 0);
+ for (int i = 320; i <= 397; ++i) {
+ addShapeToTable(_screen->getPagePtr(3), i, i-320);
+ }
+
uint32 size = 0;
uint8 *itemsDat = _res->fileData("_ITEMS.DAT", &size);
diff --git a/engines/kyra/kyra3.h b/engines/kyra/kyra3.h
index 9cf16ef34e..750c59c0fc 100644
--- a/engines/kyra/kyra3.h
+++ b/engines/kyra/kyra3.h
@@ -102,6 +102,22 @@ private:
uint8 *_itemBuffer2;
void initItems();
+
+ // used for CSH loading and some sound stuff (maybe voice files?)
+private:
+ uint8 *_tableBuffer1;
+ uint8 *_tableBuffer2;
+ int _unkTableValue;
+
+ // do not think of thouching the code belonging to these functions
+ int initTableBuffer(uint8 *buf, int size);
+ void updateTableBuffer(uint8 *buf);
+ int getTableSize(uint8 *buf);
+ uint8 *allocTableSpace(uint8 *buf, int size, int id);
+ uint8 *findIdInTable(uint8 *buf, int id);
+
+ int addShapeToTable(uint8 *buf, int id, int shapeNum);
+ uint8 *findShapeInTable(int id);
};
} // end of namespace Kyra
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index f45b9cea1a..0e62402181 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -2210,7 +2210,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *
if (palData && palSize) {
debugC(9, kDebugLevelMain,"Loading a palette of size %i from %s", palSize, filename);
- memcpy(palData, srcData + 10, palSize);
+ memcpy(palData, srcData + 10, palSize);
}
uint8 *srcPtr = srcData + 10 + palSize;
@@ -2243,9 +2243,15 @@ uint8 *Screen::getPtrToShape(uint8 *shpFile, int shape) {
if (shapes <= shape)
return 0;
- uint32 offset = READ_LE_UINT32(shpFile + (shape << 1) + 2);
+ uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2);
return shpFile + offset + 2;
}
+uint16 Screen::getShapeSize(uint8 *shp) {
+ debugC(9, kDebugLevelScreen, "KyraEngine::getShapeSize(%p)", (void *)shp);
+
+ return READ_LE_UINT16(shp+6);
+}
+
} // End of namespace Kyra
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 73875c9da4..541ced494a 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -190,9 +190,12 @@ public:
static const int _screenDimTableCountK3;
uint8 *getPtrToShape(uint8 *shpFile, int shape);
-private:
- uint8 *getPagePtr(int pageNum);
+ uint16 getShapeSize(uint8 *shp);
+
+ // only needed for Kyra3!
+ uint8 *getPagePtr(int pageNum);
+private:
int16 encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size);
void restoreMouseRect();
void copyMouseToScreen();