aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/kyra/lol.cpp59
-rw-r--r--engines/kyra/lol.h9
-rw-r--r--engines/kyra/screen_lol.cpp2
-rw-r--r--engines/kyra/screen_lol.h2
-rw-r--r--engines/kyra/script_lol.cpp114
5 files changed, 167 insertions, 19 deletions
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 950dee57ae..3dd143fe4f 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -95,6 +95,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_currentControlMode = 0;
_specialSceneFlag = 0;
_lastCharInventory = -1;
+ _emcLastItem = -1;
_itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _effectShapes = _fireballShapes = _healShapes = _healiShapes = 0;
_levelShpList = _levelDatList = 0;
@@ -1589,6 +1590,44 @@ void LoLEngine::fadeText() {
_fadeText = false;
}
+void LoLEngine::transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage) {
+ uint16 *p1 = (uint16*) _tempBuffer5120;
+ uint16 *p2 = (uint16*) (_tempBuffer5120 + 640);
+
+ for (int i = 0; i < w; i++)
+ p1[i] = i;
+
+ for (int i = 0; i < h; i++)
+ p2[i] = i;
+
+ for (int i = 0; i < w; i++)
+ SWAP(p1[_rnd.getRandomNumberRng(0, w - 1)], p1[i]);
+
+ for (int i = 0; i < h; i++)
+ SWAP(p2[_rnd.getRandomNumberRng(0, h - 1)], p2[i]);
+
+ for (int i = 0; i < h; i++) {
+ int i2 = i;
+
+ for (int ii = 0; ii < w; ii++) {
+ int dx1 = x1 + p1[ii];
+ int dy1 = y1 + p2[i2];
+ int dx2 = x2 + p1[ii];
+ int dy2 = y2 + p2[i2];
+
+ if (++i2 == h)
+ i2 = 0;
+
+ _screen->setPagePixel(dstPage, dx2, dy2, _screen->getPagePixel(srcPage, dx1, dy1));
+ }
+
+ if (!dstPage && (i & 5) == 5) {
+ updateInput();
+ _screen->updateScreen();
+ }
+ }
+}
+
void LoLEngine::setPaletteBrightness(uint8 *palette, int brightness, int modifier) {
generateBrightnessPalette(palette, _screen->getPalette(1), brightness, modifier);
_screen->fadePalette(_screen->getPalette(1), 5, 0);
@@ -3468,31 +3507,31 @@ void LoLEngine::drawMapPage(int pageNum) {
uint8 w31 = _levelBlockProperties[b3].walls[1];
// draw block
- _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 6, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 6, 0, _mapOverlay);
// draw north wall
drawMapBlockWall(b3, w31, sx, sy, 3);
drawMapShape(w31, sx, sy, 3);
if (_wllBuffer4[w31] & 0xc0)
- _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 1, 6, 0, _mapOverlay);
// draw west wall
drawMapBlockWall(b1, w13, sx, sy, 1);
drawMapShape(w13, sx, sy, 1);
if (_wllBuffer4[w13] & 0xc0)
- _screen->copyBlockSpecial(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx + 6, sy, _screen->_curPage, sx + 6, sy, 1, 6, 0, _mapOverlay);
// draw east wall
drawMapBlockWall(b0, w02, sx, sy, 0);
drawMapShape(w02, sx, sy, 0);
if (_wllBuffer4[w02] & 0xc0)
- _screen->copyBlockSpecial(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy, _screen->_curPage, sx, sy, 7, 1, 0, _mapOverlay);
//draw south wall
drawMapBlockWall(b2, w20, sx, sy, 2);
drawMapShape(w20, sx, sy, 2);
if (_wllBuffer4[w20] & 0xc0)
- _screen->copyBlockSpecial(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, sx, sy + 5, _screen->_curPage, sx, sy + 5, 7, 1, 0, _mapOverlay);
}
sx += 7;
@@ -3545,7 +3584,7 @@ void LoLEngine::drawMapPage(int pageNum) {
for (int ii = 0; ii < 11; ii++) {
if (!_defaultLegendData[ii].enable)
continue;
- _screen->copyBlockSpecial(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(_screen->_curPage, 235, (tY << 3) + 21, _screen->_curPage, 235, (tY << 3) + 21, 7, 6, 0, _mapOverlay);
_screen->drawShape(_screen->_curPage, _automapShapes[_defaultLegendData[ii].shapeIndex << 2], 232, (tY << 3) + 18 + _defaultLegendData[ii].x, 0, 0);
printMapText(_defaultLegendData[ii].stringId, 244, (tY << 3) + 22);
tY++;
@@ -3641,7 +3680,7 @@ void LoLEngine::redrawMapCursor() {
int cx = _automapTopLeftX + (((_currentBlock - sx) % 32) * 7);
int cy = _automapTopLeftY + (((_currentBlock - (sy << 5)) / 32) * 6);
_screen->copyRegion(cx, cy, cx, cy, 16, 16, 2, 0);
- _screen->copyBlockSpecial(2, 0, 0, 0, cx - 3, cy - 2, 16, 16, 0, _mapCursorOverlay);
+ _screen->copyBlockAndApplyOverlay(2, 0, 0, 0, cx - 3, cy - 2, 16, 16, 0, _mapCursorOverlay);
_mapCursorOverlay[24] = _mapCursorOverlay[1];
for (int i = 1; i < 24; i++)
@@ -3655,9 +3694,9 @@ void LoLEngine::drawMapBlockWall(uint16 block, uint8 wall, int x, int y, int dir
return;
int cp = _screen->_curPage;
- _screen->copyBlockSpecial(cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], _mapCoords[2][direction], _mapCoords[3][direction], 0, _mapOverlay);
- _screen->copyBlockSpecial(cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay);
- _screen->copyBlockSpecial(cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], cp, x + _mapCoords[0][direction], y + _mapCoords[1][direction], _mapCoords[2][direction], _mapCoords[3][direction], 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], cp, x + _mapCoords[4][direction], y + _mapCoords[5][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay);
+ _screen->copyBlockAndApplyOverlay(cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], cp, x + _mapCoords[6][direction], y + _mapCoords[7][direction], _mapCoords[8][direction], _mapCoords[9][direction], 0, _mapOverlay);
}
void LoLEngine::drawMapShape(uint8 wall, int x, int y, int direction) {
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index c4d849ca6e..4a6ab6b0ab 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -585,6 +585,7 @@ private:
int olol_allocItemPropertiesBuffer(EMCState *script);
int olol_setItemProperty(EMCState *script);
int olol_makeItem(EMCState *script);
+ int olol_placeMoveLevelItem(EMCState *script);
int olol_createLevelItem(EMCState *script);
int olol_getItemPara(EMCState *script);
int olol_getCharacterStat(EMCState *script);
@@ -671,6 +672,7 @@ private:
int olol_calcInflictableDamagePerItem(EMCState *script);
int olol_distanceAttack(EMCState *script);
int olol_removeCharacterEffects(EMCState *script);
+ int olol_checkInventoryFull(EMCState *script);
int olol_objectLeavesLevel(EMCState *script);
int olol_addSpellToScroll(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
@@ -680,8 +682,11 @@ private:
int olol_suspendMonster(EMCState *script);
int olol_triggerEventOnMouseButtonRelease(EMCState *script);
int olol_printWindowText(EMCState *script);
+ int olol_checkPartyForItemType(EMCState *script);
int olol_setUnkDoorVar(EMCState *script);
int olol_resetTimDialogueState(EMCState *script);
+ int olol_getItemOnPos(EMCState *script);
+ int olol_removeLevelItem(EMCState *script);
int olol_savePage5(EMCState *script);
int olol_restorePage5(EMCState *script);
int olol_initDialogueSequence(EMCState *script);
@@ -690,6 +695,8 @@ private:
int olol_prepareSpecialScene(EMCState *script);
int olol_restoreAfterSpecialScene(EMCState *script);
int olol_assignCustomSfx(EMCState *script);
+ int olol_transformRegion(EMCState *script);
+ int olol_calcCoordinatesAddDirectionOffset(EMCState *script);
int olol_resetPortraitsAndDisableSysTimer(EMCState *script);
int olol_enableSysTimer(EMCState *script);
int olol_checkNeedSceneRestore(EMCState *script);
@@ -759,6 +766,7 @@ private:
void resetPortraitsAndDisableSysTimer();
void toggleSelectedCharacterFrame(bool mode);
void fadeText();
+ void transformRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
void setPaletteBrightness(uint8 *palette, int brightness, int modifier);
void generateBrightnessPalette(uint8 *src, uint8 *dst, int brightness, int modifier);
void generateFlashPalette(uint8 *src, uint8 *dst, int colorFlags);
@@ -1104,6 +1112,7 @@ private:
int _specialSceneFlag;
int _lastCharInventory;
uint16 _charStatusFlags[3];
+ int _emcLastItem;
FlyingObject *_flyingObjects;
diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp
index 47d526f915..f8dfca5615 100644
--- a/engines/kyra/screen_lol.cpp
+++ b/engines/kyra/screen_lol.cpp
@@ -618,7 +618,7 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in
addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
}
-void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) {
+void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) {
if (!w || !h || !ovl)
return;
diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h
index 2f230d79a6..6de38ff78d 100644
--- a/engines/kyra/screen_lol.h
+++ b/engines/kyra/screen_lol.h
@@ -76,7 +76,7 @@ public:
uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
- void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
+ void copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
void applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl);
uint8 getShapePaletteSize(const uint8 *shp);
diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp
index 41dc2b8ef0..f1d5b6b3ab 100644
--- a/engines/kyra/script_lol.cpp
+++ b/engines/kyra/script_lol.cpp
@@ -275,6 +275,12 @@ int LoLEngine::olol_makeItem(EMCState *script) {
return makeItem(stackPos(0), stackPos(1), stackPos(2));
}
+int LoLEngine::olol_placeMoveLevelItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setItemProperty(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ placeMoveLevelItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3) & 0xff, stackPos(4) & 0xff, stackPos(5));
+ return 1;
+}
+
int LoLEngine::olol_createLevelItem(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setItemProperty(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
int item = makeItem(stackPos(0), stackPos(1), stackPos(2));
@@ -1443,6 +1449,15 @@ int LoLEngine::olol_removeCharacterEffects(EMCState *script) {
return 1;
}
+int LoLEngine::olol_checkInventoryFull(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkInventoryFull(%p)", (const void *)script);
+ for (int i = 0; i < 48; i++) {
+ if (_inventory[i])
+ return 0;
+ }
+ return 1;
+}
+
int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_objectLeavesLevel(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int o = _levelBlockProperties[stackPos(0)].assignedObjects;
@@ -1570,6 +1585,32 @@ int LoLEngine::olol_printWindowText(EMCState *script) {
return 1;
}
+int LoLEngine::olol_checkPartyForItemType(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkPartyForItemType(%p) (%d, %d, %d))", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ int p = stackPos(1);
+
+ if (!stackPos(2)) {
+ for (int i = 0; i < 48; i++) {
+ if (!_inventory[i] || _itemsInPlay[_inventory[i]].itemPropertyIndex != p)
+ continue;
+ return 1;
+ }
+
+ if (_itemsInPlay[_itemInHand].itemPropertyIndex == p)
+ return 1;
+ }
+
+ int last = (stackPos(0) == -1) ? 3 : stackPos(0);
+ int first = (stackPos(0) == -1) ? 0 : stackPos(0);
+
+ for (int i = first; i <= last; i++) {
+ if (itemEquipped(i, p))
+ return 1;
+ }
+
+ return 0;
+}
+
int LoLEngine::olol_setUnkDoorVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setUnkDoorVar(%p) (%d)", (const void *)script, stackPos(0));
_emcDoorState = stackPos(0);
@@ -1582,6 +1623,51 @@ int LoLEngine::olol_resetTimDialogueState(EMCState *script) {
return 1;
}
+int LoLEngine::olol_getItemOnPos(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getItemOnPos(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ int pX = stackPos(1);
+ if (pX != -1)
+ pX &= 0xff;
+
+ int pY = stackPos(2);
+ if (pY != -1)
+ pY &= 0xff;
+
+ int o = (stackPos(3) || _emcLastItem == -1) ? stackPos(0) : _emcLastItem;
+
+ _emcLastItem = _levelBlockProperties[o].assignedObjects;
+
+ while (_emcLastItem) {
+ if (_emcLastItem & 0x8000) {
+ o = _emcLastItem & 0x7fff;
+ _emcLastItem = _levelBlockProperties[o].assignedObjects;
+ continue;
+ }
+
+ if (pX != -1 && (_itemsInPlay[_emcLastItem].x & 0xff) != pX) {
+ o = _emcLastItem & 0x7fff;
+ _emcLastItem = _levelBlockProperties[o].assignedObjects;
+ continue;
+ }
+
+ if (pY != -1 && (_itemsInPlay[_emcLastItem].y & 0xff) != pY) {
+ o = _emcLastItem & 0x7fff;
+ _emcLastItem = _levelBlockProperties[o].assignedObjects;
+ continue;
+ }
+
+ return _emcLastItem;
+ }
+
+ return 0;
+}
+
+int LoLEngine::olol_removeLevelItem(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_removeLevelItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ removeLevelItem(stackPos(0), stackPos(1));
+ return 1;
+}
+
int LoLEngine::olol_savePage5(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_savePage5(%p)", (const void *)script);
savePage5();
@@ -1640,6 +1726,20 @@ int LoLEngine::olol_assignCustomSfx(EMCState *script) {
return 0;
}
+int LoLEngine::olol_transformRegion(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_transformRegion(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
+ transformRegion(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
+ return 1;
+}
+
+int LoLEngine::olol_calcCoordinatesAddDirectionOffset(EMCState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcCoordinatesAddDirectionOffset(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ uint16 x = stackPos(0);
+ uint16 y = stackPos(1);
+ calcCoordinatesAddDirectionOffset(x, y, stackPos(2));
+ return stackPos(3) ? x : y;
+}
+
int LoLEngine::olol_resetPortraitsAndDisableSysTimer(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetPortraitsAndDisableSysTimer(%p)", (const void *)script);
resetPortraitsAndDisableSysTimer();
@@ -2041,7 +2141,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_makeItem);
// 0x10
- OpcodeUnImpl();
+ Opcode(olol_placeMoveLevelItem);
Opcode(olol_createLevelItem);
Opcode(olol_getItemPara);
Opcode(olol_getCharacterStat);
@@ -2191,7 +2291,7 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_removeCharacterEffects);
// 0x74
- OpcodeUnImpl();
+ Opcode(olol_checkInventoryFull);
Opcode(olol_objectLeavesLevel);
OpcodeUnImpl();
OpcodeUnImpl();
@@ -2216,13 +2316,13 @@ void LoLEngine::setupOpcodeTable() {
// 0x84
OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_checkPartyForItemType);
Opcode(olol_setUnkDoorVar);
Opcode(olol_resetTimDialogueState);
// 0x88
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_getItemOnPos);
+ Opcode(olol_removeLevelItem);
Opcode(olol_savePage5);
Opcode(olol_restorePage5);
@@ -2245,8 +2345,8 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
// 0x98
- OpcodeUnImpl();
- OpcodeUnImpl();
+ Opcode(olol_transformRegion);
+ Opcode(olol_calcCoordinatesAddDirectionOffset);
Opcode(olol_resetPortraitsAndDisableSysTimer);
Opcode(olol_enableSysTimer);