1 2 /* 3 * REminiscence - Flashback interpreter 4 * Copyright (C) 2005-2019 Gregory Montoir (cyx@users.sourceforge.net) 5 */ 6 7 #ifndef GAME_H__ 8 #define GAME_H__ 9 10 #include "intern.h" 11 #include "cutscene.h" 12 #include "menu.h" 13 #include "mixer.h" 14 #include "resource.h" 15 #include "seq_player.h" 16 #include "video.h" 17 18 struct File; 19 struct FileSystem; 20 struct SystemStub; 21 22 enum { 23 kCheatOneHitKill = 1 << 0, 24 kCheatNoHit = 1 << 1, 25 kCheatLifeCounter = 1 << 2 26 }; 27 28 struct Game { 29 typedef int (Game::*pge_OpcodeProc)(ObjectOpcodeArgs *args); 30 typedef int (Game::*pge_ZOrderCallback)(LivePGE *, LivePGE *, uint8_t, uint8_t); 31 typedef int (Game::*col_Callback1)(LivePGE *, LivePGE *, int16_t, int16_t); 32 typedef int (Game::*col_Callback2)(LivePGE *, int16_t, int16_t, int16_t); 33 34 enum { 35 kIngameSaveSlot = 0, 36 kRewindSize = 120, // 10mins (~2MB) 37 kAutoSaveSlot = 255, 38 kAutoSaveIntervalMs = 5 * 1000 39 }; 40 41 enum { 42 CT_UP_ROOM = 0x00, 43 CT_DOWN_ROOM = 0x40, 44 CT_RIGHT_ROOM = 0x80, 45 CT_LEFT_ROOM = 0xC0 46 }; 47 48 static const Demo _demoInputs[3]; 49 static const Level _gameLevels[]; 50 static const uint16_t _scoreTable[]; 51 static const uint8_t _monsterListLevel1[]; 52 static const uint8_t _monsterListLevel2[]; 53 static const uint8_t _monsterListLevel3[]; 54 static const uint8_t _monsterListLevel4_1[]; 55 static const uint8_t _monsterListLevel4_2[]; 56 static const uint8_t _monsterListLevel5_1[]; 57 static const uint8_t _monsterListLevel5_2[]; 58 static const uint8_t *_monsterListLevels[]; 59 static const uint8_t _monsterPals[4][32]; 60 static const char *_monsterNames[2][4]; 61 static const pge_OpcodeProc _pge_opcodeTable[]; 62 static const uint8_t _pge_modKeysTable[]; 63 static const uint8_t _protectionCodeData[]; 64 static const uint8_t _protectionWordData[]; 65 static const uint8_t _protectionNumberDataAmiga[]; 66 static const uint8_t _protectionCodeDataAmiga[]; 67 static const uint8_t _protectionPal[]; 68 69 Cutscene _cut; 70 Menu _menu; 71 Mixer _mix; 72 Resource _res; 73 SeqPlayer _seq; 74 Video _vid; 75 SystemStub *_stub; 76 FileSystem *_fs; 77 const char *_savePath; 78 File _rewindBuffer[kRewindSize]; 79 int _rewindPtr, _rewindLen; 80 uint32_t _cheats; 81 82 const uint8_t *_stringsTable; 83 const char **_textsTable; 84 uint8_t _currentLevel; 85 uint8_t _skillLevel; 86 int _demoBin; 87 uint32_t _score; 88 uint8_t _currentRoom; 89 uint8_t _currentIcon; 90 bool _loadMap; 91 uint8_t _printLevelCodeCounter; 92 uint32_t _randSeed; 93 uint16_t _currentInventoryIconNum; 94 uint16_t _curMonsterFrame; 95 uint16_t _curMonsterNum; 96 uint8_t _blinkingConradCounter; 97 uint16_t _textToDisplay; 98 bool _eraseBackground; 99 AnimBufferState _animBuffer0State[41]; 100 AnimBufferState _animBuffer1State[6]; // Conrad 101 AnimBufferState _animBuffer2State[42]; 102 AnimBufferState _animBuffer3State[12]; 103 AnimBuffers _animBuffers; 104 uint16_t _deathCutsceneCounter; 105 bool _saveStateCompleted; 106 bool _endLoop; 107 uint32_t _frameTimestamp; 108 WidescreenMode _widescreenMode; 109 bool _autoSave; 110 uint32_t _saveTimestamp; 111 112 Game(SystemStub *, FileSystem *, const char *savePath, int level, ResourceType ver, Language lang, WidescreenMode widescreenMode, bool autoSave, uint32_t cheats); 113 114 void run(); 115 void displayTitleScreenAmiga(); 116 void displayTitleScreenMac(int num); 117 void resetGameState(); 118 void mainLoop(); 119 void updateTiming(); 120 void playCutscene(int id = -1); 121 bool playCutsceneSeq(const char *name); 122 bool hasLevelMap(int level, int room) const; 123 void loadLevelMap(); 124 void loadLevelData(); 125 void drawIcon(uint8_t iconNum, int16_t x, int16_t y, uint8_t colMask); 126 void drawCurrentInventoryItem(); 127 void printLevelCode(); 128 void showFinalScore(); 129 bool handleConfigPanel(); 130 bool handleContinueAbort(); 131 void printSaveStateCompleted(); 132 void drawLevelTexts(); 133 void drawStoryTexts(); 134 void drawString(const uint8_t *p, int x, int y, uint8_t color, bool hcenter = false); 135 void prepareAnims(); 136 void prepareAnimsHelper(LivePGE *pge, int16_t dx, int16_t dy); 137 void drawAnims(); 138 void drawAnimBuffer(uint8_t stateNum, AnimBufferState *state); 139 void drawPiege(AnimBufferState *state); 140 void drawObject(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags); 141 void drawObjectFrame(const uint8_t *bankDataPtr, const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t flags); 142 void drawCharacter(const uint8_t *dataPtr, int16_t x, int16_t y, uint8_t a, uint8_t b, uint8_t flags); 143 int loadMonsterSprites(LivePGE *pge); 144 void playSound(uint8_t sfxId, uint8_t softVol); 145 uint16_t getRandomNumber(); 146 void changeLevel(); 147 void handleInventory(); 148 149 // protection 150 bool handleProtectionScreenShape(); 151 bool handleProtectionScreenWords(); 152 153 // pieges 154 bool _pge_playAnimSound; 155 MessagePGE _pge_messages[256]; 156 MessagePGE *_pge_messagesTable[256]; // indexed by pge number 157 MessagePGE *_pge_nextFreeMessage; 158 LivePGE *_pge_liveTable2[256]; // active pieges list (index = pge number) 159 LivePGE *_pge_liveTable1[256]; // pieges list by room (index = room) 160 LivePGE _pgeLive[256]; 161 uint8_t _pge_currentPiegeRoom; 162 bool _pge_currentPiegeFacingDir; // (false == left) 163 bool _pge_processOBJ; 164 uint8_t _pge_inpKeysMask; 165 uint16_t _pge_opGunVar; 166 uint16_t _pge_compareVar1; 167 uint16_t _pge_compareVar2; 168 uint8_t _pge_zoomPiegeNum; 169 uint8_t _pge_zoomCounter; 170 int _pge_zoomX, _pge_zoomY; 171 172 void pge_resetMessages(); 173 void pge_clearMessages(uint8_t pge_index); 174 int pge_hasMessageData(LivePGE *pge, uint16_t msg_num, uint16_t counter) const; 175 void pge_loadForCurrentLevel(uint16_t idx); 176 void pge_process(LivePGE *pge); 177 void pge_setupNextAnimFrame(LivePGE *pge, MessagePGE *le); 178 void pge_playAnimSound(LivePGE *pge, uint16_t arg2); 179 void pge_setupAnim(LivePGE *pge); 180 int pge_execute(LivePGE *live_pge, InitPGE *init_pge, const Object *obj); 181 void pge_prepare(); 182 void pge_setupDefaultAnim(LivePGE *pge); 183 uint16_t pge_processOBJ(LivePGE *pge); 184 void pge_setupOtherPieges(LivePGE *pge, InitPGE *init_pge); 185 void pge_addToCurrentRoomList(LivePGE *pge, uint8_t room); 186 void pge_getInput(); 187 int pge_op_isInpUp(ObjectOpcodeArgs *args); 188 int pge_op_isInpBackward(ObjectOpcodeArgs *args); 189 int pge_op_isInpDown(ObjectOpcodeArgs *args); 190 int pge_op_isInpForward(ObjectOpcodeArgs *args); 191 int pge_op_isInpUpMod(ObjectOpcodeArgs *args); 192 int pge_op_isInpBackwardMod(ObjectOpcodeArgs *args); 193 int pge_op_isInpDownMod(ObjectOpcodeArgs *args); 194 int pge_op_isInpForwardMod(ObjectOpcodeArgs *args); 195 int pge_op_isInpIdle(ObjectOpcodeArgs *args); 196 int pge_op_isInpNoMod(ObjectOpcodeArgs *args); 197 int pge_op_getCollision0u(ObjectOpcodeArgs *args); 198 int pge_op_getCollision00(ObjectOpcodeArgs *args); 199 int pge_op_getCollision0d(ObjectOpcodeArgs *args); 200 int pge_op_getCollision1u(ObjectOpcodeArgs *args); 201 int pge_op_getCollision10(ObjectOpcodeArgs *args); 202 int pge_op_getCollision1d(ObjectOpcodeArgs *args); 203 int pge_op_getCollision2u(ObjectOpcodeArgs *args); 204 int pge_op_getCollision20(ObjectOpcodeArgs *args); 205 int pge_op_getCollision2d(ObjectOpcodeArgs *args); 206 int pge_op_doesNotCollide0u(ObjectOpcodeArgs *args); 207 int pge_op_doesNotCollide00(ObjectOpcodeArgs *args); 208 int pge_op_doesNotCollide0d(ObjectOpcodeArgs *args); 209 int pge_op_doesNotCollide1u(ObjectOpcodeArgs *args); 210 int pge_op_doesNotCollide10(ObjectOpcodeArgs *args); 211 int pge_op_doesNotCollide1d(ObjectOpcodeArgs *args); 212 int pge_op_doesNotCollide2u(ObjectOpcodeArgs *args); 213 int pge_op_doesNotCollide20(ObjectOpcodeArgs *args); 214 int pge_op_doesNotCollide2d(ObjectOpcodeArgs *args); 215 int pge_op_collides0o0d(ObjectOpcodeArgs *args); 216 int pge_op_collides2o2d(ObjectOpcodeArgs *args); 217 int pge_op_collides0o0u(ObjectOpcodeArgs *args); 218 int pge_op_collides2o2u(ObjectOpcodeArgs *args); 219 int pge_op_collides2u2o(ObjectOpcodeArgs *args); 220 int pge_hasPiegeSentMessage(ObjectOpcodeArgs *args); 221 int pge_op_sendMessageData0(ObjectOpcodeArgs *args); 222 int pge_op_sendMessageData1(ObjectOpcodeArgs *args); 223 int pge_op_sendMessageData2(ObjectOpcodeArgs *args); 224 int pge_op_sendMessageData3(ObjectOpcodeArgs *args); 225 int pge_op_isPiegeDead(ObjectOpcodeArgs *args); 226 int pge_op_collides1u2o(ObjectOpcodeArgs *args); 227 int pge_op_collides1u1o(ObjectOpcodeArgs *args); 228 int pge_op_collides1o1u(ObjectOpcodeArgs *args); 229 int pge_o_unk0x2B(ObjectOpcodeArgs *args); 230 int pge_o_unk0x2C(ObjectOpcodeArgs *args); 231 int pge_o_unk0x2D(ObjectOpcodeArgs *args); 232 int pge_op_nop(ObjectOpcodeArgs *args); 233 int pge_op_pickupObject(ObjectOpcodeArgs *args); 234 int pge_op_addItemToInventory(ObjectOpcodeArgs *args); 235 int pge_op_copyPiege(ObjectOpcodeArgs *args); 236 int pge_op_canUseCurrentInventoryItem(ObjectOpcodeArgs *args); 237 int pge_op_removeItemFromInventory(ObjectOpcodeArgs *args); 238 int pge_o_unk0x34(ObjectOpcodeArgs *args); 239 int pge_op_isInpMod(ObjectOpcodeArgs *args); 240 int pge_op_setCollisionState1(ObjectOpcodeArgs *args); 241 int pge_op_setCollisionState0(ObjectOpcodeArgs *args); 242 int pge_hasMessageData0(ObjectOpcodeArgs *args); 243 int pge_hasMessageData1(ObjectOpcodeArgs *args); 244 int pge_hasMessageData2(ObjectOpcodeArgs *args); 245 int pge_hasMessageData3(ObjectOpcodeArgs *args); 246 int pge_o_unk0x3C(ObjectOpcodeArgs *args); 247 int pge_o_unk0x3D(ObjectOpcodeArgs *args); 248 int pge_op_setPiegeCounter(ObjectOpcodeArgs *args); 249 int pge_op_decPiegeCounter(ObjectOpcodeArgs *args); 250 int pge_o_unk0x40(ObjectOpcodeArgs *args); 251 int pge_op_wakeUpPiege(ObjectOpcodeArgs *args); 252 int pge_op_removePiege(ObjectOpcodeArgs *args); 253 int pge_op_removePiegeIfNotNear(ObjectOpcodeArgs *args); 254 int pge_op_loadPiegeCounter(ObjectOpcodeArgs *args); 255 int pge_o_unk0x45(ObjectOpcodeArgs *args); 256 int pge_o_unk0x46(ObjectOpcodeArgs *args); 257 int pge_o_unk0x47(ObjectOpcodeArgs *args); 258 int pge_o_unk0x48(ObjectOpcodeArgs *args); 259 int pge_o_unk0x49(ObjectOpcodeArgs *args); 260 int pge_op_killInventoryPiege(ObjectOpcodeArgs *args); 261 int pge_op_killPiege(ObjectOpcodeArgs *args); 262 int pge_op_isInCurrentRoom(ObjectOpcodeArgs *args); 263 int pge_op_isNotInCurrentRoom(ObjectOpcodeArgs *args); 264 int pge_op_scrollPosY(ObjectOpcodeArgs *args); 265 int pge_op_playDefaultDeathCutscene(ObjectOpcodeArgs *args); 266 int pge_o_unk0x50(ObjectOpcodeArgs *args); 267 int pge_o_unk0x52(ObjectOpcodeArgs *args); 268 int pge_o_unk0x53(ObjectOpcodeArgs *args); 269 int pge_op_isPiegeNear(ObjectOpcodeArgs *args); 270 int pge_op_setLife(ObjectOpcodeArgs *args); 271 int pge_op_incLife(ObjectOpcodeArgs *args); 272 int pge_op_setPiegeDefaultAnim(ObjectOpcodeArgs *args); 273 int pge_op_setLifeCounter(ObjectOpcodeArgs *args); 274 int pge_op_decLifeCounter(ObjectOpcodeArgs *args); 275 int pge_op_playCutscene(ObjectOpcodeArgs *args); 276 int pge_op_compareUnkVar(ObjectOpcodeArgs *args); 277 int pge_op_playDeathCutscene(ObjectOpcodeArgs *args); 278 int pge_o_unk0x5D(ObjectOpcodeArgs *args); 279 int pge_o_unk0x5E(ObjectOpcodeArgs *args); 280 int pge_o_unk0x5F(ObjectOpcodeArgs *args); 281 int pge_op_findAndCopyPiege(ObjectOpcodeArgs *args); 282 int pge_op_isInRandomRange(ObjectOpcodeArgs *args); 283 int pge_o_unk0x62(ObjectOpcodeArgs *args); 284 int pge_o_unk0x63(ObjectOpcodeArgs *args); 285 int pge_o_unk0x64(ObjectOpcodeArgs *args); 286 int pge_op_addToCredits(ObjectOpcodeArgs *args); 287 int pge_op_subFromCredits(ObjectOpcodeArgs *args); 288 int pge_o_unk0x67(ObjectOpcodeArgs *args); 289 int pge_op_setCollisionState2(ObjectOpcodeArgs *args); 290 int pge_op_saveState(ObjectOpcodeArgs *args); 291 int pge_o_unk0x6A(ObjectOpcodeArgs *args); 292 int pge_isToggleable(ObjectOpcodeArgs *args); 293 int pge_o_unk0x6C(ObjectOpcodeArgs *args); 294 int pge_op_isCollidingObject(ObjectOpcodeArgs *args); 295 int pge_o_unk0x6E(ObjectOpcodeArgs *args); 296 int pge_o_unk0x6F(ObjectOpcodeArgs *args); 297 int pge_o_unk0x70(ObjectOpcodeArgs *args); 298 int pge_o_unk0x71(ObjectOpcodeArgs *args); 299 int pge_o_unk0x72(ObjectOpcodeArgs *args); 300 int pge_o_unk0x73(ObjectOpcodeArgs *args); 301 int pge_op_collides4u(ObjectOpcodeArgs *args); 302 int pge_op_doesNotCollide4u(ObjectOpcodeArgs *args); 303 int pge_op_isBelowConrad(ObjectOpcodeArgs *args); 304 int pge_op_isAboveConrad(ObjectOpcodeArgs *args); 305 int pge_op_isNotFacingConrad(ObjectOpcodeArgs *args); 306 int pge_op_isFacingConrad(ObjectOpcodeArgs *args); 307 int pge_op_collides2u1u(ObjectOpcodeArgs *args); 308 int pge_op_displayText(ObjectOpcodeArgs *args); 309 int pge_o_unk0x7C(ObjectOpcodeArgs *args); 310 int pge_op_playSound(ObjectOpcodeArgs *args); 311 int pge_o_unk0x7E(ObjectOpcodeArgs *args); 312 int pge_o_unk0x7F(ObjectOpcodeArgs *args); 313 int pge_op_setPiegePosX(ObjectOpcodeArgs *args); 314 int pge_op_setPiegePosModX(ObjectOpcodeArgs *args); 315 int pge_op_changeRoom(ObjectOpcodeArgs *args); 316 int pge_op_hasInventoryItem(ObjectOpcodeArgs *args); 317 int pge_op_changeLevel(ObjectOpcodeArgs *args); 318 int pge_op_shakeScreen(ObjectOpcodeArgs *args); 319 int pge_o_unk0x86(ObjectOpcodeArgs *args); 320 int pge_op_playSoundGroup(ObjectOpcodeArgs *args); 321 int pge_op_adjustPos(ObjectOpcodeArgs *args); 322 int pge_op_setGunVar(ObjectOpcodeArgs *args); 323 int pge_op_compareGunVar(ObjectOpcodeArgs *args); 324 int pge_setCurrentInventoryObject(LivePGE *pge); 325 void pge_updateInventory(LivePGE *pge1, LivePGE *pge2); 326 void pge_reorderInventory(LivePGE *pge); 327 LivePGE *pge_getPreviousInventoryItem(LivePGE *pge, LivePGE *last_pge); 328 void pge_addToInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3); 329 int pge_updateCollisionState(LivePGE *pge, int16_t pge_dy, uint8_t value); 330 int pge_ZOrder(LivePGE *pge, int16_t num, pge_ZOrderCallback compare, uint16_t unk); 331 void pge_sendMessage(uint8_t src_pge_index, uint8_t dst_pge_index, int16_t num); 332 void pge_removeFromInventory(LivePGE *pge1, LivePGE *pge2, LivePGE *pge3); 333 int pge_ZOrderByAnimY(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 334 int pge_ZOrderByAnimYIfType(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 335 int pge_ZOrderIfIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 336 int pge_ZOrderByIndex(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 337 int pge_ZOrderByObj(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 338 int pge_ZOrderIfDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 339 int pge_ZOrderIfSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 340 int pge_ZOrderIfTypeAndSameDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 341 int pge_ZOrderIfTypeAndDifferentDirection(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 342 int pge_ZOrderByNumber(LivePGE *pge1, LivePGE *pge2, uint8_t comp, uint8_t comp2); 343 void pge_updateZoom(); 344 345 346 // collision 347 CollisionSlot _col_slots[256]; 348 uint8_t _col_curPos; 349 CollisionSlot *_col_slotsTable[256]; 350 CollisionSlot *_col_curSlot; 351 CollisionSlot2 _col_slots2[256]; 352 CollisionSlot2 *_col_slots2Cur; 353 CollisionSlot2 *_col_slots2Next; 354 uint8_t _col_activeCollisionSlots[0x30 * 3]; // left, current, right 355 uint8_t _col_currentLeftRoom; 356 uint8_t _col_currentRightRoom; 357 int16_t _col_currentPiegeGridPosX; 358 int16_t _col_currentPiegeGridPosY; 359 360 void col_prepareRoomState(); 361 void col_clearState(); 362 LivePGE *col_findPiege(LivePGE *pge, uint16_t arg2); 363 int16_t col_findSlot(int16_t pos); 364 void col_preparePiegeState(LivePGE *dst_pge); 365 uint16_t col_getGridPos(LivePGE *pge, int16_t dx); 366 int16_t col_getGridData(LivePGE *pge, int16_t dy, int16_t dx); 367 uint8_t col_findCurrentCollidingObject(LivePGE *pge, uint8_t n1, uint8_t n2, uint8_t n3, LivePGE **pge_out); 368 int16_t col_detectHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC); 369 int col_detectHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2); 370 int col_detectHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2); 371 int col_detectHitCallback4(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2); 372 int col_detectHitCallback5(LivePGE *pge1, LivePGE *pge2, int16_t unk1, int16_t unk2); 373 int col_detectHitCallback1(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2); 374 int col_detectHitCallback6(LivePGE *pge, int16_t dy, int16_t unk1, int16_t unk2); 375 int col_detectHitCallbackHelper(LivePGE *pge, int16_t unk1); 376 int col_detectGunHitCallback1(LivePGE *pge, int16_t arg2, int16_t arg4, int16_t arg6); 377 int col_detectGunHitCallback2(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t); 378 int col_detectGunHitCallback3(LivePGE *pge1, LivePGE *pge2, int16_t arg4, int16_t); 379 int col_detectGunHit(LivePGE *pge, int16_t arg2, int16_t arg4, col_Callback1 callback1, col_Callback2 callback2, int16_t argA, int16_t argC); 380 381 382 // input 383 uint8_t _inp_lastKeysHit; 384 uint8_t _inp_lastKeysHitLeftRight; 385 int _inp_demPos; 386 387 void inp_handleSpecialKeys(); 388 void inp_update(); 389 390 391 // save/load state 392 uint8_t _stateSlot; 393 bool _validSaveState; 394 395 void makeGameStateName(uint8_t slot, char *buf); 396 bool saveGameState(uint8_t slot); 397 bool loadGameState(uint8_t slot); 398 void saveState(File *f); 399 void loadState(File *f, int version); 400 void clearStateRewind(); 401 bool saveStateRewind(); 402 bool loadStateRewind(); 403 }; 404 405 #endif // GAME_H__ 406