From ff3fbfcf770bcb43d2d5d77617550c9c0501afa5 Mon Sep 17 00:00:00 2001 From: Tarek Soliman Date: Fri, 29 Apr 2011 22:54:12 -0500 Subject: LASTEXPRESS: flag all WIP games with ADGF_UNSTABLE all --- engines/lastexpress/detection.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp index 369d815543..de80e75341 100644 --- a/engines/lastexpress/detection.cpp +++ b/engines/lastexpress/detection.cpp @@ -47,7 +47,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -65,7 +65,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -83,7 +83,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -98,7 +98,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformUnknown, - ADGF_DEMO, + ADGF_DEMO | ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -116,7 +116,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::FR_FRA, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -134,7 +134,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::DE_DEU, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -152,7 +152,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::ES_ESP, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, @@ -170,7 +170,7 @@ static const ADGameDescription gameDescriptions[] = { }, Common::IT_ITA, Common::kPlatformUnknown, - ADGF_NO_FLAGS, + ADGF_UNSTABLE, Common::GUIO_NONE }, -- cgit v1.2.3 From c288d6d20729563c6ce3416fd641947a35562469 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Wed, 22 Jun 2011 00:20:05 +0300 Subject: LASTEXPRESS: Implement sound filters. Still not hooked in. --- engines/lastexpress/game/sound.cpp | 351 +++++++++++++++++++++++++++++++++++++ engines/lastexpress/game/sound.h | 2 +- 2 files changed, 352 insertions(+), 1 deletion(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 3f98ac79ea..b8d2755907 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -1948,4 +1948,355 @@ void SoundManager::stopAllSound() { (*i)->soundStream->stop(); } +////////////////////////////////////////////////////////////////////////// +// Sound filter +////////////////////////////////////////////////////////////////////////// + +static int filterData[1424] = { + 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, + 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, + 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, + 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, + 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, + 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, + 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, + 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, + 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, + 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, + 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, + 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, + 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, + 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, + 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, + 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, + 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, + 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, + 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, + 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, + 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, + 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, + 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, + 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, + 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, + 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, + 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, + 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, + 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, + 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, + 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, + 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, + 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, + 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, + 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, + 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, + 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, + 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, + 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, + 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, + 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, + 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, + 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, + 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, + 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, + 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, + 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, + 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, + 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, + 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, + 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, + 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, + 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, + 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, + 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, + 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, + 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, + 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, + 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, + 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, + 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, + 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, + 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, + 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, + 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, + 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, + 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, + 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, + 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, + 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, + 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, + 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, + 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, + 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, + 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, + 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, + 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, + 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, + 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, + 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, + 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, + 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, + 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, + 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, + 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, + 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, + 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, + 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, + 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, + 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, + 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, + 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, + 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, + 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, + 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, + 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, + 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, + 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, + 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, + 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, + 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, + 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, + 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, + 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, + 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, + 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, + 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, + 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, + 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, + 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, + 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, + 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, + 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, + 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, + 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, + 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, + 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, + 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, + 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, + 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, + 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, + 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, + 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, + 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, + 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, + 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, + 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, + 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, + 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, + 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, + 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, + 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, + 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, + 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, + 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, + 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, + 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, + 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, + 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, + 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, + 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, + 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, + 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, + 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, + 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, + 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, + 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, + 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, + 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, + 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, + 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, + 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, + 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, + 5632 +}; + +static int filterData2[1424] = { + 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, + -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, + -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, + -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, + -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, + 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, + 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, + -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, + -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, + -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, + 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, + 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, + -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, + -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, + -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, + 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, + 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, + -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, + -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, + 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, + 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, + -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, + -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, + -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, + 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, + 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, + -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, + -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, + 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, + 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, + -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, + -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, + 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, + -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, + -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, + 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, + -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, + 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, + 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, + -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, + 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, + 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, + -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, + 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, + 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, + -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, + 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, + -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, + -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, + 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, + -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, + -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, + 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, + -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, + 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, + -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, + 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, + -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, + -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, + 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, + -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, + -68, -204, -340, -476, -612, -748, -884, -1020, 74, + 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, + -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, + 904, 1069, 1233, -82, -246, -411, -575, -740, -904, + -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, + -90, -271, -452, -633, -814, -995, -1176, -1357, 99, + 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, + -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, + 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, + -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, + 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, + -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, + -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, + 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, + -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, + 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, + -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, + 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, + -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, + -194, -582, -970, -1358, -1746, -2134, -2522, -2910, + 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, + -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, + 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, + -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, + 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, + -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, + 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, + -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, + 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, + -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, + 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, + -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, + -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, + 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, + -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, + 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, + -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, + 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, + -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, + 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, + -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, + 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, + -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, + 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, + -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, + 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, + -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, + -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, + 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, + -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, + 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, + -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, + 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, + -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, + 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, + -5933, -8306, -10679, -13052, -15426, -17799, 1305, + 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, + -3915, -6526, -9136, -11747, -14357, -16968, -19578, + 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, + -1435, -4307, -7179, -10051, -12922, -15794, -18666, + -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, + 23690, -1579, -4738, -7896, -11055, -14214, -17373, + -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, + 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, + -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, + 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, + -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, + 27329, 31533, -2102, -6306, -10511, -14715, -18920, + -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, + 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, + -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, + 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, + -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, + 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, + -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, + 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, + -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, + 32767, 32767, 32767, -3385, -10157, -16928, -23700, + -30471, -32767, -32767, -32767, 3724, 11172, 18621, + 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, + -26069, -32767, -32767, -32767, -32767, 4095, 12287, + 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, + -20479, -28671, -32767, -32767, -32767, -32767 +}; + +static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0}; +static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1}; + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2); + +void SoundManager::applyFilter(SoundEntry *entry, int16 *buffer) { + if ((((byte *)entry->soundData)[1] << 6) > 0x1600) { + entry->status.status |= 0x20000000; + } else { + int variant = entry->status.status & 0x1f; + + soundFilter((byte *)entry->soundData, buffer, p1s[variant], p2s[variant]); + } +} + + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { + int data1, data2, data1p, data2p; + byte idx; + + data2 = data[0]; + data1 = data[1] << 6; + + data += 2; + + for (int count = 0; count < 735; count++) { + idx = data[count] >> 4; + data1p = filterData[idx + data1]; + data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); + + buffer[2 * count] = (p2 * data2p) >> p1; + + idx = data[count] & 0xF; + + data1 = filterData[idx + data1p]; + data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); + buffer[2 * count + 1] = (p2 * data2) >> p1; + } +} + + } // End of namespace LastExpress diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index ddafc21829..5b1fe64cd8 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -381,7 +381,7 @@ private: void drawSubtitleOnScreen(SubtitleEntry *subtitle); // Sound filter - void applyFilter(SoundEntry *entry, SoundBuffer buffer); + void applyFilter(SoundEntry *entry, int16 *buffer); }; } // End of namespace LastExpress -- cgit v1.2.3 From 1fe9985912c3bb819d1145b03389a615f9b11401 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Wed, 22 Jun 2011 10:41:38 +0300 Subject: LASTEXPRESS: Named several soundEntry structure members --- engines/lastexpress/game/sound.cpp | 10 +++++----- engines/lastexpress/game/sound.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index b8d2755907..4779fc532f 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -614,16 +614,16 @@ void SoundManager::saveLoadWithSerializer(Common::Serializer &s) { if (entry->name2.matchString("NISSND?") && (entry->status.status & kFlagType7) != kFlag3) { s.syncAsUint32LE(entry->status.status); // status; s.syncAsUint32LE(entry->type); // type; - s.syncAsUint32LE(entry->field_1C); // field_8; + s.syncAsUint32LE(entry->blockCount); // field_8; s.syncAsUint32LE(entry->time); // time; s.syncAsUint32LE(entry->field_34); // field_10; s.syncAsUint32LE(entry->field_38); // field_14; s.syncAsUint32LE(entry->entity); // entity; - uint32 field_1C = (uint32)entry->field_48 - _data2; - if (field_1C > kFlag8) - field_1C = 0; - s.syncAsUint32LE(field_1C); // field_1C; + uint32 blockCount = (uint32)entry->field_48 - _data2; + if (blockCount > kFlag8) + blockCount = 0; + s.syncAsUint32LE(blockCount); // blockCount; s.syncAsUint32LE(entry->field_4C); // field_20; diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index 5b1fe64cd8..839c868813 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -246,14 +246,14 @@ private: struct SoundEntry { SoundStatusUnion status; SoundType type; // int - //int field_8; - //int field_C; - int processedFrameCount; + //int data; + //int endOffset; + int currentDataPtr; void *soundData; - //int field_18; - int field_1C; + //int currentBufferPtr; + int blockCount; uint32 time; - //int field_24; + //int size; //int field_28; Common::SeekableReadStream *stream; // int //int field_30; @@ -276,10 +276,10 @@ private: status.status = 0; type = kSoundTypeNone; - processedFrameCount = 0; + currentDataPtr = 0; soundData = NULL; - field_1C = 0; + blockCount = 0; time = 0; stream = NULL; -- cgit v1.2.3 From 7dca4bf09683650b3a8ce44d87723460226f98f8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 22 Jun 2011 18:11:13 +0200 Subject: LASTEXPRESS: Make some static data const respectively static. --- engines/lastexpress/game/sound.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 4779fc532f..1c7abbf95e 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -40,7 +40,7 @@ namespace LastExpress { #define SOUNDCACHE_MAX_SIZE 6 // Letters & messages -const char *messages[24] = { +static const char *const messages[24] = { "", "TXT1001", // 1 "TXT1001A", // 2 @@ -67,7 +67,7 @@ const char *messages[24] = { "ENDALRM3" // 65 }; -const char *cities[17] = { +static const char *const cities[17] = { "EPERNAY", "CHALONS", "BARLEDUC", @@ -87,7 +87,7 @@ const char *cities[17] = { "POLICE" }; -const char *locomotiveSounds[5] = { +static const char *const locomotiveSounds[5] = { "ZFX1005", "ZFX1006", "ZFX1007", @@ -1952,7 +1952,7 @@ void SoundManager::stopAllSound() { // Sound filter ////////////////////////////////////////////////////////////////////////// -static int filterData[1424] = { +static const int filterData[1424] = { 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, @@ -2109,7 +2109,7 @@ static int filterData[1424] = { 5632 }; -static int filterData2[1424] = { +static const int filterData2[1424] = { 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, @@ -2258,8 +2258,8 @@ static int filterData2[1424] = { -20479, -28671, -32767, -32767, -32767, -32767 }; -static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0}; -static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1}; +static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; +static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; static void soundFilter(byte *data, int16 *buffer, int p1, int p2); -- cgit v1.2.3 From 3c2a9b292f5a851529fb0196eab662fd9996a459 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 21 Jun 2011 23:50:01 -0400 Subject: LASTEXPRESS: Move Fight class to its own folder --- engines/lastexpress/debug.cpp | 3 +- engines/lastexpress/entities/anna.cpp | 3 +- engines/lastexpress/entities/ivo.cpp | 3 +- engines/lastexpress/entities/milos.cpp | 3 +- engines/lastexpress/entities/salko.cpp | 3 +- engines/lastexpress/entities/vesna.cpp | 3 +- engines/lastexpress/fight/fight.cpp | 1583 ++++++++++++++++++++++++++++++++ engines/lastexpress/fight/fight.h | 266 ++++++ engines/lastexpress/game/fight.cpp | 1583 -------------------------------- engines/lastexpress/game/fight.h | 266 ------ engines/lastexpress/game/logic.cpp | 4 +- engines/lastexpress/game/menu.cpp | 3 +- engines/lastexpress/module.mk | 2 +- 13 files changed, 1867 insertions(+), 1858 deletions(-) create mode 100644 engines/lastexpress/fight/fight.cpp create mode 100644 engines/lastexpress/fight/fight.h delete mode 100644 engines/lastexpress/game/fight.cpp delete mode 100644 engines/lastexpress/game/fight.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index 4b7c5f6a9a..d5c7df0e55 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -31,9 +31,10 @@ #include "lastexpress/data/snd.h" #include "lastexpress/data/subtitle.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/beetle.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp index 0bedda41e8..bce99ad16d 100644 --- a/engines/lastexpress/entities/anna.cpp +++ b/engines/lastexpress/entities/anna.cpp @@ -22,9 +22,10 @@ #include "lastexpress/entities/anna.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp index 35f4ccfb8c..861c3cf9bd 100644 --- a/engines/lastexpress/entities/ivo.cpp +++ b/engines/lastexpress/entities/ivo.cpp @@ -22,9 +22,10 @@ #include "lastexpress/entities/ivo.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp index 587c43cade..45fd6883f0 100644 --- a/engines/lastexpress/entities/milos.cpp +++ b/engines/lastexpress/entities/milos.cpp @@ -24,9 +24,10 @@ #include "lastexpress/entities/vesna.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp index 4d510bb9bf..bbaff5f1d9 100644 --- a/engines/lastexpress/entities/salko.cpp +++ b/engines/lastexpress/entities/salko.cpp @@ -22,9 +22,10 @@ #include "lastexpress/entities/salko.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp index 8e09dbf7b0..79ac934ef9 100644 --- a/engines/lastexpress/entities/vesna.cpp +++ b/engines/lastexpress/entities/vesna.cpp @@ -22,9 +22,10 @@ #include "lastexpress/entities/vesna.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/action.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp new file mode 100644 index 0000000000..5b3530f488 --- /dev/null +++ b/engines/lastexpress/fight/fight.cpp @@ -0,0 +1,1583 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fight.h" + +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/scene.h" +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/graphics.h" +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +#include "common/func.h" + +namespace LastExpress { + +#define CALL_FUNCTION0(fighter, name) \ + (*fighter->name)(fighter) + +#define CALL_FUNCTION1(fighter, name, a) \ + (*fighter->name)(fighter, a) + +#define REGISTER_PLAYER_FUNCTIONS(name) \ + if (!_data) \ + error("Fight::load##namePlayer - invalid data!"); \ + _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleAction##name); \ + _data->player->update = new Common::Functor1Mem(this, &Fight::update##name); \ + _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract##name); + +#define REGISTER_OPPONENT_FUNCTIONS(name) \ + if (!_data) \ + error("Fight::load##nameOpponent - invalid data!"); \ + _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleOpponentAction##name); \ + _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponent##name); \ + _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); + +#define CHECK_SEQUENCE2(fighter, value) \ + (fighter->frame->getInfo()->field_33 & value) + +Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {} + +Fight::~Fight() { + clearData(); + _data = NULL; + + // Zero passed pointers + _engine = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Events +////////////////////////////////////////////////////////////////////////// + +void Fight::eventMouse(const Common::Event &ev) { + if (!_data || _data->index) + return; + + // TODO move all the egg handling to inventory functions + + getFlags()->mouseLeftClick = false; + getFlags()->shouldRedraw = false; + getFlags()->mouseRightClick = false; + + if (ev.mouse.x < 608 || ev.mouse.y < 448 || ev.mouse.x >= 640 || ev.mouse.x >= 480) { + + // Handle right button click + if (ev.type == Common::EVENT_RBUTTONUP) { + getSound()->removeFromQueue(kEntityTables0); + setStopped(); + + getGlobalTimer() ? _state = 0 : ++_state; + + getFlags()->mouseRightClick = true; + } + + if (_handleTimer) { + // Timer expired => show with full brightness + if (!getGlobalTimer()) + getInventory()->drawBlinkingEgg(); + + _handleTimer = false; + } + + // Check hotspots + Scene *scene = getScenes()->get(getState()->scene); + SceneHotspot *hotspot = NULL; + + if (!scene->checkHotSpot(ev.mouse, &hotspot)) { + _engine->getCursor()->setStyle(kCursorNormal); + } else { + _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); + + // Call player function + if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { + if (ev.type == Common::EVENT_LBUTTONUP) + CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action); + } else { + _engine->getCursor()->setStyle(kCursorNormal); + } + } + } else { + // Handle clicks on menu icon + + if (!_handleTimer) { + // Timer expired => show with full brightness + if (!getGlobalTimer()) + getInventory()->drawBlinkingEgg(); + + _handleTimer = true; + } + + // Stop fight if clicked + if (ev.type == Common::EVENT_LBUTTONUP) { + _handleTimer = false; + getSound()->removeFromQueue(kEntityTables0); + bailout(kFightEndExit); + } + + // Reset timer on right click + if (ev.type == Common::EVENT_RBUTTONUP) { + if (getGlobalTimer()) { + if (getSound()->isBuffered("TIMER")) + getSound()->removeFromQueue("TIMER"); + + setGlobalTimer(900); + } + } + } + + getFlags()->shouldRedraw = true; +} + +void Fight::eventTick(const Common::Event &ev) { + handleTick(ev, true); +} + +void Fight::handleTick(const Common::Event &ev, bool isProcessing) { + // TODO move all the egg handling to inventory functions + + // Blink egg + if (getGlobalTimer()) { + warning("Fight::handleMouseMove - egg blinking not implemented!"); + } + + if (!_data || _data->index) + return; + + SceneHotspot *hotspot = NULL; + if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { + _engine->getCursor()->setStyle(kCursorNormal); + } else { + _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); + } + + CALL_FUNCTION0(_data->player, update); + CALL_FUNCTION0(_data->opponent, update); + + // Draw sequences + if (!_data->isRunning) + return; + + if (isProcessing) + getScenes()->drawFrames(true); + + if (_data->index) { + // Set next sequence name index + _data->index--; + _data->sequences[_data->index] = loadSequence(_data->names[_data->index]); + } +} + +////////////////////////////////////////////////////////////////////////// +// Setup +////////////////////////////////////////////////////////////////////////// + +Fight::FightEndType Fight::setup(FightType type) { + if (_data) + error("Fight::setup - calling fight setup again while a fight is already in progress!"); + + ////////////////////////////////////////////////////////////////////////// + // Prepare UI & state + if (_state >= 5 && (type == kFightSalko || type == kFightVesna)) { + _state = 0; + return kFightEndWin; + } + + getInventory()->showHourGlass(); + // TODO events function + getFlags()->flag_0 = false; + getFlags()->mouseRightClick = false; + getEntities()->reset(); + + // Compute scene to use + SceneIndex sceneIndex; + switch(type) { + default: + sceneIndex = kSceneFightDefault; + break; + + case kFightMilos: + sceneIndex = (getObjects()->get(kObjectCompartment1).location2 < kObjectLocation3) ? kSceneFightMilos : kSceneFightMilosBedOpened; + break; + + case kFightAnna: + sceneIndex = kSceneFightAnna; + break; + + case kFightIvo: + sceneIndex = kSceneFightIvo; + break; + + case kFightSalko: + sceneIndex = kSceneFightSalko; + break; + + case kFightVesna: + sceneIndex = kSceneFightVesna; + break; + } + + if (getFlags()->shouldRedraw) { + getFlags()->shouldRedraw = false; + askForRedraw(); + //redrawScreen(); + } + + // Load the scene object + Scene *scene = getScenes()->get(sceneIndex); + + // Update game entities and state + getEntityData(kEntityPlayer)->entityPosition = scene->entityPosition; + getEntityData(kEntityPlayer)->location = scene->location; + + getState()->scene = sceneIndex; + + getFlags()->flag_3 = true; + + // Draw the scene + _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC); + // FIXME move to start of fight? + askForRedraw(); + redrawScreen(); + + ////////////////////////////////////////////////////////////////////////// + // Setup the fight + _data = new FightData; + loadData(type); + + // Show opponents & egg button + Common::Event emptyEvent; + handleTick(emptyEvent, false); + getInventory()->drawEgg(); + + // Start fight + _endType = kFightEndLost; + while (_data->isRunning) { + if (_engine->handleEvents()) + continue; + + getSound()->updateQueue(); + } + + // Cleanup after fight is over + clearData(); + + return _endType; +} + +////////////////////////////////////////////////////////////////////////// +// Status +////////////////////////////////////////////////////////////////////////// + +void Fight::setStopped() { + if (_data) + _data->isRunning = false; +} + +void Fight::bailout(FightEndType type) { + _state = 0; + _endType = type; + setStopped(); +} + +////////////////////////////////////////////////////////////////////////// +// Cleanup +////////////////////////////////////////////////////////////////////////// + +void Fight::clearData() { + if (!_data) + return; + + // Clear data + clearSequences(_data->player); + clearSequences(_data->opponent); + + SAFE_DELETE(_data->player); + SAFE_DELETE(_data->opponent); + + SAFE_DELETE(_data); + + _engine->restoreEventHandlers(); +} + +void Fight::clearSequences(Fighter *combatant) const { + if (!combatant) + return; + + // The original game resets the function pointers to default values, just before deleting the struct + getScenes()->removeAndRedraw(&combatant->frame, false); + + // Free sequences + for (int i = 0; i < (int)combatant->sequences.size(); i++) + SAFE_DELETE(combatant->sequences[i]); +} + +////////////////////////////////////////////////////////////////////////// +// Drawing +////////////////////////////////////////////////////////////////////////// + +void Fight::setSequenceAndDraw(Fighter *combatant, uint32 sequenceIndex, FightSequenceType type) const { + if (combatant->sequences.size() < sequenceIndex) + return; + + switch (type) { + default: + break; + + case kFightSequenceType0: + if (combatant->sequenceIndex) + return; + + combatant->sequence = combatant->sequences[sequenceIndex]; + combatant->sequenceIndex = sequenceIndex; + draw(combatant); + break; + + case kFightSequenceType1: + combatant->sequence = combatant->sequences[sequenceIndex]; + combatant->sequenceIndex = sequenceIndex; + combatant->sequenceIndex2 = 0; + draw(combatant); + break; + + case kFightSequenceType2: + combatant->sequenceIndex2 = sequenceIndex; + break; + } +} + +void Fight::draw(Fighter *combatant) const { + getScenes()->removeAndRedraw(&combatant->frame, false); + + combatant->frameIndex = 0; + combatant->field_24 = 0; +} + +////////////////////////////////////////////////////////////////////////// +// Loading +////////////////////////////////////////////////////////////////////////// + +void Fight::loadData(FightType type) { + if (!_data) + error("Fight::loadData - invalid data!"); + + switch (type) { + default: + break; + + case kFightMilos: + loadMilosPlayer(); + loadMilosOpponent(); + break; + + case kFightAnna: + loadAnnaPlayer(); + loadAnnaOpponent(); + break; + + case kFightIvo: + loadIvoPlayer(); + loadIvoOpponent(); + break; + + case kFightSalko: + loadSalkoPlayer(); + loadSalkoOpponent(); + break; + + case kFightVesna: + loadVesnaPlayer(); + loadVesnaOpponent(); + break; + } + + if (!_data->player || !_data->opponent) + error("Fight::loadData - error loading fight data (type=%d)", type); + + ////////////////////////////////////////////////////////////////////////// + // Start running the fight + _data->isRunning = true; + + if (_state < 5) { + setSequenceAndDraw(_data->player, 0, kFightSequenceType0); + setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); + goto end_load; + } + + switch(type) { + default: + break; + + case kFightMilos: + _data->opponent->countdown = 1; + setSequenceAndDraw(_data->player, 4, kFightSequenceType0); + setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); + break; + + case kFightIvo: + _data->opponent->countdown = 1; + setSequenceAndDraw(_data->player, 3, kFightSequenceType0); + setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0); + break; + + case kFightVesna: + _data->opponent->countdown = 1; + setSequenceAndDraw(_data->player, 0, kFightSequenceType0); + setSequenceAndDraw(_data->player, 3, kFightSequenceType2); + setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0); + break; + } + +end_load: + // Setup event handlers + _engine->backupEventHandlers(); + SET_EVENT_HANDLERS(Fight, this); +} + +////////////////////////////////////////////////////////////////////////// +// Shared +////////////////////////////////////////////////////////////////////////// +void Fight::processFighter(Fighter *fighter) { + if (!_data) + error("Fight::processFighter - invalid data!"); + + if (!fighter->sequence) { + if (fighter->frame) { + getScenes()->removeFromQueue(fighter->frame); + getScenes()->setCoordinates(fighter->frame); + } + SAFE_DELETE(fighter->frame); + return; + } + + if (fighter->sequence->count() <= fighter->frameIndex) { + switch(fighter->action) { + default: + break; + + case kFightAction101: + setSequenceAndDraw(fighter, fighter->sequenceIndex2, kFightSequenceType1); + fighter->sequenceIndex2 = 0; + break; + + case kFightActionResetFrame: + fighter->frameIndex = 0; + break; + + case kFightAction103: + setSequenceAndDraw(fighter, 0, kFightSequenceType1); + CALL_FUNCTION1(fighter, handleAction, kFightAction101); + setSequenceAndDraw(fighter->opponent, 0, kFightSequenceType1); + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction101); + CALL_FUNCTION0(fighter->opponent, update); + break; + + case kFightActionWin: + bailout(kFightEndWin); + break; + + case kFightActionLost: + bailout(kFightEndLost); + break; + } + } + + if (_data->isRunning) { + + // Get the current sequence frame + SequenceFrame *frame = new SequenceFrame(fighter->sequence, (uint16)fighter->frameIndex); + frame->getInfo()->location = 1; + + if (fighter->frame == frame) { + delete frame; + return; + } + + getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31); + + // Add current frame to queue and advance + getScenes()->addToQueue(frame); + fighter->frameIndex++; + + if (fighter->frame) { + getScenes()->removeFromQueue(fighter->frame); + + if (!frame->getInfo()->field_2E) + getScenes()->setCoordinates(fighter->frame); + } + + // Replace by new frame + delete fighter->frame; + fighter->frame = frame; + } +} + +void Fight::handleAction(Fighter *fighter, FightAction action) { + switch (action) { + default: + return; + + case kFightAction101: + break; + + case kFightActionResetFrame: + fighter->countdown--; + break; + + case kFightAction103: + CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); + break; + + case kFightActionWin: + _endType = kFightEndWin; + CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); + break; + + case kFightActionLost: + _endType = kFightEndLost; + CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); + break; + } + + // Update action + fighter->action = action; +} + +bool Fight::canInteract(Fighter const *fighter, FightAction /*= (FightAction)0*/ ) { + return (fighter->action == kFightAction101 && !fighter->sequenceIndex); +} + +void Fight::update(Fighter *fighter) { + + processFighter(fighter); + + if (fighter->frame) + fighter->frame->getInfo()->location = (fighter->action == kFightActionResetFrame ? 2 : 0); +} + +void Fight::updateOpponent(Fighter *fighter) { + + // This is an opponent struct! + Opponent *opponent = (Opponent *)fighter; + + processFighter(opponent); + + if (opponent->field_38 && !opponent->sequenceIndex) + opponent->field_38--; + + if (fighter->frame) + fighter->frame->getInfo()->location = 1; +} + +////////////////////////////////////////////////////////////////////////// +// Milos +////////////////////////////////////////////////////////////////////////// + +void Fight::loadMilosPlayer() { + REGISTER_PLAYER_FUNCTIONS(Milos) + + _data->player->sequences.push_back(loadSequence("2001cr.seq")); + _data->player->sequences.push_back(loadSequence("2001cdl.seq")); + _data->player->sequences.push_back(loadSequence("2001cdr.seq")); + _data->player->sequences.push_back(loadSequence("2001cdm.seq")); + _data->player->sequences.push_back(loadSequence("2001csgr.seq")); + _data->player->sequences.push_back(loadSequence("2001csgl.seq")); + _data->player->sequences.push_back(loadSequence("2001dbk.seq")); +} + +void Fight::loadMilosOpponent() { + REGISTER_OPPONENT_FUNCTIONS(Milos) + + _data->opponent->sequences.push_back(loadSequence("2001or.seq")); + _data->opponent->sequences.push_back(loadSequence("2001oal.seq")); + _data->opponent->sequences.push_back(loadSequence("2001oam.seq")); + _data->opponent->sequences.push_back(loadSequence("2001okl.seq")); + _data->opponent->sequences.push_back(loadSequence("2001okm.seq")); + _data->opponent->sequences.push_back(loadSequence("2001dbk.seq")); + _data->opponent->sequences.push_back(loadSequence("2001wbk.seq")); + + getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault); + + _data->opponent->field_38 = 35; +} + +void Fight::handleActionMilos(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + return; + + case kFightAction1: + if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 6, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 3, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction2: + if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 6, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction128: + if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4) || fighter->opponent->sequenceIndex != 1) { + switch (fighter->opponent->sequenceIndex) { + default: + setSequenceAndDraw(fighter, rnd(3) + 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(fighter, 1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(fighter, 3, kFightSequenceType0); + break; + } + } else { + setSequenceAndDraw(fighter, 4, kFightSequenceType1); + CALL_FUNCTION0(fighter, update); + } + break; + } +} + +void Fight::updateMilos(Fighter *fighter) { + if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { + + // Draw sequences + if (fighter->opponent->countdown <= 0) { + setSequenceAndDraw(fighter, 5, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); + + getSound()->removeFromQueue(kEntityTables0); + getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault); + + CALL_FUNCTION1(fighter, handleAction, kFightActionWin); + } + + if (fighter->sequenceIndex == 4) { + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction4); + _endType = kFightEndLost; + } + } + + update(fighter); +} + +bool Fight::canInteractMilos(Fighter const *fighter, FightAction action) { + if (!_data) + error("Fight::canInteractMilos - invalid data!"); + + if (action != kFightAction128 + || _data->player->sequenceIndex != 1 + || !fighter->frame + || CHECK_SEQUENCE2(fighter, 4) + || fighter->opponent->sequenceIndex != 1) { + return canInteract(fighter); + } + + _engine->getCursor()->setStyle(kCursorHand); + + return true; +} + +void Fight::handleOpponentActionMilos(Fighter *fighter, FightAction action) { + if (action == kFightAction4) { + setSequenceAndDraw(fighter, 5, kFightSequenceType1); + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + } else { + if (action != kFightAction131) + handleAction(fighter, action); + } +} + +void Fight::updateOpponentMilos(Fighter *fighter) { + // This is an opponent struct! + Opponent *opponent = (Opponent *)fighter; + + if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { + + if (opponent->opponent->field_34 >= 2) { + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType1); + break; + + case 3: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + } + } else { + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + } + + // Update field_38 + if (opponent->opponent->field_34 < 5) + opponent->field_38 = 6 * (5 - opponent->opponent->field_34); + else + opponent->field_38 = 0; + } + + if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { + if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) + CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); + + if (opponent->opponent->countdown <= 0) { + getSound()->removeFromQueue(kEntityTables0); + CALL_FUNCTION1(opponent, handleAction, kFightActionLost); + } + } + + updateOpponent(opponent); +} + +////////////////////////////////////////////////////////////////////////// +// Anna +////////////////////////////////////////////////////////////////////////// + +void Fight::loadAnnaPlayer() { + if (!_data) + error("Fight::loadAnnaPlayer - invalid data!"); + + // Special case: we are using some shared functions directly + _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleActionAnna); + _data->player->update = new Common::Functor1Mem(this, &Fight::update); + _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); + + _data->player->sequences.push_back(loadSequence("2002cr.seq")); + _data->player->sequences.push_back(loadSequence("2002cdl.seq")); + _data->player->sequences.push_back(loadSequence("2002cdr.seq")); + _data->player->sequences.push_back(loadSequence("2002cdm.seq")); + _data->player->sequences.push_back(loadSequence("2002lbk.seq")); +} + +void Fight::loadAnnaOpponent() { + if (!_data) + error("Fight::loadAnnaOpponent - invalid data!"); + + // Special case: we are using some shared functions directly + _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleAction); + _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponentAnna); + _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); + + _data->opponent->sequences.push_back(loadSequence("2002or.seq")); + _data->opponent->sequences.push_back(loadSequence("2002oal.seq")); + _data->opponent->sequences.push_back(loadSequence("2002oam.seq")); + _data->opponent->sequences.push_back(loadSequence("2002oar.seq")); + _data->opponent->sequences.push_back(loadSequence("2002okr.seq")); + _data->opponent->sequences.push_back(loadSequence("2002okml.seq")); + _data->opponent->sequences.push_back(loadSequence("2002okm.seq")); + + getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault); + + _data->opponent->field_38 = 30; +} + +void Fight::handleActionAnna(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + return; + + case kFightAction1: + if ((fighter->sequenceIndex != 1 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 4, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction2: + if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 4, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction3: + if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 1) || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 4, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction128: + switch (fighter->opponent->sequenceIndex) { + default: + setSequenceAndDraw(fighter, 3, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(fighter, 1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(fighter, 3, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(fighter, 2, kFightSequenceType0); + break; + } + break; + } + + if (fighter->field_34 > 4) { + getSound()->removeFromQueue(kEntityTables0); + bailout(kFightEndWin); + } +} + +void Fight::updateOpponentAnna(Fighter *fighter) { + // This is an opponent struct! + Opponent *opponent = (Opponent *)fighter; + + if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { + + if (opponent->opponent->field_34 >= 2) { + switch (rnd(6)) { + default: + break; + + case 0: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(opponent, 3, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(opponent, 3, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 5: + setSequenceAndDraw(opponent, 3, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + } + } + + // Update field_38 + opponent->field_38 = (int32)rnd(15); + } + + if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { + if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 3) + CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); + + if (opponent->opponent->countdown <= 0) { + getSound()->removeFromQueue(kEntityTables0); + CALL_FUNCTION1(opponent, handleAction, kFightActionLost); + } + } + + updateOpponent(opponent); +} + +////////////////////////////////////////////////////////////////////////// +// Ivo +////////////////////////////////////////////////////////////////////////// + +void Fight::loadIvoPlayer() { + REGISTER_PLAYER_FUNCTIONS(Ivo) + + _data->player->sequences.push_back(loadSequence("2003cr.seq")); + _data->player->sequences.push_back(loadSequence("2003car.seq")); + _data->player->sequences.push_back(loadSequence("2003cal.seq")); + _data->player->sequences.push_back(loadSequence("2003cdr.seq")); + _data->player->sequences.push_back(loadSequence("2003cdm.seq")); + _data->player->sequences.push_back(loadSequence("2003chr.seq")); + _data->player->sequences.push_back(loadSequence("2003chl.seq")); + _data->player->sequences.push_back(loadSequence("2003ckr.seq")); + _data->player->sequences.push_back(loadSequence("2003lbk.seq")); + _data->player->sequences.push_back(loadSequence("2003fbk.seq")); + + _data->player->countdown = 5; +} + +void Fight::loadIvoOpponent() { + REGISTER_OPPONENT_FUNCTIONS(Ivo) + + _data->opponent->sequences.push_back(loadSequence("2003or.seq")); + _data->opponent->sequences.push_back(loadSequence("2003oal.seq")); + _data->opponent->sequences.push_back(loadSequence("2003oar.seq")); + _data->opponent->sequences.push_back(loadSequence("2003odm.seq")); + _data->opponent->sequences.push_back(loadSequence("2003okl.seq")); + _data->opponent->sequences.push_back(loadSequence("2003okj.seq")); + _data->opponent->sequences.push_back(loadSequence("blank.seq")); + _data->opponent->sequences.push_back(loadSequence("csdr.seq")); + _data->opponent->sequences.push_back(loadSequence("2003l.seq")); + + getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault); + + _data->opponent->countdown = 5; + _data->opponent->field_38 = 15; +} + +void Fight::handleActionIvo(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + return; + + case kFightAction1: + if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 7, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } + break; + + case kFightAction2: + if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 7, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } + break; + + case kFightAction128: + switch (fighter->opponent->sequenceIndex) { + default: + case 1: + setSequenceAndDraw(fighter, 1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(fighter, 2, kFightSequenceType0); + break; + } + break; + + case kFightAction129: + setSequenceAndDraw(fighter, (fighter->opponent->countdown > 1) ? 4 : 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); + break; + + case kFightAction130: + setSequenceAndDraw(fighter, 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); + break; + } +} + +void Fight::updateIvo(Fighter *fighter) { + + if ((fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) && !fighter->frameIndex) + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction131); + + if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { + + // Draw sequences + if (fighter->opponent->countdown <= 0) { + setSequenceAndDraw(fighter, 9, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, 8, kFightSequenceType1); + getSound()->removeFromQueue(kEntityTables0); + + CALL_FUNCTION1(fighter, handleAction, kFightActionWin); + return; + } + + if (fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) + CALL_FUNCTION1(fighter->opponent, handleAction, (FightAction)fighter->sequenceIndex); + } + + update(fighter); +} + +bool Fight::canInteractIvo(Fighter const *fighter, FightAction action) { + if (action == kFightAction129 || action == kFightAction130) + return (fighter->sequenceIndex >= 8); + + return canInteract(fighter); +} + +void Fight::handleOpponentActionIvo(Fighter *fighter, FightAction action) { + // This is an opponent struct! + Opponent *opponent = (Opponent *)fighter; + + switch (action) { + default: + handleAction(fighter, action); + break; + + case kFightAction3: + if ((opponent->sequenceIndex != 1 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { + setSequenceAndDraw(opponent, 6, kFightSequenceType1); + setSequenceAndDraw(opponent->opponent, 6, kFightSequenceType1); + CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); + } + break; + + case kFightAction4: + if ((opponent->sequenceIndex != 2 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { + setSequenceAndDraw(opponent, 6, kFightSequenceType1); + setSequenceAndDraw(opponent->opponent, 5, kFightSequenceType1); + CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); + } + break; + + case kFightAction131: + if (opponent->sequenceIndex) + break; + + if (rnd(100) <= (unsigned int)(opponent->countdown > 2 ? 60 : 75)) { + setSequenceAndDraw(opponent, 3 , kFightSequenceType1); + if (opponent->opponent->sequenceIndex == 4) + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + } + break; + } +} + +void Fight::updateOpponentIvo(Fighter *fighter) { + // This is an opponent struct! + Opponent *opponent = (Opponent *)fighter; + + if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { + + if (opponent->opponent->field_34 >= 2) { + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 3: + setSequenceAndDraw(opponent, 0, kFightSequenceType2); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(opponent, 0, kFightSequenceType1); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + } + } + + // Update field_38 + opponent->field_38 = 3 * opponent->countdown + (int32)rnd(10); + } + + if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { + + if (opponent->opponent->countdown <= 0) { + setSequenceAndDraw(opponent, 7, kFightSequenceType1); + setSequenceAndDraw(opponent->opponent, 8, kFightSequenceType1); + getSound()->removeFromQueue(kEntityTables0); + + CALL_FUNCTION1(opponent->opponent, handleAction, kFightActionWin); + + return; + } + + if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) + CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); + } + + updateOpponent(opponent); +} + +////////////////////////////////////////////////////////////////////////// +// Salko +////////////////////////////////////////////////////////////////////////// + +void Fight::loadSalkoPlayer() { + REGISTER_PLAYER_FUNCTIONS(Salko) + + _data->player->sequences.push_back(loadSequence("2004cr.seq")); + _data->player->sequences.push_back(loadSequence("2004cdr.seq")); + _data->player->sequences.push_back(loadSequence("2004chj.seq")); + _data->player->sequences.push_back(loadSequence("2004bk.seq")); + + _data->player->countdown = 2; +} + +void Fight::loadSalkoOpponent() { + REGISTER_OPPONENT_FUNCTIONS(Salko) + + _data->opponent->sequences.push_back(loadSequence("2004or.seq")); + _data->opponent->sequences.push_back(loadSequence("2004oam.seq")); + _data->opponent->sequences.push_back(loadSequence("2004oar.seq")); + _data->opponent->sequences.push_back(loadSequence("2004okr.seq")); + _data->opponent->sequences.push_back(loadSequence("2004ohm.seq")); + _data->opponent->sequences.push_back(loadSequence("blank.seq")); + + getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault); + + _data->opponent->countdown = 3; + _data->opponent->field_38 = 30; +} + +void Fight::handleActionSalko(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + return; + + case kFightAction1: + case kFightAction2: + if (fighter->sequenceIndex != 1 && CHECK_SEQUENCE2(fighter, 4)) { + fighter->field_34 = 0; + + setSequenceAndDraw(fighter, 3, kFightSequenceType1); + setSequenceAndDraw(fighter->opponent, (action == kFightAction1 ? 3 : 4), kFightSequenceType1); + + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + + if (action == kFightAction2) + fighter->countdown= 0; + + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction5: + if (fighter->sequenceIndex != 3) { + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } + break; + + case kFightAction128: + setSequenceAndDraw(fighter, 1, kFightSequenceType0); + fighter->field_34 = 0; + break; + + case kFightAction131: + setSequenceAndDraw(fighter, 2, (fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0)); + break; + } +} + +void Fight::updateSalko(Fighter *fighter) { + update(fighter); + + // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation) + if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { + + if (fighter->opponent->countdown <= 0) { + getSound()->removeFromQueue(kEntityTables0); + bailout(kFightEndWin); + + return; + } + + if (fighter->sequenceIndex == 2) + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction2); + } +} + +bool Fight::canInteractSalko(Fighter const *fighter, FightAction action) { + if (action == kFightAction131) { + if (fighter->sequenceIndex == 1) { + if (fighter->opponent->countdown <= 0) + _engine->getCursor()->setStyle(kCursorHand); + + return true; + } + + return false; + } + + return canInteract(fighter); +} + +void Fight::handleOpponentActionSalko(Fighter *fighter, FightAction action) { + if (action == kFightAction2) { + setSequenceAndDraw(fighter, 5, kFightSequenceType1); + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + } else { + handleAction(fighter, action); + } +} + +void Fight::updateOpponentSalko(Fighter *fighter) { + // This is an opponent struct + Opponent *opponent = (Opponent *)fighter; + + if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { + + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 3: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + } + + // Update field_38 + opponent->field_38 = 4 * opponent->countdown; + } + + if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { + if (opponent->opponent->countdown <= 0) { + getSound()->removeFromQueue(kEntityTables0); + bailout(kFightEndLost); + + // Stop processing + return; + } + + if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) + CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); + } + + updateOpponent(opponent); +} + +////////////////////////////////////////////////////////////////////////// +// Vesna +////////////////////////////////////////////////////////////////////////// + +void Fight::loadVesnaPlayer() { + REGISTER_PLAYER_FUNCTIONS(Vesna) + + _data->player->sequences.push_back(loadSequence("2005cr.seq")); + _data->player->sequences.push_back(loadSequence("2005cdr.seq")); + _data->player->sequences.push_back(loadSequence("2005cbr.seq")); + _data->player->sequences.push_back(loadSequence("2005bk.seq")); + _data->player->sequences.push_back(loadSequence("2005cdm1.seq")); + _data->player->sequences.push_back(loadSequence("2005chl.seq")); +} + +void Fight::loadVesnaOpponent() { + REGISTER_OPPONENT_FUNCTIONS(Vesna) + + _data->opponent->sequences.push_back(loadSequence("2005or.seq")); + _data->opponent->sequences.push_back(loadSequence("2005oam.seq")); + _data->opponent->sequences.push_back(loadSequence("2005oar.seq")); + _data->opponent->sequences.push_back(loadSequence("2005okml.seq")); + _data->opponent->sequences.push_back(loadSequence("2005okr.seq")); + _data->opponent->sequences.push_back(loadSequence("2005odm1.seq")); + _data->opponent->sequences.push_back(loadSequence("2005csbm.seq")); + _data->opponent->sequences.push_back(loadSequence("2005oam4.seq")); + + getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault); + + _data->opponent->countdown = 4; + _data->opponent->field_38 = 30; +} + +void Fight::handleActionVesna(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + return; + + case kFightAction1: + if (fighter->sequenceIndex != 1) { + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction2: + if (fighter->sequenceIndex != 2) { + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } else { + fighter->field_34++; + } + break; + + case kFightAction5: + if (fighter->sequenceIndex != 3) { + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + CALL_FUNCTION0(fighter, update); + } + break; + + case kFightAction128: + if (fighter->sequenceIndex == 1 && fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { + setSequenceAndDraw(fighter, 5, kFightSequenceType1); + } else { + setSequenceAndDraw(fighter, (fighter->opponent->sequenceIndex == 5) ? 3 : 1, kFightSequenceType0); + } + break; + + case kFightAction132: + setSequenceAndDraw(fighter, 2, kFightSequenceType0); + break; + } + + if (fighter->field_34 > 10) { + setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType2); + fighter->opponent->countdown = 1; + fighter->field_34 = 0; + } +} + +void Fight::updateVesna(Fighter *fighter) { + if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { + + if (fighter->sequenceIndex == 3) + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction3); + + if (fighter->opponent->countdown <= 0) { + getSound()->removeFromQueue(kEntityTables0); + bailout(kFightEndWin); + return; + } + + if (fighter->sequenceIndex == 5) + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction5); + } + + update(fighter); +} + +bool Fight::canInteractVesna(Fighter const *fighter, FightAction action) { + if (action != kFightAction128) + return canInteract(fighter); + + if (fighter->sequenceIndex != 1) { + + if (fighter->opponent->sequenceIndex == 5) { + _engine->getCursor()->setStyle(kCursorDown); + return true; + } + + return canInteract(fighter); + } + + if (fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { + _engine->getCursor()->setStyle(kCursorPunchLeft); + return true; + } + + return false; +} + +void Fight::handleOpponentActionVesna(Fighter *fighter, FightAction action) { + switch (action) { + default: + handleAction(fighter, action); + break; + + case kFightAction3: + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + break; + + case kFightAction5: + setSequenceAndDraw(fighter, 7, kFightSequenceType1); + CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); + if (fighter->countdown <= 1) + fighter->countdown = 1; + break; + + case kFightAction131: + break; + } +} + +void Fight::updateOpponentVesna(Fighter *fighter) { + // This is an opponent struct + Opponent *opponent = (Opponent *)fighter; + + if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { + + if (opponent->opponent->field_34 == 1) { + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + } else { + switch (rnd(6)) { + default: + break; + + case 0: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + + case 2: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(opponent, 1, kFightSequenceType0); + setSequenceAndDraw(opponent, 2, kFightSequenceType2); + break; + + case 5: + setSequenceAndDraw(opponent, 2, kFightSequenceType0); + setSequenceAndDraw(opponent, 1, kFightSequenceType2); + break; + } + } + + // Update field_38 + opponent->field_38 = 4 * opponent->countdown; + } + + if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { + if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 5) + CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); + + if (opponent->opponent->countdown <= 0) { + + switch (opponent->sequenceIndex) { + default: + break; + + case 1: + setSequenceAndDraw(opponent, 3, kFightSequenceType1); + break; + + case 2: + setSequenceAndDraw(opponent, 4, kFightSequenceType1); + break; + + case 5: + setSequenceAndDraw(opponent, 6, kFightSequenceType1); + break; + } + + setSequenceAndDraw(opponent->opponent, 4, kFightSequenceType1); + + CALL_FUNCTION1(opponent, handleAction, kFightActionLost); + CALL_FUNCTION0(opponent->opponent, update); + CALL_FUNCTION0(opponent, update); + + getSound()->removeFromQueue(kEntityTables0); + + // Stop processing + return; + } + } + + updateOpponent(opponent); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fight.h b/engines/lastexpress/fight/fight.h new file mode 100644 index 0000000000..a33cc93a29 --- /dev/null +++ b/engines/lastexpress/fight/fight.h @@ -0,0 +1,266 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHT_H +#define LASTEXPRESS_FIGHT_H + +/* + Fight structure + --------------- + uint32 {4} - player struct + uint32 {4} - opponent struct + uint32 {4} - hasLost flag + + byte {1} - isRunning + + Fight participant structure + --------------------------- + uint32 {4} - function pointer + uint32 {4} - pointer to fight structure + uint32 {4} - pointer to opponent (fight participant structure) + uint32 {4} - array of sequences + uint32 {4} - number of sequences + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint16 {2} - ?? + uint16 {2} - ?? - only for opponent structure + uint32 {4} - ?? - only for opponent structure + +*/ + +#include "lastexpress/shared.h" + +#include "lastexpress/eventhandler.h" + +#include "common/array.h" + +namespace LastExpress { + +class LastExpressEngine; +class Sequence; +class SequenceFrame; + +////////////////////////////////////////////////////////////////////////// +// TODO : objectify! +class Fight : public EventHandler { +public: + enum FightEndType { + kFightEndWin = 0, + kFightEndLost = 1, + kFightEndExit = 2 + }; + + Fight(LastExpressEngine *engine); + ~Fight(); + + FightEndType setup(FightType type); + + void eventMouse(const Common::Event &ev); + void eventTick(const Common::Event &ev); + + void setStopped(); + void resetState() { _state = 0; } + +private: + enum FightSequenceType { + kFightSequenceType0 = 0, + kFightSequenceType1 = 1, + kFightSequenceType2 = 2 + }; + + enum FightAction { + kFightAction1 = 1, + kFightAction2 = 2, + kFightAction3 = 3, + kFightAction4 = 4, + kFightAction5 = 5, + kFightAction101 = 101, + kFightActionResetFrame = 102, + kFightAction103 = 103, + kFightActionWin = 104, + kFightActionLost = 105, + kFightAction128 = 128, + kFightAction129 = 129, + kFightAction130 = 130, + kFightAction131 = 131, + kFightAction132 = 132 + }; + + struct Fighter { + Common::Functor2 *handleAction; + Common::Functor1 *update; + Common::Functor2 *canInteract; + Fighter *opponent; + Common::Array sequences; + uint32 sequenceIndex; + Sequence *sequence; + SequenceFrame *frame; + uint32 frameIndex; + uint32 field_24; + FightAction action; + uint32 sequenceIndex2; + int32 countdown; // countdown before loosing ? + uint32 field_34; + + Fighter() { + handleAction = NULL; + update = NULL; + canInteract = NULL; + + opponent = NULL; + + sequenceIndex = 0; + sequence = NULL; + frame = NULL; + frameIndex = 0; + + field_24 = 0; + + action = kFightAction101; + sequenceIndex2 = 0; + + countdown = 1; + + field_34 = 0; + } + }; + + // Opponent struct + struct Opponent : Fighter { + int32 field_38; + + Opponent() : Fighter() { + field_38 = 0; + } + }; + + struct FightData { + Fighter *player; + Opponent *opponent; + int32 index; + + Sequence *sequences[20]; + Common::String names[20]; + + bool isRunning; + + FightData() { + player = new Fighter(); + opponent = new Opponent(); + + // Set opponents + player->opponent = opponent; + opponent->opponent = player; + + index = 0; + + isRunning = false; + } + }; + + LastExpressEngine *_engine; + FightData *_data; + FightEndType _endType; + int _state; + + bool _handleTimer; + + // Events + void handleTick(const Common::Event &ev, bool unknown); + + // State + void bailout(FightEndType type); + + + // Drawing + void setSequenceAndDraw(Fighter *fighter, uint32 sequenceIndex, FightSequenceType type) const; + void draw(Fighter *fighter) const; + + // Cleanup + void clearData(); + void clearSequences(Fighter *fighter) const; + + ////////////////////////////////////////////////////////////////////////// + // Loading + void loadData(FightType type); + + // Shared + void processFighter(Fighter *fighter); + + // Default functions + void handleAction(Fighter *fighter, FightAction action); + void update(Fighter *fighter); + bool canInteract(Fighter const *fighter, FightAction = (FightAction)0); + void updateOpponent(Fighter *fighter); + + // Milos + void loadMilosPlayer(); + void loadMilosOpponent(); + void handleActionMilos(Fighter *fighter, FightAction action); + void updateMilos(Fighter *fighter); + bool canInteractMilos(Fighter const *fighter, FightAction action); + void handleOpponentActionMilos(Fighter *fighter, FightAction action); + void updateOpponentMilos(Fighter *fighter); + + // Anna + void loadAnnaPlayer(); + void loadAnnaOpponent(); + void handleActionAnna(Fighter *fighter, FightAction action); + void updateOpponentAnna(Fighter *fighter); + + // Ivo + void loadIvoPlayer(); + void loadIvoOpponent(); + void handleActionIvo(Fighter *fighter, FightAction action); + void updateIvo(Fighter *fighter); + bool canInteractIvo(Fighter const *fighter, FightAction action); + void handleOpponentActionIvo(Fighter *fighter, FightAction action); + void updateOpponentIvo(Fighter *fighter); + + // Salko + void loadSalkoPlayer(); + void loadSalkoOpponent(); + void handleActionSalko(Fighter *fighter, FightAction action); + void updateSalko(Fighter *fighter); + bool canInteractSalko(Fighter const *fighter, FightAction action); + void handleOpponentActionSalko(Fighter *fighter, FightAction action); + void updateOpponentSalko(Fighter *fighter); + + // Vesna + void loadVesnaPlayer(); + void loadVesnaOpponent(); + void handleActionVesna(Fighter *fighter, FightAction action); + void updateVesna(Fighter *fighter); + bool canInteractVesna(Fighter const *fighter, FightAction action); + void handleOpponentActionVesna(Fighter *fighter, FightAction action); + void updateOpponentVesna(Fighter *fighter); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHT_H diff --git a/engines/lastexpress/game/fight.cpp b/engines/lastexpress/game/fight.cpp deleted file mode 100644 index ecc43bed2b..0000000000 --- a/engines/lastexpress/game/fight.cpp +++ /dev/null @@ -1,1583 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "lastexpress/game/fight.h" - -#include "lastexpress/data/cursor.h" -#include "lastexpress/data/scene.h" -#include "lastexpress/data/sequence.h" - -#include "lastexpress/game/entities.h" -#include "lastexpress/game/inventory.h" -#include "lastexpress/game/logic.h" -#include "lastexpress/game/object.h" -#include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" -#include "lastexpress/game/state.h" - -#include "lastexpress/graphics.h" -#include "lastexpress/helpers.h" -#include "lastexpress/lastexpress.h" -#include "lastexpress/resource.h" - -#include "common/func.h" - -namespace LastExpress { - -#define CALL_FUNCTION0(fighter, name) \ - (*fighter->name)(fighter) - -#define CALL_FUNCTION1(fighter, name, a) \ - (*fighter->name)(fighter, a) - -#define REGISTER_PLAYER_FUNCTIONS(name) \ - if (!_data) \ - error("Fight::load##namePlayer - invalid data!"); \ - _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleAction##name); \ - _data->player->update = new Common::Functor1Mem(this, &Fight::update##name); \ - _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract##name); - -#define REGISTER_OPPONENT_FUNCTIONS(name) \ - if (!_data) \ - error("Fight::load##nameOpponent - invalid data!"); \ - _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleOpponentAction##name); \ - _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponent##name); \ - _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); - -#define CHECK_SEQUENCE2(fighter, value) \ - (fighter->frame->getInfo()->field_33 & value) - -Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {} - -Fight::~Fight() { - clearData(); - _data = NULL; - - // Zero passed pointers - _engine = NULL; -} - -////////////////////////////////////////////////////////////////////////// -// Events -////////////////////////////////////////////////////////////////////////// - -void Fight::eventMouse(const Common::Event &ev) { - if (!_data || _data->index) - return; - - // TODO move all the egg handling to inventory functions - - getFlags()->mouseLeftClick = false; - getFlags()->shouldRedraw = false; - getFlags()->mouseRightClick = false; - - if (ev.mouse.x < 608 || ev.mouse.y < 448 || ev.mouse.x >= 640 || ev.mouse.x >= 480) { - - // Handle right button click - if (ev.type == Common::EVENT_RBUTTONUP) { - getSound()->removeFromQueue(kEntityTables0); - setStopped(); - - getGlobalTimer() ? _state = 0 : ++_state; - - getFlags()->mouseRightClick = true; - } - - if (_handleTimer) { - // Timer expired => show with full brightness - if (!getGlobalTimer()) - getInventory()->drawBlinkingEgg(); - - _handleTimer = false; - } - - // Check hotspots - Scene *scene = getScenes()->get(getState()->scene); - SceneHotspot *hotspot = NULL; - - if (!scene->checkHotSpot(ev.mouse, &hotspot)) { - _engine->getCursor()->setStyle(kCursorNormal); - } else { - _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); - - // Call player function - if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { - if (ev.type == Common::EVENT_LBUTTONUP) - CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action); - } else { - _engine->getCursor()->setStyle(kCursorNormal); - } - } - } else { - // Handle clicks on menu icon - - if (!_handleTimer) { - // Timer expired => show with full brightness - if (!getGlobalTimer()) - getInventory()->drawBlinkingEgg(); - - _handleTimer = true; - } - - // Stop fight if clicked - if (ev.type == Common::EVENT_LBUTTONUP) { - _handleTimer = false; - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndExit); - } - - // Reset timer on right click - if (ev.type == Common::EVENT_RBUTTONUP) { - if (getGlobalTimer()) { - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); - - setGlobalTimer(900); - } - } - } - - getFlags()->shouldRedraw = true; -} - -void Fight::eventTick(const Common::Event &ev) { - handleTick(ev, true); -} - -void Fight::handleTick(const Common::Event &ev, bool isProcessing) { - // TODO move all the egg handling to inventory functions - - // Blink egg - if (getGlobalTimer()) { - warning("Fight::handleMouseMove - egg blinking not implemented!"); - } - - if (!_data || _data->index) - return; - - SceneHotspot *hotspot = NULL; - if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { - _engine->getCursor()->setStyle(kCursorNormal); - } else { - _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); - } - - CALL_FUNCTION0(_data->player, update); - CALL_FUNCTION0(_data->opponent, update); - - // Draw sequences - if (!_data->isRunning) - return; - - if (isProcessing) - getScenes()->drawFrames(true); - - if (_data->index) { - // Set next sequence name index - _data->index--; - _data->sequences[_data->index] = loadSequence(_data->names[_data->index]); - } -} - -////////////////////////////////////////////////////////////////////////// -// Setup -////////////////////////////////////////////////////////////////////////// - -Fight::FightEndType Fight::setup(FightType type) { - if (_data) - error("Fight::setup - calling fight setup again while a fight is already in progress!"); - - ////////////////////////////////////////////////////////////////////////// - // Prepare UI & state - if (_state >= 5 && (type == kFightSalko || type == kFightVesna)) { - _state = 0; - return kFightEndWin; - } - - getInventory()->showHourGlass(); - // TODO events function - getFlags()->flag_0 = false; - getFlags()->mouseRightClick = false; - getEntities()->reset(); - - // Compute scene to use - SceneIndex sceneIndex; - switch(type) { - default: - sceneIndex = kSceneFightDefault; - break; - - case kFightMilos: - sceneIndex = (getObjects()->get(kObjectCompartment1).location2 < kObjectLocation3) ? kSceneFightMilos : kSceneFightMilosBedOpened; - break; - - case kFightAnna: - sceneIndex = kSceneFightAnna; - break; - - case kFightIvo: - sceneIndex = kSceneFightIvo; - break; - - case kFightSalko: - sceneIndex = kSceneFightSalko; - break; - - case kFightVesna: - sceneIndex = kSceneFightVesna; - break; - } - - if (getFlags()->shouldRedraw) { - getFlags()->shouldRedraw = false; - askForRedraw(); - //redrawScreen(); - } - - // Load the scene object - Scene *scene = getScenes()->get(sceneIndex); - - // Update game entities and state - getEntityData(kEntityPlayer)->entityPosition = scene->entityPosition; - getEntityData(kEntityPlayer)->location = scene->location; - - getState()->scene = sceneIndex; - - getFlags()->flag_3 = true; - - // Draw the scene - _engine->getGraphicsManager()->draw(scene, GraphicsManager::kBackgroundC); - // FIXME move to start of fight? - askForRedraw(); - redrawScreen(); - - ////////////////////////////////////////////////////////////////////////// - // Setup the fight - _data = new FightData; - loadData(type); - - // Show opponents & egg button - Common::Event emptyEvent; - handleTick(emptyEvent, false); - getInventory()->drawEgg(); - - // Start fight - _endType = kFightEndLost; - while (_data->isRunning) { - if (_engine->handleEvents()) - continue; - - getSound()->updateQueue(); - } - - // Cleanup after fight is over - clearData(); - - return _endType; -} - -////////////////////////////////////////////////////////////////////////// -// Status -////////////////////////////////////////////////////////////////////////// - -void Fight::setStopped() { - if (_data) - _data->isRunning = false; -} - -void Fight::bailout(FightEndType type) { - _state = 0; - _endType = type; - setStopped(); -} - -////////////////////////////////////////////////////////////////////////// -// Cleanup -////////////////////////////////////////////////////////////////////////// - -void Fight::clearData() { - if (!_data) - return; - - // Clear data - clearSequences(_data->player); - clearSequences(_data->opponent); - - SAFE_DELETE(_data->player); - SAFE_DELETE(_data->opponent); - - SAFE_DELETE(_data); - - _engine->restoreEventHandlers(); -} - -void Fight::clearSequences(Fighter *combatant) const { - if (!combatant) - return; - - // The original game resets the function pointers to default values, just before deleting the struct - getScenes()->removeAndRedraw(&combatant->frame, false); - - // Free sequences - for (int i = 0; i < (int)combatant->sequences.size(); i++) - SAFE_DELETE(combatant->sequences[i]); -} - -////////////////////////////////////////////////////////////////////////// -// Drawing -////////////////////////////////////////////////////////////////////////// - -void Fight::setSequenceAndDraw(Fighter *combatant, uint32 sequenceIndex, FightSequenceType type) const { - if (combatant->sequences.size() < sequenceIndex) - return; - - switch (type) { - default: - break; - - case kFightSequenceType0: - if (combatant->sequenceIndex) - return; - - combatant->sequence = combatant->sequences[sequenceIndex]; - combatant->sequenceIndex = sequenceIndex; - draw(combatant); - break; - - case kFightSequenceType1: - combatant->sequence = combatant->sequences[sequenceIndex]; - combatant->sequenceIndex = sequenceIndex; - combatant->sequenceIndex2 = 0; - draw(combatant); - break; - - case kFightSequenceType2: - combatant->sequenceIndex2 = sequenceIndex; - break; - } -} - -void Fight::draw(Fighter *combatant) const { - getScenes()->removeAndRedraw(&combatant->frame, false); - - combatant->frameIndex = 0; - combatant->field_24 = 0; -} - -////////////////////////////////////////////////////////////////////////// -// Loading -////////////////////////////////////////////////////////////////////////// - -void Fight::loadData(FightType type) { - if (!_data) - error("Fight::loadData - invalid data!"); - - switch (type) { - default: - break; - - case kFightMilos: - loadMilosPlayer(); - loadMilosOpponent(); - break; - - case kFightAnna: - loadAnnaPlayer(); - loadAnnaOpponent(); - break; - - case kFightIvo: - loadIvoPlayer(); - loadIvoOpponent(); - break; - - case kFightSalko: - loadSalkoPlayer(); - loadSalkoOpponent(); - break; - - case kFightVesna: - loadVesnaPlayer(); - loadVesnaOpponent(); - break; - } - - if (!_data->player || !_data->opponent) - error("Fight::loadData - error loading fight data (type=%d)", type); - - ////////////////////////////////////////////////////////////////////////// - // Start running the fight - _data->isRunning = true; - - if (_state < 5) { - setSequenceAndDraw(_data->player, 0, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); - goto end_load; - } - - switch(type) { - default: - break; - - case kFightMilos: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 4, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); - break; - - case kFightIvo: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 3, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0); - break; - - case kFightVesna: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 0, kFightSequenceType0); - setSequenceAndDraw(_data->player, 3, kFightSequenceType2); - setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0); - break; - } - -end_load: - // Setup event handlers - _engine->backupEventHandlers(); - SET_EVENT_HANDLERS(Fight, this); -} - -////////////////////////////////////////////////////////////////////////// -// Shared -////////////////////////////////////////////////////////////////////////// -void Fight::processFighter(Fighter *fighter) { - if (!_data) - error("Fight::processFighter - invalid data!"); - - if (!fighter->sequence) { - if (fighter->frame) { - getScenes()->removeFromQueue(fighter->frame); - getScenes()->setCoordinates(fighter->frame); - } - SAFE_DELETE(fighter->frame); - return; - } - - if (fighter->sequence->count() <= fighter->frameIndex) { - switch(fighter->action) { - default: - break; - - case kFightAction101: - setSequenceAndDraw(fighter, fighter->sequenceIndex2, kFightSequenceType1); - fighter->sequenceIndex2 = 0; - break; - - case kFightActionResetFrame: - fighter->frameIndex = 0; - break; - - case kFightAction103: - setSequenceAndDraw(fighter, 0, kFightSequenceType1); - CALL_FUNCTION1(fighter, handleAction, kFightAction101); - setSequenceAndDraw(fighter->opponent, 0, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction101); - CALL_FUNCTION0(fighter->opponent, update); - break; - - case kFightActionWin: - bailout(kFightEndWin); - break; - - case kFightActionLost: - bailout(kFightEndLost); - break; - } - } - - if (_data->isRunning) { - - // Get the current sequence frame - SequenceFrame *frame = new SequenceFrame(fighter->sequence, (uint16)fighter->frameIndex); - frame->getInfo()->location = 1; - - if (fighter->frame == frame) { - delete frame; - return; - } - - getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31); - - // Add current frame to queue and advance - getScenes()->addToQueue(frame); - fighter->frameIndex++; - - if (fighter->frame) { - getScenes()->removeFromQueue(fighter->frame); - - if (!frame->getInfo()->field_2E) - getScenes()->setCoordinates(fighter->frame); - } - - // Replace by new frame - delete fighter->frame; - fighter->frame = frame; - } -} - -void Fight::handleAction(Fighter *fighter, FightAction action) { - switch (action) { - default: - return; - - case kFightAction101: - break; - - case kFightActionResetFrame: - fighter->countdown--; - break; - - case kFightAction103: - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - - case kFightActionWin: - _endType = kFightEndWin; - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - - case kFightActionLost: - _endType = kFightEndLost; - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - } - - // Update action - fighter->action = action; -} - -bool Fight::canInteract(Fighter const *fighter, FightAction /*= (FightAction)0*/ ) { - return (fighter->action == kFightAction101 && !fighter->sequenceIndex); -} - -void Fight::update(Fighter *fighter) { - - processFighter(fighter); - - if (fighter->frame) - fighter->frame->getInfo()->location = (fighter->action == kFightActionResetFrame ? 2 : 0); -} - -void Fight::updateOpponent(Fighter *fighter) { - - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - processFighter(opponent); - - if (opponent->field_38 && !opponent->sequenceIndex) - opponent->field_38--; - - if (fighter->frame) - fighter->frame->getInfo()->location = 1; -} - -////////////////////////////////////////////////////////////////////////// -// Milos -////////////////////////////////////////////////////////////////////////// - -void Fight::loadMilosPlayer() { - REGISTER_PLAYER_FUNCTIONS(Milos) - - _data->player->sequences.push_back(loadSequence("2001cr.seq")); - _data->player->sequences.push_back(loadSequence("2001cdl.seq")); - _data->player->sequences.push_back(loadSequence("2001cdr.seq")); - _data->player->sequences.push_back(loadSequence("2001cdm.seq")); - _data->player->sequences.push_back(loadSequence("2001csgr.seq")); - _data->player->sequences.push_back(loadSequence("2001csgl.seq")); - _data->player->sequences.push_back(loadSequence("2001dbk.seq")); -} - -void Fight::loadMilosOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Milos) - - _data->opponent->sequences.push_back(loadSequence("2001or.seq")); - _data->opponent->sequences.push_back(loadSequence("2001oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2001oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2001okl.seq")); - _data->opponent->sequences.push_back(loadSequence("2001okm.seq")); - _data->opponent->sequences.push_back(loadSequence("2001dbk.seq")); - _data->opponent->sequences.push_back(loadSequence("2001wbk.seq")); - - getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault); - - _data->opponent->field_38 = 35; -} - -void Fight::handleActionMilos(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 6, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 3, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 6, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction128: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4) || fighter->opponent->sequenceIndex != 1) { - switch (fighter->opponent->sequenceIndex) { - default: - setSequenceAndDraw(fighter, rnd(3) + 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - } - } else { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - CALL_FUNCTION0(fighter, update); - } - break; - } -} - -void Fight::updateMilos(Fighter *fighter) { - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - // Draw sequences - if (fighter->opponent->countdown <= 0) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); - - getSound()->removeFromQueue(kEntityTables0); - getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault); - - CALL_FUNCTION1(fighter, handleAction, kFightActionWin); - } - - if (fighter->sequenceIndex == 4) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction4); - _endType = kFightEndLost; - } - } - - update(fighter); -} - -bool Fight::canInteractMilos(Fighter const *fighter, FightAction action) { - if (!_data) - error("Fight::canInteractMilos - invalid data!"); - - if (action != kFightAction128 - || _data->player->sequenceIndex != 1 - || !fighter->frame - || CHECK_SEQUENCE2(fighter, 4) - || fighter->opponent->sequenceIndex != 1) { - return canInteract(fighter); - } - - _engine->getCursor()->setStyle(kCursorHand); - - return true; -} - -void Fight::handleOpponentActionMilos(Fighter *fighter, FightAction action) { - if (action == kFightAction4) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - } else { - if (action != kFightAction131) - handleAction(fighter, action); - } -} - -void Fight::updateOpponentMilos(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType1); - break; - - case 3: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } else { - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - } - - // Update field_38 - if (opponent->opponent->field_34 < 5) - opponent->field_38 = 6 * (5 - opponent->opponent->field_34); - else - opponent->field_38 = 0; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - } - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Anna -////////////////////////////////////////////////////////////////////////// - -void Fight::loadAnnaPlayer() { - if (!_data) - error("Fight::loadAnnaPlayer - invalid data!"); - - // Special case: we are using some shared functions directly - _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleActionAnna); - _data->player->update = new Common::Functor1Mem(this, &Fight::update); - _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); - - _data->player->sequences.push_back(loadSequence("2002cr.seq")); - _data->player->sequences.push_back(loadSequence("2002cdl.seq")); - _data->player->sequences.push_back(loadSequence("2002cdr.seq")); - _data->player->sequences.push_back(loadSequence("2002cdm.seq")); - _data->player->sequences.push_back(loadSequence("2002lbk.seq")); -} - -void Fight::loadAnnaOpponent() { - if (!_data) - error("Fight::loadAnnaOpponent - invalid data!"); - - // Special case: we are using some shared functions directly - _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleAction); - _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponentAnna); - _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); - - _data->opponent->sequences.push_back(loadSequence("2002or.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okml.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okm.seq")); - - getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault); - - _data->opponent->field_38 = 30; -} - -void Fight::handleActionAnna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if ((fighter->sequenceIndex != 1 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction3: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 1) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction128: - switch (fighter->opponent->sequenceIndex) { - default: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - break; - } - - if (fighter->field_34 > 4) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - } -} - -void Fight::updateOpponentAnna(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(6)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 5: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = (int32)rnd(15); - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 3) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - } - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Ivo -////////////////////////////////////////////////////////////////////////// - -void Fight::loadIvoPlayer() { - REGISTER_PLAYER_FUNCTIONS(Ivo) - - _data->player->sequences.push_back(loadSequence("2003cr.seq")); - _data->player->sequences.push_back(loadSequence("2003car.seq")); - _data->player->sequences.push_back(loadSequence("2003cal.seq")); - _data->player->sequences.push_back(loadSequence("2003cdr.seq")); - _data->player->sequences.push_back(loadSequence("2003cdm.seq")); - _data->player->sequences.push_back(loadSequence("2003chr.seq")); - _data->player->sequences.push_back(loadSequence("2003chl.seq")); - _data->player->sequences.push_back(loadSequence("2003ckr.seq")); - _data->player->sequences.push_back(loadSequence("2003lbk.seq")); - _data->player->sequences.push_back(loadSequence("2003fbk.seq")); - - _data->player->countdown = 5; -} - -void Fight::loadIvoOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Ivo) - - _data->opponent->sequences.push_back(loadSequence("2003or.seq")); - _data->opponent->sequences.push_back(loadSequence("2003oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2003oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2003odm.seq")); - _data->opponent->sequences.push_back(loadSequence("2003okl.seq")); - _data->opponent->sequences.push_back(loadSequence("2003okj.seq")); - _data->opponent->sequences.push_back(loadSequence("blank.seq")); - _data->opponent->sequences.push_back(loadSequence("csdr.seq")); - _data->opponent->sequences.push_back(loadSequence("2003l.seq")); - - getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault); - - _data->opponent->countdown = 5; - _data->opponent->field_38 = 15; -} - -void Fight::handleActionIvo(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - switch (fighter->opponent->sequenceIndex) { - default: - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - break; - - case kFightAction129: - setSequenceAndDraw(fighter, (fighter->opponent->countdown > 1) ? 4 : 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); - break; - - case kFightAction130: - setSequenceAndDraw(fighter, 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); - break; - } -} - -void Fight::updateIvo(Fighter *fighter) { - - if ((fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) && !fighter->frameIndex) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction131); - - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - // Draw sequences - if (fighter->opponent->countdown <= 0) { - setSequenceAndDraw(fighter, 9, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); - - CALL_FUNCTION1(fighter, handleAction, kFightActionWin); - return; - } - - if (fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) - CALL_FUNCTION1(fighter->opponent, handleAction, (FightAction)fighter->sequenceIndex); - } - - update(fighter); -} - -bool Fight::canInteractIvo(Fighter const *fighter, FightAction action) { - if (action == kFightAction129 || action == kFightAction130) - return (fighter->sequenceIndex >= 8); - - return canInteract(fighter); -} - -void Fight::handleOpponentActionIvo(Fighter *fighter, FightAction action) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - switch (action) { - default: - handleAction(fighter, action); - break; - - case kFightAction3: - if ((opponent->sequenceIndex != 1 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 6, kFightSequenceType1); - CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); - } - break; - - case kFightAction4: - if ((opponent->sequenceIndex != 2 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 5, kFightSequenceType1); - CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); - } - break; - - case kFightAction131: - if (opponent->sequenceIndex) - break; - - if (rnd(100) <= (unsigned int)(opponent->countdown > 2 ? 60 : 75)) { - setSequenceAndDraw(opponent, 3 , kFightSequenceType1); - if (opponent->opponent->sequenceIndex == 4) - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - } - break; - } -} - -void Fight::updateOpponentIvo(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 3: - setSequenceAndDraw(opponent, 0, kFightSequenceType2); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 0, kFightSequenceType1); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = 3 * opponent->countdown + (int32)rnd(10); - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - - if (opponent->opponent->countdown <= 0) { - setSequenceAndDraw(opponent, 7, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); - - CALL_FUNCTION1(opponent->opponent, handleAction, kFightActionWin); - - return; - } - - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Salko -////////////////////////////////////////////////////////////////////////// - -void Fight::loadSalkoPlayer() { - REGISTER_PLAYER_FUNCTIONS(Salko) - - _data->player->sequences.push_back(loadSequence("2004cr.seq")); - _data->player->sequences.push_back(loadSequence("2004cdr.seq")); - _data->player->sequences.push_back(loadSequence("2004chj.seq")); - _data->player->sequences.push_back(loadSequence("2004bk.seq")); - - _data->player->countdown = 2; -} - -void Fight::loadSalkoOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Salko) - - _data->opponent->sequences.push_back(loadSequence("2004or.seq")); - _data->opponent->sequences.push_back(loadSequence("2004oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2004oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2004okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2004ohm.seq")); - _data->opponent->sequences.push_back(loadSequence("blank.seq")); - - getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault); - - _data->opponent->countdown = 3; - _data->opponent->field_38 = 30; -} - -void Fight::handleActionSalko(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - case kFightAction2: - if (fighter->sequenceIndex != 1 && CHECK_SEQUENCE2(fighter, 4)) { - fighter->field_34 = 0; - - setSequenceAndDraw(fighter, 3, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, (action == kFightAction1 ? 3 : 4), kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - - if (action == kFightAction2) - fighter->countdown= 0; - - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction5: - if (fighter->sequenceIndex != 3) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - fighter->field_34 = 0; - break; - - case kFightAction131: - setSequenceAndDraw(fighter, 2, (fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0)); - break; - } -} - -void Fight::updateSalko(Fighter *fighter) { - update(fighter); - - // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation) - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - if (fighter->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - - return; - } - - if (fighter->sequenceIndex == 2) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction2); - } -} - -bool Fight::canInteractSalko(Fighter const *fighter, FightAction action) { - if (action == kFightAction131) { - if (fighter->sequenceIndex == 1) { - if (fighter->opponent->countdown <= 0) - _engine->getCursor()->setStyle(kCursorHand); - - return true; - } - - return false; - } - - return canInteract(fighter); -} - -void Fight::handleOpponentActionSalko(Fighter *fighter, FightAction action) { - if (action == kFightAction2) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - } else { - handleAction(fighter, action); - } -} - -void Fight::updateOpponentSalko(Fighter *fighter) { - // This is an opponent struct - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 3: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - - // Update field_38 - opponent->field_38 = 4 * opponent->countdown; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndLost); - - // Stop processing - return; - } - - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Vesna -////////////////////////////////////////////////////////////////////////// - -void Fight::loadVesnaPlayer() { - REGISTER_PLAYER_FUNCTIONS(Vesna) - - _data->player->sequences.push_back(loadSequence("2005cr.seq")); - _data->player->sequences.push_back(loadSequence("2005cdr.seq")); - _data->player->sequences.push_back(loadSequence("2005cbr.seq")); - _data->player->sequences.push_back(loadSequence("2005bk.seq")); - _data->player->sequences.push_back(loadSequence("2005cdm1.seq")); - _data->player->sequences.push_back(loadSequence("2005chl.seq")); -} - -void Fight::loadVesnaOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Vesna) - - _data->opponent->sequences.push_back(loadSequence("2005or.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2005okml.seq")); - _data->opponent->sequences.push_back(loadSequence("2005okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2005odm1.seq")); - _data->opponent->sequences.push_back(loadSequence("2005csbm.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oam4.seq")); - - getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault); - - _data->opponent->countdown = 4; - _data->opponent->field_38 = 30; -} - -void Fight::handleActionVesna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if (fighter->sequenceIndex != 2) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction5: - if (fighter->sequenceIndex != 3) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - if (fighter->sequenceIndex == 1 && fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - } else { - setSequenceAndDraw(fighter, (fighter->opponent->sequenceIndex == 5) ? 3 : 1, kFightSequenceType0); - } - break; - - case kFightAction132: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - - if (fighter->field_34 > 10) { - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType2); - fighter->opponent->countdown = 1; - fighter->field_34 = 0; - } -} - -void Fight::updateVesna(Fighter *fighter) { - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - if (fighter->sequenceIndex == 3) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction3); - - if (fighter->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - return; - } - - if (fighter->sequenceIndex == 5) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction5); - } - - update(fighter); -} - -bool Fight::canInteractVesna(Fighter const *fighter, FightAction action) { - if (action != kFightAction128) - return canInteract(fighter); - - if (fighter->sequenceIndex != 1) { - - if (fighter->opponent->sequenceIndex == 5) { - _engine->getCursor()->setStyle(kCursorDown); - return true; - } - - return canInteract(fighter); - } - - if (fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { - _engine->getCursor()->setStyle(kCursorPunchLeft); - return true; - } - - return false; -} - -void Fight::handleOpponentActionVesna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - break; - - case kFightAction3: - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - break; - - case kFightAction5: - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - if (fighter->countdown <= 1) - fighter->countdown = 1; - break; - - case kFightAction131: - break; - } -} - -void Fight::updateOpponentVesna(Fighter *fighter) { - // This is an opponent struct - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 == 1) { - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - } else { - switch (rnd(6)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 2: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 5: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = 4 * opponent->countdown; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 5) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - - switch (opponent->sequenceIndex) { - default: - break; - - case 1: - setSequenceAndDraw(opponent, 3, kFightSequenceType1); - break; - - case 2: - setSequenceAndDraw(opponent, 4, kFightSequenceType1); - break; - - case 5: - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - break; - } - - setSequenceAndDraw(opponent->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - CALL_FUNCTION0(opponent->opponent, update); - CALL_FUNCTION0(opponent, update); - - getSound()->removeFromQueue(kEntityTables0); - - // Stop processing - return; - } - } - - updateOpponent(opponent); -} - -} // End of namespace LastExpress diff --git a/engines/lastexpress/game/fight.h b/engines/lastexpress/game/fight.h deleted file mode 100644 index a33cc93a29..0000000000 --- a/engines/lastexpress/game/fight.h +++ /dev/null @@ -1,266 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef LASTEXPRESS_FIGHT_H -#define LASTEXPRESS_FIGHT_H - -/* - Fight structure - --------------- - uint32 {4} - player struct - uint32 {4} - opponent struct - uint32 {4} - hasLost flag - - byte {1} - isRunning - - Fight participant structure - --------------------------- - uint32 {4} - function pointer - uint32 {4} - pointer to fight structure - uint32 {4} - pointer to opponent (fight participant structure) - uint32 {4} - array of sequences - uint32 {4} - number of sequences - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint16 {2} - ?? - uint16 {2} - ?? - only for opponent structure - uint32 {4} - ?? - only for opponent structure - -*/ - -#include "lastexpress/shared.h" - -#include "lastexpress/eventhandler.h" - -#include "common/array.h" - -namespace LastExpress { - -class LastExpressEngine; -class Sequence; -class SequenceFrame; - -////////////////////////////////////////////////////////////////////////// -// TODO : objectify! -class Fight : public EventHandler { -public: - enum FightEndType { - kFightEndWin = 0, - kFightEndLost = 1, - kFightEndExit = 2 - }; - - Fight(LastExpressEngine *engine); - ~Fight(); - - FightEndType setup(FightType type); - - void eventMouse(const Common::Event &ev); - void eventTick(const Common::Event &ev); - - void setStopped(); - void resetState() { _state = 0; } - -private: - enum FightSequenceType { - kFightSequenceType0 = 0, - kFightSequenceType1 = 1, - kFightSequenceType2 = 2 - }; - - enum FightAction { - kFightAction1 = 1, - kFightAction2 = 2, - kFightAction3 = 3, - kFightAction4 = 4, - kFightAction5 = 5, - kFightAction101 = 101, - kFightActionResetFrame = 102, - kFightAction103 = 103, - kFightActionWin = 104, - kFightActionLost = 105, - kFightAction128 = 128, - kFightAction129 = 129, - kFightAction130 = 130, - kFightAction131 = 131, - kFightAction132 = 132 - }; - - struct Fighter { - Common::Functor2 *handleAction; - Common::Functor1 *update; - Common::Functor2 *canInteract; - Fighter *opponent; - Common::Array sequences; - uint32 sequenceIndex; - Sequence *sequence; - SequenceFrame *frame; - uint32 frameIndex; - uint32 field_24; - FightAction action; - uint32 sequenceIndex2; - int32 countdown; // countdown before loosing ? - uint32 field_34; - - Fighter() { - handleAction = NULL; - update = NULL; - canInteract = NULL; - - opponent = NULL; - - sequenceIndex = 0; - sequence = NULL; - frame = NULL; - frameIndex = 0; - - field_24 = 0; - - action = kFightAction101; - sequenceIndex2 = 0; - - countdown = 1; - - field_34 = 0; - } - }; - - // Opponent struct - struct Opponent : Fighter { - int32 field_38; - - Opponent() : Fighter() { - field_38 = 0; - } - }; - - struct FightData { - Fighter *player; - Opponent *opponent; - int32 index; - - Sequence *sequences[20]; - Common::String names[20]; - - bool isRunning; - - FightData() { - player = new Fighter(); - opponent = new Opponent(); - - // Set opponents - player->opponent = opponent; - opponent->opponent = player; - - index = 0; - - isRunning = false; - } - }; - - LastExpressEngine *_engine; - FightData *_data; - FightEndType _endType; - int _state; - - bool _handleTimer; - - // Events - void handleTick(const Common::Event &ev, bool unknown); - - // State - void bailout(FightEndType type); - - - // Drawing - void setSequenceAndDraw(Fighter *fighter, uint32 sequenceIndex, FightSequenceType type) const; - void draw(Fighter *fighter) const; - - // Cleanup - void clearData(); - void clearSequences(Fighter *fighter) const; - - ////////////////////////////////////////////////////////////////////////// - // Loading - void loadData(FightType type); - - // Shared - void processFighter(Fighter *fighter); - - // Default functions - void handleAction(Fighter *fighter, FightAction action); - void update(Fighter *fighter); - bool canInteract(Fighter const *fighter, FightAction = (FightAction)0); - void updateOpponent(Fighter *fighter); - - // Milos - void loadMilosPlayer(); - void loadMilosOpponent(); - void handleActionMilos(Fighter *fighter, FightAction action); - void updateMilos(Fighter *fighter); - bool canInteractMilos(Fighter const *fighter, FightAction action); - void handleOpponentActionMilos(Fighter *fighter, FightAction action); - void updateOpponentMilos(Fighter *fighter); - - // Anna - void loadAnnaPlayer(); - void loadAnnaOpponent(); - void handleActionAnna(Fighter *fighter, FightAction action); - void updateOpponentAnna(Fighter *fighter); - - // Ivo - void loadIvoPlayer(); - void loadIvoOpponent(); - void handleActionIvo(Fighter *fighter, FightAction action); - void updateIvo(Fighter *fighter); - bool canInteractIvo(Fighter const *fighter, FightAction action); - void handleOpponentActionIvo(Fighter *fighter, FightAction action); - void updateOpponentIvo(Fighter *fighter); - - // Salko - void loadSalkoPlayer(); - void loadSalkoOpponent(); - void handleActionSalko(Fighter *fighter, FightAction action); - void updateSalko(Fighter *fighter); - bool canInteractSalko(Fighter const *fighter, FightAction action); - void handleOpponentActionSalko(Fighter *fighter, FightAction action); - void updateOpponentSalko(Fighter *fighter); - - // Vesna - void loadVesnaPlayer(); - void loadVesnaOpponent(); - void handleActionVesna(Fighter *fighter, FightAction action); - void updateVesna(Fighter *fighter); - bool canInteractVesna(Fighter const *fighter, FightAction action); - void handleOpponentActionVesna(Fighter *fighter, FightAction action); - void updateOpponentVesna(Fighter *fighter); -}; - -} // End of namespace LastExpress - -#endif // LASTEXPRESS_FIGHT_H diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index 0911c60de0..a8a2ce87b1 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -30,11 +30,13 @@ // Entities #include "lastexpress/entities/chapters.h" +// Fight +#include "lastexpress/fight/fight.h" + // Game #include "lastexpress/game/action.h" #include "lastexpress/game/beetle.h" #include "lastexpress/game/entities.h" -#include "lastexpress/game/fight.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/menu.h" #include "lastexpress/game/object.h" diff --git a/engines/lastexpress/game/menu.cpp b/engines/lastexpress/game/menu.cpp index f9eef26326..27a43d8f61 100644 --- a/engines/lastexpress/game/menu.cpp +++ b/engines/lastexpress/game/menu.cpp @@ -28,7 +28,8 @@ #include "lastexpress/data/snd.h" #include "lastexpress/data/scene.h" -#include "lastexpress/game/fight.h" +#include "lastexpress/fight/fight.h" + #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/savegame.h" diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index 12fbb4f85b..3827c16681 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -45,10 +45,10 @@ MODULE_OBJS := \ entities/verges.o \ entities/vesna.o \ entities/yasmin.o \ + fight/fight.o \ game/action.o \ game/beetle.o \ game/entities.o \ - game/fight.o \ game/inventory.o \ game/logic.o \ game/menu.o \ -- cgit v1.2.3 From 434a2e66b1fc59e1b7732591cfefd7e389905817 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 22 Jun 2011 02:20:15 -0400 Subject: LASTEXPRESS: Refactor Fight class - Replace structs holding function pointers by proper classes - Move each fighter functions to separate files --- engines/lastexpress/fight/fight.cpp | 1290 ++------------------------- engines/lastexpress/fight/fight.h | 169 +--- engines/lastexpress/fight/fighter.cpp | 248 +++++ engines/lastexpress/fight/fighter.h | 123 +++ engines/lastexpress/fight/fighter_anna.cpp | 186 ++++ engines/lastexpress/fight/fighter_anna.h | 48 + engines/lastexpress/fight/fighter_ivo.cpp | 244 +++++ engines/lastexpress/fight/fighter_ivo.h | 51 ++ engines/lastexpress/fight/fighter_milos.cpp | 221 +++++ engines/lastexpress/fight/fighter_milos.h | 51 ++ engines/lastexpress/fight/fighter_salko.cpp | 201 +++++ engines/lastexpress/fight/fighter_salko.h | 51 ++ engines/lastexpress/fight/fighter_vesna.cpp | 264 ++++++ engines/lastexpress/fight/fighter_vesna.h | 51 ++ engines/lastexpress/module.mk | 6 + 15 files changed, 1816 insertions(+), 1388 deletions(-) create mode 100644 engines/lastexpress/fight/fighter.cpp create mode 100644 engines/lastexpress/fight/fighter.h create mode 100644 engines/lastexpress/fight/fighter_anna.cpp create mode 100644 engines/lastexpress/fight/fighter_anna.h create mode 100644 engines/lastexpress/fight/fighter_ivo.cpp create mode 100644 engines/lastexpress/fight/fighter_ivo.h create mode 100644 engines/lastexpress/fight/fighter_milos.cpp create mode 100644 engines/lastexpress/fight/fighter_milos.h create mode 100644 engines/lastexpress/fight/fighter_salko.cpp create mode 100644 engines/lastexpress/fight/fighter_salko.h create mode 100644 engines/lastexpress/fight/fighter_vesna.cpp create mode 100644 engines/lastexpress/fight/fighter_vesna.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp index 5b3530f488..685b3b09d1 100644 --- a/engines/lastexpress/fight/fight.cpp +++ b/engines/lastexpress/fight/fight.cpp @@ -22,16 +22,19 @@ #include "lastexpress/fight/fight.h" +#include "lastexpress/fight/fighter_anna.h" +#include "lastexpress/fight/fighter_ivo.h" +#include "lastexpress/fight/fighter_milos.h" +#include "lastexpress/fight/fighter_salko.h" +#include "lastexpress/fight/fighter_vesna.h" + #include "lastexpress/data/cursor.h" -#include "lastexpress/data/scene.h" #include "lastexpress/data/sequence.h" -#include "lastexpress/game/entities.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/graphics.h" @@ -39,34 +42,24 @@ #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" -#include "common/func.h" - namespace LastExpress { -#define CALL_FUNCTION0(fighter, name) \ - (*fighter->name)(fighter) +Fight::FightData::FightData() { + player = NULL; + opponent = NULL; -#define CALL_FUNCTION1(fighter, name, a) \ - (*fighter->name)(fighter, a) + index = 0; -#define REGISTER_PLAYER_FUNCTIONS(name) \ - if (!_data) \ - error("Fight::load##namePlayer - invalid data!"); \ - _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleAction##name); \ - _data->player->update = new Common::Functor1Mem(this, &Fight::update##name); \ - _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract##name); - -#define REGISTER_OPPONENT_FUNCTIONS(name) \ - if (!_data) \ - error("Fight::load##nameOpponent - invalid data!"); \ - _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleOpponentAction##name); \ - _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponent##name); \ - _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); + isFightRunning = false; +} -#define CHECK_SEQUENCE2(fighter, value) \ - (fighter->frame->getInfo()->field_33 & value) +Fight::FightData::~FightData() { + SAFE_DELETE(player); + SAFE_DELETE(opponent); +} -Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) {} +Fight::Fight(LastExpressEngine *engine) : _engine(engine), _data(NULL), _endType(kFightEndLost), _state(0), _handleTimer(false) { +} Fight::~Fight() { clearData(); @@ -79,7 +72,6 @@ Fight::~Fight() { ////////////////////////////////////////////////////////////////////////// // Events ////////////////////////////////////////////////////////////////////////// - void Fight::eventMouse(const Common::Event &ev) { if (!_data || _data->index) return; @@ -120,9 +112,9 @@ void Fight::eventMouse(const Common::Event &ev) { _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); // Call player function - if (CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { + if (_data->player->canInteract((Fighter::FightAction)hotspot->action)) { if (ev.type == Common::EVENT_LBUTTONUP) - CALL_FUNCTION1(_data->player, handleAction, (FightAction)hotspot->action); + _data->player->handleAction((Fighter::FightAction)hotspot->action); } else { _engine->getCursor()->setStyle(kCursorNormal); } @@ -175,17 +167,17 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) { return; SceneHotspot *hotspot = NULL; - if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !CALL_FUNCTION1(_data->player, canInteract, (FightAction)hotspot->action)) { + if (!getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot) || !_data->player->canInteract((Fighter::FightAction)hotspot->action)) { _engine->getCursor()->setStyle(kCursorNormal); } else { _engine->getCursor()->setStyle((CursorStyle)hotspot->cursor); } - CALL_FUNCTION0(_data->player, update); - CALL_FUNCTION0(_data->opponent, update); + _data->player->update(); + _data->opponent->update(); // Draw sequences - if (!_data->isRunning) + if (!_data->isFightRunning) return; if (isProcessing) @@ -201,7 +193,6 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) { ////////////////////////////////////////////////////////////////////////// // Setup ////////////////////////////////////////////////////////////////////////// - Fight::FightEndType Fight::setup(FightType type) { if (_data) error("Fight::setup - calling fight setup again while a fight is already in progress!"); @@ -282,7 +273,7 @@ Fight::FightEndType Fight::setup(FightType type) { // Start fight _endType = kFightEndLost; - while (_data->isRunning) { + while (_data->isFightRunning) { if (_engine->handleEvents()) continue; @@ -298,10 +289,9 @@ Fight::FightEndType Fight::setup(FightType type) { ////////////////////////////////////////////////////////////////////////// // Status ////////////////////////////////////////////////////////////////////////// - void Fight::setStopped() { if (_data) - _data->isRunning = false; + _data->isFightRunning = false; } void Fight::bailout(FightEndType type) { @@ -313,80 +303,19 @@ void Fight::bailout(FightEndType type) { ////////////////////////////////////////////////////////////////////////// // Cleanup ////////////////////////////////////////////////////////////////////////// - void Fight::clearData() { if (!_data) return; // Clear data - clearSequences(_data->player); - clearSequences(_data->opponent); - - SAFE_DELETE(_data->player); - SAFE_DELETE(_data->opponent); - SAFE_DELETE(_data); _engine->restoreEventHandlers(); } -void Fight::clearSequences(Fighter *combatant) const { - if (!combatant) - return; - - // The original game resets the function pointers to default values, just before deleting the struct - getScenes()->removeAndRedraw(&combatant->frame, false); - - // Free sequences - for (int i = 0; i < (int)combatant->sequences.size(); i++) - SAFE_DELETE(combatant->sequences[i]); -} - -////////////////////////////////////////////////////////////////////////// -// Drawing -////////////////////////////////////////////////////////////////////////// - -void Fight::setSequenceAndDraw(Fighter *combatant, uint32 sequenceIndex, FightSequenceType type) const { - if (combatant->sequences.size() < sequenceIndex) - return; - - switch (type) { - default: - break; - - case kFightSequenceType0: - if (combatant->sequenceIndex) - return; - - combatant->sequence = combatant->sequences[sequenceIndex]; - combatant->sequenceIndex = sequenceIndex; - draw(combatant); - break; - - case kFightSequenceType1: - combatant->sequence = combatant->sequences[sequenceIndex]; - combatant->sequenceIndex = sequenceIndex; - combatant->sequenceIndex2 = 0; - draw(combatant); - break; - - case kFightSequenceType2: - combatant->sequenceIndex2 = sequenceIndex; - break; - } -} - -void Fight::draw(Fighter *combatant) const { - getScenes()->removeAndRedraw(&combatant->frame, false); - - combatant->frameIndex = 0; - combatant->field_24 = 0; -} - ////////////////////////////////////////////////////////////////////////// // Loading ////////////////////////////////////////////////////////////////////////// - void Fight::loadData(FightType type) { if (!_data) error("Fight::loadData - invalid data!"); @@ -396,41 +325,44 @@ void Fight::loadData(FightType type) { break; case kFightMilos: - loadMilosPlayer(); - loadMilosOpponent(); + _data->player = new FighterPlayerMilos(_engine); + _data->opponent = new FighterOpponentMilos(_engine); break; case kFightAnna: - loadAnnaPlayer(); - loadAnnaOpponent(); + _data->player = new FighterPlayerAnna(_engine); + _data->opponent = new FighterOpponentAnna(_engine); break; case kFightIvo: - loadIvoPlayer(); - loadIvoOpponent(); + _data->player = new FighterPlayerIvo(_engine); + _data->opponent = new FighterOpponentIvo(_engine); break; case kFightSalko: - loadSalkoPlayer(); - loadSalkoOpponent(); + _data->player = new FighterPlayerSalko(_engine); + _data->opponent = new FighterOpponentSalko(_engine); break; case kFightVesna: - loadVesnaPlayer(); - loadVesnaOpponent(); + _data->player = new FighterPlayerVesna(_engine); + _data->opponent = new FighterOpponentVesna(_engine); break; } if (!_data->player || !_data->opponent) error("Fight::loadData - error loading fight data (type=%d)", type); + // Setup opponent pointers + setOpponents(); + ////////////////////////////////////////////////////////////////////////// // Start running the fight - _data->isRunning = true; + _data->isFightRunning = true; if (_state < 5) { - setSequenceAndDraw(_data->player, 0, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); + _data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0); + _data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0); goto end_load; } @@ -439,22 +371,22 @@ void Fight::loadData(FightType type) { break; case kFightMilos: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 4, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 0, kFightSequenceType0); + _data->opponent->setCountdown(1); + _data->player->setSequenceAndDraw(4, Fighter::kFightSequenceType0); + _data->opponent->setSequenceAndDraw(0, Fighter::kFightSequenceType0); break; case kFightIvo: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 3, kFightSequenceType0); - setSequenceAndDraw(_data->opponent, 6, kFightSequenceType0); + _data->opponent->setCountdown(1); + _data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType0); + _data->opponent->setSequenceAndDraw(6, Fighter::kFightSequenceType0); break; case kFightVesna: - _data->opponent->countdown = 1; - setSequenceAndDraw(_data->player, 0, kFightSequenceType0); - setSequenceAndDraw(_data->player, 3, kFightSequenceType2); - setSequenceAndDraw(_data->opponent, 5, kFightSequenceType0); + _data->opponent->setCountdown(1); + _data->player->setSequenceAndDraw(0, Fighter::kFightSequenceType0); + _data->player->setSequenceAndDraw(3, Fighter::kFightSequenceType2); + _data->opponent->setSequenceAndDraw(5, Fighter::kFightSequenceType0); break; } @@ -464,1120 +396,12 @@ end_load: SET_EVENT_HANDLERS(Fight, this); } -////////////////////////////////////////////////////////////////////////// -// Shared -////////////////////////////////////////////////////////////////////////// -void Fight::processFighter(Fighter *fighter) { - if (!_data) - error("Fight::processFighter - invalid data!"); - - if (!fighter->sequence) { - if (fighter->frame) { - getScenes()->removeFromQueue(fighter->frame); - getScenes()->setCoordinates(fighter->frame); - } - SAFE_DELETE(fighter->frame); - return; - } - - if (fighter->sequence->count() <= fighter->frameIndex) { - switch(fighter->action) { - default: - break; - - case kFightAction101: - setSequenceAndDraw(fighter, fighter->sequenceIndex2, kFightSequenceType1); - fighter->sequenceIndex2 = 0; - break; - - case kFightActionResetFrame: - fighter->frameIndex = 0; - break; - - case kFightAction103: - setSequenceAndDraw(fighter, 0, kFightSequenceType1); - CALL_FUNCTION1(fighter, handleAction, kFightAction101); - setSequenceAndDraw(fighter->opponent, 0, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction101); - CALL_FUNCTION0(fighter->opponent, update); - break; - - case kFightActionWin: - bailout(kFightEndWin); - break; - - case kFightActionLost: - bailout(kFightEndLost); - break; - } - } - - if (_data->isRunning) { - - // Get the current sequence frame - SequenceFrame *frame = new SequenceFrame(fighter->sequence, (uint16)fighter->frameIndex); - frame->getInfo()->location = 1; - - if (fighter->frame == frame) { - delete frame; - return; - } - - getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31); - - // Add current frame to queue and advance - getScenes()->addToQueue(frame); - fighter->frameIndex++; - - if (fighter->frame) { - getScenes()->removeFromQueue(fighter->frame); - - if (!frame->getInfo()->field_2E) - getScenes()->setCoordinates(fighter->frame); - } - - // Replace by new frame - delete fighter->frame; - fighter->frame = frame; - } -} - -void Fight::handleAction(Fighter *fighter, FightAction action) { - switch (action) { - default: - return; - - case kFightAction101: - break; - - case kFightActionResetFrame: - fighter->countdown--; - break; - - case kFightAction103: - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - - case kFightActionWin: - _endType = kFightEndWin; - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - - case kFightActionLost: - _endType = kFightEndLost; - CALL_FUNCTION1(fighter->opponent, handleAction, kFightActionResetFrame); - break; - } - - // Update action - fighter->action = action; -} - -bool Fight::canInteract(Fighter const *fighter, FightAction /*= (FightAction)0*/ ) { - return (fighter->action == kFightAction101 && !fighter->sequenceIndex); -} - -void Fight::update(Fighter *fighter) { - - processFighter(fighter); - - if (fighter->frame) - fighter->frame->getInfo()->location = (fighter->action == kFightActionResetFrame ? 2 : 0); -} - -void Fight::updateOpponent(Fighter *fighter) { - - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - processFighter(opponent); - - if (opponent->field_38 && !opponent->sequenceIndex) - opponent->field_38--; - - if (fighter->frame) - fighter->frame->getInfo()->location = 1; -} - -////////////////////////////////////////////////////////////////////////// -// Milos -////////////////////////////////////////////////////////////////////////// - -void Fight::loadMilosPlayer() { - REGISTER_PLAYER_FUNCTIONS(Milos) - - _data->player->sequences.push_back(loadSequence("2001cr.seq")); - _data->player->sequences.push_back(loadSequence("2001cdl.seq")); - _data->player->sequences.push_back(loadSequence("2001cdr.seq")); - _data->player->sequences.push_back(loadSequence("2001cdm.seq")); - _data->player->sequences.push_back(loadSequence("2001csgr.seq")); - _data->player->sequences.push_back(loadSequence("2001csgl.seq")); - _data->player->sequences.push_back(loadSequence("2001dbk.seq")); -} - -void Fight::loadMilosOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Milos) - - _data->opponent->sequences.push_back(loadSequence("2001or.seq")); - _data->opponent->sequences.push_back(loadSequence("2001oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2001oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2001okl.seq")); - _data->opponent->sequences.push_back(loadSequence("2001okm.seq")); - _data->opponent->sequences.push_back(loadSequence("2001dbk.seq")); - _data->opponent->sequences.push_back(loadSequence("2001wbk.seq")); - - getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault); - - _data->opponent->field_38 = 35; -} - -void Fight::handleActionMilos(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 6, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 3, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 6, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction128: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4) || fighter->opponent->sequenceIndex != 1) { - switch (fighter->opponent->sequenceIndex) { - default: - setSequenceAndDraw(fighter, rnd(3) + 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - } - } else { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - CALL_FUNCTION0(fighter, update); - } - break; - } -} - -void Fight::updateMilos(Fighter *fighter) { - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - // Draw sequences - if (fighter->opponent->countdown <= 0) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); - - getSound()->removeFromQueue(kEntityTables0); - getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault); - - CALL_FUNCTION1(fighter, handleAction, kFightActionWin); - } - - if (fighter->sequenceIndex == 4) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction4); - _endType = kFightEndLost; - } - } - - update(fighter); -} - -bool Fight::canInteractMilos(Fighter const *fighter, FightAction action) { - if (!_data) - error("Fight::canInteractMilos - invalid data!"); - - if (action != kFightAction128 - || _data->player->sequenceIndex != 1 - || !fighter->frame - || CHECK_SEQUENCE2(fighter, 4) - || fighter->opponent->sequenceIndex != 1) { - return canInteract(fighter); - } - - _engine->getCursor()->setStyle(kCursorHand); - - return true; -} - -void Fight::handleOpponentActionMilos(Fighter *fighter, FightAction action) { - if (action == kFightAction4) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - } else { - if (action != kFightAction131) - handleAction(fighter, action); - } -} - -void Fight::updateOpponentMilos(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType1); - break; - - case 3: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } else { - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - } - - // Update field_38 - if (opponent->opponent->field_34 < 5) - opponent->field_38 = 6 * (5 - opponent->opponent->field_34); - else - opponent->field_38 = 0; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - } - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Anna -////////////////////////////////////////////////////////////////////////// - -void Fight::loadAnnaPlayer() { - if (!_data) - error("Fight::loadAnnaPlayer - invalid data!"); - - // Special case: we are using some shared functions directly - _data->player->handleAction = new Common::Functor2Mem(this, &Fight::handleActionAnna); - _data->player->update = new Common::Functor1Mem(this, &Fight::update); - _data->player->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); - - _data->player->sequences.push_back(loadSequence("2002cr.seq")); - _data->player->sequences.push_back(loadSequence("2002cdl.seq")); - _data->player->sequences.push_back(loadSequence("2002cdr.seq")); - _data->player->sequences.push_back(loadSequence("2002cdm.seq")); - _data->player->sequences.push_back(loadSequence("2002lbk.seq")); -} - -void Fight::loadAnnaOpponent() { - if (!_data) - error("Fight::loadAnnaOpponent - invalid data!"); - - // Special case: we are using some shared functions directly - _data->opponent->handleAction = new Common::Functor2Mem(this, &Fight::handleAction); - _data->opponent->update = new Common::Functor1Mem(this, &Fight::updateOpponentAnna); - _data->opponent->canInteract = new Common::Functor2Mem(this, &Fight::canInteract); - - _data->opponent->sequences.push_back(loadSequence("2002or.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2002oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okml.seq")); - _data->opponent->sequences.push_back(loadSequence("2002okm.seq")); - - getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault); - - _data->opponent->field_38 = 30; -} - -void Fight::handleActionAnna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if ((fighter->sequenceIndex != 1 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction3: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 1) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 4, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 6, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction128: - switch (fighter->opponent->sequenceIndex) { - default: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 3, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - break; - } - - if (fighter->field_34 > 4) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - } -} - -void Fight::updateOpponentAnna(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(6)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 5: - setSequenceAndDraw(opponent, 3, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = (int32)rnd(15); - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 3) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - } - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Ivo -////////////////////////////////////////////////////////////////////////// - -void Fight::loadIvoPlayer() { - REGISTER_PLAYER_FUNCTIONS(Ivo) - - _data->player->sequences.push_back(loadSequence("2003cr.seq")); - _data->player->sequences.push_back(loadSequence("2003car.seq")); - _data->player->sequences.push_back(loadSequence("2003cal.seq")); - _data->player->sequences.push_back(loadSequence("2003cdr.seq")); - _data->player->sequences.push_back(loadSequence("2003cdm.seq")); - _data->player->sequences.push_back(loadSequence("2003chr.seq")); - _data->player->sequences.push_back(loadSequence("2003chl.seq")); - _data->player->sequences.push_back(loadSequence("2003ckr.seq")); - _data->player->sequences.push_back(loadSequence("2003lbk.seq")); - _data->player->sequences.push_back(loadSequence("2003fbk.seq")); - - _data->player->countdown = 5; -} - -void Fight::loadIvoOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Ivo) - - _data->opponent->sequences.push_back(loadSequence("2003or.seq")); - _data->opponent->sequences.push_back(loadSequence("2003oal.seq")); - _data->opponent->sequences.push_back(loadSequence("2003oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2003odm.seq")); - _data->opponent->sequences.push_back(loadSequence("2003okl.seq")); - _data->opponent->sequences.push_back(loadSequence("2003okj.seq")); - _data->opponent->sequences.push_back(loadSequence("blank.seq")); - _data->opponent->sequences.push_back(loadSequence("csdr.seq")); - _data->opponent->sequences.push_back(loadSequence("2003l.seq")); - - getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault); - - _data->opponent->countdown = 5; - _data->opponent->field_38 = 15; -} - -void Fight::handleActionIvo(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1 || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction2: - if ((fighter->sequenceIndex != 2 && fighter->sequenceIndex != 3) || CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - switch (fighter->opponent->sequenceIndex) { - default: - case 1: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - break; - - case kFightAction129: - setSequenceAndDraw(fighter, (fighter->opponent->countdown > 1) ? 4 : 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); - break; - - case kFightAction130: - setSequenceAndDraw(fighter, 3, fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); - break; - } -} - -void Fight::updateIvo(Fighter *fighter) { - - if ((fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) && !fighter->frameIndex) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction131); - - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - // Draw sequences - if (fighter->opponent->countdown <= 0) { - setSequenceAndDraw(fighter, 9, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, 8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); - - CALL_FUNCTION1(fighter, handleAction, kFightActionWin); - return; - } - - if (fighter->sequenceIndex == 3 || fighter->sequenceIndex == 4) - CALL_FUNCTION1(fighter->opponent, handleAction, (FightAction)fighter->sequenceIndex); - } - - update(fighter); -} - -bool Fight::canInteractIvo(Fighter const *fighter, FightAction action) { - if (action == kFightAction129 || action == kFightAction130) - return (fighter->sequenceIndex >= 8); - - return canInteract(fighter); -} - -void Fight::handleOpponentActionIvo(Fighter *fighter, FightAction action) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - switch (action) { - default: - handleAction(fighter, action); - break; - - case kFightAction3: - if ((opponent->sequenceIndex != 1 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 6, kFightSequenceType1); - CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); - } - break; - - case kFightAction4: - if ((opponent->sequenceIndex != 2 && opponent->sequenceIndex != 3) || CHECK_SEQUENCE2(opponent, 4)) { - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 5, kFightSequenceType1); - CALL_FUNCTION1(opponent->opponent, handleAction, kFightAction103); - } - break; - - case kFightAction131: - if (opponent->sequenceIndex) - break; - - if (rnd(100) <= (unsigned int)(opponent->countdown > 2 ? 60 : 75)) { - setSequenceAndDraw(opponent, 3 , kFightSequenceType1); - if (opponent->opponent->sequenceIndex == 4) - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - } - break; - } -} - -void Fight::updateOpponentIvo(Fighter *fighter) { - // This is an opponent struct! - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 >= 2) { - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 3: - setSequenceAndDraw(opponent, 0, kFightSequenceType2); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 0, kFightSequenceType1); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = 3 * opponent->countdown + (int32)rnd(10); - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - - if (opponent->opponent->countdown <= 0) { - setSequenceAndDraw(opponent, 7, kFightSequenceType1); - setSequenceAndDraw(opponent->opponent, 8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); - - CALL_FUNCTION1(opponent->opponent, handleAction, kFightActionWin); - - return; - } - - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Salko -////////////////////////////////////////////////////////////////////////// - -void Fight::loadSalkoPlayer() { - REGISTER_PLAYER_FUNCTIONS(Salko) - - _data->player->sequences.push_back(loadSequence("2004cr.seq")); - _data->player->sequences.push_back(loadSequence("2004cdr.seq")); - _data->player->sequences.push_back(loadSequence("2004chj.seq")); - _data->player->sequences.push_back(loadSequence("2004bk.seq")); - - _data->player->countdown = 2; -} - -void Fight::loadSalkoOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Salko) - - _data->opponent->sequences.push_back(loadSequence("2004or.seq")); - _data->opponent->sequences.push_back(loadSequence("2004oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2004oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2004okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2004ohm.seq")); - _data->opponent->sequences.push_back(loadSequence("blank.seq")); - - getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault); - - _data->opponent->countdown = 3; - _data->opponent->field_38 = 30; -} - -void Fight::handleActionSalko(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - case kFightAction2: - if (fighter->sequenceIndex != 1 && CHECK_SEQUENCE2(fighter, 4)) { - fighter->field_34 = 0; - - setSequenceAndDraw(fighter, 3, kFightSequenceType1); - setSequenceAndDraw(fighter->opponent, (action == kFightAction1 ? 3 : 4), kFightSequenceType1); - - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - - if (action == kFightAction2) - fighter->countdown= 0; - - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction5: - if (fighter->sequenceIndex != 3) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - setSequenceAndDraw(fighter, 1, kFightSequenceType0); - fighter->field_34 = 0; - break; - - case kFightAction131: - setSequenceAndDraw(fighter, 2, (fighter->sequenceIndex ? kFightSequenceType2 : kFightSequenceType0)); - break; - } -} - -void Fight::updateSalko(Fighter *fighter) { - update(fighter); - - // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation) - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - if (fighter->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - - return; - } - - if (fighter->sequenceIndex == 2) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction2); - } -} - -bool Fight::canInteractSalko(Fighter const *fighter, FightAction action) { - if (action == kFightAction131) { - if (fighter->sequenceIndex == 1) { - if (fighter->opponent->countdown <= 0) - _engine->getCursor()->setStyle(kCursorHand); - - return true; - } - - return false; - } - - return canInteract(fighter); -} - -void Fight::handleOpponentActionSalko(Fighter *fighter, FightAction action) { - if (action == kFightAction2) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - } else { - handleAction(fighter, action); - } -} - -void Fight::updateOpponentSalko(Fighter *fighter) { - // This is an opponent struct - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - switch (rnd(5)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 2: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 3: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - - // Update field_38 - opponent->field_38 = 4 * opponent->countdown; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndLost); - - // Stop processing - return; - } - - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - } - - updateOpponent(opponent); -} - -////////////////////////////////////////////////////////////////////////// -// Vesna -////////////////////////////////////////////////////////////////////////// - -void Fight::loadVesnaPlayer() { - REGISTER_PLAYER_FUNCTIONS(Vesna) - - _data->player->sequences.push_back(loadSequence("2005cr.seq")); - _data->player->sequences.push_back(loadSequence("2005cdr.seq")); - _data->player->sequences.push_back(loadSequence("2005cbr.seq")); - _data->player->sequences.push_back(loadSequence("2005bk.seq")); - _data->player->sequences.push_back(loadSequence("2005cdm1.seq")); - _data->player->sequences.push_back(loadSequence("2005chl.seq")); -} - -void Fight::loadVesnaOpponent() { - REGISTER_OPPONENT_FUNCTIONS(Vesna) - - _data->opponent->sequences.push_back(loadSequence("2005or.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oam.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oar.seq")); - _data->opponent->sequences.push_back(loadSequence("2005okml.seq")); - _data->opponent->sequences.push_back(loadSequence("2005okr.seq")); - _data->opponent->sequences.push_back(loadSequence("2005odm1.seq")); - _data->opponent->sequences.push_back(loadSequence("2005csbm.seq")); - _data->opponent->sequences.push_back(loadSequence("2005oam4.seq")); - - getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault); - - _data->opponent->countdown = 4; - _data->opponent->field_38 = 30; -} - -void Fight::handleActionVesna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - return; - - case kFightAction1: - if (fighter->sequenceIndex != 1) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction2: - if (fighter->sequenceIndex != 2) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } else { - fighter->field_34++; - } - break; - - case kFightAction5: - if (fighter->sequenceIndex != 3) { - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - CALL_FUNCTION0(fighter, update); - } - break; - - case kFightAction128: - if (fighter->sequenceIndex == 1 && fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { - setSequenceAndDraw(fighter, 5, kFightSequenceType1); - } else { - setSequenceAndDraw(fighter, (fighter->opponent->sequenceIndex == 5) ? 3 : 1, kFightSequenceType0); - } - break; - - case kFightAction132: - setSequenceAndDraw(fighter, 2, kFightSequenceType0); - break; - } - - if (fighter->field_34 > 10) { - setSequenceAndDraw(fighter->opponent, 5, kFightSequenceType2); - fighter->opponent->countdown = 1; - fighter->field_34 = 0; - } -} - -void Fight::updateVesna(Fighter *fighter) { - if (fighter->frame && CHECK_SEQUENCE2(fighter, 2)) { - - if (fighter->sequenceIndex == 3) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction3); - - if (fighter->opponent->countdown <= 0) { - getSound()->removeFromQueue(kEntityTables0); - bailout(kFightEndWin); - return; - } - - if (fighter->sequenceIndex == 5) - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction5); - } - - update(fighter); -} - -bool Fight::canInteractVesna(Fighter const *fighter, FightAction action) { - if (action != kFightAction128) - return canInteract(fighter); - - if (fighter->sequenceIndex != 1) { - - if (fighter->opponent->sequenceIndex == 5) { - _engine->getCursor()->setStyle(kCursorDown); - return true; - } - - return canInteract(fighter); - } - - if (fighter->opponent->sequenceIndex == 1 && CHECK_SEQUENCE2(fighter, 4)) { - _engine->getCursor()->setStyle(kCursorPunchLeft); - return true; - } - - return false; -} - -void Fight::handleOpponentActionVesna(Fighter *fighter, FightAction action) { - switch (action) { - default: - handleAction(fighter, action); - break; - - case kFightAction3: - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - break; - - case kFightAction5: - setSequenceAndDraw(fighter, 7, kFightSequenceType1); - CALL_FUNCTION1(fighter->opponent, handleAction, kFightAction103); - if (fighter->countdown <= 1) - fighter->countdown = 1; - break; - - case kFightAction131: - break; - } -} - -void Fight::updateOpponentVesna(Fighter *fighter) { - // This is an opponent struct - Opponent *opponent = (Opponent *)fighter; - - if (!opponent->field_38 && CALL_FUNCTION1(opponent, canInteract, kFightAction1) && !opponent->sequenceIndex2) { - - if (opponent->opponent->field_34 == 1) { - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - } else { - switch (rnd(6)) { - default: - break; - - case 0: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - break; - - case 1: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - - case 2: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - break; - - case 3: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 4: - setSequenceAndDraw(opponent, 1, kFightSequenceType0); - setSequenceAndDraw(opponent, 2, kFightSequenceType2); - break; - - case 5: - setSequenceAndDraw(opponent, 2, kFightSequenceType0); - setSequenceAndDraw(opponent, 1, kFightSequenceType2); - break; - } - } - - // Update field_38 - opponent->field_38 = 4 * opponent->countdown; - } - - if (opponent->frame && CHECK_SEQUENCE2(opponent, 2)) { - if (opponent->sequenceIndex == 1 || opponent->sequenceIndex == 2 || opponent->sequenceIndex == 5) - CALL_FUNCTION1(opponent->opponent, handleAction, (FightAction)opponent->sequenceIndex); - - if (opponent->opponent->countdown <= 0) { - - switch (opponent->sequenceIndex) { - default: - break; - - case 1: - setSequenceAndDraw(opponent, 3, kFightSequenceType1); - break; - - case 2: - setSequenceAndDraw(opponent, 4, kFightSequenceType1); - break; - - case 5: - setSequenceAndDraw(opponent, 6, kFightSequenceType1); - break; - } - - setSequenceAndDraw(opponent->opponent, 4, kFightSequenceType1); - - CALL_FUNCTION1(opponent, handleAction, kFightActionLost); - CALL_FUNCTION0(opponent->opponent, update); - CALL_FUNCTION0(opponent, update); - - getSound()->removeFromQueue(kEntityTables0); - - // Stop processing - return; - } - } +void Fight::setOpponents() { + _data->player->setOpponent(_data->opponent); + _data->opponent->setOpponent(_data->player); - updateOpponent(opponent); + _data->player->setFight(this); + _data->opponent->setFight(this); } } // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fight.h b/engines/lastexpress/fight/fight.h index a33cc93a29..fffb520789 100644 --- a/engines/lastexpress/fight/fight.h +++ b/engines/lastexpress/fight/fight.h @@ -57,16 +57,14 @@ #include "lastexpress/eventhandler.h" -#include "common/array.h" - namespace LastExpress { class LastExpressEngine; class Sequence; -class SequenceFrame; -////////////////////////////////////////////////////////////////////////// -// TODO : objectify! +class Fighter; +class Opponent; + class Fight : public EventHandler { public: enum FightEndType { @@ -83,82 +81,15 @@ public: void eventMouse(const Common::Event &ev); void eventTick(const Common::Event &ev); + // State + bool isRunning() { return _data->isFightRunning; } + void setRunningState(bool state) { _data->isFightRunning = state; } + void bailout(FightEndType type); void setStopped(); void resetState() { _state = 0; } + void setEndType(FightEndType endType) { _endType = endType; } private: - enum FightSequenceType { - kFightSequenceType0 = 0, - kFightSequenceType1 = 1, - kFightSequenceType2 = 2 - }; - - enum FightAction { - kFightAction1 = 1, - kFightAction2 = 2, - kFightAction3 = 3, - kFightAction4 = 4, - kFightAction5 = 5, - kFightAction101 = 101, - kFightActionResetFrame = 102, - kFightAction103 = 103, - kFightActionWin = 104, - kFightActionLost = 105, - kFightAction128 = 128, - kFightAction129 = 129, - kFightAction130 = 130, - kFightAction131 = 131, - kFightAction132 = 132 - }; - - struct Fighter { - Common::Functor2 *handleAction; - Common::Functor1 *update; - Common::Functor2 *canInteract; - Fighter *opponent; - Common::Array sequences; - uint32 sequenceIndex; - Sequence *sequence; - SequenceFrame *frame; - uint32 frameIndex; - uint32 field_24; - FightAction action; - uint32 sequenceIndex2; - int32 countdown; // countdown before loosing ? - uint32 field_34; - - Fighter() { - handleAction = NULL; - update = NULL; - canInteract = NULL; - - opponent = NULL; - - sequenceIndex = 0; - sequence = NULL; - frame = NULL; - frameIndex = 0; - - field_24 = 0; - - action = kFightAction101; - sequenceIndex2 = 0; - - countdown = 1; - - field_34 = 0; - } - }; - - // Opponent struct - struct Opponent : Fighter { - int32 field_38; - - Opponent() : Fighter() { - field_38 = 0; - } - }; - struct FightData { Fighter *player; Opponent *opponent; @@ -167,20 +98,10 @@ private: Sequence *sequences[20]; Common::String names[20]; - bool isRunning; - - FightData() { - player = new Fighter(); - opponent = new Opponent(); - - // Set opponents - player->opponent = opponent; - opponent->opponent = player; + bool isFightRunning; - index = 0; - - isRunning = false; - } + FightData(); + ~FightData(); }; LastExpressEngine *_engine; @@ -193,72 +114,10 @@ private: // Events void handleTick(const Common::Event &ev, bool unknown); - // State - void bailout(FightEndType type); - - - // Drawing - void setSequenceAndDraw(Fighter *fighter, uint32 sequenceIndex, FightSequenceType type) const; - void draw(Fighter *fighter) const; - - // Cleanup - void clearData(); - void clearSequences(Fighter *fighter) const; - - ////////////////////////////////////////////////////////////////////////// - // Loading + // Data void loadData(FightType type); - - // Shared - void processFighter(Fighter *fighter); - - // Default functions - void handleAction(Fighter *fighter, FightAction action); - void update(Fighter *fighter); - bool canInteract(Fighter const *fighter, FightAction = (FightAction)0); - void updateOpponent(Fighter *fighter); - - // Milos - void loadMilosPlayer(); - void loadMilosOpponent(); - void handleActionMilos(Fighter *fighter, FightAction action); - void updateMilos(Fighter *fighter); - bool canInteractMilos(Fighter const *fighter, FightAction action); - void handleOpponentActionMilos(Fighter *fighter, FightAction action); - void updateOpponentMilos(Fighter *fighter); - - // Anna - void loadAnnaPlayer(); - void loadAnnaOpponent(); - void handleActionAnna(Fighter *fighter, FightAction action); - void updateOpponentAnna(Fighter *fighter); - - // Ivo - void loadIvoPlayer(); - void loadIvoOpponent(); - void handleActionIvo(Fighter *fighter, FightAction action); - void updateIvo(Fighter *fighter); - bool canInteractIvo(Fighter const *fighter, FightAction action); - void handleOpponentActionIvo(Fighter *fighter, FightAction action); - void updateOpponentIvo(Fighter *fighter); - - // Salko - void loadSalkoPlayer(); - void loadSalkoOpponent(); - void handleActionSalko(Fighter *fighter, FightAction action); - void updateSalko(Fighter *fighter); - bool canInteractSalko(Fighter const *fighter, FightAction action); - void handleOpponentActionSalko(Fighter *fighter, FightAction action); - void updateOpponentSalko(Fighter *fighter); - - // Vesna - void loadVesnaPlayer(); - void loadVesnaOpponent(); - void handleActionVesna(Fighter *fighter, FightAction action); - void updateVesna(Fighter *fighter); - bool canInteractVesna(Fighter const *fighter, FightAction action); - void handleOpponentActionVesna(Fighter *fighter, FightAction action); - void updateOpponentVesna(Fighter *fighter); + void clearData(); + void setOpponents(); }; } // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter.cpp b/engines/lastexpress/fight/fighter.cpp new file mode 100644 index 0000000000..fcd69183fb --- /dev/null +++ b/engines/lastexpress/fight/fighter.cpp @@ -0,0 +1,248 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter.h" + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +Fighter::Fighter(LastExpressEngine *engine) : _engine(engine) { + _opponent = NULL; + _fight = NULL; + + _sequenceIndex = 0; + _sequence = NULL; + _frame = NULL; + _frameIndex = 0; + + _field_24 = 0; + + _action = kFightAction101; + _sequenceIndex2 = 0; + + _countdown = 1; + + _field_34 = 0; +} + +Fighter::~Fighter() { + clearSequences(); +} + +////////////////////////////////////////////////////////////////////////// +// Cleanup +////////////////////////////////////////////////////////////////////////// +void Fighter::clearSequences() { + // The original game resets the function pointers to default values, just before deleting the struct + + getScenes()->removeAndRedraw(&_frame, false); + + // Free sequences + for (int i = 0; i < (int)_sequences.size(); i++) + SAFE_DELETE(_sequences[i]); +} + +////////////////////////////////////////////////////////////////////////// +// Drawing +////////////////////////////////////////////////////////////////////////// +void Fighter::setSequenceAndDraw(uint32 sequenceIndex, FightSequenceType type) { + if (_sequences.size() < sequenceIndex) + return; + + switch (type) { + default: + break; + + case kFightSequenceType0: + if (_sequenceIndex) + return; + + _sequence = _sequences[sequenceIndex]; + _sequenceIndex = sequenceIndex; + draw(); + break; + + case kFightSequenceType1: + _sequence = _sequences[sequenceIndex]; + _sequenceIndex = sequenceIndex; + _sequenceIndex2 = 0; + draw(); + break; + + case kFightSequenceType2: + _sequenceIndex2 = sequenceIndex; + break; + } +} + +void Fighter::draw() { + getScenes()->removeAndRedraw(&_frame, false); + + _frameIndex = 0; + _field_24 = 0; +} + +////////////////////////////////////////////////////////////////////////// +// Processing +////////////////////////////////////////////////////////////////////////// +void Fighter::process() { + if (!_sequence) { + if (_frame) { + getScenes()->removeFromQueue(_frame); + getScenes()->setCoordinates(_frame); + } + SAFE_DELETE(_frame); + return; + } + + if (_sequence->count() <= _frameIndex) { + switch(_action) { + default: + break; + + case kFightAction101: + setSequenceAndDraw(_sequenceIndex2, kFightSequenceType1); + _sequenceIndex2 = 0; + break; + + case kFightActionResetFrame: + _frameIndex = 0; + break; + + case kFightAction103: + setSequenceAndDraw(0, kFightSequenceType1); + handleAction(kFightAction101); + _opponent->setSequenceAndDraw(0, kFightSequenceType1); + _opponent->handleAction(kFightAction101); + _opponent->update(); + break; + + case kFightActionWin: + _fight->bailout(Fight::kFightEndWin); + break; + + case kFightActionLost: + _fight->bailout(Fight::kFightEndLost); + break; + } + } + + if (_fight->isRunning()) { + + // Get the current sequence frame + SequenceFrame *frame = new SequenceFrame(_sequence, (uint16)_frameIndex); + frame->getInfo()->location = 1; + + if (_frame == frame) { + delete frame; + return; + } + + getSound()->playFightSound(frame->getInfo()->soundAction, frame->getInfo()->field_31); + + // Add current frame to queue and advance + getScenes()->addToQueue(frame); + _frameIndex++; + + if (_frame) { + getScenes()->removeFromQueue(_frame); + + if (!frame->getInfo()->field_2E) + getScenes()->setCoordinates(_frame); + } + + // Replace by new frame + delete _frame; + _frame = frame; + } +} + +////////////////////////////////////////////////////////////////////////// +// Default actions +////////////////////////////////////////////////////////////////////////// +void Fighter::handleAction(FightAction action) { + switch (action) { + default: + return; + + case kFightAction101: + break; + + case kFightActionResetFrame: + _countdown--; + break; + + case kFightAction103: + _opponent->handleAction(kFightActionResetFrame); + break; + + case kFightActionWin: + _fight->setEndType(Fight::kFightEndWin); + _opponent->handleAction(kFightActionResetFrame); + break; + + case kFightActionLost: + _fight->setEndType(Fight::kFightEndLost); + _opponent->handleAction(kFightActionResetFrame); + break; + } + + // Update action + _action = action; +} + +bool Fighter::canInteract(FightAction /*action = kFightActionNone*/ ) { + return (_action == kFightAction101 && !_sequenceIndex); +} + +void Fighter::update() { + process(); + + if (_frame) + _frame->getInfo()->location = (_action == kFightActionResetFrame ? 2 : 0); +} + +void Opponent::update() { + process(); + + if (_field_38 && !_sequenceIndex) + _field_38--; + + if (_frame) + _frame->getInfo()->location = 1; +} + +////////////////////////////////////////////////////////////////////////// +// Helpers +////////////////////////////////////////////////////////////////////////// +bool Fighter::checkFrame(uint32 val) { + return (_frame->getInfo()->field_33 & val); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter.h b/engines/lastexpress/fight/fighter.h new file mode 100644 index 0000000000..e37fe49d86 --- /dev/null +++ b/engines/lastexpress/fight/fighter.h @@ -0,0 +1,123 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_H +#define LASTEXPRESS_FIGHTER_H + +#include "lastexpress/fight/fight.h" + +#include "common/array.h" + +namespace LastExpress { + +class Fight; +class Sequence; +class SequenceFrame; + +class Fighter { +public: + enum FightAction { + kFightActionNone = 0, + kFightAction1 = 1, + kFightAction2 = 2, + kFightAction3 = 3, + kFightAction4 = 4, + kFightAction5 = 5, + kFightAction101 = 101, + kFightActionResetFrame = 102, + kFightAction103 = 103, + kFightActionWin = 104, + kFightActionLost = 105, + kFightAction128 = 128, + kFightAction129 = 129, + kFightAction130 = 130, + kFightAction131 = 131, + kFightAction132 = 132 + }; + + enum FightSequenceType { + kFightSequenceType0 = 0, + kFightSequenceType1 = 1, + kFightSequenceType2 = 2 + }; + + Fighter(LastExpressEngine *engine); + virtual ~Fighter(); + + // Default functions + virtual void handleAction(FightAction action); + virtual void update(); + virtual bool canInteract(FightAction action = kFightActionNone); + + // Drawing + void setSequenceAndDraw(uint32 sequenceIndex, FightSequenceType type); + + // Accessors + void setOpponent(Fighter *opponent) { _opponent = opponent; } + void setCountdown(int32 countdown) { _countdown = countdown; } + void setFight(Fight *fight) { _fight = fight; } + + int getCountdown() { return _countdown; } + uint32 getSequenceIndex() { return _sequenceIndex; } + uint32 getField34() { return _field_34; } + +protected: + LastExpressEngine *_engine; + Fight *_fight; + Fighter *_opponent; + Sequence *_sequence; + SequenceFrame *_frame; + uint32 _sequenceIndex; + Common::Array _sequences; + uint32 _frameIndex; + uint32 _field_24; + FightAction _action; + uint32 _sequenceIndex2; + int32 _countdown; // countdown before loosing ? + uint32 _field_34; + + // Drawing and processing + void draw(); + void process(); + + // Cleanup + void clearSequences(); + + // Helpers + bool checkFrame(uint32 val); +}; + +class Opponent : public Fighter { +public: + Opponent(LastExpressEngine *engine) : Fighter(engine) { + _field_38 = 0; + } + + virtual void update(); + +protected: + int32 _field_38; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_H diff --git a/engines/lastexpress/fight/fighter_anna.cpp b/engines/lastexpress/fight/fighter_anna.cpp new file mode 100644 index 0000000000..db2ab54c4b --- /dev/null +++ b/engines/lastexpress/fight/fighter_anna.cpp @@ -0,0 +1,186 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter_anna.h" + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Player +////////////////////////////////////////////////////////////////////////// +FighterPlayerAnna::FighterPlayerAnna(LastExpressEngine *engine) : Fighter(engine) { + _sequences.push_back(loadSequence("2002cr.seq")); + _sequences.push_back(loadSequence("2002cdl.seq")); + _sequences.push_back(loadSequence("2002cdr.seq")); + _sequences.push_back(loadSequence("2002cdm.seq")); + _sequences.push_back(loadSequence("2002lbk.seq")); +} + +void FighterPlayerAnna::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + return; + + case kFightAction1: + if ((_sequenceIndex != 1 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(4, kFightSequenceType1); + _opponent->setSequenceAndDraw(4, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction2: + if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(4, kFightSequenceType1); + _opponent->setSequenceAndDraw(5, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction3: + if ((_sequenceIndex != 2 && _sequenceIndex != 1) || checkFrame(4)) { + setSequenceAndDraw(4, kFightSequenceType1); + _opponent->setSequenceAndDraw(6, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction128: + switch (_opponent->getSequenceIndex()) { + default: + setSequenceAndDraw(3, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(3, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(2, kFightSequenceType0); + break; + } + break; + } + + if (_field_34 > 4) { + getSound()->removeFromQueue(kEntityTables0); + _fight->bailout(Fight::kFightEndWin); + } +} + +////////////////////////////////////////////////////////////////////////// +// Opponent +////////////////////////////////////////////////////////////////////////// +FighterOpponentAnna::FighterOpponentAnna(LastExpressEngine *engine) : Opponent(engine) { + _sequences.push_back(loadSequence("2002or.seq")); + _sequences.push_back(loadSequence("2002oal.seq")); + _sequences.push_back(loadSequence("2002oam.seq")); + _sequences.push_back(loadSequence("2002oar.seq")); + _sequences.push_back(loadSequence("2002okr.seq")); + _sequences.push_back(loadSequence("2002okml.seq")); + _sequences.push_back(loadSequence("2002okm.seq")); + + getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault); + + _field_38 = 30; +} + +void FighterOpponentAnna::update() { + if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) { + + if (_opponent->getField34() >= 2) { + switch (rnd(6)) { + default: + break; + + case 0: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(3, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(3, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 5: + setSequenceAndDraw(3, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + } + } + + // Update field_38 + _field_38 = (int32)rnd(15); + } + + if (_frame && checkFrame(2)) { + if (_sequenceIndex == 1 || _sequenceIndex == 2 || _sequenceIndex == 3) + _opponent->handleAction((FightAction)_sequenceIndex); + + if (_opponent->getCountdown() <= 0) { + getSound()->removeFromQueue(kEntityTables0); + handleAction(kFightActionLost); + } + } + + Fighter::update(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter_anna.h b/engines/lastexpress/fight/fighter_anna.h new file mode 100644 index 0000000000..abb6f9dc64 --- /dev/null +++ b/engines/lastexpress/fight/fighter_anna.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_ANNA_H +#define LASTEXPRESS_FIGHTER_ANNA_H + +#include "lastexpress/fight/fighter.h" + +namespace LastExpress { + +class LastExpressEngine; + +class FighterPlayerAnna : public Fighter { +public: + FighterPlayerAnna(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); +}; + +class FighterOpponentAnna : public Opponent { +public: + FighterOpponentAnna(LastExpressEngine *engine); + + virtual void update(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_ANNA_H diff --git a/engines/lastexpress/fight/fighter_ivo.cpp b/engines/lastexpress/fight/fighter_ivo.cpp new file mode 100644 index 0000000000..423b6b4ce5 --- /dev/null +++ b/engines/lastexpress/fight/fighter_ivo.cpp @@ -0,0 +1,244 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter_ivo.h" + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Player +////////////////////////////////////////////////////////////////////////// +FighterPlayerIvo::FighterPlayerIvo(LastExpressEngine *engine) : Fighter(engine) { + _sequences.push_back(loadSequence("2003cr.seq")); + _sequences.push_back(loadSequence("2003car.seq")); + _sequences.push_back(loadSequence("2003cal.seq")); + _sequences.push_back(loadSequence("2003cdr.seq")); + _sequences.push_back(loadSequence("2003cdm.seq")); + _sequences.push_back(loadSequence("2003chr.seq")); + _sequences.push_back(loadSequence("2003chl.seq")); + _sequences.push_back(loadSequence("2003ckr.seq")); + _sequences.push_back(loadSequence("2003lbk.seq")); + _sequences.push_back(loadSequence("2003fbk.seq")); + + _countdown = 5; +} + +void FighterPlayerIvo::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + return; + + case kFightAction1: + if (_sequenceIndex != 1 || checkFrame(4)) { + setSequenceAndDraw(7, kFightSequenceType1); + _opponent->setSequenceAndDraw(4, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } + break; + + case kFightAction2: + if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(7, kFightSequenceType1); + _opponent->setSequenceAndDraw(5, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } + break; + + case kFightAction128: + switch (_opponent->getSequenceIndex()) { + default: + case 1: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(2, kFightSequenceType0); + break; + } + break; + + case kFightAction129: + setSequenceAndDraw((_opponent->getCountdown() > 1) ? 4 : 3, _sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); + break; + + case kFightAction130: + setSequenceAndDraw(3, _sequenceIndex ? kFightSequenceType2 : kFightSequenceType0); + break; + } +} + +void FighterPlayerIvo::update() { + + if ((_sequenceIndex == 3 || _sequenceIndex == 4) && !_frameIndex) + _opponent->handleAction(kFightAction131); + + if (_frame && checkFrame(2)) { + + // Draw sequences + if (_opponent->getCountdown() <= 0) { + setSequenceAndDraw(9, kFightSequenceType1); + _opponent->setSequenceAndDraw(8, kFightSequenceType1); + getSound()->removeFromQueue(kEntityTables0); + + handleAction(kFightActionWin); + return; + } + + if (_sequenceIndex == 3 || _sequenceIndex == 4) + _opponent->handleAction((FightAction)_sequenceIndex); + } + + Fighter::update(); +} + +bool FighterPlayerIvo::canInteract(FightAction action) { + if (action == kFightAction129 || action == kFightAction130) + return (_sequenceIndex >= 8); + + return Fighter::canInteract(); +} + +////////////////////////////////////////////////////////////////////////// +// Opponent +////////////////////////////////////////////////////////////////////////// +FighterOpponentIvo::FighterOpponentIvo(LastExpressEngine *engine) : Opponent(engine) { + _sequences.push_back(loadSequence("2003or.seq")); + _sequences.push_back(loadSequence("2003oal.seq")); + _sequences.push_back(loadSequence("2003oar.seq")); + _sequences.push_back(loadSequence("2003odm.seq")); + _sequences.push_back(loadSequence("2003okl.seq")); + _sequences.push_back(loadSequence("2003okj.seq")); + _sequences.push_back(loadSequence("blank.seq")); + _sequences.push_back(loadSequence("csdr.seq")); + _sequences.push_back(loadSequence("2003l.seq")); + + getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault); + + _countdown = 5; + _field_38 = 15; +} + +void FighterOpponentIvo::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + break; + + case kFightAction3: + if ((_sequenceIndex != 1 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(6, kFightSequenceType1); + _opponent->setSequenceAndDraw(6, kFightSequenceType1); + _opponent->handleAction(kFightAction103); + } + break; + + case kFightAction4: + if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(6, kFightSequenceType1); + _opponent->setSequenceAndDraw(5, kFightSequenceType1); + _opponent->handleAction(kFightAction103); + } + break; + + case kFightAction131: + if (_sequenceIndex) + break; + + if (rnd(100) <= (unsigned int)(_countdown > 2 ? 60 : 75)) { + setSequenceAndDraw(3 , kFightSequenceType1); + if (_opponent->getSequenceIndex() == 4) + setSequenceAndDraw(2, kFightSequenceType2); + } + break; + } +} + +void FighterOpponentIvo::update() { + if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) { + + if (_opponent->getField34() >= 2) { + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 3: + setSequenceAndDraw(0, kFightSequenceType2); + setSequenceAndDraw(1, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(0, kFightSequenceType1); + setSequenceAndDraw(1, kFightSequenceType2); + break; + } + } + + // Update field_38 + _field_38 = 3 * _countdown + (int32)rnd(10); + } + + if (_frame && checkFrame(2)) { + + if (_opponent->getCountdown() <= 0) { + setSequenceAndDraw(7, kFightSequenceType1); + _opponent->setSequenceAndDraw(8, kFightSequenceType1); + getSound()->removeFromQueue(kEntityTables0); + + _opponent->handleAction(kFightActionWin); + + return; + } + + if (_sequenceIndex == 1 || _sequenceIndex == 2) + _opponent->handleAction((FightAction)_sequenceIndex); + } + + Fighter::update(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter_ivo.h b/engines/lastexpress/fight/fighter_ivo.h new file mode 100644 index 0000000000..ca54fea904 --- /dev/null +++ b/engines/lastexpress/fight/fighter_ivo.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_IVO_H +#define LASTEXPRESS_FIGHTER_IVO_H + +#include "lastexpress/fight/fighter.h" + +namespace LastExpress { + +class LastExpressEngine; + +class FighterPlayerIvo : public Fighter { +public: + FighterPlayerIvo(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); + virtual bool canInteract(FightAction action = kFightActionNone); +}; + +class FighterOpponentIvo : public Opponent { +public: + FighterOpponentIvo(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_IVO_H diff --git a/engines/lastexpress/fight/fighter_milos.cpp b/engines/lastexpress/fight/fighter_milos.cpp new file mode 100644 index 0000000000..46e4bde7a6 --- /dev/null +++ b/engines/lastexpress/fight/fighter_milos.cpp @@ -0,0 +1,221 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter_milos.h" + +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Player +////////////////////////////////////////////////////////////////////////// +FighterPlayerMilos::FighterPlayerMilos(LastExpressEngine *engine) : Fighter(engine) { + _sequences.push_back(loadSequence("2001cr.seq")); + _sequences.push_back(loadSequence("2001cdl.seq")); + _sequences.push_back(loadSequence("2001cdr.seq")); + _sequences.push_back(loadSequence("2001cdm.seq")); + _sequences.push_back(loadSequence("2001csgr.seq")); + _sequences.push_back(loadSequence("2001csgl.seq")); + _sequences.push_back(loadSequence("2001dbk.seq")); +} + +void FighterPlayerMilos::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + return; + + case kFightAction1: + if (_sequenceIndex != 1 || checkFrame(4)) { + setSequenceAndDraw(6, kFightSequenceType1); + _opponent->setSequenceAndDraw(3, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction2: + if ((_sequenceIndex != 2 && _sequenceIndex != 3) || checkFrame(4)) { + setSequenceAndDraw(6, kFightSequenceType1); + _opponent->setSequenceAndDraw(4, kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction128: + if (_sequenceIndex != 1 || checkFrame(4) || _opponent->getSequenceIndex() != 1) { + switch (_opponent->getSequenceIndex()) { + default: + setSequenceAndDraw(rnd(3) + 1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(3, kFightSequenceType0); + break; + } + } else { + setSequenceAndDraw(4, kFightSequenceType1); + update(); + } + break; + } +} + +void FighterPlayerMilos::update() { + if (_frame && checkFrame(2)) { + + // Draw sequences + if (_opponent->getCountdown() <= 0) { + setSequenceAndDraw(5, kFightSequenceType1); + _opponent->setSequenceAndDraw(6, kFightSequenceType1); + + getSound()->removeFromQueue(kEntityTables0); + getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault); + + handleAction(kFightActionWin); + } + + if (_sequenceIndex == 4) { + _opponent->handleAction(kFightAction4); + _fight->setEndType(Fight::kFightEndLost); + } + } + + Fighter::update(); +} + +bool FighterPlayerMilos::canInteract(FightAction action) { + if (action != kFightAction128 + || _sequenceIndex != 1 + || !_frame + || checkFrame(4) + || _opponent->getSequenceIndex() != 1) { + return Fighter::canInteract(); + } + + _engine->getCursor()->setStyle(kCursorHand); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +// Opponent +////////////////////////////////////////////////////////////////////////// +FighterOpponentMilos::FighterOpponentMilos(LastExpressEngine *engine) : Opponent(engine) { + _sequences.push_back(loadSequence("2001or.seq")); + _sequences.push_back(loadSequence("2001oal.seq")); + _sequences.push_back(loadSequence("2001oam.seq")); + _sequences.push_back(loadSequence("2001okl.seq")); + _sequences.push_back(loadSequence("2001okm.seq")); + _sequences.push_back(loadSequence("2001dbk.seq")); + _sequences.push_back(loadSequence("2001wbk.seq")); + + getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault); + + _field_38 = 35; +} + +void FighterOpponentMilos::handleAction(FightAction action) { + if (action == kFightAction4) { + setSequenceAndDraw(5, kFightSequenceType1); + _opponent->handleAction(kFightAction103); + } else { + if (action != kFightAction131) + Fighter::handleAction(action); + } +} + +void FighterOpponentMilos::update() { + if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) { + + if (_opponent->getField34() >= 2) { + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(2, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType1); + break; + + case 3: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(1, kFightSequenceType2); + break; + } + } else { + setSequenceAndDraw(2, kFightSequenceType0); + } + + // Update field_38 + if (_opponent->getField34() < 5) + _field_38 = 6 * (5 - _opponent->getField34()); + else + _field_38 = 0; + } + + if (_frame && checkFrame(2)) { + if (_sequenceIndex == 1 || _sequenceIndex == 2) + _opponent->handleAction((FightAction)_sequenceIndex); + + if (_opponent->getCountdown() <= 0) { + getSound()->removeFromQueue(kEntityTables0); + handleAction(kFightActionLost); + } + } + + Fighter::update(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter_milos.h b/engines/lastexpress/fight/fighter_milos.h new file mode 100644 index 0000000000..2126dd1838 --- /dev/null +++ b/engines/lastexpress/fight/fighter_milos.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_MILOS_H +#define LASTEXPRESS_FIGHTER_MILOS_H + +#include "lastexpress/fight/fighter.h" + +namespace LastExpress { + +class LastExpressEngine; + +class FighterPlayerMilos : public Fighter { +public: + FighterPlayerMilos(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); + virtual bool canInteract(FightAction action = kFightActionNone); +}; + +class FighterOpponentMilos : public Opponent { +public: + FighterOpponentMilos(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_MILOS_H diff --git a/engines/lastexpress/fight/fighter_salko.cpp b/engines/lastexpress/fight/fighter_salko.cpp new file mode 100644 index 0000000000..795dd41b93 --- /dev/null +++ b/engines/lastexpress/fight/fighter_salko.cpp @@ -0,0 +1,201 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter_salko.h" + +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Player +////////////////////////////////////////////////////////////////////////// +FighterPlayerSalko::FighterPlayerSalko(LastExpressEngine *engine) : Fighter(engine) { + _sequences.push_back(loadSequence("2004cr.seq")); + _sequences.push_back(loadSequence("2004cdr.seq")); + _sequences.push_back(loadSequence("2004chj.seq")); + _sequences.push_back(loadSequence("2004bk.seq")); + + _countdown = 2; +} + +void FighterPlayerSalko::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + return; + + case kFightAction1: + case kFightAction2: + if (_sequenceIndex != 1 && checkFrame(4)) { + _field_34 = 0; + + setSequenceAndDraw(3, kFightSequenceType1); + _opponent->setSequenceAndDraw((action == kFightAction1 ? 3 : 4), kFightSequenceType1); + + _opponent->handleAction(kFightAction103); + + if (action == kFightAction2) + _countdown= 0; + + update(); + } else { + _field_34++; + } + break; + + case kFightAction5: + if (_sequenceIndex != 3) { + _opponent->handleAction(kFightAction103); + update(); + } + break; + + case kFightAction128: + setSequenceAndDraw(1, kFightSequenceType0); + _field_34 = 0; + break; + + case kFightAction131: + setSequenceAndDraw(2, (_sequenceIndex ? kFightSequenceType2 : kFightSequenceType0)); + break; + } +} + +void FighterPlayerSalko::update() { + Fighter::update(); + + // The original doesn't check for currentSequence2 != NULL (might not happen when everything is working properly, but crashes with our current implementation) + if (_frame && checkFrame(2)) { + + if (_opponent->getCountdown() <= 0) { + getSound()->removeFromQueue(kEntityTables0); + _fight->bailout(Fight::kFightEndWin); + + return; + } + + if (_sequenceIndex == 2) + _opponent->handleAction(kFightAction2); + } +} + +bool FighterPlayerSalko::canInteract(FightAction action) { + if (action == kFightAction131) { + if (_sequenceIndex == 1) { + if (_opponent->getCountdown() <= 0) + _engine->getCursor()->setStyle(kCursorHand); + + return true; + } + + return false; + } + + return Fighter::canInteract(); +} + +////////////////////////////////////////////////////////////////////////// +// Opponent +////////////////////////////////////////////////////////////////////////// +FighterOpponentSalko::FighterOpponentSalko(LastExpressEngine *engine) : Opponent(engine) { + _sequences.push_back(loadSequence("2004or.seq")); + _sequences.push_back(loadSequence("2004oam.seq")); + _sequences.push_back(loadSequence("2004oar.seq")); + _sequences.push_back(loadSequence("2004okr.seq")); + _sequences.push_back(loadSequence("2004ohm.seq")); + _sequences.push_back(loadSequence("blank.seq")); + + getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault); + + _countdown = 3; + _field_38 = 30; +} + +void FighterOpponentSalko::handleAction(FightAction action) { + if (action == kFightAction2) { + setSequenceAndDraw(5, kFightSequenceType1); + _opponent->handleAction(kFightAction103); + } else { + Fighter::handleAction(action); + } +} + +void FighterOpponentSalko::update() { + if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) { + + switch (rnd(5)) { + default: + break; + + case 0: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(2, kFightSequenceType0); + break; + + case 2: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 3: + setSequenceAndDraw(2, kFightSequenceType0); + setSequenceAndDraw(1, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(1, kFightSequenceType2); + break; + } + + // Update field_38 + _field_38 = 4 * _countdown; + } + + if (_frame && checkFrame(2)) { + if (_opponent->getCountdown() <= 0) { + getSound()->removeFromQueue(kEntityTables0); + _fight->bailout(Fight::kFightEndLost); + + // Stop processing + return; + } + + if (_sequenceIndex == 1 || _sequenceIndex == 2) + _opponent->handleAction((FightAction)_sequenceIndex); + } + + Fighter::update(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter_salko.h b/engines/lastexpress/fight/fighter_salko.h new file mode 100644 index 0000000000..0a2a615867 --- /dev/null +++ b/engines/lastexpress/fight/fighter_salko.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_SALKO_H +#define LASTEXPRESS_FIGHTER_SALKO_H + +#include "lastexpress/fight/fighter.h" + +namespace LastExpress { + +class LastExpressEngine; + +class FighterPlayerSalko : public Fighter { +public: + FighterPlayerSalko(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); + virtual bool canInteract(FightAction action = kFightActionNone); +}; + +class FighterOpponentSalko : public Opponent { +public: + FighterOpponentSalko(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_SALKO_H diff --git a/engines/lastexpress/fight/fighter_vesna.cpp b/engines/lastexpress/fight/fighter_vesna.cpp new file mode 100644 index 0000000000..a2460106b0 --- /dev/null +++ b/engines/lastexpress/fight/fighter_vesna.cpp @@ -0,0 +1,264 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/fight/fighter_vesna.h" + +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// Player +////////////////////////////////////////////////////////////////////////// +FighterPlayerVesna::FighterPlayerVesna(LastExpressEngine *engine) : Fighter(engine) { + _sequences.push_back(loadSequence("2005cr.seq")); + _sequences.push_back(loadSequence("2005cdr.seq")); + _sequences.push_back(loadSequence("2005cbr.seq")); + _sequences.push_back(loadSequence("2005bk.seq")); + _sequences.push_back(loadSequence("2005cdm1.seq")); + _sequences.push_back(loadSequence("2005chl.seq")); +} + +void FighterPlayerVesna::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + return; + + case kFightAction1: + if (_sequenceIndex != 1) { + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction2: + if (_sequenceIndex != 2) { + _opponent->handleAction(kFightAction103); + update(); + } else { + _field_34++; + } + break; + + case kFightAction5: + if (_sequenceIndex != 3) { + _opponent->handleAction(kFightAction103); + update(); + } + break; + + case kFightAction128: + if (_sequenceIndex == 1 && _opponent->getSequenceIndex() == 1 && checkFrame(4)) { + setSequenceAndDraw(5, kFightSequenceType1); + } else { + setSequenceAndDraw((_opponent->getSequenceIndex() == 5) ? 3 : 1, kFightSequenceType0); + } + break; + + case kFightAction132: + setSequenceAndDraw(2, kFightSequenceType0); + break; + } + + if (_field_34 > 10) { + _opponent->setSequenceAndDraw(5, kFightSequenceType2); + _opponent->setCountdown(1); + _field_34 = 0; + } +} + +void FighterPlayerVesna::update() { + if (_frame && checkFrame(2)) { + + if (_sequenceIndex == 3) + _opponent->handleAction(kFightAction3); + + if (_opponent->getCountdown() <= 0) { + getSound()->removeFromQueue(kEntityTables0); + _fight->bailout(Fight::kFightEndWin); + return; + } + + if (_sequenceIndex == 5) + _opponent->handleAction(kFightAction5); + } + + Fighter::update(); +} + +bool FighterPlayerVesna::canInteract(FightAction action) { + if (action != kFightAction128) + return Fighter::canInteract(); + + if (_sequenceIndex != 1) { + + if (_opponent->getSequenceIndex() == 5) { + _engine->getCursor()->setStyle(kCursorDown); + return true; + } + + return Fighter::canInteract(); + } + + if (_opponent->getSequenceIndex() == 1 && checkFrame(4)) { + _engine->getCursor()->setStyle(kCursorPunchLeft); + return true; + } + + return false; +} + +////////////////////////////////////////////////////////////////////////// +// Opponent +////////////////////////////////////////////////////////////////////////// +FighterOpponentVesna::FighterOpponentVesna(LastExpressEngine *engine) : Opponent(engine) { + _sequences.push_back(loadSequence("2005or.seq")); + _sequences.push_back(loadSequence("2005oam.seq")); + _sequences.push_back(loadSequence("2005oar.seq")); + _sequences.push_back(loadSequence("2005okml.seq")); + _sequences.push_back(loadSequence("2005okr.seq")); + _sequences.push_back(loadSequence("2005odm1.seq")); + _sequences.push_back(loadSequence("2005csbm.seq")); + _sequences.push_back(loadSequence("2005oam4.seq")); + + getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault); + + _countdown = 4; + _field_38 = 30; +} + +void FighterOpponentVesna::handleAction(FightAction action) { + switch (action) { + default: + Fighter::handleAction(action); + break; + + case kFightAction3: + _opponent->handleAction(kFightAction103); + break; + + case kFightAction5: + setSequenceAndDraw(7, kFightSequenceType1); + _opponent->handleAction(kFightAction103); + if (_countdown <= 1) + _countdown = 1; + break; + + case kFightAction131: + break; + } +} + +void FighterOpponentVesna::update() { + if (!_field_38 && canInteract(kFightAction1) && !_sequenceIndex2) { + + if (_opponent->getField34() == 1) { + setSequenceAndDraw(2, kFightSequenceType0); + } else { + switch (rnd(6)) { + default: + break; + + case 0: + setSequenceAndDraw(1, kFightSequenceType0); + break; + + case 1: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(1, kFightSequenceType2); + break; + + case 2: + setSequenceAndDraw(2, kFightSequenceType0); + break; + + case 3: + setSequenceAndDraw(2, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 4: + setSequenceAndDraw(1, kFightSequenceType0); + setSequenceAndDraw(2, kFightSequenceType2); + break; + + case 5: + setSequenceAndDraw(2, kFightSequenceType0); + setSequenceAndDraw(1, kFightSequenceType2); + break; + } + } + + // Update field_38 + _field_38 = 4 * _countdown; + } + + if (_frame && checkFrame(2)) { + if (_sequenceIndex == 1 || _sequenceIndex == 2 || _sequenceIndex == 5) + _opponent->handleAction((FightAction)_sequenceIndex); + + if (_opponent->getCountdown() <= 0) { + + switch (_sequenceIndex) { + default: + break; + + case 1: + setSequenceAndDraw(3, kFightSequenceType1); + break; + + case 2: + setSequenceAndDraw(4, kFightSequenceType1); + break; + + case 5: + setSequenceAndDraw(6, kFightSequenceType1); + break; + } + + _opponent->setSequenceAndDraw(4, kFightSequenceType1); + + handleAction(kFightActionLost); + _opponent->update(); + Fighter::update(); + + getSound()->removeFromQueue(kEntityTables0); + + // Stop processing + return; + } + } + + Fighter::update(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/fight/fighter_vesna.h b/engines/lastexpress/fight/fighter_vesna.h new file mode 100644 index 0000000000..5c8ec855ae --- /dev/null +++ b/engines/lastexpress/fight/fighter_vesna.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_FIGHTER_VESNA_H +#define LASTEXPRESS_FIGHTER_VESNA_H + +#include "lastexpress/fight/fighter.h" + +namespace LastExpress { + +class LastExpressEngine; + +class FighterPlayerVesna : public Fighter { +public: + FighterPlayerVesna(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); + virtual bool canInteract(FightAction action = kFightActionNone); +}; + +class FighterOpponentVesna : public Opponent { +public: + FighterOpponentVesna(LastExpressEngine *engine); + + virtual void handleAction(FightAction action); + virtual void update(); +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_FIGHTER_VESNA_H diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index 3827c16681..e81151910b 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -46,6 +46,12 @@ MODULE_OBJS := \ entities/vesna.o \ entities/yasmin.o \ fight/fight.o \ + fight/fighter.o \ + fight/fighter_anna.o \ + fight/fighter_ivo.o \ + fight/fighter_milos.o \ + fight/fighter_salko.o \ + fight/fighter_vesna.o \ game/action.o \ game/beetle.o \ game/entities.o \ -- cgit v1.2.3 From 85bb5ef45e6b62b52317df2d83a7ad8663dbdfc0 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 22 Jun 2011 02:47:51 -0400 Subject: LASTEXPRESS: Fix leak and corruption of event handlers function pointers - Add better error handling - Properly delete previous event handlers when setting new ones or restoring from backup --- engines/lastexpress/lastexpress.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index e162998719..120e6eb28b 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -288,22 +288,34 @@ void LastExpressEngine::handleSoundTimer() { /// Event Handling /////////////////////////////////////////////////////////////////////////////////// void LastExpressEngine::backupEventHandlers() { + if (_eventMouseBackup != NULL || _eventTickBackup != NULL) + error("[LastExpressEngine::backupEventHandlers] backup event handlers are already set"); + _eventMouseBackup = _eventMouse; _eventTickBackup = _eventTick; } void LastExpressEngine::restoreEventHandlers() { if (_eventMouseBackup == NULL || _eventTickBackup == NULL) - error("LastExpressEngine::restoreEventHandlers: restore called before backing up the event handlers!"); + error("[LastExpressEngine::restoreEventHandlers] restore called before backing up the event handlers"); + + // Cleanup previous event handlers + SAFE_DELETE(_eventMouse); + SAFE_DELETE(_eventTick); _eventMouse = _eventMouseBackup; _eventTick = _eventTickBackup; + + _eventMouseBackup = NULL; + _eventTickBackup = NULL; } void LastExpressEngine::setEventHandlers(EventHandler::EventFunction *mouse, EventHandler::EventFunction *tick) { - // Cleanup previous event handlers - delete _eventMouse; - delete _eventTick; + if (_eventMouse != _eventMouseBackup) + SAFE_DELETE(_eventMouse); + + if (_eventTick != _eventTickBackup) + SAFE_DELETE(_eventTick); _eventMouse = mouse; _eventTick = tick; -- cgit v1.2.3 From f0cf72f4313c146dcec25fa004312a4319b89b91 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 22 Jun 2011 23:32:14 -0400 Subject: LASTEXPRESS: Move Menu class to a separate folder --- engines/lastexpress/entities/chapters.cpp | 3 +- engines/lastexpress/game/inventory.cpp | 3 +- engines/lastexpress/game/logic.cpp | 3 +- engines/lastexpress/game/menu.cpp | 1542 ----------------------------- engines/lastexpress/game/menu.h | 207 ---- engines/lastexpress/game/savegame.cpp | 3 +- engines/lastexpress/lastexpress.cpp | 3 +- engines/lastexpress/menu/menu.cpp | 1542 +++++++++++++++++++++++++++++ engines/lastexpress/menu/menu.h | 207 ++++ engines/lastexpress/module.mk | 2 +- 10 files changed, 1760 insertions(+), 1755 deletions(-) delete mode 100644 engines/lastexpress/game/menu.cpp delete mode 100644 engines/lastexpress/game/menu.h create mode 100644 engines/lastexpress/menu/menu.cpp create mode 100644 engines/lastexpress/menu/menu.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp index 1252a62d8d..6a41590f64 100644 --- a/engines/lastexpress/entities/chapters.cpp +++ b/engines/lastexpress/entities/chapters.cpp @@ -57,13 +57,14 @@ #include "lastexpress/game/entities.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" -#include "lastexpress/game/menu.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/menu/menu.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp index adf6ff772e..07ad8d936b 100644 --- a/engines/lastexpress/game/inventory.cpp +++ b/engines/lastexpress/game/inventory.cpp @@ -27,11 +27,12 @@ #include "lastexpress/data/snd.h" #include "lastexpress/game/logic.h" -#include "lastexpress/game/menu.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/menu/menu.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index a8a2ce87b1..3bd7d6da68 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -38,7 +38,6 @@ #include "lastexpress/game/beetle.h" #include "lastexpress/game/entities.h" #include "lastexpress/game/inventory.h" -#include "lastexpress/game/menu.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" @@ -46,6 +45,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/menu/menu.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/game/menu.cpp b/engines/lastexpress/game/menu.cpp deleted file mode 100644 index 27a43d8f61..0000000000 --- a/engines/lastexpress/game/menu.cpp +++ /dev/null @@ -1,1542 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "lastexpress/game/menu.h" - -// Data -#include "lastexpress/data/animation.h" -#include "lastexpress/data/cursor.h" -#include "lastexpress/data/snd.h" -#include "lastexpress/data/scene.h" - -#include "lastexpress/fight/fight.h" - -#include "lastexpress/game/inventory.h" -#include "lastexpress/game/logic.h" -#include "lastexpress/game/savegame.h" -#include "lastexpress/game/savepoint.h" -#include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" -#include "lastexpress/game/state.h" - -#include "lastexpress/graphics.h" -#include "lastexpress/helpers.h" -#include "lastexpress/lastexpress.h" -#include "lastexpress/resource.h" - -#include "common/rational.h" - -#define getNextGameId() (GameId)((_gameId + 1) % 6) - -namespace LastExpress { - -// Bottom-left buttons (quit.seq) -enum StartMenuButtons { - kButtonVolumeDownPushed, - kButtonVolumeDown, - kButtonVolume, - kButtonVolumeUp, - kButtonVolumeUpPushed, - kButtonBrightnessDownPushed, // 5 - kButtonBrightnessDown, - kButtonBrightness, - kButtonBrightnessUp, - kButtonBrightnessUpPushed, - kButtonQuit, // 10 - kButtonQuitPushed -}; - -// Egg buttons (buttns.seq) -enum StartMenuEggButtons { - kButtonShield, - kButtonRewind, - kButtonRewindPushed, - kButtonForward, - kButtonForwardPushed, - kButtonCredits, // 5 - kButtonCreditsPushed, - kButtonContinue -}; - -// Tooltips sequence (helpnewr.seq) -enum StartMenuTooltips { - kTooltipInsertCd1, - kTooltipInsertCd2, - kTooltipInsertCd3, - kTooltipContinueGame, - kTooltipReplayGame, - kTooltipContinueRewoundGame, // 5 - kTooltipViewGameEnding, - kTooltipStartAnotherGame, - kTooltipVolumeUp, - kTooltipVolumeDown, - kTooltipBrightnessUp, // 10 - kTooltipBrightnessDown, - kTooltipQuit, - kTooltipRewindParis, - kTooltipForwardStrasbourg, - kTooltipRewindStrasbourg, // 15 - kTooltipRewindMunich, - kTooltipForwardMunich, - kTooltipForwardVienna, - kTooltipRewindVienna, - kTooltipRewindBudapest, // 20 - kTooltipForwardBudapest, - kTooltipForwardBelgrade, - kTooltipRewindBelgrade, - kTooltipForwardConstantinople, - kTooltipSwitchBlueGame, // 25 - kTooltipSwitchRedGame, - kTooltipSwitchGoldGame, - kTooltipSwitchGreenGame, - kTooltipSwitchTealGame, - kTooltipSwitchPurpleGame, // 30 - kTooltipPlayNewGame, - kTooltipCredits, - kTooltipFastForward, - kTooltipRewind -}; - -////////////////////////////////////////////////////////////////////////// -// DATA -////////////////////////////////////////////////////////////////////////// - -// Information about the cities on the train line -static const struct { - uint8 frame; - TimeValue time; -} _trainCities[31] = { - {0, kTimeCityParis}, - {9, kTimeCityEpernay}, - {11, kTimeCityChalons}, - {16, kTimeCityBarLeDuc}, - {21, kTimeCityNancy}, - {25, kTimeCityLuneville}, - {35, kTimeCityAvricourt}, - {37, kTimeCityDeutschAvricourt}, - {40, kTimeCityStrasbourg}, - {53, kTimeCityBadenOos}, - {56, kTimeCityKarlsruhe}, - {60, kTimeCityStuttgart}, - {63, kTimeCityGeislingen}, - {66, kTimeCityUlm}, - {68, kTimeCityAugsburg}, - {73, kTimeCityMunich}, - {84, kTimeCitySalzbourg}, - {89, kTimeCityAttnangPuchheim}, - {97, kTimeCityWels}, - {100, kTimeCityLinz}, - {104, kTimeCityAmstetten}, - {111, kTimeCityVienna}, - {120, kTimeCityPoszony}, - {124, kTimeCityGalanta}, - {132, kTimeCityBudapest}, - {148, kTimeCityBelgrade}, - /* Line 1 ends at 150 - line 2 begins at 0 */ - {157, kTimeCityNish}, - {165, kTimeCityTzaribrod}, - {174, kTimeCitySofia}, - {198, kTimeCityAdrianople}, - {210, kTimeCityConstantinople}}; - -static const struct { - TimeValue time; - uint index; - StartMenuTooltips rewind; - StartMenuTooltips forward; -} _cityButtonsInfo[7] = { - {kTimeCityParis, 64, kTooltipRewindParis, kTooltipRewindParis}, - {kTimeCityStrasbourg, 128, kTooltipRewindStrasbourg, kTooltipForwardStrasbourg}, - {kTimeCityMunich, 129, kTooltipRewindMunich, kTooltipForwardMunich}, - {kTimeCityVienna, 130, kTooltipRewindVienna, kTooltipForwardVienna}, - {kTimeCityBudapest, 131, kTooltipRewindBudapest, kTooltipForwardBudapest}, - {kTimeCityBelgrade, 132, kTooltipRewindBelgrade, kTooltipForwardBelgrade}, - {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople} -}; - -////////////////////////////////////////////////////////////////////////// -// Clock -////////////////////////////////////////////////////////////////////////// -class Clock { -public: - explicit Clock(LastExpressEngine *engine); - ~Clock(); - - void draw(uint32 time); - void clear(); - -private: - LastExpressEngine *_engine; - - // Frames - SequenceFrame *_frameMinutes; - SequenceFrame *_frameHour; - SequenceFrame *_frameSun; - SequenceFrame *_frameDate; -}; - -Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) { - _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true); - _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true); - _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true); - _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true); -} - -Clock::~Clock() { - SAFE_DELETE(_frameMinutes); - SAFE_DELETE(_frameHour); - SAFE_DELETE(_frameSun); - SAFE_DELETE(_frameDate); - - // Zero passed pointers - _engine = NULL; -} - -void Clock::clear() { - getScenes()->removeFromQueue(_frameMinutes); - getScenes()->removeFromQueue(_frameHour); - getScenes()->removeFromQueue(_frameSun); - getScenes()->removeFromQueue(_frameDate); -} - -void Clock::draw(uint32 time) { - assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); - - // Check that sequences have been loaded - if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate) - error("Clock::process: clock sequences have not been loaded correctly!"); - - // Clear existing frames - clear(); - - // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914 - // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914 - // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins - - // 15 = 1 second - // 15 * 60 = 900 = 1 minute - // 900 * 60 = 54000 = 1 hour - // 54000 * 24 = 1296000 = 1 day - - // Calculate each sequence index from the current time - - uint8 hour = 0; - uint8 minute = 0; - State::getHourMinutes(time, &hour, &minute); - uint32 index_date = 18 * time / 1296000; - if (hour == 23) - index_date += 18 * minute / 60; - - // Set sequences frames - _frameMinutes->setFrame(minute); - _frameHour->setFrame((5 * hour + minute / 12) % 60); - _frameSun->setFrame((5 * hour + minute / 12) % 120); - _frameDate->setFrame((uint16)index_date); - - // Adjust z-order and queue - _frameMinutes->getInfo()->location = 1; - _frameHour->getInfo()->location = 1; - _frameSun->getInfo()->location = 1; - _frameDate->getInfo()->location = 1; - - getScenes()->addToQueue(_frameMinutes); - getScenes()->addToQueue(_frameHour); - getScenes()->addToQueue(_frameSun); - getScenes()->addToQueue(_frameDate); -} - -////////////////////////////////////////////////////////////////////////// -// TrainLine -////////////////////////////////////////////////////////////////////////// -class TrainLine { -public: - explicit TrainLine(LastExpressEngine *engine); - ~TrainLine(); - - void draw(uint32 time); - void clear(); - -private: - LastExpressEngine *_engine; - - // Frames - SequenceFrame *_frameLine1; - SequenceFrame *_frameLine2; -}; - -TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) { - _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true); - _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true); -} - -TrainLine::~TrainLine() { - SAFE_DELETE(_frameLine1); - SAFE_DELETE(_frameLine2); - - // Zero passed pointers - _engine = NULL; -} - -void TrainLine::clear() { - getScenes()->removeFromQueue(_frameLine1); - getScenes()->removeFromQueue(_frameLine2); -} - -// Draw the train line at the time -// line1: 150 frames (=> Belgrade) -// line2: 61 frames (=> Constantinople) -void TrainLine::draw(uint32 time) { - assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); - - // Check that sequences have been loaded - if (!_frameLine1 || !_frameLine2) - error("TrainLine::process: Line sequences have not been loaded correctly!"); - - // Clear existing frames - clear(); - - // Get the index of the last city the train has visited - uint index = 0; - for (uint i = 0; i < ARRAYSIZE(_trainCities); i++) - if ((uint32)_trainCities[i].time <= time) - index = i; - - uint16 frame; - if (time > (uint32)_trainCities[index].time) { - // Interpolate linearly to use a frame between the cities - uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame; - uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time); - uint traveledTime = (time - (uint)_trainCities[index].time); - frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities); - } else { - // Exactly on the city - frame = _trainCities[index].frame; - } - - // Set frame, z-order and queue - if (frame < 150) { - _frameLine1->setFrame(frame); - - _frameLine1->getInfo()->location = 1; - getScenes()->addToQueue(_frameLine1); - } else { - // We passed Belgrade - _frameLine1->setFrame(149); - _frameLine2->setFrame(frame - 150); - - _frameLine1->getInfo()->location = 1; - _frameLine2->getInfo()->location = 1; - - getScenes()->addToQueue(_frameLine1); - getScenes()->addToQueue(_frameLine2); - } -} - - -////////////////////////////////////////////////////////////////////////// -// Menu -////////////////////////////////////////////////////////////////////////// -Menu::Menu(LastExpressEngine *engine) : _engine(engine), - _seqTooltips(NULL), _seqEggButtons(NULL), _seqButtons(NULL), _seqAcorn(NULL), _seqCity1(NULL), _seqCity2(NULL), _seqCity3(NULL), _seqCredits(NULL), - _gameId(kGameBlue), _hasShownStartScreen(false), _hasShownIntro(false), - _isShowingCredits(false), _isGameStarted(false), _isShowingMenu(false), - _creditsSequenceIndex(0), _checkHotspotsTicks(15), _mouseFlags(Common::EVENT_INVALID), _lastHotspot(NULL), - _currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) { - - _clock = new Clock(_engine); - _trainLine = new TrainLine(_engine); -} - -Menu::~Menu() { - SAFE_DELETE(_clock); - SAFE_DELETE(_trainLine); - - SAFE_DELETE(_seqTooltips); - SAFE_DELETE(_seqEggButtons); - SAFE_DELETE(_seqButtons); - SAFE_DELETE(_seqAcorn); - SAFE_DELETE(_seqCity1); - SAFE_DELETE(_seqCity2); - SAFE_DELETE(_seqCity3); - SAFE_DELETE(_seqCredits); - - _lastHotspot = NULL; - - // Cleanup frames - for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) - SAFE_DELETE(it->_value); - - _frames.clear(); - - // Zero passed pointers - _engine = NULL; -} - -////////////////////////////////////////////////////////////////////////// -// Setup -void Menu::setup() { - - // Clear drawing queue - getScenes()->removeAndRedraw(&_frames[kOverlayAcorn], false); - SAFE_DELETE(_seqAcorn); - - // Load Menu scene - // + 1 = normal menu with open egg / clock - // + 2 = shield menu, when no savegame exists (no game has been started) - _isGameStarted = _lowerTime >= kTimeStartGame; - getScenes()->loadScene((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)); - getFlags()->shouldRedraw = true; - getLogic()->updateCursor(); - - ////////////////////////////////////////////////////////////////////////// - // Load Acorn sequence - _seqAcorn = loadSequence(getAcornSequenceName(_isGameStarted ? getNextGameId() : kGameBlue)); - - ////////////////////////////////////////////////////////////////////////// - // Check if we loaded sequences before - if (_seqTooltips && _seqTooltips->count() > 0) - return; - - // Load all static data - _seqTooltips = loadSequence("helpnewr.seq"); - _seqEggButtons = loadSequence("buttns.seq"); - _seqButtons = loadSequence("quit.seq"); - _seqCity1 = loadSequence("jlinetl.seq"); - _seqCity2 = loadSequence("jlinecen.seq"); - _seqCity3 = loadSequence("jlinebr.seq"); - _seqCredits = loadSequence("credits.seq"); - - _frames[kOverlayTooltip] = new SequenceFrame(_seqTooltips); - _frames[kOverlayEggButtons] = new SequenceFrame(_seqEggButtons); - _frames[kOverlayButtons] = new SequenceFrame(_seqButtons); - _frames[kOverlayAcorn] = new SequenceFrame(_seqAcorn); - _frames[kOverlayCity1] = new SequenceFrame(_seqCity1); - _frames[kOverlayCity2] = new SequenceFrame(_seqCity2); - _frames[kOverlayCity3] = new SequenceFrame(_seqCity3); - _frames[kOverlayCredits] = new SequenceFrame(_seqCredits); -} - -////////////////////////////////////////////////////////////////////////// -// Handle events -void Menu::eventMouse(const Common::Event &ev) { - if (!getFlags()->shouldRedraw) - return; - - bool redraw = true; - getFlags()->shouldRedraw = false; - - // Update coordinates - setCoords(ev.mouse); - //_mouseFlags = (Common::EventType)(ev.type & Common::EVENT_LBUTTONUP); - - if (_isShowingCredits) { - if (ev.type == Common::EVENT_RBUTTONUP) { - showFrame(kOverlayCredits, -1, true); - _isShowingCredits = false; - } - - if (ev.type == Common::EVENT_LBUTTONUP) { - // Last frame of the credits - if (_seqCredits && _creditsSequenceIndex == _seqCredits->count() - 1) { - showFrame(kOverlayCredits, -1, true); - _isShowingCredits = false; - } else { - ++_creditsSequenceIndex; - showFrame(kOverlayCredits, _creditsSequenceIndex, true); - } - } - } else { - // Check for hotspots - SceneHotspot *hotspot = NULL; - getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot); - - if (_lastHotspot != hotspot || ev.type == Common::EVENT_LBUTTONUP) { - _lastHotspot = hotspot; - - if (ev.type == Common::EVENT_MOUSEMOVE) { /* todo check event type */ - if (!_handleTimeDelta && hasTimeDelta()) - setTime(); - } - - if (hotspot) { - redraw = handleEvent((StartMenuAction)hotspot->action, ev.type); - getFlags()->mouseRightClick = false; - getFlags()->mouseLeftClick = false; - } else { - hideOverlays(); - } - } - } - - if (redraw) { - getFlags()->shouldRedraw = true; - askForRedraw(); - } -} - -void Menu::eventTick(const Common::Event&) { - if (hasTimeDelta()) - adjustTime(); - else if (_handleTimeDelta) - _handleTimeDelta = false; - - // Check hotspots - if (!--_checkHotspotsTicks) { - checkHotspots(); - _checkHotspotsTicks = 15; - } -} - -////////////////////////////////////////////////////////////////////////// -// Show the intro and load the main menu scene -void Menu::show(bool doSavegame, SavegameType type, uint32 value) { - - if (_isShowingMenu) - return; - - _isShowingMenu = true; - getEntities()->reset(); - - // If no blue savegame exists, this might be the first time we start the game, so we show the full intro - if (!getFlags()->mouseRightClick) { - if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) { - - if (!_hasShownIntro) { - // Show Broderbrund logo - Animation animation; - if (animation.load(getArchive("1930.nis"))) - animation.play(); - - getFlags()->mouseRightClick = false; - - // Play intro music - getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer); - - // Show The Smoking Car logo - if (animation.load(getArchive("1931.nis"))) - animation.play(); - - _hasShownIntro = true; - } - } else { - // Only show the quick intro - if (!_hasShownStartScreen) { - getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer); - getScenes()->loadScene(kSceneStartScreen); - - // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed - uint32 nextFrameCount = getFrameCount() + 60; - while (getFrameCount() < nextFrameCount) { - _engine->pollEvents(); - - if (getFlags()->mouseRightClick) - break; - - getSound()->updateQueue(); - } - } - } - } - - _hasShownStartScreen = true; - - // Init Menu - init(doSavegame, type, value); - - // Setup sound - getSound()->unknownFunction4(); - getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13); - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); - - // Init flags & misc - _isShowingCredits = false; - _handleTimeDelta = hasTimeDelta(); - getInventory()->unselectItem(); - - // Set Cursor type - _engine->getCursor()->setStyle(kCursorNormal); - _engine->getCursor()->show(true); - - setup(); - checkHotspots(); - - // Set event handlers - SET_EVENT_HANDLERS(Menu, this); -} - -bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { - bool clicked = (type == Common::EVENT_LBUTTONUP); - - switch(action) { - default: - hideOverlays(); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuCredits: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - if (clicked) { - showFrame(kOverlayEggButtons, kButtonCreditsPushed, true); - showFrame(kOverlayTooltip, -1, true); - - getSound()->playSound(kEntityPlayer, "LIB046"); - - hideOverlays(); - - _isShowingCredits = true; - _creditsSequenceIndex = 0; - - showFrame(kOverlayCredits, 0, true); - } else { - // TODO check flags ? - - showFrame(kOverlayEggButtons, kButtonCredits, true); - showFrame(kOverlayTooltip, kTooltipCredits, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuQuitGame: - showFrame(kOverlayTooltip, kTooltipQuit, true); - - if (clicked) { - showFrame(kOverlayButtons, kButtonQuitPushed, true); - - getSound()->clearStatus(); - getSound()->updateQueue(); - getSound()->playSound(kEntityPlayer, "LIB046"); - - // FIXME uncomment when sound queue is properly implemented - /*while (getSound()->isBuffered("LIB046")) - getSound()->updateQueue();*/ - - getFlags()->shouldRedraw = false; - - Engine::quitGame(); - - return false; - } else { - showFrame(kOverlayButtons, kButtonQuit, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuCase4: - if (clicked) - _index = 0; - // fall down to kMenuContinue - - ////////////////////////////////////////////////////////////////////////// - case kMenuContinue: { - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - // Determine the proper CD archive - ArchiveIndex cd = kArchiveCd1; - if (getProgress().chapter > kChapter1) - cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2; - - // Show tooltips & buttons to start a game, continue a game or load the proper cd - if (ResourceManager::isArchivePresent(cd)) { - if (_isGameStarted) { - showFrame(kOverlayEggButtons, kButtonContinue, true); - - if (_lastIndex == _index) { - showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true); - } else { - showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true); - } - - } else { - showFrame(kOverlayEggButtons, kButtonShield, true); - showFrame(kOverlayTooltip, kTooltipPlayNewGame, true); - } - } else { - showFrame(kOverlayEggButtons, -1, true); - showFrame(kOverlayTooltip, cd - 1, true); - } - - if (!clicked) - break; - - // Try loading the archive file - if (!_engine->getResourceManager()->loadArchive(cd)) - break; - - // Load the train data file and setup game - getScenes()->loadSceneDataFile(cd); - showFrame(kOverlayTooltip, -1, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - - // Setup new game - getSavePoints()->reset(); - setLogicEventHandlers(); - - if (_index) { - getSound()->processEntry(SoundManager::kSoundType11); - } else { - if (!getFlags()->mouseRightClick) { - getScenes()->loadScene((SceneIndex)(5 * _gameId + 3)); - - if (!getFlags()->mouseRightClick) { - getScenes()->loadScene((SceneIndex)(5 * _gameId + 4)); - - if (!getFlags()->mouseRightClick) { - getScenes()->loadScene((SceneIndex)(5 * _gameId + 5)); - - if (!getFlags()->mouseRightClick) { - getSound()->processEntry(SoundManager::kSoundType11); - - // Show intro - Animation animation; - if (animation.load(getArchive("1601.nis"))) - animation.play(); - - getEvent(kEventIntro) = 1; - } - } - } - } - - if (!getEvent(kEventIntro)) { - getEvent(kEventIntro) = 1; - - getSound()->processEntry(SoundManager::kSoundType11); - } - } - - // Setup game - getFlags()->isGameRunning = true; - startGame(); - - if (!_isShowingMenu) - getInventory()->show(); - - return false; - } - - ////////////////////////////////////////////////////////////////////////// - case kMenuSwitchSaveGame: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - if (clicked) { - showFrame(kOverlayAcorn, 1, true); - showFrame(kOverlayTooltip, -1, true); - getSound()->playSound(kEntityPlayer, "LIB047"); - - // Setup new menu screen - switchGame(); - setup(); - - // Set fight state to 0 - getFight()->resetState(); - - return true; - } - - // TODO Check for flag - - showFrame(kOverlayAcorn, 0, true); - - if (_isGameStarted) { - showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); - break; - } - - if (_gameId == kGameGold) { - showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); - break; - } - - if (!SaveLoad::isSavegameValid(getNextGameId())) { - showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true); - break; - } - - // Stupid tooltips ids are not in order, so we can't just increment them... - switch(_gameId) { - default: - break; - - case kGameBlue: - showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true); - break; - - case kGameRed: - showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true); - break; - - case kGameGreen: - showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true); - break; - - case kGamePurple: - showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true); - break; - - case kGameTeal: - showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true); - break; - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuRewindGame: - if (!_index || _currentTime < _time) { - hideOverlays(); - break; - } - - if (clicked) { - if (hasTimeDelta()) - _handleTimeDelta = false; - - showFrame(kOverlayEggButtons, kButtonRewindPushed, true); - showFrame(kOverlayTooltip, -1, true); - - getSound()->playSound(kEntityPlayer, "LIB046"); - - rewindTime(); - - _handleTimeDelta = false; - } else { - showFrame(kOverlayEggButtons, kButtonRewind, true); - showFrame(kOverlayTooltip, kTooltipRewind, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuForwardGame: - if (_lastIndex <= _index || _currentTime > _time) { - hideOverlays(); - break; - } - - if (clicked) { - if (hasTimeDelta()) - _handleTimeDelta = false; - - showFrame(kOverlayEggButtons, kButtonForwardPushed, true); - showFrame(kOverlayTooltip, -1, true); - - getSound()->playSound(kEntityPlayer, "LIB046"); - - forwardTime(); - - _handleTimeDelta = false; - } else { - showFrame(kOverlayEggButtons, kButtonForward, true); - showFrame(kOverlayTooltip, kTooltipFastForward, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuParis: - moveToCity(kParis, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuStrasBourg: - moveToCity(kStrasbourg, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuMunich: - moveToCity(kMunich, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuVienna: - moveToCity(kVienna, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuBudapest: - moveToCity(kBudapest, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuBelgrade: - moveToCity(kBelgrade, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuConstantinople: - moveToCity(kConstantinople, clicked); - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuDecreaseVolume: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - // Cannot decrease volume further - if (getVolume() == 0) { - showFrame(kOverlayButtons, kButtonVolume, true); - showFrame(kOverlayTooltip, -1, true); - break; - } - - showFrame(kOverlayTooltip, kTooltipVolumeDown, true); - - // Show highlight on button & adjust volume if needed - if (clicked) { - showFrame(kOverlayButtons, kButtonVolumeDownPushed, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - setVolume(getVolume() - 1); - - getSaveLoad()->saveVolumeBrightness(); - - uint32 nextFrameCount = getFrameCount() + 15; - while (nextFrameCount > getFrameCount()) { - _engine->pollEvents(); - - getSound()->updateQueue(); - } - } else { - showFrame(kOverlayButtons, kButtonVolumeDown, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuIncreaseVolume: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - // Cannot increase volume further - if (getVolume() >= 7) { - showFrame(kOverlayButtons, kButtonVolume, true); - showFrame(kOverlayTooltip, -1, true); - break; - } - - showFrame(kOverlayTooltip, kTooltipVolumeUp, true); - - // Show highlight on button & adjust volume if needed - if (clicked) { - showFrame(kOverlayButtons, kButtonVolumeUpPushed, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - setVolume(getVolume() + 1); - - getSaveLoad()->saveVolumeBrightness(); - - uint32 nextFrameCount = getFrameCount() + 15; - while (nextFrameCount > getFrameCount()) { - _engine->pollEvents(); - - getSound()->updateQueue(); - } - } else { - showFrame(kOverlayButtons, kButtonVolumeUp, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuDecreaseBrightness: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - // Cannot increase brightness further - if (getBrightness() == 0) { - showFrame(kOverlayButtons, kButtonBrightness, true); - showFrame(kOverlayTooltip, -1, true); - break; - } - - showFrame(kOverlayTooltip, kTooltipBrightnessDown, true); - - // Show highlight on button & adjust brightness if needed - if (clicked) { - showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - setBrightness(getBrightness() - 1); - - getSaveLoad()->saveVolumeBrightness(); - - // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) - _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); - showFrame(kOverlayTooltip, kTooltipBrightnessDown, false); - showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false); - } else { - showFrame(kOverlayButtons, kButtonBrightnessDown, true); - } - break; - - ////////////////////////////////////////////////////////////////////////// - case kMenuIncreaseBrightness: - if (hasTimeDelta()) { - hideOverlays(); - break; - } - - // Cannot increase brightness further - if (getBrightness() >= 6) { - showFrame(kOverlayButtons, kButtonBrightness, true); - showFrame(kOverlayTooltip, -1, true); - break; - } - - showFrame(kOverlayTooltip, kTooltipBrightnessUp, true); - - // Show highlight on button & adjust brightness if needed - if (clicked) { - showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - setBrightness(getBrightness() + 1); - - getSaveLoad()->saveVolumeBrightness(); - - // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) - _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); - showFrame(kOverlayTooltip, kTooltipBrightnessUp, false); - showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false); - } else { - showFrame(kOverlayButtons, kButtonBrightnessUp, true); - } - break; - } - - return true; -} - -void Menu::setLogicEventHandlers() { - SET_EVENT_HANDLERS(Logic, getLogic()); - clear(); - _isShowingMenu = false; -} - -////////////////////////////////////////////////////////////////////////// -// Game-related -////////////////////////////////////////////////////////////////////////// -void Menu::init(bool doSavegame, SavegameType type, uint32 value) { - - bool useSameIndex = true; - - if (getGlobalTimer()) { - value = 0; - - // Check if the CD file is present - ArchiveIndex index = kArchiveCd1; - switch (getProgress().chapter) { - default: - case kChapter1: - break; - - case kChapter2: - case kChapter3: - index = kArchiveCd2; - break; - - case kChapter4: - case kChapter5: - index = kArchiveCd3; - break; - } - - if (ResourceManager::isArchivePresent(index)) { - setGlobalTimer(0); - useSameIndex = false; - - // TODO remove existing savegame and reset index & savegame name - warning("Menu::initGame: not implemented!"); - } - - doSavegame = false; - } else { - // TODO rename saves? - } - - // Create a new savegame if needed - if (!SaveLoad::isSavegamePresent(_gameId)) - getSaveLoad()->create(_gameId); - - if (doSavegame) - getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone); - - if (!getGlobalTimer()) { - // TODO: remove existing savegame temp file - } - - // Init savegame & menu values - _lastIndex = getSaveLoad()->init(_gameId, true); - _lowerTime = getSaveLoad()->getTime(_lastIndex); - - if (useSameIndex) - _index = _lastIndex; - - //if (!getGlobalTimer()) - // _index3 = 0; - - if (!getProgress().chapter) - getProgress().chapter = kChapter1; - - getState()->time = (TimeValue)getSaveLoad()->getTime(_index); - getProgress().chapter = getSaveLoad()->getChapter(_index); - - if (_lowerTime >= kTimeStartGame) { - _currentTime = (uint32)getState()->time; - _time = (uint32)getState()->time; - _clock->draw(_time); - _trainLine->draw(_time); - - initTime(type, value); - } -} - -// Start a game (or load an existing savegame) -void Menu::startGame() { - // Clear savegame headers - getSaveLoad()->clear(); - - // Hide menu elements - _clock->clear(); - _trainLine->clear(); - - if (_lastIndex == _index) { - setGlobalTimer(0); - if (_index) { - getSaveLoad()->loadGame(_gameId); - } else { - getLogic()->resetState(); - getEntities()->setup(true, kEntityPlayer); - } - } else { - getSaveLoad()->loadGame(_gameId, _index); - } -} - -// Switch to the next savegame -void Menu::switchGame() { - - // Switch back to blue game is the current game is not started - _gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue; - - // Initialize savegame if needed - if (!SaveLoad::isSavegamePresent(_gameId)) - getSaveLoad()->create(_gameId); - - getState()->time = kTimeNone; - - // Clear menu elements - _clock->clear(); - _trainLine->clear(); - - // Clear loaded savegame data - getSaveLoad()->clear(true); - - init(false, kSavegameTypeIndex, 0); -} - -////////////////////////////////////////////////////////////////////////// -// Overlays & elements -////////////////////////////////////////////////////////////////////////// -void Menu::checkHotspots() { - if (!_isShowingMenu) - return; - - if (!getFlags()->shouldRedraw) - return; - - if (_isShowingCredits) - return; - - SceneHotspot *hotspot = NULL; - getScenes()->get(getState()->scene)->checkHotSpot(getCoords(), &hotspot); - - if (hotspot) - handleEvent((StartMenuAction)hotspot->action, _mouseFlags); - else - hideOverlays(); -} - -void Menu::hideOverlays() { - _lastHotspot = NULL; - - // Hide all menu overlays - for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) - showFrame(it->_key, -1, false); - - getScenes()->drawFrames(true); -} - -void Menu::showFrame(StartMenuOverlay overlayType, int index, bool redraw) { - if (index == -1) { - getScenes()->removeFromQueue(_frames[overlayType]); - } else { - // Check that the overlay is valid - if (!_frames[overlayType]) - return; - - // Remove the frame and add a new one with the proper index - getScenes()->removeFromQueue(_frames[overlayType]); - _frames[overlayType]->setFrame((uint16)index); - getScenes()->addToQueue(_frames[overlayType]); - } - - if (redraw) - getScenes()->drawFrames(true); -} - -// Remove all frames from the queue -void Menu::clear() { - for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) - getScenes()->removeAndRedraw(&it->_value, false); - - clearBg(GraphicsManager::kBackgroundOverlay); -} - -// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame -Common::String Menu::getAcornSequenceName(GameId id) const { - Common::String name = ""; - switch (id) { - default: - case kGameBlue: - name = "aconblu3.seq"; - break; - - case kGameRed: - name = "aconred.seq"; - break; - - case kGameGreen: - name = "acongren.seq"; - break; - - case kGamePurple: - name = "aconpurp.seq"; - break; - - case kGameTeal: - name = "aconteal.seq"; - break; - - case kGameGold: - name = "acongold.seq"; - break; - } - - return name; -} - -////////////////////////////////////////////////////////////////////////// -// Time -////////////////////////////////////////////////////////////////////////// -void Menu::initTime(SavegameType type, uint32 value) { - if (!value) - return; - - // The savegame entry index - uint32 entryIndex = 0; - - switch (type) { - default: - break; - - case kSavegameTypeIndex: - entryIndex = (_index <= value) ? 1 : _index - value; - break; - - case kSavegameTypeTime: - if (value < kTimeStartGame) - break; - - entryIndex = _index; - if (!entryIndex) - break; - - // Iterate through existing entries - do { - if (getSaveLoad()->getTime(entryIndex) <= value) - break; - - entryIndex--; - } while (entryIndex); - break; - - case kSavegameTypeEvent: - entryIndex = _index; - if (!entryIndex) - break; - - do { - if (getSaveLoad()->getValue(entryIndex) == value) - break; - - entryIndex--; - } while (entryIndex); - break; - - case kSavegameTypeEvent2: - // TODO rewrite in a more legible way - if (_index > 1) { - uint32 index = _index; - do { - if (getSaveLoad()->getValue(index) == value) - break; - - index--; - } while (index > 1); - - entryIndex = index - 1; - } else { - entryIndex = _index - 1; - } - break; - } - - if (entryIndex) { - _currentIndex = entryIndex; - updateTime(getSaveLoad()->getTime(entryIndex)); - } -} - -void Menu::updateTime(uint32 time) { - if (_currentTime == _time) - _delta = 0; - - _currentTime = time; - - if (_time != time) { - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); - - getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters); - adjustIndex(_currentTime, _time, false); - } -} - -void Menu::adjustIndex(uint32 time1, uint32 time2, bool searchEntry) { - uint32 index = 0; - int32 timeDelta = -1; - - if (time1 != time2) { - - index = _index; - - if (time2 >= time1) { - if (searchEntry) { - uint32 currentIndex = _index; - - if ((int32)_index >= 0) { - do { - // Calculate new delta - int32 newDelta = time1 - (uint32)getSaveLoad()->getTime(currentIndex); - - if (newDelta >= 0 && timeDelta >= newDelta) { - timeDelta = newDelta; - index = currentIndex; - } - - --currentIndex; - } while ((int32)currentIndex >= 0); - } - } else { - index = _index - 1; - } - } else { - if (searchEntry) { - uint32 currentIndex = _index; - - if (_lastIndex >= _index) { - do { - // Calculate new delta - int32 newDelta = (uint32)getSaveLoad()->getTime(currentIndex) - time1; - - if (newDelta >= 0 && timeDelta > newDelta) { - timeDelta = newDelta; - index = currentIndex; - } - - ++currentIndex; - } while (currentIndex <= _lastIndex); - } - } else { - index = _index + 1; - } - } - - _index = index; - checkHotspots(); - } - - if (_index == _currentIndex) { - if (getProgress().chapter != getSaveLoad()->getChapter(index)) - getProgress().chapter = getSaveLoad()->getChapter(_index); - } -} - -void Menu::goToTime(uint32 time) { - - uint32 entryIndex = 0; - uint32 deltaTime = (uint32)ABS((int32)(getSaveLoad()->getTime(0) - time)); - uint32 index = 0; - - do { - uint32 deltaTime2 = (uint32)ABS((int32)(getSaveLoad()->getTime(index) - time)); - if (deltaTime2 < deltaTime) { - deltaTime = deltaTime2; - entryIndex = index; - } - - ++index; - } while (_lastIndex >= index); - - _currentIndex = entryIndex; - updateTime(getSaveLoad()->getTime(entryIndex)); -} - -void Menu::setTime() { - _currentIndex = _index; - _currentTime = getSaveLoad()->getTime(_currentIndex); - - if (_time == _currentTime) - adjustTime(); -} - -void Menu::forwardTime() { - if (_lastIndex <= _index) - return; - - _currentIndex = _lastIndex; - updateTime(getSaveLoad()->getTime(_currentIndex)); -} - -void Menu::rewindTime() { - if (!_index) - return; - - _currentIndex = 0; - updateTime(getSaveLoad()->getTime(_currentIndex)); -} - -void Menu::adjustTime() { - uint32 originalTime = _time; - - // Adjust time delta - Common::Rational timeDelta(_delta >= 90 ? 9 : (9 * _delta + 89), _delta >= 90 ? 1 : 90); - - if (_currentTime < _time) { - timeDelta *= 900; - _time -= (uint)timeDelta.toInt(); - - if (_currentTime > _time) - _time = _currentTime; - } else { - timeDelta *= 900; - _time += (uint)timeDelta.toInt(); - - if (_currentTime < _time) - _time = _currentTime; - } - - if (_currentTime == _time && getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); - - _clock->draw(_time); - _trainLine->draw(_time); - getScenes()->drawFrames(true); - - adjustIndex(_time, originalTime, true); - - ++_delta; -} - -void Menu::moveToCity(CityButton city, bool clicked) { - uint32 time = (uint32)_cityButtonsInfo[city].time; - - // TODO Check if we have access (there seems to be more checks on some internal times) - probably : current_time (menu only) / game time / some other? - if (_lowerTime < time || _time == time || _currentTime == time) { - hideOverlays(); - return; - } - - // Show city overlay - showFrame((StartMenuOverlay)((_cityButtonsInfo[city].index >> 6) + 3), _cityButtonsInfo[city].index & 63, true); - - if (clicked) { - showFrame(kOverlayTooltip, -1, true); - getSound()->playSound(kEntityPlayer, "LIB046"); - goToTime(time); - - _handleTimeDelta = true; - - return; - } - - // Special case of first and last cities - if (city == kParis || city == kConstantinople) { - showFrame(kOverlayTooltip, (city == kParis) ? kTooltipRewindParis : kTooltipForwardConstantinople, true); - return; - } - - showFrame(kOverlayTooltip, (_time <= time) ? _cityButtonsInfo[city].forward : _cityButtonsInfo[city].rewind, true); -} - -////////////////////////////////////////////////////////////////////////// -// Sound / Brightness -////////////////////////////////////////////////////////////////////////// - -// Get current volume (converted internal ScummVM value) -uint32 Menu::getVolume() const { - return getState()->volume; -} - -// Set the volume (converts to ScummVM values) -void Menu::setVolume(uint32 volume) const { - getState()->volume = volume; - - // Clamp volume - uint32 value = volume * Audio::Mixer::kMaxMixerVolume / 7; - - if (value > Audio::Mixer::kMaxMixerVolume) - value = Audio::Mixer::kMaxMixerVolume; - - _engine->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (int32)value); -} - -uint32 Menu::getBrightness() const { - return getState()->brightness; -} - -void Menu::setBrightness(uint32 brightness) const { - getState()->brightness = brightness; - - // TODO reload cursor & font with adjusted brightness -} - -} // End of namespace LastExpress diff --git a/engines/lastexpress/game/menu.h b/engines/lastexpress/game/menu.h deleted file mode 100644 index 4b84c065cb..0000000000 --- a/engines/lastexpress/game/menu.h +++ /dev/null @@ -1,207 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef LASTEXPRESS_MENU_H -#define LASTEXPRESS_MENU_H - -#include "lastexpress/data/sequence.h" - -#include "lastexpress/eventhandler.h" - -#include "lastexpress/shared.h" - -#include "common/hashmap.h" - -namespace LastExpress { - -class LastExpressEngine; -class Scene; -class SceneHotspot; - -class Clock; -class TrainLine; - -class Menu : public EventHandler { -public: - Menu(LastExpressEngine *engine); - ~Menu(); - - void show(bool doSavegame, SavegameType type, uint32 value); - - // Event handling - void eventMouse(const Common::Event &ev); - void eventTick(const Common::Event &ev); - - bool isShown() const { return _isShowingMenu; } - - GameId getGameId() const { return _gameId; } - -private: - // Start menu events - enum StartMenuAction { - kMenuContinue = 1, - kMenuCredits = 2, - kMenuQuitGame = 3, - kMenuCase4 = 4, - kMenuSwitchSaveGame = 6, - kMenuRewindGame = 7, - kMenuForwardGame = 8, - kMenuParis = 10, - kMenuStrasBourg = 11, - kMenuMunich = 12, - kMenuVienna = 13, - kMenuBudapest = 14, - kMenuBelgrade = 15, - kMenuConstantinople = 16, - kMenuDecreaseVolume = 17, - kMenuIncreaseVolume = 18, - kMenuDecreaseBrightness = 19, - kMenuIncreaseBrightness = 20 - }; - - // City buttons - enum CityButton { - kParis = 0, - kStrasbourg = 1, - kMunich = 2, - kVienna = 3, - kBudapest = 4, - kBelgrade = 5, - kConstantinople = 6 - }; - - // Start menu overlay elements - enum StartMenuOverlay { - kOverlayTooltip, // 0 - kOverlayEggButtons, - kOverlayButtons, - kOverlayAcorn, - kOverlayCity1, - kOverlayCity2, // 5 - kOverlayCity3, - kOverlayCredits - }; - - LastExpressEngine *_engine; - - // Sequences - Sequence *_seqTooltips; - Sequence *_seqEggButtons; - Sequence *_seqButtons; - Sequence *_seqAcorn; - Sequence *_seqCity1; - Sequence *_seqCity2; - Sequence *_seqCity3; - Sequence *_seqCredits; - - GameId _gameId; - - // Indicator to know if we need to show the start animation when showMenu is called - bool _hasShownStartScreen; - bool _hasShownIntro; - - bool _isShowingCredits; - bool _isGameStarted; - bool _isShowingMenu; - - - uint16 _creditsSequenceIndex; - - ////////////////////////////////////////////////////////////////////////// - // Event handling - uint32 _checkHotspotsTicks; - Common::EventType _mouseFlags; - SceneHotspot *_lastHotspot; - - void init(bool doSavegame, SavegameType type, uint32 value); - void setup(); - bool handleEvent(StartMenuAction action, Common::EventType type); - void checkHotspots(); - void setLogicEventHandlers(); - - ////////////////////////////////////////////////////////////////////////// - // Game-related - void startGame(); - void switchGame(); - - ////////////////////////////////////////////////////////////////////////// - // Overlays & elements - Clock *_clock; - TrainLine *_trainLine; - - struct MenuOverlays_EqualTo { - bool operator()(const StartMenuOverlay &x, const StartMenuOverlay &y) const { return x == y; } - }; - - struct MenuOverlays_Hash { - uint operator()(const StartMenuOverlay &x) const { return x; } - }; - - typedef Common::HashMap MenuFrames; - - MenuFrames _frames; - - void hideOverlays(); - void showFrame(StartMenuOverlay overlay, int index, bool redraw); - - void clear(); - - // TODO: remove? - void moveToCity(CityButton city, bool clicked); - - ////////////////////////////////////////////////////////////////////////// - // Misc - Common::String getAcornSequenceName(GameId id) const; - - ////////////////////////////////////////////////////////////////////////// - // Time - uint32 _currentTime; // current game time - uint32 _lowerTime; // lower time value - uint32 _time; - - uint32 _currentIndex; // current savegame entry - uint32 _index; - uint32 _lastIndex; - uint32 _delta; - bool _handleTimeDelta; - - void initTime(SavegameType type, uint32 val); - void updateTime(uint32 time); - void adjustTime(); - void adjustIndex(uint32 time1, uint32 time2, bool searchEntry); - void goToTime(uint32 time); - void setTime(); - void forwardTime(); - void rewindTime(); - bool hasTimeDelta() { return (_currentTime - _time) >= 1; } - - ////////////////////////////////////////////////////////////////////////// - // Sound/Brightness related - uint32 getVolume() const; - void setVolume(uint32 volume) const; - uint32 getBrightness() const; - void setBrightness(uint32 brightness) const; -}; - -} // End of namespace LastExpress - -#endif // LASTEXPRESS_MENU_H diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index 5d06ecab13..594cd1276b 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -24,11 +24,12 @@ #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" -#include "lastexpress/game/menu.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/state.h" +#include "lastexpress/menu/menu.h" + #include "lastexpress/debug.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index 120e6eb28b..73893c9982 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -26,11 +26,12 @@ #include "lastexpress/data/font.h" #include "lastexpress/game/logic.h" -#include "lastexpress/game/menu.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/state.h" #include "lastexpress/game/sound.h" +#include "lastexpress/menu/menu.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/resource.h" diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp new file mode 100644 index 0000000000..b7e6a1430a --- /dev/null +++ b/engines/lastexpress/menu/menu.cpp @@ -0,0 +1,1542 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/menu/menu.h" + +// Data +#include "lastexpress/data/animation.h" +#include "lastexpress/data/cursor.h" +#include "lastexpress/data/snd.h" +#include "lastexpress/data/scene.h" + +#include "lastexpress/fight/fight.h" + +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/savegame.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/graphics.h" +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +#include "common/rational.h" + +#define getNextGameId() (GameId)((_gameId + 1) % 6) + +namespace LastExpress { + +// Bottom-left buttons (quit.seq) +enum StartMenuButtons { + kButtonVolumeDownPushed, + kButtonVolumeDown, + kButtonVolume, + kButtonVolumeUp, + kButtonVolumeUpPushed, + kButtonBrightnessDownPushed, // 5 + kButtonBrightnessDown, + kButtonBrightness, + kButtonBrightnessUp, + kButtonBrightnessUpPushed, + kButtonQuit, // 10 + kButtonQuitPushed +}; + +// Egg buttons (buttns.seq) +enum StartMenuEggButtons { + kButtonShield, + kButtonRewind, + kButtonRewindPushed, + kButtonForward, + kButtonForwardPushed, + kButtonCredits, // 5 + kButtonCreditsPushed, + kButtonContinue +}; + +// Tooltips sequence (helpnewr.seq) +enum StartMenuTooltips { + kTooltipInsertCd1, + kTooltipInsertCd2, + kTooltipInsertCd3, + kTooltipContinueGame, + kTooltipReplayGame, + kTooltipContinueRewoundGame, // 5 + kTooltipViewGameEnding, + kTooltipStartAnotherGame, + kTooltipVolumeUp, + kTooltipVolumeDown, + kTooltipBrightnessUp, // 10 + kTooltipBrightnessDown, + kTooltipQuit, + kTooltipRewindParis, + kTooltipForwardStrasbourg, + kTooltipRewindStrasbourg, // 15 + kTooltipRewindMunich, + kTooltipForwardMunich, + kTooltipForwardVienna, + kTooltipRewindVienna, + kTooltipRewindBudapest, // 20 + kTooltipForwardBudapest, + kTooltipForwardBelgrade, + kTooltipRewindBelgrade, + kTooltipForwardConstantinople, + kTooltipSwitchBlueGame, // 25 + kTooltipSwitchRedGame, + kTooltipSwitchGoldGame, + kTooltipSwitchGreenGame, + kTooltipSwitchTealGame, + kTooltipSwitchPurpleGame, // 30 + kTooltipPlayNewGame, + kTooltipCredits, + kTooltipFastForward, + kTooltipRewind +}; + +////////////////////////////////////////////////////////////////////////// +// DATA +////////////////////////////////////////////////////////////////////////// + +// Information about the cities on the train line +static const struct { + uint8 frame; + TimeValue time; +} _trainCities[31] = { + {0, kTimeCityParis}, + {9, kTimeCityEpernay}, + {11, kTimeCityChalons}, + {16, kTimeCityBarLeDuc}, + {21, kTimeCityNancy}, + {25, kTimeCityLuneville}, + {35, kTimeCityAvricourt}, + {37, kTimeCityDeutschAvricourt}, + {40, kTimeCityStrasbourg}, + {53, kTimeCityBadenOos}, + {56, kTimeCityKarlsruhe}, + {60, kTimeCityStuttgart}, + {63, kTimeCityGeislingen}, + {66, kTimeCityUlm}, + {68, kTimeCityAugsburg}, + {73, kTimeCityMunich}, + {84, kTimeCitySalzbourg}, + {89, kTimeCityAttnangPuchheim}, + {97, kTimeCityWels}, + {100, kTimeCityLinz}, + {104, kTimeCityAmstetten}, + {111, kTimeCityVienna}, + {120, kTimeCityPoszony}, + {124, kTimeCityGalanta}, + {132, kTimeCityBudapest}, + {148, kTimeCityBelgrade}, + /* Line 1 ends at 150 - line 2 begins at 0 */ + {157, kTimeCityNish}, + {165, kTimeCityTzaribrod}, + {174, kTimeCitySofia}, + {198, kTimeCityAdrianople}, + {210, kTimeCityConstantinople}}; + +static const struct { + TimeValue time; + uint index; + StartMenuTooltips rewind; + StartMenuTooltips forward; +} _cityButtonsInfo[7] = { + {kTimeCityParis, 64, kTooltipRewindParis, kTooltipRewindParis}, + {kTimeCityStrasbourg, 128, kTooltipRewindStrasbourg, kTooltipForwardStrasbourg}, + {kTimeCityMunich, 129, kTooltipRewindMunich, kTooltipForwardMunich}, + {kTimeCityVienna, 130, kTooltipRewindVienna, kTooltipForwardVienna}, + {kTimeCityBudapest, 131, kTooltipRewindBudapest, kTooltipForwardBudapest}, + {kTimeCityBelgrade, 132, kTooltipRewindBelgrade, kTooltipForwardBelgrade}, + {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople} +}; + +////////////////////////////////////////////////////////////////////////// +// Clock +////////////////////////////////////////////////////////////////////////// +class Clock { +public: + explicit Clock(LastExpressEngine *engine); + ~Clock(); + + void draw(uint32 time); + void clear(); + +private: + LastExpressEngine *_engine; + + // Frames + SequenceFrame *_frameMinutes; + SequenceFrame *_frameHour; + SequenceFrame *_frameSun; + SequenceFrame *_frameDate; +}; + +Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) { + _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true); + _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true); + _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true); + _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true); +} + +Clock::~Clock() { + SAFE_DELETE(_frameMinutes); + SAFE_DELETE(_frameHour); + SAFE_DELETE(_frameSun); + SAFE_DELETE(_frameDate); + + // Zero passed pointers + _engine = NULL; +} + +void Clock::clear() { + getScenes()->removeFromQueue(_frameMinutes); + getScenes()->removeFromQueue(_frameHour); + getScenes()->removeFromQueue(_frameSun); + getScenes()->removeFromQueue(_frameDate); +} + +void Clock::draw(uint32 time) { + assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); + + // Check that sequences have been loaded + if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate) + error("Clock::process: clock sequences have not been loaded correctly!"); + + // Clear existing frames + clear(); + + // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914 + // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914 + // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins + + // 15 = 1 second + // 15 * 60 = 900 = 1 minute + // 900 * 60 = 54000 = 1 hour + // 54000 * 24 = 1296000 = 1 day + + // Calculate each sequence index from the current time + + uint8 hour = 0; + uint8 minute = 0; + State::getHourMinutes(time, &hour, &minute); + uint32 index_date = 18 * time / 1296000; + if (hour == 23) + index_date += 18 * minute / 60; + + // Set sequences frames + _frameMinutes->setFrame(minute); + _frameHour->setFrame((5 * hour + minute / 12) % 60); + _frameSun->setFrame((5 * hour + minute / 12) % 120); + _frameDate->setFrame((uint16)index_date); + + // Adjust z-order and queue + _frameMinutes->getInfo()->location = 1; + _frameHour->getInfo()->location = 1; + _frameSun->getInfo()->location = 1; + _frameDate->getInfo()->location = 1; + + getScenes()->addToQueue(_frameMinutes); + getScenes()->addToQueue(_frameHour); + getScenes()->addToQueue(_frameSun); + getScenes()->addToQueue(_frameDate); +} + +////////////////////////////////////////////////////////////////////////// +// TrainLine +////////////////////////////////////////////////////////////////////////// +class TrainLine { +public: + explicit TrainLine(LastExpressEngine *engine); + ~TrainLine(); + + void draw(uint32 time); + void clear(); + +private: + LastExpressEngine *_engine; + + // Frames + SequenceFrame *_frameLine1; + SequenceFrame *_frameLine2; +}; + +TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) { + _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true); + _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true); +} + +TrainLine::~TrainLine() { + SAFE_DELETE(_frameLine1); + SAFE_DELETE(_frameLine2); + + // Zero passed pointers + _engine = NULL; +} + +void TrainLine::clear() { + getScenes()->removeFromQueue(_frameLine1); + getScenes()->removeFromQueue(_frameLine2); +} + +// Draw the train line at the time +// line1: 150 frames (=> Belgrade) +// line2: 61 frames (=> Constantinople) +void TrainLine::draw(uint32 time) { + assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); + + // Check that sequences have been loaded + if (!_frameLine1 || !_frameLine2) + error("TrainLine::process: Line sequences have not been loaded correctly!"); + + // Clear existing frames + clear(); + + // Get the index of the last city the train has visited + uint index = 0; + for (uint i = 0; i < ARRAYSIZE(_trainCities); i++) + if ((uint32)_trainCities[i].time <= time) + index = i; + + uint16 frame; + if (time > (uint32)_trainCities[index].time) { + // Interpolate linearly to use a frame between the cities + uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame; + uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time); + uint traveledTime = (time - (uint)_trainCities[index].time); + frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities); + } else { + // Exactly on the city + frame = _trainCities[index].frame; + } + + // Set frame, z-order and queue + if (frame < 150) { + _frameLine1->setFrame(frame); + + _frameLine1->getInfo()->location = 1; + getScenes()->addToQueue(_frameLine1); + } else { + // We passed Belgrade + _frameLine1->setFrame(149); + _frameLine2->setFrame(frame - 150); + + _frameLine1->getInfo()->location = 1; + _frameLine2->getInfo()->location = 1; + + getScenes()->addToQueue(_frameLine1); + getScenes()->addToQueue(_frameLine2); + } +} + + +////////////////////////////////////////////////////////////////////////// +// Menu +////////////////////////////////////////////////////////////////////////// +Menu::Menu(LastExpressEngine *engine) : _engine(engine), + _seqTooltips(NULL), _seqEggButtons(NULL), _seqButtons(NULL), _seqAcorn(NULL), _seqCity1(NULL), _seqCity2(NULL), _seqCity3(NULL), _seqCredits(NULL), + _gameId(kGameBlue), _hasShownStartScreen(false), _hasShownIntro(false), + _isShowingCredits(false), _isGameStarted(false), _isShowingMenu(false), + _creditsSequenceIndex(0), _checkHotspotsTicks(15), _mouseFlags(Common::EVENT_INVALID), _lastHotspot(NULL), + _currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) { + + _clock = new Clock(_engine); + _trainLine = new TrainLine(_engine); +} + +Menu::~Menu() { + SAFE_DELETE(_clock); + SAFE_DELETE(_trainLine); + + SAFE_DELETE(_seqTooltips); + SAFE_DELETE(_seqEggButtons); + SAFE_DELETE(_seqButtons); + SAFE_DELETE(_seqAcorn); + SAFE_DELETE(_seqCity1); + SAFE_DELETE(_seqCity2); + SAFE_DELETE(_seqCity3); + SAFE_DELETE(_seqCredits); + + _lastHotspot = NULL; + + // Cleanup frames + for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) + SAFE_DELETE(it->_value); + + _frames.clear(); + + // Zero passed pointers + _engine = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Setup +void Menu::setup() { + + // Clear drawing queue + getScenes()->removeAndRedraw(&_frames[kOverlayAcorn], false); + SAFE_DELETE(_seqAcorn); + + // Load Menu scene + // + 1 = normal menu with open egg / clock + // + 2 = shield menu, when no savegame exists (no game has been started) + _isGameStarted = _lowerTime >= kTimeStartGame; + getScenes()->loadScene((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)); + getFlags()->shouldRedraw = true; + getLogic()->updateCursor(); + + ////////////////////////////////////////////////////////////////////////// + // Load Acorn sequence + _seqAcorn = loadSequence(getAcornSequenceName(_isGameStarted ? getNextGameId() : kGameBlue)); + + ////////////////////////////////////////////////////////////////////////// + // Check if we loaded sequences before + if (_seqTooltips && _seqTooltips->count() > 0) + return; + + // Load all static data + _seqTooltips = loadSequence("helpnewr.seq"); + _seqEggButtons = loadSequence("buttns.seq"); + _seqButtons = loadSequence("quit.seq"); + _seqCity1 = loadSequence("jlinetl.seq"); + _seqCity2 = loadSequence("jlinecen.seq"); + _seqCity3 = loadSequence("jlinebr.seq"); + _seqCredits = loadSequence("credits.seq"); + + _frames[kOverlayTooltip] = new SequenceFrame(_seqTooltips); + _frames[kOverlayEggButtons] = new SequenceFrame(_seqEggButtons); + _frames[kOverlayButtons] = new SequenceFrame(_seqButtons); + _frames[kOverlayAcorn] = new SequenceFrame(_seqAcorn); + _frames[kOverlayCity1] = new SequenceFrame(_seqCity1); + _frames[kOverlayCity2] = new SequenceFrame(_seqCity2); + _frames[kOverlayCity3] = new SequenceFrame(_seqCity3); + _frames[kOverlayCredits] = new SequenceFrame(_seqCredits); +} + +////////////////////////////////////////////////////////////////////////// +// Handle events +void Menu::eventMouse(const Common::Event &ev) { + if (!getFlags()->shouldRedraw) + return; + + bool redraw = true; + getFlags()->shouldRedraw = false; + + // Update coordinates + setCoords(ev.mouse); + //_mouseFlags = (Common::EventType)(ev.type & Common::EVENT_LBUTTONUP); + + if (_isShowingCredits) { + if (ev.type == Common::EVENT_RBUTTONUP) { + showFrame(kOverlayCredits, -1, true); + _isShowingCredits = false; + } + + if (ev.type == Common::EVENT_LBUTTONUP) { + // Last frame of the credits + if (_seqCredits && _creditsSequenceIndex == _seqCredits->count() - 1) { + showFrame(kOverlayCredits, -1, true); + _isShowingCredits = false; + } else { + ++_creditsSequenceIndex; + showFrame(kOverlayCredits, _creditsSequenceIndex, true); + } + } + } else { + // Check for hotspots + SceneHotspot *hotspot = NULL; + getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot); + + if (_lastHotspot != hotspot || ev.type == Common::EVENT_LBUTTONUP) { + _lastHotspot = hotspot; + + if (ev.type == Common::EVENT_MOUSEMOVE) { /* todo check event type */ + if (!_handleTimeDelta && hasTimeDelta()) + setTime(); + } + + if (hotspot) { + redraw = handleEvent((StartMenuAction)hotspot->action, ev.type); + getFlags()->mouseRightClick = false; + getFlags()->mouseLeftClick = false; + } else { + hideOverlays(); + } + } + } + + if (redraw) { + getFlags()->shouldRedraw = true; + askForRedraw(); + } +} + +void Menu::eventTick(const Common::Event&) { + if (hasTimeDelta()) + adjustTime(); + else if (_handleTimeDelta) + _handleTimeDelta = false; + + // Check hotspots + if (!--_checkHotspotsTicks) { + checkHotspots(); + _checkHotspotsTicks = 15; + } +} + +////////////////////////////////////////////////////////////////////////// +// Show the intro and load the main menu scene +void Menu::show(bool doSavegame, SavegameType type, uint32 value) { + + if (_isShowingMenu) + return; + + _isShowingMenu = true; + getEntities()->reset(); + + // If no blue savegame exists, this might be the first time we start the game, so we show the full intro + if (!getFlags()->mouseRightClick) { + if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) { + + if (!_hasShownIntro) { + // Show Broderbrund logo + Animation animation; + if (animation.load(getArchive("1930.nis"))) + animation.play(); + + getFlags()->mouseRightClick = false; + + // Play intro music + getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer); + + // Show The Smoking Car logo + if (animation.load(getArchive("1931.nis"))) + animation.play(); + + _hasShownIntro = true; + } + } else { + // Only show the quick intro + if (!_hasShownStartScreen) { + getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer); + getScenes()->loadScene(kSceneStartScreen); + + // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed + uint32 nextFrameCount = getFrameCount() + 60; + while (getFrameCount() < nextFrameCount) { + _engine->pollEvents(); + + if (getFlags()->mouseRightClick) + break; + + getSound()->updateQueue(); + } + } + } + } + + _hasShownStartScreen = true; + + // Init Menu + init(doSavegame, type, value); + + // Setup sound + getSound()->unknownFunction4(); + getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13); + if (getSound()->isBuffered("TIMER")) + getSound()->removeFromQueue("TIMER"); + + // Init flags & misc + _isShowingCredits = false; + _handleTimeDelta = hasTimeDelta(); + getInventory()->unselectItem(); + + // Set Cursor type + _engine->getCursor()->setStyle(kCursorNormal); + _engine->getCursor()->show(true); + + setup(); + checkHotspots(); + + // Set event handlers + SET_EVENT_HANDLERS(Menu, this); +} + +bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { + bool clicked = (type == Common::EVENT_LBUTTONUP); + + switch(action) { + default: + hideOverlays(); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuCredits: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + if (clicked) { + showFrame(kOverlayEggButtons, kButtonCreditsPushed, true); + showFrame(kOverlayTooltip, -1, true); + + getSound()->playSound(kEntityPlayer, "LIB046"); + + hideOverlays(); + + _isShowingCredits = true; + _creditsSequenceIndex = 0; + + showFrame(kOverlayCredits, 0, true); + } else { + // TODO check flags ? + + showFrame(kOverlayEggButtons, kButtonCredits, true); + showFrame(kOverlayTooltip, kTooltipCredits, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuQuitGame: + showFrame(kOverlayTooltip, kTooltipQuit, true); + + if (clicked) { + showFrame(kOverlayButtons, kButtonQuitPushed, true); + + getSound()->clearStatus(); + getSound()->updateQueue(); + getSound()->playSound(kEntityPlayer, "LIB046"); + + // FIXME uncomment when sound queue is properly implemented + /*while (getSound()->isBuffered("LIB046")) + getSound()->updateQueue();*/ + + getFlags()->shouldRedraw = false; + + Engine::quitGame(); + + return false; + } else { + showFrame(kOverlayButtons, kButtonQuit, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuCase4: + if (clicked) + _index = 0; + // fall down to kMenuContinue + + ////////////////////////////////////////////////////////////////////////// + case kMenuContinue: { + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + // Determine the proper CD archive + ArchiveIndex cd = kArchiveCd1; + if (getProgress().chapter > kChapter1) + cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2; + + // Show tooltips & buttons to start a game, continue a game or load the proper cd + if (ResourceManager::isArchivePresent(cd)) { + if (_isGameStarted) { + showFrame(kOverlayEggButtons, kButtonContinue, true); + + if (_lastIndex == _index) { + showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true); + } else { + showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true); + } + + } else { + showFrame(kOverlayEggButtons, kButtonShield, true); + showFrame(kOverlayTooltip, kTooltipPlayNewGame, true); + } + } else { + showFrame(kOverlayEggButtons, -1, true); + showFrame(kOverlayTooltip, cd - 1, true); + } + + if (!clicked) + break; + + // Try loading the archive file + if (!_engine->getResourceManager()->loadArchive(cd)) + break; + + // Load the train data file and setup game + getScenes()->loadSceneDataFile(cd); + showFrame(kOverlayTooltip, -1, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + + // Setup new game + getSavePoints()->reset(); + setLogicEventHandlers(); + + if (_index) { + getSound()->processEntry(SoundManager::kSoundType11); + } else { + if (!getFlags()->mouseRightClick) { + getScenes()->loadScene((SceneIndex)(5 * _gameId + 3)); + + if (!getFlags()->mouseRightClick) { + getScenes()->loadScene((SceneIndex)(5 * _gameId + 4)); + + if (!getFlags()->mouseRightClick) { + getScenes()->loadScene((SceneIndex)(5 * _gameId + 5)); + + if (!getFlags()->mouseRightClick) { + getSound()->processEntry(SoundManager::kSoundType11); + + // Show intro + Animation animation; + if (animation.load(getArchive("1601.nis"))) + animation.play(); + + getEvent(kEventIntro) = 1; + } + } + } + } + + if (!getEvent(kEventIntro)) { + getEvent(kEventIntro) = 1; + + getSound()->processEntry(SoundManager::kSoundType11); + } + } + + // Setup game + getFlags()->isGameRunning = true; + startGame(); + + if (!_isShowingMenu) + getInventory()->show(); + + return false; + } + + ////////////////////////////////////////////////////////////////////////// + case kMenuSwitchSaveGame: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + if (clicked) { + showFrame(kOverlayAcorn, 1, true); + showFrame(kOverlayTooltip, -1, true); + getSound()->playSound(kEntityPlayer, "LIB047"); + + // Setup new menu screen + switchGame(); + setup(); + + // Set fight state to 0 + getFight()->resetState(); + + return true; + } + + // TODO Check for flag + + showFrame(kOverlayAcorn, 0, true); + + if (_isGameStarted) { + showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); + break; + } + + if (_gameId == kGameGold) { + showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true); + break; + } + + if (!SaveLoad::isSavegameValid(getNextGameId())) { + showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true); + break; + } + + // Stupid tooltips ids are not in order, so we can't just increment them... + switch(_gameId) { + default: + break; + + case kGameBlue: + showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true); + break; + + case kGameRed: + showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true); + break; + + case kGameGreen: + showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true); + break; + + case kGamePurple: + showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true); + break; + + case kGameTeal: + showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true); + break; + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuRewindGame: + if (!_index || _currentTime < _time) { + hideOverlays(); + break; + } + + if (clicked) { + if (hasTimeDelta()) + _handleTimeDelta = false; + + showFrame(kOverlayEggButtons, kButtonRewindPushed, true); + showFrame(kOverlayTooltip, -1, true); + + getSound()->playSound(kEntityPlayer, "LIB046"); + + rewindTime(); + + _handleTimeDelta = false; + } else { + showFrame(kOverlayEggButtons, kButtonRewind, true); + showFrame(kOverlayTooltip, kTooltipRewind, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuForwardGame: + if (_lastIndex <= _index || _currentTime > _time) { + hideOverlays(); + break; + } + + if (clicked) { + if (hasTimeDelta()) + _handleTimeDelta = false; + + showFrame(kOverlayEggButtons, kButtonForwardPushed, true); + showFrame(kOverlayTooltip, -1, true); + + getSound()->playSound(kEntityPlayer, "LIB046"); + + forwardTime(); + + _handleTimeDelta = false; + } else { + showFrame(kOverlayEggButtons, kButtonForward, true); + showFrame(kOverlayTooltip, kTooltipFastForward, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuParis: + moveToCity(kParis, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuStrasBourg: + moveToCity(kStrasbourg, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuMunich: + moveToCity(kMunich, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuVienna: + moveToCity(kVienna, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuBudapest: + moveToCity(kBudapest, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuBelgrade: + moveToCity(kBelgrade, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuConstantinople: + moveToCity(kConstantinople, clicked); + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuDecreaseVolume: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + // Cannot decrease volume further + if (getVolume() == 0) { + showFrame(kOverlayButtons, kButtonVolume, true); + showFrame(kOverlayTooltip, -1, true); + break; + } + + showFrame(kOverlayTooltip, kTooltipVolumeDown, true); + + // Show highlight on button & adjust volume if needed + if (clicked) { + showFrame(kOverlayButtons, kButtonVolumeDownPushed, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + setVolume(getVolume() - 1); + + getSaveLoad()->saveVolumeBrightness(); + + uint32 nextFrameCount = getFrameCount() + 15; + while (nextFrameCount > getFrameCount()) { + _engine->pollEvents(); + + getSound()->updateQueue(); + } + } else { + showFrame(kOverlayButtons, kButtonVolumeDown, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuIncreaseVolume: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + // Cannot increase volume further + if (getVolume() >= 7) { + showFrame(kOverlayButtons, kButtonVolume, true); + showFrame(kOverlayTooltip, -1, true); + break; + } + + showFrame(kOverlayTooltip, kTooltipVolumeUp, true); + + // Show highlight on button & adjust volume if needed + if (clicked) { + showFrame(kOverlayButtons, kButtonVolumeUpPushed, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + setVolume(getVolume() + 1); + + getSaveLoad()->saveVolumeBrightness(); + + uint32 nextFrameCount = getFrameCount() + 15; + while (nextFrameCount > getFrameCount()) { + _engine->pollEvents(); + + getSound()->updateQueue(); + } + } else { + showFrame(kOverlayButtons, kButtonVolumeUp, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuDecreaseBrightness: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + // Cannot increase brightness further + if (getBrightness() == 0) { + showFrame(kOverlayButtons, kButtonBrightness, true); + showFrame(kOverlayTooltip, -1, true); + break; + } + + showFrame(kOverlayTooltip, kTooltipBrightnessDown, true); + + // Show highlight on button & adjust brightness if needed + if (clicked) { + showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + setBrightness(getBrightness() - 1); + + getSaveLoad()->saveVolumeBrightness(); + + // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) + _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); + showFrame(kOverlayTooltip, kTooltipBrightnessDown, false); + showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false); + } else { + showFrame(kOverlayButtons, kButtonBrightnessDown, true); + } + break; + + ////////////////////////////////////////////////////////////////////////// + case kMenuIncreaseBrightness: + if (hasTimeDelta()) { + hideOverlays(); + break; + } + + // Cannot increase brightness further + if (getBrightness() >= 6) { + showFrame(kOverlayButtons, kButtonBrightness, true); + showFrame(kOverlayTooltip, -1, true); + break; + } + + showFrame(kOverlayTooltip, kTooltipBrightnessUp, true); + + // Show highlight on button & adjust brightness if needed + if (clicked) { + showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + setBrightness(getBrightness() + 1); + + getSaveLoad()->saveVolumeBrightness(); + + // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager) + _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true); + showFrame(kOverlayTooltip, kTooltipBrightnessUp, false); + showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false); + } else { + showFrame(kOverlayButtons, kButtonBrightnessUp, true); + } + break; + } + + return true; +} + +void Menu::setLogicEventHandlers() { + SET_EVENT_HANDLERS(Logic, getLogic()); + clear(); + _isShowingMenu = false; +} + +////////////////////////////////////////////////////////////////////////// +// Game-related +////////////////////////////////////////////////////////////////////////// +void Menu::init(bool doSavegame, SavegameType type, uint32 value) { + + bool useSameIndex = true; + + if (getGlobalTimer()) { + value = 0; + + // Check if the CD file is present + ArchiveIndex index = kArchiveCd1; + switch (getProgress().chapter) { + default: + case kChapter1: + break; + + case kChapter2: + case kChapter3: + index = kArchiveCd2; + break; + + case kChapter4: + case kChapter5: + index = kArchiveCd3; + break; + } + + if (ResourceManager::isArchivePresent(index)) { + setGlobalTimer(0); + useSameIndex = false; + + // TODO remove existing savegame and reset index & savegame name + warning("Menu::initGame: not implemented!"); + } + + doSavegame = false; + } else { + // TODO rename saves? + } + + // Create a new savegame if needed + if (!SaveLoad::isSavegamePresent(_gameId)) + getSaveLoad()->create(_gameId); + + if (doSavegame) + getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone); + + if (!getGlobalTimer()) { + // TODO: remove existing savegame temp file + } + + // Init savegame & menu values + _lastIndex = getSaveLoad()->init(_gameId, true); + _lowerTime = getSaveLoad()->getTime(_lastIndex); + + if (useSameIndex) + _index = _lastIndex; + + //if (!getGlobalTimer()) + // _index3 = 0; + + if (!getProgress().chapter) + getProgress().chapter = kChapter1; + + getState()->time = (TimeValue)getSaveLoad()->getTime(_index); + getProgress().chapter = getSaveLoad()->getChapter(_index); + + if (_lowerTime >= kTimeStartGame) { + _currentTime = (uint32)getState()->time; + _time = (uint32)getState()->time; + _clock->draw(_time); + _trainLine->draw(_time); + + initTime(type, value); + } +} + +// Start a game (or load an existing savegame) +void Menu::startGame() { + // Clear savegame headers + getSaveLoad()->clear(); + + // Hide menu elements + _clock->clear(); + _trainLine->clear(); + + if (_lastIndex == _index) { + setGlobalTimer(0); + if (_index) { + getSaveLoad()->loadGame(_gameId); + } else { + getLogic()->resetState(); + getEntities()->setup(true, kEntityPlayer); + } + } else { + getSaveLoad()->loadGame(_gameId, _index); + } +} + +// Switch to the next savegame +void Menu::switchGame() { + + // Switch back to blue game is the current game is not started + _gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue; + + // Initialize savegame if needed + if (!SaveLoad::isSavegamePresent(_gameId)) + getSaveLoad()->create(_gameId); + + getState()->time = kTimeNone; + + // Clear menu elements + _clock->clear(); + _trainLine->clear(); + + // Clear loaded savegame data + getSaveLoad()->clear(true); + + init(false, kSavegameTypeIndex, 0); +} + +////////////////////////////////////////////////////////////////////////// +// Overlays & elements +////////////////////////////////////////////////////////////////////////// +void Menu::checkHotspots() { + if (!_isShowingMenu) + return; + + if (!getFlags()->shouldRedraw) + return; + + if (_isShowingCredits) + return; + + SceneHotspot *hotspot = NULL; + getScenes()->get(getState()->scene)->checkHotSpot(getCoords(), &hotspot); + + if (hotspot) + handleEvent((StartMenuAction)hotspot->action, _mouseFlags); + else + hideOverlays(); +} + +void Menu::hideOverlays() { + _lastHotspot = NULL; + + // Hide all menu overlays + for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) + showFrame(it->_key, -1, false); + + getScenes()->drawFrames(true); +} + +void Menu::showFrame(StartMenuOverlay overlayType, int index, bool redraw) { + if (index == -1) { + getScenes()->removeFromQueue(_frames[overlayType]); + } else { + // Check that the overlay is valid + if (!_frames[overlayType]) + return; + + // Remove the frame and add a new one with the proper index + getScenes()->removeFromQueue(_frames[overlayType]); + _frames[overlayType]->setFrame((uint16)index); + getScenes()->addToQueue(_frames[overlayType]); + } + + if (redraw) + getScenes()->drawFrames(true); +} + +// Remove all frames from the queue +void Menu::clear() { + for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++) + getScenes()->removeAndRedraw(&it->_value, false); + + clearBg(GraphicsManager::kBackgroundOverlay); +} + +// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame +Common::String Menu::getAcornSequenceName(GameId id) const { + Common::String name = ""; + switch (id) { + default: + case kGameBlue: + name = "aconblu3.seq"; + break; + + case kGameRed: + name = "aconred.seq"; + break; + + case kGameGreen: + name = "acongren.seq"; + break; + + case kGamePurple: + name = "aconpurp.seq"; + break; + + case kGameTeal: + name = "aconteal.seq"; + break; + + case kGameGold: + name = "acongold.seq"; + break; + } + + return name; +} + +////////////////////////////////////////////////////////////////////////// +// Time +////////////////////////////////////////////////////////////////////////// +void Menu::initTime(SavegameType type, uint32 value) { + if (!value) + return; + + // The savegame entry index + uint32 entryIndex = 0; + + switch (type) { + default: + break; + + case kSavegameTypeIndex: + entryIndex = (_index <= value) ? 1 : _index - value; + break; + + case kSavegameTypeTime: + if (value < kTimeStartGame) + break; + + entryIndex = _index; + if (!entryIndex) + break; + + // Iterate through existing entries + do { + if (getSaveLoad()->getTime(entryIndex) <= value) + break; + + entryIndex--; + } while (entryIndex); + break; + + case kSavegameTypeEvent: + entryIndex = _index; + if (!entryIndex) + break; + + do { + if (getSaveLoad()->getValue(entryIndex) == value) + break; + + entryIndex--; + } while (entryIndex); + break; + + case kSavegameTypeEvent2: + // TODO rewrite in a more legible way + if (_index > 1) { + uint32 index = _index; + do { + if (getSaveLoad()->getValue(index) == value) + break; + + index--; + } while (index > 1); + + entryIndex = index - 1; + } else { + entryIndex = _index - 1; + } + break; + } + + if (entryIndex) { + _currentIndex = entryIndex; + updateTime(getSaveLoad()->getTime(entryIndex)); + } +} + +void Menu::updateTime(uint32 time) { + if (_currentTime == _time) + _delta = 0; + + _currentTime = time; + + if (_time != time) { + if (getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + + getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters); + adjustIndex(_currentTime, _time, false); + } +} + +void Menu::adjustIndex(uint32 time1, uint32 time2, bool searchEntry) { + uint32 index = 0; + int32 timeDelta = -1; + + if (time1 != time2) { + + index = _index; + + if (time2 >= time1) { + if (searchEntry) { + uint32 currentIndex = _index; + + if ((int32)_index >= 0) { + do { + // Calculate new delta + int32 newDelta = time1 - (uint32)getSaveLoad()->getTime(currentIndex); + + if (newDelta >= 0 && timeDelta >= newDelta) { + timeDelta = newDelta; + index = currentIndex; + } + + --currentIndex; + } while ((int32)currentIndex >= 0); + } + } else { + index = _index - 1; + } + } else { + if (searchEntry) { + uint32 currentIndex = _index; + + if (_lastIndex >= _index) { + do { + // Calculate new delta + int32 newDelta = (uint32)getSaveLoad()->getTime(currentIndex) - time1; + + if (newDelta >= 0 && timeDelta > newDelta) { + timeDelta = newDelta; + index = currentIndex; + } + + ++currentIndex; + } while (currentIndex <= _lastIndex); + } + } else { + index = _index + 1; + } + } + + _index = index; + checkHotspots(); + } + + if (_index == _currentIndex) { + if (getProgress().chapter != getSaveLoad()->getChapter(index)) + getProgress().chapter = getSaveLoad()->getChapter(_index); + } +} + +void Menu::goToTime(uint32 time) { + + uint32 entryIndex = 0; + uint32 deltaTime = (uint32)ABS((int32)(getSaveLoad()->getTime(0) - time)); + uint32 index = 0; + + do { + uint32 deltaTime2 = (uint32)ABS((int32)(getSaveLoad()->getTime(index) - time)); + if (deltaTime2 < deltaTime) { + deltaTime = deltaTime2; + entryIndex = index; + } + + ++index; + } while (_lastIndex >= index); + + _currentIndex = entryIndex; + updateTime(getSaveLoad()->getTime(entryIndex)); +} + +void Menu::setTime() { + _currentIndex = _index; + _currentTime = getSaveLoad()->getTime(_currentIndex); + + if (_time == _currentTime) + adjustTime(); +} + +void Menu::forwardTime() { + if (_lastIndex <= _index) + return; + + _currentIndex = _lastIndex; + updateTime(getSaveLoad()->getTime(_currentIndex)); +} + +void Menu::rewindTime() { + if (!_index) + return; + + _currentIndex = 0; + updateTime(getSaveLoad()->getTime(_currentIndex)); +} + +void Menu::adjustTime() { + uint32 originalTime = _time; + + // Adjust time delta + Common::Rational timeDelta(_delta >= 90 ? 9 : (9 * _delta + 89), _delta >= 90 ? 1 : 90); + + if (_currentTime < _time) { + timeDelta *= 900; + _time -= (uint)timeDelta.toInt(); + + if (_currentTime > _time) + _time = _currentTime; + } else { + timeDelta *= 900; + _time += (uint)timeDelta.toInt(); + + if (_currentTime < _time) + _time = _currentTime; + } + + if (_currentTime == _time && getSound()->isBuffered(kEntityChapters)) + getSound()->removeFromQueue(kEntityChapters); + + _clock->draw(_time); + _trainLine->draw(_time); + getScenes()->drawFrames(true); + + adjustIndex(_time, originalTime, true); + + ++_delta; +} + +void Menu::moveToCity(CityButton city, bool clicked) { + uint32 time = (uint32)_cityButtonsInfo[city].time; + + // TODO Check if we have access (there seems to be more checks on some internal times) - probably : current_time (menu only) / game time / some other? + if (_lowerTime < time || _time == time || _currentTime == time) { + hideOverlays(); + return; + } + + // Show city overlay + showFrame((StartMenuOverlay)((_cityButtonsInfo[city].index >> 6) + 3), _cityButtonsInfo[city].index & 63, true); + + if (clicked) { + showFrame(kOverlayTooltip, -1, true); + getSound()->playSound(kEntityPlayer, "LIB046"); + goToTime(time); + + _handleTimeDelta = true; + + return; + } + + // Special case of first and last cities + if (city == kParis || city == kConstantinople) { + showFrame(kOverlayTooltip, (city == kParis) ? kTooltipRewindParis : kTooltipForwardConstantinople, true); + return; + } + + showFrame(kOverlayTooltip, (_time <= time) ? _cityButtonsInfo[city].forward : _cityButtonsInfo[city].rewind, true); +} + +////////////////////////////////////////////////////////////////////////// +// Sound / Brightness +////////////////////////////////////////////////////////////////////////// + +// Get current volume (converted internal ScummVM value) +uint32 Menu::getVolume() const { + return getState()->volume; +} + +// Set the volume (converts to ScummVM values) +void Menu::setVolume(uint32 volume) const { + getState()->volume = volume; + + // Clamp volume + uint32 value = volume * Audio::Mixer::kMaxMixerVolume / 7; + + if (value > Audio::Mixer::kMaxMixerVolume) + value = Audio::Mixer::kMaxMixerVolume; + + _engine->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (int32)value); +} + +uint32 Menu::getBrightness() const { + return getState()->brightness; +} + +void Menu::setBrightness(uint32 brightness) const { + getState()->brightness = brightness; + + // TODO reload cursor & font with adjusted brightness +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/menu/menu.h b/engines/lastexpress/menu/menu.h new file mode 100644 index 0000000000..4b84c065cb --- /dev/null +++ b/engines/lastexpress/menu/menu.h @@ -0,0 +1,207 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_MENU_H +#define LASTEXPRESS_MENU_H + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/eventhandler.h" + +#include "lastexpress/shared.h" + +#include "common/hashmap.h" + +namespace LastExpress { + +class LastExpressEngine; +class Scene; +class SceneHotspot; + +class Clock; +class TrainLine; + +class Menu : public EventHandler { +public: + Menu(LastExpressEngine *engine); + ~Menu(); + + void show(bool doSavegame, SavegameType type, uint32 value); + + // Event handling + void eventMouse(const Common::Event &ev); + void eventTick(const Common::Event &ev); + + bool isShown() const { return _isShowingMenu; } + + GameId getGameId() const { return _gameId; } + +private: + // Start menu events + enum StartMenuAction { + kMenuContinue = 1, + kMenuCredits = 2, + kMenuQuitGame = 3, + kMenuCase4 = 4, + kMenuSwitchSaveGame = 6, + kMenuRewindGame = 7, + kMenuForwardGame = 8, + kMenuParis = 10, + kMenuStrasBourg = 11, + kMenuMunich = 12, + kMenuVienna = 13, + kMenuBudapest = 14, + kMenuBelgrade = 15, + kMenuConstantinople = 16, + kMenuDecreaseVolume = 17, + kMenuIncreaseVolume = 18, + kMenuDecreaseBrightness = 19, + kMenuIncreaseBrightness = 20 + }; + + // City buttons + enum CityButton { + kParis = 0, + kStrasbourg = 1, + kMunich = 2, + kVienna = 3, + kBudapest = 4, + kBelgrade = 5, + kConstantinople = 6 + }; + + // Start menu overlay elements + enum StartMenuOverlay { + kOverlayTooltip, // 0 + kOverlayEggButtons, + kOverlayButtons, + kOverlayAcorn, + kOverlayCity1, + kOverlayCity2, // 5 + kOverlayCity3, + kOverlayCredits + }; + + LastExpressEngine *_engine; + + // Sequences + Sequence *_seqTooltips; + Sequence *_seqEggButtons; + Sequence *_seqButtons; + Sequence *_seqAcorn; + Sequence *_seqCity1; + Sequence *_seqCity2; + Sequence *_seqCity3; + Sequence *_seqCredits; + + GameId _gameId; + + // Indicator to know if we need to show the start animation when showMenu is called + bool _hasShownStartScreen; + bool _hasShownIntro; + + bool _isShowingCredits; + bool _isGameStarted; + bool _isShowingMenu; + + + uint16 _creditsSequenceIndex; + + ////////////////////////////////////////////////////////////////////////// + // Event handling + uint32 _checkHotspotsTicks; + Common::EventType _mouseFlags; + SceneHotspot *_lastHotspot; + + void init(bool doSavegame, SavegameType type, uint32 value); + void setup(); + bool handleEvent(StartMenuAction action, Common::EventType type); + void checkHotspots(); + void setLogicEventHandlers(); + + ////////////////////////////////////////////////////////////////////////// + // Game-related + void startGame(); + void switchGame(); + + ////////////////////////////////////////////////////////////////////////// + // Overlays & elements + Clock *_clock; + TrainLine *_trainLine; + + struct MenuOverlays_EqualTo { + bool operator()(const StartMenuOverlay &x, const StartMenuOverlay &y) const { return x == y; } + }; + + struct MenuOverlays_Hash { + uint operator()(const StartMenuOverlay &x) const { return x; } + }; + + typedef Common::HashMap MenuFrames; + + MenuFrames _frames; + + void hideOverlays(); + void showFrame(StartMenuOverlay overlay, int index, bool redraw); + + void clear(); + + // TODO: remove? + void moveToCity(CityButton city, bool clicked); + + ////////////////////////////////////////////////////////////////////////// + // Misc + Common::String getAcornSequenceName(GameId id) const; + + ////////////////////////////////////////////////////////////////////////// + // Time + uint32 _currentTime; // current game time + uint32 _lowerTime; // lower time value + uint32 _time; + + uint32 _currentIndex; // current savegame entry + uint32 _index; + uint32 _lastIndex; + uint32 _delta; + bool _handleTimeDelta; + + void initTime(SavegameType type, uint32 val); + void updateTime(uint32 time); + void adjustTime(); + void adjustIndex(uint32 time1, uint32 time2, bool searchEntry); + void goToTime(uint32 time); + void setTime(); + void forwardTime(); + void rewindTime(); + bool hasTimeDelta() { return (_currentTime - _time) >= 1; } + + ////////////////////////////////////////////////////////////////////////// + // Sound/Brightness related + uint32 getVolume() const; + void setVolume(uint32 volume) const; + uint32 getBrightness() const; + void setBrightness(uint32 brightness) const; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_MENU_H diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index e81151910b..e38772ad30 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -57,13 +57,13 @@ MODULE_OBJS := \ game/entities.o \ game/inventory.o \ game/logic.o \ - game/menu.o \ game/object.o \ game/savegame.o \ game/savepoint.o \ game/scenes.o \ game/sound.o \ game/state.o \ + menu/menu.o \ debug.o \ detection.o \ graphics.o \ -- cgit v1.2.3 From 7a96e0bfb67e9b5b8c0aa9bdae8415fb98214c3f Mon Sep 17 00:00:00 2001 From: Littleboy Date: Thu, 23 Jun 2011 00:05:01 -0400 Subject: LASTEXPRESS: Extract Clock and TrainLine classes to separate files --- engines/lastexpress/menu/clock.cpp | 106 ++++++++++++++++ engines/lastexpress/menu/clock.h | 53 ++++++++ engines/lastexpress/menu/menu.cpp | 221 +-------------------------------- engines/lastexpress/menu/trainline.cpp | 142 +++++++++++++++++++++ engines/lastexpress/menu/trainline.h | 51 ++++++++ engines/lastexpress/module.mk | 2 + 6 files changed, 357 insertions(+), 218 deletions(-) create mode 100644 engines/lastexpress/menu/clock.cpp create mode 100644 engines/lastexpress/menu/clock.h create mode 100644 engines/lastexpress/menu/trainline.cpp create mode 100644 engines/lastexpress/menu/trainline.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/menu/clock.cpp b/engines/lastexpress/menu/clock.cpp new file mode 100644 index 0000000000..b0e6a260d4 --- /dev/null +++ b/engines/lastexpress/menu/clock.cpp @@ -0,0 +1,106 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/menu/clock.h" + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/scenes.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) { + _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true); + _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true); + _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true); + _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true); +} + +Clock::~Clock() { + SAFE_DELETE(_frameMinutes); + SAFE_DELETE(_frameHour); + SAFE_DELETE(_frameSun); + SAFE_DELETE(_frameDate); + + // Zero passed pointers + _engine = NULL; +} + +void Clock::clear() { + getScenes()->removeFromQueue(_frameMinutes); + getScenes()->removeFromQueue(_frameHour); + getScenes()->removeFromQueue(_frameSun); + getScenes()->removeFromQueue(_frameDate); +} + +void Clock::draw(uint32 time) { + assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); + + // Check that sequences have been loaded + if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate) + error("Clock::process: clock sequences have not been loaded correctly!"); + + // Clear existing frames + clear(); + + // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914 + // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914 + // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins + + // 15 = 1 second + // 15 * 60 = 900 = 1 minute + // 900 * 60 = 54000 = 1 hour + // 54000 * 24 = 1296000 = 1 day + + // Calculate each sequence index from the current time + + uint8 hour = 0; + uint8 minute = 0; + State::getHourMinutes(time, &hour, &minute); + uint32 index_date = 18 * time / 1296000; + if (hour == 23) + index_date += 18 * minute / 60; + + // Set sequences frames + _frameMinutes->setFrame(minute); + _frameHour->setFrame((5 * hour + minute / 12) % 60); + _frameSun->setFrame((5 * hour + minute / 12) % 120); + _frameDate->setFrame((uint16)index_date); + + // Adjust z-order and queue + _frameMinutes->getInfo()->location = 1; + _frameHour->getInfo()->location = 1; + _frameSun->getInfo()->location = 1; + _frameDate->getInfo()->location = 1; + + getScenes()->addToQueue(_frameMinutes); + getScenes()->addToQueue(_frameHour); + getScenes()->addToQueue(_frameSun); + getScenes()->addToQueue(_frameDate); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/menu/clock.h b/engines/lastexpress/menu/clock.h new file mode 100644 index 0000000000..339a18604f --- /dev/null +++ b/engines/lastexpress/menu/clock.h @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_CLOCK_H +#define LASTEXPRESS_CLOCK_H + +#include "common/scummsys.h" + +namespace LastExpress { + +class LastExpressEngine; +class SequenceFrame; + +class Clock { +public: + explicit Clock(LastExpressEngine *engine); + ~Clock(); + + void draw(uint32 time); + void clear(); + +private: + LastExpressEngine *_engine; + + // Frames + SequenceFrame *_frameMinutes; + SequenceFrame *_frameHour; + SequenceFrame *_frameSun; + SequenceFrame *_frameDate; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_CLOCK_H diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp index b7e6a1430a..e55a6d5960 100644 --- a/engines/lastexpress/menu/menu.cpp +++ b/engines/lastexpress/menu/menu.cpp @@ -38,6 +38,9 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/menu/clock.h" +#include "lastexpress/menu/trainline.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -119,45 +122,6 @@ enum StartMenuTooltips { ////////////////////////////////////////////////////////////////////////// // DATA ////////////////////////////////////////////////////////////////////////// - -// Information about the cities on the train line -static const struct { - uint8 frame; - TimeValue time; -} _trainCities[31] = { - {0, kTimeCityParis}, - {9, kTimeCityEpernay}, - {11, kTimeCityChalons}, - {16, kTimeCityBarLeDuc}, - {21, kTimeCityNancy}, - {25, kTimeCityLuneville}, - {35, kTimeCityAvricourt}, - {37, kTimeCityDeutschAvricourt}, - {40, kTimeCityStrasbourg}, - {53, kTimeCityBadenOos}, - {56, kTimeCityKarlsruhe}, - {60, kTimeCityStuttgart}, - {63, kTimeCityGeislingen}, - {66, kTimeCityUlm}, - {68, kTimeCityAugsburg}, - {73, kTimeCityMunich}, - {84, kTimeCitySalzbourg}, - {89, kTimeCityAttnangPuchheim}, - {97, kTimeCityWels}, - {100, kTimeCityLinz}, - {104, kTimeCityAmstetten}, - {111, kTimeCityVienna}, - {120, kTimeCityPoszony}, - {124, kTimeCityGalanta}, - {132, kTimeCityBudapest}, - {148, kTimeCityBelgrade}, - /* Line 1 ends at 150 - line 2 begins at 0 */ - {157, kTimeCityNish}, - {165, kTimeCityTzaribrod}, - {174, kTimeCitySofia}, - {198, kTimeCityAdrianople}, - {210, kTimeCityConstantinople}}; - static const struct { TimeValue time; uint index; @@ -173,185 +137,6 @@ static const struct { {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople} }; -////////////////////////////////////////////////////////////////////////// -// Clock -////////////////////////////////////////////////////////////////////////// -class Clock { -public: - explicit Clock(LastExpressEngine *engine); - ~Clock(); - - void draw(uint32 time); - void clear(); - -private: - LastExpressEngine *_engine; - - // Frames - SequenceFrame *_frameMinutes; - SequenceFrame *_frameHour; - SequenceFrame *_frameSun; - SequenceFrame *_frameDate; -}; - -Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) { - _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true); - _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true); - _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true); - _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true); -} - -Clock::~Clock() { - SAFE_DELETE(_frameMinutes); - SAFE_DELETE(_frameHour); - SAFE_DELETE(_frameSun); - SAFE_DELETE(_frameDate); - - // Zero passed pointers - _engine = NULL; -} - -void Clock::clear() { - getScenes()->removeFromQueue(_frameMinutes); - getScenes()->removeFromQueue(_frameHour); - getScenes()->removeFromQueue(_frameSun); - getScenes()->removeFromQueue(_frameDate); -} - -void Clock::draw(uint32 time) { - assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); - - // Check that sequences have been loaded - if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate) - error("Clock::process: clock sequences have not been loaded correctly!"); - - // Clear existing frames - clear(); - - // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914 - // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914 - // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins - - // 15 = 1 second - // 15 * 60 = 900 = 1 minute - // 900 * 60 = 54000 = 1 hour - // 54000 * 24 = 1296000 = 1 day - - // Calculate each sequence index from the current time - - uint8 hour = 0; - uint8 minute = 0; - State::getHourMinutes(time, &hour, &minute); - uint32 index_date = 18 * time / 1296000; - if (hour == 23) - index_date += 18 * minute / 60; - - // Set sequences frames - _frameMinutes->setFrame(minute); - _frameHour->setFrame((5 * hour + minute / 12) % 60); - _frameSun->setFrame((5 * hour + minute / 12) % 120); - _frameDate->setFrame((uint16)index_date); - - // Adjust z-order and queue - _frameMinutes->getInfo()->location = 1; - _frameHour->getInfo()->location = 1; - _frameSun->getInfo()->location = 1; - _frameDate->getInfo()->location = 1; - - getScenes()->addToQueue(_frameMinutes); - getScenes()->addToQueue(_frameHour); - getScenes()->addToQueue(_frameSun); - getScenes()->addToQueue(_frameDate); -} - -////////////////////////////////////////////////////////////////////////// -// TrainLine -////////////////////////////////////////////////////////////////////////// -class TrainLine { -public: - explicit TrainLine(LastExpressEngine *engine); - ~TrainLine(); - - void draw(uint32 time); - void clear(); - -private: - LastExpressEngine *_engine; - - // Frames - SequenceFrame *_frameLine1; - SequenceFrame *_frameLine2; -}; - -TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) { - _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true); - _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true); -} - -TrainLine::~TrainLine() { - SAFE_DELETE(_frameLine1); - SAFE_DELETE(_frameLine2); - - // Zero passed pointers - _engine = NULL; -} - -void TrainLine::clear() { - getScenes()->removeFromQueue(_frameLine1); - getScenes()->removeFromQueue(_frameLine2); -} - -// Draw the train line at the time -// line1: 150 frames (=> Belgrade) -// line2: 61 frames (=> Constantinople) -void TrainLine::draw(uint32 time) { - assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); - - // Check that sequences have been loaded - if (!_frameLine1 || !_frameLine2) - error("TrainLine::process: Line sequences have not been loaded correctly!"); - - // Clear existing frames - clear(); - - // Get the index of the last city the train has visited - uint index = 0; - for (uint i = 0; i < ARRAYSIZE(_trainCities); i++) - if ((uint32)_trainCities[i].time <= time) - index = i; - - uint16 frame; - if (time > (uint32)_trainCities[index].time) { - // Interpolate linearly to use a frame between the cities - uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame; - uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time); - uint traveledTime = (time - (uint)_trainCities[index].time); - frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities); - } else { - // Exactly on the city - frame = _trainCities[index].frame; - } - - // Set frame, z-order and queue - if (frame < 150) { - _frameLine1->setFrame(frame); - - _frameLine1->getInfo()->location = 1; - getScenes()->addToQueue(_frameLine1); - } else { - // We passed Belgrade - _frameLine1->setFrame(149); - _frameLine2->setFrame(frame - 150); - - _frameLine1->getInfo()->location = 1; - _frameLine2->getInfo()->location = 1; - - getScenes()->addToQueue(_frameLine1); - getScenes()->addToQueue(_frameLine2); - } -} - - ////////////////////////////////////////////////////////////////////////// // Menu ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/menu/trainline.cpp b/engines/lastexpress/menu/trainline.cpp new file mode 100644 index 0000000000..df08abf37b --- /dev/null +++ b/engines/lastexpress/menu/trainline.cpp @@ -0,0 +1,142 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/menu/trainline.h" + +#include "lastexpress/data/sequence.h" + +#include "lastexpress/game/scenes.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +// Information about the cities on the train line +static const struct { + uint8 frame; + TimeValue time; +} _trainCities[31] = { + {0, kTimeCityParis}, + {9, kTimeCityEpernay}, + {11, kTimeCityChalons}, + {16, kTimeCityBarLeDuc}, + {21, kTimeCityNancy}, + {25, kTimeCityLuneville}, + {35, kTimeCityAvricourt}, + {37, kTimeCityDeutschAvricourt}, + {40, kTimeCityStrasbourg}, + {53, kTimeCityBadenOos}, + {56, kTimeCityKarlsruhe}, + {60, kTimeCityStuttgart}, + {63, kTimeCityGeislingen}, + {66, kTimeCityUlm}, + {68, kTimeCityAugsburg}, + {73, kTimeCityMunich}, + {84, kTimeCitySalzbourg}, + {89, kTimeCityAttnangPuchheim}, + {97, kTimeCityWels}, + {100, kTimeCityLinz}, + {104, kTimeCityAmstetten}, + {111, kTimeCityVienna}, + {120, kTimeCityPoszony}, + {124, kTimeCityGalanta}, + {132, kTimeCityBudapest}, + {148, kTimeCityBelgrade}, + /* Line 1 ends at 150 - line 2 begins at 0 */ + {157, kTimeCityNish}, + {165, kTimeCityTzaribrod}, + {174, kTimeCitySofia}, + {198, kTimeCityAdrianople}, + {210, kTimeCityConstantinople} +}; + +TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) { + _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true); + _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true); +} + +TrainLine::~TrainLine() { + SAFE_DELETE(_frameLine1); + SAFE_DELETE(_frameLine2); + + // Zero passed pointers + _engine = NULL; +} + +void TrainLine::clear() { + getScenes()->removeFromQueue(_frameLine1); + getScenes()->removeFromQueue(_frameLine2); +} + +// Draw the train line at the time +// line1: 150 frames (=> Belgrade) +// line2: 61 frames (=> Constantinople) +void TrainLine::draw(uint32 time) { + assert(time >= kTimeCityParis && time <= kTimeCityConstantinople); + + // Check that sequences have been loaded + if (!_frameLine1 || !_frameLine2) + error("TrainLine::process: Line sequences have not been loaded correctly!"); + + // Clear existing frames + clear(); + + // Get the index of the last city the train has visited + uint index = 0; + for (uint i = 0; i < ARRAYSIZE(_trainCities); i++) + if ((uint32)_trainCities[i].time <= time) + index = i; + + uint16 frame; + if (time > (uint32)_trainCities[index].time) { + // Interpolate linearly to use a frame between the cities + uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame; + uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time); + uint traveledTime = (time - (uint)_trainCities[index].time); + frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities); + } else { + // Exactly on the city + frame = _trainCities[index].frame; + } + + // Set frame, z-order and queue + if (frame < 150) { + _frameLine1->setFrame(frame); + + _frameLine1->getInfo()->location = 1; + getScenes()->addToQueue(_frameLine1); + } else { + // We passed Belgrade + _frameLine1->setFrame(149); + _frameLine2->setFrame(frame - 150); + + _frameLine1->getInfo()->location = 1; + _frameLine2->getInfo()->location = 1; + + getScenes()->addToQueue(_frameLine1); + getScenes()->addToQueue(_frameLine2); + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/menu/trainline.h b/engines/lastexpress/menu/trainline.h new file mode 100644 index 0000000000..af6a121e9c --- /dev/null +++ b/engines/lastexpress/menu/trainline.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_TRAINLINE_H +#define LASTEXPRESS_TRAINLINE_H + +#include "common/scummsys.h" + +namespace LastExpress { + +class LastExpressEngine; +class SequenceFrame; + +class TrainLine { +public: + explicit TrainLine(LastExpressEngine *engine); + ~TrainLine(); + + void draw(uint32 time); + void clear(); + +private: + LastExpressEngine *_engine; + + // Frames + SequenceFrame *_frameLine1; + SequenceFrame *_frameLine2; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_TRAINLINE_H diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index e38772ad30..71d81da0c9 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -63,7 +63,9 @@ MODULE_OBJS := \ game/scenes.o \ game/sound.o \ game/state.o \ + menu/clock.o \ menu/menu.o \ + menu/trainline.o \ debug.o \ detection.o \ graphics.o \ -- cgit v1.2.3 From 7bdd3f3904828704d48e8b0a60fcfeab27f4287b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 24 Jun 2011 02:05:26 +0300 Subject: LASTEXPRESS: Implement playLoopingSound() In order for it to work properly, updateQueue() should be unstubbed. --- engines/lastexpress/game/sound.cpp | 111 ++++++++++++++++++++++++++++++++++++- engines/lastexpress/game/sound.h | 4 +- 2 files changed, 111 insertions(+), 4 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 1c7abbf95e..6cd5731e54 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -26,6 +26,7 @@ #include "lastexpress/game/entities.h" #include "lastexpress/game/inventory.h" #include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/state.h" @@ -117,6 +118,8 @@ SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine), _state( _drawSubtitles = 0; _currentSubtitle = NULL; + + _loopingSoundDuration = 0; } SoundManager::~SoundManager() { @@ -458,7 +461,7 @@ void SoundManager::removeEntry(SoundEntry *entry) { if (entry->entity) { if (entry->entity == kEntitySteam) - playLoopingSound(); + playLoopingSound(2); else if (entry->entity != kEntityTrain) getSavePoints()->push(kEntityPlayer, entry->entity, kActionEndSound); } @@ -1937,8 +1940,110 @@ void SoundManager::drawSubtitleOnScreen(SubtitleEntry *subtitle) { ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// -void SoundManager::playLoopingSound() { - warning("SoundManager::playLoopingSound: not implemented!"); +void SoundManager::playLoopingSound(int param) { + Common::List::iterator snd; + char tmp[80]; + + for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { + if ((*snd)->type == kSoundType1) + break; + } + + byte numLoops[8]; + static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, + kPosition_6470, kPosition_5790, + kPosition_4840, kPosition_4070, + kPosition_3050, kPosition_2740 }; + + numLoops[1] = 4; + numLoops[2] = 2; + numLoops[3] = 2; + numLoops[4] = 2; + numLoops[5] = 2; + numLoops[6] = 2; + + tmp[0] = 0; + + int partNumber = 1; + int fnameLen = 6; + + if (_state & 1 && param >= 0x45 && param <= 0x46) { + if (_state & 2) { + strcpy(tmp, "STEAM.SND"); + + _loopingSoundDuration = 32767; + } else { + if (getEntityData(kEntityPlayer)->location == kLocationOutsideTrain) { + partNumber = 6; + } else { + if (getEntities()->isInsideCompartments(kEntityPlayer)) { + int objNum = (getEntityData(kEntityPlayer)->car - 3) < 1 ? 9 : 40; // Weird numbers + + numLoops[0] = 0; + + for (int pos = 0; pos < 8; pos++) { + if (numLoops[0]) + break; + if (getEntities()->isInsideCompartment(kEntityPlayer, getEntityData(kEntityPlayer)->car, positions[pos])) { + numLoops[0] = 1; + partNumber = (getObjects()->get((ObjectIndex)objNum).location - 2) < 1 ? 6 : 1; + } + objNum++; + } + } else { + switch (getEntityData(kEntityPlayer)->car) { + case 1: + case 6: + partNumber = 4; + break; + case 2: + case 3: + case 4: + case 5: + partNumber = 1; + break; + case 7: + partNumber = 5; + break; + case 8: + partNumber = 99; + break; + case 9: + partNumber = 3; + break; + default: + partNumber = 6; + break; + } + } + } + + if (partNumber != 99) { + sprintf(tmp, "LOOP%d%c.SND", partNumber, _engine->getRandom().getRandomNumber(numLoops[partNumber] - 1) + 'A'); + } + } + + if (getFlags()->flag_3) + fnameLen = 5; + + if (!*snd || scumm_strnicmp((*snd)->name2.c_str(), tmp, fnameLen)) { + _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; + + if (partNumber != 99) { + playSoundWithSubtitles(tmp, kFlagLoopedSound, kEntitySteam); + + if (*snd) + updateEntry(*snd, 0); + + for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { + if ((*snd)->type == kSoundType1) { + updateEntry((*snd), 7); + break; + } + } + } + } + } } void SoundManager::stopAllSound() { diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index 839c868813..f49f2bc9f0 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -125,6 +125,7 @@ public: kFlagDefault = 0x10, kFlagType1_2 = 0x1000000, + kFlagLoopedSound = 0x1001001, kFlagSteam = 0x1001007, kFlagType13 = 0x3000000, kFlagMenuClock = 0x3080010, @@ -345,7 +346,8 @@ private: uint32 _lastWarning[12]; // Looping sound - void playLoopingSound(); + void playLoopingSound(int param); + int _loopingSoundDuration; // Sound entries Common::List _soundList; ///< List of all sound entries -- cgit v1.2.3 From 5d020fffad44c78414b91de7c26653b11b78b60f Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 24 Jun 2011 10:56:49 -0400 Subject: LASTEXPRESS: Refactor Sound class - Move entry-related functions to separate class - Move enumeration to shared header and rename FlagType to SoundFlag --- engines/lastexpress/entities/abbot.cpp | 2 +- engines/lastexpress/entities/anna.cpp | 12 +- engines/lastexpress/entities/august.cpp | 8 +- engines/lastexpress/entities/boutarel.cpp | 2 +- engines/lastexpress/entities/chapters.cpp | 30 ++-- engines/lastexpress/entities/coudert.cpp | 2 +- engines/lastexpress/entities/entity.cpp | 2 +- engines/lastexpress/entities/entity.h | 2 +- engines/lastexpress/entities/gendarmes.cpp | 18 +-- engines/lastexpress/entities/gendarmes.h | 2 +- engines/lastexpress/entities/kahina.cpp | 2 +- engines/lastexpress/entities/kronos.cpp | 2 +- engines/lastexpress/entities/mahmud.cpp | 4 +- engines/lastexpress/entities/max.cpp | 2 +- engines/lastexpress/entities/mertens.cpp | 8 +- engines/lastexpress/entities/milos.cpp | 4 +- engines/lastexpress/entities/pascale.cpp | 8 +- engines/lastexpress/entities/rebecca.cpp | 4 +- engines/lastexpress/entities/tables.cpp | 8 +- engines/lastexpress/entities/tatiana.cpp | 2 +- engines/lastexpress/entities/train.cpp | 30 ++-- engines/lastexpress/entities/vassili.cpp | 4 +- engines/lastexpress/entities/verges.cpp | 4 +- engines/lastexpress/entities/vesna.cpp | 4 +- engines/lastexpress/fight/fighter_anna.cpp | 2 +- engines/lastexpress/fight/fighter_ivo.cpp | 2 +- engines/lastexpress/fight/fighter_milos.cpp | 4 +- engines/lastexpress/fight/fighter_salko.cpp | 2 +- engines/lastexpress/fight/fighter_vesna.cpp | 2 +- engines/lastexpress/game/action.cpp | 18 +-- engines/lastexpress/game/entities.cpp | 6 +- engines/lastexpress/game/inventory.cpp | 2 +- engines/lastexpress/game/logic.cpp | 2 +- engines/lastexpress/game/scenes.cpp | 6 +- engines/lastexpress/game/sound.cpp | 168 +++++++------------ engines/lastexpress/game/sound.h | 239 ++-------------------------- engines/lastexpress/menu/menu.cpp | 14 +- engines/lastexpress/module.mk | 1 + engines/lastexpress/shared.h | 56 +++++++ engines/lastexpress/sound/entry.cpp | 151 ++++++++++++++++++ engines/lastexpress/sound/entry.h | 173 ++++++++++++++++++++ 41 files changed, 565 insertions(+), 449 deletions(-) create mode 100644 engines/lastexpress/sound/entry.cpp create mode 100644 engines/lastexpress/sound/entry.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp index 29bb31b248..112edec9af 100644 --- a/engines/lastexpress/entities/abbot.cpp +++ b/engines/lastexpress/entities/abbot.cpp @@ -1112,7 +1112,7 @@ IMPLEMENT_FUNCTION(35, Abbot, function35) case 2: getData()->location = kLocationOutsideCompartment; - getSound()->playSound(kEntityAbbot, "Abb3040", SoundManager::kFlagInvalid, 45); + getSound()->playSound(kEntityAbbot, "Abb3040", kFlagInvalid, 45); getEntities()->updatePositionEnter(kEntityAbbot, kCarRestaurant, 57); setCallback(3); diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp index bce99ad16d..d794cc8520 100644 --- a/engines/lastexpress/entities/anna.cpp +++ b/engines/lastexpress/entities/anna.cpp @@ -2063,7 +2063,7 @@ IMPLEMENT_FUNCTION(47, Anna, function47) break; case 4: - getSound()->playSound(kEntityAnna, getEvent(kEventAugustLunch) ? "Ann3136" : "Ann3136A", SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityAnna, getEvent(kEventAugustLunch) ? "Ann3136" : "Ann3136A", kFlagInvalid, 30); getSavePoints()->push(kEntityAnna, kEntityAugust, kAction122358304); setCallback(5); @@ -2258,7 +2258,7 @@ IMPLEMENT_FUNCTION(51, Anna, function51) break; case kActionDefault: - getSound()->playSound(kEntityAnna, "Aug3142", SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityAnna, "Aug3142", kFlagInvalid, 30); getEntities()->updatePositionEnter(kEntityAnna, kCarRestaurant, 57); getEntities()->drawSequenceRight(kEntityAnna, "112A"); if (getEntities()->isInRestaurant(kEntityPlayer)) @@ -3841,7 +3841,7 @@ IMPLEMENT_FUNCTION(78, Anna, function78) case 2: getAction()->playAnimation(kEventKronosHostageAnna); getScenes()->loadSceneFromPosition(kCarRestaurant, 61); - getSound()->playSound(kEntityAnna, "Mus024", SoundManager::kFlagDefault); + getSound()->playSound(kEntityAnna, "Mus024", kFlagDefault); setup_function79(); break; } @@ -3911,11 +3911,11 @@ IMPLEMENT_FUNCTION(80, Anna, function80) case kActionNone: UPDATE_PARAM(params->param1, getState()->timeTicks, 450); - getSound()->playSound(kEntityPlayer, "Kro5001", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "Kro5001", kFlagDefault); break; case kActionEndSound: - getSound()->playSound(kEntityPlayer, "Kro5002", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "Kro5002", kFlagDefault); getState()->time = kTime4923000; setCallback(1); @@ -3940,7 +3940,7 @@ IMPLEMENT_FUNCTION(80, Anna, function80) getAction()->playAnimation(kEventKronosBringFirebird); getScenes()->loadSceneFromItem(kItemFirebird); - getSound()->playSound(kEntityAnna, "Mus025", SoundManager::kFlagDefault); + getSound()->playSound(kEntityAnna, "Mus025", kFlagDefault); break; case 2: diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp index f7e7390b90..fbd50d64fb 100644 --- a/engines/lastexpress/entities/august.cpp +++ b/engines/lastexpress/entities/august.cpp @@ -199,7 +199,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_S(13, August, playSound16) - Entity::playSound(savepoint, false, SoundManager::kFlagDefault); + Entity::playSound(savepoint, false, kFlagDefault); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -338,7 +338,7 @@ IMPLEMENT_FUNCTION_II(19, August, function19, bool, bool) case kAction1: getData()->inventoryItem = kItemNone; getSound()->playSound(kEntityPlayer, "CAT1002"); - getSound()->playSound(kEntityAugust, "AUG3101", SoundManager::kFlagInvalid, 15); + getSound()->playSound(kEntityAugust, "AUG3101", kFlagInvalid, 15); break; case kActionDefault: @@ -2179,7 +2179,7 @@ IMPLEMENT_FUNCTION_III(42, August, function42, CarIndex, EntityPosition, bool) getData()->inventoryItem = kItemNone; getSound()->playSound(kEntityPlayer, "CAT1002"); - getSound()->playSound(kEntityAugust, getEvent(kEventAugustBringBriefcase) ? "AUG3103" : "AUG3100", SoundManager::kFlagInvalid, 15); + getSound()->playSound(kEntityAugust, getEvent(kEventAugustBringBriefcase) ? "AUG3103" : "AUG3100", kFlagInvalid, 15); break; case kActionExcuseMe: @@ -2385,7 +2385,7 @@ IMPLEMENT_FUNCTION(45, August, function45) case kAction1: getData()->inventoryItem = kItemNone; getSound()->playSound(kEntityPlayer, "CAT1002"); - getSound()->playSound(kEntityAugust, "AUG3102", SoundManager::kFlagInvalid, 15); + getSound()->playSound(kEntityAugust, "AUG3102", kFlagInvalid, 15); break; case kActionDefault: diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp index 0b2040897c..db7761784f 100644 --- a/engines/lastexpress/entities/boutarel.cpp +++ b/engines/lastexpress/entities/boutarel.cpp @@ -214,7 +214,7 @@ IMPLEMENT_FUNCTION_I(11, Boutarel, function11, bool) break; case kChapter1: - getSound()->playSound(kEntityBoutarel, "MRB1075", SoundManager::kFlagInvalid, 60); + getSound()->playSound(kEntityBoutarel, "MRB1075", kFlagInvalid, 60); break; case kChapter3: diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp index 6a41590f64..d4425ada43 100644 --- a/engines/lastexpress/entities/chapters.cpp +++ b/engines/lastexpress/entities/chapters.cpp @@ -160,7 +160,7 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) break; case kActionEndSound: - getSound()->playSound(kEntityChapters, "MUS0009", SoundManager::kFlagDefault); + getSound()->playSound(kEntityChapters, "MUS0009", kFlagDefault); break; case kActionKnock: @@ -192,10 +192,10 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) CALLBACK_ACTION(); } else { getSound()->playSound(kEntityPlayer, "LIB014"); - getSound()->playSound(kEntityPlayer, "LIB015", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityPlayer, "LIB015", kFlagDefault, 15); if (!getSound()->isBuffered(kEntityChapters)) - getSound()->playSound(kEntityChapters, "MUS009", SoundManager::kFlagDefault); + getSound()->playSound(kEntityChapters, "MUS009", kFlagDefault); getScenes()->loadSceneFromPosition(kCarLocomotive, 38); @@ -271,7 +271,7 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) getSound()->processEntry("ZFX1007B"); - getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); // FIXME add event pump ? @@ -699,7 +699,7 @@ IMPLEMENT_FUNCTION(9, Chapters, chapter1Next) ENTITY_PARAM(0, 3) = 0; } - getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); while (getSound()->isBuffered("MUS008")) @@ -915,11 +915,11 @@ IMPLEMENT_FUNCTION(15, Chapters, chapter3Handler) break; case 0: - getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundManager::FlagType)(rnd(15) + 2)); + getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundFlag)(rnd(15) + 2)); break; case 1: - getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundManager::FlagType)(rnd(15) + 2)); + getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundFlag)(rnd(15) + 2)); break; } @@ -1214,11 +1214,11 @@ IMPLEMENT_FUNCTION(19, Chapters, chapter4Handler) break; case 0: - getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundManager::FlagType)(rnd(15) + 2)); + getSound()->playSound(kEntityPlayer, "ZFX1008", (SoundFlag)(rnd(15) + 2)); break; case 1: - getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundManager::FlagType)(rnd(15) + 2)); + getSound()->playSound(kEntityPlayer, "ZFX1009", (SoundFlag)(rnd(15) + 2)); break; } @@ -1418,7 +1418,7 @@ label_callback_4: case 11: getScenes()->loadSceneFromPosition(kCarRedSleeping, 74); - getSound()->playSound(kEntityTrain, "ZFX4001", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTrain, "ZFX4001", kFlagDefault); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); break; } @@ -1471,7 +1471,7 @@ label_callback_4: ENTITY_PARAM(0, 3) = 0; } - getSound()->playSound(kEntityPlayer, "MUS008", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); while (getSound()->isBuffered("MUS008")) @@ -1538,7 +1538,7 @@ label_callback_4: if (getSound()->isBuffered(kEntityChapters)) getSound()->removeFromQueue(kEntityChapters); - getSound()->playSound(kEntityTrain, "ZFX4001", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTrain, "ZFX4001", kFlagDefault); getLogic()->gameOver(kSavegameTypeIndex, 0, kSceneNone, true); break; @@ -1674,7 +1674,7 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) params->param2 = 1; if (!getProgress().isNightTime) { - getSound()->playSound(kEntityChapters, "ARRIVE", SoundManager::kFlag8); + getSound()->playSound(kEntityChapters, "ARRIVE", kFlag8); getSound()->processEntries(); } } @@ -1683,7 +1683,7 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) params->param3 = 1; if (!getEvent(kEventLocomotiveMilosDay) && !getEvent(kEventLocomotiveMilosNight)) { - getSound()->playSound(kEntityChapters, "ARRIVE", SoundManager::kFlag8); + getSound()->playSound(kEntityChapters, "ARRIVE", kFlag8); getSound()->processEntries(); } } @@ -1797,7 +1797,7 @@ void Chapters::enterExitStation(const SavePoint &savepoint, bool isEnteringStati void Chapters::enterExitHelper(bool isEnteringStation) { EXPOSE_PARAMS(EntityData::EntityParametersSIIS); - getSound()->playSound(kEntityChapters, isEnteringStation ? "ARRIVE" : "DEPART", SoundManager::kFlag8); + getSound()->playSound(kEntityChapters, isEnteringStation ? "ARRIVE" : "DEPART", kFlag8); getSound()->processEntries(); getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, isEnteringStation ? kCursorNormal : kCursorHand); diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp index e74471ebca..0733a4c984 100644 --- a/engines/lastexpress/entities/coudert.cpp +++ b/engines/lastexpress/entities/coudert.cpp @@ -258,7 +258,7 @@ IMPLEMENT_FUNCTION_NOSETUP(7, Coudert, playSound16) break; case kActionDefault: - getSound()->playSound(kEntityCoudert, (char *)¶ms->seq1, SoundManager::kFlagDefault); + getSound()->playSound(kEntityCoudert, (char *)¶ms->seq1, kFlagDefault); break; case kActionCallback: diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp index 22750989fb..f6d24d69ca 100644 --- a/engines/lastexpress/entities/entity.cpp +++ b/engines/lastexpress/entities/entity.cpp @@ -255,7 +255,7 @@ void Entity::savegame(const SavePoint &savepoint) { } } -void Entity::playSound(const SavePoint &savepoint, bool resetItem, SoundManager::FlagType flag) { +void Entity::playSound(const SavePoint &savepoint, bool resetItem, SoundFlag flag) { EXPOSE_PARAMS(EntityData::EntityParametersSIIS) switch (savepoint.action) { diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h index 01cf17f791..1988aef6fe 100644 --- a/engines/lastexpress/entities/entity.h +++ b/engines/lastexpress/entities/entity.h @@ -686,7 +686,7 @@ protected: * @param resetItem true to reset item. * @param flag sound flag */ - void playSound(const SavePoint &savepoint, bool resetItem = false, SoundManager::FlagType flag = SoundManager::kFlagInvalid); + void playSound(const SavePoint &savepoint, bool resetItem = false, SoundFlag flag = kFlagInvalid); /** * Draws the entity diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp index f5ae191f9d..daa50956d3 100644 --- a/engines/lastexpress/entities/gendarmes.cpp +++ b/engines/lastexpress/entities/gendarmes.cpp @@ -88,12 +88,12 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_S(5, Gendarmes, arrestPlaysound16) - arrest(savepoint, true, SoundManager::kFlagDefault); + arrest(savepoint, true, kFlagDefault); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_I(6, Gendarmes, arrestCallback, uint32) - arrest(savepoint, true, SoundManager::kFlagInvalid, true); + arrest(savepoint, true, kFlagInvalid, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -103,7 +103,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_II(8, Gendarmes, arrestUpdateEntity, CarIndex, EntityPosition) - arrest(savepoint, true, SoundManager::kFlagInvalid, false, true); + arrest(savepoint, true, kFlagInvalid, false, true); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -221,7 +221,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, function9, CarIndex, EntityPosition) strcpy(arrestSound, "POL1043"); strcat(arrestSound, (char *)¶ms->seq2); - getSound()->playSound(kEntityGendarmes, arrestSound, SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityGendarmes, arrestSound, kFlagInvalid, 30); } getData()->location = kLocationInsideCompartment; @@ -264,7 +264,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje if (params->param6 == 0 || getState()->timeTicks > (uint32)params->param6) { params->param6 = kTimeInvalid; - getSound()->playSound(kEntityGendarmes, "POL1046A", SoundManager::kFlagDefault); + getSound()->playSound(kEntityGendarmes, "POL1046A", kFlagDefault); } UPDATE_PARAM(params->param7, getState()->timeTicks, 300); @@ -276,7 +276,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje if (getEntities()->isOutsideAlexeiWindow()) getScenes()->loadSceneFromPosition(kCarGreenSleeping, 49); - getSound()->playSound(kEntityGendarmes, "LIB017", SoundManager::kFlagDefault); + getSound()->playSound(kEntityGendarmes, "LIB017", kFlagDefault); setCallback(getProgress().jacket == kJacketBlood ? 3 : 4); setup_savegame(kSavegameTypeEvent, getProgress().jacket == kJacketBlood ? kEventMertensBloodJacket : kEventGendarmesArrestation); @@ -312,7 +312,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje break; case 2: - getSound()->playSound(kEntityGendarmes, "LIB014", SoundManager::kFlagDefault); + getSound()->playSound(kEntityGendarmes, "LIB014", kFlagDefault); getAction()->playAnimation(kEventGendarmesArrestation); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); break; @@ -338,7 +338,7 @@ IMPLEMENT_FUNCTION_III(10, Gendarmes, function10, CarIndex, EntityPosition, Obje break; case 6: - getSound()->playSound(kEntityGendarmes, "LIB014", SoundManager::kFlagDefault); + getSound()->playSound(kEntityGendarmes, "LIB014", kFlagDefault); getAction()->playAnimation(kEventGendarmesArrestation); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); break; @@ -544,7 +544,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// // Private functions ////////////////////////////////////////////////////////////////////////// -void Gendarmes::arrest(const SavePoint &savepoint, bool shouldPlaySound, SoundManager::FlagType flag, bool checkCallback, bool shouldUpdateEntity) { +void Gendarmes::arrest(const SavePoint &savepoint, bool shouldPlaySound, SoundFlag flag, bool checkCallback, bool shouldUpdateEntity) { switch (savepoint.action) { default: break; diff --git a/engines/lastexpress/entities/gendarmes.h b/engines/lastexpress/entities/gendarmes.h index e8f9cb2c38..5c3ff1d439 100644 --- a/engines/lastexpress/entities/gendarmes.h +++ b/engines/lastexpress/entities/gendarmes.h @@ -88,7 +88,7 @@ public: DECLARE_FUNCTION(chapter5) private: - void arrest(const SavePoint &savepoint, bool playSound = false, SoundManager::FlagType flag = SoundManager::kFlagInvalid, bool checkCallback = false, bool shouldUpdateEntity = false); + void arrest(const SavePoint &savepoint, bool playSound = false, SoundFlag flag = kFlagInvalid, bool checkCallback = false, bool shouldUpdateEntity = false); }; } // End of namespace LastExpress diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp index 6472ce0533..db71981b60 100644 --- a/engines/lastexpress/entities/kahina.cpp +++ b/engines/lastexpress/entities/kahina.cpp @@ -1186,7 +1186,7 @@ IMPLEMENT_FUNCTION(24, Kahina, function24) getEntities()->updateEntity(kEntityKahina, kCarKronos, kPosition_9270); getEntities()->loadSceneFromEntityPosition(getData()->car, (EntityPosition)(getData()->entityPosition + 750)); getSavePoints()->push(kEntityKahina, kEntityKronos, kAction235599361); - getSound()->playSound(kEntityKahina, "MUS016", SoundManager::kFlagDefault); + getSound()->playSound(kEntityKahina, "MUS016", kFlagDefault); getProgress().field_44 = 1; params->param1 = true; diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp index 925b0967b7..5afc52fe3d 100644 --- a/engines/lastexpress/entities/kronos.cpp +++ b/engines/lastexpress/entities/kronos.cpp @@ -457,7 +457,7 @@ IMPLEMENT_FUNCTION(19, Kronos, function19) case 2: getAction()->playAnimation(kEventConcertStart); - getSound()->setupEntry(SoundManager::kSoundType7, kEntityKronos); + getSound()->setupEntry(kSoundType7, kEntityKronos); getScenes()->loadSceneFromPosition(kCarKronos, 83); RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_function39); diff --git a/engines/lastexpress/entities/mahmud.cpp b/engines/lastexpress/entities/mahmud.cpp index 7d30d31a84..f9ae741d0e 100644 --- a/engines/lastexpress/entities/mahmud.cpp +++ b/engines/lastexpress/entities/mahmud.cpp @@ -204,7 +204,7 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) if (getState()->time >= kTimeCityGalanta) { params->param3 = 0; } else { - getSound()->playSound(kEntityTrain, "LIB050", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTrain, "LIB050", kFlagDefault); getLogic()->gameOver(kSavegameTypeIndex, 0, (getProgress().chapter == kChapter1) ? kSceneGameOverPolice1 : kSceneGameOverPolice2, true); } break; @@ -235,7 +235,7 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) break; case kActionDefault: - getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170A" : "MAH1173", SoundManager::kFlagInvalid, 45); + getSound()->playSound(kEntityMahmud, params->param2 ? "MAH1170A" : "MAH1173", kFlagInvalid, 45); getProgress().field_C4 = 1; setCallback(1); diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp index 7e5931322d..12123ed04a 100644 --- a/engines/lastexpress/entities/max.cpp +++ b/engines/lastexpress/entities/max.cpp @@ -480,7 +480,7 @@ IMPLEMENT_FUNCTION(14, Max, freeFromCage) getSound()->removeFromQueue(kEntityMax); getAction()->playAnimation(kEventCathMaxCage); - getSound()->setupEntry(SoundManager::kSoundType7, kEntityMax); + getSound()->setupEntry(kSoundType7, kEntityMax); getScenes()->processScene(); break; diff --git a/engines/lastexpress/entities/mertens.cpp b/engines/lastexpress/entities/mertens.cpp index 91082f487e..b99e344b20 100644 --- a/engines/lastexpress/entities/mertens.cpp +++ b/engines/lastexpress/entities/mertens.cpp @@ -289,7 +289,7 @@ IMPLEMENT_FUNCTION_S(8, Mertens, playSound16) break; case kActionDefault: - getSound()->playSound(kEntityMertens, (char *)¶ms->seq1, SoundManager::kFlagDefault); + getSound()->playSound(kEntityMertens, (char *)¶ms->seq1, kFlagDefault); break; case kActionCallback: @@ -896,7 +896,7 @@ IMPLEMENT_FUNCTION(17, Mertens, function17) } else { // Got the passenger list, Mertens is looking for it before sitting ENTITY_PARAM(0, 2) = 1; - getSound()->playSound(kEntityMertens, "CON1058", SoundManager::kFlagInvalid, 75); + getSound()->playSound(kEntityMertens, "CON1058", kFlagInvalid, 75); getEntities()->drawSequenceRight(kEntityMertens, "601D"); } @@ -984,7 +984,7 @@ IMPLEMENT_FUNCTION(18, Mertens, function18) getEntities()->drawSequenceRight(kEntityMertens, "601A"); } else { ENTITY_PARAM(0, 2) = 1; - getSound()->playSound(kEntityMertens, "CON1058", SoundManager::kFlagInvalid, 75); + getSound()->playSound(kEntityMertens, "CON1058", kFlagInvalid, 75); getEntities()->drawSequenceRight(kEntityMertens, "601D"); } @@ -1199,7 +1199,7 @@ IMPLEMENT_FUNCTION(22, Mertens, function22) getData()->location = kLocationInsideCompartment; getEntities()->clearSequences(kEntityMertens); if (!getSound()->isBuffered(kEntityMertens)) - getSound()->playSound(kEntityMertens, "MAH1172", SoundManager::kFlagInvalid, 225); + getSound()->playSound(kEntityMertens, "MAH1172", kFlagInvalid, 225); setCallback(7); setup_function21(kObjectCompartment4, kObject20); diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp index 45fd6883f0..68030b3be3 100644 --- a/engines/lastexpress/entities/milos.cpp +++ b/engines/lastexpress/entities/milos.cpp @@ -111,7 +111,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_S(7, Milos, playSound16) - Entity::playSound(savepoint, false, SoundManager::kFlagDefault); + Entity::playSound(savepoint, false, kFlagDefault); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -1728,7 +1728,7 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) getSound()->processEntries(); getAction()->playAnimation(isNight() ? kEventLocomotiveMilosNight : kEventLocomotiveMilosDay); - getSound()->setupEntry(SoundManager::kSoundType7, kEntityMilos); + getSound()->setupEntry(kSoundType7, kEntityMilos); getScenes()->loadSceneFromPosition(kCarCoalTender, 1); break; diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp index 7cf7f7766e..d4a7359511 100644 --- a/engines/lastexpress/entities/pascale.cpp +++ b/engines/lastexpress/entities/pascale.cpp @@ -141,15 +141,15 @@ IMPLEMENT_FUNCTION(8, Pascale, welcomeSophieAndRebecca) break; case kChapter1: - getSound()->playSound(kEntityPascale, "REB1198", SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityPascale, "REB1198", kFlagInvalid, 30); break; case kChapter3: - getSound()->playSound(kEntityPascale, "REB3001", SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityPascale, "REB3001", kFlagInvalid, 30); break; case kChapter4: - getSound()->playSound(kEntityPascale, "REB4001", SoundManager::kFlagInvalid, 30); + getSound()->playSound(kEntityPascale, "REB4001", kFlagInvalid, 30); break; } @@ -754,7 +754,7 @@ IMPLEMENT_FUNCTION(24, Pascale, welcomeAbbot) break; case kActionDefault: - getSound()->playSound(kEntityPascale, "ABB3015", SoundManager::kFlagInvalid, 105); + getSound()->playSound(kEntityPascale, "ABB3015", kFlagInvalid, 105); getEntities()->drawSequenceRight(kEntityPascale, "029A1"); getEntities()->drawSequenceRight(kEntityAbbot, "029A2"); break; diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp index 1cb895d8d6..68a37b368d 100644 --- a/engines/lastexpress/entities/rebecca.cpp +++ b/engines/lastexpress/entities/rebecca.cpp @@ -316,7 +316,7 @@ IMPLEMENT_FUNCTION_I(17, Rebecca, function17, bool) getData()->location = kLocationOutsideCompartment; if (getProgress().chapter == kChapter3) - getSound()->playSound(kEntityRebecca, "Reb3005", SoundManager::kFlagInvalid, 75); + getSound()->playSound(kEntityRebecca, "Reb3005", kFlagInvalid, 75); if (params->param1) { setCallback(5); @@ -1357,7 +1357,7 @@ label_callback_3: params->param5 = kTimeInvalid; getData()->inventoryItem = kItemNone; - getSound()->playSound(kEntityRebecca, "Reb3008", SoundManager::kFlagInvalid, 60); + getSound()->playSound(kEntityRebecca, "Reb3008", kFlagInvalid, 60); getEntities()->updatePositionEnter(kEntityRebecca, kCarRestaurant, 52); setCallback(3); diff --git a/engines/lastexpress/entities/tables.cpp b/engines/lastexpress/entities/tables.cpp index c372663c40..da053c5871 100644 --- a/engines/lastexpress/entities/tables.cpp +++ b/engines/lastexpress/entities/tables.cpp @@ -49,7 +49,7 @@ Tables::Tables(LastExpressEngine *engine, EntityIndex id) : Entity(engine, id) { IMPLEMENT_FUNCTION(1, Tables, chapter1) if (savepoint.action == kActionDefault) { if (_id == kEntityTables2) - getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + getSound()->playSoundWithSubtitles("LOOP8A.SND", kFlagLoop, kEntityTables2); setup_draw(); } @@ -59,7 +59,7 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION(2, Tables, chapter2) if (savepoint.action == kActionDefault) { if (_id == kEntityTables2) - getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + getSound()->playSoundWithSubtitles("LOOP8A.SND", kFlagLoop, kEntityTables2); setup_draw(); } @@ -69,7 +69,7 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION(3, Tables, chapter3) if (savepoint.action == kActionDefault) { if (_id == kEntityTables2) - getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + getSound()->playSoundWithSubtitles("LOOP8A.SND", kFlagLoop, kEntityTables2); setup_draw(); } @@ -79,7 +79,7 @@ IMPLEMENT_FUNCTION_END IMPLEMENT_FUNCTION(4, Tables, chapter4) if (savepoint.action == kActionDefault) { if (_id == kEntityTables2) - getSound()->playSoundWithSubtitles("LOOP8A.SND", SoundManager::kFlagLoop, kEntityTables2); + getSound()->playSoundWithSubtitles("LOOP8A.SND", kFlagLoop, kEntityTables2); setup_draw(); } diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp index 6e25d8c5c7..db5c413dc9 100644 --- a/engines/lastexpress/entities/tatiana.cpp +++ b/engines/lastexpress/entities/tatiana.cpp @@ -1952,7 +1952,7 @@ IMPLEMENT_FUNCTION(48, Tatiana, function48) UPDATE_PARAM_GOTO(params->param2, getState()->timeTicks, 5 * (3 * rnd(5) + 30), label_end); - getSound()->playSound(kEntityTatiana, "LIB012", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTatiana, "LIB012", kFlagDefault); params->param2 = 0; label_end: diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp index 19c6fe279c..1a5c6f4f64 100644 --- a/engines/lastexpress/entities/train.cpp +++ b/engines/lastexpress/entities/train.cpp @@ -118,7 +118,7 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) getObjects()->update((ObjectIndex)params->param1, kEntityTrain, kObjectLocation3, kCursorNormal, kCursorNormal); // Knock / closed door sound - getSound()->playSound(kEntityTables5, (params->param2 == 8) ? "LIB012" : "LIB013", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables5, (params->param2 == 8) ? "LIB012" : "LIB013", kFlagDefault); if (params->param4 && params->param5) { @@ -130,17 +130,17 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) break; case 1: - getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1014", kFlagDefault, 15); break; case 2: - getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); - getSound()->playSound(kEntityTables5, "Har1016", SoundManager::kFlagDefault, 150); + getSound()->playSound(kEntityTables5, "Har1013", kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1016", kFlagDefault, 150); break; case 3: - getSound()->playSound(kEntityTables5, "Har1015A", SoundManager::kFlagDefault, 15); - getSound()->playSound(kEntityTables5, "Har1015", SoundManager::kFlagDefault, 150); + getSound()->playSound(kEntityTables5, "Har1015A", kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1015", kFlagDefault, 150); break; } @@ -164,15 +164,15 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) break; case 1: - getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1014", kFlagDefault, 15); break; case 2: - getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1013", kFlagDefault, 15); break; case 3: - getSound()->playSound(kEntityTables5, "Har1013A", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1013A", kFlagDefault, 15); break; } @@ -191,11 +191,11 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) break; case 1: - getSound()->playSound(kEntityTables5, "Har1012", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1012", kFlagDefault, 15); break; case 2: - getSound()->playSound(kEntityTables5, "Har1012A", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1012A", kFlagDefault, 15); break; } @@ -207,7 +207,7 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) ENTITY_PARAM(0, 1)++; if (ENTITY_PARAM(0, 1) <= 1) - getSound()->playSound(kEntityTables5, "Har1014", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1014", kFlagDefault, 15); else params->param8 = 1; @@ -221,7 +221,7 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) ENTITY_PARAM(0, 4)++; if (ENTITY_PARAM(0, 4) <= 1) { - getSound()->playSound(kEntityTables5, "Har1011", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1011", kFlagDefault, 15); handleCompartmentAction(); return; } @@ -241,11 +241,11 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) break; case 1: - getSound()->playSound(kEntityTables5, "Har1013", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1013", kFlagDefault, 15); break; case 2: - getSound()->playSound(kEntityTables5, "Har1013A", SoundManager::kFlagDefault, 15); + getSound()->playSound(kEntityTables5, "Har1013A", kFlagDefault, 15); break; } diff --git a/engines/lastexpress/entities/vassili.cpp b/engines/lastexpress/entities/vassili.cpp index 09fb5b1223..a1daf3e524 100644 --- a/engines/lastexpress/entities/vassili.cpp +++ b/engines/lastexpress/entities/vassili.cpp @@ -268,7 +268,7 @@ IMPLEMENT_FUNCTION(8, Vassili, function8) getSavePoints()->push(kEntityVassili, kEntityAnna, kAction226031488); getSavePoints()->push(kEntityVassili, kEntityVerges, kAction226031488); getSavePoints()->push(kEntityVassili, kEntityCoudert, kAction226031488); - getSound()->playSound(kEntityVassili, "VAS1027", SoundManager::kFlagDefault); + getSound()->playSound(kEntityVassili, "VAS1027", kFlagDefault); break; } IMPLEMENT_FUNCTION_END @@ -300,7 +300,7 @@ IMPLEMENT_FUNCTION(9, Vassili, function9) setup_seizure(); } else { if (savepoint.action == kActionDefault) - getSound()->playSound(kEntityVassili, "VAS1028", SoundManager::kFlagDefault); + getSound()->playSound(kEntityVassili, "VAS1028", kFlagDefault); } break; } diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp index bc35a105b1..c0a00b8c05 100644 --- a/engines/lastexpress/entities/verges.cpp +++ b/engines/lastexpress/entities/verges.cpp @@ -123,7 +123,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_NOSETUP(5, Verges, playSound16) - Entity::playSound(savepoint, false, SoundManager::kFlagDefault); + Entity::playSound(savepoint, false, kFlagDefault); IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// @@ -699,7 +699,7 @@ IMPLEMENT_FUNCTION(24, Verges, policeGettingOffTrain) break; case kActionDefault: - getSound()->playSound(kEntityVerges, "POL1101", SoundManager::kFlagDefault); + getSound()->playSound(kEntityVerges, "POL1101", kFlagDefault); break; case kActionCallback: diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp index 79ac934ef9..74bc0d3ea9 100644 --- a/engines/lastexpress/entities/vesna.cpp +++ b/engines/lastexpress/entities/vesna.cpp @@ -1083,7 +1083,7 @@ IMPLEMENT_FUNCTION(30, Vesna, function30) case kActionNone: if (!params->param1) { UPDATE_PARAM_PROC(params->param3, getState()->timeTicks, 120) - getSound()->playSound(kEntityVesna, "Ves50001", SoundManager::kFlagDefault); + getSound()->playSound(kEntityVesna, "Ves50001", kFlagDefault); params->param1 = 1; UPDATE_PARAM_PROC_END } @@ -1146,7 +1146,7 @@ IMPLEMENT_FUNCTION(30, Vesna, function30) setCallback(2); setup_savegame(kSavegameTypeEvent, kEventCathVesnaTrainTopKilled); } else { - getSound()->playSound(kEntityVesna, "Ves5001", SoundManager::kFlagDefault); + getSound()->playSound(kEntityVesna, "Ves5001", kFlagDefault); params->param1 = 1; } break; diff --git a/engines/lastexpress/fight/fighter_anna.cpp b/engines/lastexpress/fight/fighter_anna.cpp index db2ab54c4b..3c0132eef6 100644 --- a/engines/lastexpress/fight/fighter_anna.cpp +++ b/engines/lastexpress/fight/fighter_anna.cpp @@ -124,7 +124,7 @@ FighterOpponentAnna::FighterOpponentAnna(LastExpressEngine *engine) : Opponent(e _sequences.push_back(loadSequence("2002okml.seq")); _sequences.push_back(loadSequence("2002okm.seq")); - getSound()->playSound(kEntityTables0, "MUS030", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables0, "MUS030", kFlagDefault); _field_38 = 30; } diff --git a/engines/lastexpress/fight/fighter_ivo.cpp b/engines/lastexpress/fight/fighter_ivo.cpp index 423b6b4ce5..60d6c1a874 100644 --- a/engines/lastexpress/fight/fighter_ivo.cpp +++ b/engines/lastexpress/fight/fighter_ivo.cpp @@ -144,7 +144,7 @@ FighterOpponentIvo::FighterOpponentIvo(LastExpressEngine *engine) : Opponent(eng _sequences.push_back(loadSequence("csdr.seq")); _sequences.push_back(loadSequence("2003l.seq")); - getSound()->playSound(kEntityTables0, "MUS032", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables0, "MUS032", kFlagDefault); _countdown = 5; _field_38 = 15; diff --git a/engines/lastexpress/fight/fighter_milos.cpp b/engines/lastexpress/fight/fighter_milos.cpp index 46e4bde7a6..972c44882b 100644 --- a/engines/lastexpress/fight/fighter_milos.cpp +++ b/engines/lastexpress/fight/fighter_milos.cpp @@ -108,7 +108,7 @@ void FighterPlayerMilos::update() { _opponent->setSequenceAndDraw(6, kFightSequenceType1); getSound()->removeFromQueue(kEntityTables0); - getSound()->playSound(kEntityTrain, "MUS029", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTrain, "MUS029", kFlagDefault); handleAction(kFightActionWin); } @@ -148,7 +148,7 @@ FighterOpponentMilos::FighterOpponentMilos(LastExpressEngine *engine) : Opponent _sequences.push_back(loadSequence("2001dbk.seq")); _sequences.push_back(loadSequence("2001wbk.seq")); - getSound()->playSound(kEntityTables0, "MUS027", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables0, "MUS027", kFlagDefault); _field_38 = 35; } diff --git a/engines/lastexpress/fight/fighter_salko.cpp b/engines/lastexpress/fight/fighter_salko.cpp index 795dd41b93..6f71a6dda8 100644 --- a/engines/lastexpress/fight/fighter_salko.cpp +++ b/engines/lastexpress/fight/fighter_salko.cpp @@ -132,7 +132,7 @@ FighterOpponentSalko::FighterOpponentSalko(LastExpressEngine *engine) : Opponent _sequences.push_back(loadSequence("2004ohm.seq")); _sequences.push_back(loadSequence("blank.seq")); - getSound()->playSound(kEntityTables0, "MUS035", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables0, "MUS035", kFlagDefault); _countdown = 3; _field_38 = 30; diff --git a/engines/lastexpress/fight/fighter_vesna.cpp b/engines/lastexpress/fight/fighter_vesna.cpp index a2460106b0..c92d041c7e 100644 --- a/engines/lastexpress/fight/fighter_vesna.cpp +++ b/engines/lastexpress/fight/fighter_vesna.cpp @@ -150,7 +150,7 @@ FighterOpponentVesna::FighterOpponentVesna(LastExpressEngine *engine) : Opponent _sequences.push_back(loadSequence("2005csbm.seq")); _sequences.push_back(loadSequence("2005oam4.seq")); - getSound()->playSound(kEntityTables0, "MUS038", SoundManager::kFlagDefault); + getSound()->playSound(kEntityTables0, "MUS038", kFlagDefault); _countdown = 4; _field_38 = 30; diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp index 7540d18ed8..54bb8759ee 100644 --- a/engines/lastexpress/game/action.cpp +++ b/engines/lastexpress/game/action.cpp @@ -466,7 +466,7 @@ IMPLEMENT_ACTION(playMusic) Common::String filename = Common::String::format("MUS%03d", hotspot.param1); if (!getSound()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5)) - getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault, hotspot.param2); + getSound()->playSound(kEntityPlayer, filename, kFlagDefault, hotspot.param2); return kSceneInvalid; } @@ -806,7 +806,7 @@ IMPLEMENT_ACTION(enterCompartment) getSound()->playSoundEvent(kEntityPlayer, 15, 22); if (getProgress().field_78 && !getSound()->isBuffered("MUS003")) { - getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_78 = 0; } @@ -1084,7 +1084,7 @@ IMPLEMENT_ACTION(25) case 2: if (!getSound()->isBuffered("MUS021")) - getSound()->playSound(kEntityPlayer, "MUS021", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS021", kFlagDefault); break; case 3: @@ -1183,7 +1183,7 @@ IMPLEMENT_ACTION(29) Common::String filename = Common::String::format("MUS%03d", hotspot.param3); if (!getSound()->isBuffered(filename)) - getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, filename, kFlagDefault); return kSceneInvalid; } @@ -1345,7 +1345,7 @@ IMPLEMENT_ACTION(openBed) ////////////////////////////////////////////////////////////////////////// // Action 37 IMPLEMENT_ACTION(dialog) - getSound()->playDialog(kEntityTables4, (EntityIndex)hotspot.param1, SoundManager::kFlagDefault, 0); + getSound()->playDialog(kEntityTables4, (EntityIndex)hotspot.param1, kFlagDefault, 0); return kSceneInvalid; } @@ -1355,7 +1355,7 @@ IMPLEMENT_ACTION(dialog) IMPLEMENT_ACTION(eggBox) getSound()->playSoundEvent(kEntityPlayer, 43); if (getProgress().field_7C && !getSound()->isBuffered("MUS003")) { - getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_7C = 0; } @@ -1367,7 +1367,7 @@ IMPLEMENT_ACTION(eggBox) IMPLEMENT_ACTION(39) getSound()->playSoundEvent(kEntityPlayer, 24); if (getProgress().field_80 && !getSound()->isBuffered("MUS003")) { - getSound()->playSound(kEntityPlayer, "MUS003", SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_80 = 0; } @@ -1409,7 +1409,7 @@ IMPLEMENT_ACTION(playMusicChapter) Common::String filename = Common::String::format("MUS%03d", id); if (!getSound()->isBuffered(filename)) - getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, filename, kFlagDefault); } return kSceneInvalid; @@ -1441,7 +1441,7 @@ IMPLEMENT_ACTION(playMusicChapterSetupTrain) Common::String filename = Common::String::format("MUS%03d", hotspot.param1); if (!getSound()->isBuffered(filename) && hotspot.param3 & id) { - getSound()->playSound(kEntityPlayer, filename, SoundManager::kFlagDefault); + getSound()->playSound(kEntityPlayer, filename, kFlagDefault); getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename.c_str()); getSavePoints()->push(kEntityPlayer, kEntityTrain, kAction222746496, hotspot.param2); diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp index 513ad114b0..0fa3af36b7 100644 --- a/engines/lastexpress/game/entities.cpp +++ b/engines/lastexpress/game/entities.cpp @@ -299,7 +299,7 @@ void Entities::setupChapter(ChapterIndex chapter) { memset(&_compartments1, 0, sizeof(_compartments1)); memset(&_positions, 0, sizeof(_positions)); - getSound()->resetQueue(SoundManager::kSoundType13); + getSound()->resetQueue(kSoundType13); } // we skip the header when doing entity setup @@ -2355,7 +2355,7 @@ bool Entities::changeCar(EntityData::EntityCallData *data, EntityIndex entity, C if (data->car == newCar) { if (isInGreenCarEntrance(kEntityPlayer)) { getSound()->playSoundEvent(kEntityPlayer, 14); - getSound()->excuseMe(entity, kEntityPlayer, SoundManager::kFlagDefault); + getSound()->excuseMe(entity, kEntityPlayer, kFlagDefault); getScenes()->loadSceneFromPosition(kCarGreenSleeping, 1); getSound()->playSound(kEntityPlayer, "CAT1127A"); getSound()->playSoundEvent(kEntityPlayer, 15); @@ -2374,7 +2374,7 @@ bool Entities::changeCar(EntityData::EntityCallData *data, EntityIndex entity, C if (data->car == newCar) { if (isInKronosCarEntrance(kEntityPlayer)) { getSound()->playSoundEvent(kEntityPlayer, 14); - getSound()->excuseMe(entity, kEntityPlayer, SoundManager::kFlagDefault); + getSound()->excuseMe(entity, kEntityPlayer, kFlagDefault); getScenes()->loadSceneFromPosition(kCarGreenSleeping, 62); getSound()->playSound(kEntityPlayer, "CAT1127A"); getSound()->playSoundEvent(kEntityPlayer, 15); diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp index 07ad8d936b..4d75fcaca5 100644 --- a/engines/lastexpress/game/inventory.cpp +++ b/engines/lastexpress/game/inventory.cpp @@ -156,7 +156,7 @@ void Inventory::handleMouseEvent(const Common::Event &ev) { _portraitHighlighted = false; _isOpened = false; - getSound()->playSoundWithSubtitles("LIB039.SND", SoundManager::kFlagMenuClock, kEntityPlayer); + getSound()->playSoundWithSubtitles("LIB039.SND", kFlagMenuClock, kEntityPlayer); getMenu()->show(true, kSavegameTypeIndex, 0); diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index 3bd7d6da68..c1237eefe9 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -432,7 +432,7 @@ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, boo if (showScene) { - getSound()->processEntry(SoundManager::kSoundType11); + getSound()->processEntry(kSoundType11); if (sceneIndex && !getFlags()->mouseRightClick) { getScenes()->loadScene(sceneIndex); diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp index e830b1d128..b346c9daf8 100644 --- a/engines/lastexpress/game/scenes.cpp +++ b/engines/lastexpress/game/scenes.cpp @@ -1132,7 +1132,7 @@ void SceneManager::postProcessScene() { } if (progress) - getSound()->excuseMe((progress == 1) ? entities[0] : entities[rnd(progress)], kEntityPlayer, SoundManager::kFlagDefault); + getSound()->excuseMe((progress == 1) ? entities[0] : entities[rnd(progress)], kEntityPlayer, kFlagDefault); } if (hotspot->scene) @@ -1157,8 +1157,8 @@ void SceneManager::postProcessScene() { if (getState()->time >= kTimeCityGalanta || getProgress().field_18 == 4) break; - getSound()->processEntry(SoundManager::kSoundType7); - getSound()->playSound(kEntityTrain, "LIB050", SoundManager::kFlagDefault); + getSound()->processEntry(kSoundType7); + getSound()->playSound(kEntityTrain, "LIB050", kFlagDefault); switch (getProgress().chapter) { default: diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 6cd5731e54..f8bee17d61 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -30,6 +30,8 @@ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/entry.h" + #include "lastexpress/helpers.h" #include "lastexpress/graphics.h" #include "lastexpress/lastexpress.h" @@ -96,12 +98,21 @@ static const char *const locomotiveSounds[5] = { "ZFX1007B" }; -static const SoundManager::FlagType soundFlags[32] = { - SoundManager::kFlagDefault, SoundManager::kFlag15, SoundManager::kFlag14, SoundManager::kFlag13, SoundManager::kFlag12, - SoundManager::kFlag11, SoundManager::kFlag11, SoundManager::kFlag10, SoundManager::kFlag10, SoundManager::kFlag9, SoundManager::kFlag9, SoundManager::kFlag8, SoundManager::kFlag8, - SoundManager::kFlag7, SoundManager::kFlag7, SoundManager::kFlag7, SoundManager::kFlag6, SoundManager::kFlag6, SoundManager::kFlag6, - SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag5, SoundManager::kFlag4, SoundManager::kFlag4, SoundManager::kFlag4, SoundManager::kFlag4, - SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3, SoundManager::kFlag3 +static const SoundFlag soundFlags[32] = { + kFlagDefault, + kFlag15, + kFlag14, + kFlag13, + kFlag12, + kFlag11, kFlag11, + kFlag10, kFlag10, + kFlag9, kFlag9, + kFlag8, kFlag8, + kFlag7, kFlag7, kFlag7, + kFlag6, kFlag6, kFlag6, + kFlag5, kFlag5, kFlag5, kFlag5, + kFlag4, kFlag4, kFlag4, kFlag4, + kFlag3, kFlag3, kFlag3, kFlag3, kFlag3 }; SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine), _state(0), _currentType(kSoundType16), _flag(0) { @@ -179,7 +190,7 @@ void SoundManager::resetQueue(SoundType type1, SoundType type2) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { if ((*i)->type != type1 && (*i)->type != type2) - resetEntry(*i); + (*i)->reset(); } } @@ -188,7 +199,7 @@ void SoundManager::removeFromQueue(EntityIndex entity) { SoundEntry *entry = getEntry(entity); if (entry) - resetEntry(entry); + entry->reset(); } void SoundManager::removeFromQueue(Common::String filename) { @@ -196,7 +207,7 @@ void SoundManager::removeFromQueue(Common::String filename) { SoundEntry *entry = getEntry(filename); if (entry) - resetEntry(entry); + entry->reset(); } void SoundManager::clearQueue() { @@ -244,13 +255,13 @@ bool SoundManager::isBuffered(Common::String filename, bool testForEntity) { ////////////////////////////////////////////////////////////////////////// // Entry ////////////////////////////////////////////////////////////////////////// -void SoundManager::setupEntry(SoundEntry *entry, Common::String name, FlagType flag, int a4) { +void SoundManager::setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int a4) { if (!entry) error("SoundManager::setupEntry: Invalid entry!"); entry->field_4C = a4; setEntryType(entry, flag); - setEntryStatus(entry, flag); + entry->setStatus(flag); // Add entry to sound list _soundList.push_back(entry); @@ -260,7 +271,7 @@ void SoundManager::setupEntry(SoundEntry *entry, Common::String name, FlagType f loadSoundData(entry, name); } -void SoundManager::setEntryType(SoundEntry *entry, FlagType flag) { +void SoundManager::setEntryType(SoundEntry *entry, SoundFlag flag) { switch (flag & kFlagType9) { default: case kFlagNone: @@ -271,12 +282,12 @@ void SoundManager::setEntryType(SoundEntry *entry, FlagType flag) { case kFlagType1_2: { SoundEntry *previous2 = getEntry(kSoundType2); if (previous2) - updateEntry(previous2, 0); + previous2->update(0); SoundEntry *previous = getEntry(kSoundType1); if (previous) { previous->type = kSoundType2; - updateEntry(previous, 0); + previous->update(0); } entry->type = kSoundType1; @@ -287,7 +298,7 @@ void SoundManager::setEntryType(SoundEntry *entry, FlagType flag) { SoundEntry *previous = getEntry(kSoundType3); if (previous) { previous->type = kSoundType4; - updateEntry(previous, 0); + previous->update(0); } entry->type = kSoundType11; @@ -332,21 +343,6 @@ void SoundManager::setEntryType(SoundEntry *entry, FlagType flag) { } } -void SoundManager::setEntryStatus(SoundEntry *entry, FlagType flag) const { - SoundStatus status = (SoundStatus)flag; - if (!((status & 0xFF) & kSoundStatusClear1)) - status = (SoundStatus)(status | kSoundStatusClear2); - - if (((status & 0xFF00) >> 8) & kSoundStatusClear0) - entry->status.status = (uint32)status; - else - entry->status.status = (status | kSoundStatusClear4); -} - -void SoundManager::setInCache(SoundEntry *entry) { - entry->status.status |= kSoundStatusClear2; -} - bool SoundManager::setupCache(SoundEntry *entry) { if (entry->soundData) return true; @@ -370,8 +366,10 @@ bool SoundManager::setupCache(SoundEntry *entry) { if (entry->field_4C <= size) return false; - if (cacheEntry) - setInCache(cacheEntry); + if (!cacheEntry) + error("[SoundManager::setupCache] Cannot find a valid entry"); + + cacheEntry->setInCache(); // TODO: Wait until the cache entry is ready to be removed while (!(cacheEntry->status.status1 & 1)) @@ -425,23 +423,6 @@ void SoundManager::loadSoundData(SoundEntry *entry, Common::String name) { } } -void SoundManager::resetEntry(SoundEntry *entry) const { - entry->status.status |= kSoundStatusRemoved; - entry->entity = kEntityPlayer; - - if (entry->stream) { - if (!entry->soundStream) { - SAFE_DELETE(entry->stream); - } else { - entry->soundStream->stop(); - SAFE_DELETE(entry->soundStream); - } - - entry->stream = NULL; - } -} - - void SoundManager::removeEntry(SoundEntry *entry) { entry->status.status |= kSoundStatusRemoved; @@ -467,47 +448,12 @@ void SoundManager::removeEntry(SoundEntry *entry) { } } -void SoundManager::updateEntry(SoundEntry *entry, uint value) const { - if (!(entry->status.status3 & 64)) { - int value2 = value; - - entry->status.status |= kSoundStatus_100000; - - if (value) { - if (_flag & 32) { - entry->field_40 = value; - value2 = value * 2 + 1; - } - - entry->field_3C = value2; - } else { - entry->field_3C = 0; - entry->status.status |= kSoundStatus_40000000; - } - } -} - -void SoundManager::updateEntryState(SoundEntry *entry) const { - if (_flag & 32) { - if (entry->type != kSoundType9 && entry->type != kSoundType7 && entry->type != kSoundType5) { - uint32 status = entry->status.status & kSoundStatusClear1; - - entry->status.status &= kSoundStatusClearAll; - - entry->field_40 = status; - entry->status.status |= status * 2 + 1; - } - } - - entry->status.status |= kSoundStatus_20; -} - void SoundManager::processEntry(EntityIndex entity) { Common::StackLock locker(_mutex); SoundEntry *entry = getEntry(entity); if (entry) { - updateEntry(entry, 0); + entry->update(0); entry->entity = kEntityPlayer; } } @@ -517,7 +463,7 @@ void SoundManager::processEntry(SoundType type) { SoundEntry *entry = getEntry(type); if (entry) - updateEntry(entry, 0); + entry->update(0); } void SoundManager::setupEntry(SoundType type, EntityIndex index) { @@ -533,7 +479,7 @@ void SoundManager::processEntry(Common::String filename) { SoundEntry *entry = getEntry(filename); if (entry) { - updateEntry(entry, 0); + entry->update(0); entry->entity = kEntityPlayer; } } @@ -567,7 +513,7 @@ void SoundManager::unknownFunction4() { ////////////////////////////////////////////////////////////////////////// // Entry search ////////////////////////////////////////////////////////////////////////// -SoundManager::SoundEntry *SoundManager::getEntry(EntityIndex index) { +SoundEntry *SoundManager::getEntry(EntityIndex index) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { if ((*i)->entity == index) return *i; @@ -576,7 +522,7 @@ SoundManager::SoundEntry *SoundManager::getEntry(EntityIndex index) { return NULL; } -SoundManager::SoundEntry *SoundManager::getEntry(Common::String name) { +SoundEntry *SoundManager::getEntry(Common::String name) { if (!name.contains('.')) name += ".SND"; @@ -588,7 +534,7 @@ SoundManager::SoundEntry *SoundManager::getEntry(Common::String name) { return NULL; } -SoundManager::SoundEntry *SoundManager::getEntry(SoundType type) { +SoundEntry *SoundManager::getEntry(SoundType type) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { if ((*i)->type == type) return *i; @@ -663,11 +609,11 @@ uint32 SoundManager::count() { ////////////////////////////////////////////////////////////////////////// // Game-related functions ////////////////////////////////////////////////////////////////////////// -void SoundManager::playSound(EntityIndex entity, Common::String filename, FlagType flag, byte a4) { +void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundFlag flag, byte a4) { if (isBuffered(entity) && entity) removeFromQueue(entity); - FlagType currentFlag = (flag == -1) ? getSoundFlag(entity) : (FlagType)(flag | 0x80000); + SoundFlag currentFlag = (flag == -1) ? getSoundFlag(entity) : (SoundFlag)(flag | 0x80000); // Add .SND at the end of the filename if needed if (!filename.contains('.')) @@ -678,8 +624,8 @@ void SoundManager::playSound(EntityIndex entity, Common::String filename, FlagTy getSavePoints()->push(kEntityPlayer, entity, kActionEndSound); } -bool SoundManager::playSoundWithSubtitles(Common::String filename, FlagType flag, EntityIndex entity, byte a4) { - SoundEntry *entry = new SoundEntry(); +bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4) { + SoundEntry *entry = new SoundEntry(_engine); Common::StackLock locker(_mutex); @@ -695,7 +641,7 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, FlagType flag filename.deleteLastChar(); showSubtitle(entry, filename); - updateEntryState(entry); + entry->updateState(); } return (entry->type != kSoundTypeNone); @@ -711,7 +657,7 @@ void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { return; int _action = (int)action; - FlagType flag = getSoundFlag(entity); + SoundFlag flag = getSoundFlag(entity); switch (action) { case 36: { @@ -886,7 +832,7 @@ void SoundManager::playFightSound(byte action, byte a4) { playSound(kEntityTrain, Common::String::format("LIB%03d.SND", _action), kFlagDefault, a4); } -void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, FlagType flag, byte a4) { +void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4) { if (isBuffered(getDialogName(entityDialog))) removeFromQueue(getDialogName(entityDialog)); @@ -894,7 +840,7 @@ void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, Flag } void SoundManager::playLocomotiveSound() { - playSound(kEntityPlayer, locomotiveSounds[rnd(5)], (FlagType)(rnd(15) + 2)); + playSound(kEntityPlayer, locomotiveSounds[rnd(5)], (SoundFlag)(rnd(15) + 2)); } const char *SoundManager::getDialogName(EntityIndex entity) const { @@ -1400,7 +1346,7 @@ void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compar _lastWarning[compartment - 28] = getState()->timeTicks; } -void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, FlagType flag) { +void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag flag) { if (isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain) return; @@ -1750,7 +1696,7 @@ const char *SoundManager::justAMinuteCath() const { ////////////////////////////////////////////////////////////////////////// // Sound flags ////////////////////////////////////////////////////////////////////////// -SoundManager::FlagType SoundManager::getSoundFlag(EntityIndex entity) const { +SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { if (entity == kEntityPlayer) return kFlagDefault; @@ -1758,7 +1704,7 @@ SoundManager::FlagType SoundManager::getSoundFlag(EntityIndex entity) const { return kFlagNone; // Compute sound value - FlagType ret = kFlag2; + SoundFlag ret = kFlag2; // Get default value if valid int index = ABS(getEntityData(entity)->entityPosition - getEntityData(kEntityPlayer)->entityPosition) / 230; @@ -1771,7 +1717,7 @@ SoundManager::FlagType SoundManager::getSoundFlag(EntityIndex entity) const { && !getEntities()->isOutsideAnnaWindow()) return kFlagNone; - return (FlagType)(ret / 6); + return (SoundFlag)(ret / 6); } switch (getEntityData(entity)->car) { @@ -1780,25 +1726,25 @@ SoundManager::FlagType SoundManager::getSoundFlag(EntityIndex entity) const { case kCarKronos: if (getEntities()->isInKronosSalon(entity) != getEntities()->isInKronosSalon(kEntityPlayer)) - ret = (FlagType)(ret * 2); + ret = (SoundFlag)(ret * 2); break; case kCarGreenSleeping: case kCarRedSleeping: if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInKronosSalon(entity)) - ret = (FlagType)(ret * 2); + ret = (SoundFlag)(ret * 2); if (getEntityData(kEntityPlayer)->location && (getEntityData(entity)->entityPosition != kPosition_1 || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400))) - ret = (FlagType)(ret * 2); + ret = (SoundFlag)(ret * 2); break; case kCarRestaurant: if (getEntities()->isInSalon(entity) == getEntities()->isInSalon(kEntityPlayer) && (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer))) - ret = (FlagType)(ret * 2); + ret = (SoundFlag)(ret * 2); else - ret = (FlagType)(ret * 4); + ret = (SoundFlag)(ret * 4); break; } @@ -1865,7 +1811,7 @@ void SoundManager::showSubtitle(SoundEntry *entry, Common::String filename) { } } -SoundManager::SubtitleEntry *SoundManager::loadSubtitle(Common::String filename, SoundEntry *soundEntry) { +SubtitleEntry *SoundManager::loadSubtitle(Common::String filename, SoundEntry *soundEntry) { SubtitleEntry *entry = new SubtitleEntry(); _subtitles.push_back(entry); @@ -1950,7 +1896,7 @@ void SoundManager::playLoopingSound(int param) { } byte numLoops[8]; - static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, + static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, kPosition_6470, kPosition_5790, kPosition_4840, kPosition_4070, kPosition_3050, kPosition_2740 }; @@ -2033,11 +1979,11 @@ void SoundManager::playLoopingSound(int param) { playSoundWithSubtitles(tmp, kFlagLoopedSound, kEntitySteam); if (*snd) - updateEntry(*snd, 0); + (*snd)->update(0); for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { if ((*snd)->type == kSoundType1) { - updateEntry((*snd), 7); + (*snd)->update(7); break; } } diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index f49f2bc9f0..a87bb9bb80 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -23,52 +23,6 @@ #ifndef LASTEXPRESS_SOUND_H #define LASTEXPRESS_SOUND_H -/* - - Sound entry: 68 bytes (this is what appears in the savegames) - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - entity - uint32 {4} - ?? - uint32 {4} - ?? - char {16} - name 1 - char {16} - name 2 - - Sound queue entry: 120 bytes - uint16 {2} - status - byte {1} - ?? - byte {1} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - file data pointer - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - archive structure pointer - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - entity - uint32 {4} - ?? - uint32 {4} - ?? - char {16} - name 1 - char {16} - name 2 - uint32 {4} - pointer to next entry in the queue - uint32 {4} - subtitle data pointer - -*/ - -#include "lastexpress/data/snd.h" -#include "lastexpress/data/subtitle.h" - #include "lastexpress/shared.h" #include "lastexpress/helpers.h" @@ -82,61 +36,11 @@ namespace LastExpress { class LastExpressEngine; class SubtitleManager; +class SoundEntry; +class SubtitleEntry; class SoundManager : Common::Serializable { public: - enum SoundType { - kSoundTypeNone = 0, - kSoundType1, - kSoundType2, - kSoundType3, - kSoundType4, - kSoundType5, - kSoundType6, - kSoundType7, - kSoundType8, - kSoundType9, - kSoundType10, - kSoundType11, - kSoundType12, - kSoundType13, - kSoundType14, - kSoundType15, - kSoundType16 - }; - - enum FlagType { - kFlagInvalid = -1, - kFlagNone = 0x0, - kFlag2 = 0x2, - kFlag3 = 0x3, - kFlag4 = 0x4, - kFlag5 = 0x5, - kFlag6 = 0x6, - kFlag7 = 0x7, - kFlag8 = 0x8, - kFlag9 = 0x9, - kFlag10 = 0xA, - kFlag11 = 0xB, - kFlag12 = 0xC, - kFlag13 = 0xD, - kFlag14 = 0xE, - kFlag15 = 0xF, - kFlagDefault = 0x10, - - kFlagType1_2 = 0x1000000, - kFlagLoopedSound = 0x1001001, - kFlagSteam = 0x1001007, - kFlagType13 = 0x3000000, - kFlagMenuClock = 0x3080010, - kFlagType7 = 0x4000000, - kFlagType11 = 0x5000000, - kFlagMusic = 0x5000010, - kFlagType3 = 0x6000000, - kFlagLoop = 0x6001008, - kFlagType9 = 0x7000000 - }; - SoundManager(LastExpressEngine *engine); ~SoundManager(); @@ -171,10 +75,10 @@ public: void clearStatus(); // Sound playing - void playSound(EntityIndex entity, Common::String filename, FlagType flag = kFlagInvalid, byte a4 = 0); - bool playSoundWithSubtitles(Common::String filename, FlagType flag, EntityIndex entity, byte a4 = 0); + void playSound(EntityIndex entity, Common::String filename, SoundFlag flag = kFlagInvalid, byte a4 = 0); + bool playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4 = 0); void playSoundEvent(EntityIndex entity, byte action, byte a3 = 0); - void playDialog(EntityIndex entity, EntityIndex entityDialog, FlagType flag, byte a4); + void playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4); void playSteam(CityIndex index); void playFightSound(byte action, byte a4); void playLocomotiveSound(); @@ -185,14 +89,14 @@ public: const char *getDialogName(EntityIndex entity) const; // Sound bites - void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, FlagType flag = kFlagNone); + void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, SoundFlag flag = kFlagNone); void excuseMeCath(); const char *justCheckingCath() const; const char *wrongDoorCath() const; const char *justAMinuteCath() const; // FLags - SoundManager::FlagType getSoundFlag(EntityIndex index) const; + SoundFlag getSoundFlag(EntityIndex index) const; // Debug void stopAllSound(); @@ -201,129 +105,18 @@ public: void saveLoadWithSerializer(Common::Serializer &ser); uint32 count(); + // Accessors + uint32 getFlag() { return _flag; } + private: typedef int32 *SoundBuffer; - enum SoundStatus { - kSoundStatus_20 = 0x20, - kSoundStatus_40 = 0x40, - kSoundStatus_180 = 0x180, - kSoundStatusRemoved = 0x200, - kSoundStatus_400 = 0x400, - - kSoundStatus_8000 = 0x8000, - kSoundStatus_20000 = 0x20000, - kSoundStatus_100000 = 0x100000, - kSoundStatus_40000000 = 0x40000000, - - kSoundStatusClear0 = 0x10, - kSoundStatusClear1 = 0x1F, - kSoundStatusClear2 = 0x80, - kSoundStatusClear3 = 0x200, - kSoundStatusClear4 = 0x800, - kSoundStatusClearAll = 0xFFFFFFE0 - }; - enum SoundState { kSoundState0 = 0, kSoundState1 = 1, kSoundState2 = 2 }; - union SoundStatusUnion { - uint32 status; - byte status1; - byte status2; - byte status3; - byte status4; - - SoundStatusUnion() { - status = 0; - } - }; - - struct SubtitleEntry; - - struct SoundEntry { - SoundStatusUnion status; - SoundType type; // int - //int data; - //int endOffset; - int currentDataPtr; - void *soundData; - //int currentBufferPtr; - int blockCount; - uint32 time; - //int size; - //int field_28; - Common::SeekableReadStream *stream; // int - //int field_30; - int field_34; - int field_38; - int field_3C; - int field_40; - EntityIndex entity; - int field_48; - uint32 field_4C; - Common::String name1; //char[16]; - Common::String name2; //char[16]; - //int next; // offset to the next structure in the list (not used) - SubtitleEntry *subtitle; - - // Sound stream - StreamedSound *soundStream; - - SoundEntry() { - status.status = 0; - type = kSoundTypeNone; - - currentDataPtr = 0; - soundData = NULL; - - blockCount = 0; - time = 0; - - stream = NULL; - - field_34 = 0; - field_38 = 0; - field_3C = 0; - field_40 = 0; - entity = kEntityPlayer; - field_48 = 0; - field_4C = 0; - - subtitle = NULL; - - soundStream = NULL; - } - - ~SoundEntry() { - // Entries that have been queued would have their streamed disposed automatically - if (!soundStream) - SAFE_DELETE(stream); - - delete soundStream; - } - }; - - struct SubtitleEntry { - Common::String filename; - SoundStatusUnion status; - SoundEntry *sound; - SubtitleManager *data; - - SubtitleEntry() { - status.status = 0; - sound = NULL; - data = NULL; - } - - ~SubtitleEntry() { - SAFE_DELETE(data); - } - }; - // Engine LastExpressEngine *_engine; @@ -337,6 +130,8 @@ private: uint32 _data0; uint32 _data1; uint32 _data2; + + // TODO: this seems to be a synchronization flag for the sound timer uint32 _flag; // Filters @@ -358,17 +153,11 @@ private: SoundEntry *getEntry(Common::String name); SoundEntry *getEntry(SoundType type); - void setupEntry(SoundEntry *entry, Common::String name, FlagType flag, int a4); - void setEntryType(SoundEntry *entry, FlagType flag); - void setEntryStatus(SoundEntry *entry, FlagType flag) const; - void setInCache(SoundEntry *entry); + void setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int a4); + void setEntryType(SoundEntry *entry, SoundFlag flag); bool setupCache(SoundEntry *entry); void removeFromCache(SoundEntry *entry); void loadSoundData(SoundEntry *entry, Common::String name); - - void updateEntry(SoundEntry *entry, uint value) const; - void updateEntryState(SoundEntry *entry) const; - void resetEntry(SoundEntry *entry) const; void removeEntry(SoundEntry *entry); // Subtitles diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp index e55a6d5960..74a2c77a01 100644 --- a/engines/lastexpress/menu/menu.cpp +++ b/engines/lastexpress/menu/menu.cpp @@ -314,7 +314,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) { getFlags()->mouseRightClick = false; // Play intro music - getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer); + getSound()->playSoundWithSubtitles("MUS001.SND", kFlagMusic, kEntityPlayer); // Show The Smoking Car logo if (animation.load(getArchive("1931.nis"))) @@ -325,7 +325,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) { } else { // Only show the quick intro if (!_hasShownStartScreen) { - getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer); + getSound()->playSoundWithSubtitles("MUS018.SND", kFlagMusic, kEntityPlayer); getScenes()->loadScene(kSceneStartScreen); // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed @@ -349,7 +349,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) { // Setup sound getSound()->unknownFunction4(); - getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13); + getSound()->resetQueue(kSoundType11, kSoundType13); if (getSound()->isBuffered("TIMER")) getSound()->removeFromQueue("TIMER"); @@ -484,7 +484,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { setLogicEventHandlers(); if (_index) { - getSound()->processEntry(SoundManager::kSoundType11); + getSound()->processEntry(kSoundType11); } else { if (!getFlags()->mouseRightClick) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 3)); @@ -496,7 +496,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 5)); if (!getFlags()->mouseRightClick) { - getSound()->processEntry(SoundManager::kSoundType11); + getSound()->processEntry(kSoundType11); // Show intro Animation animation; @@ -512,7 +512,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { if (!getEvent(kEventIntro)) { getEvent(kEventIntro) = 1; - getSound()->processEntry(SoundManager::kSoundType11); + getSound()->processEntry(kSoundType11); } } @@ -1120,7 +1120,7 @@ void Menu::updateTime(uint32 time) { if (getSound()->isBuffered(kEntityChapters)) getSound()->removeFromQueue(kEntityChapters); - getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters); + getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", kFlagMenuClock, kEntityChapters); adjustIndex(_currentTime, _time, false); } } diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index 71d81da0c9..eff68efb73 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -66,6 +66,7 @@ MODULE_OBJS := \ menu/clock.o \ menu/menu.o \ menu/trainline.o \ + sound/entry.o \ debug.o \ detection.o \ graphics.o \ diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index 8cebe16d87..d1730eefce 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -27,6 +27,62 @@ namespace LastExpress { +////////////////////////////////////////////////////////////////////////// +// Sound +////////////////////////////////////////////////////////////////////////// + +enum SoundType { + kSoundTypeNone = 0, + kSoundType1, + kSoundType2, + kSoundType3, + kSoundType4, + kSoundType5, + kSoundType6, + kSoundType7, + kSoundType8, + kSoundType9, + kSoundType10, + kSoundType11, + kSoundType12, + kSoundType13, + kSoundType14, + kSoundType15, + kSoundType16 +}; + +enum SoundFlag { + kFlagInvalid = -1, + kFlagNone = 0x0, + kFlag2 = 0x2, + kFlag3 = 0x3, + kFlag4 = 0x4, + kFlag5 = 0x5, + kFlag6 = 0x6, + kFlag7 = 0x7, + kFlag8 = 0x8, + kFlag9 = 0x9, + kFlag10 = 0xA, + kFlag11 = 0xB, + kFlag12 = 0xC, + kFlag13 = 0xD, + kFlag14 = 0xE, + kFlag15 = 0xF, + kFlagDefault = 0x10, + + kFlagType1_2 = 0x1000000, + kFlagLoopedSound = 0x1001001, + kFlagSteam = 0x1001007, + kFlagType13 = 0x3000000, + kFlagMenuClock = 0x3080010, + kFlagType7 = 0x4000000, + kFlagType11 = 0x5000000, + kFlagMusic = 0x5000010, + kFlagType3 = 0x6000000, + kFlagLoop = 0x6001008, + kFlagType9 = 0x7000000 +}; + ////////////////////////////////////////////////////////////////////////// // Time values ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp new file mode 100644 index 0000000000..309996886a --- /dev/null +++ b/engines/lastexpress/sound/entry.cpp @@ -0,0 +1,151 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/sound/entry.h" + +#include "lastexpress/game/sound.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +#include "common/stream.h" + +namespace LastExpress { + +////////////////////////////////////////////////////////////////////////// +// SoundEntry +////////////////////////////////////////////////////////////////////////// +SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { + status.status = 0; + type = kSoundTypeNone; + + currentDataPtr = 0; + soundData = NULL; + + blockCount = 0; + time = 0; + + stream = NULL; + + field_34 = 0; + field_38 = 0; + field_3C = 0; + field_40 = 0; + entity = kEntityPlayer; + field_48 = 0; + field_4C = 0; + + subtitle = NULL; + + soundStream = NULL; +} + +SoundEntry::~SoundEntry() { + // Entries that have been queued would have their streamed disposed automatically + if (!soundStream) + SAFE_DELETE(stream); + + delete soundStream; + + _engine = NULL; +} + +void SoundEntry::setStatus(SoundFlag flag) { + SoundStatus statusFlag = (SoundStatus)flag; + if (!((statusFlag & 0xFF) & kSoundStatusClear1)) + statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); + + if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0) + status.status = (uint32)statusFlag; + else + status.status = (statusFlag | kSoundStatusClear4); +} + +void SoundEntry::setInCache() { + status.status |= kSoundStatusClear2; +} + +void SoundEntry::update(uint val) { + if (!(status.status3 & 64)) { + int value2 = val; + + status.status |= kSoundStatus_100000; + + if (val) { + if (getSound()->getFlag() & 32) { + field_40 = val; + value2 = val * 2 + 1; + } + + field_3C = value2; + } else { + field_3C = 0; + status.status |= kSoundStatus_40000000; + } + } +} + +void SoundEntry::updateState() { + if (getSound()->getFlag() & 32) { + if (type != kSoundType9 && type != kSoundType7 && type != kSoundType5) { + uint32 newStatus = status.status & kSoundStatusClear1; + + status.status &= kSoundStatusClearAll; + + field_40 = newStatus; + status.status |= newStatus * 2 + 1; + } + } + + status.status |= kSoundStatus_20; +} + +void SoundEntry::reset() { + status.status |= kSoundStatusRemoved; + entity = kEntityPlayer; + + if (stream) { + if (!soundStream) { + SAFE_DELETE(stream); + } else { + soundStream->stop(); + SAFE_DELETE(soundStream); + } + + stream = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +// SubtitleEntry +////////////////////////////////////////////////////////////////////////// +SubtitleEntry::SubtitleEntry() { + status.status = 0; + sound = NULL; + data = NULL; +} + +SubtitleEntry::~SubtitleEntry() { + SAFE_DELETE(data); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h new file mode 100644 index 0000000000..9ed091b225 --- /dev/null +++ b/engines/lastexpress/sound/entry.h @@ -0,0 +1,173 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_SOUND_ENTRY_H +#define LASTEXPRESS_SOUND_ENTRY_H + +/* + Sound entry: 68 bytes (this is what appears in the savegames) + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - entity + uint32 {4} - ?? + uint32 {4} - ?? + char {16} - name 1 + char {16} - name 2 + + Sound queue entry: 120 bytes + uint16 {2} - status + byte {1} - ?? + byte {1} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - file data pointer + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - archive structure pointer + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - ?? + uint32 {4} - entity + uint32 {4} - ?? + uint32 {4} - ?? + char {16} - name 1 + char {16} - name 2 + uint32 {4} - pointer to next entry in the queue + uint32 {4} - subtitle data pointer +*/ + +#include "lastexpress/data/snd.h" +#include "lastexpress/data/subtitle.h" + +#include "lastexpress/shared.h" + +namespace LastExpress { + +class LastExpressEngine; +class SubtitleEntry; + +enum SoundStatus { + kSoundStatus_20 = 0x20, + kSoundStatus_40 = 0x40, + kSoundStatus_180 = 0x180, + kSoundStatusRemoved = 0x200, + kSoundStatus_400 = 0x400, + + kSoundStatus_8000 = 0x8000, + kSoundStatus_20000 = 0x20000, + kSoundStatus_100000 = 0x100000, + kSoundStatus_40000000 = 0x40000000, + + kSoundStatusClear0 = 0x10, + kSoundStatusClear1 = 0x1F, + kSoundStatusClear2 = 0x80, + kSoundStatusClear3 = 0x200, + kSoundStatusClear4 = 0x800, + kSoundStatusClearAll = 0xFFFFFFE0 +}; + +union SoundStatusUnion { + uint32 status; + byte status1; + byte status2; + byte status3; + byte status4; + + SoundStatusUnion() { + status = 0; + } +}; + +////////////////////////////////////////////////////////////////////////// +// SoundEntry +////////////////////////////////////////////////////////////////////////// +class SoundEntry { +public: + SoundEntry(LastExpressEngine *engine); + ~SoundEntry(); + + void setStatus(SoundFlag flag); + void setInCache(); + void update(uint val); + void updateState(); + void reset(); + +private: + LastExpressEngine *_engine; + +public: + SoundStatusUnion status; + SoundType type; // int + //int data; + //int endOffset; + int currentDataPtr; + void *soundData; + //int currentBufferPtr; + int blockCount; + uint32 time; + //int size; + //int field_28; + Common::SeekableReadStream *stream; // int + //int field_30; + int field_34; + int field_38; + int field_3C; + int field_40; + EntityIndex entity; + int field_48; + uint32 field_4C; + Common::String name1; //char[16]; + Common::String name2; //char[16]; + //int next; // offset to the next structure in the list (not used) + SubtitleEntry *subtitle; + + // Sound stream + StreamedSound *soundStream; +}; + +////////////////////////////////////////////////////////////////////////// +// SubtitleEntry +////////////////////////////////////////////////////////////////////////// +class SubtitleEntry { +public: + SubtitleEntry(); + ~SubtitleEntry(); + +public: + Common::String filename; + SoundStatusUnion status; + SoundEntry *sound; + SubtitleManager *data; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SOUND_ENTRY_H -- cgit v1.2.3 From 3f4d2c8130ac1db51f9a2fc5fcb5a2413b215f45 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 24 Jun 2011 11:43:10 -0400 Subject: LASTEXPRESS: Move subtitle-related methods to the SubtitleEntry class --- engines/lastexpress/game/sound.cpp | 103 ++++-------------------------------- engines/lastexpress/game/sound.h | 16 +++--- engines/lastexpress/sound/entry.cpp | 91 ++++++++++++++++++++++++++++--- engines/lastexpress/sound/entry.h | 27 +++++++--- 4 files changed, 125 insertions(+), 112 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index f8bee17d61..adb82816f5 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -127,7 +127,7 @@ SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine), _state( // Sound cache _soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE); - _drawSubtitles = 0; + _subtitlesFlag = 0; _currentSubtitle = NULL; _loopingSoundDuration = 0; @@ -436,7 +436,7 @@ void SoundManager::removeEntry(SoundEntry *entry) { // removeFromCache(entry); if (entry->subtitle) { - drawSubtitle(entry->subtitle); + entry->subtitle->draw(); SAFE_DELETE(entry->subtitle); } @@ -640,7 +640,7 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla while (filename.size() > 4) filename.deleteLastChar(); - showSubtitle(entry, filename); + entry->showSubtitle(filename); entry->updateState(); } @@ -785,7 +785,7 @@ void SoundManager::playSteam(CityIndex index) { // Get the new sound entry and show subtitles SoundEntry *entry = getEntry(kSoundType1); if (entry) - showSubtitle(entry, cities[index]); + entry->showSubtitle(cities[index]); } void SoundManager::playFightSound(byte action, byte a4) { @@ -1762,7 +1762,7 @@ void SoundManager::updateSubtitles() { for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { uint32 current_index = 0; - SoundEntry *soundEntry = (*i)->sound; + SoundEntry *soundEntry = (*i)->getSoundEntry(); SoundStatus status = (SoundStatus)soundEntry->status.status; if (!(status & kSoundStatus_40) @@ -1786,103 +1786,20 @@ void SoundManager::updateSubtitles() { if (_currentSubtitle == subtitle) { if (subtitle) - setupSubtitleAndDraw(subtitle); + subtitle->setupAndDraw(); return; } - if (_drawSubtitles & 1) - drawSubtitleOnScreen(subtitle); + if (_subtitlesFlag & 1) + subtitle->drawOnScreen(); if (subtitle) { - loadSubtitleData(subtitle); - setupSubtitleAndDraw(subtitle); + subtitle->loadData(); + subtitle->setupAndDraw(); } } -void SoundManager::showSubtitle(SoundEntry *entry, Common::String filename) { - entry->subtitle = loadSubtitle(filename, entry); - - if (entry->subtitle->status.status2 & 4) { - drawSubtitle(entry->subtitle); - SAFE_DELETE(entry->subtitle); - } else { - entry->status.status |= kSoundStatus_20000; - } -} - -SubtitleEntry *SoundManager::loadSubtitle(Common::String filename, SoundEntry *soundEntry) { - SubtitleEntry *entry = new SubtitleEntry(); - _subtitles.push_back(entry); - - // Set sound entry and filename - entry->filename = filename + ".SBE"; - entry->sound = soundEntry; - - // Load subtitle data - if (_engine->getResourceManager()->hasFile(filename)) { - if (_drawSubtitles & 2) - return entry; - - loadSubtitleData(entry); - } else { - entry->status.status = kSoundStatus_400; - } - - return entry; -} - -void SoundManager::loadSubtitleData(SubtitleEntry * entry) { - entry->data = new SubtitleManager(_engine->getFont()); - entry->data->load(getArchive(entry->filename)); - - _drawSubtitles |= 2; - _currentSubtitle = entry; -} - -void SoundManager::setupSubtitleAndDraw(SubtitleEntry *subtitle) { - if (!subtitle->data) { - subtitle->data = new SubtitleManager(_engine->getFont()); - subtitle->data->load(getArchive(subtitle->filename)); - } - - if (subtitle->data->getMaxTime() > subtitle->sound->time) { - subtitle->status.status = kSoundStatus_400; - } else { - subtitle->data->setTime((uint16)subtitle->sound->time); - - if (_drawSubtitles & 1) - drawSubtitleOnScreen(subtitle); - } - - _currentSubtitle = subtitle; -} - -void SoundManager::drawSubtitle(SubtitleEntry *subtitle) { - // Remove subtitle from queue - _subtitles.remove(subtitle); - - if (subtitle == _currentSubtitle) { - drawSubtitleOnScreen(subtitle); - - _currentSubtitle = NULL; - _drawSubtitles = 0; - } -} - -void SoundManager::drawSubtitleOnScreen(SubtitleEntry *subtitle) { - if (!subtitle) - error("SoundManager::drawSubtitleOnScreen: Invalid subtitle entry!"); - - _drawSubtitles &= ~1; - - if (subtitle->data == NULL) - return; - - if (_drawSubtitles & 1) - _engine->getGraphicsManager()->draw(subtitle->data, GraphicsManager::kBackgroundOverlay); -} - ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index a87bb9bb80..b2a1b4387b 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -107,6 +107,14 @@ public: // Accessors uint32 getFlag() { return _flag; } + int getSubtitleFlag() { return _subtitlesFlag; } + void setSubtitleFlag(int flag) { _subtitlesFlag = flag; } + + // Subtitles + void addSubtitle(SubtitleEntry *entry) { _subtitles.push_back(entry); } + void removeSubtitle(SubtitleEntry *entry) { _subtitles.remove(entry); } + void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } + SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } private: typedef int32 *SoundBuffer; @@ -161,15 +169,9 @@ private: void removeEntry(SoundEntry *entry); // Subtitles - int _drawSubtitles; + int _subtitlesFlag; Common::List _subtitles; SubtitleEntry *_currentSubtitle; - void showSubtitle(SoundEntry *entry, Common::String filename); - SubtitleEntry *loadSubtitle(Common::String filename, SoundEntry *soundEntry); - void loadSubtitleData(SubtitleEntry * entry); - void setupSubtitleAndDraw(SubtitleEntry *subtitle); - void drawSubtitle(SubtitleEntry *subtitle); - void drawSubtitleOnScreen(SubtitleEntry *subtitle); // Sound filter void applyFilter(SoundEntry *entry, int16 *buffer); diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 309996886a..848e728ba4 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -24,8 +24,10 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" #include "common/stream.h" @@ -35,7 +37,6 @@ namespace LastExpress { // SoundEntry ////////////////////////////////////////////////////////////////////////// SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { - status.status = 0; type = kSoundTypeNone; currentDataPtr = 0; @@ -135,17 +136,95 @@ void SoundEntry::reset() { } } +void SoundEntry::showSubtitle(Common::String filename) { + subtitle = new SubtitleEntry(_engine); + subtitle->load(filename, this); + + if (subtitle->getStatus().status2 & 4) { + subtitle->draw(); + SAFE_DELETE(subtitle); + } else { + status.status |= kSoundStatus_20000; + } +} + ////////////////////////////////////////////////////////////////////////// // SubtitleEntry ////////////////////////////////////////////////////////////////////////// -SubtitleEntry::SubtitleEntry() { - status.status = 0; - sound = NULL; - data = NULL; +SubtitleEntry::SubtitleEntry(LastExpressEngine *engine) : _engine(engine) { + _sound = NULL; + _data = NULL; } SubtitleEntry::~SubtitleEntry() { - SAFE_DELETE(data); + SAFE_DELETE(_data); +} + +void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) { + // Add ourselves to the list of active subtitles + getSound()->addSubtitle(this); + + // Set sound entry and filename + _filename = filename + ".SBE"; + _sound = soundEntry; + + // Load subtitle data + if (_engine->getResourceManager()->hasFile(filename)) { + if (getSound()->getSubtitleFlag() & 2) + return; + + loadData(); + } else { + _status.status = kSoundStatus_400; + } +} + +void SubtitleEntry::loadData() { + _data = new SubtitleManager(_engine->getFont()); + _data->load(getArchive(_filename)); + + getSound()->setSubtitleFlag(getSound()->getSubtitleFlag() | 2); + getSound()->setCurrentSubtitle(this); +} + +void SubtitleEntry::setupAndDraw() { + if (!_data) { + _data = new SubtitleManager(_engine->getFont()); + _data->load(getArchive(_filename)); + } + + if (_data->getMaxTime() > _sound->time) { + _status.status = kSoundStatus_400; + } else { + _data->setTime((uint16)_sound->time); + + if (getSound()->getSubtitleFlag() & 1) + drawOnScreen(); + } + + getSound()->setCurrentSubtitle(this); +} + +void SubtitleEntry::draw() { + // Remove ourselves from the queue + getSound()->removeSubtitle(this); + + if (this == getSound()->getCurrentSubtitle()) { + drawOnScreen(); + + getSound()->setCurrentSubtitle(NULL); + getSound()->setSubtitleFlag(0); + } +} + +void SubtitleEntry::drawOnScreen() { + getSound()->setSubtitleFlag(getSound()->getSubtitleFlag() & -1); + + if (_data == NULL) + return; + + if (getSound()->getSubtitleFlag() & 1) + _engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay); } } // End of namespace LastExpress diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 9ed091b225..5671e0e74b 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -120,6 +120,9 @@ public: void updateState(); void reset(); + // Subtitles + void showSubtitle(Common::String filename); + private: LastExpressEngine *_engine; @@ -158,14 +161,26 @@ public: ////////////////////////////////////////////////////////////////////////// class SubtitleEntry { public: - SubtitleEntry(); + SubtitleEntry(LastExpressEngine *engine); ~SubtitleEntry(); -public: - Common::String filename; - SoundStatusUnion status; - SoundEntry *sound; - SubtitleManager *data; + void load(Common::String filename, SoundEntry *soundEntry); + void loadData(); + void draw(); + void setupAndDraw(); + void drawOnScreen(); + + // Accessors + SoundStatusUnion getStatus() { return _status; } + SoundEntry *getSoundEntry() { return _sound; } + +private: + LastExpressEngine *_engine; + + Common::String _filename; + SoundStatusUnion _status; + SoundEntry *_sound; + SubtitleManager *_data; }; } // End of namespace LastExpress -- cgit v1.2.3 From 73d2d34e01fb929d5ed9af08646c9474ec5150ed Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 25 Jun 2011 14:50:07 +0300 Subject: LASTEXPRESS: Give proper name to another sound struct member --- engines/lastexpress/game/sound.cpp | 14 +++++++------- engines/lastexpress/game/sound.h | 2 +- engines/lastexpress/sound/entry.cpp | 2 +- engines/lastexpress/sound/entry.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index adb82816f5..c95ef85701 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -255,11 +255,11 @@ bool SoundManager::isBuffered(Common::String filename, bool testForEntity) { ////////////////////////////////////////////////////////////////////////// // Entry ////////////////////////////////////////////////////////////////////////// -void SoundManager::setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int a4) { +void SoundManager::setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int priority) { if (!entry) error("SoundManager::setupEntry: Invalid entry!"); - entry->field_4C = a4; + entry->priority = priority; setEntryType(entry, flag); entry->setStatus(flag); @@ -354,7 +354,7 @@ bool SoundManager::setupCache(SoundEntry *entry) { for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { if (!((*i)->status.status & kSoundStatus_180)) { - uint32 newSize = (*i)->field_4C + ((*i)->status.status & kSoundStatusClear1); + uint32 newSize = (*i)->priority + ((*i)->status.status & kSoundStatusClear1); if (newSize < size) { cacheEntry = (*i); @@ -363,7 +363,7 @@ bool SoundManager::setupCache(SoundEntry *entry) { } } - if (entry->field_4C <= size) + if (entry->priority <= size) return false; if (!cacheEntry) @@ -574,7 +574,7 @@ void SoundManager::saveLoadWithSerializer(Common::Serializer &s) { blockCount = 0; s.syncAsUint32LE(blockCount); // blockCount; - s.syncAsUint32LE(entry->field_4C); // field_20; + s.syncAsUint32LE(entry->priority); // field_20; char name1[16]; strcpy((char *)&name1, entry->name1.c_str()); @@ -1769,10 +1769,10 @@ void SoundManager::updateSubtitles() { || status & 0x180 || soundEntry->time == 0 || (status & 0x1F) < 6 - || ((getFlags()->nis & 0x8000) && soundEntry->field_4C < 90)) { + || ((getFlags()->nis & 0x8000) && soundEntry->priority < 90)) { current_index = 0; } else { - current_index = soundEntry->field_4C + (status & 0x1F); + current_index = soundEntry->priority + (status & 0x1F); if (_currentSubtitle == (*i)) current_index += 4; diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index b2a1b4387b..e7b06609a9 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -161,7 +161,7 @@ private: SoundEntry *getEntry(Common::String name); SoundEntry *getEntry(SoundType type); - void setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int a4); + void setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int priority); void setEntryType(SoundEntry *entry, SoundFlag flag); bool setupCache(SoundEntry *entry); void removeFromCache(SoundEntry *entry); diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 848e728ba4..67549cb5fe 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -53,7 +53,7 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { field_40 = 0; entity = kEntityPlayer; field_48 = 0; - field_4C = 0; + priority = 0; subtitle = NULL; diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 5671e0e74b..84a2342cf3 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -146,7 +146,7 @@ public: int field_40; EntityIndex entity; int field_48; - uint32 field_4C; + uint32 priority; Common::String name1; //char[16]; Common::String name2; //char[16]; //int next; // offset to the next structure in the list (not used) -- cgit v1.2.3 From 3f43619ea8b5b80b7211467ec27abc45de152ff2 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Sun, 26 Jun 2011 14:34:56 -0400 Subject: LASTEXPRESS: Add detection entry for Russian version --- engines/lastexpress/detection.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/detection.cpp b/engines/lastexpress/detection.cpp index de80e75341..0a177809dd 100644 --- a/engines/lastexpress/detection.cpp +++ b/engines/lastexpress/detection.cpp @@ -127,7 +127,7 @@ static const ADGameDescription gameDescriptions[] = { "lastexpress", "", { - {"HD.HPF", 0, "7cdd70fc0b1555785f1e9e8d371ea85c", 31301632}, // 1997-04-08 14:33:42 + {"HD.HPF", 0, "7cdd70fc0b1555785f1e9e8d371ea85c", 31301632}, // 1997-04-08 14:33:42 {"CD1.HPF", 0, "6d74cc861d172466bc745ff8bf0e59c5", 522971136}, // 1997-04-08 13:05:56 {"CD2.HPF", 0, "b71ac9391de415807c74ff078f4fab22", 655702016}, // 1997-04-08 15:26:14 {"CD3.HPF", 0, "ee55d4310546dd2a38560b096d1c2771", 641144832}, // 1997-04-05 18:35:50 @@ -163,7 +163,7 @@ static const ADGameDescription gameDescriptions[] = { "lastexpress", "", { - {"HD.HPF", 0, "5539e78fd7eecb70bc858e86b5709fe9", 29562880}, // 1997-12-11 14:11:52 + {"HD.HPF", 0, "5539e78fd7eecb70bc858e86b5709fe9", 29562880}, // 1997-12-11 14:11:52 {"CD1.HPF", 0, "3c1c80b41f2c454b7b89dcb32648796c", 522328064}, // 1997-12-11 14:39:46 {"CD2.HPF", 0, "ea6414d5a718501cfd55de3884f4431d", 665411584}, // 1997-12-11 15:20:26 {"CD3.HPF", 0, "a5bd5b58acddbd951d4551f68de22025", 637718528}, // 1997-12-11 15:58:44 @@ -173,6 +173,24 @@ static const ADGameDescription gameDescriptions[] = { ADGF_UNSTABLE, Common::GUIO_NONE }, + + // The Last Express (Russian) + // expressw.exe 1999-04-05 15:33:56 + // express.exe ??? + { + "lastexpress", + "", + { + {"HD.HPF", 0, "a9e915c20f3231c5a1ac4455286971bb", 29908992}, // 1999-04-08 12:43:56 + {"CD1.HPF", 0, "80fbb95c9228353436b7b38e4b5bb64d", 525805568}, // 1999-04-07 13:30:14 + {"CD2.HPF", 0, "a1c8c344754e03eaa86eaabc6024709e", 677289984}, // 1999-04-07 16:19:56 + {"CD3.HPF", 0, "ea5adac447e59ea6d4a1737abad46480", 642584576}, // 1999-04-07 17:26:18 + }, + Common::RU_RUS, + Common::kPlatformUnknown, + ADGF_UNSTABLE, + Common::GUIO_NONE + }, AD_TABLE_END_MARKER }; -- cgit v1.2.3 From d1341387e3c396aa6b48b39379afc9e201448048 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 28 Jun 2011 20:09:56 -0400 Subject: LASTEXPRESS: Move more entry-related functions to Entry class --- engines/lastexpress/game/sound.cpp | 258 ++++++++---------------------------- engines/lastexpress/game/sound.h | 18 ++- engines/lastexpress/sound/entry.cpp | 254 ++++++++++++++++++++++++++++------- engines/lastexpress/sound/entry.h | 97 ++++++++------ 4 files changed, 325 insertions(+), 302 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index c95ef85701..3fb3f8894d 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -161,15 +161,15 @@ void SoundManager::handleTimer() { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { SoundEntry *entry = (*i); - if (entry->stream == NULL) { + if (entry->_stream == NULL) { SAFE_DELETE(*i); i = _soundList.reverse_erase(i); continue; - } else if (!entry->soundStream) { - entry->soundStream = new StreamedSound(); + } else if (!entry->_soundStream) { + entry->_soundStream = new StreamedSound(); // TODO: stream any sound in the queue after filtering - entry->soundStream->load(entry->stream); + entry->_soundStream->load(entry->_stream); } } } @@ -189,7 +189,7 @@ void SoundManager::resetQueue(SoundType type1, SoundType type2) { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->type != type1 && (*i)->type != type2) + if ((*i)->getType() != type1 && (*i)->getType() != type2) (*i)->reset(); } } @@ -226,7 +226,7 @@ void SoundManager::clearQueue() { SoundEntry *entry = (*i); // Delete entry - removeEntry(entry); + entry->close(); SAFE_DELETE(entry); i = _soundList.reverse_erase(i); @@ -247,7 +247,7 @@ bool SoundManager::isBuffered(Common::String filename, bool testForEntity) { SoundEntry *entry = getEntry(filename); if (testForEntity) - return entry != NULL && !entry->entity; + return entry != NULL && entry->getEntity() != kEntityPlayer; return (entry != NULL); } @@ -255,96 +255,8 @@ bool SoundManager::isBuffered(Common::String filename, bool testForEntity) { ////////////////////////////////////////////////////////////////////////// // Entry ////////////////////////////////////////////////////////////////////////// -void SoundManager::setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int priority) { - if (!entry) - error("SoundManager::setupEntry: Invalid entry!"); - - entry->priority = priority; - setEntryType(entry, flag); - entry->setStatus(flag); - - // Add entry to sound list - _soundList.push_back(entry); - - // TODO Add entry to cache and load sound data - //setupCache(entry); - loadSoundData(entry, name); -} - -void SoundManager::setEntryType(SoundEntry *entry, SoundFlag flag) { - switch (flag & kFlagType9) { - default: - case kFlagNone: - entry->type = _currentType; - _currentType = (SoundType)(_currentType + 1); - break; - - case kFlagType1_2: { - SoundEntry *previous2 = getEntry(kSoundType2); - if (previous2) - previous2->update(0); - - SoundEntry *previous = getEntry(kSoundType1); - if (previous) { - previous->type = kSoundType2; - previous->update(0); - } - - entry->type = kSoundType1; - } - break; - - case kFlagType3: { - SoundEntry *previous = getEntry(kSoundType3); - if (previous) { - previous->type = kSoundType4; - previous->update(0); - } - - entry->type = kSoundType11; - } - break; - - case kFlagType7: { - SoundEntry *previous = getEntry(kSoundType7); - if (previous) - previous->type = kSoundType8; - - entry->type = kSoundType7; - } - break; - - case kFlagType9: { - SoundEntry *previous = getEntry(kSoundType9); - if (previous) - previous->type = kSoundType10; - - entry->type = kSoundType9; - } - break; - - case kFlagType11: { - SoundEntry *previous = getEntry(kSoundType11); - if (previous) - previous->type = kSoundType14; - - entry->type = kSoundType11; - } - break; - - case kFlagType13: { - SoundEntry *previous = getEntry(kSoundType13); - if (previous) - previous->type = kSoundType14; - - entry->type = kSoundType13; - } - break; - } -} - bool SoundManager::setupCache(SoundEntry *entry) { - if (entry->soundData) + if (entry->_soundData) return true; if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) { @@ -353,8 +265,8 @@ bool SoundManager::setupCache(SoundEntry *entry) { uint32 size = 1000; for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if (!((*i)->status.status & kSoundStatus_180)) { - uint32 newSize = (*i)->priority + ((*i)->status.status & kSoundStatusClear1); + if (!((*i)->_status.status & kSoundStatus_180)) { + uint32 newSize = (*i)->_priority + ((*i)->_status.status & kSoundStatusClear1); if (newSize < size) { cacheEntry = (*i); @@ -363,7 +275,7 @@ bool SoundManager::setupCache(SoundEntry *entry) { } } - if (entry->priority <= size) + if (entry->_priority <= size) return false; if (!cacheEntry) @@ -372,17 +284,17 @@ bool SoundManager::setupCache(SoundEntry *entry) { cacheEntry->setInCache(); // TODO: Wait until the cache entry is ready to be removed - while (!(cacheEntry->status.status1 & 1)) + while (!(cacheEntry->_status.status1 & 1)) ; - if (cacheEntry->soundData) + if (cacheEntry->_soundData) removeFromCache(cacheEntry); _soundCache.push_back(entry); - entry->soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); + entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); } else { _soundCache.push_back(entry); - entry->soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); + entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); } return true; @@ -392,7 +304,7 @@ void SoundManager::removeFromCache(SoundEntry *entry) { for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { if ((*i) == entry) { // Remove sound buffer - entry->soundData = NULL; + entry->_soundData = NULL; // Remove entry from sound cache i = _soundCache.reverse_erase(i); @@ -404,48 +316,7 @@ void SoundManager::clearStatus() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->status.status |= kSoundStatusClear3; -} - -void SoundManager::loadSoundData(SoundEntry *entry, Common::String name) { - entry->name2 = name; - - // Load sound data - entry->stream = getArchive(name); - - if (!entry->stream) - entry->stream = getArchive("DEFAULT.SND"); - - if (entry->stream) { - warning("Sound::loadSoundData: not implemented!"); - } else { - entry->status.status = kSoundStatusRemoved; - } -} - -void SoundManager::removeEntry(SoundEntry *entry) { - entry->status.status |= kSoundStatusRemoved; - - // Loop until ready - while (!(entry->status.status1 & 4) && !(_flag & 8) && (_flag & 1)) - ; // empty loop body - - // The original game remove the entry from the cache here, - // but since we are called from within an iterator loop - // we will remove the entry there - // removeFromCache(entry); - - if (entry->subtitle) { - entry->subtitle->draw(); - SAFE_DELETE(entry->subtitle); - } - - if (entry->entity) { - if (entry->entity == kEntitySteam) - playLoopingSound(2); - else if (entry->entity != kEntityTrain) - getSavePoints()->push(kEntityPlayer, entry->entity, kActionEndSound); - } + (*i)->_status.status |= kSoundStatusClear3; } void SoundManager::processEntry(EntityIndex entity) { @@ -454,7 +325,7 @@ void SoundManager::processEntry(EntityIndex entity) { SoundEntry *entry = getEntry(entity); if (entry) { entry->update(0); - entry->entity = kEntityPlayer; + entry->setEntity(kEntityPlayer); } } @@ -471,7 +342,7 @@ void SoundManager::setupEntry(SoundType type, EntityIndex index) { SoundEntry *entry = getEntry(type); if (entry) - entry->entity = index; + entry->setEntity(index); } void SoundManager::processEntry(Common::String filename) { @@ -480,7 +351,7 @@ void SoundManager::processEntry(Common::String filename) { SoundEntry *entry = getEntry(filename); if (entry) { entry->update(0); - entry->entity = kEntityPlayer; + entry->setEntity(kEntityPlayer); } } @@ -496,7 +367,7 @@ uint32 SoundManager::getEntryTime(EntityIndex index) { SoundEntry *entry = getEntry(index); if (entry) - return entry->time; + return entry->_time; return 0; } @@ -515,7 +386,7 @@ void SoundManager::unknownFunction4() { ////////////////////////////////////////////////////////////////////////// SoundEntry *SoundManager::getEntry(EntityIndex index) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->entity == index) + if ((*i)->getEntity() == index) return *i; } @@ -527,7 +398,7 @@ SoundEntry *SoundManager::getEntry(Common::String name) { name += ".SND"; for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->name2 == name) + if ((*i)->_name2 == name) return *i; } @@ -536,7 +407,7 @@ SoundEntry *SoundManager::getEntry(Common::String name) { SoundEntry *SoundManager::getEntry(SoundType type) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->type == type) + if ((*i)->getType() == type) return *i; } @@ -547,6 +418,8 @@ SoundEntry *SoundManager::getEntry(SoundType type) { // Savegame ////////////////////////////////////////////////////////////////////////// void SoundManager::saveLoadWithSerializer(Common::Serializer &s) { + Common::StackLock locker(_mutex); + s.syncAsUint32LE(_state); s.syncAsUint32LE(_currentType); @@ -554,39 +427,12 @@ void SoundManager::saveLoadWithSerializer(Common::Serializer &s) { uint32 numEntries = count(); s.syncAsUint32LE(numEntries); - Common::StackLock locker(_mutex); - // Save or load each entry data if (s.isSaving()) { - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - SoundEntry *entry = *i; - if (entry->name2.matchString("NISSND?") && (entry->status.status & kFlagType7) != kFlag3) { - s.syncAsUint32LE(entry->status.status); // status; - s.syncAsUint32LE(entry->type); // type; - s.syncAsUint32LE(entry->blockCount); // field_8; - s.syncAsUint32LE(entry->time); // time; - s.syncAsUint32LE(entry->field_34); // field_10; - s.syncAsUint32LE(entry->field_38); // field_14; - s.syncAsUint32LE(entry->entity); // entity; - - uint32 blockCount = (uint32)entry->field_48 - _data2; - if (blockCount > kFlag8) - blockCount = 0; - s.syncAsUint32LE(blockCount); // blockCount; - - s.syncAsUint32LE(entry->priority); // field_20; - - char name1[16]; - strcpy((char *)&name1, entry->name1.c_str()); - s.syncBytes((byte *)&name1, 16); - - char name2[16]; - strcpy((char *)&name2, entry->name2.c_str()); - s.syncBytes((byte *)&name2, 16); - } - } + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + (*i)->saveLoadWithSerializer(s); } else { - warning("Sound::saveLoadWithSerializer: not implemented!"); + warning("Sound::saveLoadWithSerializer: loading not implemented"); s.skip(numEntries * 64); } } @@ -600,7 +446,7 @@ uint32 SoundManager::count() { uint32 numEntries = 0; for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - if ((*i)->name2.matchString("NISSND?")) + if ((*i)->_name2.matchString("NISSND?")) ++numEntries; return numEntries; @@ -629,12 +475,12 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla Common::StackLock locker(_mutex); - setupEntry(entry, filename, flag, 30); - entry->entity = entity; + entry->open(filename, flag, 30); + entry->_entity = entity; if (a4) { - entry->field_48 = _data2 + 2 * a4; - entry->status.status |= kSoundStatus_8000; + entry->_field_48 = _data2 + 2 * a4; + entry->_status.status |= kSoundStatus_8000; } else { // Get subtitles name while (filename.size() > 4) @@ -644,7 +490,7 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla entry->updateState(); } - return (entry->type != kSoundTypeNone); + return (entry->getType() != kSoundTypeNone); } void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { @@ -1763,16 +1609,16 @@ void SoundManager::updateSubtitles() { for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { uint32 current_index = 0; SoundEntry *soundEntry = (*i)->getSoundEntry(); - SoundStatus status = (SoundStatus)soundEntry->status.status; + SoundStatus status = (SoundStatus)soundEntry->_status.status; if (!(status & kSoundStatus_40) - || status & 0x180 - || soundEntry->time == 0 - || (status & 0x1F) < 6 - || ((getFlags()->nis & 0x8000) && soundEntry->priority < 90)) { + || status & kSoundStatus_180 + || soundEntry->_time == 0 + || (status & kSoundStatusClear1) < 6 + || ((getFlags()->nis & 0x8000) && soundEntry->_priority < 90)) { current_index = 0; } else { - current_index = soundEntry->priority + (status & 0x1F); + current_index = soundEntry->_priority + (status & kSoundStatusClear1); if (_currentSubtitle == (*i)) current_index += 4; @@ -1808,15 +1654,15 @@ void SoundManager::playLoopingSound(int param) { char tmp[80]; for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { - if ((*snd)->type == kSoundType1) + if ((*snd)->getType() == kSoundType1) break; } byte numLoops[8]; static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, - kPosition_6470, kPosition_5790, - kPosition_4840, kPosition_4070, - kPosition_3050, kPosition_2740 }; + kPosition_6470, kPosition_5790, + kPosition_4840, kPosition_4070, + kPosition_3050, kPosition_2740 }; numLoops[1] = 4; numLoops[2] = 2; @@ -1889,7 +1735,7 @@ void SoundManager::playLoopingSound(int param) { if (getFlags()->flag_3) fnameLen = 5; - if (!*snd || scumm_strnicmp((*snd)->name2.c_str(), tmp, fnameLen)) { + if (!*snd || scumm_strnicmp((*snd)->_name2.c_str(), tmp, fnameLen)) { _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; if (partNumber != 99) { @@ -1899,7 +1745,7 @@ void SoundManager::playLoopingSound(int param) { (*snd)->update(0); for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { - if ((*snd)->type == kSoundType1) { + if ((*snd)->getType() == kSoundType1) { (*snd)->update(7); break; } @@ -1913,7 +1759,7 @@ void SoundManager::stopAllSound() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->soundStream->stop(); + (*i)->_soundStream->stop(); } ////////////////////////////////////////////////////////////////////////// @@ -2232,12 +2078,12 @@ static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, static void soundFilter(byte *data, int16 *buffer, int p1, int p2); void SoundManager::applyFilter(SoundEntry *entry, int16 *buffer) { - if ((((byte *)entry->soundData)[1] << 6) > 0x1600) { - entry->status.status |= 0x20000000; + if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) { + entry->_status.status |= 0x20000000; } else { - int variant = entry->status.status & 0x1f; + int variant = entry->_status.status & 0x1f; - soundFilter((byte *)entry->soundData, buffer, p1s[variant], p2s[variant]); + soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]); } } diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index e7b06609a9..414fb0d028 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -84,6 +84,8 @@ public: void playLocomotiveSound(); void playWarningCompartment(EntityIndex entity, ObjectIndex compartment); + void playLoopingSound(int param); + // Dialog & Letters void readText(int id); const char *getDialogName(EntityIndex entity) const; @@ -109,6 +111,9 @@ public: uint32 getFlag() { return _flag; } int getSubtitleFlag() { return _subtitlesFlag; } void setSubtitleFlag(int flag) { _subtitlesFlag = flag; } + SoundType getCurrentType() { return _currentType; } + void setCurrentType(SoundType type) { _currentType = type; } + uint32 getData2() { return _data2; } // Subtitles void addSubtitle(SubtitleEntry *entry) { _subtitles.push_back(entry); } @@ -116,6 +121,12 @@ public: void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } + // Queue + bool setupCache(SoundEntry *entry); + void addToQueue(SoundEntry *entry) { _soundList.push_back(entry); } + + SoundEntry *getEntry(SoundType type); + private: typedef int32 *SoundBuffer; @@ -149,7 +160,6 @@ private: uint32 _lastWarning[12]; // Looping sound - void playLoopingSound(int param); int _loopingSoundDuration; // Sound entries @@ -159,14 +169,8 @@ private: SoundEntry *getEntry(EntityIndex index); SoundEntry *getEntry(Common::String name); - SoundEntry *getEntry(SoundType type); - void setupEntry(SoundEntry *entry, Common::String name, SoundFlag flag, int priority); - void setEntryType(SoundEntry *entry, SoundFlag flag); - bool setupCache(SoundEntry *entry); void removeFromCache(SoundEntry *entry); - void loadSoundData(SoundEntry *entry, Common::String name); - void removeEntry(SoundEntry *entry); // Subtitles int _subtitlesFlag; diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 67549cb5fe..304d524f45 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -22,7 +22,10 @@ #include "lastexpress/sound/entry.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/savepoint.h" #include "lastexpress/game/sound.h" +#include "lastexpress/game/state.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" @@ -37,114 +40,267 @@ namespace LastExpress { // SoundEntry ////////////////////////////////////////////////////////////////////////// SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { - type = kSoundTypeNone; + _type = kSoundTypeNone; - currentDataPtr = 0; - soundData = NULL; + _currentDataPtr = 0; + _soundData = NULL; - blockCount = 0; - time = 0; + _blockCount = 0; + _time = 0; - stream = NULL; + _stream = NULL; - field_34 = 0; - field_38 = 0; - field_3C = 0; - field_40 = 0; - entity = kEntityPlayer; - field_48 = 0; - priority = 0; + _field_34 = 0; + _field_38 = 0; + _field_3C = 0; + _field_40 = 0; + _entity = kEntityPlayer; + _field_48 = 0; + _priority = 0; - subtitle = NULL; + _subtitle = NULL; - soundStream = NULL; + _soundStream = NULL; } SoundEntry::~SoundEntry() { // Entries that have been queued would have their streamed disposed automatically - if (!soundStream) - SAFE_DELETE(stream); + if (!_soundStream) + SAFE_DELETE(_stream); - delete soundStream; + delete _soundStream; _engine = NULL; } +void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { + _priority = priority; + setType(flag); + setStatus(flag); + + // Add entry to sound list + getSound()->addToQueue(this); + + // Add entry to cache and load sound data + getSound()->setupCache(this); + loadSoundData(name); +} + +void SoundEntry::close() { + _status.status |= kSoundStatusRemoved; + + // Loop until ready + while (!(_status.status1 & 4) && !(getSound()->getFlag() & 8) && (getSound()->getFlag() & 1)) + ; // empty loop body + + // The original game remove the entry from the cache here, + // but since we are called from within an iterator loop + // we will remove the entry there + // removeFromCache(entry); + + if (_subtitle) { + _subtitle->draw(); + SAFE_DELETE(_subtitle); + } + + if (_entity) { + if (_entity == kEntitySteam) + getSound()->playLoopingSound(2); + else if (_entity != kEntityTrain) + getSavePoints()->push(kEntityPlayer, _entity, kActionEndSound); + } +} + +void SoundEntry::setType(SoundFlag flag) { + switch (flag & kFlagType9) { + default: + case kFlagNone: + _type = getSound()->getCurrentType(); + getSound()->setCurrentType((SoundType)(_type + 1)); + break; + + case kFlagType1_2: { + SoundEntry *previous2 = getSound()->getEntry(kSoundType2); + if (previous2) + previous2->update(0); + + SoundEntry *previous = getSound()->getEntry(kSoundType1); + if (previous) { + previous->setType(kSoundType2); + previous->update(0); + } + + _type = kSoundType1; + } + break; + + case kFlagType3: { + SoundEntry *previous = getSound()->getEntry(kSoundType3); + if (previous) { + previous->setType(kSoundType4); + previous->update(0); + } + + _type = kSoundType11; + } + break; + + case kFlagType7: { + SoundEntry *previous = getSound()->getEntry(kSoundType7); + if (previous) + previous->setType(kSoundType8); + + _type = kSoundType7; + } + break; + + case kFlagType9: { + SoundEntry *previous = getSound()->getEntry(kSoundType9); + if (previous) + previous->setType(kSoundType10); + + _type = kSoundType9; + } + break; + + case kFlagType11: { + SoundEntry *previous = getSound()->getEntry(kSoundType11); + if (previous) + previous->setType(kSoundType14); + + _type = kSoundType11; + } + break; + + case kFlagType13: { + SoundEntry *previous = getSound()->getEntry(kSoundType13); + if (previous) + previous->setType(kSoundType14); + + _type = kSoundType13; + } + break; + } +} + void SoundEntry::setStatus(SoundFlag flag) { SoundStatus statusFlag = (SoundStatus)flag; if (!((statusFlag & 0xFF) & kSoundStatusClear1)) statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0) - status.status = (uint32)statusFlag; + _status.status = (uint32)statusFlag; else - status.status = (statusFlag | kSoundStatusClear4); + _status.status = (statusFlag | kSoundStatusClear4); } void SoundEntry::setInCache() { - status.status |= kSoundStatusClear2; + _status.status |= kSoundStatusClear2; +} + +void SoundEntry::loadSoundData(Common::String name) { + _name2 = name; + + // Load sound data + _stream = getArchive(name); + + if (!_stream) + _stream = getArchive("DEFAULT.SND"); + + if (_stream) { + warning("Sound::loadSoundData: not implemented!"); + } else { + _status.status = kSoundStatusRemoved; + } } void SoundEntry::update(uint val) { - if (!(status.status3 & 64)) { + if (!(_status.status3 & 64)) { int value2 = val; - status.status |= kSoundStatus_100000; + _status.status |= kSoundStatus_100000; if (val) { if (getSound()->getFlag() & 32) { - field_40 = val; + _field_40 = val; value2 = val * 2 + 1; } - field_3C = value2; + _field_3C = value2; } else { - field_3C = 0; - status.status |= kSoundStatus_40000000; + _field_3C = 0; + _status.status |= kSoundStatus_40000000; } } } void SoundEntry::updateState() { if (getSound()->getFlag() & 32) { - if (type != kSoundType9 && type != kSoundType7 && type != kSoundType5) { - uint32 newStatus = status.status & kSoundStatusClear1; + if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { + uint32 newStatus = _status.status & kSoundStatusClear1; - status.status &= kSoundStatusClearAll; + _status.status &= kSoundStatusClearAll; - field_40 = newStatus; - status.status |= newStatus * 2 + 1; + _field_40 = newStatus; + _status.status |= newStatus * 2 + 1; } } - status.status |= kSoundStatus_20; + _status.status |= kSoundStatus_20; } void SoundEntry::reset() { - status.status |= kSoundStatusRemoved; - entity = kEntityPlayer; + _status.status |= kSoundStatusRemoved; + _entity = kEntityPlayer; - if (stream) { - if (!soundStream) { - SAFE_DELETE(stream); + if (_stream) { + if (!_soundStream) { + SAFE_DELETE(_stream); } else { - soundStream->stop(); - SAFE_DELETE(soundStream); + _soundStream->stop(); + SAFE_DELETE(_soundStream); } - stream = NULL; + _stream = NULL; } } void SoundEntry::showSubtitle(Common::String filename) { - subtitle = new SubtitleEntry(_engine); - subtitle->load(filename, this); + _subtitle = new SubtitleEntry(_engine); + _subtitle->load(filename, this); - if (subtitle->getStatus().status2 & 4) { - subtitle->draw(); - SAFE_DELETE(subtitle); + if (_subtitle->getStatus().status2 & 4) { + _subtitle->draw(); + SAFE_DELETE(_subtitle); } else { - status.status |= kSoundStatus_20000; + _status.status |= kSoundStatus_20000; + } +} + +void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { + if (_name2.matchString("NISSND?") && (_status.status & kFlagType7) != kFlag3) { + s.syncAsUint32LE(_status.status); + s.syncAsUint32LE(_type); + s.syncAsUint32LE(_blockCount); // field_8; + s.syncAsUint32LE(_time); + s.syncAsUint32LE(_field_34); // field_10; + s.syncAsUint32LE(_field_38); // field_14; + s.syncAsUint32LE(_entity); + + uint32 delta = (uint32)_field_48 - getSound()->getData2(); + if (delta > kFlag8) + delta = 0; + s.syncAsUint32LE(delta); + + s.syncAsUint32LE(_priority); + + char name1[16]; + strcpy((char *)&name1, _name1.c_str()); + s.syncBytes((byte *)&name1, 16); + + char name2[16]; + strcpy((char *)&name2, _name2.c_str()); + s.syncBytes((byte *)&name2, 16); } } @@ -193,10 +349,10 @@ void SubtitleEntry::setupAndDraw() { _data->load(getArchive(_filename)); } - if (_data->getMaxTime() > _sound->time) { + if (_data->getMaxTime() > _sound->_time) { _status.status = kSoundStatus_400; } else { - _data->setTime((uint16)_sound->time); + _data->setTime((uint16)_sound->_time); if (getSound()->getSubtitleFlag() & 1) drawOnScreen(); diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 84a2342cf3..929d3463d5 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -24,30 +24,30 @@ #define LASTEXPRESS_SOUND_ENTRY_H /* - Sound entry: 68 bytes (this is what appears in the savegames) - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? + Sound entry: 68 bytes (this is what appears in savegames) + uint32 {4} - status + uint32 {4} - type + uint32 {4} - blockCount + uint32 {4} - time uint32 {4} - ?? uint32 {4} - ?? uint32 {4} - entity uint32 {4} - ?? - uint32 {4} - ?? + uint32 {4} - priority char {16} - name 1 char {16} - name 2 Sound queue entry: 120 bytes uint16 {2} - status + byte {1} - type byte {1} - ?? - byte {1} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - ?? - uint32 {4} - file data pointer - uint32 {4} - ?? - uint32 {4} - ?? uint32 {4} - ?? + uint32 {4} - currentDataPtr + uint32 {4} - soundData + uint32 {4} - currentBufferPtr + uint32 {4} - blockCount + uint32 {4} - time + uint32 {4} - size uint32 {4} - ?? uint32 {4} - archive structure pointer uint32 {4} - ?? @@ -57,7 +57,7 @@ uint32 {4} - ?? uint32 {4} - entity uint32 {4} - ?? - uint32 {4} - ?? + uint32 {4} - priority char {16} - name 1 char {16} - name 2 uint32 {4} - pointer to next entry in the queue @@ -69,6 +69,8 @@ #include "lastexpress/shared.h" +#include "common/serializer.h" + namespace LastExpress { class LastExpressEngine; @@ -109,13 +111,18 @@ union SoundStatusUnion { ////////////////////////////////////////////////////////////////////////// // SoundEntry ////////////////////////////////////////////////////////////////////////// -class SoundEntry { +class SoundEntry : Common::Serializable { public: SoundEntry(LastExpressEngine *engine); ~SoundEntry(); + void open(Common::String name, SoundFlag flag, int priority); + void close(); + void setStatus(SoundFlag flag); + void setType(SoundFlag flag); void setInCache(); + void loadSoundData(Common::String name); void update(uint val); void updateState(); void reset(); @@ -123,37 +130,47 @@ public: // Subtitles void showSubtitle(Common::String filename); + // Serializable + void saveLoadWithSerializer(Common::Serializer &ser); + + // Accessors + void setType(SoundType type) { _type = type; } + SoundType getType() { return _type; } + + void setEntity(EntityIndex entity) { _entity = entity; } + EntityIndex getEntity() { return _entity; } + private: LastExpressEngine *_engine; public: - SoundStatusUnion status; - SoundType type; // int - //int data; - //int endOffset; - int currentDataPtr; - void *soundData; - //int currentBufferPtr; - int blockCount; - uint32 time; - //int size; - //int field_28; - Common::SeekableReadStream *stream; // int - //int field_30; - int field_34; - int field_38; - int field_3C; - int field_40; - EntityIndex entity; - int field_48; - uint32 priority; - Common::String name1; //char[16]; - Common::String name2; //char[16]; - //int next; // offset to the next structure in the list (not used) - SubtitleEntry *subtitle; + SoundStatusUnion _status; + SoundType _type; // int + //int _data; + //int _endOffset; + int _currentDataPtr; + void *_soundData; + //int _currentBufferPtr; + int _blockCount; + uint32 _time; + //int _size; + //int _field_28; + Common::SeekableReadStream *_stream; // int + //int _field_30; + int _field_34; + int _field_38; + int _field_3C; + int _field_40; + EntityIndex _entity; + int _field_48; + uint32 _priority; + Common::String _name1; //char[16]; + Common::String _name2; //char[16]; + // original has pointer to the next structure in the list (not used) + SubtitleEntry *_subtitle; // Sound stream - StreamedSound *soundStream; + StreamedSound *_soundStream; }; ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 6eace0ca759bc62b6b0b6cf69a4341b4d1bb43e4 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 28 Jun 2011 22:10:29 -0400 Subject: LASTEXPRESS: Move sound queue related functions to a separate class - Implement missing queue reset function - Cleanup SoundManager::playLoopingSound() --- engines/lastexpress/debug.cpp | 6 +- engines/lastexpress/entities/abbot.cpp | 6 +- engines/lastexpress/entities/anna.cpp | 48 +- engines/lastexpress/entities/august.cpp | 18 +- engines/lastexpress/entities/boutarel.cpp | 4 +- engines/lastexpress/entities/chapters.cpp | 112 ++-- engines/lastexpress/entities/cooks.cpp | 6 +- engines/lastexpress/entities/coudert.cpp | 22 +- engines/lastexpress/entities/francois.cpp | 12 +- engines/lastexpress/entities/kahina.cpp | 14 +- engines/lastexpress/entities/kronos.cpp | 14 +- engines/lastexpress/entities/mahmud.cpp | 18 +- engines/lastexpress/entities/max.cpp | 46 +- engines/lastexpress/entities/mertens.cpp | 16 +- engines/lastexpress/entities/milos.cpp | 22 +- engines/lastexpress/entities/mmeboutarel.cpp | 8 +- engines/lastexpress/entities/pascale.cpp | 14 +- engines/lastexpress/entities/rebecca.cpp | 4 +- engines/lastexpress/entities/salko.cpp | 6 +- engines/lastexpress/entities/tables.cpp | 12 +- engines/lastexpress/entities/tatiana.cpp | 26 +- engines/lastexpress/entities/train.cpp | 16 +- engines/lastexpress/entities/vassili.cpp | 4 +- engines/lastexpress/entities/verges.cpp | 26 +- engines/lastexpress/fight/fight.cpp | 12 +- engines/lastexpress/fight/fighter_anna.cpp | 6 +- engines/lastexpress/fight/fighter_ivo.cpp | 6 +- engines/lastexpress/fight/fighter_milos.cpp | 6 +- engines/lastexpress/fight/fighter_salko.cpp | 6 +- engines/lastexpress/fight/fighter_vesna.cpp | 6 +- engines/lastexpress/game/action.cpp | 48 +- engines/lastexpress/game/entities.cpp | 8 +- engines/lastexpress/game/inventory.cpp | 8 +- engines/lastexpress/game/logic.cpp | 16 +- engines/lastexpress/game/savegame.cpp | 10 +- engines/lastexpress/game/scenes.cpp | 12 +- engines/lastexpress/game/sound.cpp | 803 ++------------------------- engines/lastexpress/game/sound.h | 119 +--- engines/lastexpress/helpers.h | 1 + engines/lastexpress/lastexpress.cpp | 8 +- engines/lastexpress/menu/menu.cpp | 38 +- engines/lastexpress/module.mk | 1 + engines/lastexpress/shared.h | 6 + engines/lastexpress/sound/entry.cpp | 55 +- engines/lastexpress/sound/queue.cpp | 795 ++++++++++++++++++++++++++ engines/lastexpress/sound/queue.h | 131 +++++ 46 files changed, 1379 insertions(+), 1202 deletions(-) create mode 100644 engines/lastexpress/sound/queue.cpp create mode 100644 engines/lastexpress/sound/queue.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index d5c7df0e55..2d22630381 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -44,6 +44,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -793,7 +795,7 @@ bool Debugger::cmdFight(int argc, const char **argv) { restoreArchive(); // Stop audio and restore scene - getSound()->stopAllSound(); + getSoundQueue()->stopAllSound(); clearBg(GraphicsManager::kBackgroundAll); @@ -925,7 +927,7 @@ bool Debugger::cmdBeetle(int argc, const char **argv) { restoreArchive(); // Stop audio and restore scene - getSound()->stopAllSound(); + getSoundQueue()->stopAllSound(); clearBg(GraphicsManager::kBackgroundAll); diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp index 112edec9af..6fcadcfa54 100644 --- a/engines/lastexpress/entities/abbot.cpp +++ b/engines/lastexpress/entities/abbot.cpp @@ -34,6 +34,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -1409,7 +1411,7 @@ IMPLEMENT_FUNCTION(43, Abbot, function43) setup_playSound("Abb4002"); break; } else { - if (!getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 1000) || getSound()->isBuffered(kEntityBoutarel) || !params->param4) + if (!getEntities()->isDistanceBetweenEntities(kEntityAbbot, kEntityPlayer, 1000) || getSoundQueue()->isBuffered(kEntityBoutarel) || !params->param4) params->param4 = (uint)getState()->time + 450; if (params->param4 < getState()->time) { @@ -1754,7 +1756,7 @@ IMPLEMENT_FUNCTION(49, Abbot, pickBomb) break; case kActionKnock: - if (!getSound()->isBuffered("LIB012", true)) + if (!getSoundQueue()->isBuffered("LIB012", true)) getSound()->playSound(kEntityPlayer, "LIB012"); break; diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp index d794cc8520..2eb3a9ec85 100644 --- a/engines/lastexpress/entities/anna.cpp +++ b/engines/lastexpress/entities/anna.cpp @@ -34,6 +34,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -312,7 +314,7 @@ IMPLEMENT_FUNCTION(12, Anna, function12) params->param4 = 0; params->param5 = 0; } else { - getSound()->removeFromQueue(kEntityAnna); + getSoundQueue()->removeFromQueue(kEntityAnna); getObjects()->update(kObjectCompartmentF, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); getObjects()->update(kObject53, kEntityAnna, kObjectLocation1, kCursorNormal, kCursorNormal); @@ -323,7 +325,7 @@ IMPLEMENT_FUNCTION(12, Anna, function12) break; case kActionOpenDoor: - getSound()->removeFromQueue(kEntityAnna); + getSoundQueue()->removeFromQueue(kEntityAnna); setCallback(3); setup_playSound("LIB013"); break; @@ -339,8 +341,8 @@ IMPLEMENT_FUNCTION(12, Anna, function12) getEntities()->drawSequenceLeft(kEntityAnna, "418C"); - if (getSound()->isBuffered(kEntityAnna)) - getSound()->processEntry(kEntityAnna); + if (getSoundQueue()->isBuffered(kEntityAnna)) + getSoundQueue()->processEntry(kEntityAnna); getSound()->playSound(kEntityAnna, "ANN2135A"); break; @@ -379,7 +381,7 @@ IMPLEMENT_FUNCTION(12, Anna, function12) break; case 3: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(4); setup_playSound("MAX1120"); break; @@ -503,7 +505,7 @@ IMPLEMENT_FUNCTION_IS(15, Anna, function15, TimeValue) break; case 1: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(2); setup_playSound("MAX1120"); break; @@ -1456,7 +1458,7 @@ label_callback_1: case 2: case 3: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(4); setup_playSound("MAX1120"); break; @@ -1521,8 +1523,8 @@ IMPLEMENT_FUNCTION(35, Anna, function35) case kActionKnock: case kActionOpenDoor: - if (getSound()->isBuffered(kEntityAnna)) - getSound()->processEntry(kEntityAnna); + if (getSoundQueue()->isBuffered(kEntityAnna)) + getSoundQueue()->processEntry(kEntityAnna); if (savepoint.action == kActionKnock) getSound()->playSound(kEntityPlayer, "LIB012"); @@ -1564,8 +1566,8 @@ IMPLEMENT_FUNCTION(35, Anna, function35) break; case kAction226031488: - if (getSound()->isBuffered(kEntityAnna)) - getSound()->processEntry(kEntityAnna); + if (getSoundQueue()->isBuffered(kEntityAnna)) + getSoundQueue()->processEntry(kEntityAnna); getSavePoints()->push(kEntityAnna, kEntityMax, kAction71277948); break; @@ -1844,7 +1846,7 @@ IMPLEMENT_FUNCTION(41, Anna, function41) case 1: case 2: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(3); setup_playSound("MAX1120"); break; @@ -2090,7 +2092,7 @@ IMPLEMENT_FUNCTION(48, Anna, function48) break; if (params->param3 != kTimeInvalid && getState()->time > kTime1969200) { - UPDATE_PARAM_PROC_TIME(kTime1983600, (!getEntities()->isInRestaurant(kEntityPlayer) || getSound()->isBuffered(kEntityBoutarel)), params->param3, 150) + UPDATE_PARAM_PROC_TIME(kTime1983600, (!getEntities()->isInRestaurant(kEntityPlayer) || getSoundQueue()->isBuffered(kEntityBoutarel)), params->param3, 150) setCallback(3); setup_playSound("Aug3007A"); break; @@ -2481,7 +2483,7 @@ IMPLEMENT_FUNCTION(53, Anna, function53) break; case 1: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(2); setup_playSound("MAX1120"); break; @@ -2620,7 +2622,7 @@ IMPLEMENT_FUNCTION(54, Anna, function54) break; case 1: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { setCallback(2); setup_playSound("MAX1120"); break; @@ -2789,7 +2791,7 @@ IMPLEMENT_FUNCTION(57, Anna, function57) break; case 4: - if (getSound()->isBuffered(kEntityAugust)) { + if (getSoundQueue()->isBuffered(kEntityAugust)) { setCallback(4); setup_updateFromTime(75); } else { @@ -2817,7 +2819,7 @@ IMPLEMENT_FUNCTION(57, Anna, function57) case kAction123712592: getEntities()->drawSequenceLeft(kEntityAnna, "628Af"); - if (getSound()->isBuffered(kEntityAugust)) { + if (getSoundQueue()->isBuffered(kEntityAugust)) { setCallback(4); setup_updateFromTime(75); } else { @@ -3158,8 +3160,8 @@ IMPLEMENT_FUNCTION(63, Anna, function63) // Anna will get killed... case kAction272177921: - if (getSound()->isBuffered("MUS012")) - getSound()->processEntry("MUS012"); + if (getSoundQueue()->isBuffered("MUS012")) + getSoundQueue()->processEntry("MUS012"); setCallback(1); setup_savegame(kSavegameTypeEvent, kEventAnnaKilled); @@ -3935,8 +3937,8 @@ IMPLEMENT_FUNCTION(80, Anna, function80) break; case 1: - if (getSound()->isBuffered(kEntityAnna)) - getSound()->processEntry(kEntityAnna); + if (getSoundQueue()->isBuffered(kEntityAnna)) + getSoundQueue()->processEntry(kEntityAnna); getAction()->playAnimation(kEventKronosBringFirebird); getScenes()->loadSceneFromItem(kItemFirebird); @@ -3951,8 +3953,8 @@ IMPLEMENT_FUNCTION(80, Anna, function80) case 3: getProgress().isEggOpen = true; - if (getSound()->isBuffered(kEntityAnna)) - getSound()->processEntry(kEntityAnna); + if (getSoundQueue()->isBuffered(kEntityAnna)) + getSoundQueue()->processEntry(kEntityAnna); getAction()->playAnimation(kEventKronosOpenFirebird); getScenes()->loadSceneFromPosition(kCarRestaurant, 3); diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp index fbd50d64fb..44dd3eb579 100644 --- a/engines/lastexpress/entities/august.cpp +++ b/engines/lastexpress/entities/august.cpp @@ -36,6 +36,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -1427,7 +1429,7 @@ IMPLEMENT_FUNCTION(29, August, function29) if (getState()->time < kTime1134000) { if (!getEntities()->isInRestaurant(kEntityPlayer) - || getSound()->isBuffered("MRB1076") || getSound()->isBuffered("MRB1078") || getSound()->isBuffered("MRB1078A")) + || getSoundQueue()->isBuffered("MRB1076") || getSoundQueue()->isBuffered("MRB1078") || getSoundQueue()->isBuffered("MRB1078A")) params->param3 = (uint)getState()->time + 225; if (params->param3 > getState()->time) @@ -1762,7 +1764,7 @@ IMPLEMENT_FUNCTION(34, August, function34) break; case kActionNone: - if (!getSound()->isBuffered(kEntityAugust) && getProgress().field_18 != 4) + if (!getSoundQueue()->isBuffered(kEntityAugust) && getProgress().field_18 != 4) getSound()->playSound(kEntityAugust, "AUG1057"); // August snoring break; @@ -2183,7 +2185,7 @@ IMPLEMENT_FUNCTION_III(42, August, function42, CarIndex, EntityPosition, bool) break; case kActionExcuseMe: - if (!getSound()->isBuffered(kEntityAugust)) + if (!getSoundQueue()->isBuffered(kEntityAugust)) getSound()->excuseMe(kEntityAugust); break; @@ -3343,7 +3345,7 @@ IMPLEMENT_FUNCTION(65, August, function65) getObjects()->update(kObjectCompartment3, kEntityPlayer, kObjectLocation1, kCursorHandKnock, kCursorHand); - if (!getSound()->isBuffered(kEntityAugust)) + if (!getSoundQueue()->isBuffered(kEntityAugust)) getSound()->playSound(kEntityAugust, "AUG1057"); // August snoring break; } @@ -3504,9 +3506,9 @@ IMPLEMENT_FUNCTION(69, August, unhookCars) break; case kActionDefault: - getSound()->processEntries(); - if (getSound()->isBuffered("ARRIVE")) - getSound()->removeFromQueue("ARRIVE"); + getSoundQueue()->processEntries(); + if (getSoundQueue()->isBuffered("ARRIVE")) + getSoundQueue()->removeFromQueue("ARRIVE"); setCallback(1); setup_savegame(kSavegameTypeEvent, kEventAugustUnhookCarsBetrayal); @@ -3516,7 +3518,7 @@ IMPLEMENT_FUNCTION(69, August, unhookCars) if (getCallback() == 1) { getAction()->playAnimation(getProgress().field_C ? kEventAugustUnhookCarsBetrayal : kEventAugustUnhookCars); getEntities()->clearSequences(kEntityAugust); - getSound()->resetState(); + getSoundQueue()->resetState(); getSound()->playSound(kEntityPlayer, "MUS050"); getScenes()->loadSceneFromPosition(kCarRestaurant, 85, 1); getSavePoints()->pushAll(kEntityAugust, kActionProceedChapter5); diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp index db7761784f..cf5d286d64 100644 --- a/engines/lastexpress/entities/boutarel.cpp +++ b/engines/lastexpress/entities/boutarel.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -941,7 +943,7 @@ IMPLEMENT_FUNCTION(29, Boutarel, function29) if (getEntities()->isInRestaurant(kEntityAnna) && getEntities()->isInRestaurant(kEntityAugust) - && !getSound()->isBuffered(kEntityBoutarel) + && !getSoundQueue()->isBuffered(kEntityBoutarel) && params->param3 != kTimeInvalid) { if (getState()->time <= kTime1998000) diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp index d4425ada43..53d89e9699 100644 --- a/engines/lastexpress/entities/chapters.cpp +++ b/engines/lastexpress/entities/chapters.cpp @@ -65,6 +65,8 @@ #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -164,16 +166,16 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) break; case kActionKnock: - if (!getSound()->isBuffered("LIB012", true)) + if (!getSoundQueue()->isBuffered("LIB012", true)) getSound()->playSound(kEntityPlayer, "LIB012"); break; case kActionOpenDoor: if (params->param1) { getEntities()->clearSequences(kEntityChapters); - getSound()->processEntry(kEntityChapters); + getSoundQueue()->processEntry(kEntityChapters); getSound()->playSound(kEntityPlayer, "LIB014"); - getSound()->resetState(); + getSoundQueue()->resetState(); ENTITY_PARAM(0, 4) = 7; @@ -194,7 +196,7 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) getSound()->playSound(kEntityPlayer, "LIB014"); getSound()->playSound(kEntityPlayer, "LIB015", kFlagDefault, 15); - if (!getSound()->isBuffered(kEntityChapters)) + if (!getSoundQueue()->isBuffered(kEntityChapters)) getSound()->playSound(kEntityChapters, "MUS009", kFlagDefault); getScenes()->loadSceneFromPosition(kCarLocomotive, 38); @@ -241,42 +243,42 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) RESET_ENTITY_STATE(kEntityHadija, Alouan, setup_function12); if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } - getSound()->processEntries(); + getSoundQueue()->processEntries(); - if (getSound()->isBuffered("CON1505")) - getSound()->processEntry("CON1505"); + if (getSoundQueue()->isBuffered("CON1505")) + getSoundQueue()->processEntry("CON1505"); - if (getSound()->isBuffered("AUG1057")) - getSound()->processEntry("AUG1057"); + if (getSoundQueue()->isBuffered("AUG1057")) + getSoundQueue()->processEntry("AUG1057"); - if (getSound()->isBuffered("ZFX1005")) - getSound()->processEntry("ZFX1005"); + if (getSoundQueue()->isBuffered("ZFX1005")) + getSoundQueue()->processEntry("ZFX1005"); - if (getSound()->isBuffered("ZFX1006")) - getSound()->processEntry("ZFX1006"); + if (getSoundQueue()->isBuffered("ZFX1006")) + getSoundQueue()->processEntry("ZFX1006"); - if (getSound()->isBuffered("ZFX1007")) - getSound()->processEntry("ZFX1007"); + if (getSoundQueue()->isBuffered("ZFX1007")) + getSoundQueue()->processEntry("ZFX1007"); - if (getSound()->isBuffered("ZFX1007A")) - getSound()->processEntry("ZFX1007A"); + if (getSoundQueue()->isBuffered("ZFX1007A")) + getSoundQueue()->processEntry("ZFX1007A"); - if (getSound()->isBuffered("ZFX1007B")) - getSound()->processEntry("ZFX1007B"); + if (getSoundQueue()->isBuffered("ZFX1007B")) + getSoundQueue()->processEntry("ZFX1007B"); getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); // FIXME add event pump ? - while (getSound()->isBuffered("MUS008")) - getSound()->updateQueue(); + while (getSoundQueue()->isBuffered("MUS008")) + getSoundQueue()->updateQueue(); getProgress().field_84 = true; @@ -301,7 +303,7 @@ IMPLEMENT_FUNCTION(6, Chapters, chapter1End) if (params->param2 >= 3) { - if (!getSound()->isBuffered("LIB031", true)) + if (!getSoundQueue()->isBuffered("LIB031", true)) getSound()->playSound(kEntityPlayer, "LIB031"); if (params->param2 == 3) { @@ -319,7 +321,7 @@ IMPLEMENT_FUNCTION(7, Chapters, chapter1Init) return; getProgress().chapter = kChapter1; - getSound()->resetState(); + getSoundQueue()->resetState(); getState()->time = kTimeChapter1; getState()->timeDelta = 0; @@ -385,7 +387,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// #define PLAY_STEAM() { \ - getSound()->resetState(); \ + getSoundQueue()->resetState(); \ getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4)); \ ENTITY_PARAM(0, 2) = 0; \ } @@ -563,7 +565,7 @@ label_chapter1_next: } if (ENTITY_PARAM(0, 3)) { - getSound()->resetState(); + getSoundQueue()->resetState(); ENTITY_PARAM(0, 3) = 0; if (params->param4) { @@ -694,7 +696,7 @@ IMPLEMENT_FUNCTION(9, Chapters, chapter1Next) if (savepoint.action == kActionDefault) { // Reset sound cache if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } @@ -702,8 +704,8 @@ IMPLEMENT_FUNCTION(9, Chapters, chapter1Next) getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); - while (getSound()->isBuffered("MUS008")) - getSound()->updateQueue(); + while (getSoundQueue()->isBuffered("MUS008")) + getSoundQueue()->updateQueue(); setup_chapter2(); } @@ -790,7 +792,7 @@ IMPLEMENT_FUNCTION(11, Chapters, chapter2Init) // Reset sound cache if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } @@ -874,7 +876,7 @@ IMPLEMENT_FUNCTION(14, Chapters, chapter3Init) getObjects()->update(kObject107, kEntityPlayer, kObjectLocation3, kCursorKeepValue, kCursorKeepValue); if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } @@ -987,7 +989,7 @@ label_callback_8: } } - getSound()->resetState(); + getSoundQueue()->resetState(); getSound()->playSteam((CityIndex)ENTITY_PARAM(0, 4)); ENTITY_PARAM(0, 2) = 0; @@ -998,7 +1000,7 @@ label_callback_8: } if (ENTITY_PARAM(0, 3)) { - getSound()->resetState(); + getSoundQueue()->resetState(); ENTITY_PARAM(0, 3) = 0; } break; @@ -1150,8 +1152,8 @@ IMPLEMENT_FUNCTION(18, Chapters, chapter4Init) if (savepoint.action != kActionDefault) return; - getSound()->processEntries(); - getSound()->resetState(); + getSoundQueue()->processEntries(); + getSoundQueue()->resetState(); getProgress().isTrainRunning = true; @@ -1177,7 +1179,7 @@ IMPLEMENT_FUNCTION(18, Chapters, chapter4Init) getObjects()->update(kObject107, kEntityPlayer, kObjectLocation3, kCursorKeepValue, kCursorKeepValue); if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } @@ -1319,7 +1321,7 @@ label_callback_4: } if (ENTITY_PARAM(0, 3)) { - getSound()->resetState(); + getSoundQueue()->resetState(); ENTITY_PARAM(0, 3) = 0; } else if (!params->param2 && !params->param3) { getSound()->playSound(kEntityChapters, "ZFX1001"); @@ -1356,17 +1358,17 @@ label_callback_4: goto label_callback_4; case 5: - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); getAction()->playAnimation(kEventTrainExplosionBridge); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneNone, true); break; case 6: - getSound()->processEntries(); + getSoundQueue()->processEntries(); getAction()->playAnimation(kEventTylerCastleDream); - getSound()->resetState(); + getSoundQueue()->resetState(); getProgress().field_18 = 1; @@ -1465,7 +1467,7 @@ label_callback_4: params->param1 = 1; if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; @@ -1474,8 +1476,8 @@ label_callback_4: getSound()->playSound(kEntityPlayer, "MUS008", kFlagDefault); getInventory()->unselectItem(); - while (getSound()->isBuffered("MUS008")) - getSound()->updateQueue(); + while (getSoundQueue()->isBuffered("MUS008")) + getSoundQueue()->updateQueue(); if (getInventory()->hasItem(kItemBomb)) { RESET_ENTITY_STATE(kEntityAlexei, Alexei, setup_function47); @@ -1522,8 +1524,8 @@ label_callback_4: case kAction191001984: getState()->time = kTime2520000; - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); getEntities()->clearSequences(kEntityChapters); getInventory()->removeItem(kItemTelegram); @@ -1535,8 +1537,8 @@ label_callback_4: break; case kAction201959744: - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); getSound()->playSound(kEntityTrain, "ZFX4001", kFlagDefault); @@ -1644,7 +1646,7 @@ IMPLEMENT_FUNCTION(21, Chapters, chapter5Init) getObjects()->updateLocation2(kObjectRestaurantCar, kObjectLocation2); if (ENTITY_PARAM(0, 2) || ENTITY_PARAM(0, 3)) { - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); ENTITY_PARAM(0, 2) = 0; ENTITY_PARAM(0, 3) = 0; } @@ -1675,7 +1677,7 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) if (!getProgress().isNightTime) { getSound()->playSound(kEntityChapters, "ARRIVE", kFlag8); - getSound()->processEntries(); + getSoundQueue()->processEntries(); } } @@ -1684,7 +1686,7 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) if (!getEvent(kEventLocomotiveMilosDay) && !getEvent(kEventLocomotiveMilosNight)) { getSound()->playSound(kEntityChapters, "ARRIVE", kFlag8); - getSound()->processEntries(); + getSoundQueue()->processEntries(); } } break; @@ -1713,8 +1715,8 @@ IMPLEMENT_FUNCTION(22, Chapters, chapter5Handler) getProgress().isNightTime = true; getState()->time = kTime2916000; - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); break; } IMPLEMENT_FUNCTION_END @@ -1730,7 +1732,7 @@ void Chapters::enterExitStation(const SavePoint &savepoint, bool isEnteringStati return; } - getSound()->removeFromQueue(kEntityChapters); + getSoundQueue()->removeFromQueue(kEntityChapters); if (!ENTITY_PARAM(0, 2)) { if (ENTITY_PARAM(0, 3)) @@ -1798,7 +1800,7 @@ void Chapters::enterExitHelper(bool isEnteringStation) { EXPOSE_PARAMS(EntityData::EntityParametersSIIS); getSound()->playSound(kEntityChapters, isEnteringStation ? "ARRIVE" : "DEPART", kFlag8); - getSound()->processEntries(); + getSoundQueue()->processEntries(); getObjects()->update(kObjectHandleOutsideLeft, kEntityPlayer, kObjectLocation1, kCursorNormal, isEnteringStation ? kCursorNormal : kCursorHand); getObjects()->update(kObjectHandleOutsideRight, kEntityPlayer, kObjectLocation1, kCursorNormal, isEnteringStation ? kCursorNormal : kCursorHand); diff --git a/engines/lastexpress/entities/cooks.cpp b/engines/lastexpress/entities/cooks.cpp index 336f911800..cd8fbfd8ff 100644 --- a/engines/lastexpress/entities/cooks.cpp +++ b/engines/lastexpress/entities/cooks.cpp @@ -29,6 +29,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -101,7 +103,7 @@ IMPLEMENT_FUNCTION(3, Cooks, function3) if (getEntities()->isPlayerPosition(kCarRestaurant, 46)) { getEntities()->drawSequenceLeft(kEntityCooks, "308D"); - if (!getSound()->isBuffered(kEntityCooks)) { + if (!getSoundQueue()->isBuffered(kEntityCooks)) { if (params->param1) { if (!getEntities()->hasValidFrame(kEntityCooks)) { getSound()->playSound(kEntityCooks, "LIB015"); @@ -187,7 +189,7 @@ IMPLEMENT_FUNCTION(4, Cooks, function4) if (getEntities()->isPlayerPosition(kCarRestaurant, 80)) { getEntities()->drawSequenceLeft(kEntityCooks, "308D"); - if (!getSound()->isBuffered(kEntityCooks)) { + if (!getSoundQueue()->isBuffered(kEntityCooks)) { if (params->param1) { if (!getEntities()->hasValidFrame(kEntityCooks)) { getSound()->playSound(kEntityCooks, "LIB015"); diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp index 0733a4c984..fea08f4611 100644 --- a/engines/lastexpress/entities/coudert.cpp +++ b/engines/lastexpress/entities/coudert.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -314,7 +316,7 @@ IMPLEMENT_FUNCTION_II(9, Coudert, updateEntity, CarIndex, EntityPosition) case kActionExcuseMeCath: if (getData()->clothes == kClothes1) getSound()->playSound(kEntityPlayer, "ZFX1003", getSound()->getSoundFlag(kEntityCoudert)); - else if (!getSound()->isBuffered(kEntityCoudert)) + else if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityPlayer, "JAC1112", getSound()->getSoundFlag(kEntityCoudert)); break; @@ -409,7 +411,7 @@ IMPLEMENT_FUNCTION_I(12, Coudert, excuseMe, EntityIndex) if (savepoint.action != kActionDefault) return; - if (getSound()->isBuffered(kEntityCoudert)) { + if (getSoundQueue()->isBuffered(kEntityCoudert)) { CALLBACK_ACTION(); return; } @@ -823,7 +825,7 @@ IMPLEMENT_FUNCTION(18, Coudert, function18) getScenes()->loadSceneFromItemPosition(kItem5); if (getEntities()->isPlayerPosition(kCarRedSleeping, 68)) { - if (!getSound()->isBuffered(kEntityCoudert)) + if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, "JAC1111"); getScenes()->loadSceneFromPosition(kCarRedSleeping, 25); @@ -1642,7 +1644,7 @@ IMPLEMENT_FUNCTION_I(31, Coudert, function31, uint32) break; case 1: - if (getSound()->isBuffered(kEntityCoudert)) { + if (getSoundQueue()->isBuffered(kEntityCoudert)) { getEntities()->drawSequenceLeft(kEntityCoudert, "627K"); } else { setCallback(2); @@ -1929,7 +1931,7 @@ IMPLEMENT_FUNCTION_I(35, Coudert, function35, bool) break; case 1: - if (!getSound()->isBuffered(kEntityCoudert)) + if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, "Ann3124"); if (params->param1) @@ -2008,8 +2010,8 @@ IMPLEMENT_FUNCTION(37, Coudert, function37) break; case kActionDefault: - if (getSound()->isBuffered(kEntityCoudert)) - getSound()->processEntry(kEntityCoudert); + if (getSoundQueue()->isBuffered(kEntityCoudert)) + getSoundQueue()->processEntry(kEntityCoudert); if (ENTITY_PARAM(0, 7)) { getData()->entityPosition = kPosition_8200; @@ -2268,7 +2270,7 @@ label_callback_8: } label_callback_9: - if (ENTITY_PARAM(0, 1) && !getSound()->isBuffered(kEntityCoudert)) + if (ENTITY_PARAM(0, 1) && !getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, rnd(2) ? "JAC1065" : "JAC1065A"); if (getState()->time > kTime1107000 && !ENTITY_PARAM(0, 1) && !getEvent(kEventVassiliSeizure)) { @@ -3019,7 +3021,7 @@ IMPLEMENT_FUNCTION(46, Coudert, function46) // Fallback to next case case 7: - if (getSound()->isBuffered(kEntityCoudert)) { + if (getSoundQueue()->isBuffered(kEntityCoudert)) { setCallback(7); setup_updateFromTime(75); } else { @@ -3088,7 +3090,7 @@ IMPLEMENT_FUNCTION_I(47, Coudert, function47, bool) // Fallback to next case case 4: - if (getSound()->isBuffered(kEntityCoudert)) { + if (getSoundQueue()->isBuffered(kEntityCoudert)) { setCallback(4); setup_updateFromTime(225); } else { diff --git a/engines/lastexpress/entities/francois.cpp b/engines/lastexpress/entities/francois.cpp index 86b6820499..6bbe740730 100644 --- a/engines/lastexpress/entities/francois.cpp +++ b/engines/lastexpress/entities/francois.cpp @@ -30,6 +30,8 @@ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -275,7 +277,7 @@ IMPLEMENT_FUNCTION_I(11, Francois, function11, TimeValue) break; case kActionNone: - if (!getSound()->isBuffered(kEntityFrancois)) { + if (!getSoundQueue()->isBuffered(kEntityFrancois)) { UPDATE_PARAM_PROC(CURRENT_PARAM(1, 1), getState()->timeTicks, params->param6) switch (rnd(7)) { @@ -370,8 +372,8 @@ label_callback: getData()->field_4A3 = 30; getData()->inventoryItem = kItemNone; - if (getSound()->isBuffered(kEntityFrancois)) - getSound()->processEntry(kEntityFrancois); + if (getSoundQueue()->isBuffered(kEntityFrancois)) + getSoundQueue()->processEntry(kEntityFrancois); setCallback(4); setup_updateEntity(kCarRedSleeping, kPosition_5790); @@ -381,8 +383,8 @@ label_callback: case kAction1: getData()->inventoryItem = kItemNone; - if (getSound()->isBuffered(kEntityFrancois)) - getSound()->processEntry(kEntityFrancois); + if (getSoundQueue()->isBuffered(kEntityFrancois)) + getSoundQueue()->processEntry(kEntityFrancois); setCallback(6); setup_savegame(kSavegameTypeEvent, kEventFrancoisWhistle); diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp index db71981b60..6c73784b21 100644 --- a/engines/lastexpress/entities/kahina.cpp +++ b/engines/lastexpress/entities/kahina.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -607,8 +609,8 @@ label_callback_3: break; if (getEvent(kEventKahinaAskSpeakFirebird)) { - if (getSound()->isBuffered(kEntityKahina)) - getSound()->processEntry(kEntityKahina); + if (getSoundQueue()->isBuffered(kEntityKahina)) + getSoundQueue()->processEntry(kEntityKahina); if (savepoint.action == kActionKnock) getSound()->playSound(kEntityPlayer, "LIB012"); @@ -1163,8 +1165,8 @@ IMPLEMENT_FUNCTION(24, Kahina, function24) case 1: if (ENTITY_PARAM(0, 2)) { getEntities()->clearSequences(kEntityKahina); - if (getSound()->isBuffered(kEntityKahina)) - getSound()->processEntry(kEntityKahina); + if (getSoundQueue()->isBuffered(kEntityKahina)) + getSoundQueue()->processEntry(kEntityKahina); getProgress().field_44 = 0; @@ -1198,8 +1200,8 @@ IMPLEMENT_FUNCTION(24, Kahina, function24) case kAction137503360: getEntities()->clearSequences(kEntityKahina); - if (getSound()->isBuffered(kEntityKahina)) - getSound()->processEntry(kEntityKahina); + if (getSoundQueue()->isBuffered(kEntityKahina)) + getSoundQueue()->processEntry(kEntityKahina); getProgress().field_44 = 0; diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp index 5afc52fe3d..06ebd54694 100644 --- a/engines/lastexpress/entities/kronos.cpp +++ b/engines/lastexpress/entities/kronos.cpp @@ -39,6 +39,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -216,7 +218,7 @@ IMPLEMENT_FUNCTION(11, Kronos, function11) case kActionDefault: getData()->entityPosition = kPosition_7000; - if (!getSound()->isBuffered(kEntityKronos)) + if (!getSoundQueue()->isBuffered(kEntityKronos)) getSound()->playSound(kEntityKronos, "KRO1001"); break; } @@ -457,7 +459,7 @@ IMPLEMENT_FUNCTION(19, Kronos, function19) case 2: getAction()->playAnimation(kEventConcertStart); - getSound()->setupEntry(kSoundType7, kEntityKronos); + getSoundQueue()->setupEntry(kSoundType7, kEntityKronos); getScenes()->loadSceneFromPosition(kCarKronos, 83); RESET_ENTITY_STATE(kEntityRebecca, Rebecca, setup_function39); @@ -480,7 +482,7 @@ IMPLEMENT_FUNCTION(20, Kronos, function20) break; case kActionNone: - params->param5 = getSound()->getEntryTime(kEntityKronos)* 2; + params->param5 = getSoundQueue()->getEntryTime(kEntityKronos)* 2; if (params->param6 < ARRAYSIZE(concertData) && params->param5 > concertData[params->param6].time) { @@ -560,8 +562,8 @@ IMPLEMENT_FUNCTION(20, Kronos, function20) case 3: getAction()->playAnimation(kEventCathFallingAsleep); - while (getSound()->isBuffered("1919.LNK")) - getSound()->updateQueue(); + while (getSoundQueue()->isBuffered("1919.LNK")) + getSoundQueue()->updateQueue(); getAction()->playAnimation(kEventCathWakingUp); getScenes()->processScene(); @@ -746,7 +748,7 @@ IMPLEMENT_FUNCTION(22, Kronos, function22) case kActionKnock: case kActionOpenDoor: - if (!getSound()->isBuffered(savepoint.action == kActionKnock ? "LIB012" : "LIB013", true)) + if (!getSoundQueue()->isBuffered(savepoint.action == kActionKnock ? "LIB012" : "LIB013", true)) getSound()->playSound(kEntityPlayer, savepoint.action == kActionKnock ? "LIB012" : "LIB013"); if (getEvent(kEventConcertLeaveWithBriefcase)) diff --git a/engines/lastexpress/entities/mahmud.cpp b/engines/lastexpress/entities/mahmud.cpp index f9ae741d0e..cb782854af 100644 --- a/engines/lastexpress/entities/mahmud.cpp +++ b/engines/lastexpress/entities/mahmud.cpp @@ -34,6 +34,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -157,7 +159,7 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) case kActionEndSound: case kActionDrawScene: - if (!getSound()->isBuffered(kEntityMahmud)) { + if (!getSoundQueue()->isBuffered(kEntityMahmud)) { EntityPosition position = getEntityData(kEntityPlayer)->entityPosition; if (position < kPosition_1500 || position >= kPosition_5790 || (position > kPosition_4455 && params->param5 != 5)) { getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); @@ -173,12 +175,12 @@ IMPLEMENT_FUNCTION_II(10, Mahmud, function10, ObjectIndex, bool) case kActionKnock: case kActionOpenDoor: - if (!getSound()->isBuffered((savepoint.action == kActionKnock) ? "LIB012" : "LIB013", true)) + if (!getSoundQueue()->isBuffered((savepoint.action == kActionKnock) ? "LIB012" : "LIB013", true)) getSound()->playSound(kEntityPlayer, (savepoint.action == kActionKnock) ? "LIB012" : "LIB013"); params->param5 = savepoint.param.intValue; - if (!getSound()->isBuffered(kEntityMahmud)) { + if (!getSoundQueue()->isBuffered(kEntityMahmud)) { params->param3++; switch(params->param3) { @@ -282,7 +284,7 @@ IMPLEMENT_FUNCTION(11, Mahmud, function11) case kActionOpenDoor: { getSound()->playSound(kEntityPlayer, (savepoint.action == kActionKnock ? "LIB012" : "LIB013")); - if (!getSound()->isBuffered(kEntityMahmud)) { + if (!getSoundQueue()->isBuffered(kEntityMahmud)) { params->param1++; getSound()->playSound(kEntityMahmud, (params->param1 == 1 ? "MAH1170E" : (params->param1 == 2 ? "MAH1173B" : "MAH1174"))); @@ -396,8 +398,8 @@ IMPLEMENT_FUNCTION(11, Mahmud, function11) break; case kAction123852928: - if (getSound()->isBuffered(kEntityMahmud)) - getSound()->processEntry(kEntityMahmud); + if (getSoundQueue()->isBuffered(kEntityMahmud)) + getSoundQueue()->processEntry(kEntityMahmud); getObjects()->update(kObjectCompartment5, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectCompartment6, kEntityTrain, kObjectLocation3, kCursorHandKnock, kCursorHand); @@ -560,7 +562,7 @@ IMPLEMENT_FUNCTION(14, Mahmud, chaptersHandler) TIME_CHECK_CALLBACK(kTime1098000, params->param6, 1, setup_function13); - if (!getSound()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { + if (!getSoundQueue()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { params->param7 = 1; setCallback(2); @@ -636,7 +638,7 @@ IMPLEMENT_FUNCTION(14, Mahmud, chaptersHandler) params->param4 = 0; params->param5 = 0; - if (!getSound()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { + if (!getSoundQueue()->isBuffered("HAR1104") && getState()->time > kTime1167300 && !params->param7) { params->param7 = 1; setCallback(2); setup_function12(); diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp index 12123ed04a..924f8f77aa 100644 --- a/engines/lastexpress/entities/max.cpp +++ b/engines/lastexpress/entities/max.cpp @@ -31,6 +31,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -91,7 +93,7 @@ IMPLEMENT_FUNCTION(6, Max, chapter12_handler) case kActionNone: UPDATE_PARAM(params->param2, getState()->time, params->param1); - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); @@ -108,7 +110,7 @@ IMPLEMENT_FUNCTION(6, Max, chapter12_handler) break; case kAction158007856: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); } @@ -125,7 +127,7 @@ IMPLEMENT_FUNCTION(7, Max, function7) case kActionNone: UPDATE_PARAM(params->param2, getState()->time, params->param1) - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); @@ -137,8 +139,8 @@ IMPLEMENT_FUNCTION(7, Max, function7) getObjects()->update(kObjectCompartmentF, kEntityMax, kObjectLocation1, kCursorNormal, kCursorNormal); getObjects()->update(kObject53, kEntityMax, kObjectLocation1, kCursorNormal, kCursorNormal); - if (getSound()->isBuffered(kEntityMax)) - getSound()->processEntry(kEntityMax); + if (getSoundQueue()->isBuffered(kEntityMax)) + getSoundQueue()->processEntry(kEntityMax); setCallback((savepoint.action == kActionKnock) ? 1 : 2); setup_playSound((savepoint.action == kActionKnock) ? "LIB012" : "LIB013"); @@ -156,7 +158,7 @@ IMPLEMENT_FUNCTION(7, Max, function7) break; case kActionDrawScene: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { if (getEntities()->isPlayerPosition(kCarRedSleeping, 56) || getEntities()->isPlayerPosition(kCarRedSleeping, 78)) getSound()->playSound(kEntityMax, "Max1120"); } @@ -197,7 +199,7 @@ IMPLEMENT_FUNCTION(7, Max, function7) break; case kAction158007856: - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); } @@ -214,7 +216,7 @@ IMPLEMENT_FUNCTION(8, Max, chapter4Handler) case kActionNone: UPDATE_PARAM(params->param3, getState()->time, params->param2); - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max3101"); params->param2 = 255 * (4 * rnd(20) + 40); @@ -228,8 +230,8 @@ IMPLEMENT_FUNCTION(8, Max, chapter4Handler) break; } - if (getSound()->isBuffered(kEntityMax)) - getSound()->processEntry(kEntityMax); + if (getSoundQueue()->isBuffered(kEntityMax)) + getSoundQueue()->processEntry(kEntityMax); getAction()->playAnimation(kEventCathMaxLickHand); getScenes()->processScene(); @@ -247,7 +249,7 @@ IMPLEMENT_FUNCTION(8, Max, chapter4Handler) getData()->location = kLocationInsideCompartment; getData()->car = kCarBaggage; - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max3101"); break; @@ -255,8 +257,8 @@ IMPLEMENT_FUNCTION(8, Max, chapter4Handler) if (getCallback() != 1) break; - if (getSound()->isBuffered(kEntityMax)) - getSound()->processEntry(kEntityMax); + if (getSoundQueue()->isBuffered(kEntityMax)) + getSoundQueue()->processEntry(kEntityMax); getSound()->playSound(kEntityPlayer, "LIB026"); getAction()->playAnimation(kEventCathMaxFree); @@ -392,7 +394,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler) UPDATE_PARAM(params->param3, getState()->time, params->param1); - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); @@ -424,7 +426,7 @@ IMPLEMENT_FUNCTION(13, Max, chapter3Handler) if (params->param2) break; - if (!getSound()->isBuffered(kEntityMax)) { + if (!getSoundQueue()->isBuffered(kEntityMax)) { getSound()->playSound(kEntityMax, "Max1122"); params->param1 = 255 * (4 * rnd(20) + 40); } @@ -464,7 +466,7 @@ IMPLEMENT_FUNCTION(14, Max, freeFromCage) getData()->location = kLocationInsideCompartment; getData()->car = kCarBaggage; - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max1122"); break; @@ -476,17 +478,17 @@ IMPLEMENT_FUNCTION(14, Max, freeFromCage) break; case 1: - if (getSound()->isBuffered(kEntityMax)) - getSound()->removeFromQueue(kEntityMax); + if (getSoundQueue()->isBuffered(kEntityMax)) + getSoundQueue()->removeFromQueue(kEntityMax); getAction()->playAnimation(kEventCathMaxCage); - getSound()->setupEntry(kSoundType7, kEntityMax); + getSoundQueue()->setupEntry(kSoundType7, kEntityMax); getScenes()->processScene(); break; case 2: - if (getSound()->isBuffered(kEntityMax)) - getSound()->processEntry(kEntityMax); + if (getSoundQueue()->isBuffered(kEntityMax)) + getSoundQueue()->processEntry(kEntityMax); getSound()->playSound(kEntityPlayer, "LIB026"); getAction()->playAnimation(kEventCathMaxFree); @@ -523,7 +525,7 @@ IMPLEMENT_FUNCTION(15, Max, function15) getData()->location = kLocationOutsideCompartment; getData()->car = kCarRedSleeping; - if (!getSound()->isBuffered(kEntityMax)) + if (!getSoundQueue()->isBuffered(kEntityMax)) getSound()->playSound(kEntityMax, "Max3010"); setCallback(1); diff --git a/engines/lastexpress/entities/mertens.cpp b/engines/lastexpress/entities/mertens.cpp index b99e344b20..464cc343bb 100644 --- a/engines/lastexpress/entities/mertens.cpp +++ b/engines/lastexpress/entities/mertens.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/state.h" #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -503,7 +505,7 @@ IMPLEMENT_FUNCTION_I(12, Mertens, bonsoir, EntityIndex) if (savepoint.action == kActionDefault) return; - if (getSound()->isBuffered(kEntityMertens)) { + if (getSoundQueue()->isBuffered(kEntityMertens)) { CALLBACK_ACTION(); return; } @@ -589,7 +591,7 @@ IMPLEMENT_FUNCTION_II(13, Mertens, function13, bool, bool) if (params->param2) params->param3 = 1; - if (!getSound()->isBuffered(kEntityMertens)) { + if (!getSoundQueue()->isBuffered(kEntityMertens)) { } @@ -1188,7 +1190,7 @@ IMPLEMENT_FUNCTION(22, Mertens, function22) break; case 5: - if (!getSound()->isBuffered(kEntityMertens)) + if (!getSoundQueue()->isBuffered(kEntityMertens)) getSound()->playSound(kEntityMertens, "MAH1170I"); setCallback(6); @@ -1198,7 +1200,7 @@ IMPLEMENT_FUNCTION(22, Mertens, function22) case 6: getData()->location = kLocationInsideCompartment; getEntities()->clearSequences(kEntityMertens); - if (!getSound()->isBuffered(kEntityMertens)) + if (!getSoundQueue()->isBuffered(kEntityMertens)) getSound()->playSound(kEntityMertens, "MAH1172", kFlagInvalid, 225); setCallback(7); @@ -2300,7 +2302,7 @@ IMPLEMENT_FUNCTION_I(31, Mertens, function31, MertensActionType) break; case 1: - if (getSound()->isBuffered(kEntityMertens)) { + if (getSoundQueue()->isBuffered(kEntityMertens)) { getEntities()->drawSequenceLeft(kEntityMertens, "601J"); } else { setCallback(2); @@ -3017,7 +3019,7 @@ IMPLEMENT_FUNCTION(42, Mertens, function42) if (getState()->time <= kTime1188000) { if ((!getEntities()->isPlayerInCar(kCarGreenSleeping) && !getEntities()->isPlayerInCar(kCarRedSleeping)) - || getSound()->isBuffered("REB1205") + || getSoundQueue()->isBuffered("REB1205") || !getEntities()->isInsideCompartment(kEntityMmeBoutarel, kCarRedSleeping, kPosition_5790) || !params->param4) { params->param4 = (uint)getState()->time; @@ -3138,7 +3140,7 @@ label_callback_18: } label_callback_19: - if (ENTITY_PARAM(0, 1) && !getSound()->isBuffered(kEntityMertens)) { + if (ENTITY_PARAM(0, 1) && !getSoundQueue()->isBuffered(kEntityMertens)) { if (getProgress().field_18 != 4) getSound()->playSound(kEntityMertens, "CON1505"); } diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp index 68030b3be3..1526c281b2 100644 --- a/engines/lastexpress/entities/milos.cpp +++ b/engines/lastexpress/entities/milos.cpp @@ -36,6 +36,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -1577,8 +1579,8 @@ IMPLEMENT_FUNCTION(29, Milos, chapter4Handler) break; case kAction221683008: - if (getSound()->isBuffered(kEntityMilos)) - getSound()->processEntry(kEntityMilos); + if (getSoundQueue()->isBuffered(kEntityMilos)) + getSoundQueue()->processEntry(kEntityMilos); params->param1 = 1; getSavePoints()->push(kEntityMilos, kEntityCoudert, kAction123199584); @@ -1720,15 +1722,15 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) break; case 2: - if (getSound()->isBuffered("MUS050")) - getSound()->processEntry("MUS050"); + if (getSoundQueue()->isBuffered("MUS050")) + getSoundQueue()->processEntry("MUS050"); - if (getSound()->isBuffered("ARRIVE")) - getSound()->removeFromQueue("ARRIVE"); + if (getSoundQueue()->isBuffered("ARRIVE")) + getSoundQueue()->removeFromQueue("ARRIVE"); - getSound()->processEntries(); + getSoundQueue()->processEntries(); getAction()->playAnimation(isNight() ? kEventLocomotiveMilosNight : kEventLocomotiveMilosDay); - getSound()->setupEntry(kSoundType7, kEntityMilos); + getSoundQueue()->setupEntry(kSoundType7, kEntityMilos); getScenes()->loadSceneFromPosition(kCarCoalTender, 1); break; @@ -1740,7 +1742,7 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) case 4: getAction()->playAnimation(kEventLocomotiveRestartTrain); getAction()->playAnimation(kEventLocomotiveOldBridge); - getSound()->resetState(); + getSoundQueue()->resetState(); getState()->time = kTime2983500; setCallback(5); @@ -1783,7 +1785,7 @@ IMPLEMENT_FUNCTION(34, Milos, chapter5Handler) setup_savegame(kSavegameTypeEvent, kEventLocomotiveAnnaStopsTrain); } - getSound()->processEntry(kEntityMilos); + getSoundQueue()->processEntry(kEntityMilos); if (getState()->time < kTimeTrainStopped2) getState()->time = kTimeTrainStopped2; diff --git a/engines/lastexpress/entities/mmeboutarel.cpp b/engines/lastexpress/entities/mmeboutarel.cpp index 78f2d2fb4b..1d4c52ca09 100644 --- a/engines/lastexpress/entities/mmeboutarel.cpp +++ b/engines/lastexpress/entities/mmeboutarel.cpp @@ -31,6 +31,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -399,7 +401,7 @@ IMPLEMENT_FUNCTION(13, MmeBoutarel, function13) break; case kActionNone: - if (!getSound()->isBuffered(kEntityMmeBoutarel) && params->param6 != kTimeInvalid) { + if (!getSoundQueue()->isBuffered(kEntityMmeBoutarel) && params->param6 != kTimeInvalid) { UPDATE_PARAM_PROC_TIME(params->param1, !getEntities()->isDistanceBetweenEntities(kEntityMmeBoutarel, kEntityPlayer, 2000), params->param6, 0) getObjects()->update(kObjectCompartmentD, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); getObjects()->update(kObject51, kEntityPlayer, kObjectLocation1, kCursorNormal, kCursorNormal); @@ -883,8 +885,8 @@ IMPLEMENT_FUNCTION(21, MmeBoutarel, chapter3Handler) if (getState()->time <= kTime2038500) { if (!getEntities()->isPlayerInCar(kCarRedSleeping) || !params->param1 - || getSound()->isBuffered("FRA2012") - || getSound()->isBuffered("FRA2010") + || getSoundQueue()->isBuffered("FRA2012") + || getSoundQueue()->isBuffered("FRA2010") ||!params->param2) params->param2 = (uint)getState()->time; diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp index d4a7359511..8bbcf64e84 100644 --- a/engines/lastexpress/entities/pascale.cpp +++ b/engines/lastexpress/entities/pascale.cpp @@ -30,6 +30,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -201,7 +203,7 @@ IMPLEMENT_FUNCTION(10, Pascale, welcomeCath) break; case kActionNone: - if (params->param1 && !getSound()->isBuffered(kEntityPascale)) + if (params->param1 && !getSoundQueue()->isBuffered(kEntityPascale)) getEntities()->updatePositionExit(kEntityPascale, kCarRestaurant, 64); break; @@ -462,10 +464,10 @@ IMPLEMENT_FUNCTION(16, Pascale, serveTatianaVassili) getEntities()->drawSequenceLeft(kEntityPascale, "014B"); getEntities()->updatePositionEnter(kEntityPascale, kCarRestaurant, 67); - if (getSound()->isBuffered("TAT1069A")) - getSound()->processEntry("TAT1069A"); - else if (getSound()->isBuffered("TAT1069B")) - getSound()->processEntry("TAT1069B"); + if (getSoundQueue()->isBuffered("TAT1069A")) + getSoundQueue()->processEntry("TAT1069A"); + else if (getSoundQueue()->isBuffered("TAT1069B")) + getSoundQueue()->processEntry("TAT1069B"); setCallback(2); setup_playSound("TAT1066"); @@ -1213,7 +1215,7 @@ label_callback1: break; case kAction169750080: - if (getSound()->isBuffered(kEntityPascale)) { + if (getSoundQueue()->isBuffered(kEntityPascale)) { params->param4 = 1; } else { setCallback(7); diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp index 68a37b368d..6d1c5244f2 100644 --- a/engines/lastexpress/entities/rebecca.cpp +++ b/engines/lastexpress/entities/rebecca.cpp @@ -30,6 +30,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -511,7 +513,7 @@ IMPLEMENT_FUNCTION_I(20, Rebecca, function20, TimeValue) if (getProgress().chapter == kChapter1 && !ENTITY_PARAM(0, 3)) { if (params->param7 != kTimeInvalid && getState()->time > kTime1174500) { if (getState()->time <= kTime1183500) { - if (!getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntityPlayer, 2000) || getSound()->isBuffered("CON1210") || !params->param7) + if (!getEntities()->isDistanceBetweenEntities(kEntityRebecca, kEntityPlayer, 2000) || getSoundQueue()->isBuffered("CON1210") || !params->param7) params->param7 = (uint)(getState()->time); if (params->param7 >= getState()->time) diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp index bbaff5f1d9..6dcab7121e 100644 --- a/engines/lastexpress/entities/salko.cpp +++ b/engines/lastexpress/entities/salko.cpp @@ -33,6 +33,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -596,8 +598,8 @@ IMPLEMENT_FUNCTION(24, Salko, chapter5Handler) break; case 1: - if (getSound()->isBuffered("MUS050")) - getSound()->processEntry("MUS050"); + if (getSoundQueue()->isBuffered("MUS050")) + getSoundQueue()->processEntry("MUS050"); getAction()->playAnimation(kEventCathSalkoTrainTopFight); diff --git a/engines/lastexpress/entities/tables.cpp b/engines/lastexpress/entities/tables.cpp index da053c5871..702b636c31 100644 --- a/engines/lastexpress/entities/tables.cpp +++ b/engines/lastexpress/entities/tables.cpp @@ -29,6 +29,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -88,8 +90,8 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION(5, Tables, chapter5) if (savepoint.action == kActionDefault) { - if (_id == kEntityTables2 && getSound()->isBuffered(kEntityTables2)) - getSound()->processEntry(kEntityTables2); + if (_id == kEntityTables2 && getSoundQueue()->isBuffered(kEntityTables2)) + getSoundQueue()->processEntry(kEntityTables2); setup_draw(); } @@ -113,21 +115,21 @@ IMPLEMENT_FUNCTION(6, Tables, draw) case kChapter1: if (getState()->time > kTime1165500 && !params->param1) { params->param1 = 1; - getSound()->processEntry(kEntityTables2); + getSoundQueue()->processEntry(kEntityTables2); } break; case kChapter3: if (getState()->time > kTime2052000 && !params->param2) { params->param2 = 1; - getSound()->processEntry(kEntityTables2); + getSoundQueue()->processEntry(kEntityTables2); } break; case kChapter4: if (getState()->time > kTime2488500 && !params->param3) { params->param3 = 1; - getSound()->processEntry(kEntityTables2); + getSoundQueue()->processEntry(kEntityTables2); } break; diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp index db5c413dc9..2f60b448ba 100644 --- a/engines/lastexpress/entities/tatiana.cpp +++ b/engines/lastexpress/entities/tatiana.cpp @@ -35,6 +35,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -420,7 +422,7 @@ IMPLEMENT_FUNCTION(19, Tatiana, chapter1Handler) break; case kActionNone: - if (getSound()->isBuffered(kEntityTatiana) || !params->param4 || params->param3 == 2 || getSound()->isBuffered("TAT1066")) + if (getSoundQueue()->isBuffered(kEntityTatiana) || !params->param4 || params->param3 == 2 || getSoundQueue()->isBuffered("TAT1066")) goto label_tatiana_chapter1_2; UPDATE_PARAM_PROC(params->param5, getState()->timeTicks, 450) @@ -568,7 +570,7 @@ IMPLEMENT_FUNCTION(21, Tatiana, function21) // Fallback to next case case 3: - if (getSound()->isBuffered(kEntityTatiana)) { + if (getSoundQueue()->isBuffered(kEntityTatiana)) { setCallback(3); setup_updateFromTime(75); } else { @@ -1858,7 +1860,7 @@ IMPLEMENT_FUNCTION(46, Tatiana, function46) parameters->param3 = 1; if (parameters->param2) { - getSound()->removeFromQueue(kEntityTatiana); + getSoundQueue()->removeFromQueue(kEntityTatiana); getSavePoints()->call(kEntityTatiana, kEntityTatiana, kActionEndSound); } } else { @@ -1947,7 +1949,7 @@ IMPLEMENT_FUNCTION(48, Tatiana, function48) params->param1 = 0; } - if (!params->param1 || getSound()->isBuffered(kEntityTatiana)) + if (!params->param1 || getSoundQueue()->isBuffered(kEntityTatiana)) goto label_end; UPDATE_PARAM_GOTO(params->param2, getState()->timeTicks, 5 * (3 * rnd(5) + 30), label_end); @@ -2086,7 +2088,7 @@ IMPLEMENT_FUNCTION(50, Tatiana, function50) break; case kActionKnock: - if (!getSound()->isBuffered("LIB012", true)) + if (!getSoundQueue()->isBuffered("LIB012", true)) getSound()->playSound(kEntityPlayer, "LIB012"); break; @@ -2107,14 +2109,14 @@ IMPLEMENT_FUNCTION(50, Tatiana, function50) getObjects()->update(kObject48, kEntityTatiana, kObjectLocationNone, kCursorHandKnock, kCursorHand); getObjects()->update(kObjectCompartmentA, kEntityTatiana, kObjectLocationNone, kCursorHandKnock, kCursorHand); - if (!getSound()->isBuffered(kEntityTatiana)) + if (!getSoundQueue()->isBuffered(kEntityTatiana)) getSound()->playSound(kEntityTatiana, "Tat4166"); break; case kActionCallback: if (getCallback() == 1) { - if (getSound()->isBuffered("MUS013")) - getSound()->processEntry("MUS013"); + if (getSoundQueue()->isBuffered("MUS013")) + getSoundQueue()->processEntry("MUS013"); getAction()->playAnimation(kEventVassiliDeadAlexei); getSavePoints()->push(kEntityTatiana, kEntityAbbot, kAction104060776); @@ -2223,11 +2225,11 @@ IMPLEMENT_FUNCTION(54, Tatiana, function54) case kActionCallback: if (getCallback() == 1) { - if (getSound()->isBuffered("MUS050")) - getSound()->processEntry("MUS050"); + if (getSoundQueue()->isBuffered("MUS050")) + getSoundQueue()->processEntry("MUS050"); - if (getSound()->isBuffered(kEntityTatiana)) - getSound()->processEntry(kEntityTatiana); + if (getSoundQueue()->isBuffered(kEntityTatiana)) + getSoundQueue()->processEntry(kEntityTatiana); getAction()->playAnimation(isNight() ? kEventTatianaVassiliTalkNight : kEventTatianaVassiliTalk); getScenes()->processScene(); diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp index 1a5c6f4f64..74eed63bbf 100644 --- a/engines/lastexpress/entities/train.cpp +++ b/engines/lastexpress/entities/train.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/state.h" #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -300,13 +302,13 @@ label_process: } // Update object - if (ENTITY_PARAM(0, 8) && !getSound()->isBuffered(kEntityTables5)) { + if (ENTITY_PARAM(0, 8) && !getSoundQueue()->isBuffered(kEntityTables5)) { getObjects()->update((ObjectIndex)ENTITY_PARAM(0, 8), getObjects()->get((ObjectIndex)ENTITY_PARAM(0, 8)).entity, kObjectLocation3, kCursorHandKnock, kCursorHand); ENTITY_PARAM(0, 8) = 0; } // Play clock sound - if (params->param6 && !getSound()->isBuffered("ZFX1001", true)) + if (params->param6 && !getSoundQueue()->isBuffered("ZFX1001", true)) getSound()->playSound(kEntityPlayer, "ZFX1001"); break; @@ -339,12 +341,12 @@ label_process: // Play clock sound if (getEntities()->isPlayerPosition(kCarRestaurant, 81)) { params->param6 = 1; - if (!getSound()->isBuffered("ZFX1001")) + if (!getSoundQueue()->isBuffered("ZFX1001")) getSound()->playSound(kEntityPlayer, "ZFX1001"); } else { params->param6 = 0; - if (getSound()->isBuffered("ZFX1001", true)) - getSound()->removeFromQueue("ZFX1001"); + if (getSoundQueue()->isBuffered("ZFX1001", true)) + getSoundQueue()->removeFromQueue("ZFX1001"); } // Draw moving background behind windows @@ -562,8 +564,8 @@ void Train::resetParam8() { && !getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params1->param1, (EntityPosition)params1->param2) && !getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params1->param1, (EntityPosition)params1->param3)) { - if (getSound()->isBuffered((const char *)¶ms1->seq)) - getSound()->processEntry((const char *)¶ms1->seq); + if (getSoundQueue()->isBuffered((const char *)¶ms1->seq)) + getSoundQueue()->processEntry((const char *)¶ms1->seq); params->param8 = 0; } diff --git a/engines/lastexpress/entities/vassili.cpp b/engines/lastexpress/entities/vassili.cpp index a1daf3e524..a7fbc7cf32 100644 --- a/engines/lastexpress/entities/vassili.cpp +++ b/engines/lastexpress/entities/vassili.cpp @@ -35,6 +35,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -295,7 +297,7 @@ IMPLEMENT_FUNCTION(9, Vassili, function9) || getEntities()->isPlayerPosition(kCarRedSleeping, 41)) { if (savepoint.action == kActionDrawScene) - getSound()->processEntry(kEntityVassili); + getSoundQueue()->processEntry(kEntityVassili); setup_seizure(); } else { diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp index c0a00b8c05..c18137c835 100644 --- a/engines/lastexpress/entities/verges.cpp +++ b/engines/lastexpress/entities/verges.cpp @@ -32,6 +32,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -139,7 +141,7 @@ IMPLEMENT_FUNCTION_END ////////////////////////////////////////////////////////////////////////// IMPLEMENT_FUNCTION_II(8, Verges, updateEntity, CarIndex, EntityPosition) if (savepoint.action == kActionExcuseMeCath) { - if (!getSound()->isBuffered(kEntityVerges)) + if (!getSoundQueue()->isBuffered(kEntityVerges)) getSound()->playSound(kEntityPlayer, "TRA1113", getSound()->getSoundFlag(kEntityVerges)); return; @@ -187,7 +189,7 @@ switch (savepoint.action) { break; case 2: - if (!getSound()->isBuffered(kEntityVerges)) + if (!getSoundQueue()->isBuffered(kEntityVerges)) getSound()->playSound(kEntityVerges, (char *)¶ms->seq1); getEntities()->drawSequenceRight(kEntityVerges, "813DS"); @@ -232,7 +234,7 @@ IMPLEMENT_FUNCTION_IIS(10, Verges, function10, CarIndex, EntityPosition) case kActionNone: if (!params->param7) { - if (!getSound()->isBuffered(kEntityVerges)) { + if (!getSoundQueue()->isBuffered(kEntityVerges)) { getSound()->playSound(kEntityVerges, (char *)¶ms->seq); params->param7 = 1; } @@ -258,7 +260,7 @@ IMPLEMENT_FUNCTION_IIS(10, Verges, function10, CarIndex, EntityPosition) break; case kActionDefault: - if (!getSound()->isBuffered(kEntityVerges)) { + if (!getSoundQueue()->isBuffered(kEntityVerges)) { getSound()->playSound(kEntityVerges, (char *)¶ms->seq); params->param7 = 1; } @@ -704,7 +706,7 @@ IMPLEMENT_FUNCTION(24, Verges, policeGettingOffTrain) case kActionCallback: if (getCallback() == 1) { - getSound()->processEntry(kEntityVerges); + getSoundQueue()->processEntry(kEntityVerges); getAction()->playAnimation(kEventGendarmesArrestation); getLogic()->gameOver(kSavegameTypeIndex, 1, kSceneGameOverPolice1, true); } @@ -1314,7 +1316,7 @@ IMPLEMENT_FUNCTION(32, Verges, function32) break; case 2: - if (!getSound()->isBuffered(kEntityVerges)) + if (!getSoundQueue()->isBuffered(kEntityVerges)) getSound()->playSound(kEntityVerges, "TRA3004"); getEntities()->drawSequenceRight(kEntityVerges, "813DS"); @@ -1752,16 +1754,16 @@ IMPLEMENT_FUNCTION(40, Verges, chapter5Handler) break; case kActionNone: - if (getEntities()->isInSalon(kEntityPlayer) && !getSound()->isBuffered(kEntityVerges)) + if (getEntities()->isInSalon(kEntityPlayer) && !getSoundQueue()->isBuffered(kEntityVerges)) getSound()->playSound(kEntityVerges, "WAT5000"); break; case kActionOpenDoor: - if (getSound()->isBuffered(kEntityVerges)) - getSound()->processEntry(kEntityVerges); + if (getSoundQueue()->isBuffered(kEntityVerges)) + getSoundQueue()->processEntry(kEntityVerges); - if (getSound()->isBuffered("MUS050")) - getSound()->processEntry("MUS050"); + if (getSoundQueue()->isBuffered("MUS050")) + getSoundQueue()->processEntry("MUS050"); getObjects()->update(kObject65, kEntityPlayer, kObjectLocationNone, kCursorNormal, kCursorForward); @@ -1811,7 +1813,7 @@ IMPLEMENT_FUNCTION(41, Verges, function41) // Fallback to next case case 2: - if (getSound()->isBuffered(kEntityVerges)) { + if (getSoundQueue()->isBuffered(kEntityVerges)) { setCallback(2); setup_updateFromTime(225); } else { diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp index 685b3b09d1..38a93cfd94 100644 --- a/engines/lastexpress/fight/fight.cpp +++ b/engines/lastexpress/fight/fight.cpp @@ -37,6 +37,8 @@ #include "lastexpress/game/scenes.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -86,7 +88,7 @@ void Fight::eventMouse(const Common::Event &ev) { // Handle right button click if (ev.type == Common::EVENT_RBUTTONUP) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); setStopped(); getGlobalTimer() ? _state = 0 : ++_state; @@ -133,15 +135,15 @@ void Fight::eventMouse(const Common::Event &ev) { // Stop fight if clicked if (ev.type == Common::EVENT_LBUTTONUP) { _handleTimer = false; - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); bailout(kFightEndExit); } // Reset timer on right click if (ev.type == Common::EVENT_RBUTTONUP) { if (getGlobalTimer()) { - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); + if (getSoundQueue()->isBuffered("TIMER")) + getSoundQueue()->removeFromQueue("TIMER"); setGlobalTimer(900); } @@ -277,7 +279,7 @@ Fight::FightEndType Fight::setup(FightType type) { if (_engine->handleEvents()) continue; - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); } // Cleanup after fight is over diff --git a/engines/lastexpress/fight/fighter_anna.cpp b/engines/lastexpress/fight/fighter_anna.cpp index 3c0132eef6..feb35515a0 100644 --- a/engines/lastexpress/fight/fighter_anna.cpp +++ b/engines/lastexpress/fight/fighter_anna.cpp @@ -26,6 +26,8 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -107,7 +109,7 @@ void FighterPlayerAnna::handleAction(FightAction action) { } if (_field_34 > 4) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); _fight->bailout(Fight::kFightEndWin); } } @@ -175,7 +177,7 @@ void FighterOpponentAnna::update() { _opponent->handleAction((FightAction)_sequenceIndex); if (_opponent->getCountdown() <= 0) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); handleAction(kFightActionLost); } } diff --git a/engines/lastexpress/fight/fighter_ivo.cpp b/engines/lastexpress/fight/fighter_ivo.cpp index 60d6c1a874..9988fca790 100644 --- a/engines/lastexpress/fight/fighter_ivo.cpp +++ b/engines/lastexpress/fight/fighter_ivo.cpp @@ -26,6 +26,8 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -110,7 +112,7 @@ void FighterPlayerIvo::update() { if (_opponent->getCountdown() <= 0) { setSequenceAndDraw(9, kFightSequenceType1); _opponent->setSequenceAndDraw(8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); handleAction(kFightActionWin); return; @@ -227,7 +229,7 @@ void FighterOpponentIvo::update() { if (_opponent->getCountdown() <= 0) { setSequenceAndDraw(7, kFightSequenceType1); _opponent->setSequenceAndDraw(8, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); _opponent->handleAction(kFightActionWin); diff --git a/engines/lastexpress/fight/fighter_milos.cpp b/engines/lastexpress/fight/fighter_milos.cpp index 972c44882b..82c965caf3 100644 --- a/engines/lastexpress/fight/fighter_milos.cpp +++ b/engines/lastexpress/fight/fighter_milos.cpp @@ -27,6 +27,8 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -107,7 +109,7 @@ void FighterPlayerMilos::update() { setSequenceAndDraw(5, kFightSequenceType1); _opponent->setSequenceAndDraw(6, kFightSequenceType1); - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); getSound()->playSound(kEntityTrain, "MUS029", kFlagDefault); handleAction(kFightActionWin); @@ -210,7 +212,7 @@ void FighterOpponentMilos::update() { _opponent->handleAction((FightAction)_sequenceIndex); if (_opponent->getCountdown() <= 0) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); handleAction(kFightActionLost); } } diff --git a/engines/lastexpress/fight/fighter_salko.cpp b/engines/lastexpress/fight/fighter_salko.cpp index 6f71a6dda8..166f7c3899 100644 --- a/engines/lastexpress/fight/fighter_salko.cpp +++ b/engines/lastexpress/fight/fighter_salko.cpp @@ -27,6 +27,8 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -95,7 +97,7 @@ void FighterPlayerSalko::update() { if (_frame && checkFrame(2)) { if (_opponent->getCountdown() <= 0) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); _fight->bailout(Fight::kFightEndWin); return; @@ -184,7 +186,7 @@ void FighterOpponentSalko::update() { if (_frame && checkFrame(2)) { if (_opponent->getCountdown() <= 0) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); _fight->bailout(Fight::kFightEndLost); // Stop processing diff --git a/engines/lastexpress/fight/fighter_vesna.cpp b/engines/lastexpress/fight/fighter_vesna.cpp index c92d041c7e..075f158bda 100644 --- a/engines/lastexpress/fight/fighter_vesna.cpp +++ b/engines/lastexpress/fight/fighter_vesna.cpp @@ -27,6 +27,8 @@ #include "lastexpress/game/sound.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -103,7 +105,7 @@ void FighterPlayerVesna::update() { _opponent->handleAction(kFightAction3); if (_opponent->getCountdown() <= 0) { - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); _fight->bailout(Fight::kFightEndWin); return; } @@ -251,7 +253,7 @@ void FighterOpponentVesna::update() { _opponent->update(); Fighter::update(); - getSound()->removeFromQueue(kEntityTables0); + getSoundQueue()->removeFromQueue(kEntityTables0); // Stop processing return; diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp index 54bb8759ee..f195825d6e 100644 --- a/engines/lastexpress/game/action.cpp +++ b/engines/lastexpress/game/action.cpp @@ -42,6 +42,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" #include "lastexpress/resource.h" @@ -453,7 +455,7 @@ IMPLEMENT_ACTION(savePoint) IMPLEMENT_ACTION(playSound) // Check that the file is not already buffered - if (hotspot.param2 || !getSound()->isBuffered(Common::String::format("LIB%03d", hotspot.param1), true)) + if (hotspot.param2 || !getSoundQueue()->isBuffered(Common::String::format("LIB%03d", hotspot.param1), true)) getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2); return kSceneInvalid; @@ -465,7 +467,7 @@ IMPLEMENT_ACTION(playMusic) // Check that the file is not already buffered Common::String filename = Common::String::format("MUS%03d", hotspot.param1); - if (!getSound()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5)) + if (!getSoundQueue()->isBuffered(filename) && (hotspot.param1 != 50 || getProgress().chapter == kChapter5)) getSound()->playSound(kEntityPlayer, filename, kFlagDefault, hotspot.param2); return kSceneInvalid; @@ -481,7 +483,7 @@ IMPLEMENT_ACTION(knock) if (getObjects()->get(object).entity) { getSavePoints()->push(kEntityPlayer, getObjects()->get(object).entity, kActionKnock, object); } else { - if (!getSound()->isBuffered("LIB012", true)) + if (!getSoundQueue()->isBuffered("LIB012", true)) getSound()->playSoundEvent(kEntityPlayer, 12); } @@ -516,7 +518,7 @@ IMPLEMENT_ACTION(compartment) && (compartment != kObjectCompartment1 || !getInventory()->hasItem(kItemKey) || (getInventory()->getSelectedItem() != kItemFirebird && getInventory()->getSelectedItem() != kItemBriefcase)))) { - if (!getSound()->isBuffered("LIB13")) + if (!getSoundQueue()->isBuffered("LIB13")) getSound()->playSoundEvent(kEntityPlayer, 13); // Stop processing further @@ -621,7 +623,7 @@ IMPLEMENT_ACTION(updateObjetLocation2) getObjects()->updateLocation2(object, location); - if (object != kObject112 || getSound()->isBuffered("LIB096")) { + if (object != kObject112 || getSoundQueue()->isBuffered("LIB096")) { if (object == 1) getSound()->playSoundEvent(kEntityPlayer, 73); } else { @@ -805,7 +807,7 @@ IMPLEMENT_ACTION(enterCompartment) getSound()->playSoundEvent(kEntityPlayer, 14); getSound()->playSoundEvent(kEntityPlayer, 15, 22); - if (getProgress().field_78 && !getSound()->isBuffered("MUS003")) { + if (getProgress().field_78 && !getSoundQueue()->isBuffered("MUS003")) { getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_78 = 0; } @@ -1083,7 +1085,7 @@ IMPLEMENT_ACTION(25) break; case 2: - if (!getSound()->isBuffered("MUS021")) + if (!getSoundQueue()->isBuffered("MUS021")) getSound()->playSound(kEntityPlayer, "MUS021", kFlagDefault); break; @@ -1134,7 +1136,7 @@ IMPLEMENT_ACTION(26) ////////////////////////////////////////////////////////////////////////// // Action 27 IMPLEMENT_ACTION(27) - if (!getSound()->isBuffered("LIB031", true)) + if (!getSoundQueue()->isBuffered("LIB031", true)) getSound()->playSoundEvent(kEntityPlayer, 31); switch (getEntityData(kEntityPlayer)->car) { @@ -1182,7 +1184,7 @@ IMPLEMENT_ACTION(29) getSound()->playSoundEvent(kEntityPlayer, hotspot.param1, hotspot.param2); Common::String filename = Common::String::format("MUS%03d", hotspot.param3); - if (!getSound()->isBuffered(filename)) + if (!getSoundQueue()->isBuffered(filename)) getSound()->playSound(kEntityPlayer, filename, kFlagDefault); return kSceneInvalid; @@ -1354,7 +1356,7 @@ IMPLEMENT_ACTION(dialog) // Action 38 IMPLEMENT_ACTION(eggBox) getSound()->playSoundEvent(kEntityPlayer, 43); - if (getProgress().field_7C && !getSound()->isBuffered("MUS003")) { + if (getProgress().field_7C && !getSoundQueue()->isBuffered("MUS003")) { getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_7C = 0; } @@ -1366,7 +1368,7 @@ IMPLEMENT_ACTION(eggBox) // Action 39 IMPLEMENT_ACTION(39) getSound()->playSoundEvent(kEntityPlayer, 24); - if (getProgress().field_80 && !getSound()->isBuffered("MUS003")) { + if (getProgress().field_80 && !getSoundQueue()->isBuffered("MUS003")) { getSound()->playSound(kEntityPlayer, "MUS003", kFlagDefault); getProgress().field_80 = 0; } @@ -1408,7 +1410,7 @@ IMPLEMENT_ACTION(playMusicChapter) if (id) { Common::String filename = Common::String::format("MUS%03d", id); - if (!getSound()->isBuffered(filename)) + if (!getSoundQueue()->isBuffered(filename)) getSound()->playSound(kEntityPlayer, filename, kFlagDefault); } @@ -1440,7 +1442,7 @@ IMPLEMENT_ACTION(playMusicChapterSetupTrain) Common::String filename = Common::String::format("MUS%03d", hotspot.param1); - if (!getSound()->isBuffered(filename) && hotspot.param3 & id) { + if (!getSoundQueue()->isBuffered(filename) && hotspot.param3 & id) { getSound()->playSound(kEntityPlayer, filename, kFlagDefault); getSavePoints()->call(kEntityPlayer, kEntityTrain, kAction203863200, filename.c_str()); @@ -1612,7 +1614,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityMertens)) + if (!getSoundQueue()->isBuffered(kEntityMertens)) getSound()->playWarningCompartment(kEntityMertens, object); getSavePoints()->push(kEntityPlayer, kEntityMertens, kAction305159806); @@ -1628,7 +1630,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityMertens)) + if (!getSoundQueue()->isBuffered(kEntityMertens)) getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A"); if (doLoadScene) @@ -1640,7 +1642,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityMertens)) + if (!getSoundQueue()->isBuffered(kEntityMertens)) getSound()->playSound(kEntityMertens, (rnd(2)) ? "JAC1000" : "JAC1000A"); if (doLoadScene) @@ -1667,7 +1669,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityCoudert)) + if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playWarningCompartment(kEntityCoudert, object); getSavePoints()->push(kEntityPlayer, kEntityCoudert, kAction305159806); @@ -1684,7 +1686,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityCoudert)) + if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A"); if (doLoadScene) @@ -1699,7 +1701,7 @@ bool Action::handleOtherCompartment(ObjectIndex object, bool doPlaySound, bool d if (doPlaySound) playCompartmentSoundEvents(object); - if (!getSound()->isBuffered(kEntityCoudert)) + if (!getSoundQueue()->isBuffered(kEntityCoudert)) getSound()->playSound(kEntityCoudert, (rnd(2)) ? "JAC1000" : "JAC1000A"); if (doLoadScene) @@ -1930,8 +1932,8 @@ void Action::playAnimation(EventIndex index, bool debugMode) const { if (!getFlags()->mouseRightClick) { if (getGlobalTimer()) { - if (getSound()->isBuffered("TIMER")) { - getSound()->processEntry("TIMER"); + if (getSoundQueue()->isBuffered("TIMER")) { + getSoundQueue()->processEntry("TIMER"); setGlobalTimer(105); } } @@ -1948,8 +1950,8 @@ void Action::playAnimation(EventIndex index, bool debugMode) const { if (animation.load(getArchive(Common::String(_animationList[index].filename) + ".nis") , processSound ? Animation::kFlagDefault : Animation::kFlagProcess)) animation.play(); - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); + if (getSoundQueue()->isBuffered("TIMER")) + getSoundQueue()->removeFromQueue("TIMER"); } // Show cursor diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp index 0fa3af36b7..8dd2c26c19 100644 --- a/engines/lastexpress/game/entities.cpp +++ b/engines/lastexpress/game/entities.cpp @@ -71,6 +71,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -299,7 +301,7 @@ void Entities::setupChapter(ChapterIndex chapter) { memset(&_compartments1, 0, sizeof(_compartments1)); memset(&_positions, 0, sizeof(_positions)); - getSound()->resetQueue(kSoundType13); + getSoundQueue()->resetQueue(kSoundType13); } // we skip the header when doing entity setup @@ -369,8 +371,8 @@ void Entities::resetState(EntityIndex entityIndex) { getData(entityIndex)->currentCall = 0; getData(entityIndex)->inventoryItem = kItemNone; - if (getSound()->isBuffered(entityIndex)) - getSound()->removeFromQueue(entityIndex); + if (getSoundQueue()->isBuffered(entityIndex)) + getSoundQueue()->removeFromQueue(entityIndex); clearSequences(entityIndex); diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp index 4d75fcaca5..c3a10225e9 100644 --- a/engines/lastexpress/game/inventory.cpp +++ b/engines/lastexpress/game/inventory.cpp @@ -33,6 +33,8 @@ #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -162,8 +164,8 @@ void Inventory::handleMouseEvent(const Common::Event &ev) { } else if (ev.type == Common::EVENT_RBUTTONDOWN) { if (getGlobalTimer()) { - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); + if (getSoundQueue()->isBuffered("TIMER")) + getSoundQueue()->removeFromQueue("TIMER"); setGlobalTimer(900); } @@ -630,7 +632,7 @@ void Inventory::drawBlinkingEgg() { // if (getGlobalTimer() + ticks >= 90) // getSound()->playSoundWithSubtitles("TIMER.SND", 50331664, kEntityPlayer); - // if (getSound()->isBuffered("TIMER")) + // if (getSoundQueue()->isBuffered("TIMER")) // setGlobalTimer(0); //} diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index c1237eefe9..cdde2a0e0a 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -47,6 +47,8 @@ #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -152,7 +154,7 @@ void Logic::eventMouse(const Common::Event &ev) { _engine->getCursor()->setStyle(getInventory()->get(kItemWhistle)->cursor); // Check if clicked - if (ev.type == Common::EVENT_LBUTTONUP && !getSound()->isBuffered("LIB045")) { + if (ev.type == Common::EVENT_LBUTTONUP && !getSoundQueue()->isBuffered("LIB045")) { getSound()->playSoundEvent(kEntityPlayer, 45); @@ -424,7 +426,7 @@ void Logic::resetState() { */ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, bool showScene) const { - getSound()->processEntries(); + getSoundQueue()->processEntries(); getEntities()->reset(); getFlags()->isGameRunning = false; getSavePoints()->reset(); @@ -432,16 +434,16 @@ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, boo if (showScene) { - getSound()->processEntry(kSoundType11); + getSoundQueue()->processEntry(kSoundType11); if (sceneIndex && !getFlags()->mouseRightClick) { getScenes()->loadScene(sceneIndex); - while (getSound()->isBuffered(kEntityTables4)) { + while (getSoundQueue()->isBuffered(kEntityTables4)) { if (getFlags()->mouseRightClick) break; - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); } } } @@ -451,7 +453,7 @@ void Logic::gameOver(SavegameType type, uint32 value, SceneIndex sceneIndex, boo } void Logic::switchChapter() const { - getSound()->clearStatus(); + getSoundQueue()->clearStatus(); switch(getState()->progress.chapter) { default: @@ -491,7 +493,7 @@ void Logic::switchChapter() const { } void Logic::playFinalSequence() const { - getSound()->processEntries(); + getSoundQueue()->processEntries(); _action->playAnimation(kEventFinalSequence); showCredits(); diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index 594cd1276b..8dfc214913 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -30,6 +30,8 @@ #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/debug.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" @@ -125,7 +127,7 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) { while (_savegame->pos() < _savegame->size() && !_savegame->eos() && !_savegame->err()) { // Update sound queue while we go through the savegame - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); SavegameEntryHeader *entry = new SavegameEntryHeader(); entry->saveLoadWithSerializer(ser); @@ -217,7 +219,7 @@ void SaveLoad::loadGame(GameId id) { _gameTicksLastSavegame = getState()->timeTicks; if (header.keepIndex) { - getSound()->clearQueue(); + getSoundQueue()->clearQueue(); readEntry(&type, &entity, &val, false); } @@ -377,7 +379,7 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) { WRITE_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32); WRITE_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128); WRITE_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40); - WRITE_ENTRY("sound", getSound()->saveLoadWithSerializer(ser), 3 * 4 + getSound()->count() * 64); + WRITE_ENTRY("sound", getSoundQueue()->saveLoadWithSerializer(ser), 3 * 4 + getSoundQueue()->count() * 64); WRITE_ENTRY("savepoints", getSavePoints()->saveLoadWithSerializer(ser), 128 * 16 + 4 + getSavePoints()->count() * 16); header.offset = (uint32)_savegame->pos() - (originalPosition + 32); @@ -452,7 +454,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b LOAD_ENTRY("inventory", getInventory()->saveLoadWithSerializer(ser), 7 * 32); LOAD_ENTRY("objects", getObjects()->saveLoadWithSerializer(ser), 5 * 128); LOAD_ENTRY("entities", getEntities()->saveLoadWithSerializer(ser), 1262 * 40); - LOAD_ENTRY_ONLY("sound", getSound()->saveLoadWithSerializer(ser)); + LOAD_ENTRY_ONLY("sound", getSoundQueue()->saveLoadWithSerializer(ser)); LOAD_ENTRY_ONLY("savepoints", getSavePoints()->saveLoadWithSerializer(ser)); // Update chapter diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp index b346c9daf8..408f48044c 100644 --- a/engines/lastexpress/game/scenes.cpp +++ b/engines/lastexpress/game/scenes.cpp @@ -34,6 +34,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -1057,9 +1059,9 @@ void SceneManager::preProcessScene(SceneIndex *index) { // Sound processing Scene *newScene = getScenes()->get(*index); - if (getSound()->isBuffered(kEntityTables4)) { + if (getSoundQueue()->isBuffered(kEntityTables4)) { if (newScene->type != Scene::kTypeReadText || newScene->param1) - getSound()->processEntry(kEntityTables4); + getSoundQueue()->processEntry(kEntityTables4); } // Cleanup beetle sequences @@ -1089,8 +1091,8 @@ void SceneManager::postProcessScene() { if (getFlags()->mouseRightClick) break; - getSound()->updateQueue(); - getSound()->updateSubtitles(); + getSoundQueue()->updateQueue(); + getSoundQueue()->updateSubtitles(); } } @@ -1157,7 +1159,7 @@ void SceneManager::postProcessScene() { if (getState()->time >= kTimeCityGalanta || getProgress().field_18 == 4) break; - getSound()->processEntry(kSoundType7); + getSoundQueue()->processEntry(kSoundType7); getSound()->playSound(kEntityTrain, "LIB050", kFlagDefault); switch (getProgress().chapter) { diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp index 3fb3f8894d..bc4f71e18d 100644 --- a/engines/lastexpress/game/sound.cpp +++ b/engines/lastexpress/game/sound.cpp @@ -31,6 +31,7 @@ #include "lastexpress/game/state.h" #include "lastexpress/sound/entry.h" +#include "lastexpress/sound/queue.h" #include "lastexpress/helpers.h" #include "lastexpress/graphics.h" @@ -39,9 +40,6 @@ namespace LastExpress { -#define SOUNDCACHE_ENTRY_SIZE 92160 -#define SOUNDCACHE_MAX_SIZE 6 - // Letters & messages static const char *const messages[24] = { "", @@ -115,349 +113,32 @@ static const SoundFlag soundFlags[32] = { kFlag3, kFlag3, kFlag3, kFlag3, kFlag3 }; -SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine), _state(0), _currentType(kSoundType16), _flag(0) { +SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine) { + _loopingSoundDuration = 0; + + _queue = new SoundQueue(engine); + + memset(&_lastWarning, 0, sizeof(_lastWarning)); + // Initialize unknown data _data0 = 0; _data1 = 0; _data2 = 0; - - memset(&_buffer, 0, sizeof(_buffer)); - memset(&_lastWarning, 0, sizeof(_lastWarning)); - - // Sound cache - _soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE); - - _subtitlesFlag = 0; - _currentSubtitle = NULL; - - _loopingSoundDuration = 0; } SoundManager::~SoundManager() { - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - SAFE_DELETE(*i); - _soundList.clear(); - - // Entries in the cache are just pointers to sound list entries - _soundCache.clear(); - - for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) - SAFE_DELETE(*i); - _subtitles.clear(); - - _currentSubtitle = NULL; - - free(_soundCacheData); + SAFE_DELETE(_queue); // Zero passed pointers _engine = NULL; } ////////////////////////////////////////////////////////////////////////// -// Timer -////////////////////////////////////////////////////////////////////////// -void SoundManager::handleTimer() { - Common::StackLock locker(_mutex); - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - SoundEntry *entry = (*i); - if (entry->_stream == NULL) { - SAFE_DELETE(*i); - i = _soundList.reverse_erase(i); - continue; - } else if (!entry->_soundStream) { - entry->_soundStream = new StreamedSound(); - - // TODO: stream any sound in the queue after filtering - entry->_soundStream->load(entry->_stream); - } - } -} - -////////////////////////////////////////////////////////////////////////// -// Sound queue management -////////////////////////////////////////////////////////////////////////// -void SoundManager::updateQueue() { - // TODO add mutex lock! - warning("Sound::updateQueue: not implemented!"); -} - -void SoundManager::resetQueue(SoundType type1, SoundType type2) { - if (!type2) - type2 = type1; - - Common::StackLock locker(_mutex); - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->getType() != type1 && (*i)->getType() != type2) - (*i)->reset(); - } -} - -void SoundManager::removeFromQueue(EntityIndex entity) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(entity); - if (entry) - entry->reset(); -} - -void SoundManager::removeFromQueue(Common::String filename) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(filename); - if (entry) - entry->reset(); -} - -void SoundManager::clearQueue() { - _flag |= 4; - - // FIXME: Wait a while for a flag to be set - //for (int i = 0; i < 3000000; i++) - // if (_flag & 8) - // break; - - _flag |= 8; - - Common::StackLock locker(_mutex); - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - SoundEntry *entry = (*i); - - // Delete entry - entry->close(); - SAFE_DELETE(entry); - - i = _soundList.reverse_erase(i); - } - - updateSubtitles(); -} - -bool SoundManager::isBuffered(EntityIndex entity) { - Common::StackLock locker(_mutex); - - return (getEntry(entity) != NULL); -} - -bool SoundManager::isBuffered(Common::String filename, bool testForEntity) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(filename); - - if (testForEntity) - return entry != NULL && entry->getEntity() != kEntityPlayer; - - return (entry != NULL); -} - -////////////////////////////////////////////////////////////////////////// -// Entry -////////////////////////////////////////////////////////////////////////// -bool SoundManager::setupCache(SoundEntry *entry) { - if (entry->_soundData) - return true; - - if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) { - - SoundEntry *cacheEntry = NULL; - uint32 size = 1000; - - for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if (!((*i)->_status.status & kSoundStatus_180)) { - uint32 newSize = (*i)->_priority + ((*i)->_status.status & kSoundStatusClear1); - - if (newSize < size) { - cacheEntry = (*i); - size = newSize; - } - } - } - - if (entry->_priority <= size) - return false; - - if (!cacheEntry) - error("[SoundManager::setupCache] Cannot find a valid entry"); - - cacheEntry->setInCache(); - - // TODO: Wait until the cache entry is ready to be removed - while (!(cacheEntry->_status.status1 & 1)) - ; - - if (cacheEntry->_soundData) - removeFromCache(cacheEntry); - - _soundCache.push_back(entry); - entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); - } else { - _soundCache.push_back(entry); - entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); - } - - return true; -} - -void SoundManager::removeFromCache(SoundEntry *entry) { - for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if ((*i) == entry) { - // Remove sound buffer - entry->_soundData = NULL; - - // Remove entry from sound cache - i = _soundCache.reverse_erase(i); - } - } -} - -void SoundManager::clearStatus() { - Common::StackLock locker(_mutex); - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->_status.status |= kSoundStatusClear3; -} - -void SoundManager::processEntry(EntityIndex entity) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(entity); - if (entry) { - entry->update(0); - entry->setEntity(kEntityPlayer); - } -} - -void SoundManager::processEntry(SoundType type) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(type); - if (entry) - entry->update(0); -} - -void SoundManager::setupEntry(SoundType type, EntityIndex index) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(type); - if (entry) - entry->setEntity(index); -} - -void SoundManager::processEntry(Common::String filename) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(filename); - if (entry) { - entry->update(0); - entry->setEntity(kEntityPlayer); - } -} - -void SoundManager::processEntries() { - _state = 0; - - processEntry(kSoundType1); - processEntry(kSoundType2); -} - -uint32 SoundManager::getEntryTime(EntityIndex index) { - Common::StackLock locker(_mutex); - - SoundEntry *entry = getEntry(index); - if (entry) - return entry->_time; - - return 0; -} - -////////////////////////////////////////////////////////////////////////// -// Misc -////////////////////////////////////////////////////////////////////////// - -void SoundManager::unknownFunction4() { - // TODO: Add mutex ? - warning("Sound::unknownFunction4: not implemented!"); -} - -////////////////////////////////////////////////////////////////////////// -// Entry search -////////////////////////////////////////////////////////////////////////// -SoundEntry *SoundManager::getEntry(EntityIndex index) { - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->getEntity() == index) - return *i; - } - - return NULL; -} - -SoundEntry *SoundManager::getEntry(Common::String name) { - if (!name.contains('.')) - name += ".SND"; - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->_name2 == name) - return *i; - } - - return NULL; -} - -SoundEntry *SoundManager::getEntry(SoundType type) { - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->getType() == type) - return *i; - } - - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -// Savegame -////////////////////////////////////////////////////////////////////////// -void SoundManager::saveLoadWithSerializer(Common::Serializer &s) { - Common::StackLock locker(_mutex); - - s.syncAsUint32LE(_state); - s.syncAsUint32LE(_currentType); - - // Compute the number of entries to save - uint32 numEntries = count(); - s.syncAsUint32LE(numEntries); - - // Save or load each entry data - if (s.isSaving()) { - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->saveLoadWithSerializer(s); - } else { - warning("Sound::saveLoadWithSerializer: loading not implemented"); - s.skip(numEntries * 64); - } -} - - -// FIXME: We probably need another mutex here to protect during the whole savegame process -// as we could have removed an entry between the time we check the count and the time we -// save the entries -uint32 SoundManager::count() { - Common::StackLock locker(_mutex); - - uint32 numEntries = 0; - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - if ((*i)->_name2.matchString("NISSND?")) - ++numEntries; - - return numEntries; -} - -////////////////////////////////////////////////////////////////////////// -// Game-related functions +// Sound-related functions ////////////////////////////////////////////////////////////////////////// void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundFlag flag, byte a4) { - if (isBuffered(entity) && entity) - removeFromQueue(entity); + if (_queue->isBuffered(entity) && entity) + _queue->removeFromQueue(entity); SoundFlag currentFlag = (flag == -1) ? getSoundFlag(entity) : (SoundFlag)(flag | 0x80000); @@ -473,8 +154,6 @@ void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundF bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4) { SoundEntry *entry = new SoundEntry(_engine); - Common::StackLock locker(_mutex); - entry->open(filename, flag, 30); entry->_entity = entity; @@ -623,13 +302,13 @@ void SoundManager::playSteam(CityIndex index) { if (index >= ARRAYSIZE(cities)) error("SoundManager::playSteam: invalid city index (was %d, max %d)", index, ARRAYSIZE(cities)); - _state |= kSoundState2; + _queue->resetState(kSoundState2); - if (!getEntry(kSoundType1)) + if (!_queue->getEntry(kSoundType1)) playSoundWithSubtitles("STEAM.SND", kFlagSteam, kEntitySteam); // Get the new sound entry and show subtitles - SoundEntry *entry = getEntry(kSoundType1); + SoundEntry *entry = _queue->getEntry(kSoundType1); if (entry) entry->showSubtitle(cities[index]); } @@ -679,8 +358,8 @@ void SoundManager::playFightSound(byte action, byte a4) { } void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4) { - if (isBuffered(getDialogName(entityDialog))) - removeFromQueue(getDialogName(entityDialog)); + if (_queue->isBuffered(getDialogName(entityDialog))) + _queue->removeFromQueue(getDialogName(entityDialog)); playSound(entity, getDialogName(entityDialog), flag, a4); } @@ -993,7 +672,7 @@ const char *SoundManager::getDialogName(EntityIndex entity) const { // Letters & Messages ////////////////////////////////////////////////////////////////////////// void SoundManager::readText(int id){ - if (!isBuffered(kEntityTables4)) + if (!_queue->isBuffered(kEntityTables4)) return; if (id < 0 || (id > 8 && id < 50) || id > 64) @@ -1004,8 +683,8 @@ void SoundManager::readText(int id){ // Check if file is in cache for id [1;8] if (id <= 8) - if (isBuffered(text)) - removeFromQueue(text); + if (_queue->isBuffered(text)) + _queue->removeFromQueue(text); playSound(kEntityTables4, text, kFlagDefault); } @@ -1193,7 +872,7 @@ void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compar } void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag flag) { - if (isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain) + if (_queue->isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain) return; if (entity2 == kEntityFrancois || entity2 == kEntityMax) @@ -1597,73 +1276,18 @@ SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { return ret; } -////////////////////////////////////////////////////////////////////////// -// Subtitles -////////////////////////////////////////////////////////////////////////// -void SoundManager::updateSubtitles() { - Common::StackLock locker(_mutex); - - uint32 index = 0; - SubtitleEntry *subtitle = NULL; - - for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { - uint32 current_index = 0; - SoundEntry *soundEntry = (*i)->getSoundEntry(); - SoundStatus status = (SoundStatus)soundEntry->_status.status; - - if (!(status & kSoundStatus_40) - || status & kSoundStatus_180 - || soundEntry->_time == 0 - || (status & kSoundStatusClear1) < 6 - || ((getFlags()->nis & 0x8000) && soundEntry->_priority < 90)) { - current_index = 0; - } else { - current_index = soundEntry->_priority + (status & kSoundStatusClear1); - - if (_currentSubtitle == (*i)) - current_index += 4; - } - - if (index < current_index) { - index = current_index; - subtitle = (*i); - } - } - - if (_currentSubtitle == subtitle) { - if (subtitle) - subtitle->setupAndDraw(); - - return; - } - - if (_subtitlesFlag & 1) - subtitle->drawOnScreen(); - - if (subtitle) { - subtitle->loadData(); - subtitle->setupAndDraw(); - } -} - ////////////////////////////////////////////////////////////////////////// // Misc ////////////////////////////////////////////////////////////////////////// void SoundManager::playLoopingSound(int param) { - Common::List::iterator snd; - char tmp[80]; + SoundEntry *entry = _queue->getEntry(kSoundType1); - for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { - if ((*snd)->getType() == kSoundType1) - break; - } - - byte numLoops[8]; static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, kPosition_6470, kPosition_5790, kPosition_4840, kPosition_4070, kPosition_3050, kPosition_2740 }; + byte numLoops[8]; numLoops[1] = 4; numLoops[2] = 2; numLoops[3] = 2; @@ -1671,13 +1295,14 @@ void SoundManager::playLoopingSound(int param) { numLoops[5] = 2; numLoops[6] = 2; + char tmp[80]; tmp[0] = 0; int partNumber = 1; int fnameLen = 6; - if (_state & 1 && param >= 0x45 && param <= 0x46) { - if (_state & 2) { + if (_queue->getSoundState() & 1 && param >= 0x45 && param <= 0x46) { + if (_queue->getSoundState() & 2) { strcpy(tmp, "STEAM.SND"); _loopingSoundDuration = 32767; @@ -1727,390 +1352,28 @@ void SoundManager::playLoopingSound(int param) { } } - if (partNumber != 99) { + if (partNumber != 99) sprintf(tmp, "LOOP%d%c.SND", partNumber, _engine->getRandom().getRandomNumber(numLoops[partNumber] - 1) + 'A'); - } } if (getFlags()->flag_3) fnameLen = 5; - if (!*snd || scumm_strnicmp((*snd)->_name2.c_str(), tmp, fnameLen)) { + if (!entry || scumm_strnicmp(entry->_name2.c_str(), tmp, fnameLen)) { _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; if (partNumber != 99) { playSoundWithSubtitles(tmp, kFlagLoopedSound, kEntitySteam); - if (*snd) - (*snd)->update(0); + if (entry) + entry->update(0); - for (snd = _soundList.begin(); snd != _soundList.end(); ++snd) { - if ((*snd)->getType() == kSoundType1) { - (*snd)->update(7); - break; - } - } + SoundEntry *entry1 = _queue->getEntry(kSoundType1); + if (entry1) + entry1->update(7); } } } } -void SoundManager::stopAllSound() { - Common::StackLock locker(_mutex); - - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->_soundStream->stop(); -} - -////////////////////////////////////////////////////////////////////////// -// Sound filter -////////////////////////////////////////////////////////////////////////// - -static const int filterData[1424] = { - 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, - 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, - 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, - 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, - 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, - 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, - 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, - 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, - 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, - 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, - 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, - 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, - 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, - 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, - 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, - 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, - 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, - 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, - 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, - 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, - 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, - 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, - 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, - 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, - 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, - 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, - 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, - 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, - 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, - 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, - 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, - 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, - 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, - 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, - 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, - 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, - 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, - 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, - 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, - 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, - 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, - 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, - 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, - 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, - 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, - 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, - 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, - 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, - 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, - 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, - 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, - 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, - 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, - 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, - 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, - 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, - 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, - 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, - 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, - 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, - 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, - 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, - 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, - 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, - 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, - 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, - 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, - 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, - 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, - 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, - 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, - 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, - 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, - 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, - 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, - 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, - 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, - 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, - 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, - 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, - 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, - 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, - 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, - 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, - 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, - 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, - 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, - 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, - 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, - 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, - 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, - 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, - 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, - 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, - 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, - 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, - 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, - 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, - 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, - 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, - 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, - 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, - 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, - 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, - 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, - 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, - 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, - 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, - 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, - 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, - 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, - 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, - 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, - 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, - 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, - 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, - 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, - 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, - 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, - 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, - 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, - 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, - 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, - 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, - 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, - 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, - 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, - 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, - 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, - 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, - 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, - 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, - 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, - 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, - 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, - 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, - 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, - 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, - 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, - 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, - 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, - 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, - 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, - 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, - 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, - 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, - 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, - 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, - 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, - 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, - 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, - 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, - 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, - 5632 -}; - -static const int filterData2[1424] = { - 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, - -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, - -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, - -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, - -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, - 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, - 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, - -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, - -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, - -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, - 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, - 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, - -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, - -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, - -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, - 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, - 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, - -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, - -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, - 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, - 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, - -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, - -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, - -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, - 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, - 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, - -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, - -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, - 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, - 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, - -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, - -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, - 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, - -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, - -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, - 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, - 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, - -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, - 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, - 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, - -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, - 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, - 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, - -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, - 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, - 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, - -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, - 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, - -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, - -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, - 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, - -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, - -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, - 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, - -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, - 631, -42, -126, -210, -294, -379, -463, -547, -631, - 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, - -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, - 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, - -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, - -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, - 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, - -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, - -68, -204, -340, -476, -612, -748, -884, -1020, 74, - 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, - -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, - 904, 1069, 1233, -82, -246, -411, -575, -740, -904, - -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, - -90, -271, -452, -633, -814, -995, -1176, -1357, 99, - 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, - -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, - 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, - -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, - 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, - -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, - -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, - 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, - -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, - 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, - -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, - 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, - -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, - -194, -582, -970, -1358, -1746, -2134, -2522, -2910, - 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, - -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, - 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, - -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, - 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, - -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, - 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, - -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, - 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, - -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, - 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, - -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, - -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, - 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, - -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, - 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, - -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, - 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, - -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, - 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, - -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, - 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, - -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, - 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, - -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, - 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, - -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, - -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, - 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, - -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, - 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, - -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, - 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, - -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, - 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, - -5933, -8306, -10679, -13052, -15426, -17799, 1305, - 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, - -3915, -6526, -9136, -11747, -14357, -16968, -19578, - 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, - -1435, -4307, -7179, -10051, -12922, -15794, -18666, - -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, - 23690, -1579, -4738, -7896, -11055, -14214, -17373, - -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, - 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, - -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, - 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, - -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, - 27329, 31533, -2102, -6306, -10511, -14715, -18920, - -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, - 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, - -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, - 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, - -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, - 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, - -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, - 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, - -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, - 32767, 32767, 32767, -3385, -10157, -16928, -23700, - -30471, -32767, -32767, -32767, 3724, 11172, 18621, - 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, - -26069, -32767, -32767, -32767, -32767, 4095, 12287, - 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, - -20479, -28671, -32767, -32767, -32767, -32767 -}; - -static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; -static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2); - -void SoundManager::applyFilter(SoundEntry *entry, int16 *buffer) { - if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) { - entry->_status.status |= 0x20000000; - } else { - int variant = entry->_status.status & 0x1f; - - soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]); - } -} - - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { - int data1, data2, data1p, data2p; - byte idx; - - data2 = data[0]; - data1 = data[1] << 6; - - data += 2; - - for (int count = 0; count < 735; count++) { - idx = data[count] >> 4; - data1p = filterData[idx + data1]; - data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); - - buffer[2 * count] = (p2 * data2p) >> p1; - - idx = data[count] & 0xF; - - data1 = filterData[idx + data1p]; - data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); - buffer[2 * count + 1] = (p2 * data2) >> p1; - } -} - - } // End of namespace LastExpress diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h index 414fb0d028..797e52646e 100644 --- a/engines/lastexpress/game/sound.h +++ b/engines/lastexpress/game/sound.h @@ -25,55 +25,18 @@ #include "lastexpress/shared.h" -#include "lastexpress/helpers.h" - -#include "common/list.h" -#include "common/mutex.h" -#include "common/system.h" -#include "common/serializer.h" +#include "common/str.h" namespace LastExpress { class LastExpressEngine; -class SubtitleManager; -class SoundEntry; -class SubtitleEntry; +class SoundQueue; -class SoundManager : Common::Serializable { +class SoundManager { public: SoundManager(LastExpressEngine *engine); ~SoundManager(); - // Timer - void handleTimer(); - - // State - void resetState() { _state |= kSoundType1; } - - // Sound queue - void updateQueue(); - void resetQueue(SoundType type1, SoundType type2 = kSoundTypeNone); - void clearQueue(); - - // Subtitles - void updateSubtitles(); - - // Entry - bool isBuffered(Common::String filename, bool testForEntity = false); - bool isBuffered(EntityIndex entity); - void setupEntry(SoundType type, EntityIndex index); - void processEntry(EntityIndex entity); - void processEntry(SoundType type); - void processEntry(Common::String filename); - void processEntries(); - void removeFromQueue(Common::String filename); - void removeFromQueue(EntityIndex entity); - uint32 getEntryTime(EntityIndex index); - - // Misc - void unknownFunction4(); - void clearStatus(); - // Sound playing void playSound(EntityIndex entity, Common::String filename, SoundFlag flag = kFlagInvalid, byte a4 = 0); bool playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4 = 0); @@ -83,7 +46,6 @@ public: void playFightSound(byte action, byte a4); void playLocomotiveSound(); void playWarningCompartment(EntityIndex entity, ObjectIndex compartment); - void playLoopingSound(int param); // Dialog & Letters @@ -97,64 +59,16 @@ public: const char *wrongDoorCath() const; const char *justAMinuteCath() const; - // FLags + // Flags SoundFlag getSoundFlag(EntityIndex index) const; - // Debug - void stopAllSound(); - - // Serializable - void saveLoadWithSerializer(Common::Serializer &ser); - uint32 count(); - // Accessors - uint32 getFlag() { return _flag; } - int getSubtitleFlag() { return _subtitlesFlag; } - void setSubtitleFlag(int flag) { _subtitlesFlag = flag; } - SoundType getCurrentType() { return _currentType; } - void setCurrentType(SoundType type) { _currentType = type; } + SoundQueue *getQueue() { return _queue; } uint32 getData2() { return _data2; } - // Subtitles - void addSubtitle(SubtitleEntry *entry) { _subtitles.push_back(entry); } - void removeSubtitle(SubtitleEntry *entry) { _subtitles.remove(entry); } - void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } - SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } - - // Queue - bool setupCache(SoundEntry *entry); - void addToQueue(SoundEntry *entry) { _soundList.push_back(entry); } - - SoundEntry *getEntry(SoundType type); - private: - typedef int32 *SoundBuffer; - - enum SoundState { - kSoundState0 = 0, - kSoundState1 = 1, - kSoundState2 = 2 - }; - - // Engine LastExpressEngine *_engine; - - // State flag - int _state; - SoundType _currentType; - - Common::Mutex _mutex; - - // Unknown data - uint32 _data0; - uint32 _data1; - uint32 _data2; - - // TODO: this seems to be a synchronization flag for the sound timer - uint32 _flag; - - // Filters - int32 _buffer[2940]; ///< Static sound buffer + SoundQueue *_queue; // Compartment warnings by Mertens or Coudert uint32 _lastWarning[12]; @@ -162,23 +76,10 @@ private: // Looping sound int _loopingSoundDuration; - // Sound entries - Common::List _soundList; ///< List of all sound entries - Common::List _soundCache; ///< List of entries with a data buffer - void *_soundCacheData; - - SoundEntry *getEntry(EntityIndex index); - SoundEntry *getEntry(Common::String name); - - void removeFromCache(SoundEntry *entry); - - // Subtitles - int _subtitlesFlag; - Common::List _subtitles; - SubtitleEntry *_currentSubtitle; - - // Sound filter - void applyFilter(SoundEntry *entry, int16 *buffer); + // Unknown data + uint32 _data0; + uint32 _data1; + uint32 _data2; }; } // End of namespace LastExpress diff --git a/engines/lastexpress/helpers.h b/engines/lastexpress/helpers.h index 594c8b0400..7f3f1e246c 100644 --- a/engines/lastexpress/helpers.h +++ b/engines/lastexpress/helpers.h @@ -63,6 +63,7 @@ // Sound #define getSound() _engine->getSoundManager() +#define getSoundQueue() _engine->getSoundManager()->getQueue() // Others #define getEntityData(entity) getEntities()->getData(entity) diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index 73893c9982..2829f60740 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -32,6 +32,8 @@ #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/resource.h" @@ -151,8 +153,8 @@ Common::Error LastExpressEngine::run() { _menu->show(false, kSavegameTypeIndex, 0); while (!shouldQuit()) { - _soundMan->updateQueue(); - _soundMan->updateSubtitles(); + _soundMan->getQueue()->updateQueue(); + _soundMan->getQueue()->updateSubtitles(); if (handleEvents()) continue; @@ -280,7 +282,7 @@ void LastExpressEngine::soundTimer(void *refCon) { void LastExpressEngine::handleSoundTimer() { if (_frameCounter & 1) if (_soundMan) - _soundMan->handleTimer(); + _soundMan->getQueue()->handleTimer(); _frameCounter++; } diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp index 74a2c77a01..288e53fc11 100644 --- a/engines/lastexpress/menu/menu.cpp +++ b/engines/lastexpress/menu/menu.cpp @@ -41,6 +41,8 @@ #include "lastexpress/menu/clock.h" #include "lastexpress/menu/trainline.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -336,7 +338,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) { if (getFlags()->mouseRightClick) break; - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); } } } @@ -348,10 +350,10 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) { init(doSavegame, type, value); // Setup sound - getSound()->unknownFunction4(); - getSound()->resetQueue(kSoundType11, kSoundType13); - if (getSound()->isBuffered("TIMER")) - getSound()->removeFromQueue("TIMER"); + getSoundQueue()->resetQueue(); + getSoundQueue()->resetQueue(kSoundType11, kSoundType13); + if (getSoundQueue()->isBuffered("TIMER")) + getSoundQueue()->removeFromQueue("TIMER"); // Init flags & misc _isShowingCredits = false; @@ -411,13 +413,13 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { if (clicked) { showFrame(kOverlayButtons, kButtonQuitPushed, true); - getSound()->clearStatus(); - getSound()->updateQueue(); + getSoundQueue()->clearStatus(); + getSoundQueue()->updateQueue(); getSound()->playSound(kEntityPlayer, "LIB046"); // FIXME uncomment when sound queue is properly implemented - /*while (getSound()->isBuffered("LIB046")) - getSound()->updateQueue();*/ + /*while (getSoundQueue()->isBuffered("LIB046")) + getSoundQueue()->updateQueue();*/ getFlags()->shouldRedraw = false; @@ -484,7 +486,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { setLogicEventHandlers(); if (_index) { - getSound()->processEntry(kSoundType11); + getSoundQueue()->processEntry(kSoundType11); } else { if (!getFlags()->mouseRightClick) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 3)); @@ -496,7 +498,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { getScenes()->loadScene((SceneIndex)(5 * _gameId + 5)); if (!getFlags()->mouseRightClick) { - getSound()->processEntry(kSoundType11); + getSoundQueue()->processEntry(kSoundType11); // Show intro Animation animation; @@ -512,7 +514,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { if (!getEvent(kEventIntro)) { getEvent(kEventIntro) = 1; - getSound()->processEntry(kSoundType11); + getSoundQueue()->processEntry(kSoundType11); } } @@ -707,7 +709,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { while (nextFrameCount > getFrameCount()) { _engine->pollEvents(); - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); } } else { showFrame(kOverlayButtons, kButtonVolumeDown, true); @@ -742,7 +744,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) { while (nextFrameCount > getFrameCount()) { _engine->pollEvents(); - getSound()->updateQueue(); + getSoundQueue()->updateQueue(); } } else { showFrame(kOverlayButtons, kButtonVolumeUp, true); @@ -1117,8 +1119,8 @@ void Menu::updateTime(uint32 time) { _currentTime = time; if (_time != time) { - if (getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", kFlagMenuClock, kEntityChapters); adjustIndex(_currentTime, _time, false); @@ -1249,8 +1251,8 @@ void Menu::adjustTime() { _time = _currentTime; } - if (_currentTime == _time && getSound()->isBuffered(kEntityChapters)) - getSound()->removeFromQueue(kEntityChapters); + if (_currentTime == _time && getSoundQueue()->isBuffered(kEntityChapters)) + getSoundQueue()->removeFromQueue(kEntityChapters); _clock->draw(_time); _trainLine->draw(_time); diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index eff68efb73..355ecba33b 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -67,6 +67,7 @@ MODULE_OBJS := \ menu/menu.o \ menu/trainline.o \ sound/entry.o \ + sound/queue.o \ debug.o \ detection.o \ graphics.o \ diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index d1730eefce..69816a3d6c 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -83,6 +83,12 @@ enum SoundFlag { kFlagType9 = 0x7000000 }; +enum SoundState { + kSoundState0 = 0, + kSoundState1 = 1, + kSoundState2 = 2 +}; + ////////////////////////////////////////////////////////////////////////// // Time values ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 304d524f45..817416110e 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -27,6 +27,8 @@ #include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/queue.h" + #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" @@ -70,6 +72,7 @@ SoundEntry::~SoundEntry() { delete _soundStream; + // Zero passed pointers _engine = NULL; } @@ -79,10 +82,10 @@ void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { setStatus(flag); // Add entry to sound list - getSound()->addToQueue(this); + getSoundQueue()->addToQueue(this); // Add entry to cache and load sound data - getSound()->setupCache(this); + getSoundQueue()->setupCache(this); loadSoundData(name); } @@ -90,7 +93,7 @@ void SoundEntry::close() { _status.status |= kSoundStatusRemoved; // Loop until ready - while (!(_status.status1 & 4) && !(getSound()->getFlag() & 8) && (getSound()->getFlag() & 1)) + while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) ; // empty loop body // The original game remove the entry from the cache here, @@ -115,16 +118,16 @@ void SoundEntry::setType(SoundFlag flag) { switch (flag & kFlagType9) { default: case kFlagNone: - _type = getSound()->getCurrentType(); - getSound()->setCurrentType((SoundType)(_type + 1)); + _type = getSoundQueue()->getCurrentType(); + getSoundQueue()->setCurrentType((SoundType)(_type + 1)); break; case kFlagType1_2: { - SoundEntry *previous2 = getSound()->getEntry(kSoundType2); + SoundEntry *previous2 = getSoundQueue()->getEntry(kSoundType2); if (previous2) previous2->update(0); - SoundEntry *previous = getSound()->getEntry(kSoundType1); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType1); if (previous) { previous->setType(kSoundType2); previous->update(0); @@ -135,7 +138,7 @@ void SoundEntry::setType(SoundFlag flag) { break; case kFlagType3: { - SoundEntry *previous = getSound()->getEntry(kSoundType3); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType3); if (previous) { previous->setType(kSoundType4); previous->update(0); @@ -146,7 +149,7 @@ void SoundEntry::setType(SoundFlag flag) { break; case kFlagType7: { - SoundEntry *previous = getSound()->getEntry(kSoundType7); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType7); if (previous) previous->setType(kSoundType8); @@ -155,7 +158,7 @@ void SoundEntry::setType(SoundFlag flag) { break; case kFlagType9: { - SoundEntry *previous = getSound()->getEntry(kSoundType9); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType9); if (previous) previous->setType(kSoundType10); @@ -164,7 +167,7 @@ void SoundEntry::setType(SoundFlag flag) { break; case kFlagType11: { - SoundEntry *previous = getSound()->getEntry(kSoundType11); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType11); if (previous) previous->setType(kSoundType14); @@ -173,7 +176,7 @@ void SoundEntry::setType(SoundFlag flag) { break; case kFlagType13: { - SoundEntry *previous = getSound()->getEntry(kSoundType13); + SoundEntry *previous = getSoundQueue()->getEntry(kSoundType13); if (previous) previous->setType(kSoundType14); @@ -221,7 +224,7 @@ void SoundEntry::update(uint val) { _status.status |= kSoundStatus_100000; if (val) { - if (getSound()->getFlag() & 32) { + if (getSoundQueue()->getFlag() & 32) { _field_40 = val; value2 = val * 2 + 1; } @@ -235,7 +238,7 @@ void SoundEntry::update(uint val) { } void SoundEntry::updateState() { - if (getSound()->getFlag() & 32) { + if (getSoundQueue()->getFlag() & 32) { if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { uint32 newStatus = _status.status & kSoundStatusClear1; @@ -318,7 +321,7 @@ SubtitleEntry::~SubtitleEntry() { void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) { // Add ourselves to the list of active subtitles - getSound()->addSubtitle(this); + getSoundQueue()->addSubtitle(this); // Set sound entry and filename _filename = filename + ".SBE"; @@ -326,7 +329,7 @@ void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) { // Load subtitle data if (_engine->getResourceManager()->hasFile(filename)) { - if (getSound()->getSubtitleFlag() & 2) + if (getSoundQueue()->getSubtitleFlag() & 2) return; loadData(); @@ -339,8 +342,8 @@ void SubtitleEntry::loadData() { _data = new SubtitleManager(_engine->getFont()); _data->load(getArchive(_filename)); - getSound()->setSubtitleFlag(getSound()->getSubtitleFlag() | 2); - getSound()->setCurrentSubtitle(this); + getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() | 2); + getSoundQueue()->setCurrentSubtitle(this); } void SubtitleEntry::setupAndDraw() { @@ -354,32 +357,32 @@ void SubtitleEntry::setupAndDraw() { } else { _data->setTime((uint16)_sound->_time); - if (getSound()->getSubtitleFlag() & 1) + if (getSoundQueue()->getSubtitleFlag() & 1) drawOnScreen(); } - getSound()->setCurrentSubtitle(this); + getSoundQueue()->setCurrentSubtitle(this); } void SubtitleEntry::draw() { // Remove ourselves from the queue - getSound()->removeSubtitle(this); + getSoundQueue()->removeSubtitle(this); - if (this == getSound()->getCurrentSubtitle()) { + if (this == getSoundQueue()->getCurrentSubtitle()) { drawOnScreen(); - getSound()->setCurrentSubtitle(NULL); - getSound()->setSubtitleFlag(0); + getSoundQueue()->setCurrentSubtitle(NULL); + getSoundQueue()->setSubtitleFlag(0); } } void SubtitleEntry::drawOnScreen() { - getSound()->setSubtitleFlag(getSound()->getSubtitleFlag() & -1); + getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() & -1); if (_data == NULL) return; - if (getSound()->getSubtitleFlag() & 1) + if (getSoundQueue()->getSubtitleFlag() & 1) _engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay); } diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp new file mode 100644 index 0000000000..9126f5709d --- /dev/null +++ b/engines/lastexpress/sound/queue.cpp @@ -0,0 +1,795 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/sound/queue.h" + +#include "lastexpress/game/logic.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/sound/entry.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/lastexpress.h" + +namespace LastExpress { + +#define SOUNDCACHE_ENTRY_SIZE 92160 +#define SOUNDCACHE_MAX_SIZE 6 + +SoundQueue::SoundQueue(LastExpressEngine *engine) : _engine(engine) { + _state = 0; + _currentType = kSoundType16; + _flag = 0; + + // Cache and filter buffers + memset(&_buffer, 0, sizeof(_buffer)); + _soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE); + + _subtitlesFlag = 0; + _currentSubtitle = NULL; +} + +SoundQueue::~SoundQueue() { + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + SAFE_DELETE(*i); + _soundList.clear(); + + // Entries in the cache are just pointers to sound list entries + _soundCache.clear(); + + for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) + SAFE_DELETE(*i); + _subtitles.clear(); + + _currentSubtitle = NULL; + + free(_soundCacheData); + + // Zero passed pointers + _engine = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Timer +////////////////////////////////////////////////////////////////////////// +void SoundQueue::handleTimer() { + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + SoundEntry *entry = (*i); + if (entry->_stream == NULL) { + SAFE_DELETE(*i); + i = _soundList.reverse_erase(i); + continue; + } else if (!entry->_soundStream) { + entry->_soundStream = new StreamedSound(); + + // TODO: stream any sound in the queue after filtering + entry->_soundStream->load(entry->_stream); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// Sound queue management +////////////////////////////////////////////////////////////////////////// +void SoundQueue::addToQueue(SoundEntry *entry) { + _soundList.push_back(entry); +} + +void SoundQueue::removeFromQueue(EntityIndex entity) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(entity); + if (entry) + entry->reset(); +} + +void SoundQueue::removeFromQueue(Common::String filename) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(filename); + if (entry) + entry->reset(); +} + +void SoundQueue::updateQueue() { + Common::StackLock locker(_mutex); + + warning("Sound::updateQueue: not implemented!"); +} + +void SoundQueue::resetQueue() { + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->getType() == kSoundType1) { + (*i)->reset(); + break; + } + } + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->getType() == kSoundType2) { + (*i)->reset(); + break; + } + } +} + +void SoundQueue::resetQueue(SoundType type1, SoundType type2) { + if (!type2) + type2 = type1; + + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->getType() != type1 && (*i)->getType() != type2) + (*i)->reset(); + } +} + +void SoundQueue::clearQueue() { + _flag |= 4; + + // FIXME: Wait a while for a flag to be set + //for (int i = 0; i < 3000000; i++) + // if (_flag & 8) + // break; + + _flag |= 8; + + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + SoundEntry *entry = (*i); + + // Delete entry + entry->close(); + SAFE_DELETE(entry); + + i = _soundList.reverse_erase(i); + } + + updateSubtitles(); +} + +////////////////////////////////////////////////////////////////////////// +// State +////////////////////////////////////////////////////////////////////////// +void SoundQueue::clearStatus() { + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + (*i)->_status.status |= kSoundStatusClear3; +} + +////////////////////////////////////////////////////////////////////////// +// Entry management +////////////////////////////////////////////////////////////////////////// +void SoundQueue::setupEntry(SoundType type, EntityIndex index) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(type); + if (entry) + entry->setEntity(index); +} + +void SoundQueue::processEntry(EntityIndex entity) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(entity); + if (entry) { + entry->update(0); + entry->setEntity(kEntityPlayer); + } +} + +void SoundQueue::processEntry(SoundType type) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(type); + if (entry) + entry->update(0); +} + +void SoundQueue::processEntry(Common::String filename) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(filename); + if (entry) { + entry->update(0); + entry->setEntity(kEntityPlayer); + } +} + +void SoundQueue::processEntries() { + _state = 0; + + processEntry(kSoundType1); + processEntry(kSoundType2); +} + +SoundEntry *SoundQueue::getEntry(EntityIndex index) { + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->getEntity() == index) + return *i; + } + + return NULL; +} + +SoundEntry *SoundQueue::getEntry(Common::String name) { + if (!name.contains('.')) + name += ".SND"; + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->_name2 == name) + return *i; + } + + return NULL; +} + +SoundEntry *SoundQueue::getEntry(SoundType type) { + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { + if ((*i)->getType() == type) + return *i; + } + + return NULL; +} + +uint32 SoundQueue::getEntryTime(EntityIndex index) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(index); + if (entry) + return entry->_time; + + return 0; +} + +bool SoundQueue::isBuffered(EntityIndex entity) { + Common::StackLock locker(_mutex); + + return (getEntry(entity) != NULL); +} + +bool SoundQueue::isBuffered(Common::String filename, bool testForEntity) { + Common::StackLock locker(_mutex); + + SoundEntry *entry = getEntry(filename); + + if (testForEntity) + return entry != NULL && entry->getEntity() != kEntityPlayer; + + return (entry != NULL); +} + +////////////////////////////////////////////////////////////////////////// +// Subtitles +////////////////////////////////////////////////////////////////////////// +void SoundQueue::updateSubtitles() { + Common::StackLock locker(_mutex); + + uint32 index = 0; + SubtitleEntry *subtitle = NULL; + + for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { + uint32 current_index = 0; + SoundEntry *soundEntry = (*i)->getSoundEntry(); + SoundStatus status = (SoundStatus)soundEntry->_status.status; + + if (!(status & kSoundStatus_40) + || status & kSoundStatus_180 + || soundEntry->_time == 0 + || (status & kSoundStatusClear1) < 6 + || ((getFlags()->nis & 0x8000) && soundEntry->_priority < 90)) { + current_index = 0; + } else { + current_index = soundEntry->_priority + (status & kSoundStatusClear1); + + if (_currentSubtitle == (*i)) + current_index += 4; + } + + if (index < current_index) { + index = current_index; + subtitle = (*i); + } + } + + if (_currentSubtitle == subtitle) { + if (subtitle) + subtitle->setupAndDraw(); + + return; + } + + if (_subtitlesFlag & 1) + subtitle->drawOnScreen(); + + if (subtitle) { + subtitle->loadData(); + subtitle->setupAndDraw(); + } +} + +////////////////////////////////////////////////////////////////////////// +// Cache +////////////////////////////////////////////////////////////////////////// +bool SoundQueue::setupCache(SoundEntry *entry) { + if (entry->_soundData) + return true; + + if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) { + + SoundEntry *cacheEntry = NULL; + uint32 size = 1000; + + for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { + if (!((*i)->_status.status & kSoundStatus_180)) { + uint32 newSize = (*i)->_priority + ((*i)->_status.status & kSoundStatusClear1); + + if (newSize < size) { + cacheEntry = (*i); + size = newSize; + } + } + } + + if (entry->_priority <= size) + return false; + + if (!cacheEntry) + error("[SoundManager::setupCache] Cannot find a valid entry"); + + cacheEntry->setInCache(); + + // TODO: Wait until the cache entry is ready to be removed + while (!(cacheEntry->_status.status1 & 1)) + ; + + if (cacheEntry->_soundData) + removeFromCache(cacheEntry); + + _soundCache.push_back(entry); + entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); + } else { + _soundCache.push_back(entry); + entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); + } + + return true; +} + +void SoundQueue::removeFromCache(SoundEntry *entry) { + for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { + if ((*i) == entry) { + // Remove sound buffer + entry->_soundData = NULL; + + // Remove entry from sound cache + i = _soundCache.reverse_erase(i); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// Savegame +////////////////////////////////////////////////////////////////////////// +void SoundQueue::saveLoadWithSerializer(Common::Serializer &s) { + Common::StackLock locker(_mutex); + + s.syncAsUint32LE(_state); + s.syncAsUint32LE(_currentType); + + // Compute the number of entries to save + uint32 numEntries = count(); + s.syncAsUint32LE(numEntries); + + // Save or load each entry data + if (s.isSaving()) { + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + (*i)->saveLoadWithSerializer(s); + } else { + warning("Sound::saveLoadWithSerializer: loading not implemented"); + s.skip(numEntries * 64); + } +} + + +// FIXME: We probably need another mutex here to protect during the whole savegame process +// as we could have removed an entry between the time we check the count and the time we +// save the entries +uint32 SoundQueue::count() { + Common::StackLock locker(_mutex); + + uint32 numEntries = 0; + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + if ((*i)->_name2.matchString("NISSND?")) + ++numEntries; + + return numEntries; +} + +////////////////////////////////////////////////////////////////////////// +// Sound filters +////////////////////////////////////////////////////////////////////////// +static const int filterData[1424] = { + 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, + 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, + 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, + 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, + 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, + 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, + 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, + 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, + 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, + 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, + 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, + 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, + 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, + 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, + 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, + 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, + 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, + 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, + 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, + 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, + 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, + 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, + 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, + 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, + 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, + 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, + 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, + 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, + 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, + 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, + 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, + 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, + 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, + 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, + 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, + 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, + 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, + 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, + 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, + 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, + 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, + 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, + 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, + 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, + 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, + 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, + 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, + 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, + 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, + 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, + 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, + 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, + 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, + 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, + 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, + 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, + 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, + 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, + 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, + 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, + 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, + 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, + 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, + 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, + 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, + 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, + 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, + 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, + 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, + 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, + 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, + 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, + 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, + 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, + 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, + 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, + 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, + 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, + 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, + 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, + 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, + 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, + 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, + 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, + 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, + 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, + 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, + 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, + 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, + 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, + 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, + 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, + 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, + 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, + 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, + 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, + 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, + 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, + 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, + 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, + 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, + 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, + 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, + 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, + 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, + 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, + 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, + 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, + 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, + 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, + 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, + 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, + 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, + 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, + 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, + 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, + 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, + 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, + 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, + 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, + 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, + 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, + 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, + 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, + 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, + 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, + 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, + 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, + 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, + 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, + 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, + 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, + 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, + 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, + 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, + 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, + 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, + 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, + 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, + 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, + 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, + 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, + 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, + 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, + 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, + 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, + 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, + 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, + 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, + 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, + 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, + 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, + 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, + 5632 +}; + +static const int filterData2[1424] = { + 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, + -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, + -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, + -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, + -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, + 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, + 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, + -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, + -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, + -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, + 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, + 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, + -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, + -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, + -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, + 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, + 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, + -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, + -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, + 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, + 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, + -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, + -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, + -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, + 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, + 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, + -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, + -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, + 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, + 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, + -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, + -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, + 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, + -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, + -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, + 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, + -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, + 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, + 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, + -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, + 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, + 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, + -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, + 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, + 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, + -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, + 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, + -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, + -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, + 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, + -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, + -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, + 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, + -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, + 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, + -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, + 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, + -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, + -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, + 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, + -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, + -68, -204, -340, -476, -612, -748, -884, -1020, 74, + 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, + -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, + 904, 1069, 1233, -82, -246, -411, -575, -740, -904, + -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, + -90, -271, -452, -633, -814, -995, -1176, -1357, 99, + 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, + -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, + 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, + -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, + 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, + -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, + -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, + 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, + -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, + 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, + -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, + 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, + -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, + -194, -582, -970, -1358, -1746, -2134, -2522, -2910, + 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, + -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, + 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, + -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, + 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, + -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, + 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, + -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, + 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, + -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, + 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, + -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, + -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, + 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, + -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, + 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, + -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, + 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, + -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, + 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, + -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, + 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, + -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, + 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, + -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, + 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, + -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, + -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, + 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, + -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, + 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, + -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, + 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, + -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, + 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, + -5933, -8306, -10679, -13052, -15426, -17799, 1305, + 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, + -3915, -6526, -9136, -11747, -14357, -16968, -19578, + 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, + -1435, -4307, -7179, -10051, -12922, -15794, -18666, + -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, + 23690, -1579, -4738, -7896, -11055, -14214, -17373, + -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, + 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, + -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, + 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, + -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, + 27329, 31533, -2102, -6306, -10511, -14715, -18920, + -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, + 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, + -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, + 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, + -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, + 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, + -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, + 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, + -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, + 32767, 32767, 32767, -3385, -10157, -16928, -23700, + -30471, -32767, -32767, -32767, 3724, 11172, 18621, + 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, + -26069, -32767, -32767, -32767, -32767, 4095, 12287, + 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, + -20479, -28671, -32767, -32767, -32767, -32767 +}; + +static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; +static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2); + +void SoundQueue::applyFilter(SoundEntry *entry, int16 *buffer) { + if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) { + entry->_status.status |= 0x20000000; + } else { + int variant = entry->_status.status & 0x1f; + + soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]); + } +} + + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { + int data1, data2, data1p, data2p; + byte idx; + + data2 = data[0]; + data1 = data[1] << 6; + + data += 2; + + for (int count = 0; count < 735; count++) { + idx = data[count] >> 4; + data1p = filterData[idx + data1]; + data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); + + buffer[2 * count] = (p2 * data2p) >> p1; + + idx = data[count] & 0xF; + + data1 = filterData[idx + data1p]; + data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); + buffer[2 * count + 1] = (p2 * data2) >> p1; + } +} + +////////////////////////////////////////////////////////////////////////// +// Debug +////////////////////////////////////////////////////////////////////////// +void SoundQueue::stopAllSound() { + Common::StackLock locker(_mutex); + + for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) + (*i)->_soundStream->stop(); +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/sound/queue.h b/engines/lastexpress/sound/queue.h new file mode 100644 index 0000000000..3748a266e0 --- /dev/null +++ b/engines/lastexpress/sound/queue.h @@ -0,0 +1,131 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_SOUND_QUEUE_H +#define LASTEXPRESS_SOUND_QUEUE_H + +#include "lastexpress/shared.h" + +#include "common/array.h" +#include "common/mutex.h" +#include "common/serializer.h" + +namespace LastExpress { + +class LastExpressEngine; +class SoundEntry; +class SubtitleEntry; + +class SoundQueue : Common::Serializable { +public: + SoundQueue(LastExpressEngine *engine); + ~SoundQueue(); + + // Timer + void handleTimer(); + + // Queue + void addToQueue(SoundEntry *entry); + void removeFromQueue(Common::String filename); + void removeFromQueue(EntityIndex entity); + void updateQueue(); + void resetQueue(); + void resetQueue(SoundType type1, SoundType type2 = kSoundTypeNone); + void clearQueue(); + + // State + void clearStatus(); + int getSoundState() { return _state; } + void resetState() { resetState(kSoundState1); } + void resetState(SoundState state) { _state |= state; } + + // Entries + void setupEntry(SoundType type, EntityIndex index); + void processEntry(EntityIndex entity); + void processEntry(SoundType type); + void processEntry(Common::String filename); + void processEntries(); + SoundEntry *getEntry(SoundType type); + SoundEntry *getEntry(EntityIndex index); + SoundEntry *getEntry(Common::String name); + uint32 getEntryTime(EntityIndex index); + bool isBuffered(Common::String filename, bool testForEntity = false); + bool isBuffered(EntityIndex entity); + + // Subtitles + void updateSubtitles(); + void addSubtitle(SubtitleEntry *entry) { _subtitles.push_back(entry); } + void removeSubtitle(SubtitleEntry *entry) { _subtitles.remove(entry); } + void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } + SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } + + // Cache + bool setupCache(SoundEntry *entry); + + // Serializable + void saveLoadWithSerializer(Common::Serializer &ser); + uint32 count(); + + // Accessors + uint32 getFlag() { return _flag; } + int getSubtitleFlag() { return _subtitlesFlag; } + void setSubtitleFlag(int flag) { _subtitlesFlag = flag; } + SoundType getCurrentType() { return _currentType; } + void setCurrentType(SoundType type) { _currentType = type; } + +protected: + // Debug + void stopAllSound(); + +private: + LastExpressEngine *_engine; + + Common::Mutex _mutex; + + // State & shared data + int _state; + SoundType _currentType; + // TODO: this seems to be a synchronization flag for the sound timer + uint32 _flag; + + // Entries + Common::List _soundList; ///< List of all sound entries + Common::List _soundCache; ///< List of entries with a data buffer + void *_soundCacheData; + + // Subtitles + int _subtitlesFlag; + Common::List _subtitles; + SubtitleEntry *_currentSubtitle; + + // Filters + int32 _buffer[2940]; ///< Static sound buffer + + void removeFromCache(SoundEntry *entry); + void applyFilter(SoundEntry *entry, int16 *buffer); + + friend class Debugger; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SOUND_QUEUE_H -- cgit v1.2.3 From 90dc4f9a8c3f77b15c7c6d49651338dbc40c40fa Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 28 Jun 2011 22:30:24 -0400 Subject: LASTEXPRESS: Move Sound class to the sound folder --- engines/lastexpress/debug.cpp | 2 +- engines/lastexpress/entities/abbot.cpp | 2 +- engines/lastexpress/entities/alexei.cpp | 3 +- engines/lastexpress/entities/alouan.cpp | 3 +- engines/lastexpress/entities/anna.cpp | 2 +- engines/lastexpress/entities/august.cpp | 2 +- engines/lastexpress/entities/boutarel.cpp | 2 +- engines/lastexpress/entities/chapters.cpp | 2 +- engines/lastexpress/entities/cooks.cpp | 2 +- engines/lastexpress/entities/coudert.cpp | 2 +- engines/lastexpress/entities/entity.cpp | 3 +- engines/lastexpress/entities/entity.h | 2 +- engines/lastexpress/entities/gendarmes.h | 2 +- engines/lastexpress/entities/hadija.cpp | 3 +- engines/lastexpress/entities/ivo.cpp | 3 +- engines/lastexpress/entities/kahina.cpp | 2 +- engines/lastexpress/entities/kronos.cpp | 2 +- engines/lastexpress/entities/mahmud.cpp | 2 +- engines/lastexpress/entities/max.cpp | 2 +- engines/lastexpress/entities/mertens.cpp | 2 +- engines/lastexpress/entities/milos.cpp | 2 +- engines/lastexpress/entities/mmeboutarel.cpp | 2 +- engines/lastexpress/entities/pascale.cpp | 2 +- engines/lastexpress/entities/rebecca.cpp | 2 +- engines/lastexpress/entities/salko.cpp | 2 +- engines/lastexpress/entities/servers0.cpp | 3 +- engines/lastexpress/entities/servers1.cpp | 3 +- engines/lastexpress/entities/sophie.cpp | 3 +- engines/lastexpress/entities/tables.cpp | 2 +- engines/lastexpress/entities/tatiana.cpp | 2 +- engines/lastexpress/entities/train.cpp | 2 +- engines/lastexpress/entities/vassili.cpp | 2 +- engines/lastexpress/entities/verges.cpp | 2 +- engines/lastexpress/entities/vesna.cpp | 3 +- engines/lastexpress/entities/yasmin.cpp | 3 +- engines/lastexpress/fight/fighter.cpp | 3 +- engines/lastexpress/fight/fighter_anna.cpp | 3 +- engines/lastexpress/fight/fighter_ivo.cpp | 3 +- engines/lastexpress/fight/fighter_milos.cpp | 3 +- engines/lastexpress/fight/fighter_salko.cpp | 3 +- engines/lastexpress/fight/fighter_vesna.cpp | 3 +- engines/lastexpress/game/action.cpp | 2 +- engines/lastexpress/game/entities.cpp | 2 +- engines/lastexpress/game/inventory.cpp | 2 +- engines/lastexpress/game/logic.cpp | 2 +- engines/lastexpress/game/scenes.cpp | 2 +- engines/lastexpress/game/sound.cpp | 1379 -------------------------- engines/lastexpress/game/sound.h | 87 -- engines/lastexpress/lastexpress.cpp | 2 +- engines/lastexpress/menu/menu.cpp | 2 +- engines/lastexpress/module.mk | 2 +- engines/lastexpress/sound/entry.cpp | 2 +- engines/lastexpress/sound/sound.cpp | 1379 ++++++++++++++++++++++++++ engines/lastexpress/sound/sound.h | 87 ++ 54 files changed, 1527 insertions(+), 1521 deletions(-) delete mode 100644 engines/lastexpress/game/sound.cpp delete mode 100644 engines/lastexpress/game/sound.h create mode 100644 engines/lastexpress/sound/sound.cpp create mode 100644 engines/lastexpress/sound/sound.h (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index 2d22630381..dc2807db63 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -41,10 +41,10 @@ #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/abbot.cpp b/engines/lastexpress/entities/abbot.cpp index 6fcadcfa54..c5c6f2a44d 100644 --- a/engines/lastexpress/entities/abbot.cpp +++ b/engines/lastexpress/entities/abbot.cpp @@ -31,10 +31,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/alexei.cpp b/engines/lastexpress/entities/alexei.cpp index d723a5607c..073ca3f175 100644 --- a/engines/lastexpress/entities/alexei.cpp +++ b/engines/lastexpress/entities/alexei.cpp @@ -29,9 +29,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/alouan.cpp b/engines/lastexpress/entities/alouan.cpp index 715622aaab..cd79870559 100644 --- a/engines/lastexpress/entities/alouan.cpp +++ b/engines/lastexpress/entities/alouan.cpp @@ -26,9 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/anna.cpp b/engines/lastexpress/entities/anna.cpp index 2eb3a9ec85..b13aa21f6d 100644 --- a/engines/lastexpress/entities/anna.cpp +++ b/engines/lastexpress/entities/anna.cpp @@ -31,10 +31,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/august.cpp b/engines/lastexpress/entities/august.cpp index 44dd3eb579..eb3b09af59 100644 --- a/engines/lastexpress/entities/august.cpp +++ b/engines/lastexpress/entities/august.cpp @@ -33,10 +33,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/boutarel.cpp b/engines/lastexpress/entities/boutarel.cpp index cf5d286d64..315b12a69e 100644 --- a/engines/lastexpress/entities/boutarel.cpp +++ b/engines/lastexpress/entities/boutarel.cpp @@ -29,10 +29,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp index 53d89e9699..96e08ba808 100644 --- a/engines/lastexpress/entities/chapters.cpp +++ b/engines/lastexpress/entities/chapters.cpp @@ -60,10 +60,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/menu/menu.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/sound/queue.h" diff --git a/engines/lastexpress/entities/cooks.cpp b/engines/lastexpress/entities/cooks.cpp index cd8fbfd8ff..42e888cc7c 100644 --- a/engines/lastexpress/entities/cooks.cpp +++ b/engines/lastexpress/entities/cooks.cpp @@ -26,10 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/coudert.cpp b/engines/lastexpress/entities/coudert.cpp index fea08f4611..c3e7e37b88 100644 --- a/engines/lastexpress/entities/coudert.cpp +++ b/engines/lastexpress/entities/coudert.cpp @@ -29,10 +29,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp index f6d24d69ca..60efd70329 100644 --- a/engines/lastexpress/entities/entity.cpp +++ b/engines/lastexpress/entities/entity.cpp @@ -33,9 +33,10 @@ #include "lastexpress/game/state.h" #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h index 1988aef6fe..6a4f4166bb 100644 --- a/engines/lastexpress/entities/entity.h +++ b/engines/lastexpress/entities/entity.h @@ -25,7 +25,7 @@ #include "lastexpress/shared.h" -#include "lastexpress/game/sound.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/gendarmes.h b/engines/lastexpress/entities/gendarmes.h index 5c3ff1d439..d999cfc1fd 100644 --- a/engines/lastexpress/entities/gendarmes.h +++ b/engines/lastexpress/entities/gendarmes.h @@ -26,7 +26,7 @@ #include "lastexpress/entities/entity.h" #include "lastexpress/entities/entity_intern.h" -#include "lastexpress/game/sound.h" +#include "lastexpress/sound/sound.h" namespace LastExpress { diff --git a/engines/lastexpress/entities/hadija.cpp b/engines/lastexpress/entities/hadija.cpp index ce2c9718db..8ec972b939 100644 --- a/engines/lastexpress/entities/hadija.cpp +++ b/engines/lastexpress/entities/hadija.cpp @@ -26,9 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/ivo.cpp b/engines/lastexpress/entities/ivo.cpp index 861c3cf9bd..f2261b438c 100644 --- a/engines/lastexpress/entities/ivo.cpp +++ b/engines/lastexpress/entities/ivo.cpp @@ -30,9 +30,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/kahina.cpp b/engines/lastexpress/entities/kahina.cpp index 6c73784b21..2918b1e8bd 100644 --- a/engines/lastexpress/entities/kahina.cpp +++ b/engines/lastexpress/entities/kahina.cpp @@ -29,10 +29,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/kronos.cpp b/engines/lastexpress/entities/kronos.cpp index 06ebd54694..134dce9c81 100644 --- a/engines/lastexpress/entities/kronos.cpp +++ b/engines/lastexpress/entities/kronos.cpp @@ -36,10 +36,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/mahmud.cpp b/engines/lastexpress/entities/mahmud.cpp index cb782854af..0e67b45cd2 100644 --- a/engines/lastexpress/entities/mahmud.cpp +++ b/engines/lastexpress/entities/mahmud.cpp @@ -31,10 +31,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/max.cpp b/engines/lastexpress/entities/max.cpp index 924f8f77aa..eacc38bf60 100644 --- a/engines/lastexpress/entities/max.cpp +++ b/engines/lastexpress/entities/max.cpp @@ -28,10 +28,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/mertens.cpp b/engines/lastexpress/entities/mertens.cpp index 464cc343bb..e222af4805 100644 --- a/engines/lastexpress/entities/mertens.cpp +++ b/engines/lastexpress/entities/mertens.cpp @@ -30,9 +30,9 @@ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/state.h" -#include "lastexpress/game/sound.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/milos.cpp b/engines/lastexpress/entities/milos.cpp index 1526c281b2..ff3d2b6744 100644 --- a/engines/lastexpress/entities/milos.cpp +++ b/engines/lastexpress/entities/milos.cpp @@ -33,10 +33,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/mmeboutarel.cpp b/engines/lastexpress/entities/mmeboutarel.cpp index 1d4c52ca09..9ca10ca374 100644 --- a/engines/lastexpress/entities/mmeboutarel.cpp +++ b/engines/lastexpress/entities/mmeboutarel.cpp @@ -28,10 +28,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/pascale.cpp b/engines/lastexpress/entities/pascale.cpp index 8bbcf64e84..a191273702 100644 --- a/engines/lastexpress/entities/pascale.cpp +++ b/engines/lastexpress/entities/pascale.cpp @@ -27,10 +27,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/rebecca.cpp b/engines/lastexpress/entities/rebecca.cpp index 6d1c5244f2..b1a176b47e 100644 --- a/engines/lastexpress/entities/rebecca.cpp +++ b/engines/lastexpress/entities/rebecca.cpp @@ -27,10 +27,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/salko.cpp b/engines/lastexpress/entities/salko.cpp index 6dcab7121e..63d995dc42 100644 --- a/engines/lastexpress/entities/salko.cpp +++ b/engines/lastexpress/entities/salko.cpp @@ -30,10 +30,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/servers0.cpp b/engines/lastexpress/entities/servers0.cpp index 1fec775659..989bddd662 100644 --- a/engines/lastexpress/entities/servers0.cpp +++ b/engines/lastexpress/entities/servers0.cpp @@ -26,9 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/servers1.cpp b/engines/lastexpress/entities/servers1.cpp index cd0a162755..995fbbc01b 100644 --- a/engines/lastexpress/entities/servers1.cpp +++ b/engines/lastexpress/entities/servers1.cpp @@ -26,9 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/sophie.cpp b/engines/lastexpress/entities/sophie.cpp index e0c63f7297..57bd491949 100644 --- a/engines/lastexpress/entities/sophie.cpp +++ b/engines/lastexpress/entities/sophie.cpp @@ -25,9 +25,10 @@ #include "lastexpress/game/entities.h" #include "lastexpress/game/logic.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/entities/tables.cpp b/engines/lastexpress/entities/tables.cpp index 702b636c31..06ea4c597c 100644 --- a/engines/lastexpress/entities/tables.cpp +++ b/engines/lastexpress/entities/tables.cpp @@ -26,10 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/tatiana.cpp b/engines/lastexpress/entities/tatiana.cpp index 2f60b448ba..c8901b3e30 100644 --- a/engines/lastexpress/entities/tatiana.cpp +++ b/engines/lastexpress/entities/tatiana.cpp @@ -32,10 +32,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp index 74eed63bbf..7d90ea5e64 100644 --- a/engines/lastexpress/entities/train.cpp +++ b/engines/lastexpress/entities/train.cpp @@ -30,9 +30,9 @@ #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/state.h" -#include "lastexpress/game/sound.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/vassili.cpp b/engines/lastexpress/entities/vassili.cpp index a7fbc7cf32..22f41afa92 100644 --- a/engines/lastexpress/entities/vassili.cpp +++ b/engines/lastexpress/entities/vassili.cpp @@ -32,10 +32,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/verges.cpp b/engines/lastexpress/entities/verges.cpp index c18137c835..8246f85145 100644 --- a/engines/lastexpress/entities/verges.cpp +++ b/engines/lastexpress/entities/verges.cpp @@ -29,10 +29,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/vesna.cpp b/engines/lastexpress/entities/vesna.cpp index 74bc0d3ea9..7a1f1d3195 100644 --- a/engines/lastexpress/entities/vesna.cpp +++ b/engines/lastexpress/entities/vesna.cpp @@ -30,9 +30,10 @@ #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/entities/yasmin.cpp b/engines/lastexpress/entities/yasmin.cpp index 7e8b2f7348..45e5e11568 100644 --- a/engines/lastexpress/entities/yasmin.cpp +++ b/engines/lastexpress/entities/yasmin.cpp @@ -26,9 +26,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" +#include "lastexpress/sound/sound.h" + #include "lastexpress/lastexpress.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/fight/fighter.cpp b/engines/lastexpress/fight/fighter.cpp index fcd69183fb..bae7728a2b 100644 --- a/engines/lastexpress/fight/fighter.cpp +++ b/engines/lastexpress/fight/fighter.cpp @@ -25,7 +25,8 @@ #include "lastexpress/data/sequence.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" + +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/fight/fighter_anna.cpp b/engines/lastexpress/fight/fighter_anna.cpp index feb35515a0..c7660cab1a 100644 --- a/engines/lastexpress/fight/fighter_anna.cpp +++ b/engines/lastexpress/fight/fighter_anna.cpp @@ -24,9 +24,8 @@ #include "lastexpress/data/sequence.h" -#include "lastexpress/game/sound.h" - #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/fight/fighter_ivo.cpp b/engines/lastexpress/fight/fighter_ivo.cpp index 9988fca790..87a52c6be4 100644 --- a/engines/lastexpress/fight/fighter_ivo.cpp +++ b/engines/lastexpress/fight/fighter_ivo.cpp @@ -24,9 +24,8 @@ #include "lastexpress/data/sequence.h" -#include "lastexpress/game/sound.h" - #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/fight/fighter_milos.cpp b/engines/lastexpress/fight/fighter_milos.cpp index 82c965caf3..9f8e726165 100644 --- a/engines/lastexpress/fight/fighter_milos.cpp +++ b/engines/lastexpress/fight/fighter_milos.cpp @@ -25,9 +25,8 @@ #include "lastexpress/data/cursor.h" #include "lastexpress/data/sequence.h" -#include "lastexpress/game/sound.h" - #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/fight/fighter_salko.cpp b/engines/lastexpress/fight/fighter_salko.cpp index 166f7c3899..1082674235 100644 --- a/engines/lastexpress/fight/fighter_salko.cpp +++ b/engines/lastexpress/fight/fighter_salko.cpp @@ -25,9 +25,8 @@ #include "lastexpress/data/cursor.h" #include "lastexpress/data/sequence.h" -#include "lastexpress/game/sound.h" - #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/fight/fighter_vesna.cpp b/engines/lastexpress/fight/fighter_vesna.cpp index 075f158bda..02aaa1c16c 100644 --- a/engines/lastexpress/fight/fighter_vesna.cpp +++ b/engines/lastexpress/fight/fighter_vesna.cpp @@ -25,9 +25,8 @@ #include "lastexpress/data/cursor.h" #include "lastexpress/data/sequence.h" -#include "lastexpress/game/sound.h" - #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp index f195825d6e..2c7b5b3c32 100644 --- a/engines/lastexpress/game/action.cpp +++ b/engines/lastexpress/game/action.cpp @@ -39,10 +39,10 @@ #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/helpers.h" #include "lastexpress/lastexpress.h" diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp index 8dd2c26c19..a56531891b 100644 --- a/engines/lastexpress/game/entities.cpp +++ b/engines/lastexpress/game/entities.cpp @@ -68,10 +68,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp index c3a10225e9..d902c8860a 100644 --- a/engines/lastexpress/game/inventory.cpp +++ b/engines/lastexpress/game/inventory.cpp @@ -28,12 +28,12 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/menu/menu.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index cdde2a0e0a..2b7b1cfa50 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -42,12 +42,12 @@ #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/menu/menu.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp index 408f48044c..65efc80265 100644 --- a/engines/lastexpress/game/scenes.cpp +++ b/engines/lastexpress/game/scenes.cpp @@ -31,10 +31,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/object.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/game/sound.cpp b/engines/lastexpress/game/sound.cpp deleted file mode 100644 index bc4f71e18d..0000000000 --- a/engines/lastexpress/game/sound.cpp +++ /dev/null @@ -1,1379 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "lastexpress/game/sound.h" - -#include "lastexpress/game/action.h" -#include "lastexpress/game/entities.h" -#include "lastexpress/game/inventory.h" -#include "lastexpress/game/logic.h" -#include "lastexpress/game/object.h" -#include "lastexpress/game/savepoint.h" -#include "lastexpress/game/state.h" - -#include "lastexpress/sound/entry.h" -#include "lastexpress/sound/queue.h" - -#include "lastexpress/helpers.h" -#include "lastexpress/graphics.h" -#include "lastexpress/lastexpress.h" -#include "lastexpress/resource.h" - -namespace LastExpress { - -// Letters & messages -static const char *const messages[24] = { - "", - "TXT1001", // 1 - "TXT1001A", // 2 - "TXT1011", // 3 - "TXT1012", // 4 - "TXT1013", // 5 - "TXT1014", // 6 - "TXT1020", // 7 - "TXT1030", // 8 - "END1009B", // 50 - "END1046", // 51 - "END1047", // 52 - "END1112", // 53 - "END1112A", // 54 - "END1503", // 55 - "END1505A", // 56 - "END1505B", // 57 - "END1610", // 58 - "END1612A", // 59 - "END1612C", // 61 - "END1612D", // 62 - "ENDALRM1", // 63 - "ENDALRM2", // 64 - "ENDALRM3" // 65 -}; - -static const char *const cities[17] = { - "EPERNAY", - "CHALONS", - "BARLEDUC", - "NANCY", - "LUNEVILL", - "AVRICOUR", - "DEUTSCHA", - "STRASBOU", - "BADENOOS", - "SALZBURG", - "ATTNANG", - "WELS", - "LINZ", - "VIENNA", - "POZSONY", - "GALANTA", - "POLICE" -}; - -static const char *const locomotiveSounds[5] = { - "ZFX1005", - "ZFX1006", - "ZFX1007", - "ZFX1007A", - "ZFX1007B" -}; - -static const SoundFlag soundFlags[32] = { - kFlagDefault, - kFlag15, - kFlag14, - kFlag13, - kFlag12, - kFlag11, kFlag11, - kFlag10, kFlag10, - kFlag9, kFlag9, - kFlag8, kFlag8, - kFlag7, kFlag7, kFlag7, - kFlag6, kFlag6, kFlag6, - kFlag5, kFlag5, kFlag5, kFlag5, - kFlag4, kFlag4, kFlag4, kFlag4, - kFlag3, kFlag3, kFlag3, kFlag3, kFlag3 -}; - -SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine) { - _loopingSoundDuration = 0; - - _queue = new SoundQueue(engine); - - memset(&_lastWarning, 0, sizeof(_lastWarning)); - - // Initialize unknown data - _data0 = 0; - _data1 = 0; - _data2 = 0; -} - -SoundManager::~SoundManager() { - SAFE_DELETE(_queue); - - // Zero passed pointers - _engine = NULL; -} - -////////////////////////////////////////////////////////////////////////// -// Sound-related functions -////////////////////////////////////////////////////////////////////////// -void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundFlag flag, byte a4) { - if (_queue->isBuffered(entity) && entity) - _queue->removeFromQueue(entity); - - SoundFlag currentFlag = (flag == -1) ? getSoundFlag(entity) : (SoundFlag)(flag | 0x80000); - - // Add .SND at the end of the filename if needed - if (!filename.contains('.')) - filename += ".SND"; - - if (!playSoundWithSubtitles(filename, currentFlag, entity, a4)) - if (entity) - getSavePoints()->push(kEntityPlayer, entity, kActionEndSound); -} - -bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4) { - SoundEntry *entry = new SoundEntry(_engine); - - entry->open(filename, flag, 30); - entry->_entity = entity; - - if (a4) { - entry->_field_48 = _data2 + 2 * a4; - entry->_status.status |= kSoundStatus_8000; - } else { - // Get subtitles name - while (filename.size() > 4) - filename.deleteLastChar(); - - entry->showSubtitle(filename); - entry->updateState(); - } - - return (entry->getType() != kSoundTypeNone); -} - -void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { - int values[5]; - - if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car) - return; - - if (getEntities()->isInSalon(entity) != getEntities()->isInSalon(kEntityPlayer)) - return; - - int _action = (int)action; - SoundFlag flag = getSoundFlag(entity); - - switch (action) { - case 36: { - int _param3 = (flag <= 9) ? flag + 7 : 16; - - if (_param3 > 7) { - _data0 = (uint)_param3; - _data1 = _data2 + 2 * a3; - } - break; - } - - case 37: - _data0 = 7; - _data1 = _data2 + 2 * a3; - break; - - case 150: - case 156: - case 162: - case 168: - case 188: - case 198: - _action += 1 + (int)rnd(5); - break; - - case 174: - case 184: - case 194: - _action += 1 + (int)rnd(3); - break; - - case 180: - _action += 1 + (int)rnd(4); - break; - - case 246: - values[0] = 0; - values[1] = 104; - values[2] = 105; - values[3] = 106; - values[4] = 116; - _action = values[rnd(5)]; - break; - - case 247: - values[0] = 11; - values[1] = 123; - values[2] = 124; - _action = values[rnd(3)]; - break; - - case 248: - values[0] = 0; - values[1] = 103; - values[2] = 108; - values[3] = 109; - _action = values[rnd(4)]; - break; - - case 249: - values[0] = 0; - values[1] = 56; - values[2] = 112; - values[3] = 113; - _action = values[rnd(4)]; - break; - - case 250: - values[0] = 0; - values[1] = 107; - values[2] = 115; - values[3] = 117; - _action = values[rnd(4)]; - break; - - case 251: - values[0] = 0; - values[1] = 11; - values[2] = 56; - values[3] = 113; - _action = values[rnd(4)]; - break; - - case 252: - values[0] = 0; - values[1] = 6; - values[2] = 109; - values[3] = 121; - _action = values[rnd(4)]; - break; - - case 254: - values[0] = 0; - values[1] = 104; - values[2] = 120; - values[3] = 121; - _action = values[rnd(4)]; - break; - - case 255: - values[0] = 0; - values[1] = 106; - values[2] = 115; - _action = values[rnd(3)]; - break; - - default: - break; - } - - if (_action && flag) - playSoundWithSubtitles(Common::String::format("LIB%03d.SND", _action), flag, kEntityPlayer, a3); -} - -void SoundManager::playSteam(CityIndex index) { - if (index >= ARRAYSIZE(cities)) - error("SoundManager::playSteam: invalid city index (was %d, max %d)", index, ARRAYSIZE(cities)); - - _queue->resetState(kSoundState2); - - if (!_queue->getEntry(kSoundType1)) - playSoundWithSubtitles("STEAM.SND", kFlagSteam, kEntitySteam); - - // Get the new sound entry and show subtitles - SoundEntry *entry = _queue->getEntry(kSoundType1); - if (entry) - entry->showSubtitle(cities[index]); -} - -void SoundManager::playFightSound(byte action, byte a4) { - int _action = (int)action; - int values[5]; - - switch (action) { - default: - break; - - case 174: - case 184: - case 194: - values[0] = action + 1; - values[1] = action + 2; - values[2] = action + 3; - _action = values[rnd(3)]; - break; - - case 180: - values[0] = action + 1; - values[1] = action + 2; - values[2] = action + 3; - values[3] = action + 4; - _action = values[rnd(4)]; - break; - - case 150: - case 156: - case 162: - case 168: - case 188: - case 198: - values[0] = action + 1; - values[1] = action + 2; - values[2] = action + 3; - values[3] = action + 4; - values[4] = action + 5; - _action = values[rnd(5)]; - break; - } - - if (_action) - playSound(kEntityTrain, Common::String::format("LIB%03d.SND", _action), kFlagDefault, a4); -} - -void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4) { - if (_queue->isBuffered(getDialogName(entityDialog))) - _queue->removeFromQueue(getDialogName(entityDialog)); - - playSound(entity, getDialogName(entityDialog), flag, a4); -} - -void SoundManager::playLocomotiveSound() { - playSound(kEntityPlayer, locomotiveSounds[rnd(5)], (SoundFlag)(rnd(15) + 2)); -} - -const char *SoundManager::getDialogName(EntityIndex entity) const { - switch (entity) { - case kEntityAnna: - if (getEvent(kEventAnnaDialogGoToJerusalem)) - return "XANN12"; - - if (getEvent(kEventLocomotiveRestartTrain)) - return "XANN11"; - - if (getEvent(kEventAnnaBaggageTies) || getEvent(kEventAnnaBaggageTies2) || getEvent(kEventAnnaBaggageTies3) || getEvent(kEventAnnaBaggageTies4)) - return "XANN10"; - - if (getEvent(kEventAnnaTired) || getEvent(kEventAnnaTiredKiss)) - return "XANN9"; - - if (getEvent(kEventAnnaBaggageArgument)) - return "XANN8"; - - if (getEvent(kEventKronosVisit)) - return "XANN7"; - - if (getEvent(kEventAbbotIntroduction)) - return "XANN6A"; - - if (getEvent(kEventVassiliSeizure)) - return "XANN6"; - - if (getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction)) - return "XANN5"; - - if (getProgress().field_60) - return "XANN4"; - - if (getEvent(kEventAnnaGiveScarf) || getEvent(kEventAnnaGiveScarfDiner) || getEvent(kEventAnnaGiveScarfSalon) - || getEvent(kEventAnnaGiveScarfMonogram) || getEvent(kEventAnnaGiveScarfDinerMonogram) || getEvent(kEventAnnaGiveScarfSalonMonogram)) - return "XANN3"; - - if (getEvent(kEventDinerMindJoin)) - return "XANN2"; - - if (getEvent(kEventGotALight) || getEvent(kEventGotALightD)) - return "XANN1"; - - break; - - case kEntityAugust: - if (getEvent(kEventAugustTalkCigar)) - return "XAUG6"; - - if (getEvent(kEventAugustBringBriefcase)) - return "XAUG5"; - - // Getting closer to Vienna... - if (getState()->time > kTime2200500 && !getEvent(kEventAugustMerchandise)) - return "XAUG4A"; - - if (getEvent(kEventAugustMerchandise)) - return "XAUG4"; - - if (getEvent(kEventDinerAugust) || getEvent(kEventDinerAugustAlexeiBackground) || getEvent(kEventMeetAugustTylerCompartment) - || getEvent(kEventMeetAugustTylerCompartmentBed) || getEvent(kEventMeetAugustHisCompartment) || getEvent(kEventMeetAugustHisCompartmentBed)) - return "XAUG3"; - - if (getEvent(kEventAugustPresentAnnaFirstIntroduction)) - return "XAUG2"; - - if (getProgress().eventMertensAugustWaiting) - return "XAUG1"; - - break; - - case kEntityTatiana: - if (getEvent(kEventTatianaTylerCompartment)) - return "XTAT6"; - - if (getEvent(kEventTatianaCompartmentStealEgg)) - return "XTAT5"; - - if (getEvent(kEventTatianaGivePoem)) - return "XTAT3"; - - if (getProgress().field_64) - return "XTAT1"; - - break; - - case kEntityVassili: - if (getEvent(kEventCathFreePassengers)) - return "XVAS4"; - - if (getEvent(kEventVassiliCompartmentStealEgg)) - return "XVAS3"; - - if (getEvent(kEventAbbotIntroduction)) - return "XVAS2"; - - if (getEvent(kEventVassiliSeizure)) - return "XVAS1A"; - - if (getProgress().field_64) - return "XVAS1"; - - break; - - case kEntityAlexei: - if (getProgress().field_88) - return "XALX6"; - - if (getProgress().field_8C) - return "XALX5"; - - if (getProgress().field_90) - return "XALX4A"; - - if (getProgress().field_68) - return "XALX4"; - - if (getEvent(kEventAlexeiSalonPoem)) - return "XALX3"; - - if (getEvent(kEventAlexeiSalonVassili)) - return "XALX2"; - - if (getEvent(kEventAlexeiDiner) || getEvent(kEventAlexeiDinerOriginalJacket)) - return "XALX1"; - - break; - - case kEntityAbbot: - if (getEvent(kEventAbbotDrinkDefuse)) - return "XABB4"; - - if (getEvent(kEventAbbotInvitationDrink) || getEvent(kEventDefuseBomb)) - return "XABB3"; - - if (getEvent(kEventAbbotWrongCompartment) || getEvent(kEventAbbotWrongCompartmentBed)) - return "XABB2"; - - if (getEvent(kEventAbbotIntroduction)) - return "XABB1"; - - break; - - case kEntityMilos: - if (getEvent(kEventLocomotiveMilosDay) || getEvent(kEventLocomotiveMilosNight)) - return "XMIL5"; - - if (getEvent(kEventMilosCompartmentVisitTyler) && (getProgress().chapter == kChapter3 || getProgress().chapter == kChapter4)) - return "XMIL4"; - - if (getEvent(kEventMilosCorridorThanks) || getProgress().chapter == kChapter5) - return "XMIL3"; - - if (getEvent(kEventMilosCompartmentVisitAugust)) - return "XMIL2"; - - if (getEvent(kEventMilosTylerCompartmentDefeat)) - return "XMIL1"; - - break; - - case kEntityVesna: - if (getProgress().field_94) - return "XVES2"; - - if (getProgress().field_98) - return "XVES1"; - - break; - - case kEntityKronos: - if (getEvent(kEventKronosReturnBriefcase)) - return "XKRO6"; - - if (getEvent(kEventKronosBringEggCeiling) || getEvent(kEventKronosBringEgg)) - return "XKRO5"; - - if (getEvent(kEventKronosConversation) || getEvent(kEventKronosConversationFirebird)) { - ObjectLocation location = getInventory()->get(kItemFirebird)->location; - if (location != kObjectLocation6 && location != kObjectLocation5 && location != kObjectLocation2 && location != kObjectLocation1) - return "XKRO4A"; - } - - if (getEvent(kEventKronosConversationFirebird)) - return "XKRO4"; - - if (getEvent(kEventKronosConversation)) { - if (!getEvent(kEventMilosCompartmentVisitAugust)) - return "XKRO3"; - else - return "XKRO2"; - } - - if (getProgress().eventMertensKronosInvitation) - return "XKRO1"; - - break; - - case kEntityFrancois: - if (getProgress().field_9C) - return "XFRA3"; - - if (getProgress().field_A0 - || getEvent(kEventFrancoisWhistle) || getEvent(kEventFrancoisWhistleD) - || getEvent(kEventFrancoisWhistleNight) || getEvent(kEventFrancoisWhistleNightD)) - return "XFRA2"; - - if (getState()->time > kTimeParisEpernay) // Between Paris and Epernay - return "XFRA1"; - - break; - - case kEntityMmeBoutarel: - if (getProgress().field_A4) - return "XMME4"; - - if (getProgress().field_A8) - return "XMME3"; - - if (getProgress().field_A0) - return "XMME2"; - - if (getProgress().field_AC) - return "XMME1"; - - break; - - case kEntityBoutarel: - if (getProgress().eventMetBoutarel) - return "XMRB1"; - - break; - - case kEntityRebecca: - if (getProgress().field_B4) - return "XREB1A"; - - if (getProgress().field_B8) - return "XREB1"; - - break; - - case kEntitySophie: - if (getProgress().field_B0) - return "XSOP2"; - - if (getProgress().field_BC) - return "XSOP1B"; - - if (getProgress().field_B4) - return "XSOP1A"; - - if (getProgress().field_B8) - return "XSOP1"; - - break; - - case kEntityMahmud: - if (getProgress().field_C4) - return "XMAH1"; - - break; - - case kEntityYasmin: - if (getProgress().eventMetYasmin) - return "XHAR2"; - - break; - - case kEntityHadija: - if (getProgress().eventMetHadija) - return "XHAR1"; - - break; - - case kEntityAlouan: - if (getProgress().field_DC) - return "XHAR3"; - - break; - - case kEntityGendarmes: - if (getProgress().field_E0) - return "XHAR4"; - - break; - - case kEntityChapters: - if (getEvent(kEventCathDream) || getEvent(kEventCathWakingUp)) - return "XTYL3"; - - return "XTYL1"; - - default: - break; - } - - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -// Letters & Messages -////////////////////////////////////////////////////////////////////////// -void SoundManager::readText(int id){ - if (!_queue->isBuffered(kEntityTables4)) - return; - - if (id < 0 || (id > 8 && id < 50) || id > 64) - error("Sound::readText - attempting to use invalid id. Valid values [1;8] - [50;64], was %d", id); - - // Get proper message file (names are stored in sequence in the array but id is [1;8] - [50;64]) - const char *text = messages[id <= 8 ? id : id - 41]; - - // Check if file is in cache for id [1;8] - if (id <= 8) - if (_queue->isBuffered(text)) - _queue->removeFromQueue(text); - - playSound(kEntityTables4, text, kFlagDefault); -} - -////////////////////////////////////////////////////////////////////////// -// Sound bites -////////////////////////////////////////////////////////////////////////// -void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compartment) { - -#define PLAY_WARNING(index, sound1, sound2, sound3, sound4, sound5, sound6) { \ - if (_lastWarning[index] + 450 >= getState()->timeTicks) { \ - if (rnd(2)) \ - playSound(kEntityMertens, sound1, kFlagDefault); \ - else \ - playSound(kEntityMertens, rnd(2) ? sound2 : sound3, kFlagDefault); \ - } else { \ - if (rnd(2)) \ - playSound(kEntityMertens, sound4, kFlagDefault); \ - else \ - playSound(kEntityMertens, rnd(2) ? sound5 : sound6, kFlagDefault); \ - } \ - _lastWarning[index] = getState()->timeTicks; \ -} - - if (entity != kEntityMertens && entity != kEntityCoudert) - return; - - ////////////////////////////////////////////////////////////////////////// - // Mertens - if (entity == kEntityMertens) { - - switch (compartment) { - default: - break; - - case kObjectCompartment2: - PLAY_WARNING(0, "Con1502A", "Con1500B", "Con1500C", "Con1502", "Con1500", "Con1500A"); - break; - - case kObjectCompartment3: - PLAY_WARNING(1, "Con1501A", "Con1500B", "Con1500C", "Con1501", "Con1500", "Con1500A"); - break; - - case kObjectCompartment4: - PLAY_WARNING(2, "Con1503", "Con1500B", "Con1500C", "Con1503", "Con1500", "Con1500A"); - break; - - case kObjectCompartment5: - case kObjectCompartment6: - case kObjectCompartment7: - case kObjectCompartment8: - ++_lastWarning[3]; - - switch (_lastWarning[3]) { - default: - break; - - case 1: - getSound()->playSound(kEntityMertens, "Con1503C", kFlagDefault); - break; - - case 2: - getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503E" : "Con1503A", kFlagDefault); - break; - - case 3: - getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503B" : "Con1503D", kFlagDefault); - _lastWarning[3] = 0; - break; - } - } - - return; - } - - ////////////////////////////////////////////////////////////////////////// - // Coudert - switch (compartment) { - default: - break; - - case kObjectCompartmentA: - if (_lastWarning[4] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1508" : "Jac1508A", kFlagDefault); - break; - - case kObjectCompartmentB: - if (_lastWarning[5] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (getProgress().field_40 || (getState()->time > kTimeCityLinz && getState()->time < kTime2133000)) - getSound()->playSound(kEntityCoudert, "Jac1507A", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, "Jac1507", kFlagDefault); - break; - - case kObjectCompartmentC: - if (_lastWarning[6] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (getProgress().chapter < kChapter3) - getSound()->playSound(kEntityCoudert, "Jac1506", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1506A" : "Jac1506B", kFlagDefault); - break; - - case kObjectCompartmentD: - if (_lastWarning[7] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - getSound()->playSound(kEntityCoudert, "Jac1505", kFlagDefault); - break; - - case kObjectCompartmentE: - if (_lastWarning[8] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (getProgress().field_40 || (getState()->time > kTime2115000 && getState()->time < kTime2133000)) { - getSound()->playSound(kEntityCoudert, "Jac1504B", kFlagDefault); - break; - } - - if (getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840)) - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1504" : "Jac1504A", kFlagDefault); - break; - - case kObjectCompartmentF: - if (_lastWarning[9] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (getProgress().field_40 || (getState()->time > kTime2083500 && getState()->time < kTime2133000)) { - getSound()->playSound(kEntityCoudert, "Jac1503B", kFlagDefault); - break; - } - - if (rnd(2) || getEntities()->isInsideCompartment(kEntityAnna, kCarRedSleeping, kPosition_4070)) - getSound()->playSound(kEntityCoudert, "Jac1503", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, "Jac1503A", kFlagDefault); - break; - - case kObjectCompartmentG: - if (_lastWarning[10] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (rnd(2) || getEntities()->isInsideCompartment(kEntityMilos, kCarRedSleeping, kPosition_3050)) - getSound()->playSound(kEntityCoudert, "Jac1502", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, "Jac1502A", kFlagDefault); - break; - - case kObjectCompartmentH: - if (_lastWarning[11] + 450 >= getState()->timeTicks) { - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - break; - } - - if (getEntities()->isInsideCompartment(kEntityIvo, kCarRedSleeping, kPosition_2740)) - getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); - else - getSound()->playSound(kEntityCoudert, "Jac1501", kFlagDefault); - break; - } - - // Update ticks (Compartments A - H are indexes 4 - 11) - _lastWarning[compartment - 28] = getState()->timeTicks; -} - -void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag flag) { - if (_queue->isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain) - return; - - if (entity2 == kEntityFrancois || entity2 == kEntityMax) - return; - - if (entity == kEntityFrancois && getEntityData(kEntityFrancois)->field_4A3 != 30) - return; - - if (flag == kFlagNone) - flag = getSoundFlag(entity); - - switch (entity) { - default: - break; - - case kEntityAnna: - playSound(kEntityPlayer, "ANN1107A", flag); - break; - - case kEntityAugust: - switch(rnd(4)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "AUG1100A", flag); - break; - - case 1: - playSound(kEntityPlayer, "AUG1100B", flag); - break; - - case 2: - playSound(kEntityPlayer, "AUG1100C", flag); - break; - - case 3: - playSound(kEntityPlayer, "AUG1100D", flag); - break; - } - break; - - case kEntityMertens: - if (Entities::isFemale(entity2)) { - playSound(kEntityPlayer, (rnd(2) ? "CON1111" : "CON1111A"), flag); - } else { - if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { - switch(rnd(3)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "CON1110A", flag); - break; - - case 1: - playSound(kEntityPlayer, "CON1110C", flag); - break; - - case 2: - playSound(kEntityPlayer, "CON1110", flag); - break; - } - } else { - if (isNight()) { - playSound(kEntityPlayer, (getProgress().field_18 == 2 ? "CON1110F" : "CON1110E")); - } else { - playSound(kEntityPlayer, "CON1110D"); - } - } - } - break; - - case kEntityCoudert: - if (Entities::isFemale(entity2)) { - playSound(kEntityPlayer, "JAC1111D", flag); - } else { - if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { - switch(rnd(4)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "JAC1111", flag); - break; - - case 1: - playSound(kEntityPlayer, "JAC1111A", flag); - break; - - case 2: - playSound(kEntityPlayer, "JAC1111B", flag); - break; - - case 3: - playSound(kEntityPlayer, "JAC1111C", flag); - break; - } - } else { - playSound(kEntityPlayer, "JAC1113B", flag); - } - } - break; - - case kEntityPascale: - playSound(kEntityPlayer, (rnd(2) ? "HDE1002" : "HED1002A"), flag); - break; - - case kEntityServers0: - case kEntityServers1: - switch(rnd(3)) { - default: - break; - - case 0: - playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002" : "WAT1003", flag); - break; - - case 1: - playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002A" : "WAT1003A", flag); - break; - - case 2: - playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002B" : "WAT1003B", flag); - break; - } - break; - - case kEntityVerges: - if (Entities::isFemale(entity2)) { - playSound(kEntityPlayer, (rnd(2) ? "TRA1113A" : "TRA1113B")); - } else { - playSound(kEntityPlayer, "TRA1112", flag); - } - break; - - case kEntityTatiana: - playSound(kEntityPlayer, (rnd(2) ? "TAT1102A" : "TAT1102B"), flag); - break; - - case kEntityAlexei: - playSound(kEntityPlayer, (rnd(2) ? "ALX1099C" : "ALX1099D"), flag); - break; - - case kEntityAbbot: - if (Entities::isFemale(entity2)) { - playSound(kEntityPlayer, "ABB3002C", flag); - } else { - switch(rnd(3)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "ABB3002", flag); - break; - - case 1: - playSound(kEntityPlayer, "ABB3002A", flag); - break; - - case 2: - playSound(kEntityPlayer, "ABB3002B", flag); - break; - } - } - break; - - case kEntityVesna: - switch(rnd(3)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "VES1109A", flag); - break; - - case 1: - playSound(kEntityPlayer, "VES1109B", flag); - break; - - case 2: - playSound(kEntityPlayer, "VES1109C", flag); - break; - } - break; - - case kEntityKahina: - playSound(kEntityPlayer, (rnd(2) ? "KAH1001" : "KAH1001A"), flag); - break; - - case kEntityFrancois: - case kEntityMmeBoutarel: - switch(rnd(4)) { - default: - break; - - case 0: - playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001" : "MME1103A", flag); - break; - - case 1: - playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001A" : "MME1103B", flag); - break; - - case 2: - playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001B" : "MME1103C", flag); - break; - - case 3: - playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001C" : "MME1103D", flag); - break; - } - break; - - case kEntityBoutarel: - playSound(kEntityPlayer, "MRB1104", flag); - if (flag > 2) - getProgress().eventMetBoutarel = true; - break; - - case kEntityRebecca: - playSound(kEntityPlayer, (rnd(2) ? "REB1106" : "REB110A"), flag); - break; - - case kEntitySophie: { - switch(rnd(3)) { - default: - break; - - case 0: - playSound(kEntityPlayer, "SOP1105", flag); - break; - - case 1: - playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105C" : "SOP1105A", flag); - break; - - case 2: - playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105D" : "SOP1105B", flag); - break; - } - break; - } - - case kEntityMahmud: - playSound(kEntityPlayer, "MAH1101", flag); - break; - - case kEntityYasmin: - playSound(kEntityPlayer, "HAR1002", flag); - if (flag > 2) - getProgress().eventMetYasmin = true; - break; - - case kEntityHadija: - playSound(kEntityPlayer, (rnd(2) ? "HAR1001" : "HAR1001A"), flag); - if (flag > 2) - getProgress().eventMetHadija = true; - break; - - case kEntityAlouan: - playSound(kEntityPlayer, "HAR1004", flag); - break; - } -} - -void SoundManager::excuseMeCath() { - switch(rnd(3)) { - default: - playSound(kEntityPlayer, "CAT1126B"); - break; - - case 1: - playSound(kEntityPlayer, "CAT1126C"); - break; - - case 2: - playSound(kEntityPlayer, "CAT1126D"); - break; - } -} - -const char *SoundManager::justCheckingCath() const { - switch(rnd(4)) { - default: - break; - - case 0: - return "CAT5001"; - - case 1: - return "CAT5001A"; - - case 2: - return "CAT5001B"; - - case 3: - return "CAT5001C"; - } - - return "CAT5001"; -} - -const char *SoundManager::wrongDoorCath() const { - switch(rnd(5)) { - default: - break; - - case 0: - return "CAT1125"; - - case 1: - return "CAT1125A"; - - case 2: - return "CAT1125B"; - - case 3: - return "CAT1125C"; - - case 4: - return "CAT1125D"; - } - - return "CAT1125"; -} - -const char *SoundManager::justAMinuteCath() const { - switch(rnd(3)) { - default: - break; - - case 0: - return "CAT1520"; - - case 1: - return "CAT1521"; - - case 2: - return "CAT1125"; // ?? is this a bug in the original? - } - - return "CAT1520"; -} - -////////////////////////////////////////////////////////////////////////// -// Sound flags -////////////////////////////////////////////////////////////////////////// -SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { - if (entity == kEntityPlayer) - return kFlagDefault; - - if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car) - return kFlagNone; - - // Compute sound value - SoundFlag ret = kFlag2; - - // Get default value if valid - int index = ABS(getEntityData(entity)->entityPosition - getEntityData(kEntityPlayer)->entityPosition) / 230; - if (index < 32) - ret = soundFlags[index]; - - if (getEntityData(entity)->location == kLocationOutsideTrain) { - if (getEntityData(entity)->car != kCarKronos - && !getEntities()->isOutsideAlexeiWindow() - && !getEntities()->isOutsideAnnaWindow()) - return kFlagNone; - - return (SoundFlag)(ret / 6); - } - - switch (getEntityData(entity)->car) { - default: - break; - - case kCarKronos: - if (getEntities()->isInKronosSalon(entity) != getEntities()->isInKronosSalon(kEntityPlayer)) - ret = (SoundFlag)(ret * 2); - break; - - case kCarGreenSleeping: - case kCarRedSleeping: - if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInKronosSalon(entity)) - ret = (SoundFlag)(ret * 2); - - if (getEntityData(kEntityPlayer)->location - && (getEntityData(entity)->entityPosition != kPosition_1 || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400))) - ret = (SoundFlag)(ret * 2); - break; - - case kCarRestaurant: - if (getEntities()->isInSalon(entity) == getEntities()->isInSalon(kEntityPlayer) - && (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer))) - ret = (SoundFlag)(ret * 2); - else - ret = (SoundFlag)(ret * 4); - break; - } - - return ret; -} - -////////////////////////////////////////////////////////////////////////// -// Misc -////////////////////////////////////////////////////////////////////////// -void SoundManager::playLoopingSound(int param) { - SoundEntry *entry = _queue->getEntry(kSoundType1); - - static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, - kPosition_6470, kPosition_5790, - kPosition_4840, kPosition_4070, - kPosition_3050, kPosition_2740 }; - - byte numLoops[8]; - numLoops[1] = 4; - numLoops[2] = 2; - numLoops[3] = 2; - numLoops[4] = 2; - numLoops[5] = 2; - numLoops[6] = 2; - - char tmp[80]; - tmp[0] = 0; - - int partNumber = 1; - int fnameLen = 6; - - if (_queue->getSoundState() & 1 && param >= 0x45 && param <= 0x46) { - if (_queue->getSoundState() & 2) { - strcpy(tmp, "STEAM.SND"); - - _loopingSoundDuration = 32767; - } else { - if (getEntityData(kEntityPlayer)->location == kLocationOutsideTrain) { - partNumber = 6; - } else { - if (getEntities()->isInsideCompartments(kEntityPlayer)) { - int objNum = (getEntityData(kEntityPlayer)->car - 3) < 1 ? 9 : 40; // Weird numbers - - numLoops[0] = 0; - - for (int pos = 0; pos < 8; pos++) { - if (numLoops[0]) - break; - if (getEntities()->isInsideCompartment(kEntityPlayer, getEntityData(kEntityPlayer)->car, positions[pos])) { - numLoops[0] = 1; - partNumber = (getObjects()->get((ObjectIndex)objNum).location - 2) < 1 ? 6 : 1; - } - objNum++; - } - } else { - switch (getEntityData(kEntityPlayer)->car) { - case 1: - case 6: - partNumber = 4; - break; - case 2: - case 3: - case 4: - case 5: - partNumber = 1; - break; - case 7: - partNumber = 5; - break; - case 8: - partNumber = 99; - break; - case 9: - partNumber = 3; - break; - default: - partNumber = 6; - break; - } - } - } - - if (partNumber != 99) - sprintf(tmp, "LOOP%d%c.SND", partNumber, _engine->getRandom().getRandomNumber(numLoops[partNumber] - 1) + 'A'); - } - - if (getFlags()->flag_3) - fnameLen = 5; - - if (!entry || scumm_strnicmp(entry->_name2.c_str(), tmp, fnameLen)) { - _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; - - if (partNumber != 99) { - playSoundWithSubtitles(tmp, kFlagLoopedSound, kEntitySteam); - - if (entry) - entry->update(0); - - SoundEntry *entry1 = _queue->getEntry(kSoundType1); - if (entry1) - entry1->update(7); - } - } - } -} - -} // End of namespace LastExpress diff --git a/engines/lastexpress/game/sound.h b/engines/lastexpress/game/sound.h deleted file mode 100644 index 797e52646e..0000000000 --- a/engines/lastexpress/game/sound.h +++ /dev/null @@ -1,87 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef LASTEXPRESS_SOUND_H -#define LASTEXPRESS_SOUND_H - -#include "lastexpress/shared.h" - -#include "common/str.h" - -namespace LastExpress { - -class LastExpressEngine; -class SoundQueue; - -class SoundManager { -public: - SoundManager(LastExpressEngine *engine); - ~SoundManager(); - - // Sound playing - void playSound(EntityIndex entity, Common::String filename, SoundFlag flag = kFlagInvalid, byte a4 = 0); - bool playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4 = 0); - void playSoundEvent(EntityIndex entity, byte action, byte a3 = 0); - void playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4); - void playSteam(CityIndex index); - void playFightSound(byte action, byte a4); - void playLocomotiveSound(); - void playWarningCompartment(EntityIndex entity, ObjectIndex compartment); - void playLoopingSound(int param); - - // Dialog & Letters - void readText(int id); - const char *getDialogName(EntityIndex entity) const; - - // Sound bites - void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, SoundFlag flag = kFlagNone); - void excuseMeCath(); - const char *justCheckingCath() const; - const char *wrongDoorCath() const; - const char *justAMinuteCath() const; - - // Flags - SoundFlag getSoundFlag(EntityIndex index) const; - - // Accessors - SoundQueue *getQueue() { return _queue; } - uint32 getData2() { return _data2; } - -private: - LastExpressEngine *_engine; - SoundQueue *_queue; - - // Compartment warnings by Mertens or Coudert - uint32 _lastWarning[12]; - - // Looping sound - int _loopingSoundDuration; - - // Unknown data - uint32 _data0; - uint32 _data1; - uint32 _data2; -}; - -} // End of namespace LastExpress - -#endif // LASTEXPRESS_SOUND_H diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index 2829f60740..5d83527525 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -28,11 +28,11 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/scenes.h" #include "lastexpress/game/state.h" -#include "lastexpress/game/sound.h" #include "lastexpress/menu/menu.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp index 288e53fc11..bfead02ad0 100644 --- a/engines/lastexpress/menu/menu.cpp +++ b/engines/lastexpress/menu/menu.cpp @@ -35,13 +35,13 @@ #include "lastexpress/game/savegame.h" #include "lastexpress/game/savepoint.h" #include "lastexpress/game/scenes.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/menu/clock.h" #include "lastexpress/menu/trainline.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk index 355ecba33b..a11a7c4b67 100644 --- a/engines/lastexpress/module.mk +++ b/engines/lastexpress/module.mk @@ -61,13 +61,13 @@ MODULE_OBJS := \ game/savegame.o \ game/savepoint.o \ game/scenes.o \ - game/sound.o \ game/state.o \ menu/clock.o \ menu/menu.o \ menu/trainline.o \ sound/entry.o \ sound/queue.o \ + sound/sound.o \ debug.o \ detection.o \ graphics.o \ diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 817416110e..5cdcc15d5a 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -24,10 +24,10 @@ #include "lastexpress/game/logic.h" #include "lastexpress/game/savepoint.h" -#include "lastexpress/game/sound.h" #include "lastexpress/game/state.h" #include "lastexpress/sound/queue.h" +#include "lastexpress/sound/sound.h" #include "lastexpress/graphics.h" #include "lastexpress/helpers.h" diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp new file mode 100644 index 0000000000..16e502ad5a --- /dev/null +++ b/engines/lastexpress/sound/sound.cpp @@ -0,0 +1,1379 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "lastexpress/sound/sound.h" + +#include "lastexpress/game/action.h" +#include "lastexpress/game/entities.h" +#include "lastexpress/game/inventory.h" +#include "lastexpress/game/logic.h" +#include "lastexpress/game/object.h" +#include "lastexpress/game/savepoint.h" +#include "lastexpress/game/state.h" + +#include "lastexpress/sound/entry.h" +#include "lastexpress/sound/queue.h" + +#include "lastexpress/helpers.h" +#include "lastexpress/graphics.h" +#include "lastexpress/lastexpress.h" +#include "lastexpress/resource.h" + +namespace LastExpress { + +// Letters & messages +static const char *const messages[24] = { + "", + "TXT1001", // 1 + "TXT1001A", // 2 + "TXT1011", // 3 + "TXT1012", // 4 + "TXT1013", // 5 + "TXT1014", // 6 + "TXT1020", // 7 + "TXT1030", // 8 + "END1009B", // 50 + "END1046", // 51 + "END1047", // 52 + "END1112", // 53 + "END1112A", // 54 + "END1503", // 55 + "END1505A", // 56 + "END1505B", // 57 + "END1610", // 58 + "END1612A", // 59 + "END1612C", // 61 + "END1612D", // 62 + "ENDALRM1", // 63 + "ENDALRM2", // 64 + "ENDALRM3" // 65 +}; + +static const char *const cities[17] = { + "EPERNAY", + "CHALONS", + "BARLEDUC", + "NANCY", + "LUNEVILL", + "AVRICOUR", + "DEUTSCHA", + "STRASBOU", + "BADENOOS", + "SALZBURG", + "ATTNANG", + "WELS", + "LINZ", + "VIENNA", + "POZSONY", + "GALANTA", + "POLICE" +}; + +static const char *const locomotiveSounds[5] = { + "ZFX1005", + "ZFX1006", + "ZFX1007", + "ZFX1007A", + "ZFX1007B" +}; + +static const SoundFlag soundFlags[32] = { + kFlagDefault, + kFlag15, + kFlag14, + kFlag13, + kFlag12, + kFlag11, kFlag11, + kFlag10, kFlag10, + kFlag9, kFlag9, + kFlag8, kFlag8, + kFlag7, kFlag7, kFlag7, + kFlag6, kFlag6, kFlag6, + kFlag5, kFlag5, kFlag5, kFlag5, + kFlag4, kFlag4, kFlag4, kFlag4, + kFlag3, kFlag3, kFlag3, kFlag3, kFlag3 +}; + +SoundManager::SoundManager(LastExpressEngine *engine) : _engine(engine) { + _loopingSoundDuration = 0; + + _queue = new SoundQueue(engine); + + memset(&_lastWarning, 0, sizeof(_lastWarning)); + + // Initialize unknown data + _data0 = 0; + _data1 = 0; + _data2 = 0; +} + +SoundManager::~SoundManager() { + SAFE_DELETE(_queue); + + // Zero passed pointers + _engine = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Sound-related functions +////////////////////////////////////////////////////////////////////////// +void SoundManager::playSound(EntityIndex entity, Common::String filename, SoundFlag flag, byte a4) { + if (_queue->isBuffered(entity) && entity) + _queue->removeFromQueue(entity); + + SoundFlag currentFlag = (flag == -1) ? getSoundFlag(entity) : (SoundFlag)(flag | 0x80000); + + // Add .SND at the end of the filename if needed + if (!filename.contains('.')) + filename += ".SND"; + + if (!playSoundWithSubtitles(filename, currentFlag, entity, a4)) + if (entity) + getSavePoints()->push(kEntityPlayer, entity, kActionEndSound); +} + +bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4) { + SoundEntry *entry = new SoundEntry(_engine); + + entry->open(filename, flag, 30); + entry->_entity = entity; + + if (a4) { + entry->_field_48 = _data2 + 2 * a4; + entry->_status.status |= kSoundStatus_8000; + } else { + // Get subtitles name + while (filename.size() > 4) + filename.deleteLastChar(); + + entry->showSubtitle(filename); + entry->updateState(); + } + + return (entry->getType() != kSoundTypeNone); +} + +void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { + int values[5]; + + if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car) + return; + + if (getEntities()->isInSalon(entity) != getEntities()->isInSalon(kEntityPlayer)) + return; + + int _action = (int)action; + SoundFlag flag = getSoundFlag(entity); + + switch (action) { + case 36: { + int _param3 = (flag <= 9) ? flag + 7 : 16; + + if (_param3 > 7) { + _data0 = (uint)_param3; + _data1 = _data2 + 2 * a3; + } + break; + } + + case 37: + _data0 = 7; + _data1 = _data2 + 2 * a3; + break; + + case 150: + case 156: + case 162: + case 168: + case 188: + case 198: + _action += 1 + (int)rnd(5); + break; + + case 174: + case 184: + case 194: + _action += 1 + (int)rnd(3); + break; + + case 180: + _action += 1 + (int)rnd(4); + break; + + case 246: + values[0] = 0; + values[1] = 104; + values[2] = 105; + values[3] = 106; + values[4] = 116; + _action = values[rnd(5)]; + break; + + case 247: + values[0] = 11; + values[1] = 123; + values[2] = 124; + _action = values[rnd(3)]; + break; + + case 248: + values[0] = 0; + values[1] = 103; + values[2] = 108; + values[3] = 109; + _action = values[rnd(4)]; + break; + + case 249: + values[0] = 0; + values[1] = 56; + values[2] = 112; + values[3] = 113; + _action = values[rnd(4)]; + break; + + case 250: + values[0] = 0; + values[1] = 107; + values[2] = 115; + values[3] = 117; + _action = values[rnd(4)]; + break; + + case 251: + values[0] = 0; + values[1] = 11; + values[2] = 56; + values[3] = 113; + _action = values[rnd(4)]; + break; + + case 252: + values[0] = 0; + values[1] = 6; + values[2] = 109; + values[3] = 121; + _action = values[rnd(4)]; + break; + + case 254: + values[0] = 0; + values[1] = 104; + values[2] = 120; + values[3] = 121; + _action = values[rnd(4)]; + break; + + case 255: + values[0] = 0; + values[1] = 106; + values[2] = 115; + _action = values[rnd(3)]; + break; + + default: + break; + } + + if (_action && flag) + playSoundWithSubtitles(Common::String::format("LIB%03d.SND", _action), flag, kEntityPlayer, a3); +} + +void SoundManager::playSteam(CityIndex index) { + if (index >= ARRAYSIZE(cities)) + error("SoundManager::playSteam: invalid city index (was %d, max %d)", index, ARRAYSIZE(cities)); + + _queue->resetState(kSoundState2); + + if (!_queue->getEntry(kSoundType1)) + playSoundWithSubtitles("STEAM.SND", kFlagSteam, kEntitySteam); + + // Get the new sound entry and show subtitles + SoundEntry *entry = _queue->getEntry(kSoundType1); + if (entry) + entry->showSubtitle(cities[index]); +} + +void SoundManager::playFightSound(byte action, byte a4) { + int _action = (int)action; + int values[5]; + + switch (action) { + default: + break; + + case 174: + case 184: + case 194: + values[0] = action + 1; + values[1] = action + 2; + values[2] = action + 3; + _action = values[rnd(3)]; + break; + + case 180: + values[0] = action + 1; + values[1] = action + 2; + values[2] = action + 3; + values[3] = action + 4; + _action = values[rnd(4)]; + break; + + case 150: + case 156: + case 162: + case 168: + case 188: + case 198: + values[0] = action + 1; + values[1] = action + 2; + values[2] = action + 3; + values[3] = action + 4; + values[4] = action + 5; + _action = values[rnd(5)]; + break; + } + + if (_action) + playSound(kEntityTrain, Common::String::format("LIB%03d.SND", _action), kFlagDefault, a4); +} + +void SoundManager::playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4) { + if (_queue->isBuffered(getDialogName(entityDialog))) + _queue->removeFromQueue(getDialogName(entityDialog)); + + playSound(entity, getDialogName(entityDialog), flag, a4); +} + +void SoundManager::playLocomotiveSound() { + playSound(kEntityPlayer, locomotiveSounds[rnd(5)], (SoundFlag)(rnd(15) + 2)); +} + +const char *SoundManager::getDialogName(EntityIndex entity) const { + switch (entity) { + case kEntityAnna: + if (getEvent(kEventAnnaDialogGoToJerusalem)) + return "XANN12"; + + if (getEvent(kEventLocomotiveRestartTrain)) + return "XANN11"; + + if (getEvent(kEventAnnaBaggageTies) || getEvent(kEventAnnaBaggageTies2) || getEvent(kEventAnnaBaggageTies3) || getEvent(kEventAnnaBaggageTies4)) + return "XANN10"; + + if (getEvent(kEventAnnaTired) || getEvent(kEventAnnaTiredKiss)) + return "XANN9"; + + if (getEvent(kEventAnnaBaggageArgument)) + return "XANN8"; + + if (getEvent(kEventKronosVisit)) + return "XANN7"; + + if (getEvent(kEventAbbotIntroduction)) + return "XANN6A"; + + if (getEvent(kEventVassiliSeizure)) + return "XANN6"; + + if (getEvent(kEventAugustPresentAnna) || getEvent(kEventAugustPresentAnnaFirstIntroduction)) + return "XANN5"; + + if (getProgress().field_60) + return "XANN4"; + + if (getEvent(kEventAnnaGiveScarf) || getEvent(kEventAnnaGiveScarfDiner) || getEvent(kEventAnnaGiveScarfSalon) + || getEvent(kEventAnnaGiveScarfMonogram) || getEvent(kEventAnnaGiveScarfDinerMonogram) || getEvent(kEventAnnaGiveScarfSalonMonogram)) + return "XANN3"; + + if (getEvent(kEventDinerMindJoin)) + return "XANN2"; + + if (getEvent(kEventGotALight) || getEvent(kEventGotALightD)) + return "XANN1"; + + break; + + case kEntityAugust: + if (getEvent(kEventAugustTalkCigar)) + return "XAUG6"; + + if (getEvent(kEventAugustBringBriefcase)) + return "XAUG5"; + + // Getting closer to Vienna... + if (getState()->time > kTime2200500 && !getEvent(kEventAugustMerchandise)) + return "XAUG4A"; + + if (getEvent(kEventAugustMerchandise)) + return "XAUG4"; + + if (getEvent(kEventDinerAugust) || getEvent(kEventDinerAugustAlexeiBackground) || getEvent(kEventMeetAugustTylerCompartment) + || getEvent(kEventMeetAugustTylerCompartmentBed) || getEvent(kEventMeetAugustHisCompartment) || getEvent(kEventMeetAugustHisCompartmentBed)) + return "XAUG3"; + + if (getEvent(kEventAugustPresentAnnaFirstIntroduction)) + return "XAUG2"; + + if (getProgress().eventMertensAugustWaiting) + return "XAUG1"; + + break; + + case kEntityTatiana: + if (getEvent(kEventTatianaTylerCompartment)) + return "XTAT6"; + + if (getEvent(kEventTatianaCompartmentStealEgg)) + return "XTAT5"; + + if (getEvent(kEventTatianaGivePoem)) + return "XTAT3"; + + if (getProgress().field_64) + return "XTAT1"; + + break; + + case kEntityVassili: + if (getEvent(kEventCathFreePassengers)) + return "XVAS4"; + + if (getEvent(kEventVassiliCompartmentStealEgg)) + return "XVAS3"; + + if (getEvent(kEventAbbotIntroduction)) + return "XVAS2"; + + if (getEvent(kEventVassiliSeizure)) + return "XVAS1A"; + + if (getProgress().field_64) + return "XVAS1"; + + break; + + case kEntityAlexei: + if (getProgress().field_88) + return "XALX6"; + + if (getProgress().field_8C) + return "XALX5"; + + if (getProgress().field_90) + return "XALX4A"; + + if (getProgress().field_68) + return "XALX4"; + + if (getEvent(kEventAlexeiSalonPoem)) + return "XALX3"; + + if (getEvent(kEventAlexeiSalonVassili)) + return "XALX2"; + + if (getEvent(kEventAlexeiDiner) || getEvent(kEventAlexeiDinerOriginalJacket)) + return "XALX1"; + + break; + + case kEntityAbbot: + if (getEvent(kEventAbbotDrinkDefuse)) + return "XABB4"; + + if (getEvent(kEventAbbotInvitationDrink) || getEvent(kEventDefuseBomb)) + return "XABB3"; + + if (getEvent(kEventAbbotWrongCompartment) || getEvent(kEventAbbotWrongCompartmentBed)) + return "XABB2"; + + if (getEvent(kEventAbbotIntroduction)) + return "XABB1"; + + break; + + case kEntityMilos: + if (getEvent(kEventLocomotiveMilosDay) || getEvent(kEventLocomotiveMilosNight)) + return "XMIL5"; + + if (getEvent(kEventMilosCompartmentVisitTyler) && (getProgress().chapter == kChapter3 || getProgress().chapter == kChapter4)) + return "XMIL4"; + + if (getEvent(kEventMilosCorridorThanks) || getProgress().chapter == kChapter5) + return "XMIL3"; + + if (getEvent(kEventMilosCompartmentVisitAugust)) + return "XMIL2"; + + if (getEvent(kEventMilosTylerCompartmentDefeat)) + return "XMIL1"; + + break; + + case kEntityVesna: + if (getProgress().field_94) + return "XVES2"; + + if (getProgress().field_98) + return "XVES1"; + + break; + + case kEntityKronos: + if (getEvent(kEventKronosReturnBriefcase)) + return "XKRO6"; + + if (getEvent(kEventKronosBringEggCeiling) || getEvent(kEventKronosBringEgg)) + return "XKRO5"; + + if (getEvent(kEventKronosConversation) || getEvent(kEventKronosConversationFirebird)) { + ObjectLocation location = getInventory()->get(kItemFirebird)->location; + if (location != kObjectLocation6 && location != kObjectLocation5 && location != kObjectLocation2 && location != kObjectLocation1) + return "XKRO4A"; + } + + if (getEvent(kEventKronosConversationFirebird)) + return "XKRO4"; + + if (getEvent(kEventKronosConversation)) { + if (!getEvent(kEventMilosCompartmentVisitAugust)) + return "XKRO3"; + else + return "XKRO2"; + } + + if (getProgress().eventMertensKronosInvitation) + return "XKRO1"; + + break; + + case kEntityFrancois: + if (getProgress().field_9C) + return "XFRA3"; + + if (getProgress().field_A0 + || getEvent(kEventFrancoisWhistle) || getEvent(kEventFrancoisWhistleD) + || getEvent(kEventFrancoisWhistleNight) || getEvent(kEventFrancoisWhistleNightD)) + return "XFRA2"; + + if (getState()->time > kTimeParisEpernay) // Between Paris and Epernay + return "XFRA1"; + + break; + + case kEntityMmeBoutarel: + if (getProgress().field_A4) + return "XMME4"; + + if (getProgress().field_A8) + return "XMME3"; + + if (getProgress().field_A0) + return "XMME2"; + + if (getProgress().field_AC) + return "XMME1"; + + break; + + case kEntityBoutarel: + if (getProgress().eventMetBoutarel) + return "XMRB1"; + + break; + + case kEntityRebecca: + if (getProgress().field_B4) + return "XREB1A"; + + if (getProgress().field_B8) + return "XREB1"; + + break; + + case kEntitySophie: + if (getProgress().field_B0) + return "XSOP2"; + + if (getProgress().field_BC) + return "XSOP1B"; + + if (getProgress().field_B4) + return "XSOP1A"; + + if (getProgress().field_B8) + return "XSOP1"; + + break; + + case kEntityMahmud: + if (getProgress().field_C4) + return "XMAH1"; + + break; + + case kEntityYasmin: + if (getProgress().eventMetYasmin) + return "XHAR2"; + + break; + + case kEntityHadija: + if (getProgress().eventMetHadija) + return "XHAR1"; + + break; + + case kEntityAlouan: + if (getProgress().field_DC) + return "XHAR3"; + + break; + + case kEntityGendarmes: + if (getProgress().field_E0) + return "XHAR4"; + + break; + + case kEntityChapters: + if (getEvent(kEventCathDream) || getEvent(kEventCathWakingUp)) + return "XTYL3"; + + return "XTYL1"; + + default: + break; + } + + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Letters & Messages +////////////////////////////////////////////////////////////////////////// +void SoundManager::readText(int id){ + if (!_queue->isBuffered(kEntityTables4)) + return; + + if (id < 0 || (id > 8 && id < 50) || id > 64) + error("Sound::readText - attempting to use invalid id. Valid values [1;8] - [50;64], was %d", id); + + // Get proper message file (names are stored in sequence in the array but id is [1;8] - [50;64]) + const char *text = messages[id <= 8 ? id : id - 41]; + + // Check if file is in cache for id [1;8] + if (id <= 8) + if (_queue->isBuffered(text)) + _queue->removeFromQueue(text); + + playSound(kEntityTables4, text, kFlagDefault); +} + +////////////////////////////////////////////////////////////////////////// +// Sound bites +////////////////////////////////////////////////////////////////////////// +void SoundManager::playWarningCompartment(EntityIndex entity, ObjectIndex compartment) { + +#define PLAY_WARNING(index, sound1, sound2, sound3, sound4, sound5, sound6) { \ + if (_lastWarning[index] + 450 >= getState()->timeTicks) { \ + if (rnd(2)) \ + playSound(kEntityMertens, sound1, kFlagDefault); \ + else \ + playSound(kEntityMertens, rnd(2) ? sound2 : sound3, kFlagDefault); \ + } else { \ + if (rnd(2)) \ + playSound(kEntityMertens, sound4, kFlagDefault); \ + else \ + playSound(kEntityMertens, rnd(2) ? sound5 : sound6, kFlagDefault); \ + } \ + _lastWarning[index] = getState()->timeTicks; \ +} + + if (entity != kEntityMertens && entity != kEntityCoudert) + return; + + ////////////////////////////////////////////////////////////////////////// + // Mertens + if (entity == kEntityMertens) { + + switch (compartment) { + default: + break; + + case kObjectCompartment2: + PLAY_WARNING(0, "Con1502A", "Con1500B", "Con1500C", "Con1502", "Con1500", "Con1500A"); + break; + + case kObjectCompartment3: + PLAY_WARNING(1, "Con1501A", "Con1500B", "Con1500C", "Con1501", "Con1500", "Con1500A"); + break; + + case kObjectCompartment4: + PLAY_WARNING(2, "Con1503", "Con1500B", "Con1500C", "Con1503", "Con1500", "Con1500A"); + break; + + case kObjectCompartment5: + case kObjectCompartment6: + case kObjectCompartment7: + case kObjectCompartment8: + ++_lastWarning[3]; + + switch (_lastWarning[3]) { + default: + break; + + case 1: + getSound()->playSound(kEntityMertens, "Con1503C", kFlagDefault); + break; + + case 2: + getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503E" : "Con1503A", kFlagDefault); + break; + + case 3: + getSound()->playSound(kEntityMertens, rnd(2) ? "Con1503B" : "Con1503D", kFlagDefault); + _lastWarning[3] = 0; + break; + } + } + + return; + } + + ////////////////////////////////////////////////////////////////////////// + // Coudert + switch (compartment) { + default: + break; + + case kObjectCompartmentA: + if (_lastWarning[4] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1508" : "Jac1508A", kFlagDefault); + break; + + case kObjectCompartmentB: + if (_lastWarning[5] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (getProgress().field_40 || (getState()->time > kTimeCityLinz && getState()->time < kTime2133000)) + getSound()->playSound(kEntityCoudert, "Jac1507A", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, "Jac1507", kFlagDefault); + break; + + case kObjectCompartmentC: + if (_lastWarning[6] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (getProgress().chapter < kChapter3) + getSound()->playSound(kEntityCoudert, "Jac1506", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1506A" : "Jac1506B", kFlagDefault); + break; + + case kObjectCompartmentD: + if (_lastWarning[7] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + getSound()->playSound(kEntityCoudert, "Jac1505", kFlagDefault); + break; + + case kObjectCompartmentE: + if (_lastWarning[8] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (getProgress().field_40 || (getState()->time > kTime2115000 && getState()->time < kTime2133000)) { + getSound()->playSound(kEntityCoudert, "Jac1504B", kFlagDefault); + break; + } + + if (getEntities()->isInsideCompartment(kEntityRebecca, kCarRedSleeping, kPosition_4840)) + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1504" : "Jac1504A", kFlagDefault); + break; + + case kObjectCompartmentF: + if (_lastWarning[9] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (getProgress().field_40 || (getState()->time > kTime2083500 && getState()->time < kTime2133000)) { + getSound()->playSound(kEntityCoudert, "Jac1503B", kFlagDefault); + break; + } + + if (rnd(2) || getEntities()->isInsideCompartment(kEntityAnna, kCarRedSleeping, kPosition_4070)) + getSound()->playSound(kEntityCoudert, "Jac1503", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, "Jac1503A", kFlagDefault); + break; + + case kObjectCompartmentG: + if (_lastWarning[10] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (rnd(2) || getEntities()->isInsideCompartment(kEntityMilos, kCarRedSleeping, kPosition_3050)) + getSound()->playSound(kEntityCoudert, "Jac1502", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, "Jac1502A", kFlagDefault); + break; + + case kObjectCompartmentH: + if (_lastWarning[11] + 450 >= getState()->timeTicks) { + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + break; + } + + if (getEntities()->isInsideCompartment(kEntityIvo, kCarRedSleeping, kPosition_2740)) + getSound()->playSound(kEntityCoudert, rnd(2) ? "Jac1500" : "Jac1500A", kFlagDefault); + else + getSound()->playSound(kEntityCoudert, "Jac1501", kFlagDefault); + break; + } + + // Update ticks (Compartments A - H are indexes 4 - 11) + _lastWarning[compartment - 28] = getState()->timeTicks; +} + +void SoundManager::excuseMe(EntityIndex entity, EntityIndex entity2, SoundFlag flag) { + if (_queue->isBuffered(entity) && entity != kEntityPlayer && entity != kEntityChapters && entity != kEntityTrain) + return; + + if (entity2 == kEntityFrancois || entity2 == kEntityMax) + return; + + if (entity == kEntityFrancois && getEntityData(kEntityFrancois)->field_4A3 != 30) + return; + + if (flag == kFlagNone) + flag = getSoundFlag(entity); + + switch (entity) { + default: + break; + + case kEntityAnna: + playSound(kEntityPlayer, "ANN1107A", flag); + break; + + case kEntityAugust: + switch(rnd(4)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "AUG1100A", flag); + break; + + case 1: + playSound(kEntityPlayer, "AUG1100B", flag); + break; + + case 2: + playSound(kEntityPlayer, "AUG1100C", flag); + break; + + case 3: + playSound(kEntityPlayer, "AUG1100D", flag); + break; + } + break; + + case kEntityMertens: + if (Entities::isFemale(entity2)) { + playSound(kEntityPlayer, (rnd(2) ? "CON1111" : "CON1111A"), flag); + } else { + if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { + switch(rnd(3)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "CON1110A", flag); + break; + + case 1: + playSound(kEntityPlayer, "CON1110C", flag); + break; + + case 2: + playSound(kEntityPlayer, "CON1110", flag); + break; + } + } else { + if (isNight()) { + playSound(kEntityPlayer, (getProgress().field_18 == 2 ? "CON1110F" : "CON1110E")); + } else { + playSound(kEntityPlayer, "CON1110D"); + } + } + } + break; + + case kEntityCoudert: + if (Entities::isFemale(entity2)) { + playSound(kEntityPlayer, "JAC1111D", flag); + } else { + if (entity2 || getProgress().jacket != kJacketGreen || !rnd(2)) { + switch(rnd(4)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "JAC1111", flag); + break; + + case 1: + playSound(kEntityPlayer, "JAC1111A", flag); + break; + + case 2: + playSound(kEntityPlayer, "JAC1111B", flag); + break; + + case 3: + playSound(kEntityPlayer, "JAC1111C", flag); + break; + } + } else { + playSound(kEntityPlayer, "JAC1113B", flag); + } + } + break; + + case kEntityPascale: + playSound(kEntityPlayer, (rnd(2) ? "HDE1002" : "HED1002A"), flag); + break; + + case kEntityServers0: + case kEntityServers1: + switch(rnd(3)) { + default: + break; + + case 0: + playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002" : "WAT1003", flag); + break; + + case 1: + playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002A" : "WAT1003A", flag); + break; + + case 2: + playSound(kEntityPlayer, (entity == kEntityServers0) ? "WAT1002B" : "WAT1003B", flag); + break; + } + break; + + case kEntityVerges: + if (Entities::isFemale(entity2)) { + playSound(kEntityPlayer, (rnd(2) ? "TRA1113A" : "TRA1113B")); + } else { + playSound(kEntityPlayer, "TRA1112", flag); + } + break; + + case kEntityTatiana: + playSound(kEntityPlayer, (rnd(2) ? "TAT1102A" : "TAT1102B"), flag); + break; + + case kEntityAlexei: + playSound(kEntityPlayer, (rnd(2) ? "ALX1099C" : "ALX1099D"), flag); + break; + + case kEntityAbbot: + if (Entities::isFemale(entity2)) { + playSound(kEntityPlayer, "ABB3002C", flag); + } else { + switch(rnd(3)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "ABB3002", flag); + break; + + case 1: + playSound(kEntityPlayer, "ABB3002A", flag); + break; + + case 2: + playSound(kEntityPlayer, "ABB3002B", flag); + break; + } + } + break; + + case kEntityVesna: + switch(rnd(3)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "VES1109A", flag); + break; + + case 1: + playSound(kEntityPlayer, "VES1109B", flag); + break; + + case 2: + playSound(kEntityPlayer, "VES1109C", flag); + break; + } + break; + + case kEntityKahina: + playSound(kEntityPlayer, (rnd(2) ? "KAH1001" : "KAH1001A"), flag); + break; + + case kEntityFrancois: + case kEntityMmeBoutarel: + switch(rnd(4)) { + default: + break; + + case 0: + playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001" : "MME1103A", flag); + break; + + case 1: + playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001A" : "MME1103B", flag); + break; + + case 2: + playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001B" : "MME1103C", flag); + break; + + case 3: + playSound(kEntityPlayer, (entity == kEntityFrancois) ? "FRA1001C" : "MME1103D", flag); + break; + } + break; + + case kEntityBoutarel: + playSound(kEntityPlayer, "MRB1104", flag); + if (flag > 2) + getProgress().eventMetBoutarel = true; + break; + + case kEntityRebecca: + playSound(kEntityPlayer, (rnd(2) ? "REB1106" : "REB110A"), flag); + break; + + case kEntitySophie: { + switch(rnd(3)) { + default: + break; + + case 0: + playSound(kEntityPlayer, "SOP1105", flag); + break; + + case 1: + playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105C" : "SOP1105A", flag); + break; + + case 2: + playSound(kEntityPlayer, Entities::isFemale(entity2) ? "SOP1105D" : "SOP1105B", flag); + break; + } + break; + } + + case kEntityMahmud: + playSound(kEntityPlayer, "MAH1101", flag); + break; + + case kEntityYasmin: + playSound(kEntityPlayer, "HAR1002", flag); + if (flag > 2) + getProgress().eventMetYasmin = true; + break; + + case kEntityHadija: + playSound(kEntityPlayer, (rnd(2) ? "HAR1001" : "HAR1001A"), flag); + if (flag > 2) + getProgress().eventMetHadija = true; + break; + + case kEntityAlouan: + playSound(kEntityPlayer, "HAR1004", flag); + break; + } +} + +void SoundManager::excuseMeCath() { + switch(rnd(3)) { + default: + playSound(kEntityPlayer, "CAT1126B"); + break; + + case 1: + playSound(kEntityPlayer, "CAT1126C"); + break; + + case 2: + playSound(kEntityPlayer, "CAT1126D"); + break; + } +} + +const char *SoundManager::justCheckingCath() const { + switch(rnd(4)) { + default: + break; + + case 0: + return "CAT5001"; + + case 1: + return "CAT5001A"; + + case 2: + return "CAT5001B"; + + case 3: + return "CAT5001C"; + } + + return "CAT5001"; +} + +const char *SoundManager::wrongDoorCath() const { + switch(rnd(5)) { + default: + break; + + case 0: + return "CAT1125"; + + case 1: + return "CAT1125A"; + + case 2: + return "CAT1125B"; + + case 3: + return "CAT1125C"; + + case 4: + return "CAT1125D"; + } + + return "CAT1125"; +} + +const char *SoundManager::justAMinuteCath() const { + switch(rnd(3)) { + default: + break; + + case 0: + return "CAT1520"; + + case 1: + return "CAT1521"; + + case 2: + return "CAT1125"; // ?? is this a bug in the original? + } + + return "CAT1520"; +} + +////////////////////////////////////////////////////////////////////////// +// Sound flags +////////////////////////////////////////////////////////////////////////// +SoundFlag SoundManager::getSoundFlag(EntityIndex entity) const { + if (entity == kEntityPlayer) + return kFlagDefault; + + if (getEntityData(entity)->car != getEntityData(kEntityPlayer)->car) + return kFlagNone; + + // Compute sound value + SoundFlag ret = kFlag2; + + // Get default value if valid + int index = ABS(getEntityData(entity)->entityPosition - getEntityData(kEntityPlayer)->entityPosition) / 230; + if (index < 32) + ret = soundFlags[index]; + + if (getEntityData(entity)->location == kLocationOutsideTrain) { + if (getEntityData(entity)->car != kCarKronos + && !getEntities()->isOutsideAlexeiWindow() + && !getEntities()->isOutsideAnnaWindow()) + return kFlagNone; + + return (SoundFlag)(ret / 6); + } + + switch (getEntityData(entity)->car) { + default: + break; + + case kCarKronos: + if (getEntities()->isInKronosSalon(entity) != getEntities()->isInKronosSalon(kEntityPlayer)) + ret = (SoundFlag)(ret * 2); + break; + + case kCarGreenSleeping: + case kCarRedSleeping: + if (getEntities()->isInGreenCarEntrance(kEntityPlayer) && !getEntities()->isInKronosSalon(entity)) + ret = (SoundFlag)(ret * 2); + + if (getEntityData(kEntityPlayer)->location + && (getEntityData(entity)->entityPosition != kPosition_1 || !getEntities()->isDistanceBetweenEntities(kEntityPlayer, entity, 400))) + ret = (SoundFlag)(ret * 2); + break; + + case kCarRestaurant: + if (getEntities()->isInSalon(entity) == getEntities()->isInSalon(kEntityPlayer) + && (getEntities()->isInRestaurant(entity) != getEntities()->isInRestaurant(kEntityPlayer))) + ret = (SoundFlag)(ret * 2); + else + ret = (SoundFlag)(ret * 4); + break; + } + + return ret; +} + +////////////////////////////////////////////////////////////////////////// +// Misc +////////////////////////////////////////////////////////////////////////// +void SoundManager::playLoopingSound(int param) { + SoundEntry *entry = _queue->getEntry(kSoundType1); + + static const EntityPosition positions[8] = { kPosition_8200, kPosition_7500, + kPosition_6470, kPosition_5790, + kPosition_4840, kPosition_4070, + kPosition_3050, kPosition_2740 }; + + byte numLoops[8]; + numLoops[1] = 4; + numLoops[2] = 2; + numLoops[3] = 2; + numLoops[4] = 2; + numLoops[5] = 2; + numLoops[6] = 2; + + char tmp[80]; + tmp[0] = 0; + + int partNumber = 1; + int fnameLen = 6; + + if (_queue->getSoundState() & 1 && param >= 0x45 && param <= 0x46) { + if (_queue->getSoundState() & 2) { + strcpy(tmp, "STEAM.SND"); + + _loopingSoundDuration = 32767; + } else { + if (getEntityData(kEntityPlayer)->location == kLocationOutsideTrain) { + partNumber = 6; + } else { + if (getEntities()->isInsideCompartments(kEntityPlayer)) { + int objNum = (getEntityData(kEntityPlayer)->car - 3) < 1 ? 9 : 40; // Weird numbers + + numLoops[0] = 0; + + for (int pos = 0; pos < 8; pos++) { + if (numLoops[0]) + break; + if (getEntities()->isInsideCompartment(kEntityPlayer, getEntityData(kEntityPlayer)->car, positions[pos])) { + numLoops[0] = 1; + partNumber = (getObjects()->get((ObjectIndex)objNum).location - 2) < 1 ? 6 : 1; + } + objNum++; + } + } else { + switch (getEntityData(kEntityPlayer)->car) { + case 1: + case 6: + partNumber = 4; + break; + case 2: + case 3: + case 4: + case 5: + partNumber = 1; + break; + case 7: + partNumber = 5; + break; + case 8: + partNumber = 99; + break; + case 9: + partNumber = 3; + break; + default: + partNumber = 6; + break; + } + } + } + + if (partNumber != 99) + sprintf(tmp, "LOOP%d%c.SND", partNumber, _engine->getRandom().getRandomNumber(numLoops[partNumber] - 1) + 'A'); + } + + if (getFlags()->flag_3) + fnameLen = 5; + + if (!entry || scumm_strnicmp(entry->_name2.c_str(), tmp, fnameLen)) { + _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; + + if (partNumber != 99) { + playSoundWithSubtitles(tmp, kFlagLoopedSound, kEntitySteam); + + if (entry) + entry->update(0); + + SoundEntry *entry1 = _queue->getEntry(kSoundType1); + if (entry1) + entry1->update(7); + } + } + } +} + +} // End of namespace LastExpress diff --git a/engines/lastexpress/sound/sound.h b/engines/lastexpress/sound/sound.h new file mode 100644 index 0000000000..797e52646e --- /dev/null +++ b/engines/lastexpress/sound/sound.h @@ -0,0 +1,87 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef LASTEXPRESS_SOUND_H +#define LASTEXPRESS_SOUND_H + +#include "lastexpress/shared.h" + +#include "common/str.h" + +namespace LastExpress { + +class LastExpressEngine; +class SoundQueue; + +class SoundManager { +public: + SoundManager(LastExpressEngine *engine); + ~SoundManager(); + + // Sound playing + void playSound(EntityIndex entity, Common::String filename, SoundFlag flag = kFlagInvalid, byte a4 = 0); + bool playSoundWithSubtitles(Common::String filename, SoundFlag flag, EntityIndex entity, byte a4 = 0); + void playSoundEvent(EntityIndex entity, byte action, byte a3 = 0); + void playDialog(EntityIndex entity, EntityIndex entityDialog, SoundFlag flag, byte a4); + void playSteam(CityIndex index); + void playFightSound(byte action, byte a4); + void playLocomotiveSound(); + void playWarningCompartment(EntityIndex entity, ObjectIndex compartment); + void playLoopingSound(int param); + + // Dialog & Letters + void readText(int id); + const char *getDialogName(EntityIndex entity) const; + + // Sound bites + void excuseMe(EntityIndex entity, EntityIndex entity2 = kEntityPlayer, SoundFlag flag = kFlagNone); + void excuseMeCath(); + const char *justCheckingCath() const; + const char *wrongDoorCath() const; + const char *justAMinuteCath() const; + + // Flags + SoundFlag getSoundFlag(EntityIndex index) const; + + // Accessors + SoundQueue *getQueue() { return _queue; } + uint32 getData2() { return _data2; } + +private: + LastExpressEngine *_engine; + SoundQueue *_queue; + + // Compartment warnings by Mertens or Coudert + uint32 _lastWarning[12]; + + // Looping sound + int _loopingSoundDuration; + + // Unknown data + uint32 _data0; + uint32 _data1; + uint32 _data2; +}; + +} // End of namespace LastExpress + +#endif // LASTEXPRESS_SOUND_H -- cgit v1.2.3 From b4ac4988cca41c2a59e4de99b8fe5392372e21dd Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 28 Jun 2011 22:54:51 -0400 Subject: LASTEXPRESS: Cleanup comments --- engines/lastexpress/data/animation.cpp | 12 +++--- engines/lastexpress/data/background.cpp | 2 +- engines/lastexpress/data/font.cpp | 8 ++-- engines/lastexpress/data/scene.cpp | 8 ++-- engines/lastexpress/data/sequence.cpp | 14 +++---- engines/lastexpress/data/snd.cpp | 4 +- engines/lastexpress/data/subtitle.cpp | 4 +- engines/lastexpress/entities/entity.cpp | 10 ++--- engines/lastexpress/entities/entity.h | 20 +++++----- engines/lastexpress/entities/entity_intern.h | 4 +- engines/lastexpress/entities/train.cpp | 2 +- engines/lastexpress/fight/fight.cpp | 8 ++-- engines/lastexpress/game/action.cpp | 4 +- engines/lastexpress/game/beetle.cpp | 14 +++---- engines/lastexpress/game/entities.cpp | 14 +++---- engines/lastexpress/game/inventory.cpp | 4 +- engines/lastexpress/game/logic.cpp | 4 +- engines/lastexpress/game/object.cpp | 2 +- engines/lastexpress/game/savegame.cpp | 56 ++++++++++++++-------------- engines/lastexpress/game/savepoint.cpp | 6 +-- engines/lastexpress/game/scenes.cpp | 6 +-- engines/lastexpress/game/state.cpp | 2 +- engines/lastexpress/game/state.h | 2 +- engines/lastexpress/graphics.cpp | 6 +-- engines/lastexpress/lastexpress.cpp | 2 +- engines/lastexpress/menu/clock.cpp | 2 +- engines/lastexpress/menu/menu.cpp | 2 +- engines/lastexpress/menu/trainline.cpp | 2 +- engines/lastexpress/resource.cpp | 4 +- engines/lastexpress/sound/entry.cpp | 2 +- engines/lastexpress/sound/queue.cpp | 4 +- engines/lastexpress/sound/sound.cpp | 4 +- 32 files changed, 119 insertions(+), 119 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/animation.cpp b/engines/lastexpress/data/animation.cpp index 1cbf7672d1..28d30ec7d1 100644 --- a/engines/lastexpress/data/animation.cpp +++ b/engines/lastexpress/data/animation.cpp @@ -77,7 +77,7 @@ bool Animation::load(Common::SeekableReadStream *stream, int flag) { // Check if there is enough data if (_stream->size() - _stream->pos() < (signed)(numChunks * sizeof(Chunk))) { - debugC(2, kLastExpressDebugGraphics, "NIS file seems to be corrupted!"); + debugC(2, kLastExpressDebugGraphics, "NIS file seems to be corrupted"); return false; } @@ -101,10 +101,10 @@ bool Animation::load(Common::SeekableReadStream *stream, int flag) { bool Animation::process() { if (!_currentChunk) - error("Animation::process - internal error: the current chunk iterator is invalid!"); + error("[Animation::process] Current chunk iterator is invalid"); if (_stream == NULL || _chunks.size() == 0) - error("Trying to show an animation before loading data"); + error("[Animation::process] Trying to show an animation before loading data"); // TODO: - subtract the time paused by the GUI // - Re-implement to be closer to the original engine @@ -191,7 +191,7 @@ bool Animation::process() { break; default: - error(" UNKNOWN chunk type=%x frame=%d size=%d", _currentChunk->type, _currentChunk->frame, _currentChunk->size); + error("[Animation::process] UNKNOWN chunk type=%x frame=%d size=%d", _currentChunk->type, _currentChunk->frame, _currentChunk->size); break; } _currentChunk++; @@ -206,7 +206,7 @@ bool Animation::hasEnded() { Common::Rect Animation::draw(Graphics::Surface *surface) { if (!_overlay) - error("Animation::draw - internal error: the current overlay animation frame is invalid!"); + error("[Animation::draw] Current overlay animation frame is invalid"); // Paint the background if (_backgroundCurrent == 1 && _background1) @@ -242,7 +242,7 @@ AnimFrame *Animation::processChunkFrame(Common::SeekableReadStream *in, const Ch void Animation::processChunkAudio(Common::SeekableReadStream *in, const Chunk &c) { if (!_audio) - error("Animation::processChunkAudio - internal error: the audio stream is invalid!"); + error("[Animation::processChunkAudio] Audio stream is invalid"); // Skip the Snd header, to queue just the audio blocks uint32 size = c.size; diff --git a/engines/lastexpress/data/background.cpp b/engines/lastexpress/data/background.cpp index de6fd7eeae..3d866c26f9 100644 --- a/engines/lastexpress/data/background.cpp +++ b/engines/lastexpress/data/background.cpp @@ -85,7 +85,7 @@ bool Background::load(Common::SeekableReadStream *stream) { Common::Rect Background::draw(Graphics::Surface *surface) { if (!_data) { - debugC(2, kLastExpressDebugGraphics, "Trying to show a background before loading data!"); + debugC(2, kLastExpressDebugGraphics, "Trying to show a background before loading data"); return Common::Rect(); } diff --git a/engines/lastexpress/data/font.cpp b/engines/lastexpress/data/font.cpp index 9a60b88a25..79cf64e617 100644 --- a/engines/lastexpress/data/font.cpp +++ b/engines/lastexpress/data/font.cpp @@ -89,17 +89,17 @@ bool Font::load(Common::SeekableReadStream *stream) { uint16 Font::getCharGlyph(uint16 c) const { //warning("%c", c); if (c >= 0x200) - error("Express::Font: Invalid character %d", c); + error("[Font::getCharGlyph] Invalid character %d", c); return _charMap[c]; } byte *Font::getGlyphImg(uint16 g) { if (!_glyphs) - error("Express::getGlyphImg: Invalid glyphs!"); + error("[Font::getGlyphImg] Invalid glyphs"); if (g >= _numGlyphs) - error("Express::getGlyphImg: Invalid glyph %d (%d available)", g, _numGlyphs); + error("[Font::getGlyphImg] Invalid glyph %d (%d available)", g, _numGlyphs); return _glyphs + g * 18 * 8; } @@ -140,7 +140,7 @@ uint8 Font::getCharWidth(uint16 c) const{ return 10; } else { if (!_glyphWidths) - error("Express::getCharWidth: Invalid glyphs widths!"); + error("[Font::getCharWidth] Invalid glyphs widths"); return _glyphWidths[getCharGlyph(c)]; } diff --git a/engines/lastexpress/data/scene.cpp b/engines/lastexpress/data/scene.cpp index 2ec8e6935d..8f279ffbb3 100644 --- a/engines/lastexpress/data/scene.cpp +++ b/engines/lastexpress/data/scene.cpp @@ -187,10 +187,10 @@ bool Scene::checkHotSpot(const Common::Point &coord, SceneHotspot **hotspot) { SceneHotspot *Scene::getHotspot(uint index) { if (_hotspots.empty()) - error("Scene::getHotspot: scene does not have any hotspots!"); + error("[Scene::getHotspot] Scene does not have any hotspots"); if (index >= _hotspots.size()) - error("Scene::getHotspot: invalid index (was: %d, max: %d)", index, _hotspots.size() - 1); + error("[Scene::getHotspot] Invalid index (was: %d, max: %d)", index, _hotspots.size() - 1); return _hotspots[index]; } @@ -202,7 +202,7 @@ Common::Rect Scene::draw(Graphics::Surface *surface) { Common::String sceneName(_name); sceneName.trim(); if (sceneName.empty()) - error("Scene::draw: This scene is not a valid drawing scene!"); + error("[Scene::draw] This scene is not a valid drawing scene"); // Load background Background *background = ((LastExpressEngine *)g_engine)->getResourceManager()->loadBackground(sceneName); @@ -260,7 +260,7 @@ bool SceneLoader::load(Common::SeekableReadStream *stream) { // Read the default scene to get the total number of scenes Scene *header = Scene::load(_stream); if (!header) - error("SceneLoader::load: Invalid data file!"); + error("[SceneLoader::load] Invalid data file"); debugC(2, kLastExpressDebugScenes, " found %d entries", header->entityPosition); /* Header entityPosition is the scene count */ diff --git a/engines/lastexpress/data/sequence.cpp b/engines/lastexpress/data/sequence.cpp index a27c27de2e..a62348f6c0 100644 --- a/engines/lastexpress/data/sequence.cpp +++ b/engines/lastexpress/data/sequence.cpp @@ -115,7 +115,7 @@ AnimFrame::AnimFrame(Common::SeekableReadStream *in, const FrameInfo &f) : _pale decompFF(in, f); break; default: - error("Unknown frame compression: %d", f.compressionType); + error("[AnimFrame::AnimFrame] Unknown frame compression: %d", f.compressionType); } readPalette(in, f); @@ -379,11 +379,11 @@ bool Sequence::load(Common::SeekableReadStream *stream, byte field30) { // Move stream to start of frame _stream->seek((int32)(_sequenceHeaderSize + i * _sequenceFrameSize), SEEK_SET); if (_stream->eos()) - error("Couldn't seek to the current frame data"); + error("[Sequence::load] Couldn't seek to the current frame data"); // Check if there is enough data if ((unsigned)(_stream->size() - _stream->pos()) < _sequenceFrameSize) - error("The sequence frame does not have a valid header"); + error("[Sequence::load] The sequence frame does not have a valid header"); FrameInfo info; info.read(_stream, true); @@ -397,10 +397,10 @@ bool Sequence::load(Common::SeekableReadStream *stream, byte field30) { FrameInfo *Sequence::getFrameInfo(uint16 index) { if (_frames.size() == 0) - error("Trying to decode a sequence before loading its data"); + error("[Sequence::getFrameInfo] Trying to decode a sequence before loading its data"); if (index > _frames.size() - 1) - error("Invalid sequence frame requested: %d, max %d", index, _frames.size() - 1); + error("[Sequence::getFrameInfo] Invalid sequence frame requested: %d, max %d", index, _frames.size() - 1); return &_frames[index]; } @@ -463,14 +463,14 @@ bool SequenceFrame::nextFrame() { FrameInfo *SequenceFrame::getInfo() { if (!_sequence) - error("SequenceFrame::getFrameInfo: Invalid sequence!"); + error("[SequenceFrame::getInfo] Invalid sequence"); return _sequence->getFrameInfo(_frame); } Common::String SequenceFrame::getName() { if (!_sequence) - error("SequenceFrame::getName: Invalid sequence!"); + error("[SequenceFrame::getName] Invalid sequence"); return _sequence->getName(); } diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index 3ffe3ca14b..d92ebbc5e3 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -152,7 +152,7 @@ void AppendableSound::queueBuffer(const byte *data, uint32 size) { void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) { if (!_as) - error("AppendableSound::queueBuffer - internal error: the audio stream is invalid!"); + error("[AppendableSound::queueBuffer] Audio stream is invalid"); // Setup the ADPCM decoder uint32 sizeIn = (uint32)bufferIn->size(); @@ -164,7 +164,7 @@ void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) { void AppendableSound::finish() { if (!_as) - error("AppendableSound::queueBuffer - internal error: the audio stream is invalid!"); + error("[AppendableSound::finish] Audio stream is invalid"); if (!_finished) _as->finish(); diff --git a/engines/lastexpress/data/subtitle.cpp b/engines/lastexpress/data/subtitle.cpp index c3a7397b66..0be832cbdd 100644 --- a/engines/lastexpress/data/subtitle.cpp +++ b/engines/lastexpress/data/subtitle.cpp @@ -168,13 +168,13 @@ bool SubtitleManager::load(Common::SeekableReadStream *stream) { // Read header to get the number of subtitles uint32 numSubtitles = stream->readUint16LE(); if (stream->eos()) - error("Cannot read from subtitle file"); + error("[SubtitleManager::load] Cannot read from subtitle file"); debugC(3, kLastExpressDebugSubtitle, "Number of subtitles in file: %d", numSubtitles); // TODO: Check that stream contain enough data //if (stream->size() < (signed)(numSubtitles * sizeof(SubtitleData))) { - //debugC(2, kLastExpressDebugSubtitle, "Subtitle file does not contain valid data!"); + //debugC(2, kLastExpressDebugSubtitle, "Subtitle file does not contain valid data"); //return false; //} diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp index 60efd70329..e136ca4776 100644 --- a/engines/lastexpress/entities/entity.cpp +++ b/engines/lastexpress/entities/entity.cpp @@ -105,24 +105,24 @@ void EntityData::EntityCallData::saveLoadWithSerializer(Common::Serializer &s) { ////////////////////////////////////////////////////////////////////////// EntityData::EntityParameters *EntityData::getParameters(uint callback, byte index) const { if (callback >= 9) - error("EntityData::getParameters: invalid callback value (was: %d, max: 9)", callback); + error("[EntityData::getParameters] Invalid callback value (was: %d, max: 9)", callback); if (index >= 4) - error("EntityData::getParameters: invalid index value (was: %d, max: 4)", index); + error("[EntityData::getParameters] Invalid index value (was: %d, max: 4)", index); return _parameters[callback].parameters[index]; } int EntityData::getCallback(uint callback) const { if (callback >= 16) - error("EntityData::getParameters: invalid callback value (was: %d, max: 16)", callback); + error("[EntityData::getCallback] Invalid callback value (was: %d, max: 16)", callback); return _data.callbacks[callback]; } void EntityData::setCallback(uint callback, byte index) { if (callback >= 16) - error("EntityData::getParameters: invalid callback value (was: %d, max: 16)", callback); + error("[EntityData::setCallback] Invalid callback value (was: %d, max: 16)", callback); _data.callbacks[callback] = index; } @@ -137,7 +137,7 @@ void EntityData::updateParameters(uint32 index) const { else if (index < 32) getParameters(8, 3)->update(index - 24); else - error("EntityData::updateParameters: invalid param index to update (was:%d, max:32)!", index); + error("[EntityData::updateParameters] Invalid param index to update (was:%d, max:32)", index); } void EntityData::saveLoadWithSerializer(Common::Serializer &s) { diff --git a/engines/lastexpress/entities/entity.h b/engines/lastexpress/entities/entity.h index 6a4f4166bb..039f461c7b 100644 --- a/engines/lastexpress/entities/entity.h +++ b/engines/lastexpress/entities/entity.h @@ -85,7 +85,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersIIII::update: invalid index (was: %d)", index); + error("[EntityParametersIIII::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 1: param2 = 1; break; @@ -134,7 +134,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersSIII::update: invalid index (was: %d)", index); + error("[EntityParametersSIII::update] Invalid index (was: %d)", index); case 3: param4 = 1; break; case 4: param5 = 1; break; @@ -174,7 +174,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersSIIS::update: invalid index (was: %d)", index); + error("[EntityParametersSIIS::update] Invalid index (was: %d)", index); case 3: param4 = 1; break; case 4: param5 = 1; break; @@ -209,7 +209,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersISSI::update: invalid index (was: %d)", index); + error("[EntityParametersISSI::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 7: param8 = 1; break; @@ -248,7 +248,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersISII::update: invalid index (was: %d)", index); + error("[EntityParametersISII::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 4: param5 = 1; break; @@ -288,7 +288,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersSSII::update: invalid index (was: %d)", index); + error("[EntityParametersSSII::update] Invalid index (was: %d)", index); case 6: param7 = 1; break; case 7: param8 = 1; break; @@ -319,7 +319,7 @@ public: } void update(uint32) { - error("EntityParametersSSS::update: cannot update this type of parameters"); + error("[EntityParametersSSS::update] Cannot update this type of parameters"); } void saveLoadWithSerializer(Common::Serializer &s) { @@ -349,7 +349,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersIISS::update: invalid index (was: %d)", index); + error("[EntityParametersIISS::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 1: param2 = 1; break; @@ -388,7 +388,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersIISI::update: invalid index (was: %d)", index); + error("[EntityParametersIISI::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 1: param2 = 1; break; @@ -432,7 +432,7 @@ public: void update(uint32 index) { switch (index) { default: - error("EntityParametersIIIS::update: invalid index (was: %d)", index); + error("[EntityParametersIIIS::update] Invalid index (was: %d)", index); case 0: param1 = 1; break; case 1: param2 = 1; break; diff --git a/engines/lastexpress/entities/entity_intern.h b/engines/lastexpress/entities/entity_intern.h index 43d7f702c9..bf75e022de 100644 --- a/engines/lastexpress/entities/entity_intern.h +++ b/engines/lastexpress/entities/entity_intern.h @@ -96,7 +96,7 @@ void class::setup_##name() { \ #define EXPOSE_PARAMS(type) \ type *params = (type*)_data->getCurrentParameters(); \ if (!params) \ - error("Trying to call an entity function with invalid parameters!"); \ + error("[EXPOSE_PARAMS] Trying to call an entity function with invalid parameters"); \ // function signature without setup (we keep the index for consistency but never use it) @@ -413,7 +413,7 @@ void class::setup_##name() { \ ////////////////////////////////////////////////////////////////////////// #define CALLBACK_ACTION() { \ if (getData()->currentCall == 0) \ - error("CALLBACK_ACTION: currentCall is already 0, cannot proceed!"); \ + error("[CALLBACK_ACTION] currentCall is already 0, cannot proceed"); \ getData()->currentCall--; \ getSavePoints()->setCallback(_entityIndex, _callbacks[_data->getCurrentCallback()]); \ getSavePoints()->call(_entityIndex, _entityIndex, kActionCallback); \ diff --git a/engines/lastexpress/entities/train.cpp b/engines/lastexpress/entities/train.cpp index 7d90ea5e64..bced1da62b 100644 --- a/engines/lastexpress/entities/train.cpp +++ b/engines/lastexpress/entities/train.cpp @@ -92,7 +92,7 @@ IMPLEMENT_FUNCTION_II(7, Train, harem, ObjectIndex, uint32) switch (params->param1) { default: - error("Train::harem: Invalid value for parameter 1: %d", params->param1); + error("[Train::harem] Invalid value for parameter 1: %d", params->param1); break; case kObjectCompartment5: diff --git a/engines/lastexpress/fight/fight.cpp b/engines/lastexpress/fight/fight.cpp index 38a93cfd94..b832d46a60 100644 --- a/engines/lastexpress/fight/fight.cpp +++ b/engines/lastexpress/fight/fight.cpp @@ -162,7 +162,7 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) { // Blink egg if (getGlobalTimer()) { - warning("Fight::handleMouseMove - egg blinking not implemented!"); + warning("[Fight::handleTick] Egg blinking not implemented"); } if (!_data || _data->index) @@ -197,7 +197,7 @@ void Fight::handleTick(const Common::Event &ev, bool isProcessing) { ////////////////////////////////////////////////////////////////////////// Fight::FightEndType Fight::setup(FightType type) { if (_data) - error("Fight::setup - calling fight setup again while a fight is already in progress!"); + error("[Fight::setup] Calling fight setup again while a fight is already in progress"); ////////////////////////////////////////////////////////////////////////// // Prepare UI & state @@ -320,7 +320,7 @@ void Fight::clearData() { ////////////////////////////////////////////////////////////////////////// void Fight::loadData(FightType type) { if (!_data) - error("Fight::loadData - invalid data!"); + error("[Fight::loadData] Data not initialized"); switch (type) { default: @@ -353,7 +353,7 @@ void Fight::loadData(FightType type) { } if (!_data->player || !_data->opponent) - error("Fight::loadData - error loading fight data (type=%d)", type); + error("[Fight::loadData] Error loading fight data (type=%d)", type); // Setup opponent pointers setOpponents(); diff --git a/engines/lastexpress/game/action.cpp b/engines/lastexpress/game/action.cpp index 2c7b5b3c32..2ef4c20d70 100644 --- a/engines/lastexpress/game/action.cpp +++ b/engines/lastexpress/game/action.cpp @@ -407,7 +407,7 @@ SceneIndex Action::processHotspot(const SceneHotspot &hotspot) { ////////////////////////////////////////////////////////////////////////// // Action 0 IMPLEMENT_ACTION(dummy) - warning("Action::action_dummy: Dummy action function called (hotspot action: %d)!", hotspot.action); + warning("[Action::action_dummy] Dummy action function called (hotspot action: %d)", hotspot.action); return kSceneInvalid; } @@ -1910,7 +1910,7 @@ LABEL_KEY: // Play an animation and add delta time to global game time void Action::playAnimation(EventIndex index, bool debugMode) const { if (index >= _animationListSize) - error("Action::playAnimation: invalid event index (value=%i, max=%i)", index, _animationListSize); + error("[Action::playAnimation] Invalid event index (value=%i, max=%i)", index, _animationListSize); // In debug mode, just show the animation if (debugMode) { diff --git a/engines/lastexpress/game/beetle.cpp b/engines/lastexpress/game/beetle.cpp index cb6f0a3306..ab707ddae9 100644 --- a/engines/lastexpress/game/beetle.cpp +++ b/engines/lastexpress/game/beetle.cpp @@ -131,7 +131,7 @@ bool Beetle::isLoaded() const { bool Beetle::catchBeetle() { if (!_data) - error("Beetle::catchBeetle: sequences have not been loaded!"); + error("[Beetle::catchBeetle] Sequences have not been loaded"); if (getInventory()->getSelectedItem() == kItemMatchBox && getInventory()->hasItem(kItemMatch) @@ -148,14 +148,14 @@ bool Beetle::catchBeetle() { bool Beetle::isCatchable() const { if (!_data) - error("Beetle::isCatchable: sequences have not been loaded!"); + error("[Beetle::isCatchable] Sequences have not been loaded"); return (_data->indexes[_data->offset] >= 30); } void Beetle::update() { if (!_data) - error("Beetle::update: sequences have not been loaded!"); + error("[Beetle::update] Sequences have not been loaded"); if (!_data->isLoaded) return; @@ -194,7 +194,7 @@ void Beetle::update() { void Beetle::drawUpdate() { if (!_data) - error("Beetle::drawUpdate: sequences have not been loaded!"); + error("[Beetle::drawUpdate] Sequences have not been loaded"); if (_data->frame != NULL) { getScenes()->setCoordinates(_data->frame); @@ -366,7 +366,7 @@ void Beetle::drawUpdate() { void Beetle::move() { if (!_data) - error("Beetle::move: sequences have not been loaded!"); + error("[Beetle::move] Sequences have not been loaded"); if (_data->indexes[_data->offset] >= 24 && _data->indexes[_data->offset] <= 29) return; @@ -444,7 +444,7 @@ update_data: // Update the beetle sequence to show the correct frames in the correct place void Beetle::updateFrame(SequenceFrame *frame) const { if (!_data) - error("Beetle::updateSequence: sequences have not been loaded!"); + error("[Beetle::updateFrame] Sequences have not been loaded"); if (!frame) return; @@ -459,7 +459,7 @@ void Beetle::updateFrame(SequenceFrame *frame) const { void Beetle::updateData(uint32 index) { if (!_data) - error("Beetle::updateData: sequences have not been loaded!"); + error("[Beetle::updateData] Sequences have not been loaded"); if (!_data->isLoaded) return; diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp index a56531891b..f6bb2030f0 100644 --- a/engines/lastexpress/game/entities.cpp +++ b/engines/lastexpress/game/entities.cpp @@ -202,7 +202,7 @@ Entity *Entities::get(EntityIndex entity) { assert((uint)entity < _entities.size()); if (entity == kEntityPlayer) - error("Cannot get entity for index == 0!"); + error("[Entities::get] Cannot get entity for kEntityPlayer"); return _entities[entity]; } @@ -220,24 +220,24 @@ int Entities::getPosition(CarIndex car, Position position) const { int index = 100 * car + position; if (car > 10) - error("Entities::getPosition: trying to access an invalid car (was: %d, valid:0-9)", car); + error("[Entities::getPosition] Trying to access an invalid car (was: %d, valid:0-9)", car); if (position > 100) - error("Entities::getPosition: trying to access an invalid position (was: %d, valid:0-100)", position); + error("[Entities::getPosition] Trying to access an invalid position (was: %d, valid:0-100)", position); return _positions[index]; } int Entities::getCompartments(int index) const { if (index >= _compartmentsCount) - error("Entities::getCompartments: trying to access an invalid compartment (was: %d, valid:0-15)", index); + error("[Entities::getCompartments] Trying to access an invalid compartment (was: %d, valid:0-15)", index); return _compartments[index]; } int Entities::getCompartments1(int index) const { if (index >= _compartmentsCount) - error("Entities::getCompartments: trying to access an invalid compartment (was: %d, valid:0-15)", index); + error("[Entities::getCompartments] Trying to access an invalid compartment (was: %d, valid:0-15)", index); return _compartments1[index]; } @@ -1782,7 +1782,7 @@ void Entities::enterCompartment(EntityIndex entity, ObjectIndex compartment, boo // Update compartments int index = (compartment < 32 ? compartment - 1 : compartment - 24); if (index >= 16) - error("Entities::exitCompartment: invalid compartment index!"); + error("[Entities::enterCompartment] Invalid compartment index"); if (useCompartment1) _compartments1[index] |= STORE_VALUE(entity); @@ -1868,7 +1868,7 @@ void Entities::exitCompartment(EntityIndex entity, ObjectIndex compartment, bool // Update compartments int index = (compartment < 32 ? compartment - 1 : compartment - 24); if (index >= 16) - error("Entities::exitCompartment: invalid compartment index!"); + error("[Entities::exitCompartment] Invalid compartment index"); if (useCompartment1) _compartments1[index] &= ~STORE_VALUE(entity); diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp index d902c8860a..e417b1ec0d 100644 --- a/engines/lastexpress/game/inventory.cpp +++ b/engines/lastexpress/game/inventory.cpp @@ -439,7 +439,7 @@ void Inventory::showHourGlass(){ ////////////////////////////////////////////////////////////////////////// Inventory::InventoryEntry *Inventory::get(InventoryItem item) { if (item >= kPortraitOriginal) - error("Inventory::getEntry: Invalid inventory item!"); + error("[Inventory::get] Invalid inventory item"); return &_entries[item]; } @@ -623,7 +623,7 @@ void Inventory::drawEgg() { // Blinking egg: we need to blink the egg for delta time, with the blinking getting faster until it's always lit. void Inventory::drawBlinkingEgg() { - warning("Inventory::drawEgg - blinking not implemented!"); + warning("[Inventory::drawBlinkingEgg] Blinking not implemented"); //// TODO show egg (with or without mouseover) diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp index 2b7b1cfa50..aeac8cff98 100644 --- a/engines/lastexpress/game/logic.cpp +++ b/engines/lastexpress/game/logic.cpp @@ -413,7 +413,7 @@ void Logic::eventTick(const Common::Event &) { void Logic::resetState() { getState()->scene = kSceneDefault; - warning("Logic::resetState: not implemented! You need to restart the engine until this is implemented."); + warning("[Logic::resetState] Not implemented! You need to restart the engine until this is implemented."); } /** @@ -506,7 +506,7 @@ void Logic::playFinalSequence() const { } void Logic::showCredits() const { - error("Logic::showCredits: not implemented!"); + error("[Logic::showCredits] Not implemented"); } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/game/object.cpp b/engines/lastexpress/game/object.cpp index a600075953..d9e9e4279a 100644 --- a/engines/lastexpress/game/object.cpp +++ b/engines/lastexpress/game/object.cpp @@ -39,7 +39,7 @@ Objects::Objects(LastExpressEngine *engine) : _engine(engine) {} const Objects::Object Objects::get(ObjectIndex index) const { if (index >= kObjectMax) - error("Objects::get - internal error: invalid object index (%d)", index); + error("[Objects::get] Invalid object index (%d)", index); return _objects[index]; } diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index 8dfc214913..ebada5dd4e 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -75,10 +75,10 @@ void SaveLoad::initStream() { void SaveLoad::flushStream(GameId id) { Common::OutSaveFile *save = openForSaving(id); if (!save) - error("SaveLoad::flushStream: cannot open savegame (%s)!", getFilename(id).c_str()); + error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(id).c_str()); if (!_savegame) - error("SaveLoad::flushStream: savegame stream is invalid"); + error("[SaveLoad::flushStream] Savegame stream is invalid"); save->write(_savegame->getData(), (uint32)_savegame->size()); @@ -109,7 +109,7 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) { SavegameMainHeader mainHeader; mainHeader.saveLoadWithSerializer(ser); if (!mainHeader.isValid()) - error("SaveLoad::init - Savegame seems to be corrupted (invalid header)"); + error("[SaveLoad::init] Savegame seems to be corrupted (invalid header)"); // Reset cached entry headers if needed if (resetHeaders) { @@ -148,10 +148,10 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) { void SaveLoad::loadStream(GameId id) { Common::InSaveFile *save = openForLoading(id); if (save->size() < 32) - error("SaveLoad::init - Savegame seems to be corrupted (not enough data: %i bytes)", save->size()); + error("[SaveLoad::loadStream] Savegame seems to be corrupted (not enough data: %i bytes)", save->size()); if (!_savegame) - error("SaveLoad::loadStream: savegame stream is invalid"); + error("[SaveLoad::loadStream] Savegame stream is invalid"); // Load all savegame data uint8* buf = new uint8[8192]; @@ -192,7 +192,7 @@ void SaveLoad::clear(bool clearStream) { // Load game void SaveLoad::loadGame(GameId id) { if (!_savegame) - error("SaveLoad::loadGame: No savegame stream present!"); + error("[SaveLoad::loadGame] No savegame stream present"); // Rewind current savegame _savegame->seek(0); @@ -200,12 +200,12 @@ void SaveLoad::loadGame(GameId id) { // Validate main header SavegameMainHeader header; if (!loadMainHeader(_savegame, &header)) { - debugC(2, kLastExpressDebugSavegame, "SaveLoad::saveGame - Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str()); + debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str()); return; } if (!_savegame) - error("SaveLoad::loadGame: No savegame stream present!"); + error("[SaveLoad::loadGame] No savegame stream present"); // Load the last entry _savegame->seek(header.offsetEntry); @@ -230,7 +230,7 @@ void SaveLoad::loadGame(GameId id) { // Load a specific game entry void SaveLoad::loadGame(GameId id, uint32 index) { - error("SaveLoad::loadGame: not implemented! (only loading the last entry is working for now)"); + error("[SaveLoad::loadGame] Not implemented! (only loading the last entry is working for now)"); } // Save game @@ -241,12 +241,12 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) { // Validate main header SavegameMainHeader header; if (!loadMainHeader(_savegame, &header)) { - debugC(2, kLastExpressDebugSavegame, "SaveLoad::saveGame - Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str()); + debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str()); return; } if (!_savegame) - error("SaveLoad::saveGame: savegame stream is invalid"); + error("[SaveLoad::saveGame] Savegame stream is invalid"); // Validate the current entry if it exists if (header.count > 0) { @@ -258,7 +258,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) { entry.saveLoadWithSerializer(ser); if (!entry.isValid()) { - warning("SaveLoad::saveGame: Invalid entry. This savegame might be corrupted!"); + warning("[SaveLoad::saveGame] Invalid entry. This savegame might be corrupted"); _savegame->seek(header.offset); } else if (getState()->time < entry.time || (type == kSavegameTypeTickInterval && getState()->time == entry.time)) { // Not ready to save a game, skipping! @@ -296,7 +296,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) { // Validate the main header if (!header.isValid()) - error("SaveLoad::saveGame: main game header is invalid!"); + error("[SaveLoad::saveGame] Main game header is invalid"); // Write the main header _savegame->seek(0); @@ -307,7 +307,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) { } void SaveLoad::saveVolumeBrightness() { - warning("SaveLoad::saveVolumeBrightness: not implemented!"); + warning("[SaveLoad::saveVolumeBrightness] Not implemented"); } ////////////////////////////////////////////////////////////////////////// @@ -319,7 +319,7 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he // Check there is enough data (32 bytes) if (stream->size() < 32) { - debugC(2, kLastExpressDebugSavegame, "SaveLoad::loadMainHeader - Savegame seems to be corrupted (not enough data: %i bytes)!", stream->size()); + debugC(2, kLastExpressDebugSavegame, "Savegame seems to be corrupted (not enough data: %i bytes)", stream->size()); return false; } @@ -331,7 +331,7 @@ bool SaveLoad::loadMainHeader(Common::InSaveFile *stream, SavegameMainHeader *he // Validate the header if (!header->isValid()) { - debugC(2, kLastExpressDebugSavegame, "SaveLoad::loadMainHeader - Cannot validate main header!"); + debugC(2, kLastExpressDebugSavegame, "Cannot validate main header"); return false; } @@ -348,11 +348,11 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) { uint32 _count = (uint32)_savegame->pos() - _prevPosition; \ debugC(kLastExpressDebugSavegame, "Savegame: Writing " #name ": %d bytes", _count); \ if (_count != val)\ - error("SaveLoad::writeEntry: Number of bytes written (%d) differ from expected count (%d)", _count, val); \ + error("[SaveLoad::writeEntry] Number of bytes written (%d) differ from expected count (%d)", _count, val); \ } if (!_savegame) - error("SaveLoad::writeEntry: savegame stream is invalid"); + error("[SaveLoad::writeEntry] Savegame stream is invalid"); SavegameEntryHeader header; @@ -395,7 +395,7 @@ void SaveLoad::writeEntry(SavegameType type, EntityIndex entity, uint32 value) { // Validate entry header if (!header.isValid()) - error("SaveLoad::writeEntry: entry header is invalid"); + error("[SaveLoad::writeEntry] Entry header is invalid"); // Save the header with the updated info _savegame->seek(originalPosition); @@ -412,7 +412,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b uint32 _count = (uint32)_savegame->pos() - _prevPosition; \ debugC(kLastExpressDebugSavegame, "Savegame: Reading " #name ": %d bytes", _count); \ if (_count != val) \ - error("SaveLoad::readEntry: Number of bytes read (%d) differ from expected count (%d)", _count, val); \ + error("[SaveLoad::readEntry] Number of bytes read (%d) differ from expected count (%d)", _count, val); \ } #define LOAD_ENTRY_ONLY(name, func) { \ @@ -423,10 +423,10 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b } if (!type || !entity || !val) - error("SaveLoad::readEntry: Invalid parameters passed!"); + error("[SaveLoad::readEntry] Invalid parameters passed"); if (!_savegame) - error("SaveLoad::readEntry: No savegame stream present!"); + error("[SaveLoad::readEntry] No savegame stream present"); // Load entry header SavegameEntryHeader entry; @@ -434,7 +434,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b entry.saveLoadWithSerializer(ser); if (!entry.isValid()) - error("SaveLoad::readEntry: entry header is invalid!"); + error("[SaveLoad::readEntry] Entry header is invalid"); // Init type, entity & value *type = entry.type; @@ -469,7 +469,7 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b SaveLoad::SavegameEntryHeader *SaveLoad::getEntry(uint32 index) { if (index >= _gameHeaders.size()) - error("SaveLoad::getEntry: invalid index (was:%d, max:%d)", index, _gameHeaders.size() - 1); + error("[SaveLoad::getEntry] Invalid index (was:%d, max:%d)", index, _gameHeaders.size() - 1); return _gameHeaders[index]; } @@ -489,7 +489,7 @@ bool SaveLoad::isSavegamePresent(GameId id) { // Check if the game has been started in the specific savegame bool SaveLoad::isSavegameValid(GameId id) { if (!isSavegamePresent(id)) { - debugC(2, kLastExpressDebugSavegame, "SaveLoad::isSavegameValid - Savegame does not exist: %s", getFilename(id).c_str()); + debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(id).c_str()); return false; } @@ -552,7 +552,7 @@ bool SaveLoad::isGameFinished(uint32 menuIndex, uint32 savegameIndex) { // Get the file name from the savegame ID Common::String SaveLoad::getFilename(GameId id) { if (id >= 6) - error("SaveLoad::getName - attempting to use an invalid game id. Valid values: 0 - 5, was %d", id); + error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - 5, was %d", id); return gameInfo[id].saveFile; } @@ -561,7 +561,7 @@ Common::InSaveFile *SaveLoad::openForLoading(GameId id) { Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(id)); if (!load) - debugC(2, kLastExpressDebugSavegame, "SaveLoad::openForLoading - Cannot open savegame for loading: %s", getFilename(id).c_str()); + debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(id).c_str()); return load; } @@ -570,7 +570,7 @@ Common::OutSaveFile *SaveLoad::openForSaving(GameId id) { Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(id)); if (!save) - debugC(2, kLastExpressDebugSavegame, "SaveLoad::openForSaving - Cannot open savegame for writing: %s", getFilename(id).c_str()); + debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(id).c_str()); return save; } diff --git a/engines/lastexpress/game/savepoint.cpp b/engines/lastexpress/game/savepoint.cpp index 7ec7c241e9..64ae26c2be 100644 --- a/engines/lastexpress/game/savepoint.cpp +++ b/engines/lastexpress/game/savepoint.cpp @@ -128,17 +128,17 @@ void SavePoints::addData(EntityIndex entity, ActionIndex action, uint32 param) { ////////////////////////////////////////////////////////////////////////// void SavePoints::setCallback(EntityIndex index, Entity::Callback *callback) { if (index >= 40) - error("SavePoints::setCallback - attempting to use an invalid entity index. Valid values 0-39, was %d", index); + error("[SavePoints::setCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index); if (!callback || !callback->isValid()) - error("SavePoints::setCallback - attempting to set an invalid callback for entity %s", ENTITY_NAME(index)); + error("[SavePoints::setCallback] Attempting to set an invalid callback for entity %s", ENTITY_NAME(index)); _callbacks[index] = callback; } Entity::Callback *SavePoints::getCallback(EntityIndex index) const { if (index >= 40) - error("SavePoints::getCallback - attempting to use an invalid entity index. Valid values 0-39, was %d", index); + error("[SavePoints::getCallback] Attempting to use an invalid entity index. Valid values 0-39, was %d", index); return _callbacks[index]; } diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp index 65efc80265..b886951e0b 100644 --- a/engines/lastexpress/game/scenes.cpp +++ b/engines/lastexpress/game/scenes.cpp @@ -81,12 +81,12 @@ void SceneManager::loadSceneDataFile(ArchiveIndex archive) { case kArchiveCd2: case kArchiveCd3: if (!_sceneLoader->load(getArchive(Common::String::format("CD%iTRAIN.DAT", archive)))) - error("SceneManager::loadSceneDataFile: cannot load data file CD%iTRAIN.DAT", archive); + error("[SceneManager::loadSceneDataFile] Cannot load data file CD%iTRAIN.DAT", archive); break; default: case kArchiveAll: - error("SceneManager::loadSceneDataFile: Invalid archive index (must be [1-3], was %d", archive); + error("[SceneManager::loadSceneDataFile] Invalid archive index (must be [1-3], was %d", archive); break; } } @@ -464,7 +464,7 @@ bool SceneManager::checkPosition(SceneIndex index, CheckPositionType type) const switch (type) { default: - error("SceneManager::checkPosition: Invalid position type: %d", type); + error("[SceneManager::checkPosition] Invalid position type: %d", type); case kCheckPositionLookingUp: return isInSleepingCar && (position >= 1 && position <= 19); diff --git a/engines/lastexpress/game/state.cpp b/engines/lastexpress/game/state.cpp index 0cf2ddba40..f3fd9720b1 100644 --- a/engines/lastexpress/game/state.cpp +++ b/engines/lastexpress/game/state.cpp @@ -57,7 +57,7 @@ bool State::isNightTime() const { void State::getHourMinutes(uint32 time, uint8 *hours, uint8 *minutes) { if (hours == NULL || minutes == NULL) - error("State::getHourMinutes: invalid parameters passed!"); + error("[State::getHourMinutes] Invalid parameters passed"); *hours = (uint8)((time % 1296000) / 54000); *minutes = (uint8)((time % 54000) / 900); diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h index 8f71e7d424..c937fdce9f 100644 --- a/engines/lastexpress/game/state.h +++ b/engines/lastexpress/game/state.h @@ -325,7 +325,7 @@ public: switch (index) { default: - error("GameProgress::isEqual: invalid index value (was: %d, max:127)", index); + error("[GameProgress::getValueName] Invalid index value (was: %d, max:127)", index); break; EXPOSE_VALUE(0, field_0); diff --git a/engines/lastexpress/graphics.cpp b/engines/lastexpress/graphics.cpp index abbdf2b766..e129457256 100644 --- a/engines/lastexpress/graphics.cpp +++ b/engines/lastexpress/graphics.cpp @@ -72,7 +72,7 @@ void GraphicsManager::clear(BackgroundType type) { void GraphicsManager::clear(BackgroundType type, const Common::Rect &rect) { switch (type) { default: - error("GraphicsManager::clear() - Unknown background type: %d", type); + error("[GraphicsManager::clear] Unknown background type: %d", type); break; case kBackgroundA: @@ -105,7 +105,7 @@ bool GraphicsManager::draw(Drawable *drawable, BackgroundType type, bool transit Graphics::Surface *GraphicsManager::getSurface(BackgroundType type) { switch (type) { default: - error("GraphicsManager::getSurface() - Unknown surface type: %d", type); + error("[GraphicsManager::getSurface] Unknown surface type: %d", type); break; case kBackgroundA: @@ -121,7 +121,7 @@ Graphics::Surface *GraphicsManager::getSurface(BackgroundType type) { return &_inventory; case kBackgroundAll: - error("GraphicsManager::getSurface() - cannot return a surface for kBackgroundAll!"); + error("[GraphicsManager::getSurface] Cannot return a surface for kBackgroundAll"); break; } } diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index 5d83527525..885ca8b212 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -185,7 +185,7 @@ void LastExpressEngine::pollEvents() { bool LastExpressEngine::handleEvents() { // Make sure all the subsystems have been initialized if (!_debugger || !_graphicsMan) - error("LastExpressEngine::handleEvents: called before the required subsystems have been initialized!"); + error("[LastExpressEngine::handleEvents] Called before the required subsystems have been initialized"); // Execute stored commands if (_debugger->hasCommand()) { diff --git a/engines/lastexpress/menu/clock.cpp b/engines/lastexpress/menu/clock.cpp index b0e6a260d4..dedf045940 100644 --- a/engines/lastexpress/menu/clock.cpp +++ b/engines/lastexpress/menu/clock.cpp @@ -62,7 +62,7 @@ void Clock::draw(uint32 time) { // Check that sequences have been loaded if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate) - error("Clock::process: clock sequences have not been loaded correctly!"); + error("[Clock::draw] Clock sequences have not been loaded correctly"); // Clear existing frames clear(); diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp index bfead02ad0..f1a8bebe94 100644 --- a/engines/lastexpress/menu/menu.cpp +++ b/engines/lastexpress/menu/menu.cpp @@ -860,7 +860,7 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) { useSameIndex = false; // TODO remove existing savegame and reset index & savegame name - warning("Menu::initGame: not implemented!"); + warning("[Menu::initGame] Not implemented"); } doSavegame = false; diff --git a/engines/lastexpress/menu/trainline.cpp b/engines/lastexpress/menu/trainline.cpp index df08abf37b..f819776163 100644 --- a/engines/lastexpress/menu/trainline.cpp +++ b/engines/lastexpress/menu/trainline.cpp @@ -97,7 +97,7 @@ void TrainLine::draw(uint32 time) { // Check that sequences have been loaded if (!_frameLine1 || !_frameLine2) - error("TrainLine::process: Line sequences have not been loaded correctly!"); + error("[TrainLine::draw] Line sequences have not been loaded correctly"); // Clear existing frames clear(); diff --git a/engines/lastexpress/resource.cpp b/engines/lastexpress/resource.cpp index f376a3a299..3910aaa010 100644 --- a/engines/lastexpress/resource.cpp +++ b/engines/lastexpress/resource.cpp @@ -52,7 +52,7 @@ bool ResourceManager::isArchivePresent(ArchiveIndex type) { switch (type) { default: case kArchiveAll: - error("ResourceManager::isArchivePresent: Only checks for single CDs are valid!"); + error("[ResourceManager::isArchivePresent] Only checks for single CDs are valid"); case kArchiveCd1: return Common::File::exists(archiveCD1Path); @@ -134,7 +134,7 @@ Common::SeekableReadStream *ResourceManager::getFileStream(const Common::String // Check if the file exits in the archive if (!hasFile(name)) { //#ifdef _DEBUG -// error("ResourceManager::getFileStream: cannot open file: %s", name.c_str()); +// error("[ResourceManager::getFileStream] Cannot open file: %s", name.c_str()); //#endif debugC(2, kLastExpressDebugResource, "Error opening file: %s", name.c_str()); return NULL; diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 5cdcc15d5a..f3f06b8128 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -211,7 +211,7 @@ void SoundEntry::loadSoundData(Common::String name) { _stream = getArchive("DEFAULT.SND"); if (_stream) { - warning("Sound::loadSoundData: not implemented!"); + warning("[Sound::loadSoundData] Not implemented"); } else { _status.status = kSoundStatusRemoved; } diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index 9126f5709d..7eb67b387c 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -115,7 +115,7 @@ void SoundQueue::removeFromQueue(Common::String filename) { void SoundQueue::updateQueue() { Common::StackLock locker(_mutex); - warning("Sound::updateQueue: not implemented!"); + warning("[Sound::updateQueue] Not implemented"); } void SoundQueue::resetQueue() { @@ -413,7 +413,7 @@ void SoundQueue::saveLoadWithSerializer(Common::Serializer &s) { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) (*i)->saveLoadWithSerializer(s); } else { - warning("Sound::saveLoadWithSerializer: loading not implemented"); + warning("[Sound::saveLoadWithSerializer] Loading not implemented"); s.skip(numEntries * 64); } } diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index 16e502ad5a..45f8140d27 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -300,7 +300,7 @@ void SoundManager::playSoundEvent(EntityIndex entity, byte action, byte a3) { void SoundManager::playSteam(CityIndex index) { if (index >= ARRAYSIZE(cities)) - error("SoundManager::playSteam: invalid city index (was %d, max %d)", index, ARRAYSIZE(cities)); + error("[SoundManager::playSteam] Invalid city index (was %d, max %d)", index, ARRAYSIZE(cities)); _queue->resetState(kSoundState2); @@ -676,7 +676,7 @@ void SoundManager::readText(int id){ return; if (id < 0 || (id > 8 && id < 50) || id > 64) - error("Sound::readText - attempting to use invalid id. Valid values [1;8] - [50;64], was %d", id); + error("[Sound::readText] Attempting to use invalid id. Valid values [1;8] - [50;64], was %d", id); // Get proper message file (names are stored in sequence in the array but id is [1;8] - [50;64]) const char *text = messages[id <= 8 ? id : id - 41]; -- cgit v1.2.3 From 04933a1937ef0de703a932e1392578aea4d38d64 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Tue, 28 Jun 2011 23:17:13 -0400 Subject: LASTEXPRESS: Make SoundEntry members private --- engines/lastexpress/sound/entry.cpp | 11 +++++++++-- engines/lastexpress/sound/entry.h | 27 ++++++++++++++++++++------ engines/lastexpress/sound/queue.cpp | 38 ++++++++++++++++++------------------- engines/lastexpress/sound/sound.cpp | 8 ++++---- 4 files changed, 52 insertions(+), 32 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index f3f06b8128..c34bb4f0cc 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -307,6 +307,13 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { } } +void SoundEntry::loadStream() { + if (!_soundStream) + _soundStream = new StreamedSound(); + + _soundStream->load(_stream); +} + ////////////////////////////////////////////////////////////////////////// // SubtitleEntry ////////////////////////////////////////////////////////////////////////// @@ -352,10 +359,10 @@ void SubtitleEntry::setupAndDraw() { _data->load(getArchive(_filename)); } - if (_data->getMaxTime() > _sound->_time) { + if (_data->getMaxTime() > _sound->getTime()) { _status.status = kSoundStatus_400; } else { - _data->setTime((uint16)_sound->_time); + _data->setTime((uint16)_sound->getTime()); if (getSoundQueue()->getSubtitleFlag() & 1) drawOnScreen(); diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 929d3463d5..60795332f8 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -86,6 +86,7 @@ enum SoundStatus { kSoundStatus_8000 = 0x8000, kSoundStatus_20000 = 0x20000, kSoundStatus_100000 = 0x100000, + kSoundStatus_20000000 = 0x20000000, kSoundStatus_40000000 = 0x40000000, kSoundStatusClear0 = 0x10, @@ -127,6 +128,8 @@ public: void updateState(); void reset(); + void loadStream(); + // Subtitles void showSubtitle(Common::String filename); @@ -134,22 +137,34 @@ public: void saveLoadWithSerializer(Common::Serializer &ser); // Accessors - void setType(SoundType type) { _type = type; } - SoundType getType() { return _type; } - + void setStatus(int status) { _status.status = status; } + void setType(SoundType type) { _type = type; } void setEntity(EntityIndex entity) { _entity = entity; } - EntityIndex getEntity() { return _entity; } + void setField48(int val) { _field_48 = val; } + + SoundStatusUnion getStatus() { return _status; } + SoundType getType() { return _type; } + uint32 getTime() { return _time; } + EntityIndex getEntity() { return _entity; } + uint32 getPriority() { return _priority; } + Common::String getName2() { return _name2; } + + // Streams + Common::SeekableReadStream *getStream() { return _stream; } + StreamedSound *getStreamedSound() { return _soundStream; } + +public: + // TODO replace by on-the-fly allocated buffer + void *_soundData; private: LastExpressEngine *_engine; -public: SoundStatusUnion _status; SoundType _type; // int //int _data; //int _endOffset; int _currentDataPtr; - void *_soundData; //int _currentBufferPtr; int _blockCount; uint32 _time; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index 7eb67b387c..cbd942f082 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -76,15 +76,13 @@ void SoundQueue::handleTimer() { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { SoundEntry *entry = (*i); - if (entry->_stream == NULL) { + if (entry->getStream() == NULL) { SAFE_DELETE(*i); i = _soundList.reverse_erase(i); continue; - } else if (!entry->_soundStream) { - entry->_soundStream = new StreamedSound(); - + } else if (!entry->getStreamedSound()) { // TODO: stream any sound in the queue after filtering - entry->_soundStream->load(entry->_stream); + entry->loadStream(); } } } @@ -180,7 +178,7 @@ void SoundQueue::clearStatus() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->_status.status |= kSoundStatusClear3; + (*i)->setStatus((*i)->getStatus().status | kSoundStatusClear3); } ////////////////////////////////////////////////////////////////////////// @@ -243,7 +241,7 @@ SoundEntry *SoundQueue::getEntry(Common::String name) { name += ".SND"; for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { - if ((*i)->_name2 == name) + if ((*i)->getName2() == name) return *i; } @@ -264,7 +262,7 @@ uint32 SoundQueue::getEntryTime(EntityIndex index) { SoundEntry *entry = getEntry(index); if (entry) - return entry->_time; + return entry->getTime(); return 0; } @@ -298,16 +296,16 @@ void SoundQueue::updateSubtitles() { for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { uint32 current_index = 0; SoundEntry *soundEntry = (*i)->getSoundEntry(); - SoundStatus status = (SoundStatus)soundEntry->_status.status; + SoundStatus status = (SoundStatus)soundEntry->getStatus().status; if (!(status & kSoundStatus_40) || status & kSoundStatus_180 - || soundEntry->_time == 0 + || soundEntry->getTime() == 0 || (status & kSoundStatusClear1) < 6 - || ((getFlags()->nis & 0x8000) && soundEntry->_priority < 90)) { + || ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) { current_index = 0; } else { - current_index = soundEntry->_priority + (status & kSoundStatusClear1); + current_index = soundEntry->getPriority() + (status & kSoundStatusClear1); if (_currentSubtitle == (*i)) current_index += 4; @@ -348,8 +346,8 @@ bool SoundQueue::setupCache(SoundEntry *entry) { uint32 size = 1000; for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if (!((*i)->_status.status & kSoundStatus_180)) { - uint32 newSize = (*i)->_priority + ((*i)->_status.status & kSoundStatusClear1); + if (!((*i)->getStatus().status & kSoundStatus_180)) { + uint32 newSize = (*i)->getPriority() + ((*i)->getStatus().status & kSoundStatusClear1); if (newSize < size) { cacheEntry = (*i); @@ -358,7 +356,7 @@ bool SoundQueue::setupCache(SoundEntry *entry) { } } - if (entry->_priority <= size) + if (entry->getPriority() <= size) return false; if (!cacheEntry) @@ -367,7 +365,7 @@ bool SoundQueue::setupCache(SoundEntry *entry) { cacheEntry->setInCache(); // TODO: Wait until the cache entry is ready to be removed - while (!(cacheEntry->_status.status1 & 1)) + while (!(cacheEntry->getStatus().status1 & 1)) ; if (cacheEntry->_soundData) @@ -427,7 +425,7 @@ uint32 SoundQueue::count() { uint32 numEntries = 0; for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - if ((*i)->_name2.matchString("NISSND?")) + if ((*i)->getName2().matchString("NISSND?")) ++numEntries; return numEntries; @@ -749,9 +747,9 @@ static void soundFilter(byte *data, int16 *buffer, int p1, int p2); void SoundQueue::applyFilter(SoundEntry *entry, int16 *buffer) { if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) { - entry->_status.status |= 0x20000000; + entry->setStatus(entry->getStatus().status | kSoundStatus_20000000); } else { - int variant = entry->_status.status & 0x1f; + int variant = entry->getStatus().status & 0x1f; soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]); } @@ -789,7 +787,7 @@ void SoundQueue::stopAllSound() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->_soundStream->stop(); + (*i)->getStreamedSound()->stop(); } } // End of namespace LastExpress diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index 45f8140d27..c726769495 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -155,11 +155,11 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla SoundEntry *entry = new SoundEntry(_engine); entry->open(filename, flag, 30); - entry->_entity = entity; + entry->setEntity(entity); if (a4) { - entry->_field_48 = _data2 + 2 * a4; - entry->_status.status |= kSoundStatus_8000; + entry->setField48(_data2 + 2 * a4); + entry->setStatus(entry->getStatus().status | kSoundStatus_8000); } else { // Get subtitles name while (filename.size() > 4) @@ -1359,7 +1359,7 @@ void SoundManager::playLoopingSound(int param) { if (getFlags()->flag_3) fnameLen = 5; - if (!entry || scumm_strnicmp(entry->_name2.c_str(), tmp, fnameLen)) { + if (!entry || scumm_strnicmp(entry->getName2().c_str(), tmp, fnameLen)) { _loopingSoundDuration = _engine->getRandom().getRandomNumber(319) + 260; if (partNumber != 99) { -- cgit v1.2.3 From 9cc5d404c7c5d096f05d37680eb85929802290df Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 06:19:19 -0400 Subject: LASTEXPRESS: Replace shared sound buffer by per-entry buffer --- engines/lastexpress/sound/entry.cpp | 21 ++++++++-- engines/lastexpress/sound/entry.h | 10 ++--- engines/lastexpress/sound/queue.cpp | 76 +------------------------------------ engines/lastexpress/sound/queue.h | 8 ---- 4 files changed, 24 insertions(+), 91 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index c34bb4f0cc..e22efffd6b 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -38,6 +38,8 @@ namespace LastExpress { +#define SOUNDCACHE_ENTRY_SIZE 92160 + ////////////////////////////////////////////////////////////////////////// // SoundEntry ////////////////////////////////////////////////////////////////////////// @@ -45,7 +47,7 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _type = kSoundTypeNone; _currentDataPtr = 0; - _soundData = NULL; + _soundBuffer = NULL; _blockCount = 0; _time = 0; @@ -66,12 +68,13 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { } SoundEntry::~SoundEntry() { - // Entries that have been queued would have their streamed disposed automatically + // Entries that have been queued will have their streamed disposed automatically if (!_soundStream) SAFE_DELETE(_stream); - delete _soundStream; + free(_soundBuffer); + // Zero passed pointers _engine = NULL; } @@ -85,7 +88,7 @@ void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { getSoundQueue()->addToQueue(this); // Add entry to cache and load sound data - getSoundQueue()->setupCache(this); + setupCache(); loadSoundData(name); } @@ -197,6 +200,16 @@ void SoundEntry::setStatus(SoundFlag flag) { _status.status = (statusFlag | kSoundStatusClear4); } +void SoundEntry::setupCache() { + if (_soundBuffer) + return; + + // Original has a priority-based shared buffer (of 6 entries) + // We simply allocate a new buffer for each sound entry that needs it + _soundBuffer = (byte *)malloc(SOUNDCACHE_ENTRY_SIZE); + memset(_soundBuffer, 0, SOUNDCACHE_ENTRY_SIZE); +} + void SoundEntry::setInCache() { _status.status |= kSoundStatusClear2; } diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 60795332f8..6b0f780152 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -152,10 +152,7 @@ public: // Streams Common::SeekableReadStream *getStream() { return _stream; } StreamedSound *getStreamedSound() { return _soundStream; } - -public: - // TODO replace by on-the-fly allocated buffer - void *_soundData; + byte *getSoundBuffer() { return _soundBuffer; } private: LastExpressEngine *_engine; @@ -184,8 +181,11 @@ private: // original has pointer to the next structure in the list (not used) SubtitleEntry *_subtitle; - // Sound stream + // Sound buffer & stream + byte *_soundBuffer; StreamedSound *_soundStream; + + void setupCache(); }; ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index cbd942f082..92c853343e 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -32,18 +32,11 @@ namespace LastExpress { -#define SOUNDCACHE_ENTRY_SIZE 92160 -#define SOUNDCACHE_MAX_SIZE 6 - SoundQueue::SoundQueue(LastExpressEngine *engine) : _engine(engine) { _state = 0; _currentType = kSoundType16; _flag = 0; - // Cache and filter buffers - memset(&_buffer, 0, sizeof(_buffer)); - _soundCacheData = malloc(6 * SOUNDCACHE_ENTRY_SIZE); - _subtitlesFlag = 0; _currentSubtitle = NULL; } @@ -53,17 +46,12 @@ SoundQueue::~SoundQueue() { SAFE_DELETE(*i); _soundList.clear(); - // Entries in the cache are just pointers to sound list entries - _soundCache.clear(); - for (Common::List::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) SAFE_DELETE(*i); _subtitles.clear(); _currentSubtitle = NULL; - free(_soundCacheData); - // Zero passed pointers _engine = NULL; } @@ -333,66 +321,6 @@ void SoundQueue::updateSubtitles() { } } -////////////////////////////////////////////////////////////////////////// -// Cache -////////////////////////////////////////////////////////////////////////// -bool SoundQueue::setupCache(SoundEntry *entry) { - if (entry->_soundData) - return true; - - if (_soundCache.size() >= SOUNDCACHE_MAX_SIZE) { - - SoundEntry *cacheEntry = NULL; - uint32 size = 1000; - - for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if (!((*i)->getStatus().status & kSoundStatus_180)) { - uint32 newSize = (*i)->getPriority() + ((*i)->getStatus().status & kSoundStatusClear1); - - if (newSize < size) { - cacheEntry = (*i); - size = newSize; - } - } - } - - if (entry->getPriority() <= size) - return false; - - if (!cacheEntry) - error("[SoundManager::setupCache] Cannot find a valid entry"); - - cacheEntry->setInCache(); - - // TODO: Wait until the cache entry is ready to be removed - while (!(cacheEntry->getStatus().status1 & 1)) - ; - - if (cacheEntry->_soundData) - removeFromCache(cacheEntry); - - _soundCache.push_back(entry); - entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); - } else { - _soundCache.push_back(entry); - entry->_soundData = (char *)_soundCacheData + SOUNDCACHE_ENTRY_SIZE * (_soundCache.size() - 1); - } - - return true; -} - -void SoundQueue::removeFromCache(SoundEntry *entry) { - for (Common::List::iterator i = _soundCache.begin(); i != _soundCache.end(); ++i) { - if ((*i) == entry) { - // Remove sound buffer - entry->_soundData = NULL; - - // Remove entry from sound cache - i = _soundCache.reverse_erase(i); - } - } -} - ////////////////////////////////////////////////////////////////////////// // Savegame ////////////////////////////////////////////////////////////////////////// @@ -746,12 +674,12 @@ static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, static void soundFilter(byte *data, int16 *buffer, int p1, int p2); void SoundQueue::applyFilter(SoundEntry *entry, int16 *buffer) { - if ((((byte *)entry->_soundData)[1] << 6) > 0x1600) { + if ((((byte *)entry->getSoundBuffer())[1] << 6) > 0x1600) { entry->setStatus(entry->getStatus().status | kSoundStatus_20000000); } else { int variant = entry->getStatus().status & 0x1f; - soundFilter((byte *)entry->_soundData, buffer, p1s[variant], p2s[variant]); + soundFilter((byte *)entry->getSoundBuffer(), buffer, p1s[variant], p2s[variant]); } } diff --git a/engines/lastexpress/sound/queue.h b/engines/lastexpress/sound/queue.h index 3748a266e0..0ab8598c4e 100644 --- a/engines/lastexpress/sound/queue.h +++ b/engines/lastexpress/sound/queue.h @@ -78,9 +78,6 @@ public: void setCurrentSubtitle(SubtitleEntry *entry) { _currentSubtitle = entry; } SubtitleEntry *getCurrentSubtitle() { return _currentSubtitle; } - // Cache - bool setupCache(SoundEntry *entry); - // Serializable void saveLoadWithSerializer(Common::Serializer &ser); uint32 count(); @@ -109,7 +106,6 @@ private: // Entries Common::List _soundList; ///< List of all sound entries - Common::List _soundCache; ///< List of entries with a data buffer void *_soundCacheData; // Subtitles @@ -117,10 +113,6 @@ private: Common::List _subtitles; SubtitleEntry *_currentSubtitle; - // Filters - int32 _buffer[2940]; ///< Static sound buffer - - void removeFromCache(SoundEntry *entry); void applyFilter(SoundEntry *entry, int16 *buffer); friend class Debugger; -- cgit v1.2.3 From 4526bbb5b63c40a365abf5f150bfbd29cbff32c9 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 06:28:55 -0400 Subject: LASTEXPRESS: Move SoundStatus to shared header --- engines/lastexpress/shared.h | 21 +++++++++++++++++++++ engines/lastexpress/sound/entry.h | 21 --------------------- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index 69816a3d6c..6969e437ea 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -89,6 +89,27 @@ enum SoundState { kSoundState2 = 2 }; +enum SoundStatus { + kSoundStatus_20 = 0x20, + kSoundStatus_40 = 0x40, + kSoundStatus_180 = 0x180, + kSoundStatusRemoved = 0x200, + kSoundStatus_400 = 0x400, + + kSoundStatus_8000 = 0x8000, + kSoundStatus_20000 = 0x20000, + kSoundStatus_100000 = 0x100000, + kSoundStatus_20000000 = 0x20000000, + kSoundStatus_40000000 = 0x40000000, + + kSoundStatusClear0 = 0x10, + kSoundStatusClear1 = 0x1F, + kSoundStatusClear2 = 0x80, + kSoundStatusClear3 = 0x200, + kSoundStatusClear4 = 0x800, + kSoundStatusClearAll = 0xFFFFFFE0 +}; + ////////////////////////////////////////////////////////////////////////// // Time values ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 6b0f780152..1ea3f5b821 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -76,27 +76,6 @@ namespace LastExpress { class LastExpressEngine; class SubtitleEntry; -enum SoundStatus { - kSoundStatus_20 = 0x20, - kSoundStatus_40 = 0x40, - kSoundStatus_180 = 0x180, - kSoundStatusRemoved = 0x200, - kSoundStatus_400 = 0x400, - - kSoundStatus_8000 = 0x8000, - kSoundStatus_20000 = 0x20000, - kSoundStatus_100000 = 0x100000, - kSoundStatus_20000000 = 0x20000000, - kSoundStatus_40000000 = 0x40000000, - - kSoundStatusClear0 = 0x10, - kSoundStatusClear1 = 0x1F, - kSoundStatusClear2 = 0x80, - kSoundStatusClear3 = 0x200, - kSoundStatusClear4 = 0x800, - kSoundStatusClearAll = 0xFFFFFFE0 -}; - union SoundStatusUnion { uint32 status; byte status1; -- cgit v1.2.3 From 2788cb8bf72f0897a8bed32fbb5730f892b10edf Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 10:26:04 -0400 Subject: LASTEXPRESS: Update sound timer and sound entry playing - Move filtering to SoundEntry class - Make some methods of SoundEntry class private - Add methods to check if a StreamedSound/AppendableSound is done playing --- engines/lastexpress/data/snd.cpp | 16 +- engines/lastexpress/data/snd.h | 8 + engines/lastexpress/sound/entry.cpp | 407 +++++++++++++++++++++++++++++++++++- engines/lastexpress/sound/entry.h | 25 +-- engines/lastexpress/sound/queue.cpp | 364 +------------------------------- engines/lastexpress/sound/queue.h | 2 - engines/lastexpress/sound/sound.cpp | 3 + 7 files changed, 445 insertions(+), 380 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index d92ebbc5e3..fa2d8a2e51 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -103,7 +103,8 @@ void SimpleSound::play(Audio::AudioStream *as) { ////////////////////////////////////////////////////////////////////////// // StreamedSound ////////////////////////////////////////////////////////////////////////// -StreamedSound::StreamedSound() {} +StreamedSound::StreamedSound() : _loaded(false) {} + StreamedSound::~StreamedSound() {} bool StreamedSound::load(Common::SeekableReadStream *stream) { @@ -120,9 +121,18 @@ bool StreamedSound::load(Common::SeekableReadStream *stream) { // Start playing the decoded audio stream play(as); + _loaded = true; + return true; } +bool StreamedSound::isFinished() { + if (!_loaded) + return false; + + return !g_system->getMixer()->isSoundHandleActive(_handle); +} + ////////////////////////////////////////////////////////////////////////// // StreamedSound ////////////////////////////////////////////////////////////////////////// @@ -172,4 +182,8 @@ void AppendableSound::finish() { _finished = true; } +bool AppendableSound::isFinished() { + return _as->endOfStream(); +} + } // End of namespace LastExpress diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h index 95a136ee1c..1c34e4f950 100644 --- a/engines/lastexpress/data/snd.h +++ b/engines/lastexpress/data/snd.h @@ -55,6 +55,7 @@ public: virtual ~SimpleSound(); void stop() const; + virtual bool isFinished() = 0; protected: void loadHeader(Common::SeekableReadStream *in); @@ -76,6 +77,11 @@ public: ~StreamedSound(); bool load(Common::SeekableReadStream *stream); + + virtual bool isFinished(); + +private: + bool _loaded; }; class AppendableSound : public SimpleSound { @@ -87,6 +93,8 @@ public: void queueBuffer(Common::SeekableReadStream *bufferIn); void finish(); + virtual bool isFinished(); + private: Audio::QueuingAudioStream *_as; bool _finished; diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index e22efffd6b..5cbc593d29 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -39,6 +39,7 @@ namespace LastExpress { #define SOUNDCACHE_ENTRY_SIZE 92160 +#define FILTER_BUFFER_SIZE 2940 ////////////////////////////////////////////////////////////////////////// // SoundEntry @@ -65,6 +66,8 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _subtitle = NULL; _soundStream = NULL; + + _queued = false; } SoundEntry::~SoundEntry() { @@ -82,10 +85,7 @@ SoundEntry::~SoundEntry() { void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { _priority = priority; setType(flag); - setStatus(flag); - - // Add entry to sound list - getSoundQueue()->addToQueue(this); + setupStatus(flag); // Add entry to cache and load sound data setupCache(); @@ -117,6 +117,48 @@ void SoundEntry::close() { } } +void SoundEntry::play() { + if (!_soundStream) + _soundStream = new StreamedSound(); + + if (_queued) + return; + + if (!_stream) { + warning("[SoundEntry::play] stream has been disposed"); + return; + } + + // Stream the contents of the sound buffer + /*int16 *buffer = (int16 *)malloc(FILTER_BUFFER_SIZE); + memset(buffer, 0, FILTER_BUFFER_SIZE); + + applyFilter(buffer); + + _soundStream->queueBuffer((const byte *)buffer, FILTER_BUFFER_SIZE, true); + + + // Skip header + _stream->seek(12, SEEK_SET); + */ + + _stream->seek(0); + _soundStream->load(_stream); + + _queued = true; +} + +bool SoundEntry::isFinished() { + if (!_stream) + return true; + + if (!_soundStream || !_queued) + return false; + + // TODO check that all data has been queued + return _soundStream->isFinished(); +} + void SoundEntry::setType(SoundFlag flag) { switch (flag & kFlagType9) { default: @@ -189,7 +231,7 @@ void SoundEntry::setType(SoundFlag flag) { } } -void SoundEntry::setStatus(SoundFlag flag) { +void SoundEntry::setupStatus(SoundFlag flag) { SoundStatus statusFlag = (SoundStatus)flag; if (!((statusFlag & 0xFF) & kSoundStatusClear1)) statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); @@ -208,6 +250,8 @@ void SoundEntry::setupCache() { // We simply allocate a new buffer for each sound entry that needs it _soundBuffer = (byte *)malloc(SOUNDCACHE_ENTRY_SIZE); memset(_soundBuffer, 0, SOUNDCACHE_ENTRY_SIZE); + + setInCache(); } void SoundEntry::setInCache() { @@ -224,7 +268,7 @@ void SoundEntry::loadSoundData(Common::String name) { _stream = getArchive("DEFAULT.SND"); if (_stream) { - warning("[Sound::loadSoundData] Not implemented"); + _stream->read(_soundBuffer, MIN(SOUNDCACHE_ENTRY_SIZE, _stream->size())); } else { _status.status = kSoundStatusRemoved; } @@ -273,6 +317,7 @@ void SoundEntry::reset() { if (!_soundStream) { SAFE_DELETE(_stream); } else { + // the original stream will be disposed _soundStream->stop(); SAFE_DELETE(_soundStream); } @@ -320,11 +365,353 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { } } -void SoundEntry::loadStream() { - if (!_soundStream) - _soundStream = new StreamedSound(); +////////////////////////////////////////////////////////////////////////// +// Sound filters +////////////////////////////////////////////////////////////////////////// +static const int filterData[1424] = { + 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, + 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, + 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, + 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, + 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, + 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, + 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, + 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, + 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, + 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, + 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, + 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, + 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, + 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, + 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, + 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, + 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, + 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, + 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, + 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, + 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, + 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, + 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, + 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, + 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, + 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, + 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, + 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, + 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, + 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, + 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, + 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, + 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, + 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, + 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, + 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, + 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, + 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, + 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, + 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, + 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, + 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, + 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, + 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, + 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, + 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, + 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, + 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, + 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, + 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, + 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, + 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, + 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, + 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, + 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, + 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, + 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, + 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, + 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, + 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, + 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, + 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, + 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, + 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, + 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, + 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, + 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, + 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, + 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, + 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, + 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, + 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, + 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, + 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, + 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, + 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, + 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, + 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, + 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, + 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, + 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, + 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, + 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, + 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, + 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, + 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, + 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, + 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, + 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, + 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, + 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, + 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, + 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, + 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, + 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, + 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, + 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, + 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, + 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, + 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, + 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, + 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, + 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, + 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, + 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, + 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, + 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, + 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, + 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, + 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, + 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, + 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, + 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, + 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, + 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, + 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, + 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, + 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, + 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, + 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, + 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, + 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, + 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, + 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, + 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, + 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, + 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, + 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, + 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, + 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, + 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, + 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, + 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, + 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, + 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, + 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, + 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, + 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, + 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, + 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, + 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, + 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, + 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, + 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, + 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, + 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, + 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, + 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, + 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, + 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, + 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, + 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, + 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, + 5632 +}; + +static const int filterData2[1424] = { + 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, + -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, + -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, + -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, + -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, + 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, + 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, + -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, + -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, + -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, + 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, + 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, + -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, + -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, + -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, + 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, + 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, + -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, + -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, + 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, + 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, + -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, + -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, + -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, + 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, + 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, + -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, + -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, + 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, + 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, + -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, + -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, + 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, + -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, + -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, + 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, + -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, + 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, + 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, + -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, + 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, + 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, + -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, + 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, + 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, + -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, + 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, + -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, + -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, + 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, + -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, + -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, + 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, + -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, + 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, + -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, + 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, + -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, + -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, + 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, + -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, + -68, -204, -340, -476, -612, -748, -884, -1020, 74, + 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, + -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, + 904, 1069, 1233, -82, -246, -411, -575, -740, -904, + -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, + -90, -271, -452, -633, -814, -995, -1176, -1357, 99, + 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, + -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, + 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, + -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, + 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, + -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, + -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, + 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, + -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, + 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, + -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, + 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, + -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, + -194, -582, -970, -1358, -1746, -2134, -2522, -2910, + 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, + -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, + 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, + -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, + 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, + -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, + 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, + -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, + 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, + -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, + 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, + -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, + -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, + 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, + -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, + 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, + -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, + 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, + -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, + 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, + -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, + 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, + -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, + 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, + -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, + 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, + -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, + -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, + 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, + -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, + 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, + -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, + 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, + -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, + 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, + -5933, -8306, -10679, -13052, -15426, -17799, 1305, + 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, + -3915, -6526, -9136, -11747, -14357, -16968, -19578, + 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, + -1435, -4307, -7179, -10051, -12922, -15794, -18666, + -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, + 23690, -1579, -4738, -7896, -11055, -14214, -17373, + -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, + 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, + -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, + 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, + -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, + 27329, 31533, -2102, -6306, -10511, -14715, -18920, + -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, + 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, + -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, + 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, + -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, + 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, + -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, + 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, + -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, + 32767, 32767, 32767, -3385, -10157, -16928, -23700, + -30471, -32767, -32767, -32767, 3724, 11172, 18621, + 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, + -26069, -32767, -32767, -32767, -32767, 4095, 12287, + 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, + -20479, -28671, -32767, -32767, -32767, -32767 +}; + +static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; +static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2); + +void SoundEntry::applyFilter(int16 *buffer) { + if ((_soundBuffer[1] << 6) > 5632) { + _status.status |= kSoundStatus_20000000; + } else { + int variant = _status.status & 0x1f; - _soundStream->load(_stream); + soundFilter(_soundBuffer, buffer, p1s[variant], p2s[variant]); + } +} + + +static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { + int data1, data2, data1p, data2p; + byte idx; + + data2 = data[0]; + data1 = data[1] << 6; + + data += 2; + + for (int count = 0; count < 735; count++) { + idx = data[count] >> 4; + data1p = filterData[idx + data1]; + data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); + + buffer[2 * count] = (p2 * data2p) >> p1; + + idx = data[count] & 0xF; + + data1 = filterData[idx + data1p]; + data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); + buffer[2 * count + 1] = (p2 * data2) >> p1; + } } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 1ea3f5b821..8da780f294 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -98,16 +98,11 @@ public: void open(Common::String name, SoundFlag flag, int priority); void close(); - - void setStatus(SoundFlag flag); - void setType(SoundFlag flag); - void setInCache(); - void loadSoundData(Common::String name); + void play(); + void reset(); + bool isFinished(); void update(uint val); void updateState(); - void reset(); - - void loadStream(); // Subtitles void showSubtitle(Common::String filename); @@ -129,8 +124,7 @@ public: Common::String getName2() { return _name2; } // Streams - Common::SeekableReadStream *getStream() { return _stream; } - StreamedSound *getStreamedSound() { return _soundStream; } + SimpleSound *getSoundStream() { return _soundStream; } byte *getSoundBuffer() { return _soundBuffer; } private: @@ -146,7 +140,7 @@ private: uint32 _time; //int _size; //int _field_28; - Common::SeekableReadStream *_stream; // int + Common::SeekableReadStream *_stream; // The file stream //int _field_30; int _field_34; int _field_38; @@ -161,10 +155,17 @@ private: SubtitleEntry *_subtitle; // Sound buffer & stream + bool _queued; byte *_soundBuffer; - StreamedSound *_soundStream; + StreamedSound *_soundStream; // the filtered sound stream + void setType(SoundFlag flag); + void setupStatus(SoundFlag flag); void setupCache(); + void setInCache(); + void loadSoundData(Common::String name); + + void applyFilter(int16 *buffer); }; ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index 92c853343e..d5475a27de 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -64,14 +64,17 @@ void SoundQueue::handleTimer() { for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { SoundEntry *entry = (*i); - if (entry->getStream() == NULL) { - SAFE_DELETE(*i); + + // When the entry has stopped playing, we remove his buffer + if (entry->isFinished()) { + entry->close(); + SAFE_DELETE(entry); i = _soundList.reverse_erase(i); continue; - } else if (!entry->getStreamedSound()) { - // TODO: stream any sound in the queue after filtering - entry->loadStream(); } + + // Queue the entry data, applying filtering + entry->play(); } } @@ -359,355 +362,6 @@ uint32 SoundQueue::count() { return numEntries; } -////////////////////////////////////////////////////////////////////////// -// Sound filters -////////////////////////////////////////////////////////////////////////// -static const int filterData[1424] = { - 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, - 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, - 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, - 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, - 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, - 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, - 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, - 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, - 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, - 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, - 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, - 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, - 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, - 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, - 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, - 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, - 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, - 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, - 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, - 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, - 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, - 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, - 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, - 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, - 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, - 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, - 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, - 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, - 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, - 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, - 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, - 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, - 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, - 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, - 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, - 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, - 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, - 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, - 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, - 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, - 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, - 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, - 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, - 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, - 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, - 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, - 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, - 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, - 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, - 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, - 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, - 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, - 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, - 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, - 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, - 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, - 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, - 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, - 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, - 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, - 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, - 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, - 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, - 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, - 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, - 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, - 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, - 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, - 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, - 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, - 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, - 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, - 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, - 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, - 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, - 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, - 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, - 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, - 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, - 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, - 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, - 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, - 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, - 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, - 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, - 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, - 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, - 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, - 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, - 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, - 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, - 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, - 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, - 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, - 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, - 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, - 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, - 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, - 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, - 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, - 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, - 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, - 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, - 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, - 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, - 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, - 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, - 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, - 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, - 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, - 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, - 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, - 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, - 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, - 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, - 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, - 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, - 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, - 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, - 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, - 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, - 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, - 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, - 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, - 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, - 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, - 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, - 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, - 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, - 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, - 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, - 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, - 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, - 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, - 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, - 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, - 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, - 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, - 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, - 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, - 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, - 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, - 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, - 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, - 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, - 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, - 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, - 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, - 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, - 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, - 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, - 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, - 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, - 5632 -}; - -static const int filterData2[1424] = { - 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, - -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, - -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, - -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, - -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, - 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, - 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, - -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, - -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, - -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, - 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, - 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, - -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, - -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, - -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, - 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, - 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, - -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, - -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, - 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, - 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, - -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, - -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, - -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, - 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, - 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, - -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, - -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, - 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, - 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, - -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, - -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, - 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, - -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, - -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, - 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, - 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, - -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, - 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, - 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, - -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, - 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, - 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, - -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, - 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, - 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, - -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, - 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, - -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, - -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, - 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, - -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, - -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, - 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, - -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, - 631, -42, -126, -210, -294, -379, -463, -547, -631, - 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, - -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, - 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, - -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, - -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, - 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, - -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, - -68, -204, -340, -476, -612, -748, -884, -1020, 74, - 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, - -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, - 904, 1069, 1233, -82, -246, -411, -575, -740, -904, - -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, - -90, -271, -452, -633, -814, -995, -1176, -1357, 99, - 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, - -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, - 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, - -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, - 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, - -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, - -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, - 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, - -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, - 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, - -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, - 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, - -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, - -194, -582, -970, -1358, -1746, -2134, -2522, -2910, - 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, - -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, - 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, - -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, - 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, - -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, - 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, - -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, - 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, - -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, - 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, - -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, - -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, - 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, - -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, - 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, - -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, - 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, - -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, - 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, - -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, - 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, - -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, - 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, - -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, - 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, - -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, - -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, - 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, - -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, - 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, - -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, - 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, - -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, - 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, - -5933, -8306, -10679, -13052, -15426, -17799, 1305, - 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, - -3915, -6526, -9136, -11747, -14357, -16968, -19578, - 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, - -1435, -4307, -7179, -10051, -12922, -15794, -18666, - -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, - 23690, -1579, -4738, -7896, -11055, -14214, -17373, - -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, - 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, - -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, - 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, - -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, - 27329, 31533, -2102, -6306, -10511, -14715, -18920, - -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, - 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, - -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, - 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, - -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, - 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, - -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, - 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, - -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, - 32767, 32767, 32767, -3385, -10157, -16928, -23700, - -30471, -32767, -32767, -32767, 3724, 11172, 18621, - 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, - -26069, -32767, -32767, -32767, -32767, 4095, 12287, - 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, - -20479, -28671, -32767, -32767, -32767, -32767 -}; - -static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; -static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2); - -void SoundQueue::applyFilter(SoundEntry *entry, int16 *buffer) { - if ((((byte *)entry->getSoundBuffer())[1] << 6) > 0x1600) { - entry->setStatus(entry->getStatus().status | kSoundStatus_20000000); - } else { - int variant = entry->getStatus().status & 0x1f; - - soundFilter((byte *)entry->getSoundBuffer(), buffer, p1s[variant], p2s[variant]); - } -} - - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { - int data1, data2, data1p, data2p; - byte idx; - - data2 = data[0]; - data1 = data[1] << 6; - - data += 2; - - for (int count = 0; count < 735; count++) { - idx = data[count] >> 4; - data1p = filterData[idx + data1]; - data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); - - buffer[2 * count] = (p2 * data2p) >> p1; - - idx = data[count] & 0xF; - - data1 = filterData[idx + data1p]; - data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); - buffer[2 * count + 1] = (p2 * data2) >> p1; - } -} - ////////////////////////////////////////////////////////////////////////// // Debug ////////////////////////////////////////////////////////////////////////// @@ -715,7 +369,7 @@ void SoundQueue::stopAllSound() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->getStreamedSound()->stop(); + (*i)->getSoundStream()->stop(); } } // End of namespace LastExpress diff --git a/engines/lastexpress/sound/queue.h b/engines/lastexpress/sound/queue.h index 0ab8598c4e..75fe06883a 100644 --- a/engines/lastexpress/sound/queue.h +++ b/engines/lastexpress/sound/queue.h @@ -113,8 +113,6 @@ private: Common::List _subtitles; SubtitleEntry *_currentSubtitle; - void applyFilter(SoundEntry *entry, int16 *buffer); - friend class Debugger; }; diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index c726769495..ff9e7e5aac 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -169,6 +169,9 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla entry->updateState(); } + // Add entry to sound list + _queue->addToQueue(entry); + return (entry->getType() != kSoundTypeNone); } -- cgit v1.2.3 From 3385fd37b974088e1cd7117e67c87e935742d729 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 12:06:33 -0400 Subject: LASTEXPRESS: Hook up preliminary sound filtering - Add debug checks in soundFilter() - Rename kSoundStatusClear1 to kSoundStatusFilterVariant --- engines/lastexpress/shared.h | 36 ++++++++++----------- engines/lastexpress/sound/entry.cpp | 63 +++++++++++++++++++++++-------------- engines/lastexpress/sound/entry.h | 4 +-- engines/lastexpress/sound/queue.cpp | 8 ++--- 4 files changed, 64 insertions(+), 47 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index 6969e437ea..b4ced96ee1 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -90,24 +90,24 @@ enum SoundState { }; enum SoundStatus { - kSoundStatus_20 = 0x20, - kSoundStatus_40 = 0x40, - kSoundStatus_180 = 0x180, - kSoundStatusRemoved = 0x200, - kSoundStatus_400 = 0x400, - - kSoundStatus_8000 = 0x8000, - kSoundStatus_20000 = 0x20000, - kSoundStatus_100000 = 0x100000, - kSoundStatus_20000000 = 0x20000000, - kSoundStatus_40000000 = 0x40000000, - - kSoundStatusClear0 = 0x10, - kSoundStatusClear1 = 0x1F, - kSoundStatusClear2 = 0x80, - kSoundStatusClear3 = 0x200, - kSoundStatusClear4 = 0x800, - kSoundStatusClearAll = 0xFFFFFFE0 + kSoundStatus_20 = 0x20, + kSoundStatus_40 = 0x40, + kSoundStatus_180 = 0x180, + kSoundStatusRemoved = 0x200, + kSoundStatus_400 = 0x400, + + kSoundStatus_8000 = 0x8000, + kSoundStatus_20000 = 0x20000, + kSoundStatus_100000 = 0x100000, + kSoundStatus_20000000 = 0x20000000, + kSoundStatus_40000000 = 0x40000000, + + kSoundStatusClear0 = 0x10, + kSoundStatusFilterVariant = 0x1F, + kSoundStatusClear2 = 0x80, + kSoundStatusClear3 = 0x200, + kSoundStatusClear4 = 0x800, + kSoundStatusClearAll = 0xFFFFFFE0 }; ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 5cbc593d29..4bdb9f7f96 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -47,7 +47,7 @@ namespace LastExpress { SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _type = kSoundTypeNone; - _currentDataPtr = 0; + _currentDataPtr = NULL; _soundBuffer = NULL; _blockCount = 0; @@ -58,7 +58,7 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _field_34 = 0; _field_38 = 0; _field_3C = 0; - _field_40 = 0; + _variant = 0; _entity = kEntityPlayer; _field_48 = 0; _priority = 0; @@ -118,32 +118,37 @@ void SoundEntry::close() { } void SoundEntry::play() { - if (!_soundStream) - _soundStream = new StreamedSound(); - - if (_queued) - return; - if (!_stream) { warning("[SoundEntry::play] stream has been disposed"); return; } - // Stream the contents of the sound buffer - /*int16 *buffer = (int16 *)malloc(FILTER_BUFFER_SIZE); + if (_queued) + return; + + // Apply filter + int16 *buffer = (int16 *)malloc(FILTER_BUFFER_SIZE); memset(buffer, 0, FILTER_BUFFER_SIZE); applyFilter(buffer); - _soundStream->queueBuffer((const byte *)buffer, FILTER_BUFFER_SIZE, true); + // Queue the filtered data +#if 0 + if (!_soundStream) + _soundStream = new AppendableSound(); + // FIXME: make sure the filtered sound buffer is disposed + _soundStream->queueBuffer((const byte *)buffer, FILTER_BUFFER_SIZE /* true */); +#else + free(buffer); - // Skip header - _stream->seek(12, SEEK_SET); - */ + // DEBUG: unfiltered stream + if (!_soundStream) + _soundStream = new StreamedSound(); _stream->seek(0); _soundStream->load(_stream); +#endif _queued = true; } @@ -233,7 +238,7 @@ void SoundEntry::setType(SoundFlag flag) { void SoundEntry::setupStatus(SoundFlag flag) { SoundStatus statusFlag = (SoundStatus)flag; - if (!((statusFlag & 0xFF) & kSoundStatusClear1)) + if (!((statusFlag & 0xFF) & kSoundStatusFilterVariant)) statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0) @@ -269,6 +274,7 @@ void SoundEntry::loadSoundData(Common::String name) { if (_stream) { _stream->read(_soundBuffer, MIN(SOUNDCACHE_ENTRY_SIZE, _stream->size())); + _currentDataPtr = _soundBuffer + 6; } else { _status.status = kSoundStatusRemoved; } @@ -282,7 +288,7 @@ void SoundEntry::update(uint val) { if (val) { if (getSoundQueue()->getFlag() & 32) { - _field_40 = val; + _variant = val; value2 = val * 2 + 1; } @@ -297,12 +303,12 @@ void SoundEntry::update(uint val) { void SoundEntry::updateState() { if (getSoundQueue()->getFlag() & 32) { if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { - uint32 newStatus = _status.status & kSoundStatusClear1; + uint32 variant = _status.status & kSoundStatusFilterVariant; _status.status &= kSoundStatusClearAll; - _field_40 = newStatus; - _status.status |= newStatus * 2 + 1; + _variant = variant; + _status.status |= variant * 2 + 1; } } @@ -680,16 +686,16 @@ static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, static void soundFilter(byte *data, int16 *buffer, int p1, int p2); void SoundEntry::applyFilter(int16 *buffer) { - if ((_soundBuffer[1] << 6) > 5632) { + if ((READ_UINT16((int16 *)(_currentDataPtr + 2)) << 6) > 5632) { _status.status |= kSoundStatus_20000000; } else { - int variant = _status.status & 0x1f; + int variant = _status.status & kSoundStatusFilterVariant; - soundFilter(_soundBuffer, buffer, p1s[variant], p2s[variant]); + soundFilter(_currentDataPtr, buffer, p1s[variant], p2s[variant]); + _currentDataPtr += 739; } } - static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { int data1, data2, data1p, data2p; byte idx; @@ -701,6 +707,12 @@ static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { for (int count = 0; count < 735; count++) { idx = data[count] >> 4; + + if ((idx + data1) > ARRAYSIZE(filterData)) { + warning("Error in sound filter, aborting..."); + return; + } + data1p = filterData[idx + data1]; data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); @@ -708,6 +720,11 @@ static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { idx = data[count] & 0xF; + if ((idx + data1p) > ARRAYSIZE(filterData)) { + warning("Error in sound filter, aborting..."); + return; + } + data1 = filterData[idx + data1p]; data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); buffer[2 * count + 1] = (p2 * data2) >> p1; diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 8da780f294..a466d31b3a 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -134,7 +134,7 @@ private: SoundType _type; // int //int _data; //int _endOffset; - int _currentDataPtr; + byte * _currentDataPtr; //int _currentBufferPtr; int _blockCount; uint32 _time; @@ -145,7 +145,7 @@ private: int _field_34; int _field_38; int _field_3C; - int _field_40; + int _variant; EntityIndex _entity; int _field_48; uint32 _priority; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index d5475a27de..ad5c9bf4e3 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -102,9 +102,9 @@ void SoundQueue::removeFromQueue(Common::String filename) { } void SoundQueue::updateQueue() { - Common::StackLock locker(_mutex); + //Common::StackLock locker(_mutex); - warning("[Sound::updateQueue] Not implemented"); + //warning("[Sound::updateQueue] Not implemented"); } void SoundQueue::resetQueue() { @@ -292,11 +292,11 @@ void SoundQueue::updateSubtitles() { if (!(status & kSoundStatus_40) || status & kSoundStatus_180 || soundEntry->getTime() == 0 - || (status & kSoundStatusClear1) < 6 + || (status & kSoundStatusFilterVariant) < 6 || ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) { current_index = 0; } else { - current_index = soundEntry->getPriority() + (status & kSoundStatusClear1); + current_index = soundEntry->getPriority() + (status & kSoundStatusFilterVariant); if (_currentSubtitle == (*i)) current_index += 4; -- cgit v1.2.3 From a5398bd663064d3ebca61c3e49eeb7773eadd612 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 15:22:43 -0400 Subject: LASTEXPRESS: Fix loading of subtitles from sound name --- engines/lastexpress/sound/entry.cpp | 10 +++++----- engines/lastexpress/sound/sound.cpp | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 4bdb9f7f96..2840d85ca7 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -752,7 +752,7 @@ void SubtitleEntry::load(Common::String filename, SoundEntry *soundEntry) { _sound = soundEntry; // Load subtitle data - if (_engine->getResourceManager()->hasFile(filename)) { + if (_engine->getResourceManager()->hasFile(_filename)) { if (getSoundQueue()->getSubtitleFlag() & 2) return; @@ -786,6 +786,8 @@ void SubtitleEntry::setupAndDraw() { } getSoundQueue()->setCurrentSubtitle(this); + + // TODO Missing code } void SubtitleEntry::draw() { @@ -801,13 +803,11 @@ void SubtitleEntry::draw() { } void SubtitleEntry::drawOnScreen() { - getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() & -1); - if (_data == NULL) return; - if (getSoundQueue()->getSubtitleFlag() & 1) - _engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay); + getSoundQueue()->setSubtitleFlag(getSoundQueue()->getSubtitleFlag() & -2); + _engine->getGraphicsManager()->draw(_data, GraphicsManager::kBackgroundOverlay); } } // End of namespace LastExpress diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index ff9e7e5aac..c04b6d361f 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -162,7 +162,8 @@ bool SoundManager::playSoundWithSubtitles(Common::String filename, SoundFlag fla entry->setStatus(entry->getStatus().status | kSoundStatus_8000); } else { // Get subtitles name - while (filename.size() > 4) + uint32 size = filename.size(); + while (filename.size() > size - 4) filename.deleteLastChar(); entry->showSubtitle(filename); -- cgit v1.2.3 From 7e4224e52a2202ba98dd93ffe209d231e5c1d35c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 3 Jul 2011 00:15:30 +0200 Subject: COMMON: Fix compilation when USE_HASHMAP_MEMORY_POOL is not defined. --- engines/lastexpress/resource.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/resource.h b/engines/lastexpress/resource.h index 7dc909ab34..9e05a90399 100644 --- a/engines/lastexpress/resource.h +++ b/engines/lastexpress/resource.h @@ -26,6 +26,8 @@ #include "lastexpress/data/archive.h" #include "lastexpress/shared.h" +#include "common/array.h" + namespace LastExpress { class Background; -- cgit v1.2.3 From 47e9a6ccdc6a162309ddaba2e6f6f83d5a047990 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Mon, 4 Jul 2011 14:24:50 -0400 Subject: LASTEXPRESS: Move sound filtering to base Sound class - Rename kSoundStatusRemoved to kSoundStatusClosed - Rename kSoundStatusClear2 to kSoundStatusCached - Remove sound cache handling --- engines/lastexpress/data/snd.cpp | 375 +++++++++++++++++++++++++++++- engines/lastexpress/data/snd.h | 8 +- engines/lastexpress/shared.h | 6 +- engines/lastexpress/sound/entry.cpp | 442 ++---------------------------------- engines/lastexpress/sound/entry.h | 12 +- engines/lastexpress/sound/queue.cpp | 4 +- 6 files changed, 402 insertions(+), 445 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index fa2d8a2e51..28d20df9bd 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -36,13 +36,329 @@ namespace LastExpress { +#pragma region Sound filters tables + +static const int filterData[1424] = { + 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, + 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, + 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, + 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, + 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, + 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, + 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, + 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, + 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, + 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, + 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, + 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, + 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, + 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, + 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, + 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, + 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, + 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, + 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, + 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, + 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, + 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, + 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, + 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, + 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, + 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, + 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, + 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, + 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, + 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, + 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, + 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, + 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, + 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, + 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, + 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, + 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, + 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, + 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, + 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, + 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, + 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, + 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, + 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, + 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, + 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, + 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, + 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, + 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, + 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, + 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, + 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, + 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, + 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, + 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, + 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, + 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, + 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, + 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, + 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, + 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, + 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, + 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, + 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, + 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, + 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, + 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, + 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, + 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, + 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, + 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, + 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, + 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, + 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, + 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, + 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, + 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, + 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, + 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, + 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, + 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, + 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, + 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, + 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, + 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, + 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, + 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, + 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, + 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, + 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, + 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, + 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, + 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, + 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, + 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, + 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, + 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, + 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, + 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, + 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, + 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, + 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, + 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, + 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, + 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, + 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, + 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, + 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, + 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, + 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, + 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, + 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, + 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, + 4.6, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, + 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, + 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, + 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, + 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, + 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, + 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, + 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, + 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, + 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, + 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, + 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, + 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, + 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, + 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, + 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, + 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, + 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, + 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, + 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, + 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, + 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, + 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, + 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, + 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, + 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, + 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, + 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, + 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, + 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, + 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, + 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, + 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, + 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, + 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, + 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, + 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, + 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, + 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, + 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, + 5632 +}; + +static const int filterData2[1424] = { + 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, + -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, + -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, + -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, + -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, + 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, + 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, + -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, + -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, + -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, + 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, + 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, + -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, + -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, + -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, + 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, + 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, + -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, + -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, + 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, + 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, + -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, + -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, + -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, + 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, + 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, + -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, + -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, + 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, + 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, + -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, + -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, + 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, + -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, + -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, + 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, + 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, + -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, + 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, + 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, + -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, + 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, + 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, + -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, + 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, + 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, + -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, + 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, + -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, + -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, + 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, + -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, + -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, + 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, + -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, + 631, -42, -126, -210, -294, -379, -463, -547, -631, + 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, + -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, + 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, + -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, + -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, + 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, + -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, + -68, -204, -340, -476, -612, -748, -884, -1020, 74, + 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, + -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, + 904, 1069, 1233, -82, -246, -411, -575, -740, -904, + -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, + -90, -271, -452, -633, -814, -995, -1176, -1357, 99, + 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, + -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, + 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, + -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, + 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, + -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, + -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, + 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, + -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, + 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, + -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, + 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, + -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, + -194, -582, -970, -1358, -1746, -2134, -2522, -2910, + 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, + -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, + 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, + -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, + 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, + -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, + 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, + -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, + 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, + -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, + 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, + -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, + -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, + 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, + -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, + 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, + -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, + 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, + -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, + 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, + -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, + 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, + -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, + 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, + -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, + 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, + -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, + -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, + 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, + -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, + 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, + -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, + 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, + -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, + 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, + -5933, -8306, -10679, -13052, -15426, -17799, 1305, + 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, + -3915, -6526, -9136, -11747, -14357, -16968, -19578, + 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, + -1435, -4307, -7179, -10051, -12922, -15794, -18666, + -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, + 23690, -1579, -4738, -7896, -11055, -14214, -17373, + -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, + 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, + -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, + 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, + -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, + 27329, 31533, -2102, -6306, -10511, -14715, -18920, + -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, + 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, + -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, + 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, + -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, + 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, + -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, + 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, + -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, + 32767, 32767, 32767, -3385, -10157, -16928, -23700, + -30471, -32767, -32767, -32767, 3724, 11172, 18621, + 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, + -26069, -32767, -32767, -32767, -32767, 4095, 12287, + 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, + -20479, -28671, -32767, -32767, -32767, -32767 +}; + +static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; +static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; + +#pragma endregion + // Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles // and does not have the 4 byte per channel requirement class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream { public: - LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize) : - Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) {} + LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, int32 filterId) : + Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) { + _currentFilterId = -1; + _nextFilterId = filterId; + } int readBuffer(int16 *buffer, const int numSamples) { int samples = 0; @@ -67,6 +383,45 @@ public: return samples; } + + void setFilterId(int32 filterId) { _nextFilterId = filterId; } + +private: + int32 _currentFilterId; + int32 _nextFilterId; // the sound filter id, -1 for none + + /** + * Sound filter + * + * @param [in] data If non-null, the input data + * @param [in,out] buffer If non-null, the output buffer. + * @param p1 The first filter input. + * @param p2 The second filter input. + */ + static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { + int data1, data2, data1p, data2p; + byte idx; + + data2 = data[0]; + data1 = data[1] << 6; + + data += 2; + + for (int count = 0; count < 735; count++) { + idx = data[count] >> 4; + + data1p = filterData[idx + data1]; + data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); + + buffer[2 * count] = (p2 * data2p) >> p1; + + idx = data[count] & 0xF; + + data1 = filterData[idx + data1p]; + data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); + buffer[2 * count + 1] = (p2 * data2) >> p1; + } + } }; ////////////////////////////////////////////////////////////////////////// @@ -92,8 +447,8 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) { _blockSize = _size / _blocks; } -Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size) const { - return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize); +Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const { + return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, filterId); } void SimpleSound::play(Audio::AudioStream *as) { @@ -103,11 +458,11 @@ void SimpleSound::play(Audio::AudioStream *as) { ////////////////////////////////////////////////////////////////////////// // StreamedSound ////////////////////////////////////////////////////////////////////////// -StreamedSound::StreamedSound() : _loaded(false) {} +StreamedSound::StreamedSound() : _as(NULL), _loaded(false) {} StreamedSound::~StreamedSound() {} -bool StreamedSound::load(Common::SeekableReadStream *stream) { +bool StreamedSound::load(Common::SeekableReadStream *stream, int32 filterId) { if (!stream) return false; @@ -116,10 +471,10 @@ bool StreamedSound::load(Common::SeekableReadStream *stream) { loadHeader(stream); // Start decoding the input stream - Audio::AudioStream *as = makeDecoder(stream, _size); + _as = makeDecoder(stream, _size, filterId); // Start playing the decoded audio stream - play(as); + play(_as); _loaded = true; @@ -133,6 +488,10 @@ bool StreamedSound::isFinished() { return !g_system->getMixer()->isSoundHandleActive(_handle); } +void StreamedSound::setFilterId(int32 filterId) { + ((LastExpress_ADPCMStream *)_as)->setFilterId(filterId); +} + ////////////////////////////////////////////////////////////////////////// // StreamedSound ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h index 1c34e4f950..7111d939e7 100644 --- a/engines/lastexpress/data/snd.h +++ b/engines/lastexpress/data/snd.h @@ -59,7 +59,7 @@ public: protected: void loadHeader(Common::SeekableReadStream *in); - Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size) const; + Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const; void play(Audio::AudioStream *as); uint32 _size; ///< data size @@ -76,11 +76,13 @@ public: StreamedSound(); ~StreamedSound(); - bool load(Common::SeekableReadStream *stream); - + bool load(Common::SeekableReadStream *stream, int32 filterId = -1); virtual bool isFinished(); + void setFilterId(int32 filterId); + private: + Audio::AudioStream *_as; bool _loaded; }; diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index b4ced96ee1..7b640c773a 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -93,7 +93,7 @@ enum SoundStatus { kSoundStatus_20 = 0x20, kSoundStatus_40 = 0x40, kSoundStatus_180 = 0x180, - kSoundStatusRemoved = 0x200, + kSoundStatusClosed = 0x200, kSoundStatus_400 = 0x400, kSoundStatus_8000 = 0x8000, @@ -103,8 +103,8 @@ enum SoundStatus { kSoundStatus_40000000 = 0x40000000, kSoundStatusClear0 = 0x10, - kSoundStatusFilterVariant = 0x1F, - kSoundStatusClear2 = 0x80, + kSoundStatusFilter = 0x1F, + kSoundStatusCached = 0x80, kSoundStatusClear3 = 0x200, kSoundStatusClear4 = 0x800, kSoundStatusClearAll = 0xFFFFFFE0 diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 2840d85ca7..1ba1862875 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -47,9 +47,6 @@ namespace LastExpress { SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _type = kSoundTypeNone; - _currentDataPtr = NULL; - _soundBuffer = NULL; - _blockCount = 0; _time = 0; @@ -76,8 +73,6 @@ SoundEntry::~SoundEntry() { SAFE_DELETE(_stream); delete _soundStream; - free(_soundBuffer); - // Zero passed pointers _engine = NULL; } @@ -86,14 +81,11 @@ void SoundEntry::open(Common::String name, SoundFlag flag, int priority) { _priority = priority; setType(flag); setupStatus(flag); - - // Add entry to cache and load sound data - setupCache(); - loadSoundData(name); + loadStream(name); } void SoundEntry::close() { - _status.status |= kSoundStatusRemoved; + _status.status |= kSoundStatusClosed; // Loop until ready while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) @@ -123,34 +115,24 @@ void SoundEntry::play() { return; } - if (_queued) - return; - - // Apply filter - int16 *buffer = (int16 *)malloc(FILTER_BUFFER_SIZE); - memset(buffer, 0, FILTER_BUFFER_SIZE); - - applyFilter(buffer); - - // Queue the filtered data -#if 0 + // Prepare sound stream if (!_soundStream) - _soundStream = new AppendableSound(); + _soundStream = new StreamedSound(); - // FIXME: make sure the filtered sound buffer is disposed - _soundStream->queueBuffer((const byte *)buffer, FILTER_BUFFER_SIZE /* true */); -#else - free(buffer); + // Compute current filter id + int32 filterId = _status.status & kSoundStatusFilter; + // TODO adjust status (based on stepIndex) - // DEBUG: unfiltered stream - if (!_soundStream) - _soundStream = new StreamedSound(); + if (_queued) { + _soundStream->setFilterId(filterId); + } else { + _stream->seek(0); - _stream->seek(0); - _soundStream->load(_stream); -#endif + // Load the stream and start playing + _soundStream->load(_stream, filterId); - _queued = true; + _queued = true; + } } bool SoundEntry::isFinished() { @@ -238,8 +220,8 @@ void SoundEntry::setType(SoundFlag flag) { void SoundEntry::setupStatus(SoundFlag flag) { SoundStatus statusFlag = (SoundStatus)flag; - if (!((statusFlag & 0xFF) & kSoundStatusFilterVariant)) - statusFlag = (SoundStatus)(statusFlag | kSoundStatusClear2); + if (!((statusFlag & 0xFF) & kSoundStatusFilter)) + statusFlag = (SoundStatus)(statusFlag | kSoundStatusCached); if (((statusFlag & 0xFF00) >> 8) & kSoundStatusClear0) _status.status = (uint32)statusFlag; @@ -247,23 +229,7 @@ void SoundEntry::setupStatus(SoundFlag flag) { _status.status = (statusFlag | kSoundStatusClear4); } -void SoundEntry::setupCache() { - if (_soundBuffer) - return; - - // Original has a priority-based shared buffer (of 6 entries) - // We simply allocate a new buffer for each sound entry that needs it - _soundBuffer = (byte *)malloc(SOUNDCACHE_ENTRY_SIZE); - memset(_soundBuffer, 0, SOUNDCACHE_ENTRY_SIZE); - - setInCache(); -} - -void SoundEntry::setInCache() { - _status.status |= kSoundStatusClear2; -} - -void SoundEntry::loadSoundData(Common::String name) { +void SoundEntry::loadStream(Common::String name) { _name2 = name; // Load sound data @@ -272,12 +238,8 @@ void SoundEntry::loadSoundData(Common::String name) { if (!_stream) _stream = getArchive("DEFAULT.SND"); - if (_stream) { - _stream->read(_soundBuffer, MIN(SOUNDCACHE_ENTRY_SIZE, _stream->size())); - _currentDataPtr = _soundBuffer + 6; - } else { - _status.status = kSoundStatusRemoved; - } + if (!_stream) + _status.status = kSoundStatusClosed; } void SoundEntry::update(uint val) { @@ -303,7 +265,7 @@ void SoundEntry::update(uint val) { void SoundEntry::updateState() { if (getSoundQueue()->getFlag() & 32) { if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { - uint32 variant = _status.status & kSoundStatusFilterVariant; + uint32 variant = _status.status & kSoundStatusFilter; _status.status &= kSoundStatusClearAll; @@ -316,7 +278,7 @@ void SoundEntry::updateState() { } void SoundEntry::reset() { - _status.status |= kSoundStatusRemoved; + _status.status |= kSoundStatusClosed; _entity = kEntityPlayer; if (_stream) { @@ -371,366 +333,6 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { } } -////////////////////////////////////////////////////////////////////////// -// Sound filters -////////////////////////////////////////////////////////////////////////// -static const int filterData[1424] = { - 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, - 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, - 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, - 64, 64, 64, 64, 256, 384, 512, 640, 128, 128, 128, 128, - 320, 448, 576, 704, 128, 128, 128, 128, 320, 448, 576, - 704, 192, 192, 192, 192, 384, 512, 640, 768, 192, 192, - 192, 192, 384, 512, 640, 768, 256, 256, 256, 256, 448, - 576, 704, 832, 256, 256, 256, 256, 448, 576, 704, 832, - 320, 320, 320, 320, 512, 640, 768, 896, 320, 320, 320, - 320, 512, 640, 768, 896, 384, 384, 384, 384, 576, 704, - 832, 960, 384, 384, 384, 384, 576, 704, 832, 960, 448, - 448, 448, 448, 640, 768, 896, 1024, 448, 448, 448, 448, - 640, 768, 896, 1024, 512, 512, 512, 512, 704, 832, 960, - 1088, 512, 512, 512, 512, 704, 832, 960, 1088, 576, - 576, 576, 576, 768, 896, 1024, 1152, 576, 576, 576, - 576, 768, 896, 1024, 1152, 640, 640, 640, 640, 832, - 960, 1088, 1216, 640, 640, 640, 640, 832, 960, 1088, - 1216, 704, 704, 704, 704, 896, 1024, 1152, 1280, 704, - 704, 704, 704, 896, 1024, 1152, 1280, 768, 768, 768, - 768, 960, 1088, 1216, 1344, 768, 768, 768, 768, 960, - 1088, 1216, 1344, 832, 832, 832, 832, 1024, 1152, 1280, - 1408, 832, 832, 832, 832, 1024, 1152, 1280, 1408, 896, - 896, 896, 896, 1088, 1216, 1344, 1472, 896, 896, 896, - 896, 1088, 1216, 1344, 1472, 960, 960, 960, 960, 1152, - 1280, 1408, 1536, 960, 960, 960, 960, 1152, 1280, 1408, - 1536, 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, - 1024, 1024, 1024, 1024, 1216, 1344, 1472, 1600, 1088, - 1088, 1088, 1088, 1280, 1408, 1536, 1664, 1088, 1088, - 1088, 1088, 1280, 1408, 1536, 1664, 1152, 1152, 1152, - 1152, 1344, 1472, 1600, 1728, 1152, 1152, 1152, 1152, - 1344, 1472, 1600, 1728, 1216, 1216, 1216, 1216, 1408, - 1536, 1664, 1792, 1216, 1216, 1216, 1216, 1408, 1536, - 1664, 1792, 1280, 1280, 1280, 1280, 1472, 1600, 1728, - 1856, 1280, 1280, 1280, 1280, 1472, 1600, 1728, 1856, - 1344, 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1344, - 1344, 1344, 1344, 1536, 1664, 1792, 1920, 1408, 1408, - 1408, 1408, 1600, 1728, 1856, 1984, 1408, 1408, 1408, - 1408, 1600, 1728, 1856, 1984, 1472, 1472, 1472, 1472, - 1664, 1792, 1920, 2048, 1472, 1472, 1472, 1472, 1664, - 1792, 1920, 2048, 1536, 1536, 1536, 1536, 1728, 1856, - 1984, 2112, 1536, 1536, 1536, 1536, 1728, 1856, 1984, - 2112, 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, - 1600, 1600, 1600, 1600, 1792, 1920, 2048, 2176, 1664, - 1664, 1664, 1664, 1856, 1984, 2112, 2240, 1664, 1664, - 1664, 1664, 1856, 1984, 2112, 2240, 1728, 1728, 1728, - 1728, 1920, 2048, 2176, 2304, 1728, 1728, 1728, 1728, - 1920, 2048, 2176, 2304, 1792, 1792, 1792, 1792, 1984, - 2112, 2240, 2368, 1792, 1792, 1792, 1792, 1984, 2112, - 2240, 2368, 1856, 1856, 1856, 1856, 2048, 2176, 2304, - 2432, 1856, 1856, 1856, 1856, 2048, 2176, 2304, 2432, - 1920, 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1920, - 1920, 1920, 1920, 2112, 2240, 2368, 2496, 1984, 1984, - 1984, 1984, 2176, 2304, 2432, 2560, 1984, 1984, 1984, - 1984, 2176, 2304, 2432, 2560, 2048, 2048, 2048, 2048, - 2240, 2368, 2496, 2624, 2048, 2048, 2048, 2048, 2240, - 2368, 2496, 2624, 2112, 2112, 2112, 2112, 2304, 2432, - 2560, 2688, 2112, 2112, 2112, 2112, 2304, 2432, 2560, - 2688, 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, - 2176, 2176, 2176, 2176, 2368, 2496, 2624, 2752, 2240, - 2240, 2240, 2240, 2432, 2560, 2688, 2816, 2240, 2240, - 2240, 2240, 2432, 2560, 2688, 2816, 2304, 2304, 2304, - 2304, 2496, 2624, 2752, 2880, 2304, 2304, 2304, 2304, - 2496, 2624, 2752, 2880, 2368, 2368, 2368, 2368, 2560, - 2688, 2816, 2944, 2368, 2368, 2368, 2368, 2560, 2688, - 2816, 2944, 2432, 2432, 2432, 2432, 2624, 2752, 2880, - 3008, 2432, 2432, 2432, 2432, 2624, 2752, 2880, 3008, - 2496, 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2496, - 2496, 2496, 2496, 2688, 2816, 2944, 3072, 2560, 2560, - 2560, 2560, 2752, 2880, 3008, 3136, 2560, 2560, 2560, - 2560, 2752, 2880, 3008, 3136, 2624, 2624, 2624, 2624, - 2816, 2944, 3072, 3200, 2624, 2624, 2624, 2624, 2816, - 2944, 3072, 3200, 2688, 2688, 2688, 2688, 2880, 3008, - 3136, 3264, 2688, 2688, 2688, 2688, 2880, 3008, 3136, - 3264, 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, - 2752, 2752, 2752, 2752, 2944, 3072, 3200, 3328, 2816, - 2816, 2816, 2816, 3008, 3136, 3264, 3392, 2816, 2816, - 2816, 2816, 3008, 3136, 3264, 3392, 2880, 2880, 2880, - 2880, 3072, 3200, 3328, 3456, 2880, 2880, 2880, 2880, - 3072, 3200, 3328, 3456, 2944, 2944, 2944, 2944, 3136, - 3264, 3392, 3520, 2944, 2944, 2944, 2944, 3136, 3264, - 3392, 3520, 3008, 3008, 3008, 3008, 3200, 3328, 3456, - 3584, 3008, 3008, 3008, 3008, 3200, 3328, 3456, 3584, - 3072, 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3072, - 3072, 3072, 3072, 3264, 3392, 3520, 3648, 3136, 3136, - 3136, 3136, 3328, 3456, 3584, 3712, 3136, 3136, 3136, - 3136, 3328, 3456, 3584, 3712, 3200, 3200, 3200, 3200, - 3392, 3520, 3648, 3776, 3200, 3200, 3200, 3200, 3392, - 3520, 3648, 3776, 3264, 3264, 3264, 3264, 3456, 3584, - 3712, 3840, 3264, 3264, 3264, 3264, 3456, 3584, 3712, - 3840, 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, - 3328, 3328, 3328, 3328, 3520, 3648, 3776, 3904, 3392, - 3392, 3392, 3392, 3584, 3712, 3840, 3968, 3392, 3392, - 3392, 3392, 3584, 3712, 3840, 3968, 3456, 3456, 3456, - 3456, 3648, 3776, 3904, 4032, 3456, 3456, 3456, 3456, - 3648, 3776, 3904, 4032, 3520, 3520, 3520, 3520, 3712, - 3840, 3968, 4096, 3520, 3520, 3520, 3520, 3712, 3840, - 3968, 4096, 3584, 3584, 3584, 3584, 3776, 3904, 4032, - 4160, 3584, 3584, 3584, 3584, 3776, 3904, 4032, 4160, - 3648, 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3648, - 3648, 3648, 3648, 3840, 3968, 4096, 4224, 3712, 3712, - 3712, 3712, 3904, 4032, 4160, 4288, 3712, 3712, 3712, - 3712, 3904, 4032, 4160, 4288, 3776, 3776, 3776, 3776, - 3968, 4096, 4224, 4352, 3776, 3776, 3776, 3776, 3968, - 4096, 4224, 4352, 3840, 3840, 3840, 3840, 4032, 4160, - 4288, 4416, 3840, 3840, 3840, 3840, 4032, 4160, 4288, - 4416, 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, - 3904, 3904, 3904, 3904, 4096, 4224, 4352, 4480, 3968, - 3968, 3968, 3968, 4160, 4288, 4416, 4544, 3968, 3968, - 3968, 3968, 4160, 4288, 4416, 4544, 4032, 4032, 4032, - 4032, 4224, 4352, 4480, 4608, 4032, 4032, 4032, 4032, - 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, - 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, - 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, - 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, - 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, - 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, - 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, - 4288, 4480, 4608, 4736, 4864, 4352, 4352, 4352, 4352, - 4544, 4672, 4800, 4928, 4352, 4352, 4352, 4352, 4544, - 4672, 4800, 4928, 4416, 4416, 4416, 4416, 4608, 4736, - 4864, 4992, 4416, 4416, 4416, 4416, 4608, 4736, 4864, - 4992, 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, - 4480, 4480, 4480, 4480, 4672, 4800, 4928, 5056, 4544, - 4544, 4544, 4544, 4736, 4864, 4992, 5120, 4544, 4544, - 4544, 4544, 4736, 4864, 4992, 5120, 4608, 4608, 4608, - 4608, 4800, 4928, 5056, 5184, 4608, 4608, 4608, 4608, - 4800, 4928, 5056, 5184, 4672, 4672, 4672, 4672, 4864, - 4992, 5120, 5248, 4672, 4672, 4672, 4672, 4864, 4992, - 5120, 5248, 4736, 4736, 4736, 4736, 4928, 5056, 5184, - 5312, 4736, 4736, 4736, 4736, 4928, 5056, 5184, 5312, - 4800, 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4800, - 4800, 4800, 4800, 4992, 5120, 5248, 5376, 4864, 4864, - 4864, 4864, 5056, 5184, 5312, 5440, 4864, 4864, 4864, - 4864, 5056, 5184, 5312, 5440, 4928, 4928, 4928, 4928, - 5120, 5248, 5376, 5504, 4928, 4928, 4928, 4928, 5120, - 5248, 5376, 5504, 4992, 4992, 4992, 4992, 5184, 5312, - 5440, 5568, 4992, 4992, 4992, 4992, 5184, 5312, 5440, - 5568, 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, - 5056, 5056, 5056, 5056, 5248, 5376, 5504, 5632, 5120, - 5120, 5120, 5120, 5312, 5440, 5568, 5632, 5120, 5120, - 5120, 5120, 5312, 5440, 5568, 5632, 5184, 5184, 5184, - 5184, 5376, 5504, 5632, 5632, 5184, 5184, 5184, 5184, - 5376, 5504, 5632, 5632, 5248, 5248, 5248, 5248, 5440, - 5568, 5632, 5632, 5248, 5248, 5248, 5248, 5440, 5568, - 5632, 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, - 5632, 5312, 5312, 5312, 5312, 5504, 5632, 5632, 5632, - 5376, 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5376, - 5376, 5376, 5376, 5568, 5632, 5632, 5632, 5440, 5440, - 5440, 5440, 5632, 5632, 5632, 5632, 5440, 5440, 5440, - 5440, 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, - 5632, 5632, 5632, 5632, 5504, 5504, 5504, 5504, 5632, - 5632, 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, - 5632, 5632, 5568, 5568, 5568, 5568, 5632, 5632, 5632, - 5632 -}; - -static const int filterData2[1424] = { - 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, - -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, - -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, - -7, -10, -12, -14, -16, 1, 3, 6, 8, 11, 13, 16, 18, - -1, -3, -6, -8, -11, -13, -16, -18, 1, 4, 6, 9, 12, - 15, 17, 20, -1, -4, -6, -9, -12, -15, -17, -20, 1, 4, - 7, 10, 13, 16, 19, 22, -1, -4, -7, -10, -13, -16, -19, - -22, 1, 4, 8, 11, 14, 17, 21, 24, -1, -4, -8, -11, -14, - -17, -21, -24, 1, 5, 8, 12, 15, 19, 22, 26, -1, -5, - -8, -12, -15, -19, -22, -26, 2, 6, 10, 14, 18, 22, 26, - 30, -2, -6, -10, -14, -18, -22, -26, -30, 2, 6, 10, - 14, 19, 23, 27, 31, -2, -6, -10, -14, -19, -23, -27, - -31, 2, 7, 11, 16, 21, 26, 30, 35, -2, -7, -11, -16, - -21, -26, -30, -35, 2, 7, 13, 18, 23, 28, 34, 39, -2, - -7, -13, -18, -23, -28, -34, -39, 2, 8, 14, 20, 25, - 31, 37, 43, -2, -8, -14, -20, -25, -31, -37, -43, 3, - 9, 15, 21, 28, 34, 40, 46, -3, -9, -15, -21, -28, -34, - -40, -46, 3, 10, 17, 24, 31, 38, 45, 52, -3, -10, -17, - -24, -31, -38, -45, -52, 3, 11, 19, 27, 34, 42, 50, - 58, -3, -11, -19, -27, -34, -42, -50, -58, 4, 12, 21, - 29, 38, 46, 55, 63, -4, -12, -21, -29, -38, -46, -55, - -63, 4, 13, 23, 32, 41, 50, 60, 69, -4, -13, -23, -32, - -41, -50, -60, -69, 5, 15, 25, 35, 46, 56, 66, 76, -5, - -15, -25, -35, -46, -56, -66, -76, 5, 16, 28, 39, 50, - 61, 73, 84, -5, -16, -28, -39, -50, -61, -73, -84, 6, - 18, 31, 43, 56, 68, 81, 93, -6, -18, -31, -43, -56, - -68, -81, -93, 6, 20, 34, 48, 61, 75, 89, 103, -6, -20, - -34, -48, -61, -75, -89, -103, 7, 22, 37, 52, 67, 82, - 97, 112, -7, -22, -37, -52, -67, -82, -97, -112, 8, - 24, 41, 57, 74, 90, 107, 123, -8, -24, -41, -57, -74, - -90, -107, -123, 9, 27, 45, 63, 82, 100, 118, 136, -9, - -27, -45, -63, -82, -100, -118, -136, 10, 30, 50, 70, - 90, 110, 130, 150, -10, -30, -50, -70, -90, -110, -130, - -150, 11, 33, 55, 77, 99, 121, 143, 165, -11, -33, -55, - -77, -99, -121, -143, -165, 12, 36, 60, 84, 109, 133, - 157, 181, -12, -36, -60, -84, -109, -133, -157, -181, - 13, 40, 66, 93, 120, 147, 173, 200, -13, -40, -66, -93, - -120, -147, -173, -200, 14, 44, 73, 103, 132, 162, 191, - 221, -14, -44, -73, -103, -132, -162, -191, -221, 16, - 48, 81, 113, 146, 178, 211, 243, -16, -48, -81, -113, - -146, -178, -211, -243, 17, 53, 89, 125, 160, 196, 232, - 268, -17, -53, -89, -125, -160, -196, -232, -268, 19, - 58, 98, 137, 176, 215, 255, 294, -19, -58, -98, -137, - -176, -215, -255, -294, 21, 64, 108, 151, 194, 237, - 281, 324, -21, -64, -108, -151, -194, -237, -281, -324, - 23, 71, 118, 166, 213, 261, 308, 356, -23, -71, -118, - -166, -213, -261, -308, -356, 26, 78, 130, 182, 235, - 287, 339, 391, -26, -78, -130, -182, -235, -287, -339, - -391, 28, 86, 143, 201, 258, 316, 373, 431, -28, -86, - -143, -201, -258, -316, -373, -431, 31, 94, 158, 221, - 284, 347, 411, 474, -31, -94, -158, -221, -284, -347, - -411, -474, 34, 104, 174, 244, 313, 383, 453, 523, -34, - -104, -174, -244, -313, -383, -453, -523, 38, 115, 191, - 268, 345, 422, 498, 575, -38, -115, -191, -268, -345, - -422, -498, -575, 42, 126, 210, 294, 379, 463, 547, - 631, -42, -126, -210, -294, -379, -463, -547, -631, - 46, 139, 231, 324, 417, 510, 602, 695, -46, -139, -231, - -324, -417, -510, -602, -695, 51, 153, 255, 357, 459, - 561, 663, 765, -51, -153, -255, -357, -459, -561, -663, - -765, 56, 168, 280, 392, 505, 617, 729, 841, -56, -168, - -280, -392, -505, -617, -729, -841, 61, 185, 308, 432, - 555, 679, 802, 926, -61, -185, -308, -432, -555, -679, - -802, -926, 68, 204, 340, 476, 612, 748, 884, 1020, - -68, -204, -340, -476, -612, -748, -884, -1020, 74, - 224, 373, 523, 672, 822, 971, 1121, -74, -224, -373, - -523, -672, -822, -971, -1121, 82, 246, 411, 575, 740, - 904, 1069, 1233, -82, -246, -411, -575, -740, -904, - -1069, -1233, 90, 271, 452, 633, 814, 995, 1176, 1357, - -90, -271, -452, -633, -814, -995, -1176, -1357, 99, - 298, 497, 696, 895, 1094, 1293, 1492, -99, -298, -497, - -696, -895, -1094, -1293, -1492, 109, 328, 547, 766, - 985, 1204, 1423, 1642, -109, -328, -547, -766, -985, - -1204, -1423, -1642, 120, 361, 601, 842, 1083, 1324, - 1564, 1805, -120, -361, -601, -842, -1083, -1324, -1564, - -1805, 132, 397, 662, 927, 1192, 1457, 1722, 1987, -132, - -397, -662, -927, -1192, -1457, -1722, -1987, 145, 437, - 728, 1020, 1311, 1603, 1894, 2186, -145, -437, -728, - -1020, -1311, -1603, -1894, -2186, 160, 480, 801, 1121, - 1442, 1762, 2083, 2403, -160, -480, -801, -1121, -1442, - -1762, -2083, -2403, 176, 529, 881, 1234, 1587, 1940, - 2292, 2645, -176, -529, -881, -1234, -1587, -1940, -2292, - -2645, 194, 582, 970, 1358, 1746, 2134, 2522, 2910, - -194, -582, -970, -1358, -1746, -2134, -2522, -2910, - 213, 640, 1066, 1493, 1920, 2347, 2773, 3200, -213, - -640, -1066, -1493, -1920, -2347, -2773, -3200, 234, - 704, 1173, 1643, 2112, 2582, 3051, 3521, -234, -704, - -1173, -1643, -2112, -2582, -3051, -3521, 258, 774, - 1291, 1807, 2324, 2840, 3357, 3873, -258, -774, -1291, - -1807, -2324, -2840, -3357, -3873, 284, 852, 1420, 1988, - 2556, 3124, 3692, 4260, -284, -852, -1420, -1988, -2556, - -3124, -3692, -4260, 312, 937, 1561, 2186, 2811, 3436, - 4060, 4685, -312, -937, -1561, -2186, -2811, -3436, - -4060, -4685, 343, 1030, 1718, 2405, 3092, 3779, 4467, - 5154, -343, -1030, -1718, -2405, -3092, -3779, -4467, - -5154, 378, 1134, 1890, 2646, 3402, 4158, 4914, 5670, - -378, -1134, -1890, -2646, -3402, -4158, -4914, -5670, - 415, 1247, 2079, 2911, 3742, 4574, 5406, 6238, -415, - -1247, -2079, -2911, -3742, -4574, -5406, -6238, 457, - 1372, 2287, 3202, 4117, 5032, 5947, 6862, -457, -1372, - -2287, -3202, -4117, -5032, -5947, -6862, 503, 1509, - 2516, 3522, 4529, 5535, 6542, 7548, -503, -1509, -2516, - -3522, -4529, -5535, -6542, -7548, 553, 1660, 2767, - 3874, 4981, 6088, 7195, 8302, -553, -1660, -2767, -3874, - -4981, -6088, -7195, -8302, 608, 1826, 3044, 4262, 5479, - 6697, 7915, 9133, -608, -1826, -3044, -4262, -5479, - -6697, -7915, -9133, 669, 2009, 3348, 4688, 6027, 7367, - 8706, 10046, -669, -2009, -3348, -4688, -6027, -7367, - -8706, -10046, 736, 2210, 3683, 5157, 6630, 8104, 9577, - 11051, -736, -2210, -3683, -5157, -6630, -8104, -9577, - -11051, 810, 2431, 4052, 5673, 7294, 8915, 10536, 12157, - -810, -2431, -4052, -5673, -7294, -8915, -10536, -12157, - 891, 2674, 4457, 6240, 8023, 9806, 11589, 13372, -891, - -2674, -4457, -6240, -8023, -9806, -11589, -13372, 980, - 2941, 4903, 6864, 8825, 10786, 12748, 14709, -980, -2941, - -4903, -6864, -8825, -10786, -12748, -14709, 1078, 3236, - 5393, 7551, 9708, 11866, 14023, 16181, -1078, -3236, - -5393, -7551, -9708, -11866, -14023, -16181, 1186, 3559, - 5933, 8306, 10679, 13052, 15426, 17799, -1186, -3559, - -5933, -8306, -10679, -13052, -15426, -17799, 1305, - 3915, 6526, 9136, 11747, 14357, 16968, 19578, -1305, - -3915, -6526, -9136, -11747, -14357, -16968, -19578, - 1435, 4307, 7179, 10051, 12922, 15794, 18666, 21538, - -1435, -4307, -7179, -10051, -12922, -15794, -18666, - -21538, 1579, 4738, 7896, 11055, 14214, 17373, 20531, - 23690, -1579, -4738, -7896, -11055, -14214, -17373, - -20531, -23690, 1737, 5212, 8686, 12161, 15636, 19111, - 22585, 26060, -1737, -5212, -8686, -12161, -15636, -19111, - -22585, -26060, 1911, 5733, 9555, 13377, 17200, 21022, - 24844, 28666, -1911, -5733, -9555, -13377, -17200, -21022, - -24844, -28666, 2102, 6306, 10511, 14715, 18920, 23124, - 27329, 31533, -2102, -6306, -10511, -14715, -18920, - -23124, -27329, -31533, 2312, 6937, 11562, 16187, 20812, - 25437, 30062, 32767, -2312, -6937, -11562, -16187, -20812, - -25437, -30062, -32767, 2543, 7631, 12718, 17806, 22893, - 27981, 32767, 32767, -2543, -7631, -12718, -17806, -22893, - -27981, -32767, -32767, 2798, 8394, 13990, 19586, 25183, - 30779, 32767, 32767, -2798, -8394, -13990, -19586, -25183, - -30779, -32767, -32767, 3077, 9233, 15389, 21545, 27700, - 32767, 32767, 32767, -3077, -9233, -15389, -21545, -27700, - -32767, -32767, -32767, 3385, 10157, 16928, 23700, 30471, - 32767, 32767, 32767, -3385, -10157, -16928, -23700, - -30471, -32767, -32767, -32767, 3724, 11172, 18621, - 26069, 32767, 32767, 32767, 32767, -3724, -11172, -18621, - -26069, -32767, -32767, -32767, -32767, 4095, 12287, - 20479, 28671, 32767, 32767, 32767, 32767, -4095, -12287, - -20479, -28671, -32767, -32767, -32767, -32767 -}; - -static const int p1s[17] = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4, 0 }; -static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, 1 }; - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2); - -void SoundEntry::applyFilter(int16 *buffer) { - if ((READ_UINT16((int16 *)(_currentDataPtr + 2)) << 6) > 5632) { - _status.status |= kSoundStatus_20000000; - } else { - int variant = _status.status & kSoundStatusFilterVariant; - - soundFilter(_currentDataPtr, buffer, p1s[variant], p2s[variant]); - _currentDataPtr += 739; - } -} - -static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { - int data1, data2, data1p, data2p; - byte idx; - - data2 = data[0]; - data1 = data[1] << 6; - - data += 2; - - for (int count = 0; count < 735; count++) { - idx = data[count] >> 4; - - if ((idx + data1) > ARRAYSIZE(filterData)) { - warning("Error in sound filter, aborting..."); - return; - } - - data1p = filterData[idx + data1]; - data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); - - buffer[2 * count] = (p2 * data2p) >> p1; - - idx = data[count] & 0xF; - - if ((idx + data1p) > ARRAYSIZE(filterData)) { - warning("Error in sound filter, aborting..."); - return; - } - - data1 = filterData[idx + data1p]; - data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); - buffer[2 * count + 1] = (p2 * data2) >> p1; - } -} - ////////////////////////////////////////////////////////////////////////// // SubtitleEntry ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index a466d31b3a..c175b7bd40 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -124,8 +124,7 @@ public: Common::String getName2() { return _name2; } // Streams - SimpleSound *getSoundStream() { return _soundStream; } - byte *getSoundBuffer() { return _soundBuffer; } + SimpleSound *getSoundStream() { return _soundStream; } private: LastExpressEngine *_engine; @@ -156,16 +155,11 @@ private: // Sound buffer & stream bool _queued; - byte *_soundBuffer; StreamedSound *_soundStream; // the filtered sound stream void setType(SoundFlag flag); void setupStatus(SoundFlag flag); - void setupCache(); - void setInCache(); - void loadSoundData(Common::String name); - - void applyFilter(int16 *buffer); + void loadStream(Common::String name); }; ////////////////////////////////////////////////////////////////////////// @@ -184,7 +178,7 @@ public: // Accessors SoundStatusUnion getStatus() { return _status; } - SoundEntry *getSoundEntry() { return _sound; } + SoundEntry *getSoundEntry() { return _sound; } private: LastExpressEngine *_engine; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index ad5c9bf4e3..b2f48cf4c1 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -292,11 +292,11 @@ void SoundQueue::updateSubtitles() { if (!(status & kSoundStatus_40) || status & kSoundStatus_180 || soundEntry->getTime() == 0 - || (status & kSoundStatusFilterVariant) < 6 + || (status & kSoundStatusFilter) < 6 || ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) { current_index = 0; } else { - current_index = soundEntry->getPriority() + (status & kSoundStatusFilterVariant); + current_index = soundEntry->getPriority() + (status & kSoundStatusFilter); if (_currentSubtitle == (*i)) current_index += 4; -- cgit v1.2.3 From c4b2800145d3f6a2896c619165a73054677f138f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 5 Jul 2011 15:32:42 +0300 Subject: LASTEXPRESS: implement Sound::updateQueue() and all dependent functions --- engines/lastexpress/sound/entry.cpp | 50 ++++++++++++++++++++++++++ engines/lastexpress/sound/entry.h | 4 ++- engines/lastexpress/sound/queue.cpp | 71 +++++++++++++++++++++++++++++++++++++ engines/lastexpress/sound/sound.h | 12 +++++-- 4 files changed, 133 insertions(+), 4 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 1ba1862875..87d8ccdb30 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -262,6 +262,56 @@ void SoundEntry::update(uint val) { } } +bool SoundEntry::updateSound() { + bool result; + char sub[16]; + + if (_status.status2 & 4) { + result = false; + } else { + if (_status.status2 & 0x80) { + if (_field_48 <= getSound()->getData2()) { + _status.status |= 0x20; + _status.status &= ~0x8000; + strcpy(sub, _name2.c_str()); + + int l = strlen(sub) + 1; + if (l - 1 > 4) + sub[l - 1 - 4] = 0; + showSubtitle(sub); + } + } else { + if (!(getSoundQueue()->getFlag() & 0x20)) { + if (!(_status.status3 & 8)) { + if (_entity) { + if (_entity < 0x80) { + updateEntryFlag(getSound()->getSoundFlag(_entity)); + } + } + } + } + //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer) + // Sound_FillSoundBuffer(v1); + } + result = true; + } + + return result; +} + +void SoundEntry::updateEntryFlag(SoundFlag flag) { + if (flag) { + if (getSoundQueue()->getFlag() & 0x20 && _type != kSoundType9 && _type != kSoundType7) + update(flag); + else + _status.status = flag + (_status.status & ~0x1F); + } else { + _variant = 0; + _status.status |= 0x80u; + _status.status &= ~0x10001F; + } +} + void SoundEntry::updateState() { if (getSoundQueue()->getFlag() & 32) { if (_type != kSoundType9 && _type != kSoundType7 && _type != kSoundType5) { diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index c175b7bd40..a88b0b7210 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -102,7 +102,9 @@ public: void reset(); bool isFinished(); void update(uint val); + bool updateSound(); void updateState(); + void updateEntryFlag(SoundFlag flag); // Subtitles void showSubtitle(Common::String filename); @@ -140,7 +142,7 @@ private: //int _size; //int _field_28; Common::SeekableReadStream *_stream; // The file stream - //int _field_30; + //int _archive; int _field_34; int _field_38; int _field_3C; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index b2f48cf4c1..0a6442ceed 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -105,6 +105,77 @@ void SoundQueue::updateQueue() { //Common::StackLock locker(_mutex); //warning("[Sound::updateQueue] Not implemented"); + + int maxPriority = 0; + Common::List::iterator lsnd; + SoundEntry *msnd; + + bool loopedPlaying; + + loopedPlaying = 0; + //++g_sound_flag; + + for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) { + if ((*lsnd)->getType() == kSoundType1) + break; + } + + if (getSoundState() & 1) { + if (!(*lsnd) || getFlags()->flag_3 || (*lsnd && (*lsnd)->getTime() > getSound()->getLoopingSoundDuration())) { + getSound()->playLoopingSound(0x45); + } else { + if (getSound()->getData1() && getSound()->getData2() >= getSound()->getData1()) { + (*lsnd)->update(getSound()->getData0()); + getSound()->setData1(0); + } + } + } + + msnd = NULL; + + for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) { + if ((*lsnd)->getStatus().status2 & 0x1) { // Sound is stopped + // original code + //if ((*lsnd)->soundBuffer) + // Sound_RemoveSoundDataFromCache(*lsnd); + //if ((*lsnd)->archive) { + // Archive_SetStatusNotLoaded((*lsnd)->archive); + // (*lsnd)->archive = 0; + // (*lsnd)->field_28 = 3; + //} + + if (_soundList.size() < 6) { + if ((*lsnd)->getStatus().status1 & 0x1F) { + int pri = (*lsnd)->getPriority() + ((*lsnd)->getStatus().status1 & 0x1F); + + if (pri > maxPriority) { + msnd = *lsnd; + maxPriority = pri; + } + } + } + } + + if (!(*lsnd)->updateSound() && !((*lsnd)->getStatus().status3 & 0x8)) { + if (msnd == *lsnd) { + maxPriority = 0; + msnd = 0; + } + if (*lsnd) { + (*lsnd)->close(); + SAFE_DELETE(*lsnd); + lsnd = _soundList.reverse_erase(lsnd); + } + } + } + + + // We don't need this + //if (msnd) + // msnd->updateEntryInternal(); + + getFlags()->flag_3 = 0; + //--g_sound_flag; } void SoundQueue::resetQueue() { diff --git a/engines/lastexpress/sound/sound.h b/engines/lastexpress/sound/sound.h index 797e52646e..517543f470 100644 --- a/engines/lastexpress/sound/sound.h +++ b/engines/lastexpress/sound/sound.h @@ -64,7 +64,13 @@ public: // Accessors SoundQueue *getQueue() { return _queue; } - uint32 getData2() { return _data2; } + uint32 getData0() { return _data0; } + int32 getData1() { return _data1; } + int32 getData2() { return _data2; } + uint32 getLoopingSoundDuration() { return _loopingSoundDuration; } + + // Setters + void setData1(int32 data) { _data1 = data; } private: LastExpressEngine *_engine; @@ -78,8 +84,8 @@ private: // Unknown data uint32 _data0; - uint32 _data1; - uint32 _data2; + int32 _data1; + int32 _data2; }; } // End of namespace LastExpress -- cgit v1.2.3 From 1a71cd1e21b318bf0fa6903cbe8b0b1993c3a398 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 8 Jul 2011 04:02:45 -0400 Subject: LASTEXPRESS: Fix typo in filter table --- engines/lastexpress/data/snd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index 28d20df9bd..29a81bec75 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -152,7 +152,7 @@ static const int filterData[1424] = { 4224, 4352, 4480, 4608, 4096, 4096, 4096, 4096, 4288, 4416, 4544, 4672, 4096, 4096, 4096, 4096, 4288, 4416, 4544, 4672, 4160, 4160, 4160, 4160, 4352, 4480, 4608, - 4.6, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, + 4736, 4160, 4160, 4160, 4160, 4352, 4480, 4608, 4736, 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4224, 4224, 4224, 4224, 4416, 4544, 4672, 4800, 4288, 4288, 4288, 4288, 4480, 4608, 4736, 4864, 4288, 4288, 4288, -- cgit v1.2.3 From af2bdfcb59a04bb328f702b8af6a89e1104f95bf Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 8 Jul 2011 05:32:05 -0400 Subject: LASTEXPRESS: Replace existing decodeIMA calls by code using our custom set of IMA and step tables --- engines/lastexpress/data/snd.cpp | 75 +++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index 29a81bec75..9e92ded204 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -38,7 +38,7 @@ namespace LastExpress { #pragma region Sound filters tables -static const int filterData[1424] = { +static const int stepTable[1424] = { 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 128, 256, 384, 512, 0, 0, 0, 0, 192, 320, 448, 576, 0, 0, 0, 0, 192, 320, 448, 576, 64, 64, 64, 64, 256, 384, 512, 640, @@ -195,7 +195,7 @@ static const int filterData[1424] = { 5632 }; -static const int filterData2[1424] = { +static const int imaTable[1424] = { 0, 2, 4, 6, 7, 9, 11, 13, 0, -2, -4, -6, -7, -9, -11, -13, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, 1, 3, 5, 7, 10, 12, 14, 16, -1, -3, -5, @@ -362,6 +362,10 @@ public: int readBuffer(int16 *buffer, const int numSamples) { int samples = 0; + // Temporary data + int step = 0; + int sample = 0; + byte idx = 0; assert(numSamples % 2 == 0); @@ -369,15 +373,37 @@ public: if (_blockPos[0] == _blockAlign) { // read block header _status.ima_ch[0].last = _stream->readSint16LE(); - _status.ima_ch[0].stepIndex = _stream->readSint16LE(); + _status.ima_ch[0].stepIndex = _stream->readSint16LE() << 6; _blockPos[0] = 4; + + // Get current filter + _currentFilterId = _nextFilterId; + _nextFilterId = -1; + + // No filter: skip decoding + if (_currentFilterId == -1) + break; + + // Compute step adjustment + _stepAdjust1 = p1s[_currentFilterId]; + _stepAdjust2 = p2s[_currentFilterId]; } for (; samples < numSamples && _blockPos[0] < _blockAlign && !_stream->eos() && _stream->pos() < _endpos; samples += 2) { byte data = _stream->readByte(); _blockPos[0]++; - buffer[samples] = decodeIMA((data >> 4) & 0x0f); - buffer[samples + 1] = decodeIMA(data & 0x0f); + + // First nibble + idx = data >> 4; + step = stepTable[idx + _status.ima_ch[0].stepIndex / 4]; + sample = CLIP(imaTable[idx + _status.ima_ch[0].stepIndex / 4] + _status.ima_ch[0].last, -32767, 32767); + buffer[samples] = (_stepAdjust2 * sample) >> _stepAdjust1; + + // Second nibble + idx = data & 0xF; + _status.ima_ch[0].stepIndex = stepTable[idx + step / 4]; + _status.ima_ch[0].last = CLIP(imaTable[idx + step / 4] + sample, -32767, 32767); + buffer[samples + 1] = (_stepAdjust2 * _status.ima_ch[0].last) >> _stepAdjust1; } } @@ -387,41 +413,10 @@ public: void setFilterId(int32 filterId) { _nextFilterId = filterId; } private: - int32 _currentFilterId; - int32 _nextFilterId; // the sound filter id, -1 for none - - /** - * Sound filter - * - * @param [in] data If non-null, the input data - * @param [in,out] buffer If non-null, the output buffer. - * @param p1 The first filter input. - * @param p2 The second filter input. - */ - static void soundFilter(byte *data, int16 *buffer, int p1, int p2) { - int data1, data2, data1p, data2p; - byte idx; - - data2 = data[0]; - data1 = data[1] << 6; - - data += 2; - - for (int count = 0; count < 735; count++) { - idx = data[count] >> 4; - - data1p = filterData[idx + data1]; - data2p = CLIP(filterData2[idx + data1] + data2, -32767, 32767); - - buffer[2 * count] = (p2 * data2p) >> p1; - - idx = data[count] & 0xF; - - data1 = filterData[idx + data1p]; - data2 = CLIP(filterData2[idx + data1p] + data2p, -32767, 32767); - buffer[2 * count + 1] = (p2 * data2) >> p1; - } - } + int32 _currentFilterId; + int32 _nextFilterId; // the sound filter id, -1 for none + int32 _stepAdjust1; + int32 _stepAdjust2; }; ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 63e2fe7e7bc54f93cf47a5c85d6ca621d332a94a Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 8 Jul 2011 21:28:49 -0400 Subject: LASTEXPRESS: Have LastExpress_ADPCMStream inherit directly from Audio::ADPCMStream (as suggested by clone2727) --- engines/lastexpress/data/snd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index 9e92ded204..6845be8808 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -352,10 +352,10 @@ static const int p2s[17] = { 0, 1, 1, 3, 1, 5, 3, 7, 1, 9, 5, 11, 3, 13, 7, 15, // Last Express ADPCM is similar to MS IMA mono, but inverts its nibbles // and does not have the 4 byte per channel requirement -class LastExpress_ADPCMStream : public Audio::Ima_ADPCMStream { +class LastExpress_ADPCMStream : public Audio::ADPCMStream { public: LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, int32 filterId) : - Audio::Ima_ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) { + Audio::ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) { _currentFilterId = -1; _nextFilterId = filterId; } -- cgit v1.2.3 From e7e689450b942b8328ab25a043a67ae2e392e46e Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 8 Jul 2011 21:32:02 -0400 Subject: LASTEXPRESS: Prefix savegame filenames with "lastexpress" --- engines/lastexpress/game/savegame.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index ebada5dd4e..57c18b5697 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -45,12 +45,12 @@ namespace LastExpress { static const struct { const char *saveFile; } gameInfo[6] = { - {"blue.egg"}, - {"red.egg"}, - {"green.egg"}, - {"purple.egg"}, - {"teal.egg"}, - {"gold.egg"} + {"lastexpress-blue.egg"}, + {"lastexpress-red.egg"}, + {"lastexpress-green.egg"}, + {"lastexpress-purple.egg"}, + {"lastexpress-teal.egg"}, + {"lastexpress-gold.egg"} }; ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From bc298a58f53a9ac2f8e3b5b96da8d7541ad99c71 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Fri, 8 Jul 2011 22:02:24 -0400 Subject: LASTEXPRESS: Simplify SoundQueue::updateQueue() - Remove useless cache code - Use helper function to get the proper sound entry - Fix crash on using an invalid entry --- engines/lastexpress/shared.h | 17 +++---- engines/lastexpress/sound/entry.cpp | 6 +-- engines/lastexpress/sound/queue.cpp | 88 +++++++++---------------------------- engines/lastexpress/sound/sound.cpp | 4 +- 4 files changed, 33 insertions(+), 82 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h index 7b640c773a..d60a498447 100644 --- a/engines/lastexpress/shared.h +++ b/engines/lastexpress/shared.h @@ -84,29 +84,26 @@ enum SoundFlag { }; enum SoundState { - kSoundState0 = 0, - kSoundState1 = 1, - kSoundState2 = 2 + kSoundStateNone = 0, + kSoundState1 = 1, + kSoundState2 = 2 }; enum SoundStatus { + kSoundStatusClear0 = 0x10, + kSoundStatusFilter = 0x1F, kSoundStatus_20 = 0x20, kSoundStatus_40 = 0x40, + kSoundStatusCached = 0x80, kSoundStatus_180 = 0x180, kSoundStatusClosed = 0x200, kSoundStatus_400 = 0x400, - + kSoundStatusClear4 = 0x800, kSoundStatus_8000 = 0x8000, kSoundStatus_20000 = 0x20000, kSoundStatus_100000 = 0x100000, kSoundStatus_20000000 = 0x20000000, kSoundStatus_40000000 = 0x40000000, - - kSoundStatusClear0 = 0x10, - kSoundStatusFilter = 0x1F, - kSoundStatusCached = 0x80, - kSoundStatusClear3 = 0x200, - kSoundStatusClear4 = 0x800, kSoundStatusClearAll = 0xFFFFFFE0 }; diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 87d8ccdb30..44cc68a57b 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -88,8 +88,8 @@ void SoundEntry::close() { _status.status |= kSoundStatusClosed; // Loop until ready - while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) - ; // empty loop body + //while (!(_status.status1 & 4) && !(getSoundQueue()->getFlag() & 8) && (getSoundQueue()->getFlag() & 1)) + // ; // empty loop body // The original game remove the entry from the cache here, // but since we are called from within an iterator loop @@ -290,7 +290,7 @@ bool SoundEntry::updateSound() { } } } - //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer) + //if (status.status2 & 0x40 && !((uint32)_status.status & 0x180) && v1->soundBuffer) // Sound_FillSoundBuffer(v1); } result = true; diff --git a/engines/lastexpress/sound/queue.cpp b/engines/lastexpress/sound/queue.cpp index 0a6442ceed..33b4c06793 100644 --- a/engines/lastexpress/sound/queue.cpp +++ b/engines/lastexpress/sound/queue.cpp @@ -102,80 +102,41 @@ void SoundQueue::removeFromQueue(Common::String filename) { } void SoundQueue::updateQueue() { - //Common::StackLock locker(_mutex); - - //warning("[Sound::updateQueue] Not implemented"); - - int maxPriority = 0; - Common::List::iterator lsnd; - SoundEntry *msnd; - - bool loopedPlaying; - - loopedPlaying = 0; - //++g_sound_flag; + Common::StackLock locker(_mutex); - for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) { - if ((*lsnd)->getType() == kSoundType1) - break; - } + ++_flag; - if (getSoundState() & 1) { - if (!(*lsnd) || getFlags()->flag_3 || (*lsnd && (*lsnd)->getTime() > getSound()->getLoopingSoundDuration())) { + if (getSoundState() & kSoundState1) { + SoundEntry *entry = getEntry(kSoundType1); + if (!entry || getFlags()->flag_3 || (entry && entry->getTime() > getSound()->getLoopingSoundDuration())) { getSound()->playLoopingSound(0x45); } else { if (getSound()->getData1() && getSound()->getData2() >= getSound()->getData1()) { - (*lsnd)->update(getSound()->getData0()); + entry->update(getSound()->getData0()); getSound()->setData1(0); } } } - msnd = NULL; - - for (lsnd = _soundList.begin(); lsnd != _soundList.end(); ++lsnd) { - if ((*lsnd)->getStatus().status2 & 0x1) { // Sound is stopped - // original code - //if ((*lsnd)->soundBuffer) - // Sound_RemoveSoundDataFromCache(*lsnd); - //if ((*lsnd)->archive) { - // Archive_SetStatusNotLoaded((*lsnd)->archive); - // (*lsnd)->archive = 0; - // (*lsnd)->field_28 = 3; - //} - - if (_soundList.size() < 6) { - if ((*lsnd)->getStatus().status1 & 0x1F) { - int pri = (*lsnd)->getPriority() + ((*lsnd)->getStatus().status1 & 0x1F); - - if (pri > maxPriority) { - msnd = *lsnd; - maxPriority = pri; - } - } - } - } + for (Common::List::iterator it = _soundList.begin(); it != _soundList.end(); ++it) { + SoundEntry *entry = *it; - if (!(*lsnd)->updateSound() && !((*lsnd)->getStatus().status3 & 0x8)) { - if (msnd == *lsnd) { - maxPriority = 0; - msnd = 0; - } - if (*lsnd) { - (*lsnd)->close(); - SAFE_DELETE(*lsnd); - lsnd = _soundList.reverse_erase(lsnd); - } + // Original removes the entry data from the cache and sets the archive as not loaded + // and if the sound data buffer is not full, loads a new entry to be played based on + // its priority and filter id + + if (!entry->updateSound() && !(entry->getStatus().status3 & 0x8)) { + entry->close(); + SAFE_DELETE(entry); + it = _soundList.reverse_erase(it); } } - - // We don't need this - //if (msnd) - // msnd->updateEntryInternal(); + // Original update the current entry, loading another set of samples to be decoded getFlags()->flag_3 = 0; - //--g_sound_flag; + + --_flag; } void SoundQueue::resetQueue() { @@ -209,17 +170,10 @@ void SoundQueue::resetQueue(SoundType type1, SoundType type2) { } void SoundQueue::clearQueue() { - _flag |= 4; - - // FIXME: Wait a while for a flag to be set - //for (int i = 0; i < 3000000; i++) - // if (_flag & 8) - // break; + Common::StackLock locker(_mutex); _flag |= 8; - Common::StackLock locker(_mutex); - for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) { SoundEntry *entry = (*i); @@ -240,7 +194,7 @@ void SoundQueue::clearStatus() { Common::StackLock locker(_mutex); for (Common::List::iterator i = _soundList.begin(); i != _soundList.end(); ++i) - (*i)->setStatus((*i)->getStatus().status | kSoundStatusClear3); + (*i)->setStatus((*i)->getStatus().status | kSoundStatusClosed); } ////////////////////////////////////////////////////////////////////////// diff --git a/engines/lastexpress/sound/sound.cpp b/engines/lastexpress/sound/sound.cpp index c04b6d361f..2f7bb4a601 100644 --- a/engines/lastexpress/sound/sound.cpp +++ b/engines/lastexpress/sound/sound.cpp @@ -1305,8 +1305,8 @@ void SoundManager::playLoopingSound(int param) { int partNumber = 1; int fnameLen = 6; - if (_queue->getSoundState() & 1 && param >= 0x45 && param <= 0x46) { - if (_queue->getSoundState() & 2) { + if (_queue->getSoundState() & kSoundState1 && param >= 0x45 && param <= 0x46) { + if (_queue->getSoundState() & kSoundState2) { strcpy(tmp, "STEAM.SND"); _loopingSoundDuration = 32767; -- cgit v1.2.3