From 566214834b40baf99eab1bb9c4dd015fa4d39302 Mon Sep 17 00:00:00 2001 From: Matthieu Milan Date: Fri, 10 Jan 2020 20:36:56 +0100 Subject: [PATCH] Imports hode 0.2.5 --- CHANGES.txt | 4 + README.txt | 2 +- RELEASES.yaml | 46 +++++++++ defs.h | 8 +- fs_posix.cpp | 1 + game.cpp | 8 +- game.h | 4 +- intern.h | 2 + main.cpp | 2 +- menu.cpp | 137 ++++++++++++++++++++++----- menu.h | 17 +++- monsters.cpp | 246 +++++++++++++++++------------------------------- resource.cpp | 69 ++++++++------ resource.h | 1 + sound.cpp | 2 +- system_sdl2.cpp | 4 +- util.h | 2 +- 17 files changed, 327 insertions(+), 228 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index b2d993e..2284020 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +* release 0.2.5 + - fixed spiders and worms movement + - several fixes for big endian platforms + * release 0.2.4 - fixed Amigo walk path in 'pwr2' screen 7 - fixed glowing stone puzzle in 'lar2' diff --git a/README.txt b/README.txt index c2dec78..f31350f 100644 --- a/README.txt +++ b/README.txt @@ -1,6 +1,6 @@ hode README -Release version: 0.2.4 +Release version: 0.2.5 ------------------------------------------------------------------------------- diff --git a/RELEASES.yaml b/RELEASES.yaml index 726eeac..63fe5f4 100644 --- a/RELEASES.yaml +++ b/RELEASES.yaml @@ -45,6 +45,52 @@ - rock_hod.mst: 5b49637348f6c6a2737a64cacf01f9bcef8e83f6 - rock_hod.sss: 55c841f6c091c2ae68f0636c075c66405d00cc6a - setup.dat: 1d476d896cafd3d4af00b15eb2eb695a804a0662 +- name: Heart of Darkness Japanese (Win32) + files: + - dark_hod.lvl: e7c188e5c47632d512d96d9da89fc8c060528d45 + - dark_hod.mst: 6c2d93b2e31c299215d0fdf05ac1e8e8e95e9042 + - dark_hod.sss: 8d5b19842e551b8ec73bda411c210cc96e08569a + - fort_hod.lvl: 82456ed6e29780b5b8031a67ba3dddb8da813c19 + - fort_hod.mst: ce55095902ade9f1d8a198f271d0946d6228b90d + - fort_hod.sss: 6ff572b553d93040c9cad74891db05b2cc8267c6 + - hod.paf: fe75aff52c879aa5cc84a87babbca2ce0affec23 + - hodwin32.exe: eb0f032f343e2c27d60291c79ae667034a0c7389 + securom: false + version_info: + - Comments: Release Candidate 0 + - CompanyName: Amazing Studio - 9 rue d' Enhgien - 75010 Paris FRANCE - Email: hod@amazingstudio.com + - FileDescription: Heart Of Darkness + - FileVersion: 1, 1, 0, 0 + - InternalName: Heart Of Darkness + - LegalCopyright: (c) 1998 by Amazing Studio & Infogrames + - LegalTrademarks: by Amazing Studio - All rights reserved + - OriginalFilename: Heart Of Darkness + - PrivateBuild: HEARTMM5511 + - ProductName: Heart Of Darkness - Windows 95 / 98 & NT - DirectX 3.x or greater + - ProductVersion: 1, 1, 0, 0 + - SpecialBuild: VC5.0 Sp3 + - isld_hod.lvl: f78e9316f2187c0ca9e42abe8a2242b3d3e6feaf + - isld_hod.mst: 448e5dd5bbe59621279562d8695c9a864cb4c286 + - isld_hod.sss: 61c5da6dfcf80684c56baebddb04125ca0c1f209 + - lar1_hod.lvl: 84f7b33a9b57f2afa68063e0128512991f86dfa0 + - lar1_hod.mst: 9db53a4a75327eeca45ffa5b761a9f04af5e5204 + - lar1_hod.sss: 72667991fde3caf36978da1fa929695de80abe4b + - lar2_hod.lvl: 999b2548490f586f955c9f5c6db95f88d49102f3 + - lar2_hod.mst: 333ea4e6be6ca9aad735fafe59177546aab41c4e + - lar2_hod.sss: c5c655b718ead1d2eb460a058df7eb3b795dea9e + - lava_hod.lvl: 2921eb2f78354e79c1257ef55543bb1a1492e914 + - lava_hod.mst: c05ce42c0abdbb2dbfc109cbb4ea7eee1937445d + - lava_hod.sss: 8fc8d2c86f67e13ca840d604c603249b20723f85 + - pwr1_hod.lvl: cd6489e11914770d95034aa6afaa2fc67f035ce8 + - pwr1_hod.mst: f821e5686ae27b2ed5000ea4b38a464ecebe44a7 + - pwr1_hod.sss: cbb39e1bfd24dcbd5bf65f9e0b92faaa9b6b02a6 + - pwr2_hod.lvl: 7263ecf8d51d45c2c62dc11701eac03b67738fd8 + - pwr2_hod.mst: 132b29e758a28529009e979ef31a29a42d0a5c4b + - pwr2_hod.sss: 24342241b4353777cc22696be8a684d635f9c809 + - rock_hod.lvl: cdb3d7ad1ae13f2234380f79bc8ec57e1e505cef + - rock_hod.mst: 5b49637348f6c6a2737a64cacf01f9bcef8e83f6 + - rock_hod.sss: 55c841f6c091c2ae68f0636c075c66405d00cc6a + - setup.dat: 5cb36223a3fc5561d9c9d945fe3261cd188b5665 - name: Heart of Darkness Demo V1.2 (Win32) files: - hod_demo.paf: 50a0942256b17ed26f3b0f59f4cf7570a6eb8688 diff --git a/defs.h b/defs.h index b50ee6a..dde1e87 100644 --- a/defs.h +++ b/defs.h @@ -103,7 +103,7 @@ struct LvlSprMoveData { uint8_t op2; uint16_t op3; uint16_t op4; - uint16_t unk0x6; + uint16_t unk0x6; // padding to 8 bytes } PACKED; // sizeof == 8 struct LvlSprHotspotData { @@ -384,9 +384,11 @@ struct MonsterObject1 { int levelPosBounds_y1; // 0xA0 uint8_t o_flags0; // 0xA4 uint8_t flagsA5; // 0xA5 - uint8_t flagsA6; // 0xA6 + uint8_t flagsA6; // 0xA6 |1:turning |2:idle |4:colliding uint8_t targetDirectionMask; // 0xA7 - uint8_t bboxNum[4]; // 0xA8, 0xA9, 0xAA, 0xAB + uint8_t bboxNum[2]; // 0xA8, 0xA9 + uint8_t walkBoxNum; // 0xAA + uint8_t unkAB; // 0xAB int32_t targetLevelPos_x; // 0xAC int32_t targetLevelPos_y; // 0xB0 int32_t previousDxPos; // 0xB4 _xMstPos2 diff --git a/fs_posix.cpp b/fs_posix.cpp index 1172de8..365b40d 100644 --- a/fs_posix.cpp +++ b/fs_posix.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "fs.h" #include "util.h" diff --git a/game.cpp b/game.cpp index f55ee65..5478082 100644 --- a/game.cpp +++ b/game.cpp @@ -1833,13 +1833,13 @@ int Game::clipLvlObjectsBoundingBox(LvlObject *o, LvlObject *ptr, int type) { case 0: obj1.x2 = obj1.x1 + o->width - 1; obj1.y2 += o->height - 1; - obj2.x2 += ptr->width - 1; + obj2.x2 = obj2.x1 + ptr->width - 1; obj2.y2 += ptr->height - 1; return clipBoundingBox(&obj1, &obj2); case 48: - obj1.x2 += o->width - 1; + obj1.x2 = obj1.x1 + o->width - 1; obj1.y2 += o->height - 1; - obj2.x2 += ptr->width - 1; + obj2.x2 = obj2.x1 + ptr->width - 1; obj2.y2 += ptr->height - 1; if (clipBoundingBox(&obj1, &obj2)) { return updateBoundingBoxClippingOffset(&obj1, &obj2, _res->getLvlSpriteCoordPtr(ptr->levelData0x2988, ptr->currentSprite), (ptr->flags1 >> 4) & 3); @@ -4817,6 +4817,8 @@ void Game::saveSetupCfg() { if (count != kSetupCfgSize) { warning("Failed to write %d bytes to '%s', ret %d", kSetupCfgSize, _setupCfg, count); } + } else { + warning("Failed to save '%s'", kSetupCfgSize); } } diff --git a/game.h b/game.h index 1b4b6a9..58fc5b0 100644 --- a/game.h +++ b/game.h @@ -42,7 +42,7 @@ enum { kCheatOneHitPlasmaCannon = 1 << 1, kCheatOneHitSpecialPowers = 1 << 2, kCheatWalkOnLava = 1 << 3, - kCheatGateNoCrush = 1 << 4, + kCheatGateNoCrush = 1 << 4 }; struct Game { @@ -404,7 +404,7 @@ struct Game { void mstBoundingBoxClear(MonsterObject1 *m, int dir); int mstBoundingBoxCollides1(int num, int x1, int y1, int x2, int y2) const; int mstBoundingBoxUpdate(int num, int monster1Index, int x1, int y1, int x2, int y2); - int mstBoundingBoxCollides2(int num, int x1, int y1, int x2, int y2) const; + int mstBoundingBoxCollides2(int monster1Index, int x1, int y1, int x2, int y2) const; void mstTaskSetMonster2ScreenPosition(Task *t); int getMstDistance(int y, const AndyShootData *p) const; diff --git a/intern.h b/intern.h index 7e396c5..6615a49 100644 --- a/intern.h +++ b/intern.h @@ -17,8 +17,10 @@ #define le32toh(x) x #define htole16(x) x #define htole32(x) x +static const bool kByteSwapData = false; // no byteswap needed on little endian #else #include +static const bool kByteSwapData = (__BYTE_ORDER == __BIG_ENDIAN); #endif #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/main.cpp b/main.cpp index ec933fe..417f1d0 100644 --- a/main.cpp +++ b/main.cpp @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) { } g->_res->loadSetupDat(); if (_runMenu) { - Menu *m = new Menu(g->_paf, g->_res, g->_video); + Menu *m = new Menu(g, g->_paf, g->_res, g->_video); m->mainLoop(); delete m; } else { diff --git a/menu.cpp b/menu.cpp index adbdbf5..a9b58b3 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1,4 +1,5 @@ +#include "game.h" #include "menu.h" #include "lzw.h" #include "paf.h" @@ -7,22 +8,72 @@ #include "util.h" #include "video.h" -Menu::Menu(PafPlayer *paf, Resource *res, Video *video) - : _paf(paf), _res(res), _video(video) { +Menu::Menu(Game *g, PafPlayer *paf, Resource *res, Video *video) + : _g(g), _paf(paf), _res(res), _video(video) { _titleSprites = 0; _playerSprites = 0; - _titleBitmap = 0; - _playerBitmap = 0; + _titleBitmapData = 0; + _titleBitmapSize = 0; + _playerBitmapData = 0; + _playerBitmapSize = 0; + _soundData = 0; _currentOption = 0; } void Menu::loadData() { _res->loadDatMenuBuffers(); - if (_res->_datHdr.version == 10) { + const int version = _res->_datHdr.version; + const int options = 19; - const uint8_t *ptr = _res->_menuBuffer1; - uint32_t ptrOffset = 0; + const uint8_t *ptr = _res->_menuBuffer1; + uint32_t ptrOffset = 0; + + if (version == 10) { + + _titleSprites = (DatSpritesGroup *)(ptr + ptrOffset); + _titleSprites->size = le32toh(_titleSprites->size); + ptrOffset += sizeof(DatSpritesGroup) + _titleSprites->size; + + _playerSprites = (DatSpritesGroup *)(ptr + ptrOffset); + _playerSprites->size = le32toh(_playerSprites->size); + ptrOffset += sizeof(DatSpritesGroup) + _playerSprites->size; + + _titleBitmapSize = READ_LE_UINT32(ptr + ptrOffset); + _titleBitmapData = ptr + ptrOffset + 8; + ptrOffset += 8 + _titleBitmapSize + 768; + + _playerBitmapSize = READ_LE_UINT32(ptr + ptrOffset); + _playerBitmapData = ptr + ptrOffset + 8; + ptrOffset += 8 + _playerBitmapSize + 768; + + } else if (version == 11) { + + ptr = _res->_menuBuffer1; + uint32_t hdrOffset = 4; + + ptrOffset = 4 + (2 + options) * 8; // pointers to bitmaps + ptrOffset += _res->_datHdr.cutscenesCount * 12; + for (int i = 0; i < 8; ++i) { + ptrOffset += _res->_datHdr.levelCheckpointsCount[i] * 12; + } + ptrOffset += _res->_datHdr.levelsCount * 12; + + _titleBitmapSize = READ_LE_UINT32(ptr + hdrOffset); + hdrOffset += 8; + _titleBitmapData = ptr + ptrOffset; + ptrOffset += _titleBitmapSize + 768; + + _playerBitmapSize = READ_LE_UINT32(ptr + hdrOffset); + hdrOffset += 8; + _playerBitmapData = ptr + ptrOffset; + ptrOffset += _playerBitmapSize + 768; + } + + ptr = _res->_menuBuffer0; + ptrOffset = 0; + + if (version == 11) { _titleSprites = (DatSpritesGroup *)(ptr + ptrOffset); _titleSprites->size = le32toh(_titleSprites->size); @@ -32,15 +83,40 @@ void Menu::loadData() { _playerSprites->size = le32toh(_playerSprites->size); ptrOffset += sizeof(DatSpritesGroup) + _playerSprites->size; - _titleBitmap = (DatBitmap *)(ptr + ptrOffset); - _titleBitmap->size = le32toh(_titleBitmap->size); - ptrOffset += sizeof(DatBitmap) + _titleBitmap->size; + ptrOffset += _res->_datHdr.menusCount * 8; - _playerBitmap = (DatBitmap *)(ptr + ptrOffset); - _playerBitmap->size = le32toh(_playerBitmap->size); - ptrOffset += sizeof(DatBitmap) + _playerBitmap->size; - } else { - warning("Unhandled .dat version %d", _res->_datHdr.version); + const int size = READ_LE_UINT32(ptr + ptrOffset); ptrOffset += 4; + assert((size % (16 * 10)) == 0); + ptrOffset += size; + + _soundData = ptr + ptrOffset; + ptrOffset += _res->_datHdr.soundDataSize; + } +} + +int Menu::getSoundNum(int num) const { + assert((num & 7) == 0); + num /= 8; + if (_soundData) { + const int count = READ_LE_UINT32(_soundData + 4); + const uint8_t *p = _soundData + 8 + count * 8; + for (int i = 0; i < count; ++i) { + const int count2 = READ_LE_UINT32(_soundData + 8 + i * 8 + 4); + if (i == num) { + assert(count2 != 0); + return (int16_t)READ_LE_UINT16(p); + } + p += count2 * 2; + } + assert((p - _soundData) == _res->_datHdr.soundDataSize); + } + return -1; +} + +void Menu::playSound(int num) { + num = getSoundNum(num); + if (num != -1) { + _g->playSound(num, 0, 0, 5); } } @@ -56,33 +132,48 @@ void Menu::drawSprite(const DatSpritesGroup *spriteGroup, uint32_t num) { } } -void Menu::drawBitmap(const DatBitmap *bitmap) { - const uint8_t *data = (const uint8_t *)&bitmap[1]; - const uint32_t uncompressedSize = decodeLZW(data, _video->_frontLayer); +void Menu::drawBitmap(const uint8_t *bitmapData, uint32_t bitmapSize, const DatSpritesGroup *spritesGroup) { + const uint32_t uncompressedSize = decodeLZW(bitmapData, _video->_frontLayer); assert(uncompressedSize == Video::W * Video::H); - const uint8_t *palette = data + bitmap->size; + const uint8_t *palette = bitmapData + bitmapSize; g_system->setPalette(palette, 256, 6); - if (bitmap == _titleBitmap) { - drawSprite(_titleSprites, _currentOption); - } + drawSprite(spritesGroup, _currentOption); g_system->copyRect(0, 0, Video::W, Video::H, _video->_frontLayer, Video::W); g_system->updateScreen(false); } void Menu::mainLoop() { loadData(); + handleTitleScreen(); +} + +void Menu::handleTitleScreen() { while (!g_system->inp.quit) { if (g_system->inp.keyReleased(SYS_INP_UP)) { if (_currentOption > 0) { --_currentOption; } + playSound(0x70); } if (g_system->inp.keyReleased(SYS_INP_DOWN)) { if (_currentOption < 3) { ++_currentOption; } + playSound(0x70); + } + if (g_system->inp.keyReleased(SYS_INP_SHOOT) || g_system->inp.keyReleased(SYS_INP_JUMP)) { + if (_currentOption == 0) { + // assign player + } else if (_currentOption == 1) { + // play + } else if (_currentOption == 2) { + // options + } else if (_currentOption == 3) { + break; + } + playSound(0x78); } - drawBitmap(_titleBitmap); + drawBitmap(_titleBitmapData, _titleBitmapSize, _titleSprites); g_system->processEvents(); g_system->sleep(15); } diff --git a/menu.h b/menu.h index 5d21c8c..401a0d0 100644 --- a/menu.h +++ b/menu.h @@ -4,6 +4,7 @@ #include "intern.h" +struct Game; struct PafPlayer; struct Resource; struct Video; @@ -23,24 +24,32 @@ struct DatBitmap { struct Menu { + Game *_g; PafPlayer *_paf; Resource *_res; Video *_video; DatSpritesGroup *_titleSprites; DatSpritesGroup *_playerSprites; - DatBitmap *_titleBitmap; - DatBitmap *_playerBitmap; + const uint8_t *_titleBitmapData; + uint32_t _titleBitmapSize; + const uint8_t *_playerBitmapData; + uint32_t _playerBitmapSize; + const uint8_t *_soundData; int _currentOption; - Menu(PafPlayer *paf, Resource *res, Video *video); + Menu(Game *g, PafPlayer *paf, Resource *res, Video *video); void loadData(); + int getSoundNum(int num) const; + void playSound(int num); + void drawSprite(const DatSpritesGroup *spriteGroup, uint32_t num); - void drawBitmap(const DatBitmap *bitmap); + void drawBitmap(const uint8_t *bitmapData, uint32_t bitmapSize, const DatSpritesGroup *spritesGroup); void mainLoop(); + void handleTitleScreen(); }; #endif // MENU_H__ diff --git a/monsters.cpp b/monsters.cpp index 36932d9..8edbdbc 100644 --- a/monsters.cpp +++ b/monsters.cpp @@ -437,7 +437,7 @@ void Game::mstBoundingBoxClear(MonsterObject1 *m, int dir) { uint8_t num = m->bboxNum[dir]; if (num < _mstBoundingBoxesCount && _mstBoundingBoxesTable[num].monster1Index == m->monster1Index) { _mstBoundingBoxesTable[num].monster1Index = 0xFF; - int i = num + 1; + int i = num; for (; i < _mstBoundingBoxesCount; ++i) { if (_mstBoundingBoxesTable[i].monster1Index != 0xFF) { break; @@ -492,14 +492,14 @@ int Game::mstBoundingBoxUpdate(int num, int monster1Index, int x1, int y1, int x return num; } -int Game::mstBoundingBoxCollides2(int num, int x1, int y1, int x2, int y2) const { +int Game::mstBoundingBoxCollides2(int monster1Index, int x1, int y1, int x2, int y2) const { for (int i = 0; i < _mstBoundingBoxesCount; ++i) { const MstBoundingBox *p = &_mstBoundingBoxesTable[i]; - if (p->monster1Index == 0xFF || p->monster1Index == num) { + if (p->monster1Index == 0xFF || p->monster1Index == monster1Index) { continue; } - if (p->monster1Index == 0xFE) { - if (_monsterObjects1Table[num].monsterInfos[944] != 15) { + if (p->monster1Index == 0xFE) { // Andy + if (_monsterObjects1Table[monster1Index].monsterInfos[944] != 15) { continue; } } @@ -655,7 +655,7 @@ void Game::mstTaskUpdateScreenPosition(Task *t) { const uint8_t *ptr = m->monsterInfos; if (ptr[946] & 4) { - const uint8_t *ptr1 = ptr + (o->flags0 & 255) * 28; // va + const uint8_t *ptr1 = ptr + (o->flags0 & 0xFF) * 28; // va if (ptr1[0xE] != 0) { _mstTemp_x1 = m->xMstPos + (int8_t)ptr1[0xC]; _mstTemp_y1 = m->yMstPos + (int8_t)ptr1[0xD]; @@ -1482,8 +1482,8 @@ void Game::mstMonster1MoveTowardsGoal1(MonsterObject1 *m) { const uint8_t *p = m->monsterInfos; const uint32_t indexWalkBox = walkNode->walkBox; const MstWalkBox *m34 = &_res->_mstWalkBoxData[indexWalkBox]; - const int w = READ_LE_UINT32(p + 904); - const int h = READ_LE_UINT32(p + 908); + const int w = (int32_t)READ_LE_UINT32(p + 904); + const int h = (int32_t)READ_LE_UINT32(p + 908); debug(kDebug_MONSTER, "mstMonster1MoveTowardsGoal1 m %p pos %d,%d [%d,%d,%d,%d]", m, m->xMstPos, m->yMstPos, m34->left, m34->top, m34->right, m34->bottom); if (!rect_contains(m34->left - w, m34->top - h, m34->right + w, m34->bottom + h, m->xMstPos, m->yMstPos)) { mstMonster1UpdateWalkPath(m); @@ -1542,7 +1542,7 @@ void Game::mstMonster1MoveTowardsGoal1(MonsterObject1 *m) { } MstBehaviorState *behaviorState = m->behaviorState; MstWalkPath *walkPath = &_res->_mstWalkPathData[behaviorState->walkPath]; - uint8_t _cl = m->bboxNum[2]; + uint8_t _cl = m->walkBoxNum; if (m->unkBC != _xMstPos1 || m->unkC0 != _yMstPos1) { bool inWalkBox = false; if (_cl < walkPath->count) { @@ -1576,7 +1576,7 @@ void Game::mstMonster1MoveTowardsGoal1(MonsterObject1 *m) { } else { _cl = _al; } - m->bboxNum[2] = _cl; + m->walkBoxNum = _cl; m->unkBC = -1; m->unkC0 = -1; } @@ -1602,14 +1602,12 @@ void Game::mstMonster1MoveTowardsGoal1(MonsterObject1 *m) { const uint8_t *p = m->monsterInfos; const int w = (int32_t)READ_LE_UINT32(p + 904); const int h = (int32_t)READ_LE_UINT32(p + 908); - while (_xMstPos1 >= walkNode->coords[1][vf] + w) { - if (_xMstPos1 > walkNode->coords[0][vf] - w) { - break; - } - if (_yMstPos1 < walkNode->coords[3][vf] + h) { - break; - } - if (_yMstPos1 > walkNode->coords[2][vf] - h) { + while (1) { + const int x1 = walkNode->coords[1][vf] + w; // left + const int x2 = walkNode->coords[0][vf] - w; // right + const int y1 = walkNode->coords[3][vf] + h; // top + const int y2 = walkNode->coords[2][vf] - h; // bottom + if (!rect_contains(x1, y1, x2, y2, _xMstPos1, _yMstPos1)) { break; } int var1C; @@ -1628,6 +1626,7 @@ void Game::mstMonster1MoveTowardsGoal1(MonsterObject1 *m) { break; } const uint32_t indexWalkNode = walkNode->neighborWalkNode[var1C]; + assert(indexWalkNode != kNone && indexWalkNode < walkPath->count); walkNode = &walkPath->data[indexWalkNode]; if (walkNode == &walkPath->data[_cl]) { m->targetDirectionMask = 0xFF; @@ -1742,7 +1741,7 @@ void Game::mstMonster1MoveTowardsGoal2(MonsterObject1 *m) { } const int num = var20 + var8 * 5; const int dirMask = _mstLut3[num]; - if (_mstLut1[dirMask] == m->bboxNum[3]) { + if (_mstLut1[dirMask] == m->unkAB) { continue; } int vc, va; @@ -1782,8 +1781,8 @@ void Game::mstMonster1MoveTowardsGoal2(MonsterObject1 *m) { continue; } } - const int w = READ_LE_UINT32(m->monsterInfos + 904); - const int h = READ_LE_UINT32(m->monsterInfos + 908); + const int w = (int32_t)READ_LE_UINT32(m->monsterInfos + 904); + const int h = (int32_t)READ_LE_UINT32(m->monsterInfos + 908); if (!rect_contains(m34->left - w, m34->top - h, m34->right + w, m34->bottom + h, xPos, yPos)) { const uint32_t indexWalkPath = m->behaviorState->walkPath; MstWalkPath *walkPath = &_res->_mstWalkPathData[indexWalkPath]; @@ -1799,9 +1798,10 @@ void Game::mstMonster1MoveTowardsGoal2(MonsterObject1 *m) { m->targetLevelPos_y = yPos; p = _res->_mstMonsterInfos + m->m49Unk1->offsetMonsterInfo; if (p[0xE] != 0) { + bboxIndex = m->monster1Index; const int x1 = m->xMstPos + (int8_t)p[0xC]; - const int x2 = x1 + p[0xE] - 1; const int y1 = m->yMstPos + (int8_t)p[0xD]; + const int x2 = x1 + p[0xE] - 1; const int y2 = y1 + p[0xF] - 1; const int r = mstBoundingBoxCollides2(m->monster1Index, x1, y1, x2, y2); if (r != 0) { @@ -1818,17 +1818,12 @@ void Game::mstMonster1MoveTowardsGoal2(MonsterObject1 *m) { } m->goalDirectionMask = dirMask; if (var20 == 0) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; } else { - uint8_t n = _mstLut1[dirMask]; - if (n < 4) { - n += 4; - } else { - n -= 4; - } - m->bboxNum[3] = n; + const uint8_t n = _mstLut1[dirMask]; + m->unkAB = (n < 4) ? n + 4 : n - 4; } - // return; // TODO: re-enable when m->levelBounds_x1/x2/y1/y2 are corrected + return; } m->task->flags |= 0x80; m->goalDirectionMask = 0; @@ -1856,7 +1851,7 @@ int Game::mstTaskStopMonster1(Task *t, MonsterObject1 *m) { } int Game::mstTaskUpdatePositionActionDirection(Task *t, MonsterObject1 *m) { - if ((m->monsterInfos[946] & 4) == 0 || (_mstLut1[m->goalDirectionMask] & 1) != 0) { + if ((m->monsterInfos[946] & 4) == 0 && (_mstLut1[m->goalDirectionMask] & 1) != 0) { if (_xMstPos2 < m->m49->unk14) { m->goalDirectionMask &= ~kDirectionKeyMaskHorizontal; } @@ -1915,7 +1910,6 @@ int Game::mstTaskUpdatePositionActionDirection(Task *t, MonsterObject1 *m) { if (m->targetDirectionMask != 0xFF) { _xMstPos2 = 0; } - } } else { if (_yMstPos2 < m->m49Unk1->unkB) { @@ -2304,7 +2298,7 @@ int Game::mstUpdateTaskMonsterObject1(Task *t) { MonsterObject1 *m = t->monster1; MonsterObject1 *_mstCurrentMonster1 = m; LvlObject *o = m->o16; - const int num = o->flags0 & 255; + const int num = o->flags0 & 0xFF; const uint8_t *ptr = m->monsterInfos + num * 28; // vb int8_t a = ptr[6]; if (a != 0) { @@ -2660,7 +2654,7 @@ int Game::mstUpdateTaskMonsterObject1(Task *t) { } if ((m->monsterInfos[946] & 2) == 0) { MstWalkNode *walkPath = m->walkNode; - int vf = READ_LE_UINT32(m->monsterInfos + 904); + int vf = (int32_t)READ_LE_UINT32(m->monsterInfos + 904); int vb = MAX(m->goalPosBounds_x1, walkPath->coords[1][1] + vf); int va = MIN(m->goalPosBounds_x2, walkPath->coords[0][1] - vf); const uint32_t indexUnk36 = walkPath->movingBoundsIndex2; @@ -3134,9 +3128,9 @@ int Game::mstTaskSetActionDirection(Task *t, int num, int delay) { } else if ((o->directionKeyMask & kDirectionKeyMaskDown) == 0) { va = 0; } - const int x1 = m->xMstPos + (int8_t)p[0xC]; // vf + const int x1 = m->xMstPos + (int8_t)p[0xC]; + const int y1 = m->yMstPos + (int8_t)p[0xD]; const int x2 = x1 + p[0xE] - 1; - const int y1 = m->yMstPos + (int8_t)p[0xD]; // ve const int y2 = y1 + p[0xF] - 1; if ((var8 & 0xE0) != 0x60 && mstBoundingBoxCollides2(m->monster1Index, x1, y1, x2, y2) != 0) { t->flags |= 0x80; @@ -4489,15 +4483,11 @@ int Game::mstTask_main(Task *t) { case 226: { // 68 - add_monster_group const int num = READ_LE_UINT16(p + 2); const MstOp226Data *m226Data = &_res->_mstOp226Data[num]; - int vf = _res->_mstPointOffsets[_currentScreen].xOffset; + int xPos = _res->_mstPointOffsets[_currentScreen].xOffset; int yPos = _res->_mstPointOffsets[_currentScreen].yOffset; int countRight = 0; // var1C int countLeft = 0; // var8 - int vc = m226Data->unk4 * 256; - int vd = vf + 256; - vf -= vc; - vd += vc; - int var20 = vd; + int xOffset = m226Data->unk4 * 256; for (int i = 0; i < kMaxMonsterObjects1; ++i) { MonsterObject1 *m = &_monsterObjects1Table[i]; if (!m->m46) { @@ -4506,10 +4496,7 @@ int Game::mstTask_main(Task *t) { if (m->monsterInfos[944] != _res->_mstMonsterInfos[m226Data->unk0 * kMonsterInfoDataSize + 944]) { continue; } - if (m->xMstPos < vf || m->xMstPos > var20) { - continue; - } - if (m->yMstPos < yPos || m->yMstPos > yPos + 192) { + if (!rect_contains(xPos - xOffset, yPos, xPos + xOffset + 256, yPos + 192, m->xMstPos, m->yMstPos)) { continue; } if (_mstAndyLevelPosX > m->xMstPos) { @@ -4523,7 +4510,7 @@ int Game::mstTask_main(Task *t) { if (total >= m226Data->unk3) { break; } - vc = m226Data->unk3 - total; + int vc = m226Data->unk3 - total; int countType1 = m226Data->unk1; // vf if (countLeft >= countType1) { @@ -4567,7 +4554,7 @@ int Game::mstTask_main(Task *t) { const int a = getTaskVar(t, m->indexVar1, m->maskVars & 15); const int b = getTaskVar(t, m->indexVar2, m->maskVars >> 4); if (compareOp(m->compare, a, b)) { - assert(m->codeData != kNone); + assert(m->codeData < _res->_mstHdr.codeSize); p = _res->_mstCodeData + m->codeData * 4 - 4; } } @@ -4579,13 +4566,13 @@ int Game::mstTask_main(Task *t) { const int a = getTaskFlag(t, m->indexVar1, m->maskVars & 15); const int b = getTaskFlag(t, m->indexVar2, m->maskVars >> 4); if (compareOp(m->compare, a, b)) { - assert(m->codeData != kNone); + assert(m->codeData < _res->_mstHdr.codeSize); p = _res->_mstCodeData + m->codeData * 4 - 4; } } break; case 231: - case 232: { // 71 + case 232: { // 71 - compare_flags_monster const int num = READ_LE_UINT16(p + 2); const MstOp234Data *m = &_res->_mstOp234Data[num]; const int a = getTaskFlag(t, m->indexVar1, m->maskVars & 15); @@ -4593,10 +4580,9 @@ int Game::mstTask_main(Task *t) { if (compareOp(m->compare, a, b)) { if (p[0] == 231) { LvlObject *o = 0; - MonsterObject1 *m = t->monster1; - if (m) { - if ((m->flagsA6 & 2) == 0) { - o = m->o16; + if (t->monster1) { + if ((t->monster1->flagsA6 & 2) == 0) { + o = t->monster1->o16; } } else if (t->monster2) { o = t->monster2->o; @@ -4612,10 +4598,9 @@ int Game::mstTask_main(Task *t) { } else { if (p[0] == 232) { LvlObject *o = 0; - MonsterObject1 *m = t->monster1; - if (m) { - if ((m->flagsA6 & 2) == 0) { - o = m->o16; + if (t->monster1) { + if ((t->monster1->flagsA6 & 2) == 0) { + o = t->monster1->o16; } } else if (t->monster2) { o = t->monster2->o; @@ -4632,7 +4617,7 @@ int Game::mstTask_main(Task *t) { } break; case 233: - case 234: { // 72 + case 234: { // 72 - compare_vars_monster const int num = READ_LE_UINT16(p + 2); const MstOp234Data *m = &_res->_mstOp234Data[num]; const int a = getTaskVar(t, m->indexVar1, m->maskVars & 15); @@ -4820,7 +4805,11 @@ int Game::mstTask_main(Task *t) { p = t->codeData; } ++_runTaskOpcodesCount; - } while (_runTaskOpcodesCount <= 128 && ret == 0); + if (_runTaskOpcodesCount >= 128) { // prevent infinite loop + warning("Stopping task %p, counter %d", t, _runTaskOpcodesCount); + break; + } + } while (ret == 0); if (t->codeData) { t->codeData = p; } @@ -4833,7 +4822,7 @@ void Game::mstOp26_removeMstTaskScreen(Task **tasksList, int screenNum) { MonsterObject1 *m = current->monster1; // vc Task *next = current->nextPtr; // ve if (m && m->o16->screenNum == screenNum) { - if (_mstActionNum != -1 && (m->flagsA5 & 8) != 0 && m->action != 0) { + if (_mstActionNum != -1 && (m->flagsA5 & 8) != 0 && m->action) { mstMonster1ClearChasingMonster(m); } if (m->monsterInfos[946] & 4) { @@ -4862,7 +4851,7 @@ void Game::mstOp27_removeMstTaskScreenType(Task **tasksList, int screenNum, int MonsterObject1 *m = current->monster1; Task *next = current->nextPtr; if (m && m->o16->screenNum == screenNum && (m->monsterInfos[944] & 0x7F) == type) { - if (_mstActionNum != -1 && (m->flagsA5 & 8) != 0 && m->action != 0) { + if (_mstActionNum != -1 && (m->flagsA5 & 8) != 0 && m->action) { mstMonster1ClearChasingMonster(m); } if (m->monsterInfos[946] & 4) { @@ -5008,7 +4997,7 @@ int Game::mstOp49_setMovingBounds(int a, int b, int c, int d, int screen, Task * m->goalPos_x2 = m->goalDistance_x2; m->goalPos_y1 = m->goalDistance_y1; m->goalPos_y2 = m->goalDistance_y2; - m->bboxNum[2] = 0xFF; + m->walkBoxNum = 0xFF; m->unkC0 = -1; m->unkBC = -1; m->targetDirectionMask = 0xFF; @@ -5020,7 +5009,7 @@ int Game::mstOp49_setMovingBounds(int a, int b, int c, int d, int screen, Task * m->goalDistance_x1 = m->goalPos_x1 = m->goalDistance_x2 = m->goalPos_x2 = m->xMstPos; } if (m->monsterInfos[946] & 4) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); @@ -5078,22 +5067,21 @@ int Game::mstOp49_setMovingBounds(int a, int b, int c, int d, int screen, Task * } } } - const uint8_t *p = _res->_mstMonsterInfos + m->m49Unk1->offsetMonsterInfo; if ((m->monsterInfos[946] & 4) != 0 && p[0xE] != 0 && m->bboxNum[0] == 0xFF) { const int x1 = m->xMstPos + (int8_t)p[0xC]; - const int x2 = x1 + p[0xE] - 1; const int y1 = m->yMstPos + (int8_t)p[0xD]; + const int x2 = x1 + p[0xE] - 1; const int y2 = y1 + p[0xF] - 1; if (mstBoundingBoxCollides2(m->monster1Index, x1, y1, x2, y2) != 0) { m->indexUnk49Unk1 = 0; m->m49Unk1 = &m->m49->data1[0]; - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); if (p[0xE] != 0) { - t->flags &= ~0x80; + t->flags |= 0x80; mstTaskResetMonster1WalkPath(t); return 0; } @@ -5111,7 +5099,7 @@ int Game::mstOp49_setMovingBounds(int a, int b, int c, int d, int screen, Task * mstMonster1MoveTowardsGoal1(m); } else if (t->run == &Game::mstTask_monsterWait9) { mstMonster1MoveTowardsGoal2(m); - } else { + } else { // &Game::mstTask_monsterWait7 mstMonster1MoveTowardsGoal1(m); } const MstMovingBoundsUnk1 *m49Unk1 = m->m49Unk1; @@ -5170,9 +5158,8 @@ void Game::mstOp52() { return; } MstMonsterAction *m48 = &_res->_mstMonsterActionData[_mstActionNum]; - int j = 0; for (int i = 0; i < m48->areaCount; ++i) { - MstMonsterArea *m48Area = &m48->area[j]; + MstMonsterArea *m48Area = &m48->area[i]; const uint8_t num = m48Area->data->monster1Index; if (num != 0xFF) { assert(num < kMaxMonsterObjects1); @@ -5181,8 +5168,8 @@ void Game::mstOp52() { if ((m->flagsA5 & 0x70) == 0) { assert(m->task->monster1 == m); Task *t = m->task; - const int a = (m->o16->flags0 & 255) * 28; - if (m->monsterInfos[a] != 0) { + const int num = m->o16->flags0 & 0xFF; + if (m->monsterInfos[num * 28] != 0) { if (t->run != &Game::mstTask_monsterWait1 && t->run != &Game::mstTask_monsterWait4 && t->run != &Game::mstTask_monsterWait2 && t->run != &Game::mstTask_monsterWait3 && t->run != &Game::mstTask_monsterWait5 && t->run != &Game::mstTask_monsterWait6 && t->run != &Game::mstTask_monsterWait7 && t->run != &Game::mstTask_monsterWait8 && t->run != &Game::mstTask_monsterWait9 && t->run != &Game::mstTask_monsterWait10) { m->flagsA5 = (m->flagsA5 & ~0xF) | 6; mstTaskInitMonster1Type2(m->task, 1); @@ -5197,7 +5184,6 @@ void Game::mstOp52() { } } } - ++j; } _mstActionNum = -1; } @@ -5218,7 +5204,6 @@ bool Game::mstHasMonsterInRange(const MstMonsterAction *m48, uint8_t flag) { int var24 = 0; //int var28 = 0; - //int var18 = 0; int vf = 0; for (int i = 0; i < m48->areaCount; ++i) { const MstMonsterArea *m12 = &m48->area[i]; @@ -5311,13 +5296,11 @@ bool Game::mstHasMonsterInRange(const MstMonsterAction *m48, uint8_t flag) { var4C = vf; goto l1; } - //var18 += 12; //++var28; } //var28 = vf; - //int var20 = 0; for (int i = vf; i < m48->areaCount; ++i) { - MstMonsterArea *m12 = &m48->area[i]; // var20 + MstMonsterArea *m12 = &m48->area[i]; assert(m12->count == 1); MstMonsterAreaAction *m12u4 = m12->data; if (m12->unk0 == 0) { @@ -5402,7 +5385,6 @@ bool Game::mstHasMonsterInRange(const MstMonsterAction *m48, uint8_t flag) { goto l2; } } - //var20 += 12; //++var28; } return var24 != 0; @@ -5848,20 +5830,15 @@ int Game::mstOp56_specialAction(Task *t, int code, int num) { screenNum = _res->_mstHdr.screensCount - 1; } const int x = _res->_mstPointOffsets[screenNum].xOffset; - const int y = _res->_mstPointOffsets[screenNum].yOffset; // vd - const int xOffset = op204Data->arg3 * 256; // va - const int x1 = x - xOffset; // ve - const int x2 = x + xOffset; // vf + const int y = _res->_mstPointOffsets[screenNum].yOffset; + const int xOffset = op204Data->arg3 * 256; int count = 0; for (int i = 0; i < kMaxMonsterObjects1; ++i) { const MonsterObject1 *m = &_monsterObjects1Table[i]; if (!m->m46) { continue; } - if (m->xMstPos < x1 || m->xMstPos > x2) { - continue; - } - if (m->yMstPos < y || m->yMstPos > y + 192) { + if (!rect_contains(x - xOffset, y, x + xOffset + 256, y + 192, m->xMstPos, m->yMstPos)) { continue; } const int num = op204Data->arg1; @@ -6275,8 +6252,8 @@ void Game::mstResetCollisionTable() { if ((_bl & 0xB0) != 0) { continue; } - const uint8_t *p = m->monsterInfos + (m->o16->flags0 & 255) * 28; - if (p[0] != 0) { + const int num = m->o16->flags0 & 0xFF; + if (m->monsterInfos[num * 28] != 0) { continue; } if (m->task->run == &Game::mstTask_monsterWait4) { @@ -6301,6 +6278,7 @@ void Game::mstResetCollisionTable() { } } +// resume bytecode execution void Game::mstTaskRestart(Task *t) { t->run = &Game::mstTask_main; LvlObject *o = 0; @@ -6353,7 +6331,7 @@ int Game::mstTaskInitMonster1Type1(Task *t) { if (m->monsterInfos[946] & 2) { m->unkC0 = -1; m->unkBC = -1; - m->bboxNum[2] = 0xFF; + m->walkBoxNum = 0xFF; m->targetDirectionMask = 0xFF; y = m34->top; if (m->yMstPos < m34->top || m->yMstPos > m34->bottom) { @@ -6362,7 +6340,7 @@ int Game::mstTaskInitMonster1Type1(Task *t) { } x = m34->left; if (m->monsterInfos[946] & 4) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); @@ -6455,18 +6433,18 @@ int Game::mstTaskInitMonster1Type1(Task *t) { const uint8_t *p = _res->_mstMonsterInfos + m->m49Unk1->offsetMonsterInfo; if ((m->monsterInfos[946] & 4) != 0 && p[0xE] != 0 && m->bboxNum[0] == 0xFF) { const int x1 = m->xMstPos + (int8_t)p[0xC]; - const int x2 = x1 + p[0xE] - 1; const int y1 = m->yMstPos + (int8_t)p[0xD]; + const int x2 = x1 + p[0xE] - 1; const int y2 = y1 + p[0xF] - 1; if (mstBoundingBoxCollides2(m->monster1Index, x1, y1, x2, y2) != 0) { m->indexUnk49Unk1 = 0; m->m49Unk1 = &m->m49->data1[0]; - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); if (p[0xE] != 0) { - t->flags &= ~0x80; + t->flags |= 0x80; mstTaskResetMonster1WalkPath(t); return 0; } @@ -6478,7 +6456,7 @@ int Game::mstTaskInitMonster1Type1(Task *t) { m->indexUnk49Unk1 = m->m49->count1 - 1; m->m49Unk1 = &m->m49->data1[m->indexUnk49Unk1]; if (m->monsterInfos[946] & 4) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); @@ -6527,7 +6505,7 @@ int Game::mstTaskInitMonster1Type2(Task *t, int flag) { m->goalScreenNum = 0xFD; m->unkC0 = -1; m->unkBC = -1; - m->bboxNum[2] = 0xFF; + m->walkBoxNum = 0xFF; m->targetDirectionMask = 0xFF; if (mstSetCurrentPos(m, m->xMstPos, m->yMstPos)) { mstTaskResetMonster1WalkPath(t); @@ -6538,7 +6516,7 @@ int Game::mstTaskInitMonster1Type2(Task *t, int flag) { if (p[946] & 2) { m->unkE4 = 255; if (p[946] & 4) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); @@ -6619,18 +6597,18 @@ int Game::mstTaskInitMonster1Type2(Task *t, int flag) { const uint8_t *p = _res->_mstMonsterInfos + m->m49Unk1->offsetMonsterInfo; if ((m->monsterInfos[946] & 4) != 0 && p[0xE] != 0 && m->bboxNum[0] == 0xFF) { const int x1 = m->xMstPos + (int8_t)p[0xC]; - const int x2 = x1 + p[0xE] - 1; const int y1 = m->yMstPos + (int8_t)p[0xD]; + const int x2 = x1 + p[0xE] - 1; const int y2 = y1 + p[0xF] - 1; if (mstBoundingBoxCollides2(m->monster1Index, x1, y1, x2, y2) != 0) { m->indexUnk49Unk1 = 0; m->m49Unk1 = &m->m49->data1[0]; - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); if (p[0xE] != 0) { - t->flags &= ~0x80; + t->flags |= 0x80; mstTaskResetMonster1WalkPath(t); return 0; } @@ -6642,7 +6620,7 @@ int Game::mstTaskInitMonster1Type2(Task *t, int flag) { m->indexUnk49Unk1 = m->m49->count1 - 1; m->m49Unk1 = &m->m49->data1[m->indexUnk49Unk1]; if (m->monsterInfos[946] & 4) { - m->bboxNum[3] = 0xFF; + m->unkAB = 0xFF; m->targetLevelPos_x = -1; m->targetLevelPos_y = -1; mstBoundingBoxClear(m, 1); @@ -6944,17 +6922,7 @@ int Game::mstTask_wait2(Task *t) { debug(kDebug_MONSTER, "mstTask_wait2 t %p count %d", t, t->arg1); --t->arg1; if (t->arg1 == 0) { - t->run = &Game::mstTask_main; - LvlObject *o = 0; - if (t->monster1) { - o = t->monster1->o16; - } else if (t->monster2) { - o = t->monster2->o; - } - if (o) { - o->actionKeyMask = 0; - o->directionKeyMask = 0; - } + mstTaskRestart(t); return 0; } return 1; @@ -6965,17 +6933,7 @@ int Game::mstTask_wait3(Task *t) { if (getTaskFlag(t, t->arg2, t->arg1) == 0) { return 1; } - t->run = &Game::mstTask_main; - LvlObject *o = 0; - if (t->monster1) { - o = t->monster1->o16; - } else if (t->monster2) { - o = t->monster2->o; - } - if (o) { - o->actionKeyMask = 0; - o->directionKeyMask = 0; - } + mstTaskRestart(t); return 0; } @@ -6985,24 +6943,12 @@ int Game::mstTask_idle(Task *t) { } int Game::mstTask_mstOp231(Task *t) { + debug(kDebug_MONSTER, "mstTask_mstOp231 t %p", t); const MstOp234Data *m = &_res->_mstOp234Data[t->arg2]; const int a = getTaskFlag(t, m->indexVar1, m->maskVars & 15); const int b = getTaskFlag(t, m->indexVar2, m->maskVars >> 4); if (!compareOp(m->compare, a, b)) { - LvlObject *o = 0; - MonsterObject1 *m = t->monster1; - if (m) { - if ((m->flagsA6 & 2) == 0) { - o = m->o16; - } - } else if (t->monster2) { - o = t->monster2->o; - } - if (o) { - o->actionKeyMask = 0; - o->directionKeyMask = 0; - } - t->run = &Game::mstTask_main; + mstTaskRestart(t); return 0; } return 1; @@ -7020,17 +6966,7 @@ int Game::mstTask_mstOp233(Task *t) { const int a = getTaskVar(t, m->indexVar1, m->maskVars & 15); const int b = getTaskVar(t, m->indexVar2, m->maskVars >> 4); if (!compareOp(m->compare, a, b)) { - t->run = &Game::mstTask_main; - LvlObject *o = 0; - if (t->monster1) { - o = t->monster1->o16; - } else if (t->monster2) { - o = t->monster2->o; - } - if (o) { - o->actionKeyMask = 0; - o->directionKeyMask = 0; - } + mstTaskRestart(t); return 0; } return 1; @@ -7042,17 +6978,7 @@ int Game::mstTask_mstOp234(Task *t) { const int a = getTaskVar(t, m->indexVar1, m->maskVars & 15); const int b = getTaskVar(t, m->indexVar2, m->maskVars >> 4); if (compareOp(m->compare, a, b)) { - t->run = &Game::mstTask_main; - LvlObject *o = 0; - if (t->monster1) { - o = t->monster1->o16; - } else if (t->monster2) { - o = t->monster2->o; - } - if (o) { - o->actionKeyMask = 0; - o->directionKeyMask = 0; - } + mstTaskRestart(t); return 0; } return 1; diff --git a/resource.cpp b/resource.cpp index 4b7e0a1..8c1cef4 100644 --- a/resource.cpp +++ b/resource.cpp @@ -152,7 +152,7 @@ void Resource::loadSetupDat() { _datHdr.levelCheckpointsCount[i] = _datFile->readUint32(); } _datHdr.yesNoQuitImage = _datFile->readUint32(); - _datFile->readUint32(); // 0x44 + _datHdr.soundDataSize = _datFile->readUint32(); _datHdr.loadingImageSize = _datFile->readUint32(); const int hintsCount = (_datHdr.version == 11) ? 46 : 20; for (int i = 0; i < hintsCount; ++i) { @@ -195,7 +195,6 @@ void Resource::loadSetupDat() { _menuBuffersOffset = _datHdr.hintsImageOffsetTable[_datHdr.yesNoQuitImage + 2]; } - bool Resource::loadDatHintImage(int num, uint8_t *dst, uint8_t *pal) { if (!_isPsx) { const int offset = _datHdr.hintsImageOffsetTable[num]; @@ -347,37 +346,44 @@ static uint32_t resFixPointersLevelData0x2988(uint8_t *src, uint8_t *ptr, LvlObj assert(src == base + kLvlAnimHdrOffset); dat->animsInfoData = base; -#ifdef __BYTE_ORDER - if (__BYTE_ORDER == __BIG_ENDIAN) { + dat->refCount = 0xFF; + dat->framesData = (framesDataOffset == 0) ? 0 : base + framesDataOffset; + dat->hotspotsData = (hotspotsDataOffset == 0) ? 0 : base + hotspotsDataOffset; + dat->movesData = (movesDataOffset == 0) ? 0 : base + movesDataOffset; + dat->coordsData = (coordsDataOffset == 0) ? 0 : base + coordsDataOffset; + if (kByteSwapData) { for (int i = 0; i < dat->hotspotsCount; ++i) { LvlAnimHeader *ah = ((LvlAnimHeader *)(base + kLvlAnimHdrOffset)) + i; ah->unk0 = le16toh(ah->unk0); ah->seqOffset = le32toh(ah->seqOffset); - if (ah->seqOffset != 0) { - for (int seq = 0; seq < ah->seqCount; ++seq) { - LvlAnimSeqHeader *ash = ((LvlAnimSeqHeader *)(base + ah->seqOffset)) + seq; - ash->firstFrame = le16toh(ash->firstFrame); - ash->unk2 = le16toh(ash->unk2); - ash->sound = le16toh(ash->sound); - ash->flags0 = le16toh(ash->flags0); - ash->flags1 = le16toh(ash->flags1); - ash->unkE = le16toh(ash->unkE); - ash->offset = le32toh(ash->offset); - if (ash->offset != 0) { - LvlAnimSeqFrameHeader *asfh = (LvlAnimSeqFrameHeader *)(base + ash->offset); - asfh->move = le16toh(asfh->move); - asfh->anim = le16toh(asfh->anim); - } + if (ah->seqOffset == 0) { + continue; + } + for (int j = 0; j < ah->seqCount; ++j) { + LvlAnimSeqHeader *ash = ((LvlAnimSeqHeader *)(base + ah->seqOffset)) + j; + ash->firstFrame = le16toh(ash->firstFrame); + ash->unk2 = le16toh(ash->unk2); + ash->sound = le16toh(ash->sound); + ash->flags0 = le16toh(ash->flags0); + ash->flags1 = le16toh(ash->flags1); + ash->unkE = le16toh(ash->unkE); + ash->offset = le32toh(ash->offset); + if (ash->offset == 0) { + continue; + } + for (int k = 0; k < ash->count; ++k) { + LvlAnimSeqFrameHeader *asfh = ((LvlAnimSeqFrameHeader *)(base + ash->offset)) + k; + asfh->move = le16toh(asfh->move); + asfh->anim = le16toh(asfh->anim); } } } + for (int i = 0; i < dat->movesCount; ++i) { + LvlSprMoveData *smd = ((LvlSprMoveData *)dat->movesData) + i; + smd->op3 = le16toh(smd->op3); + smd->op4 = le16toh(smd->op4); + } } -#endif - dat->refCount = 0xFF; - dat->framesData = (framesDataOffset == 0) ? 0 : base + framesDataOffset; - dat->hotspotsData = (hotspotsDataOffset == 0) ? 0 : base + hotspotsDataOffset; - dat->movesData = (movesDataOffset == 0) ? 0 : base + movesDataOffset; - dat->coordsData = (coordsDataOffset == 0) ? 0 : base + coordsDataOffset; dat->framesOffsetsTable = ptr; if (dat->coordsData) { @@ -963,7 +969,12 @@ void Resource::loadSssData(File *fp, const uint32_t baseOffset) { if (bufferSize != bytesRead) { error("Unexpected number of bytes read %d (%d)", bytesRead, bufferSize); } - // preload PCM (_sssHdr.preloadPcmCount) + // preload PCM (_sssHdr.preloadPcmCount or setup.dat) + if (fp == _datFile) { + for (int i = 0; i < _sssHdr.pcmCount; ++i) { + loadSssPcm(fp, &_sssPcmTable[i]); + } + } for (int i = 0; i < _sssHdr.banksDataCount; ++i) { uint32_t mask = 1; _sssDataUnk6[i].mask = 0; @@ -1042,7 +1053,9 @@ void Resource::loadSssPcm(File *fp, SssPcm *pcm) { return; } pcm->ptr = p; - fp->seek(pcm->offset, SEEK_SET); + if (fp != _datFile || pcm == &_sssPcmTable[0]) { + fp->seek(pcm->offset, SEEK_SET); + } for (int i = 0; i < pcm->strideCount; ++i) { uint8_t samples[256 * sizeof(int16_t)]; fp->read(samples, sizeof(samples)); @@ -1501,6 +1514,8 @@ void Resource::loadMstData(File *fp) { _mstMovingBoundsData[i].indexData = (uint8_t *)malloc(_mstMovingBoundsData[i].indexDataCount); fp->read(_mstMovingBoundsData[i].indexData, _mstMovingBoundsData[i].indexDataCount); bytesRead += _mstMovingBoundsData[i].indexDataCount; + } else { + _mstMovingBoundsData[i].indexData = 0; } } diff --git a/resource.h b/resource.h index 96f202b..fabf425 100644 --- a/resource.h +++ b/resource.h @@ -20,6 +20,7 @@ struct DatHdr { uint32_t levelsCount; // 0x1C uint32_t levelCheckpointsCount[8]; // 0x20..0x3C int yesNoQuitImage; // 0x40 + int soundDataSize; // 0x44 int loadingImageSize; // 0x48 uint32_t hintsImageOffsetTable[46]; uint32_t hintsImageSizeTable[46]; diff --git a/sound.cpp b/sound.cpp index 6ba1688..130b9e9 100644 --- a/sound.cpp +++ b/sound.cpp @@ -7,7 +7,7 @@ enum { kFlagPlaying = 1 << 0, kFlagPaused = 1 << 1, // no PCM - kFlagNoCode = 1 << 2, // no bytecode + kFlagNoCode = 1 << 2 // no bytecode }; static const bool kLimitSounds = false; // limit the number of active playing sounds diff --git a/system_sdl2.cpp b/system_sdl2.cpp index 786175b..a9c01dd 100644 --- a/system_sdl2.cpp +++ b/system_sdl2.cpp @@ -14,7 +14,6 @@ static const char *kIconBmp = "icon.bmp"; static int _scalerMultiplier = 3; static const Scaler *_scaler = &scaler_xbr; -static const float _gamma = 1.f; static const int _pixelFormat = SDL_PIXELFORMAT_RGB888; @@ -36,7 +35,7 @@ struct System_SDL2 : System { enum { kJoystickCommitValue = 3200, kKeyMappingsSize = 20, - kAudioHz = 22050, + kAudioHz = 22050 }; uint8_t *_offscreenLut; @@ -176,6 +175,7 @@ void System_SDL2::destroy() { SDL_JoystickClose(_joystick); _joystick = 0; } + SDL_Quit(); } template diff --git a/util.h b/util.h index e1e1857..129f590 100644 --- a/util.h +++ b/util.h @@ -15,7 +15,7 @@ enum { kDebug_SOUND = 1 << 3, kDebug_PAF = 1 << 4, kDebug_MONSTER = 1 << 5, - kDebug_SWITCHES = 1 << 6, // 'lar1' and 'lar2' levels + kDebug_SWITCHES = 1 << 6 // 'lar1' and 'lar2' levels }; extern int g_debugMask;