diff --git a/docs/progress.svg b/docs/progress.svg
index 07c01e92e..cd8326f60 100644
--- a/docs/progress.svg
+++ b/docs/progress.svg
@@ -256,35 +256,35 @@
-
-
-
-
+
+
+
+
-
+
-
-
+
+
-
-
+
+
-
+
-
+
@@ -323,12 +323,12 @@
-
+
-
+
-
-
+
+
@@ -425,11 +425,11 @@
-
-
+
+
-
-
+
+
@@ -450,20 +450,20 @@
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -517,9 +517,9 @@
-
+
-
+
@@ -528,10 +528,10 @@
-
-
-
-
+
+
+
+
@@ -561,9 +561,9 @@
-
+
-
+
@@ -576,53 +576,53 @@
-
+
-
+
-
-
-
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
+
-
-
-
+
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
@@ -638,8 +638,8 @@
-
-
+
+
@@ -659,10 +659,10 @@
-
-
-
-
+
+
+
+
@@ -678,31 +678,31 @@
-
-
+
+
-
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -727,742 +727,746 @@
-
-
+
+
+
+
TombATI functions, arranged according to the function sizes:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Functions decompiled (count): 40.05%
-Functions decompiled (bytesize): 37.96%
-Functions not decompiled, but with known names (count): 45.95%
-Functions not decompiled, but with known names (bytesize): 46.06%
-Functions not decompiled, with unknown names (count): 13.99%
-Functions not decompiled, with unknown names (bytesize): 15.97%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Functions decompiled (count): 40.08%
+Functions decompiled (bytesize): 38.13%
+Functions not decompiled, but with known names (count): 45.83%
+Functions not decompiled, but with known names (bytesize): 46.04%
+Functions not decompiled, with unknown names (count): 14.09%
+Functions not decompiled, with unknown names (bytesize): 15.83%
diff --git a/docs/progress.txt b/docs/progress.txt
index 5da6de1a8..76308ed70 100644
--- a/docs/progress.txt
+++ b/docs/progress.txt
@@ -350,10 +350,12 @@ S_FadeToBlack 0x0041CD10 0x0000003F *
S_Wait 0x0041CD50 0x0000004D -
SoundStart 0x0041CDA0 0x00000045 *
WinPlayFMV 0x0041CDF0 0x0000024A -
-S_PlayFMV 0x0041D040 0x0000007C -
-sub_41D0C0 0x0041D0C0 0x000001CA -
+sub_41D00B 0x0041D00B 0x0000002F -
+S_PlayFMV 0x0041D040 0x0000007C *
+sub_41D078 0x0041D078 0x00000044 -
# game.cpp
+StartGame 0x0041D0C0 0x000001CA +
GameLoop 0x0041D2C0 0x00000065 +
LevelCompleteSequence 0x0041D330 0x0000021C -
LevelStats 0x0041D5A0 0x00000346 +
@@ -832,8 +834,8 @@ draw_scaled_spriteC 0x004360A0 0x000001FB -
# setup.cpp
InitialiseLevel 0x004362A0 0x00000119 +
-InitialiseGameFlags ---------- ---------- -
-InitialiseLevelFlags 0x004363C0 0x00000018 -
+InitialiseGameFlags ---------- ---------- +
+InitialiseLevelFlags 0x004363C0 0x00000018 *
BaddyObjects 0x004363E0 0x00000C2F +
TrapObjects 0x00437010 0x00000356 +
ObjectObjects 0x00437370 0x000006D3 +
diff --git a/src/game/game.c b/src/game/game.c
index ca222dc69..ecfbf9e11 100644
--- a/src/game/game.c
+++ b/src/game/game.c
@@ -3,25 +3,102 @@
#include "game/draw.h"
#include "game/game.h"
#include "game/savegame.h"
+#include "game/setup.h"
#include "game/text.h"
#include "game/vars.h"
#include "specific/display.h"
#include "specific/frontend.h"
#include "specific/input.h"
#include "specific/output.h"
+#include "specific/shed.h"
#include "specific/sndpc.h"
#include "config.h"
#include "util.h"
-void GameLoop(int demo_mode)
+int32_t StartGame(int level_num)
+{
+ switch (level_num) {
+ case LV_GYM:
+ S_PlayFMV(FMV_GYM, 1);
+ break;
+
+ case LV_LEVEL1:
+ S_PlayFMV(FMV_SNOW, 1);
+ break;
+
+ case LV_LEVEL4:
+ S_PlayFMV(FMV_LIFT, 1);
+ break;
+
+ case LV_LEVEL8A:
+ S_PlayFMV(FMV_VISION, 1);
+ break;
+
+ case LV_LEVEL10A:
+ S_PlayFMV(FMV_CANYON, 1);
+ break;
+
+ case LV_LEVEL10B:
+ S_PlayFMV(FMV_PYRAMID, 1);
+ break;
+ }
+
+ // TODO: this probably doesn't belong here
+ CurrentLevel = level_num;
+ TitleLoaded = 0;
+ if (level_num != LV_CURRENT) {
+ InitialiseLevelFlags();
+ }
+
+ if (!InitialiseLevel(level_num)) {
+ CurrentLevel = 0;
+ return GF_EXIT_TO_TITLE;
+ }
+
+ if (GameLoop(0) == GF_EXIT_TO_TITLE) {
+ return GF_EXIT_TO_TITLE;
+ }
+
+ if (LevelComplete) {
+ if (CurrentLevel) {
+ S_FadeInInventory(1);
+ return GF_LEVELCOMPLETE | CurrentLevel;
+ }
+
+ S_FadeToBlack();
+ return GF_EXIT_TO_TITLE;
+ }
+
+ S_FadeToBlack();
+ if (!InventoryChosen) {
+ return GF_EXIT_TO_TITLE;
+ }
+
+ if (InventoryExtraData[0]) {
+ if (InventoryExtraData[0] == 1) {
+ return GF_STARTGAME | LV_LEVEL1;
+ }
+ return GF_EXIT_TO_TITLE;
+ }
+
+ S_LoadGame(SaveGame, sizeof(SAVEGAME_INFO), InventoryExtraData[1]);
+ return GF_STARTGAME | LV_CURRENT;
+}
+
+int32_t GameLoop(int demo_mode)
{
TRACE("");
OverlayFlag = 1;
InitialiseCamera();
int32_t nframes = 1;
- while (!ControlPhase(nframes, demo_mode)) {
- nframes = DrawPhaseGame();
+ int32_t ret;
+ while (1) {
+ ret = ControlPhase(nframes, demo_mode);
+ if (ret) {
+ break;
+ }
+ nframes = DrawPhaseGame(ret);
}
S_SoundStopAllSamples();
@@ -29,6 +106,8 @@ void GameLoop(int demo_mode)
if (OptionMusicVolume) {
S_CDVolume(OptionMusicVolume * 25 + 5);
}
+
+ return ret;
}
int32_t LevelIsValid(int16_t level_num)
@@ -216,6 +295,7 @@ int32_t S_LoadGame(void* data, int32_t size, int slot)
void T1MInjectGameGame()
{
+ INJECT(0x0041D0C0, StartGame);
INJECT(0x0041D2C0, GameLoop);
INJECT(0x0041D5A0, LevelStats);
INJECT(0x0041D8F0, GetRandomControl);
diff --git a/src/game/game.h b/src/game/game.h
index 7ec45bd16..2617b7b99 100644
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -7,7 +7,7 @@
#define S_SaveGame ((void (*)())0x0041DB70)
// clang-format on
-void GameLoop(int demo_mode);
+int32_t GameLoop(int demo_mode);
int32_t LevelIsValid(int16_t level_num);
void SeedRandomControl(int32_t seed);
void SeedRandomDraw(int32_t seed);
diff --git a/src/game/setup.h b/src/game/setup.h
index 142bf56a2..1d61950d4 100644
--- a/src/game/setup.h
+++ b/src/game/setup.h
@@ -3,6 +3,10 @@
#include
+// clang-format off
+#define InitialiseLevelFlags ((void (*)())0x004363C0)
+// clang-format on
+
int32_t InitialiseLevel(int32_t level_num);
void InitialiseGameFlags();
void BaddyObjects();
diff --git a/src/game/types.h b/src/game/types.h
index 72f78e94e..33ed97207 100644
--- a/src/game/types.h
+++ b/src/game/types.h
@@ -679,6 +679,21 @@ typedef enum {
IF_KILLED_ITEM = 0x8000,
} ITEM_FLAGS;
+typedef enum {
+ FMV_INTRO = 0,
+ FMV_GYM = 1,
+ FMV_SNOW = 2,
+ FMV_LIFT = 3,
+ FMV_VISION = 3,
+ FMV_CANYON = 4,
+ FMV_PYRAMID = 5,
+ FMV_PRISON = 6,
+ FMV_ENDSEQ = 7,
+ FMV_CORE = 8,
+ FMV_ESCAPE = 9,
+ NUMBER_OF_FMV
+} FMV_SEQUENCE;
+
#pragma pack(push, 1)
typedef struct {
diff --git a/src/specific/display.h b/src/specific/display.h
index fd82bf23c..8e3705116 100644
--- a/src/specific/display.h
+++ b/src/specific/display.h
@@ -4,6 +4,7 @@
// clang-format off
#define TempVideoRemove ((void (*)())0x004167D0)
#define TempVideoAdjust ((void (*)(int32_t hires, double sizer))0x00416550)
+#define S_FadeInInventory ((void (*)())0x00416B20)
// clang-format on
#endif
diff --git a/src/specific/shed.h b/src/specific/shed.h
index 5389aaf00..88c8c1484 100644
--- a/src/specific/shed.h
+++ b/src/specific/shed.h
@@ -7,6 +7,7 @@
#define WinVidSpinMessageLoop ((void (*)())0x00437AD0)
#define ShowFatalError ((void (*)(const char *message))0x0043D770)
#define S_ExitSystem ((void (*)(const char *message))0x0041E260)
+#define S_PlayFMV ((void (*)(int32_t sequence, int32_t mode))0x0041D040)
#define WriteTombAtiSettings ((void (*)())0x00438B60)
#define sub_4380E0 ((void (*)(int16_t *unk))0x004380E0)
#define InitialiseHardware ((void (*)())0x00408005)