diff options
author | WinterGrascph | 2016-05-15 15:53:00 +0200 |
---|---|---|
committer | Bendegúz Nagy | 2016-08-26 23:02:22 +0200 |
commit | a8c82c1e947e845e201aa114a246a5b3e3dd863b (patch) | |
tree | f6fd3de58c2170cb4601a25a35d83b5c23acd967 /engines | |
parent | 6d5f8e2757d04d47208f096795cb3755fd8a16f2 (diff) | |
download | scummvm-rg350-a8c82c1e947e845e201aa114a246a5b3e3dd863b.tar.gz scummvm-rg350-a8c82c1e947e845e201aa114a246a5b3e3dd863b.tar.bz2 scummvm-rg350-a8c82c1e947e845e201aa114a246a5b3e3dd863b.zip |
DM: Add some draw dungeon dependencies
I forgot to do commits and it was already too late to revert back the
changes I've because they were too numerous.
Diffstat (limited to 'engines')
-rw-r--r-- | engines/dm/dm.cpp | 14 | ||||
-rw-r--r-- | engines/dm/dm.h | 2 | ||||
-rw-r--r-- | engines/dm/dungeonman.cpp | 302 | ||||
-rw-r--r-- | engines/dm/dungeonman.h | 372 | ||||
-rw-r--r-- | engines/dm/gfx.cpp | 604 | ||||
-rw-r--r-- | engines/dm/gfx.h | 87 |
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 |