diff --git a/docs/progress.svg b/docs/progress.svg
index d485c21f2..a96ca9b55 100644
--- a/docs/progress.svg
+++ b/docs/progress.svg
@@ -168,7 +168,7 @@
-
+
@@ -889,7 +889,7 @@
-
+
@@ -1459,10 +1459,10 @@
-Functions decompiled (count): 33.74%
-Functions decompiled (bytesize): 33.24%
-Functions not decompiled, but with known names (count): 52.26%
-Functions not decompiled, but with known names (bytesize): 50.79%
+Functions decompiled (count): 33.88%
+Functions decompiled (bytesize): 33.42%
+Functions not decompiled, but with known names (count): 52.13%
+Functions not decompiled, but with known names (bytesize): 50.61%
Functions not decompiled, with unknown names (count): 13.99%
Functions not decompiled, with unknown names (bytesize): 15.97%
diff --git a/docs/progress.txt b/docs/progress.txt
index aeac88923..d9c8897ff 100644
--- a/docs/progress.txt
+++ b/docs/progress.txt
@@ -210,8 +210,8 @@ ClipTarget 0x004150C0 0x000000DC +
FlipMap 0x004151A0 0x0000016F +
RemoveRoomFlipItems ---------- ---------- +
AddRoomFlipItems ---------- ---------- +
-TriggerCDTrack 0x00415310 0x000001D2 -
-TriggerNormalCDTrack ---------- ---------- -
+TriggerCDTrack 0x00415310 0x000001D2 +
+TriggerNormalCDTrack ---------- ---------- +
# croc.cpp
AlligatorControl 0x00415520 0x00000326 *
@@ -854,7 +854,7 @@ sub_438CA0 0x00438CA0 0x00000015 -
S_SoundStopAllSamples 0x00438CC0 0x0000000F -
S_SoundStopSample 0x00438CD0 0x0000001B -
sub_438CF0 0x00438CF0 0x00000044 -
-S_CDPlay 0x00438D40 0x000000FD -
+S_CDPlay 0x00438D40 0x000000FD *
S_CDStop 0x00438E40 0x00000043 *
SampleLoader 0x00438E90 0x00000005 -
LoadSamples 0x00438EA0 0x00000189 -
diff --git a/src/game/const.h b/src/game/const.h
index c04c7d4b2..7e0b1aebc 100644
--- a/src/game/const.h
+++ b/src/game/const.h
@@ -8,6 +8,7 @@
#define MAX_ROOMS 1024
#define MAX_ROOMS_TO_DRAW 100
#define MAX_FRAMES 10
+#define MAX_CD_TRACKS 64
#define MAX_TEXTURES 2048
#define NUMBER_ITEMS 256
#define MAX_SECRETS 16
diff --git a/src/game/control.c b/src/game/control.c
index 41104b56d..2f093af2f 100644
--- a/src/game/control.c
+++ b/src/game/control.c
@@ -982,6 +982,88 @@ void AddRoomFlipItems(ROOM_INFO* r)
}
}
+void TriggerCDTrack(int16_t value, int16_t flags, int16_t type)
+{
+ if (value <= 1 || value >= MAX_CD_TRACKS) {
+ return;
+ }
+
+ switch (value) {
+ case 28:
+ if ((CDFlags[value] & IF_ONESHOT)
+ && LaraItem->current_anim_state == AS_UPJUMP) {
+ value = 29;
+ }
+ break;
+
+ case 37:
+ if (LaraItem->current_anim_state != AS_HANG) {
+ return;
+ }
+ break;
+
+ case 41:
+ if (LaraItem->current_anim_state != AS_HANG) {
+ return;
+ }
+ break;
+
+ case 42:
+ if ((CDFlags[value] & IF_ONESHOT)
+ && LaraItem->current_anim_state == AS_HANG) {
+ value = 43;
+ }
+ break;
+
+ case 49:
+ if (LaraItem->current_anim_state != AS_SURFTREAD) {
+ return;
+ }
+ break;
+
+ case 50:
+ if (CDFlags[value] & IF_ONESHOT) {
+ static int16_t gym_completion_counter = 0;
+ gym_completion_counter++;
+ if (gym_completion_counter == 30 * 4) {
+ LevelComplete = 1;
+ gym_completion_counter = 0;
+ }
+ } else if (LaraItem->current_anim_state != AS_WATEROUT) {
+ return;
+ }
+ break;
+ }
+
+ TriggerNormalCDTrack(value, flags, type);
+}
+
+void TriggerNormalCDTrack(int16_t value, int16_t flags, int16_t type)
+{
+ if (CDFlags[value] & IF_ONESHOT) {
+ return;
+ }
+
+ if (type == TT_SWITCH) {
+ CDFlags[value] ^= flags & IF_CODE_BITS;
+ } else if (type == TT_ANTIPAD) {
+ CDFlags[value] &= -1 - (flags & IF_CODE_BITS);
+ } else if (flags & IF_CODE_BITS) {
+ CDFlags[value] |= flags & IF_CODE_BITS;
+ }
+
+ if ((CDFlags[value] & IF_CODE_BITS) == IF_CODE_BITS) {
+ if (flags & IF_ONESHOT) {
+ CDFlags[value] |= IF_ONESHOT;
+ }
+ if (value != CDTrack) {
+ S_CDPlay(value);
+ }
+ } else {
+ S_CDStop();
+ }
+}
+
void T1MInjectGameControl()
{
INJECT(0x004133B0, ControlPhase);
@@ -1000,4 +1082,5 @@ void T1MInjectGameControl()
INJECT(0x00414E50, xLOS);
INJECT(0x004150C0, ClipTarget);
INJECT(0x004151A0, FlipMap);
+ INJECT(0x00415310, TriggerCDTrack);
}
diff --git a/src/game/control.h b/src/game/control.h
index dd3e93d83..e12165c55 100644
--- a/src/game/control.h
+++ b/src/game/control.h
@@ -27,6 +27,8 @@ int32_t ClipTarget(GAME_VECTOR* start, GAME_VECTOR* target, FLOOR_INFO* floor);
void FlipMap();
void RemoveRoomFlipItems(ROOM_INFO* r);
void AddRoomFlipItems(ROOM_INFO* r);
+void TriggerCDTrack(int16_t value, int16_t flags, int16_t type);
+void TriggerNormalCDTrack(int16_t value, int16_t flags, int16_t type);
void T1MInjectGameControl();
diff --git a/src/game/vars.h b/src/game/vars.h
index ffaf5de13..3e6cb222a 100644
--- a/src/game/vars.h
+++ b/src/game/vars.h
@@ -110,6 +110,7 @@
#define ControlText ARRAY_(0x0045A2F8, TEXTSTRING*, [2])
#define ScanCodeNames ARRAY_(0x00454A40, char*, [])
#define OptionMusicVolume VAR_I_(0x00456334, int32_t, 255)
+#define CDFlags ARRAY_(0x00462C20, int16_t, [MAX_CD_TRACKS])
// #define LaraControlRoutines ARRAY_(0x00456490, ControlRoutine, [])
// #define LaraCollisionRoutines ARRAY_(0x00456570, CollisionRoutine, [])
diff --git a/src/specific/sndpc.h b/src/specific/sndpc.h
index f3f61d669..20eae5a12 100644
--- a/src/specific/sndpc.h
+++ b/src/specific/sndpc.h
@@ -2,11 +2,12 @@
#define T1M_SPECIFIC_SNDPC_H
// clang-format off
-#define S_CDLoop ((void (*)())0x004380B0)
-#define S_CDStop ((void (*)())0x00438E40)
-#define S_CDVolume ((void (*)(int16_t volume))0x00437F30)
-#define SoundStart ((void (*)())0x0041CDA0)
-#define SoundInit ((int32_t (*)())0x00437E00)
+#define S_CDLoop ((void (*)())0x004380B0)
+#define S_CDStop ((void (*)())0x00438E40)
+#define S_CDPlay ((void (*)(int16_t track))0x00438D40)
+#define S_CDVolume ((void (*)(int16_t volume))0x00437F30)
+#define SoundStart ((void (*)())0x0041CDA0)
+#define SoundInit ((int32_t (*)())0x00437E00)
// clang-format on
#endif