aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/dm/dm.cpp14
-rw-r--r--engines/dm/dm.h2
-rw-r--r--engines/dm/dungeonman.cpp302
-rw-r--r--engines/dm/dungeonman.h372
-rw-r--r--engines/dm/gfx.cpp604
-rw-r--r--engines/dm/gfx.h87
6 files changed, 1222 insertions, 159 deletions
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp
index 60b2b2a3cb..ee818495e4 100644
--- a/engines/dm/dm.cpp
+++ b/engines/dm/dm.cpp
@@ -53,15 +53,18 @@ Common::Error DMEngine::run() {
_console = new Console(this);
_displayMan = new DisplayMan(this);
_dungeonMan = new DungeonMan(this);
+
+ _dungeonMan->loadDungeonFile();
+
_displayMan->setUpScreens(320, 200);
_displayMan->loadGraphics();
- _dungeonMan->loadDungeonFile();
- _displayMan->loadFloorSet(kFloorSetStone);
- _displayMan->loadWallSet(kWallSetStone);
- _displayMan->loadPalette(kPalCredits);
- _dungeonMan->setCurrentMap(0);
+ _displayMan->loadCurrentMapGraphics();
+
+ _displayMan->loadPalette(gPalCredits);
+
+ _dungeonMan->setCurrentMapAndPartyMap(0);
uint16 i = 0; //TODO: testing, please delete me
while (true) {
@@ -69,6 +72,7 @@ Common::Error DMEngine::run() {
_displayMan->drawDungeon(kDirNorth, i++, 0);
_displayMan->updateScreen();
_system->delayMillis(1000); //TODO: testing, please set me to 10
+ if (i == 3) break;
}
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index d5d748754f..7c8afd132a 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -33,8 +33,8 @@ public:
private:
Console *_console;
- Common::RandomSource *_rnd;
public:
+ Common::RandomSource *_rnd;
DisplayMan *_displayMan;
DungeonMan *_dungeonMan;
};
diff --git a/engines/dm/dungeonman.cpp b/engines/dm/dungeonman.cpp
index b94382e9b7..46d4f62704 100644
--- a/engines/dm/dungeonman.cpp
+++ b/engines/dm/dungeonman.cpp
@@ -1,4 +1,5 @@
#include "dungeonman.h"
+#include "gfx.h"
#include "common/file.h"
#include "common/memstream.h"
@@ -11,10 +12,46 @@ int8 dirIntoStepCountNorth[4] = {-1 /* North */, 0 /* East */, 1 /* West */, 0 /
void turnDirRight(direction &dir) { dir = (direction)((dir + 1) & 3); }
+
}
using namespace DM;
+CreatureInfo gCreatureInfo[kCreatureTypeCount] = { // @ G0243_as_Graphic559_CreatureInfo
+ /* { CreatureAspectIndex, AttackSoundOrdinal, Attributes, GraphicInfo,
+ MovementTicks, AttackTicks, Defense, BaseHealth, Attack, PoisonAttack,
+ Dexterity, Ranges, Properties, Resistances, AnimationTicks, WoundProbabilities, AttackType } */
+ {0, 4, 0x0482, 0x623D, 8, 20, 55, 150, 150, 240, 55, 0x1153, 0x299B, 0x0876, 0x0254, 0xFD40, 4},
+ {1, 0, 0x0480, 0xA625, 15, 32, 20, 110, 80, 15, 20, 0x3132, 0x33A9, 0x0E42, 0x0384, 0xFC41, 3},
+ {2, 6, 0x0510, 0x6198, 3, 5, 50, 10, 10, 0, 110, 0x1376, 0x710A, 0x0235, 0x0222, 0xFD20, 0},
+ {3, 0, 0x04B4, 0xB225, 10, 21, 30, 40, 58, 0, 80, 0x320A, 0x96AA, 0x0B3C, 0x0113, 0xF910, 5},
+ {4, 1, 0x0701, 0xA3B8, 9, 8, 45, 101, 90, 0, 65, 0x1554, 0x58FF, 0x0A34, 0x0143, 0xFE93, 4},
+ {5, 0, 0x0581, 0x539D, 20, 18, 100, 60, 30, 0, 30, 0x1232, 0x4338, 0x0583, 0x0265, 0xFFD6, 3},
+ {6, 3, 0x070C, 0x0020, 120, 10, 5, 165, 5, 0, 5, 0x1111, 0x10F1, 0x0764, 0x02F2, 0xFC84, 6},
+ {7, 7, 0x0300, 0x0220, 185, 15, 170, 50, 40, 5, 10, 0x1463, 0x25C4, 0x06E3, 0x01F4, 0xFD93, 4}, /* Atari ST: AttackSoundOrdinal = 0 */
+ {8, 2, 0x1864, 0x5225, 11, 16, 15, 30, 55, 0, 80, 0x1423, 0x4664, 0x0FC8, 0x0116, 0xFB30, 6},
+ {9, 10, 0x0282, 0x71B8, 21, 14, 240, 120, 219, 0, 35, 0x1023, 0x3BFF, 0x0FF7, 0x04F3, 0xF920, 3}, /* Atari ST: AttackSoundOrdinal = 7 */
+ {10, 2, 0x1480, 0x11B8, 17, 12, 25, 33, 20, 0, 40, 0x1224, 0x5497, 0x0F15, 0x0483, 0xFB20, 3},
+ {11, 0, 0x18C6, 0x0225, 255, 8, 45, 80, 105, 0, 60, 0x1314, 0x55A5, 0x0FF9, 0x0114, 0xFD95, 1},
+ {12, 11, 0x1280, 0x6038, 7, 7, 22, 20, 22, 0, 80, 0x1013, 0x6596, 0x0F63, 0x0132, 0xFA30, 4}, /* Atari ST: AttackSoundOrdinal = 8 */
+ {13, 9, 0x14A2, 0xB23D, 5, 10, 42, 39, 90, 100, 88, 0x1343, 0x5734, 0x0638, 0x0112, 0xFA30, 4}, /* Atari ST: AttackSoundOrdinal = 0 */
+ {14, 0, 0x05B8, 0x1638, 10, 20, 47, 44, 75, 0, 90, 0x4335, 0xD952, 0x035B, 0x0664, 0xFD60, 5},
+ {15, 5, 0x0381, 0x523D, 18, 19, 72, 70, 45, 35, 35, 0x1AA1, 0x15AB, 0x0B93, 0x0253, 0xFFC5, 4},
+ {16, 10, 0x0680, 0xA038, 13, 8, 28, 20, 25, 0, 41, 0x1343, 0x2148, 0x0321, 0x0332, 0xFC30, 3}, /* Atari ST: AttackSoundOrdinal = 7 */
+ {17, 0, 0x04A0, 0xF23D, 1, 16, 180, 8, 28, 20, 150, 0x1432, 0x19FD, 0x0004, 0x0112, 0xF710, 4},
+ {18, 11, 0x0280, 0xA3BD, 14, 6, 140, 60, 105, 0, 70, 0x1005, 0x7AFF, 0x0FFA, 0x0143, 0xFA30, 4}, /* Atari ST: AttackSoundOrdinal = 8 */
+ {19, 0, 0x0060, 0xE23D, 5, 18, 15, 33, 61, 0, 65, 0x3258, 0xAC77, 0x0F56, 0x0117, 0xFC40, 5},
+ {20, 8, 0x10DE, 0x0225, 25, 25, 75, 144, 66, 0, 50, 0x1381, 0x7679, 0x0EA7, 0x0345, 0xFD93, 3}, /* Atari ST: AttackSoundOrdinal = 0 */
+ {21, 3, 0x0082, 0xA3BD, 7, 15, 33, 77, 130, 0, 60, 0x1592, 0x696A, 0x0859, 0x0224, 0xFC30, 4},
+ {22, 0, 0x1480, 0x53BD, 10, 14, 68, 100, 100, 0, 75, 0x4344, 0xBDF9, 0x0A5D, 0x0124, 0xF920, 3},
+ {23, 0, 0x38AA, 0x0038, 12, 22, 255, 180, 210, 0, 130, 0x6369, 0xFF37, 0x0FBF, 0x0564, 0xFB52, 5},
+ {24, 1, 0x068A, 0x97BD, 13, 28, 110, 255, 255, 0, 70, 0x3645, 0xBF7C, 0x06CD, 0x0445, 0xFC30, 4}, /* Atari ST Version 1.0 1987-12-08 1987-12-11: Ranges = 0x2645 */
+ {25, 0, 0x38AA, 0x0000, 12, 22, 255, 180, 210, 0, 130, 0x6369, 0xFF37, 0x0FBF, 0x0564, 0xFB52, 5},
+ {26, 0, 0x38AA, 0x0000, 12, 22, 255, 180, 210, 0, 130, 0x6369, 0xFF37, 0x0FBF, 0x0564, 0xFB52, 5}};
+
+int16 DM::ordinalToIndex(int16 val) { return val - 1; }
+int16 DM::indexToOrdinal(int16 val) { return val + 1; }
+
void DungeonMan::mapCoordsAfterRelMovement(direction dir, int16 stepsForward, int16 stepsRight, int16 &posX, int16 &posY) {
posX += dirIntoStepCountEast[dir] * stepsForward;
@@ -34,6 +71,11 @@ DungeonMan::~DungeonMan() {
delete[] _dunData.squareFirstThings;
delete[] _dunData.textData;
delete[] _dunData.mapData;
+ for (uint16 i = 0; i < 16; ++i) {
+ if (_dunData.thingsData[i])
+ delete[] _dunData.thingsData[i][0];
+ delete[] _dunData.thingsData[i];
+ }
}
void DungeonMan::decompressDungeonFile() {
@@ -113,27 +155,28 @@ uint8 gAdditionalThingCounts[16] = {
50 /* Explosion */
}; // @ G0236_auc_Graphic559_AdditionalThingCounts
-// TODO: refactor THINGS into classes
-unsigned char gThingDataByteCount[16] = {
- 4, /* Door */
- 6, /* Teleporter */
- 4, /* Text String */
- 8, /* Sensor */
- 16, /* Group */
- 4, /* Weapon */
- 4, /* Armour */
- 4, /* Scroll */
- 4, /* Potion */
- 8, /* Container */
- 4, /* Junk */
+// this is the number of uint16s the data has to be stored, not the lenght of the data in dungeon.dat!
+unsigned char gThingDataWordCount[16] = {
+ 2, /* Door */
+ 3, /* Teleporter */
+ 2, /* Text String */
+ 4, /* Sensor */
+ 9, /* Group */
+ 2, /* Weapon */
+ 2, /* Armour */
+ 2, /* Scroll */
+ 2, /* Potion */
+ 4, /* Container */
+ 2, /* Junk */
0, /* Unused */
0, /* Unused */
0, /* Unused */
- 8, /* Projectile */
- 4 /* Explosion */
+ 5, /* Projectile */
+ 2 /* Explosion */
}; // @ G0235_auc_Graphic559_ThingDataByteCount
-const Thing Thing::specThingNone(0, 0, 0);
+const Thing Thing::thingNone(0);
+const Thing Thing::thingEndOfList(0xFFFE);
void DungeonMan::loadDungeonFile() {
@@ -193,8 +236,8 @@ void DungeonMan::loadDungeonFile() {
tmp = dunDataStream.readUint16BE();
_maps[i].doorSet1 = (tmp >> 12) & 0xF;
_maps[i].doorSet0 = (tmp >> 8) & 0xF;
- _maps[i].wallSet = (tmp >> 4) & 0xF;
- _maps[i].floorSet = tmp & 0xF;
+ _maps[i].wallSet = (WallSet)((tmp >> 4) & 0xF);
+ _maps[i].floorSet = (FloorSet)(tmp & 0xF);
}
// TODO: ??? is this - begin
@@ -228,7 +271,7 @@ void DungeonMan::loadDungeonFile() {
_dunData.squareFirstThings[i].set(dunDataStream.readUint16BE());
if (_messages.newGame)
for (uint16 i = 0; i < 300; ++i)
- _dunData.squareFirstThings[i] = Thing::specThingNone;
+ _dunData.squareFirstThings[i] = Thing::thingNone;
// TODO: ??? is this - end
@@ -243,12 +286,51 @@ void DungeonMan::loadDungeonFile() {
if (_messages.newGame)
_dunData.eventMaximumCount = 100;
- // load 'Things'
- // TODO: implement load things
- // this is a temporary workaround to seek to raw map data
- for (uint16 i = 0; i < kThingTypeTotal; ++i)
- dunDataStream.skip(_fileHeader.thingCounts[i] * gThingDataByteCount[i]);
+ // load things
+ for (uint16 thingType = kDoorThingType; thingType < kThingTypeTotal; ++thingType) {
+ uint16 thingCount = _fileHeader.thingCounts[thingType];
+ if (_messages.newGame) {
+ // _fileHeader.thingCounts[thingType] = 1024; // TODO: what this?? check back later
+ }
+ uint16 thingStoreWordCount = gThingDataWordCount[thingType];
+ if (!thingStoreWordCount || !thingCount)
+ continue;
+
+ if (_dunData.thingsData[thingType]) {
+ delete[] _dunData.thingsData[thingType][0];
+ delete[] _dunData.thingsData[thingType];
+ }
+ _dunData.thingsData[thingType] = new uint16*[thingCount];
+ _dunData.thingsData[thingType][0] = new uint16[thingCount * thingStoreWordCount];
+ for (uint16 i = 0; i < thingCount; ++i)
+ _dunData.thingsData[thingType][i] = _dunData.thingsData[thingType][0] + i * thingStoreWordCount;
+
+ if (thingType == kGroupThingType) {
+ for (uint16 i = 0; i < thingCount; ++i)
+ for (uint16 j = 0; j < thingStoreWordCount; ++j) {
+ if (j == 2 || j == 3)
+ _dunData.thingsData[thingType][i][j] = dunDataStream.readByte();
+ else
+ _dunData.thingsData[thingType][i][j] = dunDataStream.readUint16BE();
+ }
+ } else if (thingType == kProjectileThingType) {
+ for (uint16 i = 0; i < thingCount; ++i) {
+ _dunData.thingsData[thingType][i][0] = dunDataStream.readUint16BE();
+ _dunData.thingsData[thingType][i][1] = dunDataStream.readUint16BE();
+ _dunData.thingsData[thingType][i][2] = dunDataStream.readByte();
+ _dunData.thingsData[thingType][i][3] = dunDataStream.readByte();
+ _dunData.thingsData[thingType][i][4] = dunDataStream.readUint16BE();
+ }
+ } else {
+ for (uint16 i = 0; i < thingCount; ++i)
+ for (uint16 j = 0; j < thingStoreWordCount; ++j)
+ _dunData.thingsData[thingType][i][j] = dunDataStream.readUint16BE();
+ }
+ }
+
+
+ // load map data
_rawMapData = _rawDunFileData + dunDataStream.pos();
if (_dunData.mapData) delete[] _dunData.mapData;
@@ -282,6 +364,26 @@ void DungeonMan::setCurrentMap(uint16 mapIndex) {
= &_dunData.columnsCumulativeSquareThingCount[_dunData.mapsFirstColumnIndex[mapIndex]];
}
+void DungeonMan::setCurrentMapAndPartyMap(uint16 mapIndex) {
+ setCurrentMap(mapIndex);
+
+ byte *metaMapData = _currMap.data[_currMap.width - 1] + _currMap.height;
+ _vm->_displayMan->_currMapAllowedCreatureTypes = metaMapData;
+
+ metaMapData += _currMap.map->creatureTypeCount;
+ memcpy(_vm->_displayMan->_currMapWallOrnIndices, metaMapData, _currMap.map->wallOrnCount);
+
+ metaMapData += _currMap.map->wallOrnCount;
+ memcpy(_vm->_displayMan->_currMapFloorOrnIndices, metaMapData, _currMap.map->floorOrnCount);
+
+ metaMapData += _currMap.map->wallOrnCount;
+ memcpy(_vm->_displayMan->_currMapDoorOrnIndices, metaMapData, _currMap.map->doorOrnCount);
+
+ _currMapInscriptionWallOrnIndex = _currMap.map->wallOrnCount;
+ _vm->_displayMan->_currMapWallOrnIndices[_currMapInscriptionWallOrnIndex] = kWallOrnInscription;
+
+}
+
Square DungeonMan::getSquare(int16 mapX, int16 mapY) {
bool isInXBounds = (mapX >= 0) && (mapX < _currMap.width);
@@ -293,7 +395,7 @@ Square DungeonMan::getSquare(int16 mapX, int16 mapY) {
Square tmpSquare;
if (isInYBounds) {
- Square tmpSquare(_currMap.data[0][mapY]);
+ tmpSquare.set(_currMap.data[0][mapY]);
if (mapX == -1 && (tmpSquare.getType() == kCorridorElemType || tmpSquare.getType() == kPitElemType))
return Square(kWallElemType).set(kWallEastRandOrnAllowed);
@@ -318,7 +420,149 @@ Square DungeonMan::getRelSquare(direction dir, int16 stepsForward, int16 stepsRi
return getSquare(posX, posY);
}
-Thing DungeonMan::getSqureFirstThingIndex(int16 mapX, int16 mapY) {
- //if (mapX < 0 || mapX >= _currMap.width || mapY < 0 || mapY >= _currMap.height || !(_currMap.data[mapX] & kThingListPresent))
- return Thing();
-} \ No newline at end of file
+int16 DungeonMan::getSquareFirstThingIndex(int16 mapX, int16 mapY) {
+ if (mapX < 0 || mapX >= _currMap.width || mapY < 0 || mapY >= _currMap.height || !Square(_currMap.data[mapX][mapY]).get(kThingListPresent))
+ return -1;
+
+ int16 y;
+ uint16 index = _currMap.colCumulativeSquareFirstThingCount[mapX];
+ byte* square = _currMap.data[mapX];
+ while (y++ != mapY)
+ if (Square(*square++).get(kThingListPresent))
+ index++;
+
+ return index;
+}
+
+Thing DungeonMan::getSquareFirstThing(int16 mapX, int16 mapY) {
+ int16 index = getSquareFirstThingIndex(mapX, mapY);
+ if (index == -1)
+ return Thing::thingEndOfList;
+ return _dunData.squareFirstThings[index];
+}
+
+enum SquareAspectIndice {
+ kElemAspect = 0,
+ kFirstGroupOrObjectAspect = 1,
+ kRightWallOrnOrdAspect = 2,
+ kFrontWallOrnOrdAspect = 3,
+ kLeftWallOrnOrdAspect = 4,
+ kPitInvisibleAspect = 2,
+ kTeleporterVisibleAspect = 2,
+ kStairsUpAspect = 2,
+ kDoorStateAspect = 2,
+ kDoorThingIndexAspect = 3,
+ kFloorOrnOrdAspect = 4
+};
+
+
+void DungeonMan::setSquareAspect(uint16 *aspectArray, direction dir, int16 mapX, int16 mapY) {
+ bool leftOrnAllowed, rightOrnAllowed, frontOrnAllowed;
+ bool squareIsFakeWall;
+
+ Thing thing = getSquareFirstThing(mapX, mapY);
+ Square square = getSquare(mapX, mapY);
+
+ memset(aspectArray, 0, 5 * sizeof(int16));
+ aspectArray[kElemAspect] = square.getType();
+
+ _vm->_displayMan->_championPortraitOrdinal = 0; // BUG0_75
+ switch (square.getType()) {
+ case kWallElemType:
+ switch (dir) {
+ case kDirNorth:
+ leftOrnAllowed = square.get(kWallEastRandOrnAllowed);
+ frontOrnAllowed = square.get(kWallSouthRandOrnAllowed);
+ rightOrnAllowed = square.get(kWallWestRandOrnAllowed);
+ break;
+ case kDirEast:
+ leftOrnAllowed = square.get(kWallSouthRandOrnAllowed);
+ frontOrnAllowed = square.get(kWallWestRandOrnAllowed);
+ rightOrnAllowed = square.get(kWallNorthRandOrnAllowed);
+ break;
+ case kDirSouth:
+ leftOrnAllowed = square.get(kWallWestRandOrnAllowed);
+ frontOrnAllowed = square.get(kWallNorthRandOrnAllowed);
+ rightOrnAllowed = square.get(kWallEastRandOrnAllowed);
+ break;
+ case kDirWest:
+ leftOrnAllowed = square.get(kWallNorthRandOrnAllowed);
+ frontOrnAllowed = square.get(kWallEastRandOrnAllowed);
+ rightOrnAllowed = square.get(kWallSouthRandOrnAllowed);
+ break;
+ }
+
+ squareIsFakeWall = false;
+ setSquareAspectOrnOrdinals(aspectArray, leftOrnAllowed, frontOrnAllowed, rightOrnAllowed, dir, mapX, mapY, squareIsFakeWall);
+
+ while ((thing != Thing::thingEndOfList) && (thing.getType() <= kSensorThingType)) {
+ int16 sideIndex = (thing.getCell() - dir) & 3;
+ if (sideIndex) {
+ if (thing.getType() == kTextstringType) {
+ if (TextString(getThingData(thing)).isVisible()) {
+ aspectArray[sideIndex + 1] = _currMapInscriptionWallOrnIndex + 1;
+
+ } else {
+ Sensor sensor(getThingData(thing));
+ aspectArray[sideIndex + 1] = sensor.getOrnOrdinal();
+ if (sensor.getType() == kSensorWallChampionPortrait) {
+ _vm->_displayMan->_championPortraitOrdinal = indexToOrdinal(sensor.getData());
+ }
+ }
+ }
+ }
+ thing = getNextThing(thing);
+ }
+ if (squareIsFakeWall && (_currMap.partyPosX != mapX) && (_currMap.partyPosY != mapY)) {
+ aspectArray[kFirstGroupOrObjectAspect] = Thing::thingEndOfList.toUint16();
+ }
+ break;
+ }
+ aspectArray[kFirstGroupOrObjectAspect] = thing.toUint16();
+}
+
+void DungeonMan::setSquareAspectOrnOrdinals(uint16 *aspectArray, bool leftAllowed, bool frontAllowed, bool rightAllowed, direction dir,
+ int16 mapX, int16 mapY, bool isFakeWall) {
+ int16 ornCount = _currMap.map->randWallOrnCount;
+
+ turnDirRight(dir);
+ aspectArray[kRightWallOrnOrdAspect] = getRandomOrnOrdinal(leftAllowed, ornCount, mapX, ++mapY * (dir + 1), 30);
+ turnDirRight(dir);
+ aspectArray[kFrontWallOrnOrdAspect] = getRandomOrnOrdinal(frontAllowed, ornCount, mapX, ++mapY * (dir + 1), 30);
+ turnDirRight(dir);
+ aspectArray[kLeftWallOrnOrdAspect] = getRandomOrnOrdinal(rightAllowed, ornCount, mapX, ++mapY * (dir + 1), 30);
+
+ if (isFakeWall || mapX < 0 || mapX >= _currMap.width || mapY < 0 || mapY >= _currMap.height) {
+ for (uint16 i = kRightWallOrnOrdAspect; i <= kLeftWallOrnOrdAspect; ++i) {
+ if (isWallOrnAnAlcove(ordinalToIndex(aspectArray[i])))
+ aspectArray[i] = 0;
+ }
+ }
+}
+
+int16 DungeonMan::getRandomOrnOrdinal(bool allowed, int16 count, int16 mapX, int16 mapY, int16 modulo) {
+ int16 index = (((((2000 + (mapX << 5) + mapY) * 31417) >> 1)
+ + (3000 + (_currMap.index << 6) + _currMap.width + _currMap.height) * 11
+ + _fileHeader.ornamentRandomSeed) >> 2) % modulo;
+ if (allowed && index < count)
+ return indexToOrdinal(index);
+ return 0;
+}
+
+
+bool DungeonMan::isWallOrnAnAlcove(int16 wallOrnIndex) {
+ if (wallOrnIndex >= 0)
+ for (uint16 i = 0; i < kAlcoveOrnCount; ++i)
+ if (_vm->_displayMan->_currMapAlcoveOrnIndices[i] == wallOrnIndex)
+ return true;
+ return false;
+}
+
+uint16 *DungeonMan::getThingData(Thing thing) {
+ return _dunData.thingsData[thing.getType()][thing.getIndex()];
+}
+
+Thing DungeonMan::getNextThing(Thing thing) {
+ return getThingData(thing)[0]; // :)
+}
+
diff --git a/engines/dm/dungeonman.h b/engines/dm/dungeonman.h
index 8c7ed84bb3..df8395312c 100644
--- a/engines/dm/dungeonman.h
+++ b/engines/dm/dungeonman.h
@@ -2,12 +2,16 @@
#define DUNGEONMAN_H
#include "dm.h"
+#include "gfx.h"
namespace DM {
class DungeonMan;
-class Map;
+struct Map;
+
+int16 ordinalToIndex(int16 val); // @ M01_ORDINAL_TO_INDEX
+int16 indexToOrdinal(int16 val); // @ M00_INDEX_TO_ORDINAL
enum ThingType {
kPartyThingType = -1, // @ CM1_THING_TYPE_PARTY, special value
kDoorThingType = 0,
@@ -23,9 +27,270 @@ enum ThingType {
kJunkThingType = 10,
kProjectileThingType = 14,
kExplosionThingType = 15,
- kThingTypeTotal = 16 // +1 than the last
+ kThingTypeTotal = 16 // +1 than the last (explosionThingType)
}; // @ C[00..15]_THING_TYPE_...
+class Thing {
+ uint16 data;
+public:
+ static const Thing thingNone;
+ static const Thing thingEndOfList;
+
+ Thing() {}
+ Thing(uint16 d) { set(d); }
+
+ void set(uint16 d) {
+ data = d;
+ }
+
+ byte getCell() const { return data >> 14; }
+ ThingType getType() const { return (ThingType)((data >> 10) & 0xF); }
+ uint16 getIndex() const { return data & 0x1FF; }
+ uint16 toUint16() const { return data; } // I don't like 'em cast operators
+ bool operator==(const Thing &rhs) const { return data == rhs.data; }
+ bool operator!=(const Thing &rhs) const { return data != rhs.data; }
+}; // @ THING
+
+struct CreatureInfo {
+ byte creatureAspectIndex;
+ byte attackSoundOrdinal;
+ uint16 attributes; /* Bits 15-14 Unreferenced */
+ uint16 graphicInfo; /* Bits 11 and 6 Unreferenced */
+ byte movementTicks; /* Value 255 means the creature cannot move */
+ byte attackTicks; /* Minimum ticks between attacks */
+ byte defense;
+ byte baseHealth;
+ byte attack;
+ byte poisonAttack;
+ byte dexterity;
+ uint16 Ranges; /* Bits 7-4 Unreferenced */
+ uint16 Properties;
+ uint16 Resistances; /* Bits 15-12 and 3-0 Unreferenced */
+ uint16 AnimationTicks; /* Bits 15-12 Unreferenced */
+ uint16 WoundProbabilities; /* Contains 4 probabilities to wound a champion's Head (Bits 15-12), Legs (Bits 11-8), Torso (Bits 7-4) and Feet (Bits 3-0) */
+ byte AttackType;
+}; // @ CREATURE_INFO
+
+
+extern CreatureInfo gCreatureInfo[kCreatureTypeCount];
+
+class Door {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Door(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+ Thing getNextThing() { return nextThing; }
+ bool isMeleeDestructible() { return (attributes >> 8) & 1; }
+ bool isMagicDestructible() { return (attributes >> 7) & 1; }
+ bool hasButton() { return (attributes >> 6) & 1; }
+ bool opensVertically() { return (attributes >> 5) & 1; }
+ byte getOrnOrdinal() { return (attributes >> 1) & 0xF; }
+ byte getType() { return attributes & 1; }
+}; // @ DOOR
+
+enum TeleporterScope {
+ kTelepScopeCreatures = 1, // @ MASK0x0001_SCOPE_CREATURES
+ kTelepScopeObjOrParty = 2 // @ MASK0x0002_SCOPE_OBJECTS_OR_PARTY
+};
+
+
+class Teleporter {
+ Thing nextThing;
+ uint16 attributes;
+ uint16 destMapIndex;
+public:
+ Teleporter(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]), destMapIndex(rawDat[2]) {}
+ Thing getNextThing() { return nextThing; }
+ bool makesSound() { return (attributes >> 15) & 1; }
+ TeleporterScope getScope() { return (TeleporterScope)((attributes >> 13) & 1); }
+ bool absRotation() { return (attributes >> 12) & 1; }
+ direction getRotationDir() { return (direction)((attributes >> 10) & 1); }
+ byte getDestY() { return (attributes >> 5) & 0xF; }
+ byte getDestX() { return attributes & 0xF; }
+ uint16 getDestMapIndex() { return destMapIndex >> 8; }
+}; // @ TELEPORTER
+
+
+
+class TextString {
+ Thing nextThing;
+ uint16 textDataRef;
+public:
+ TextString(uint16 *rawDat) : nextThing(rawDat[0]), textDataRef(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+ uint16 getWordOffset() { return textDataRef >> 3; }
+ bool isVisible() { return textDataRef & 1; }
+}; // @ TEXTSTRING
+
+enum SensorActionType {
+ kSensorEffNone = -1, // @ CM1_EFFECT_NONE
+ kSensorEffSet = 0, // @ C00_EFFECT_SET
+ kSensorEffClear = 1, // @ C01_EFFECT_CLEAR
+ kSensorEffToggle = 2, // @ C02_EFFECT_TOGGLE
+ kSensorEffHold = 3, // @ C03_EFFECT_HOLD
+ kSensorEffAddExp = 10 // @ C10_EFFECT_ADD_EXPERIENCE
+};
+
+enum SensorType {
+ kSensorDisabled = 0, // @ C000_SENSOR_DISABLED /* Never triggered, may be used for a floor or wall ornament */
+ kSensorFloorTheronPartyCreatureObj = 1, // @ C001_SENSOR_FLOOR_THERON_PARTY_CREATURE_OBJECT /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorTheronPartyCreature = 2, // @ C002_SENSOR_FLOOR_THERON_PARTY_CREATURE /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorParty = 3, // @ C003_SENSOR_FLOOR_PARTY /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorObj = 4, // @ C004_SENSOR_FLOOR_OBJECT /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorPartyOnStairs = 5, // @ C005_SENSOR_FLOOR_PARTY_ON_STAIRS /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorGroupGenerator = 6, // @ C006_SENSOR_FLOOR_GROUP_GENERATOR /* Triggered by event F0245_TIMELINE_ProcessEvent5_Square_Corridor */
+ kSensorFloorCreature = 7, // @ C007_SENSOR_FLOOR_CREATURE /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorPartyPossession = 8, // @ C008_SENSOR_FLOOR_PARTY_POSSESSION /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorFloorVersionChecker = 9, // @ C009_SENSOR_FLOOR_VERSION_CHECKER /* Triggered by party/thing F0276_SENSOR_ProcessThingAdditionOrRemoval */
+ kSensorWallOrnClick = 1, // @ C001_SENSOR_WALL_ORNAMENT_CLICK /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallOrnClickWithAnyObj = 2, // @ C002_SENSOR_WALL_ORNAMENT_CLICK_WITH_ANY_OBJECT /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallOrnClickWithSpecObj = 3, // @ C003_SENSOR_WALL_ORNAMENT_CLICK_WITH_SPECIFIC_OBJECT /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallOrnClickWithSpecObjRemoved = 4, // @ C004_SENSOR_WALL_ORNAMENT_CLICK_WITH_SPECIFIC_OBJECT_REMOVED /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallAndOrGate = 5, // @ C005_SENSOR_WALL_AND_OR_GATE /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallCountdown = 6, // @ C006_SENSOR_WALL_COUNTDOWN /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallSingleProjLauncherNewObj = 7, // @ C007_SENSOR_WALL_SINGLE_PROJECTILE_LAUNCHER_NEW_OBJECT /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallSingleProjLauncherExplosion = 8, // @ C008_SENSOR_WALL_SINGLE_PROJECTILE_LAUNCHER_EXPLOSION /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallDoubleProjLauncherNewObj = 9, // @ C009_SENSOR_WALL_DOUBLE_PROJECTILE_LAUNCHER_NEW_OBJECT /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallDoubleProjLauncherExplosion = 10, // @ C010_SENSOR_WALL_DOUBLE_PROJECTILE_LAUNCHER_EXPLOSION /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallOrnClickWithSpecObjRemovedRotateSensors = 11, // @ C011_SENSOR_WALL_ORNAMENT_CLICK_WITH_SPECIFIC_OBJECT_REMOVED_ROTATE_SENSORS /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallObjGeneratorRotateSensors = 12, // @ C012_SENSOR_WALL_OBJECT_GENERATOR_ROTATE_SENSORS /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallSingleObjStorageRotateSensors = 13, // @ C013_SENSOR_WALL_SINGLE_OBJECT_STORAGE_ROTATE_SENSORS /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallSingleProjLauncherSquareObj = 14, // @ C014_SENSOR_WALL_SINGLE_PROJECTILE_LAUNCHER_SQUARE_OBJECT /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallDoubleProjLauncherSquareObj = 15, // @ C015_SENSOR_WALL_DOUBLE_PROJECTILE_LAUNCHER_SQUARE_OBJECT /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallObjExchanger = 16, // @ C016_SENSOR_WALL_OBJECT_EXCHANGER /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallOrnClickWithSpecObjRemovedSensor = 17, // @ C017_SENSOR_WALL_ORNAMENT_CLICK_WITH_SPECIFIC_OBJECT_REMOVED_REMOVE_SENSOR /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+ kSensorWallEndGame = 18, // @ C018_SENSOR_WALL_END_GAME /* Triggered by event F0248_TIMELINE_ProcessEvent6_Square_Wall */
+ kSensorWallChampionPortrait = 127 // @ C127_SENSOR_WALL_CHAMPION_PORTRAIT /* Triggered by player click F0275_SENSOR_IsTriggeredByClickOnWall */
+};
+
+class Sensor {
+ Thing nextThing;
+ uint16 datAndType;
+ uint16 attributes;
+ uint16 action;
+public:
+ Sensor(uint16 *rawDat) : nextThing(rawDat[0]), datAndType(rawDat[1]), attributes(rawDat[2]), action(rawDat[3]) {}
+
+ Thing getNextThing() { return nextThing; }
+ SensorType getType() { return (SensorType)(datAndType & 0x7F); } // @ M39_TYPE
+ uint16 getData() { return datAndType >> 7; } // @ M40_DATA
+ uint16 getDataMask1() { return (datAndType >> 7) & 0xF; } // @ M42_MASK1
+ uint16 getDataMask2() { return (datAndType >> 11) & 0xF; } // @ M43_MASK2
+ void setData(int16 dat) { datAndType = (datAndType & 0x7F) | (dat << 7); } // @ M41_SET_DATA
+ void setTypeDisabled() { datAndType &= 0xFF80; } // @ M44_SET_TYPE_DISABLED
+ uint16 getOrnOrdinal() { return attributes >> 12; }
+ bool isLocalAction() { return (attributes >> 11) & 1; }
+ uint16 getDelay() { return (attributes >> 7) & 0xF; }
+ bool hasSound() { return (attributes >> 6) & 1; }
+ bool shouldRevert() { return (attributes >> 5) & 1; }
+ SensorActionType getActionType() { return (SensorActionType)((attributes >> 3) & 3); }
+ bool isSingleUse() { return (attributes >> 2) & 1; }
+ uint16 getRemoteMapY() { return (action >> 11); }
+ uint16 getRemoteMapX() { return (action >> 6) & 0x1F; }
+ direction getRemoteDir() { return (direction)((action >> 4) & 3); }
+ uint16 getLocalAction() { return (action >> 4); }
+ // some macros missing, i got bored
+}; // @ SENSOR
+
+class Group {
+ Thing nextThing;
+ Thing possessionID;
+ byte type;
+ byte position;
+ uint16 health[4];
+ uint16 attributes;
+public:
+ Group(uint16 *rawDat) : nextThing(rawDat[0]), possessionID(rawDat[1]), type(rawDat[2]),
+ position(rawDat[3]), attributes(rawDat[8]) {
+ health[0] = rawDat[4];
+ health[1] = rawDat[5];
+ health[2] = rawDat[6];
+ health[3] = rawDat[7];
+ }
+ Thing getNextThing() { return nextThing; }
+}; // @ GROUP
+
+class Weapon {
+ Thing nextThing;
+ uint16 desc;
+public:
+ Weapon(uint16 *rawDat) : nextThing(rawDat[0]), desc(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ WEAPON
+
+class Armour {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Armour(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ ARMOUR
+
+class Scroll {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Scroll(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+ void set(Thing next, uint16 attribs) {
+ nextThing = next;
+ attributes = attribs;
+ }
+ Thing getNextThing() { return nextThing; }
+}; // @ SCROLL
+
+class Potion {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Potion(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ POTION
+
+class Container {
+ Thing nextThing;
+ Thing nextContainedThing;
+ uint16 type;
+public:
+ Container(uint16 *rawDat) : nextThing(rawDat[0]), nextContainedThing(rawDat[1]), type(rawDat[2]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ CONTAINER
+
+class Junk {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Junk(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ JUNK
+
+class Projectile {
+ Thing nextThing;
+ Thing object;
+ byte kineticEnergy;
+ byte damageEnergy;
+ uint16 timerIndex;
+public:
+ Projectile(uint16 *rawDat) : nextThing(rawDat[0]), object(rawDat[1]), kineticEnergy(rawDat[2]),
+ damageEnergy(rawDat[3]), timerIndex(rawDat[4]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ PROJECTILE
+
+class Explosion {
+ Thing nextThing;
+ uint16 attributes;
+public:
+ Explosion(uint16 *rawDat) : nextThing(rawDat[0]), attributes(rawDat[1]) {}
+
+ Thing getNextThing() { return nextThing; }
+}; // @ EXPLOSION
+
enum SquareMask {
kWallWestRandOrnAllowed = 0x1,
@@ -63,22 +328,20 @@ enum SquareType {
}; // @ C[-2..19]_ELEMENT_...
class Square {
- byte dat;
+ byte data;
public:
- Square(byte dat = 0) : dat(dat) {}
+ Square(byte dat = 0) : data(dat) {}
Square(SquareType type) { setType(type); }
- Square &set(byte dat) { this->dat = dat; return *this; }
- Square &set(SquareMask mask) { dat |= mask; return *this; }
- bool get(SquareMask mask) { return dat & mask; }
- SquareType getType() { return (SquareType)(dat >> 5); } // @ M34_SQUARE_TYPE
- Square &setType(SquareType type) { dat = (dat & 0x1F) | type << 5; return *this; }
- byte toByte() { return dat; } // I don't like 'em casts
+ Square &set(byte dat) { this->data = dat; return *this; }
+ Square &set(SquareMask mask) { data |= mask; return *this; }
+ bool get(SquareMask mask) { return data & mask; }
+ SquareType getType() { return (SquareType)(data >> 5); } // @ M34_SQUARE_TYPE
+ Square &setType(SquareType type) { data = (data & 0x1F) | type << 5; return *this; }
+ byte toByte() { return data; } // I don't like 'em casts
};
-class DungeonFileHeader {
- friend class DungeonMan;
-
+struct DungeonFileHeader {
uint16 dungeonId; // @ G0526_ui_DungeonID
// equal to dungeonId
uint16 ornamentRandomSeed;
@@ -91,9 +354,7 @@ class DungeonFileHeader {
uint16 thingCounts[16]; // @ ThingCount[16]
}; // @ DUNGEON_HEADER
-class Map {
- friend class DungeonMan;
-
+struct Map {
uint32 rawDunDataOffset;
uint8 offsetMapX, offsetMapY;
@@ -109,31 +370,14 @@ class Map {
uint8 creatureTypeCount;
uint8 difficulty;
- uint8 floorSet, wallSet, doorSet0, doorSet1;
+ FloorSet floorSet;
+ WallSet wallSet;
+ uint8 doorSet0, doorSet1;
}; // @ MAP
-class Thing {
- friend class DungeonMan;
-
- static const Thing specThingNone;
-
- Thing() {}
- Thing(uint8 cell, uint8 type, uint8 index) : cell(cell), type(type), index(index) {}
-
- void set(uint16 dat) {
- cell = dat >> 14;
- type = (dat >> 10) & 0xF;
- index = dat & 0x1FF;
- }
-
- uint8 cell;
- uint8 type;
- uint8 index;
-}; // @ THING
-class DungeonData {
- friend class DungeonMan;
+struct DungeonData {
// I have no idea the heck is this
uint16 *mapsFirstColumnIndex = NULL; // @ G0281_pui_DungeonMapsFirstColumnIndex
uint16 columCount; // @ G0282_ui_DungeonColumnCount
@@ -143,7 +387,7 @@ class DungeonData {
Thing *squareFirstThings = NULL; // @ G0283_pT_SquareFirstThings
uint16 *textData = NULL; // @ G0260_pui_DungeonTextData
- byte *rawThingData[16] = {NULL}; // @ G0284_apuc_ThingData
+ uint16 **thingsData[16] = {NULL}; // @ G0284_apuc_ThingData
byte ***mapData = NULL; // @ G0279_pppuc_DungeonMapData
@@ -151,9 +395,7 @@ class DungeonData {
uint16 eventMaximumCount; // @ G0369_ui_EventMaximumCount
}; // @ AGGREGATE
-class CurrMapData {
- friend class DungeonMan;
-
+struct CurrMapData {
direction partyDir; // @ G0308_i_PartyDirection
uint16 partyPosX; // @ G0306_i_PartyMapX
uint16 partyPosY; // @ G0307_i_PartyMapY
@@ -168,9 +410,6 @@ class CurrMapData {
}; // @ AGGREGATE
struct Messages {
- friend class DungeonMan;
-
-private:
bool newGame = true; // @ G0298_B_NewGame
bool restartGameRequest = false; // @ G0523_B_RestartGameRequested
}; // @ AGGREGATE
@@ -181,17 +420,6 @@ private:
class DungeonMan {
DMEngine *_vm;
- uint32 _rawDunFileDataSize; // @ probably NONE
- byte *_rawDunFileData; // @ ???
- DungeonFileHeader _fileHeader; // @ G0278_ps_DungeonHeader
-
- DungeonData _dunData; // @ NONE
- CurrMapData _currMap; // @ NONE
- Map *_maps; // @ G0277_ps_DungeonMaps
- // does not have to be freed
- byte *_rawMapData; // @ G0276_puc_DungeonRawMapData
- Messages _messages; // @ NONE
-
DungeonMan(const DungeonMan &other); // no implementation on purpose
void operator=(const DungeonMan &rhs); // no implementation on purpose
@@ -200,19 +428,49 @@ class DungeonMan {
void decompressDungeonFile(); // @ F0455_FLOPPY_DecompressDungeon
- Thing getSqureFirstThingIndex(int16 mapX, int16 mapY); // @ F0160_DUNGEON_GetSquareFirstThingIndex
+ int16 getSquareFirstThingIndex(int16 mapX, int16 mapY); // @ F0160_DUNGEON_GetSquareFirstThingIndex
+ Thing getSquareFirstThing(int16 mapX, int16 mapY); // @ F0161_DUNGEON_GetSquareFirstThing
+
+ int16 getRandomOrnOrdinal(bool allowed, int16 count, int16 mapX, int16 mapY, int16 modulo); // @ F0170_DUNGEON_GetRandomOrnamentOrdinal
+ void setSquareAspectOrnOrdinals(uint16 *aspectArray, bool leftAllowed, bool frontAllowed, bool rightAllowed, direction dir,
+ int16 mapX, int16 mapY, bool isFakeWall); // @ F0171_DUNGEON_SetSquareAspectRandomWallOrnamentOrdinals
+
+ bool isWallOrnAnAlcove(int16 wallOrnIndex); // @ F0149_DUNGEON_IsWallOrnamentAnAlcove
+
+ void setCurrentMap(uint16 mapIndex); // @ F0173_DUNGEON_SetCurrentMap
+
+ Thing getNextThing(Thing thing); // @ F0159_DUNGEON_GetNextThing(THING P0280_T_Thing)
+ uint16 *getThingData(Thing thing); // @ unsigned char* F0156_DUNGEON_GetThingData(register THING P0276_T_Thing)
public:
DungeonMan(DMEngine *dmEngine);
~DungeonMan();
// TODO: this does stuff other than load the file!
void loadDungeonFile(); // @ F0434_STARTEND_IsLoadDungeonSuccessful_CPSC
- void setCurrentMap(uint16 mapIndex); // @ F0173_DUNGEON_SetCurrentMap
+ void setCurrentMapAndPartyMap(uint16 mapIndex); // @ F0174_DUNGEON_SetCurrentMapAndPartyMap
+
void mapCoordsAfterRelMovement(direction dir, int16 stepsForward, int16 stepsRight, int16 &posX, int16 &posY); // @ F0150_DUNGEON_UpdateMapCoordinatesAfterRelativeMovement
SquareType getRelSquareType(direction dir, int16 stepsForward, int16 stepsRight, int16 posX, int16 posY) {
return Square(getRelSquare(dir, stepsForward, stepsRight, posX, posY)).getType();
} // @ F0153_DUNGEON_GetRelativeSquareType
+ void setSquareAspect(uint16 *aspectArray, direction dir, int16 mapX, int16 mapY); // @ F0172_DUNGEON_SetSquareAspect
+
+ uint32 _rawDunFileDataSize; // @ probably NONE
+ byte *_rawDunFileData; // @ ???
+ DungeonFileHeader _fileHeader; // @ G0278_ps_DungeonHeader
+
+ DungeonData _dunData; // @ NONE
+ CurrMapData _currMap; // @ NONE
+ Map *_maps; // @ G0277_ps_DungeonMaps
+ // does not have to be freed
+ byte *_rawMapData; // @ G0276_puc_DungeonRawMapData
+ Messages _messages; // @ NONE;
+
+ int16 _currMapInscriptionWallOrnIndex; // @ G0265_i_CurrentMapInscriptionWallOrnamentIndex
+
+
};
}
+
#endif
diff --git a/engines/dm/gfx.cpp b/engines/dm/gfx.cpp
index 385b23fdac..ae5bcd9f88 100644
--- a/engines/dm/gfx.cpp
+++ b/engines/dm/gfx.cpp
@@ -1,33 +1,456 @@
-#include "gfx.h"
#include "engines/util.h"
#include "common/system.h"
#include "common/file.h"
#include "graphics/palette.h"
#include "common/endian.h"
-#include "dm/dungeonman.h"
+
+#include "gfx.h"
+#include "dungeonman.h"
namespace DM {
-// TODO: this is ONLY for the Amiga version, name will have to be refactored
-uint16 dmPalettes[10][16] = {
- {0x000, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0x000, 0xFFF, 0xAAA, 0xFFF, 0xAAA, 0x444, 0xFF0, 0xFF0},
- {0x000, 0x666, 0x888, 0x620, 0x0CC, 0x840, 0x080, 0x0C0, 0xF00, 0xFA0, 0xC86, 0xFF0, 0x000, 0xAAA, 0x00F, 0xFFF},
- {0x006, 0x0AA, 0xFF6, 0x840, 0xFF8, 0x000, 0x080, 0xA00, 0xC84, 0xFFA, 0xF84, 0xFC0, 0xFA0, 0x000, 0x620, 0xFFC},
- {0x000, 0x666, 0x888, 0x840, 0xCA8, 0x0C0, 0x080, 0x0A0, 0x864, 0xF00, 0xA86, 0x642, 0x444, 0xAAA, 0x620, 0xFFF},
- {0x000, 0x666, 0x888, 0x620, 0x0CC, 0x840, 0x080, 0x0C0, 0xF00, 0xFA0, 0xC86, 0xFF0, 0x444, 0xAAA, 0x00F, 0xFFF},
- {0x000, 0x444, 0x666, 0x620, 0x0CC, 0x820, 0x060, 0x0A0, 0xC00, 0x000, 0x000, 0xFC0, 0x222, 0x888, 0x00C, 0xCCC},
- {0x000, 0x222, 0x444, 0x420, 0x0CC, 0x620, 0x040, 0x080, 0xA00, 0x000, 0x000, 0xFA0, 0x000, 0x666, 0x00A, 0xAAA},
- {0x000, 0x000, 0x222, 0x200, 0x0CC, 0x420, 0x020, 0x060, 0x800, 0x000, 0x000, 0xC80, 0x000, 0x444, 0x008, 0x888},
- {0x000, 0x000, 0x000, 0x000, 0x0CC, 0x200, 0x000, 0x040, 0x600, 0x000, 0x000, 0xA60, 0x000, 0x222, 0x006, 0x666},
- {0x000, 0x000, 0x000, 0x000, 0x0CC, 0x000, 0x000, 0x020, 0x400, 0x000, 0x000, 0x640, 0x000, 0x000, 0x004, 0x444}
+
+#define kFirstWallOrn 121 // @ C121_GRAPHIC_FIRST_WALL_ORNAMENT
+#define kFirstFloorSet 75 // @ C075_GRAPHIC_FIRST_FLOOR_SET
+#define kFirstWallSet 77 // @ C077_GRAPHIC_FIRST_WALL_SET
+#define kFirstStairs 90 // @ C090_GRAPHIC_FIRST_STAIRS
+#define kFirstDoorSet 108 // @ C108_GRAPHIC_FIRST_DOOR_SET
+#define kInscriptionFont 120 // @ C120_GRAPHIC_INSCRIPTION_FONT
+#define kFirstWallOrn 121 // @ C121_GRAPHIC_FIRST_WALL_ORNAMENT
+#define kFirstFloorOrn 247 // @ C247_GRAPHIC_FIRST_FLOOR_ORNAMENT
+#define kFirstDoorOrn 303 // @ C303_GRAPHIC_FIRST_DOOR_ORNAMENT
+
+
+byte gDoorOrnCoordIndices[12] = { // @ G0196_auc_Graphic558_DoorOrnamentCoordinateSetIndices
+ 0, /* Door Ornament #00 Square Grid */
+ 1, /* Door Ornament #01 Iron Bars */
+ 1, /* Door Ornament #02 Jewels */
+ 1, /* Door Ornament #03 Wooden Bars */
+ 0, /* Door Ornament #04 Arched Grid */
+ 2, /* Door Ornament #05 Block Lock */
+ 3, /* Door Ornament #06 Corner Lock */
+ 1, /* Door Ornament #07 Black door */
+ 2, /* Door Ornament #08 Red Triangle Lock */
+ 2, /* Door Ornament #09 Triangle Lock */
+ 1, /* Door Ornament #10 Ra Door */
+ 1}; /* Door Ornament #11 Iron Door Damages */
+
+byte gFloorOrnCoordSetIndices[9] = { // @ G0195_auc_Graphic558_FloorOrnamentCoordinateSetIndices
+ 0, /* Floor Ornament 00 Square Grate */
+ 0, /* Floor Ornament 01 Square Pressure Pad */
+ 0, /* Floor Ornament 02 Moss */
+ 0, /* Floor Ornament 03 Round Grate */
+ 2, /* Floor Ornament 04 Round Pressure Plate */
+ 0, /* Floor Ornament 05 Black Flame Pit */
+ 0, /* Floor Ornament 06 Crack */
+ 2, /* Floor Ornament 07 Tiny Pressure Pad */
+ 0}; /* Floor Ornament 08 Puddle */
+
+byte gWallOrnCoordSets[8][13][6] = { // @ G0205_aaauc_Graphic558_WallOrnamentCoordinateSets
+ /* { X1, X2, Y1, Y2, PixelWidth, Height } */
+ {{80, 83, 41, 45, 8 * 2, 5}, /* D3L */
+ {140, 143, 41, 45, 8 * 2, 5}, /* D3R */
+ {16, 29, 39, 50, 8 * 2, 12}, /* D3L */
+ {107, 120, 39, 50, 8 * 2, 12}, /* D3C */
+ {187, 200, 39, 50, 8 * 2, 12}, /* D3R */
+ {67, 77, 40, 49, 8 * 2, 10}, /* D2L */
+ {146, 156, 40, 49, 8 * 2, 10}, /* D2R */
+ {0, 17, 38, 55, 16 * 2, 18}, /* D2L */
+ {102, 123, 38, 55, 16 * 2, 18}, /* D2C */
+ {206, 223, 38, 55, 16 * 2, 18}, /* D2R */
+ {48, 63, 38, 56, 8 * 2, 19}, /* D1L */
+ {160, 175, 38, 56, 8 * 2, 19}, /* D1R */
+ {96, 127, 36, 63, 16 * 2, 28}}, /* D1C */
+ {{74, 82, 41, 60, 8 * 2, 20}, /* D3L */
+ {141, 149, 41, 60, 8 * 2, 20}, /* D3R */
+ {1, 47, 37, 63, 24 * 2, 27}, /* D3L */
+ {88, 134, 37, 63, 24 * 2, 27}, /* D3C */
+ {171, 217, 37, 63, 24 * 2, 27}, /* D3R */
+ {61, 76, 38, 67, 8 * 2, 30}, /* D2L */
+ {147, 162, 38, 67, 8 * 2, 30}, /* D2R */
+ {0, 43, 37, 73, 32 * 2, 37}, /* D2L */
+ {80, 143, 37, 73, 32 * 2, 37}, /* D2C */
+ {180, 223, 37, 73, 32 * 2, 37}, /* D2R */
+ {32, 63, 36, 83, 16 * 2, 48}, /* D1L */
+ {160, 191, 36, 83, 16 * 2, 48}, /* D1R */
+ {64, 159, 36, 91, 48 * 2, 56}}, /* D1C */
+ {{80, 83, 66, 70, 8 * 2, 5}, /* D3L */
+ {140, 143, 66, 70, 8 * 2, 5}, /* D3R */
+ {16, 29, 64, 75, 8 * 2, 12}, /* D3L */
+ {106, 119, 64, 75, 8 * 2, 12}, /* D3C */
+ {187, 200, 64, 75, 8 * 2, 12}, /* D3R */
+ {67, 77, 74, 83, 8 * 2, 10}, /* D2L */
+ {146, 156, 74, 83, 8 * 2, 10}, /* D2R */
+ {0, 17, 73, 90, 16 * 2, 18}, /* D2L */
+ {100, 121, 73, 90, 16 * 2, 18}, /* D2C */
+ {206, 223, 73, 90, 16 * 2, 18}, /* D2R */
+ {48, 63, 84, 102, 8 * 2, 19}, /* D1L */
+ {160, 175, 84, 102, 8 * 2, 19}, /* D1R */
+ {96, 127, 92, 119, 16 * 2, 28}}, /* D1C */
+ {{80, 83, 49, 53, 8 * 2, 5}, /* D3L */
+ {140, 143, 49, 53, 8 * 2, 5}, /* D3R */
+ {16, 29, 50, 61, 8 * 2, 12}, /* D3L */
+ {106, 119, 50, 61, 8 * 2, 12}, /* D3C */
+ {187, 200, 50, 61, 8 * 2, 12}, /* D3R */
+ {67, 77, 53, 62, 8 * 2, 10}, /* D2L */
+ {146, 156, 53, 62, 8 * 2, 10}, /* D2R */
+ {0, 17, 55, 72, 16 * 2, 18}, /* D2L */
+ {100, 121, 55, 72, 16 * 2, 18}, /* D2C */
+ {206, 223, 55, 72, 16 * 2, 18}, /* D2R */
+ {48, 63, 57, 75, 8 * 2, 19}, /* D1L */
+ {160, 175, 57, 75, 8 * 2, 19}, /* D1R */
+ {96, 127, 64, 91, 16 * 2, 28}}, /* D1C */
+ {{75, 90, 40, 44, 8 * 2, 5}, /* D3L */
+ {133, 148, 40, 44, 8 * 2, 5}, /* D3R */
+ {1, 48, 44, 49, 24 * 2, 6}, /* D3L */
+ {88, 135, 44, 49, 24 * 2, 6}, /* D3C */
+ {171, 218, 44, 49, 24 * 2, 6}, /* D3R */
+ {60, 77, 40, 46, 16 * 2, 7}, /* D2L */
+ {146, 163, 40, 46, 16 * 2, 7}, /* D2R */
+ {0, 35, 43, 50, 32 * 2, 8}, /* D2L */
+ {80, 143, 43, 50, 32 * 2, 8}, /* D2C */
+ {184, 223, 43, 50, 32 * 2, 8}, /* D2R */
+ {32, 63, 41, 52, 16 * 2, 12}, /* D1L */
+ {160, 191, 41, 52, 16 * 2, 12}, /* D1R */
+ {64, 159, 41, 52, 48 * 2, 12}}, /* D1C */
+ {{78, 85, 36, 51, 8 * 2, 16}, /* D3L */
+ {138, 145, 36, 51, 8 * 2, 16}, /* D3R */
+ {10, 41, 34, 53, 16 * 2, 20}, /* D3L */
+ {98, 129, 34, 53, 16 * 2, 20}, /* D3C */
+ {179, 210, 34, 53, 16 * 2, 20}, /* D3R */
+ {66, 75, 34, 56, 8 * 2, 23}, /* D2L */
+ {148, 157, 34, 56, 8 * 2, 23}, /* D2R */
+ {0, 26, 33, 61, 24 * 2, 29}, /* D2L */
+ {91, 133, 33, 61, 24 * 2, 29}, /* D2C */
+ {194, 223, 33, 61, 24 * 2, 29}, /* D2R */
+ {41, 56, 31, 65, 8 * 2, 35}, /* D1L */
+ {167, 182, 31, 65, 8 * 2, 35}, /* D1R */
+ {80, 143, 29, 71, 32 * 2, 43}}, /* D1C */
+ {{75, 82, 25, 75, 8 * 2, 51}, /* D3L */
+ {142, 149, 25, 75, 8 * 2, 51}, /* D3R */
+ {12, 60, 25, 75, 32 * 2, 51}, /* D3L */
+ {88, 136, 25, 75, 32 * 2, 51}, /* D3C */
+ {163, 211, 25, 75, 32 * 2, 51}, /* D3R */
+ {64, 73, 20, 90, 8 * 2, 71}, /* D2L */
+ {150, 159, 20, 90, 8 * 2, 71}, /* D2R */
+ {0, 38, 20, 90, 32 * 2, 71}, /* D2L */
+ {82, 142, 20, 90, 32 * 2, 71}, /* D2C */
+ {184, 223, 20, 90, 32 * 2, 71}, /* D2R */
+ {41, 56, 9, 119, 8 * 2, 111}, /* D1L */
+ {169, 184, 9, 119, 8 * 2, 111}, /* D1R */
+ {64, 159, 9, 119, 48 * 2, 111}}, /* D1C */
+ {{74, 85, 25, 75, 8 * 2, 51}, /* D3L */
+ {137, 149, 25, 75, 8 * 2, 51}, /* D3R */
+ {0, 75, 25, 75, 40 * 2, 51}, /* D3L Atari ST: { 0, 83, 25, 75, 48*2, 51 } */
+ {74, 149, 25, 75, 40 * 2, 51}, /* D3C Atari ST: { 74, 149, 25, 75, 48*2, 51 } */
+ {148, 223, 25, 75, 40 * 2, 51}, /* D3R Atari ST: { 139, 223, 25, 75, 48*2, 51 } */
+ {60, 77, 20, 90, 16 * 2, 71}, /* D2L */
+ {146, 163, 20, 90, 16 * 2, 71}, /* D2R */
+ {0, 74, 20, 90, 56 * 2, 71}, /* D2L */
+ {60, 163, 20, 90, 56 * 2, 71}, /* D2C */
+ {149, 223, 20, 90, 56 * 2, 71}, /* D2R */
+ {32, 63, 9, 119, 16 * 2, 111}, /* D1L */
+ {160, 191, 9, 119, 16 * 2, 111}, /* D1R */
+ {32, 191, 9, 119, 80 * 2, 111}}}; /* D1C */
+
+byte gWallOrnCoordSetIndices[60] = { // @ G0194_auc_Graphic558_WallOrnamentCoordinateSetIndices
+ 1, /* Wall Ornament 00 Unreadable Inscription */
+ 1, /* Wall Ornament 01 Square Alcove */
+ 1, /* Wall Ornament 02 Vi Altar */
+ 1, /* Wall Ornament 03 Arched Alcove */
+ 0, /* Wall Ornament 04 Hook */
+ 0, /* Wall Ornament 05 Iron Lock */
+ 0, /* Wall Ornament 06 Wood Ring */
+ 0, /* Wall Ornament 07 Small Switch */
+ 0, /* Wall Ornament 08 Dent 1 */
+ 0, /* Wall Ornament 09 Dent 2 */
+ 0, /* Wall Ornament 10 Iron Ring */
+ 2, /* Wall Ornament 11 Crack */
+ 3, /* Wall Ornament 12 Slime Outlet */
+ 0, /* Wall Ornament 13 Dent 3 */
+ 0, /* Wall Ornament 14 Tiny Switch */
+ 0, /* Wall Ornament 15 Green Switch Out */
+ 0, /* Wall Ornament 16 Blue Switch Out */
+ 0, /* Wall Ornament 17 Coin Slot */
+ 0, /* Wall Ornament 18 Double Iron Lock */
+ 0, /* Wall Ornament 19 Square Lock */
+ 0, /* Wall Ornament 20 Winged Lock */
+ 0, /* Wall Ornament 21 Onyx Lock */
+ 0, /* Wall Ornament 22 Stone Lock */
+ 0, /* Wall Ornament 23 Cross Lock */
+ 0, /* Wall Ornament 24 Topaz Lock */
+ 0, /* Wall Ornament 25 Skeleton Lock */
+ 0, /* Wall Ornament 26 Gold Lock */
+ 0, /* Wall Ornament 27 Tourquoise Lock */
+ 0, /* Wall Ornament 28 Emerald Lock */
+ 0, /* Wall Ornament 29 Ruby Lock */
+ 0, /* Wall Ornament 30 Ra Lock */
+ 0, /* Wall Ornament 31 Master Lock */
+ 0, /* Wall Ornament 32 Gem Hole */
+ 2, /* Wall Ornament 33 Slime */
+ 2, /* Wall Ornament 34 Grate */
+ 1, /* Wall Ornament 35 Fountain */
+ 1, /* Wall Ornament 36 Manacles */
+ 1, /* Wall Ornament 37 Ghoul's Head */
+ 1, /* Wall Ornament 38 Empty Torch Holder */
+ 1, /* Wall Ornament 39 Scratches */
+ 4, /* Wall Ornament 40 Poison Holes */
+ 4, /* Wall Ornament 41 Fireball Holes */
+ 4, /* Wall Ornament 42 Dagger Holes */
+ 5, /* Wall Ornament 43 Champion Mirror */
+ 0, /* Wall Ornament 44 Lever Up */
+ 0, /* Wall Ornament 45 Lever Down */
+ 1, /* Wall Ornament 46 Full Torch Holder */
+ 0, /* Wall Ornament 47 Red Switch Out */
+ 0, /* Wall Ornament 48 Eye Switch */
+ 0, /* Wall Ornament 49 Big Switch Out */
+ 2, /* Wall Ornament 50 Crack Switch Out */
+ 0, /* Wall Ornament 51 Green Switch In */
+ 0, /* Wall Ornament 52 Blue Switch In */
+ 0, /* Wall Ornament 53 Red Switch In */
+ 0, /* Wall Ornament 54 Big Switch In */
+ 2, /* Wall Ornament 55 Crack Switch In. Atari ST Version 1.0 1987-12-08: 0 */
+ 6, /* Wall Ornament 56 Amalgam (Encased Gem) */
+ 6, /* Wall Ornament 57 Amalgam (Free Gem) */
+ 6, /* Wall Ornament 58 Amalgam (Without Gem) */
+ 7}; /* Wall Ornament 59 Lord Order (Outside) */
+
+struct CreatureAspect {
+ uint16 firstNativeBitmapRelativeIndex;
+ uint16 firstDerivedBitmapIndex;
+ byte byteWidthFront;
+ byte heightFront;
+ byte byteWidthSide;
+ byte heightSide;
+ byte byteWidthAttack;
+ byte heightAttack;
+ byte coordinateSet_TransparentColor;
+ byte replacementColorSetIndices;
+
+ byte getCoordSet() { return (coordinateSet_TransparentColor >> 4) & 0xF; } // @ M71_COORDINATE_SET
+ byte getTranspColour() { return coordinateSet_TransparentColor & 0xF; } // @ M72_TRANSPARENT_COLOR
+ byte getReplColour10() { return (replacementColorSetIndices >> 4) & 0xF; } // @ M74_COLOR_10_REPLACEMENT_COLOR_SET
+ byte getReplColour9() { return replacementColorSetIndices & 0xF; } // @ M73_COLOR_09_REPLACEMENT_COLOR_SET
+}; // @ CREATURE_ASPECT
+
+
+CreatureAspect gCreatureAspects[kCreatureTypeCount] = { // @ G0219_as_Graphic558_CreatureAspects
+/* { FirstNativeBitmapRelativeIndex, FirstDerivedBitmapIndex, pixelWidthFront, HeightFront,
+pixelWidthSide, HeightSide, pixelWidthAttack, HeightAttack, CoordinateSet / TransparentColor,
+Replacement Color Set Index for color 10 / Replacement Color Set Index for color 9 } */
+ {0, 0, 56 * 2, 84, 56 * 2, 84, 56 * 2, 84, 0x1D, 0x01}, /* Creature #00 Giant Scorpion / Scorpion */
+ {4, 0, 32 * 2, 66, 0 * 2, 0, 32 * 2, 69, 0x0B, 0x20}, /* Creature #01 Swamp Slime / Slime Devil */
+ {6, 0, 24 * 2, 48, 24 * 2, 48, 0 * 2, 0, 0x0B, 0x00}, /* Creature #02 Giggler */
+ {10, 0, 32 * 2, 61, 0 * 2, 0, 32 * 2, 61, 0x24, 0x31}, /* Creature #03 Wizard Eye / Flying Eye */
+ {12, 0, 32 * 2, 64, 56 * 2, 64, 32 * 2, 64, 0x14, 0x34}, /* Creature #04 Pain Rat / Hellhound */
+ {16, 0, 24 * 2, 49, 40 * 2, 49, 0 * 2, 0, 0x18, 0x34}, /* Creature #05 Ruster */
+ {19, 0, 32 * 2, 60, 0 * 2, 0, 32 * 2, 60, 0x0D, 0x00}, /* Creature #06 Screamer */
+ {21, 0, 32 * 2, 43, 0 * 2, 0, 32 * 2, 64, 0x04, 0x00}, /* Creature #07 Rockpile / Rock pile */
+ {23, 0, 32 * 2, 83, 0 * 2, 0, 32 * 2, 93, 0x04, 0x00}, /* Creature #08 Ghost / Rive */
+ {25, 0, 32 * 2, 101, 32 * 2, 101, 32 * 2, 101, 0x14, 0x00}, /* Creature #09 Stone Golem */
+ {29, 0, 32 * 2, 82, 32 * 2, 82, 32 * 2, 83, 0x04, 0x00}, /* Creature #10 Mummy */
+ {33, 0, 32 * 2, 80, 0 * 2, 0, 32 * 2, 99, 0x14, 0x00}, /* Creature #11 Black Flame */
+ {35, 0, 32 * 2, 80, 32 * 2, 80, 32 * 2, 76, 0x04, 0x00}, /* Creature #12 Skeleton */
+ {39, 0, 32 * 2, 96, 56 * 2, 93, 32 * 2, 90, 0x1D, 0x20}, /* Creature #13 Couatl */
+ {43, 0, 32 * 2, 49, 16 * 2, 49, 32 * 2, 56, 0x04, 0x30}, /* Creature #14 Vexirk */
+ {47, 0, 32 * 2, 59, 56 * 2, 43, 32 * 2, 67, 0x14, 0x78}, /* Creature #15 Magenta Worm / Worm */
+ {51, 0, 32 * 2, 83, 32 * 2, 74, 32 * 2, 74, 0x04, 0x65}, /* Creature #16 Trolin / Ant Man */
+ {55, 0, 24 * 2, 49, 24 * 2, 53, 24 * 2, 53, 0x24, 0x00}, /* Creature #17 Giant Wasp / Muncher */
+ {59, 0, 32 * 2, 89, 32 * 2, 89, 32 * 2, 89, 0x04, 0x00}, /* Creature #18 Animated Armour / Deth Knight */
+ {63, 0, 32 * 2, 84, 32 * 2, 84, 32 * 2, 84, 0x0D, 0xA9}, /* Creature #19 Materializer / Zytaz */
+ {67, 0, 56 * 2, 27, 0 * 2, 0, 56 * 2, 80, 0x04, 0x65}, /* Creature #20 Water Elemental */
+ {69, 0, 56 * 2, 77, 56 * 2, 81, 56 * 2, 77, 0x04, 0xA9}, /* Creature #21 Oitu */
+ {73, 0, 32 * 2, 87, 32 * 2, 89, 32 * 2, 89, 0x04, 0xCB}, /* Creature #22 Demon */
+ {77, 0, 32 * 2, 96, 32 * 2, 94, 32 * 2, 96, 0x04, 0x00}, /* Creature #23 Lord Chaos */
+ {81, 0, 64 * 2, 94, 72 * 2, 94, 64 * 2, 94, 0x04, 0xCB}, /* Creature #24 Red Dragon / Dragon */
+ {85, 0, 32 * 2, 93, 0 * 2, 0, 0 * 2, 0, 0x04, 0xCB}, /* Creature #25 Lord Order */
+ {86, 0, 32 * 2, 93, 0 * 2, 0, 0 * 2, 0, 0x04, 0xCB}}; /* Creature #26 Grey Lord */
+
+struct ObjectAspect {
+ byte firstNativeBitmapRelativeIndex;
+ byte firstDerivedBitmapRelativeIndex;
+ byte width;
+ byte height;
+ byte graphicInfo; /* Bits 7-5 and 3-1 Unreferenced */
+ byte coordinateSet;
+ ObjectAspect(byte firstN, byte firstD, byte byteWidth, byte h, byte grap, byte coord) :
+ firstNativeBitmapRelativeIndex(firstN), firstDerivedBitmapRelativeIndex(firstD),
+ width(byteWidth * 2), height(h), graphicInfo(grap), coordinateSet(coord) {}
+}; // @ OBJECT_ASPECT
+
+ObjectAspect gObjectAspects[kObjAspectCount] = { // @ G0209_as_Graphic558_ObjectAspects
+ /* FirstNativeBitmapRelativeIndex, FirstDerivedBitmapRelativeIndex, ByteWidth, Height, GraphicInfo, CoordinateSet */
+ ObjectAspect(0, 0, 24, 27, 0x11, 0),
+ ObjectAspect(2, 6, 24, 8, 0x00, 1),
+ ObjectAspect(3, 8, 8, 18, 0x00, 1),
+ ObjectAspect(4, 10, 8, 8, 0x00, 1),
+ ObjectAspect(5, 12, 8, 4, 0x00, 1),
+ ObjectAspect(6, 14, 16, 11, 0x00, 1),
+ ObjectAspect(7, 16, 24, 13, 0x00, 0),
+ ObjectAspect(8, 18, 32, 16, 0x00, 0),
+ ObjectAspect(9, 20, 40, 24, 0x00, 0),
+ ObjectAspect(10, 22, 16, 20, 0x00, 1),
+ ObjectAspect(11, 24, 40, 20, 0x00, 0),
+ ObjectAspect(12, 26, 32, 4, 0x00, 1),
+ ObjectAspect(13, 28, 40, 8, 0x00, 1),
+ ObjectAspect(14, 30, 32, 17, 0x00, 0),
+ ObjectAspect(15, 32, 40, 17, 0x00, 2),
+ ObjectAspect(16, 34, 16, 9, 0x00, 1),
+ ObjectAspect(17, 36, 24, 5, 0x00, 1),
+ ObjectAspect(18, 38, 16, 9, 0x00, 0),
+ ObjectAspect(19, 40, 8, 4, 0x00, 1),
+ ObjectAspect(20, 42, 32, 21, 0x00, 2),
+ ObjectAspect(21, 44, 32, 25, 0x00, 2),
+ ObjectAspect(22, 46, 32, 14, 0x00, 1),
+ ObjectAspect(23, 48, 32, 26, 0x00, 2),
+ ObjectAspect(24, 50, 32, 16, 0x00, 0),
+ ObjectAspect(25, 52, 32, 16, 0x00, 0),
+ ObjectAspect(26, 54, 16, 16, 0x00, 1),
+ ObjectAspect(27, 56, 16, 15, 0x00, 1),
+ ObjectAspect(28, 58, 16, 13, 0x00, 1),
+ ObjectAspect(29, 60, 16, 10, 0x00, 1),
+ ObjectAspect(30, 62, 40, 24, 0x00, 0),
+ ObjectAspect(31, 64, 40, 9, 0x00, 1),
+ ObjectAspect(32, 66, 16, 3, 0x00, 1),
+ ObjectAspect(33, 68, 32, 5, 0x00, 1),
+ ObjectAspect(34, 70, 40, 16, 0x00, 0),
+ ObjectAspect(35, 72, 8, 7, 0x00, 1),
+ ObjectAspect(36, 74, 32, 7, 0x00, 1),
+ ObjectAspect(37, 76, 24, 14, 0x00, 0),
+ ObjectAspect(38, 78, 16, 8, 0x00, 0),
+ ObjectAspect(39, 80, 8, 3, 0x00, 1),
+ ObjectAspect(40, 82, 40, 9, 0x00, 1),
+ ObjectAspect(41, 84, 24, 14, 0x00, 0),
+ ObjectAspect(42, 86, 40, 20, 0x00, 0),
+ ObjectAspect(43, 88, 40, 15, 0x00, 1),
+ ObjectAspect(44, 90, 32, 10, 0x00, 1),
+ ObjectAspect(45, 92, 32, 19, 0x00, 0),
+ ObjectAspect(46, 94, 40, 25, 0x00, 2),
+ ObjectAspect(47, 96, 24, 7, 0x00, 1),
+ ObjectAspect(48, 98, 8, 7, 0x00, 1),
+ ObjectAspect(49, 100, 16, 5, 0x00, 1),
+ ObjectAspect(50, 102, 8, 9, 0x00, 1),
+ ObjectAspect(51, 104, 32, 11, 0x00, 1),
+ ObjectAspect(52, 106, 32, 14, 0x00, 0),
+ ObjectAspect(53, 108, 24, 20, 0x00, 0),
+ ObjectAspect(54, 110, 16, 14, 0x00, 1),
+ ObjectAspect(55, 112, 32, 23, 0x00, 0),
+ ObjectAspect(56, 114, 24, 16, 0x00, 0),
+ ObjectAspect(57, 116, 32, 25, 0x00, 0),
+ ObjectAspect(58, 118, 24, 25, 0x00, 0),
+ ObjectAspect(59, 120, 8, 8, 0x00, 1),
+ ObjectAspect(60, 122, 8, 7, 0x00, 1),
+ ObjectAspect(61, 124, 8, 8, 0x00, 1),
+ ObjectAspect(62, 126, 8, 8, 0x00, 1),
+ ObjectAspect(63, 128, 8, 5, 0x00, 1),
+ ObjectAspect(64, 130, 8, 13, 0x01, 1),
+ ObjectAspect(65, 134, 16, 13, 0x00, 1),
+ ObjectAspect(66, 136, 16, 14, 0x00, 0),
+ ObjectAspect(67, 138, 16, 10, 0x00, 1),
+ ObjectAspect(68, 140, 8, 18, 0x00, 1),
+ ObjectAspect(69, 142, 8, 17, 0x00, 1),
+ ObjectAspect(70, 144, 32, 18, 0x00, 0),
+ ObjectAspect(71, 146, 16, 23, 0x00, 0),
+ ObjectAspect(72, 148, 16, 24, 0x00, 0),
+ ObjectAspect(73, 150, 16, 15, 0x00, 0),
+ ObjectAspect(74, 152, 8, 7, 0x00, 1),
+ ObjectAspect(75, 154, 8, 15, 0x00, 1),
+ ObjectAspect(76, 156, 8, 9, 0x00, 1),
+ ObjectAspect(77, 158, 16, 14, 0x00, 0),
+ ObjectAspect(78, 160, 8, 8, 0x00, 1),
+ ObjectAspect(79, 162, 16, 9, 0x00, 1),
+ ObjectAspect(80, 164, 8, 13, 0x01, 1),
+ ObjectAspect(81, 168, 8, 18, 0x00, 1),
+ ObjectAspect(82, 170, 24, 28, 0x00, 0),
+ ObjectAspect(83, 172, 40, 13, 0x00, 1),
+ ObjectAspect(84, 174, 8, 4, 0x00, 1),
+ ObjectAspect(85, 176, 32, 17, 0x00, 0)};
+
+struct ProjectileAspect {
+ byte firstNativeBitmapRelativeIndex;
+ byte firstDerivedBitmapRelativeIndex;
+ byte width;
+ byte height;
+ uint16 graphicInfo; /* Bits 15-9, 7-5 and 3-2 Unreferenced */
+
+ ProjectileAspect(byte firstN, byte firstD, byte byteWidth, byte h, uint16 grap) :
+ firstNativeBitmapRelativeIndex(firstN), firstDerivedBitmapRelativeIndex(firstD),
+ width(byteWidth * 2), height(h), graphicInfo(grap) {}
+}; // @ PROJECTIL_ASPECT
+
+
+ProjectileAspect gProjectileAspect[kProjectileAspectCount] = { // @ G0210_as_Graphic558_ProjectileAspects
+ /* ProjectileAspect( FirstNativeBitmapRelativeIndex, FirstDerivedBitmapRelativeIndex, ByteWidth, Height, GraphicInfo ) */
+ ProjectileAspect(0, 0, 32, 11, 0x0011), /* Arrow */
+ ProjectileAspect(3, 18, 16, 11, 0x0011), /* Dagger */
+ ProjectileAspect(6, 36, 24, 47, 0x0010), /* Axe - Executioner */
+ ProjectileAspect(9, 54, 32, 15, 0x0112), /* Explosion Lightning Bolt */
+ ProjectileAspect(11, 54, 32, 12, 0x0011), /* Slayer */
+ ProjectileAspect(14, 72, 24, 47, 0x0010), /* Stone Club */
+ ProjectileAspect(17, 90, 24, 47, 0x0010), /* Club */
+ ProjectileAspect(20, 108, 16, 11, 0x0011), /* Poison Dart */
+ ProjectileAspect(23, 126, 48, 18, 0x0011), /* Storm - Side Splitter - Diamond Edge - Falchion - Ra Blade - Rapier - Biter - Samurai Sword - Sword - Dragon Fang */
+ ProjectileAspect(26, 144, 8, 15, 0x0012), /* Throwing Star */
+ ProjectileAspect(28, 156, 16, 28, 0x0103), /* Explosion Fireball */
+ ProjectileAspect(29, 156, 16, 11, 0x0103), /* Explosion Default */
+ ProjectileAspect(30, 156, 16, 28, 0x0103), /* Explosion Slime */
+ ProjectileAspect(31, 156, 16, 24, 0x0103) /* Explosion Poison Bolt Poison Cloud */
};
+// TODO: this is ONLY for the Amiga version, name will have to be refactored
+
+/* Identical to the palette at the end of the swoosh palette animation */
+uint16 gPalSwoosh[16] = {0x000, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0x000, 0xFFF, 0xAAA, 0xFFF, 0xAAA, 0x444, 0xFF0, 0xFF0}; // @ K0057_aui_Palette_Swoosh
+uint16 gPalMousePointer[16] = {0x000, 0x666, 0x888, 0x620, 0x0CC, 0x840, 0x080, 0x0C0, 0xF00, 0xFA0, 0xC86, 0xFF0, 0x000, 0xAAA, 0x00F, 0xFFF}; // @ K0150_aui_Palette_MousePointer
+/* Atari ST: { 0x003, 0x055, 0x773, 0x420, 0x774, 0x000, 0x040, 0x500, 0x642, 0x775, 0x742, 0x760, 0x750, 0x000, 0x310, 0x776 }, RGB colors are different */
+uint16 gPalCredits[16] = {0x006, 0x0AA, 0xFF6, 0x840, 0xFF8, 0x000, 0x080, 0xA00, 0xC84, 0xFFA, 0xF84, 0xFC0, 0xFA0, 0x000, 0x620, 0xFFC}; // @ G0019_aui_Graphic562_Palette_Credits
+/* Atari ST: { 0x000, 0x333, 0x444, 0x420, 0x654, 0x210, 0x040, 0x050, 0x432, 0x700, 0x543, 0x321, 0x222, 0x555, 0x310, 0x777 }, RGB colors are different */
+uint16 gPalEntrance[16] = {0x000, 0x666, 0x888, 0x840, 0xCA8, 0x0C0, 0x080, 0x0A0, 0x864, 0xF00, 0xA86, 0x642, 0x444, 0xAAA, 0x620, 0xFFF}; // @ G0020_aui_Graphic562_Palette_Entrance
+uint16 gPalDungeonView[6][16] = { // @ G0021_aaui_Graphic562_Palette_DungeonView
+ /* Atari ST: { 0x000, 0x333, 0x444, 0x310, 0x066, 0x420, 0x040, 0x060, 0x700, 0x750, 0x643, 0x770, 0x222, 0x555, 0x007, 0x777 }, RGB colors are different */
+ 0x000, 0x666, 0x888, 0x620, 0x0CC, 0x840, 0x080, 0x0C0, 0xF00, 0xFA0, 0xC86, 0xFF0, 0x444, 0xAAA, 0x00F, 0xFFF,
+ /* Atari ST: { 0x000, 0x222, 0x333, 0x310, 0x066, 0x410, 0x030, 0x050, 0x600, 0x640, 0x532, 0x760, 0x111, 0x444, 0x006, 0x666 }, RGB colors are different */
+ 0x000, 0x444, 0x666, 0x620, 0x0CC, 0x820, 0x060, 0x0A0, 0xC00, 0x000, 0x000, 0xFC0, 0x222, 0x888, 0x00C, 0xCCC,
+ /* Atari ST: { 0x000, 0x111, 0x222, 0x210, 0x066, 0x310, 0x020, 0x040, 0x500, 0x530, 0x421, 0x750, 0x000, 0x333, 0x005, 0x555 }, RGB colors are different */
+ 0x000, 0x222, 0x444, 0x420, 0x0CC, 0x620, 0x040, 0x080, 0xA00, 0x000, 0x000, 0xFA0, 0x000, 0x666, 0x00A, 0xAAA,
+ /* Atari ST: { 0x000, 0x000, 0x111, 0x100, 0x066, 0x210, 0x010, 0x030, 0x400, 0x420, 0x310, 0x640, 0x000, 0x222, 0x004, 0x444 }, RGB colors are different */
+ 0x000, 0x000, 0x222, 0x200, 0x0CC, 0x420, 0x020, 0x060, 0x800, 0x000, 0x000, 0xC80, 0x000, 0x444, 0x008, 0x888,
+ /* Atari ST: { 0x000, 0x000, 0x000, 0x000, 0x066, 0x100, 0x000, 0x020, 0x300, 0x310, 0x200, 0x530, 0x000, 0x111, 0x003, 0x333 }, RGB colors are different */
+ 0x000, 0x000, 0x000, 0x000, 0x0CC, 0x200, 0x000, 0x040, 0x600, 0x000, 0x000, 0xA60, 0x000, 0x222, 0x006, 0x666,
+ /* Atari ST: { 0x000, 0x000, 0x000, 0x000, 0x066, 0x000, 0x000, 0x010, 0x200, 0x200, 0x100, 0x320, 0x000, 0x000, 0x002, 0x222 }, RGB colors are different */
+ 0x000, 0x000, 0x000, 0x000, 0x0CC, 0x000, 0x000, 0x020, 0x400, 0x000, 0x000, 0x640, 0x000, 0x000, 0x004, 0x444};
+
+
+struct CreatureReplColorSet {
+ uint16 RGBColor[6];
+ byte D2ReplacementColor;
+ byte D3ReplacementColor;
+}; // @ CREATURE_REPLACEMENT_COLOR_SET
+
+CreatureReplColorSet gCreatureReplColorSets[13] = { // @ G0220_as_Graphic558_CreatureReplacementColorSets
+ /* { Color, Color, Color, Color, Color, Color, D2 replacement color index (x10), D3 replacement color index (x10) } */
+ {0x0CA0, 0x0A80, 0x0860, 0x0640, 0x0420, 0x0200, 90, 90}, /* Atari ST: { 0x0650, 0x0540, 0x0430, 0x0320, 0x0210, 0x0100, 90, 90 }, RGB colors are different */
+ {0x0060, 0x0040, 0x0020, 0x0000, 0x0000, 0x0000, 0, 0}, /* Atari ST: { 0x0030, 0x0020, 0x0010, 0x0000, 0x0000, 0x0000, 0, 0 }, */
+ {0x0860, 0x0640, 0x0420, 0x0200, 0x0000, 0x0000, 100, 100}, /* Atari ST: { 0x0430, 0x0320, 0x0210, 0x0100, 0x0000, 0x0000, 100, 100 }, */
+ {0x0640, 0x0420, 0x0200, 0x0000, 0x0000, 0x0000, 90, 0}, /* Atari ST: { 0x0320, 0x0210, 0x0100, 0x0000, 0x0000, 0x0000, 90, 0 }, */
+ {0x000A, 0x0008, 0x0006, 0x0004, 0x0002, 0x0000, 90, 100}, /* Atari ST: { 0x0005, 0x0004, 0x0003, 0x0002, 0x0001, 0x0000, 90, 100 }, */
+ {0x0008, 0x0006, 0x0004, 0x0002, 0x0000, 0x0000, 100, 0}, /* Atari ST: { 0x0004, 0x0003, 0x0002, 0x0001, 0x0000, 0x0000, 100, 0 }, */
+ {0x0808, 0x0606, 0x0404, 0x0202, 0x0000, 0x0000, 90, 0}, /* Atari ST: { 0x0404, 0x0303, 0x0202, 0x0101, 0x0000, 0x0000, 90, 0 }, */
+ {0x0A0A, 0x0808, 0x0606, 0x0404, 0x0202, 0x0000, 100, 90}, /* Atari ST: { 0x0505, 0x0404, 0x0303, 0x0202, 0x0101, 0x0000, 100, 90 }, */
+ {0x0FA0, 0x0C80, 0x0A60, 0x0840, 0x0620, 0x0400, 100, 50}, /* Atari ST: { 0x0750, 0x0640, 0x0530, 0x0420, 0x0310, 0x0200, 100, 50 }, */
+ {0x0F80, 0x0C60, 0x0A40, 0x0820, 0x0600, 0x0200, 50, 70}, /* Atari ST: { 0x0740, 0x0630, 0x0520, 0x0410, 0x0300, 0x0100, 50, 30 }, D3 replacement color index is different */
+ {0x0800, 0x0600, 0x0400, 0x0200, 0x0000, 0x0000, 100, 120}, /* Atari ST: { 0x0400, 0x0300, 0x0200, 0x0100, 0x0000, 0x0000, 100, 100 }, D3 replacement color index is different */
+ {0x0600, 0x0400, 0x0200, 0x0000, 0x0000, 0x0000, 120, 0}, /* Atari ST: { 0x0300, 0x0200, 0x0100, 0x0000, 0x0000, 0x0000, 120, 0 }, */
+ {0x0C86, 0x0A64, 0x0842, 0x0620, 0x0400, 0x0200, 100, 50}}; /* Atari ST: { 0x0643, 0x0532, 0x0421, 0x0310, 0x0200, 0x0100, 100, 50 } }; */
+
+byte gPalChangesCreature_D3[16] = {0, 120, 10, 30, 40, 30, 0, 60, 30, 0, 0, 110, 0, 20, 0, 130}; // @ G0221_auc_Graphic558_PaletteChanges_Creature_D3
+byte gPalChangesCreature_D2[16] = {0, 10, 20, 30, 40, 30, 60, 70, 50, 0, 0, 110, 120, 130, 140, 150}; // @ G0222_auc_Graphic558_PaletteChanges_Creature_D2
+
enum GraphicIndice {
- gFloorIndice = 75,
- gCeilingIndice = 76
+ kDoorMaskDestroyedIndice = 301 // @ C301_GRAPHIC_DOOR_MASK_DESTROYED
};
// The frames in the orignal sources contain inclusive boundaries and byte widths, not pixel widths
@@ -50,18 +473,28 @@ Frame gWallFrameD3R2(208, 223, 25, 73, 8, 49, 0, 0); // @ G0712_s_Graphic558_Fra
extern Viewport gDefultViewPort = {0, 0};
extern Viewport gDungeonViewport = {0, 64}; // TODO: I guessed the numbers
+byte gPalChangesNoChanges[16] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150}; // @ G0017_auc_Graphic562_PaletteChanges_NoChanges
+
+byte gPalChangesFloorOrn_D3[16] = {0, 120, 10, 30, 40, 30, 0, 60, 30, 90, 100, 110, 0, 20, 140, 130}; // @ G0213_auc_Graphic558_PaletteChanges_FloorOrnament_D3
+byte gPalChangesFloorOrn_D2[16] = {0, 10, 20, 30, 40, 30, 60, 70, 50, 90, 100, 110, 120, 130, 140, 150}; // @ G0214_auc_Graphic558_PaletteChanges_FloorOrnament_D2
+
+int gFountainOrnIndices[kFountainOrnCount] = {35}; // @ G0193_ai_Graphic558_FountainOrnamentIndices
+byte gAlcoveOrnIndices[kAlcoveOrnCount] = { // @ G0192_auc_Graphic558_AlcoveOrnamentIndices
+ 1, /* Square Alcove */
+ 2, /* Vi Altar */
+ 3}; /* Arched Alcove */
+
}
using namespace DM;
DisplayMan::DisplayMan(DMEngine *dmEngine) :
- _vm(dmEngine), _currPalette(kPalSwoosh), _screenWidth(0), _screenHeight(0),
- _vgaBuffer(NULL), _packedItemCount(0), _packedItemPos(NULL), _packedBitmaps(NULL),
- _bitmaps(NULL) {}
+ _vm(dmEngine), _screenWidth(0), _screenHeight(0),
+ _vgaBuffer(NULL), _bitmaps(NULL) {}
DisplayMan::~DisplayMan() {
- delete[] _packedBitmaps;
delete[] _packedItemPos;
+ delete[] _packedBitmaps;
delete[] _vgaBuffer;
delete[] _bitmaps[0];
delete[] _bitmaps;
@@ -72,7 +505,6 @@ DisplayMan::~DisplayMan() {
void DisplayMan::setUpScreens(uint16 width, uint16 height) {
_screenWidth = width;
_screenHeight = height;
- loadPalette(kPalSwoosh);
_vgaBuffer = new byte[_screenWidth * _screenHeight];
clearScreen(kColorBlack);
}
@@ -81,21 +513,37 @@ void DisplayMan::loadGraphics() {
Common::File f;
f.open("graphics.dat");
- _packedItemCount = f.readUint16BE();
- _packedItemPos = new uint32[_packedItemCount + 1];
+ grapItemCount = f.readUint16BE();
+ _packedItemPos = new uint32[grapItemCount + 1];
_packedItemPos[0] = 0;
- for (uint16 i = 1; i < _packedItemCount + 1; ++i)
+ for (uint16 i = 1; i < grapItemCount + 1; ++i)
_packedItemPos[i] = f.readUint16BE() + _packedItemPos[i - 1];
- _packedBitmaps = new uint8[_packedItemPos[_packedItemCount]];
+ _packedBitmaps = new uint8[_packedItemPos[grapItemCount]];
- f.seek(2 + _packedItemCount * 4);
- for (uint32 i = 0; i < _packedItemPos[_packedItemCount]; ++i)
+ f.seek(2 + grapItemCount * 4);
+ for (uint32 i = 0; i < _packedItemPos[grapItemCount]; ++i)
_packedBitmaps[i] = f.readByte();
f.close();
unpackGraphics();
+
+ for (uint16 i = kDoorOrnDestroyedMask; i <= kDoorOrnThivesEyeMask; ++i) {
+ _currMapDoorOrnInfo[i][kNativeBitmapIndex] = i + (kDoorMaskDestroyedIndice - kDoorOrnDestroyedMask);
+ _currMapDoorOrnInfo[i][kNativeCoordinateSet] = 1;
+ }
+
+ _currMapFloorOrnInfo[kFloorOrnFootprints][kNativeBitmapIndex] = 1;
+ _currMapFloorOrnInfo[kFloorOrnFootprints][kNativeCoordinateSet] = 1;
+
+ _palChangesProjectile[0] = gPalChangesFloorOrn_D3;
+ _palChangesProjectile[1] = gPalChangesFloorOrn_D2;
+ _palChangesProjectile[2] = _palChangesProjectile[3] = gPalChangesNoChanges;
+
+ loadFloorSet(kFloorSetStone);
+ loadWallSet(kWallSetStone);
+
}
void DisplayMan::unpackGraphics() {
@@ -119,18 +567,14 @@ void DisplayMan::unpackGraphics() {
}
}
-void DisplayMan::loadPalette(dmPaletteEnum palette) {
- if (_currPalette == palette)
- return;
-
+void DisplayMan::loadPalette(uint16 *palette) {
byte colorPalette[16 * 3];
for (int i = 0; i < 16; ++i) {
- colorPalette[i * 3] = (dmPalettes[palette][i] >> 8) * (256 / 16);
- colorPalette[i * 3 + 1] = (dmPalettes[palette][i] >> 4) * (256 / 16);
- colorPalette[i * 3 + 2] = dmPalettes[palette][i] * (256 / 16);
+ colorPalette[i * 3] = (palette[i] >> 8) * (256 / 16);
+ colorPalette[i * 3 + 1] = (palette[i] >> 4) * (256 / 16);
+ colorPalette[i * 3 + 2] = palette[i] * (256 / 16);
}
_vm->_system->getPaletteManager()->setPalette(colorPalette, 0, 16);
- _currPalette = palette;
}
@@ -253,7 +697,7 @@ void DisplayMan::drawWallSetBitmap(byte *bitmap, Frame &f) {
blitToScreen(bitmap, f.srcWidth, f.srcX, f.srcY, f.destFromX, f.destToX, f.destFromY, f.destToY, kColorFlesh, gDungeonViewport);
}
-void drawSquareD3L(direction dir, int16 posX, int16 posY) {
+void DisplayMan::drawSquareD3L(direction dir, int16 posX, int16 posY) {
}
@@ -278,7 +722,7 @@ enum WallSetIndices {
};
void DisplayMan::drawDungeon(direction dir, int16 posX, int16 posY) {
- loadPalette(kPalDungeonView0);
+ loadPalette(gPalDungeonView[0]);
// TODO: this is a global variable, set from here
bool flippedFloorCeiling = (posX + posY + dir) & 1;
@@ -323,17 +767,16 @@ void DisplayMan::clearBitmap(byte *bitmap, uint16 width, uint16 height, Color co
}
-void DisplayMan::loadWallSet(WallSet set) {
+void DisplayMan::loadFloorSet(FloorSet set) {
// there are 2 bitmaps per set, first one is at 75
- GraphicIndice indice = (GraphicIndice)(75 + (2 * set));
+ GraphicIndice indice = (GraphicIndice)(kFirstFloorSet + (kFloorSetGraphicCount * set));
_floorBitmap = _bitmaps[indice];
_ceilingBitmap = _bitmaps[indice + 1];
}
-void DisplayMan::loadFloorSet(FloorSet set) {
- // there are 13 bitmaps perset, first one is at 77
- uint16 firstIndice = (set * 13) + 77;
- for (uint16 i = 0; i < 13; ++i) {
+void DisplayMan::loadWallSet(WallSet set) {
+ uint16 firstIndice = (set * kWallSetGraphicCount) + kFirstWallSet;
+ for (uint16 i = 0; i < kWallSetGraphicCount; ++i) {
_wallSetBitMaps[i] = _bitmaps[i + firstIndice];
}
@@ -353,4 +796,77 @@ void DisplayMan::loadFloorSet(FloorSet set) {
_wallSetBitMaps[kWall_D3R2] = new byte[w * h];
blitToBitmap(_wallSetBitMaps[kWall_D3L2], w, h, _wallSetBitMaps[kWall_D3R2], w);
flipBitmapHorizontal(_wallSetBitMaps[kWall_D3R2], w, h);
-} \ No newline at end of file
+}
+
+
+void DisplayMan::loadCurrentMapGraphics() {
+ loadFloorSet(_vm->_dungeonMan->_currMap.map->floorSet);
+ loadWallSet(_vm->_dungeonMan->_currMap.map->wallSet);
+
+ for (int16 i = 0; i < kAlcoveOrnCount; ++i)
+ _currMapAlcoveOrnIndices[i] = -1;
+ for (int16 i = 0; i < kFountainOrnCount; ++i)
+ _currMapFountainOrnIndices[i] = -1;
+
+
+
+
+ uint16 alcoveCount = 0;
+ uint16 fountainCount = 0;
+ Map &currMap = *_vm->_dungeonMan->_currMap.map;
+
+ for (uint16 i = 0; i < currMap.wallOrnCount; ++i) {
+ uint16 ornIndice = _currMapWallOrnIndices[i];
+ uint16 nativeIndice = kFirstWallOrn + ornIndice * 2;
+
+ _currMapWallOrnInfo[i][kNativeBitmapIndex] = nativeIndice;
+ for (uint16 ornCounter = 0; ornCounter < kAlcoveOrnCount; ++ornCounter) {
+ if (ornIndice == gAlcoveOrnIndices[ornCounter]) {
+ _currMapAlcoveOrnIndices[alcoveCount++] = i;
+ if (ornIndice == 2)
+ _currMapViAltarIndex = i;
+ }
+ }
+
+ for (uint16 ornCounter = 0; ornCounter < kFountainOrnCount; ++ornCounter)
+ if (ornIndice == gFountainOrnIndices[ornCounter])
+ _currMapFountainOrnIndices[fountainCount++] = i;
+
+ _currMapWallOrnInfo[i][kNativeCoordinateSet] = gWallOrnCoordSetIndices[ornIndice];
+ }
+
+ for (uint16 i = 0; i < currMap.floorOrnCount; ++i) {
+ uint16 ornIndice = _currMapFloorOrnIndices[i];
+ uint16 nativeIndice = kFirstFloorOrn + ornIndice * 6;
+ _currMapFloorOrnInfo[i][kNativeBitmapIndex] = nativeIndice;
+ _currMapFloorOrnInfo[i][kNativeCoordinateSet] = gFloorOrnCoordSetIndices[ornIndice];
+ }
+
+ for (uint16 i = 0; i < currMap.doorOrnCount; ++i) {
+ uint16 ornIndice = _currMapDoorOrnIndices[i];
+ uint16 nativeIndice = kFirstDoorOrn + ornIndice;
+ _currMapDoorOrnInfo[i][kNativeBitmapIndex] = nativeIndice;
+ _currMapDoorOrnInfo[i][kNativeCoordinateSet] = gDoorOrnCoordIndices[ornIndice];
+ }
+
+ applyCreatureReplColors(9, 8);
+ applyCreatureReplColors(10, 12);
+
+ for (uint16 creatureType = 0; creatureType < currMap.creatureTypeCount; ++creatureType) {
+ CreatureAspect &aspect = gCreatureAspects[_currMapAllowedCreatureTypes[creatureType]];
+ uint16 replColorOrdinal = aspect.getReplColour9();
+ if (replColorOrdinal)
+ applyCreatureReplColors(9, ordinalToIndex(replColorOrdinal));
+ replColorOrdinal = aspect.getReplColour10();
+ if (replColorOrdinal)
+ applyCreatureReplColors(10, ordinalToIndex(replColorOrdinal));
+ }
+}
+
+void DisplayMan::applyCreatureReplColors(int replacedColor, int replacementColor) {
+ for (int16 i = 0; i < 6; ++i)
+ gPalDungeonView[i][replacedColor] = gCreatureReplColorSets[replacementColor].RGBColor[i];
+
+ gPalChangesCreature_D2[replacedColor] = gCreatureReplColorSets[replacementColor].D2ReplacementColor;
+ gPalChangesCreature_D3[replacedColor] = gCreatureReplColorSets[replacementColor].D3ReplacementColor;
+}
diff --git a/engines/dm/gfx.h b/engines/dm/gfx.h
index 5670a5657c..4c6b461446 100644
--- a/engines/dm/gfx.h
+++ b/engines/dm/gfx.h
@@ -6,6 +6,12 @@
namespace DM {
+extern uint16 gPalSwoosh[16];
+extern uint16 gPalMousePointer[16];
+extern uint16 gPalCredits[16];
+extern uint16 gPalEntrance[16];
+extern uint16 gPalDungeonView[6][16];
+
struct Frame;
enum WallSet {
kWallSetStone = 0 // @ C0_WALL_SET_STONE
@@ -35,18 +41,6 @@ enum Color {
kColorWhite = 15
};
-enum dmPaletteEnum {
- kPalSwoosh = 0,
- kPalMousePointer = 1,
- kPalCredits = 2,
- kPalEntrance = 3,
- kPalDungeonView0 = 4,
- kPalDungeonView1 = 5,
- kPalDungeonView2 = 6,
- kPalDungeonView3 = 7,
- kPalDungeonView4 = 8,
- kPalDungeonView5 = 9,
-};
struct Viewport {
// TODO: should probably add width and height, seems redundant right meow
@@ -57,18 +51,42 @@ extern Viewport gDefultViewPort;
extern Viewport gDungeonViewport;
+#define kAlcoveOrnCount 3
+#define kFountainOrnCount 1
+
+#define kFloorSetGraphicCount 2 // @ C002_FLOOR_SET_GRAPHIC_COUNT
+#define kWallSetGraphicCount 13 // @ C013_WALL_SET_GRAPHIC_COUNT
+#define kStairsGraphicCount 18 // @ C018_STAIRS_GRAPHIC_COUNT
+#define kDoorSetGraphicsCount 3 // @ C003_DOOR_SET_GRAPHIC_COUNT
+#define kDoorButtonCount 1 // @ C001_DOOR_BUTTON_COUNT
+#define kNativeBitmapIndex 0 // @ C0_NATIVE_BITMAP_INDEX
+#define kNativeCoordinateSet 1 // @ C1_COORDINATE_SET
+#define kCreatureTypeCount 27 // @ C027_CREATURE_TYPE_COUNT
+#define kExplosionAspectCount 4 // @ C004_EXPLOSION_ASPECT_COUNT
+#define kObjAspectCount 85 // @ C085_OBJECT_ASPECT_COUNT
+#define kProjectileAspectCount 14 // @ C014_PROJECTILE_ASPECT_COUNT
+
+
+#define kDoorButton 0 // @ C0_DOOR_BUTTON
+#define kWallOrnInscription 0 // @ C0_WALL_ORNAMENT_INSCRIPTION
+#define kFloorOrnFootprints 15 // @ C15_FLOOR_ORNAMENT_FOOTPRINTS
+#define kDoorOrnDestroyedMask 15 // @ C15_DOOR_ORNAMENT_DESTROYED_MASK
+#define kDoorOrnThivesEyeMask 16 // @ C16_DOOR_ORNAMENT_THIEVES_EYE_MASK
+
+
+
class DisplayMan {
DMEngine *_vm;
- dmPaletteEnum _currPalette;
uint16 _screenWidth;
uint16 _screenHeight;
byte *_vgaBuffer;
- uint16 _packedItemCount;
- uint32 *_packedItemPos;
- byte *_packedBitmaps; // TODO: this doesn't not contaion graphics exclusively, will have to be moved
+ /// Related to graphics.dat file
+ uint16 grapItemCount; // @ G0632_ui_GraphicCount
+ uint32 *_packedItemPos;
+ byte *_packedBitmaps;
byte **_bitmaps;
@@ -79,25 +97,36 @@ class DisplayMan {
byte *_floorBitmap;
byte *_ceilingBitmap;
+
+ byte *_palChangesProjectile[4]; // @G0075_apuc_PaletteChanges_Projectile
+
+
DisplayMan(const DisplayMan &other); // no implementation on purpose
void operator=(const DisplayMan &rhs); // no implementation on purpose
byte *getCurrentVgaBuffer();
- // the original functions has two position parameters, but they are always set to zero
+ // the original function has two position parameters, but they are always set to zero
void loadIntoBitmap(uint16 index, byte *destBitmap); // @ F0466_EXPAND_GraphicToBitmap
void unpackGraphics();
+
void drawWallSetBitmap(byte *bitmap, Frame &f); // @ F0100_DUNGEONVIEW_DrawWallSetBitmap
void drawSquareD3L(direction dir, int16 posX, int16 posY); // @ F0116_DUNGEONVIEW_DrawSquareD3L
+
+ void loadWallSet(WallSet set); // @ F0095_DUNGEONVIEW_LoadWallSet
+ void loadFloorSet(FloorSet set); // @ F0094_DUNGEONVIEW_LoadFloorSet
+
+ void applyCreatureReplColors(int replacedColor, int replacementColor); // @ F0093_DUNGEONVIEW_ApplyCreatureReplacementColors
+
public:
DisplayMan(DMEngine *dmEngine);
~DisplayMan();
void setUpScreens(uint16 width, uint16 height);
- void loadGraphics();
- void loadWallSet(WallSet set); // @ F0095_DUNGEONVIEW_LoadWallSet
- void loadFloorSet(FloorSet set); // @ F0094_DUNGEONVIEW_LoadFloorSet
+ void loadGraphics(); // @ F0479_MEMORY_ReadGraphicsDatHeader, F0460_START_InitializeGraphicData
- void loadPalette(dmPaletteEnum palette);
+ void loadCurrentMapGraphics();
+
+ void loadPalette(uint16 *palette);
/// Gives the width of an IMG0 type item
uint16 width(uint16 index);
@@ -120,10 +149,22 @@ public:
void clearScreen(Color color);
void drawDungeon(direction dir, int16 posX, int16 posY); // @ F0128_DUNGEONVIEW_Draw_CPSF
void updateScreen();
-};
-}
+ int16 _championPortraitOrdinal = 0; // @ G0289_i_DungeonView_ChampionPortraitOrdinal
+ int16 _currMapAlcoveOrnIndices[kAlcoveOrnCount]; // @ G0267_ai_CurrentMapAlcoveOrnamentIndices
+ int16 _currMapFountainOrnIndices[kFountainOrnCount]; // @ G0268_ai_CurrentMapFountainOrnamentIndices
+ int16 _currMapWallOrnInfo[16][2]; // @ G0101_aai_CurrentMapWallOrnamentsInf
+ int16 _currMapFloorOrnInfo[16][2]; // @ G0102_aai_CurrentMapFloorOrnamentsInfo
+ int16 _currMapDoorOrnInfo[17][2]; // @ G0103_aai_CurrentMapDoorOrnamentsInfo
+ byte *_currMapAllowedCreatureTypes; // @ G0264_puc_CurrentMapAllowedCreatureTypes
+ byte _currMapWallOrnIndices[16]; // @ G0261_auc_CurrentMapWallOrnamentIndices
+ byte _currMapFloorOrnIndices[16]; // @ G0262_auc_CurrentMapFloorOrnamentIndices
+ byte _currMapDoorOrnIndices[18]; // @ G0263_auc_CurrentMapDoorOrnamentIndices
+ int16 _currMapViAltarIndex; // @ G0266_i_CurrentMapViAltarWallOrnamentIndex
+};
+
+}
#endif