[Scummvm-git-logs] scummvm master -> 56e3c89ac5a7193e135a0d00397cd76ddc3c9653
dreammaster
noreply at scummvm.org
Sun Jul 26 10:21:52 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
56e3c89ac5 MADS: NEBULAR: Implemented RSound5 and RSound6
Commit: 56e3c89ac5a7193e135a0d00397cd76ddc3c9653
https://github.com/scummvm/scummvm/commit/56e3c89ac5a7193e135a0d00397cd76ddc3c9653
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-07-26T20:20:25+10:00
Commit Message:
MADS: NEBULAR: Implemented RSound5 and RSound6
Assisted-by: Claude Code:claude-opus-4.8
Changed paths:
engines/mads/nebular/rsound_nebular.cpp
engines/mads/nebular/rsound_nebular.h
diff --git a/engines/mads/nebular/rsound_nebular.cpp b/engines/mads/nebular/rsound_nebular.cpp
index 2aada741147..bbd1e74e7c8 100644
--- a/engines/mads/nebular/rsound_nebular.cpp
+++ b/engines/mads/nebular/rsound_nebular.cpp
@@ -1030,9 +1030,8 @@ const RSound4::CommandPtr RSound4::_commandList[60] = {
&RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand,
&RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand,
&RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand, &RSound4::nullCommand,
- &RSound4::nullCommand, &RSound4::nullCommand, &RSound4::command52, &RSound4::command53,
- &RSound4::command54, &RSound4::command55, &RSound4::command56, &RSound4::command57,
- &RSound4::command58, &RSound4::command59
+ &RSound4::command52, &RSound4::command53, &RSound4::command54, &RSound4::command55,
+ &RSound4::command56, &RSound4::command57, &RSound4::command58, &RSound4::command59
};
RSound4::RSound4(Audio::Mixer *mixer) : RSound(mixer, "rsound.004", 0x1340, 0x2E20) {
@@ -1231,6 +1230,392 @@ int RSound4::command59() {
/*-----------------------------------------------------------------------*/
+const RSound5::CommandPtr RSound5::_commandList[42] = {
+ &RSound5::command0, &RSound5::command1, &RSound5::command2, &RSound5::command3,
+ &RSound5::command4, &RSound5::command5, &RSound5::command6, &RSound5::command7,
+ &RSound5::command8, &RSound5::command9, &RSound5::command10, &RSound5::command11x24,
+ &RSound5::command12x25, &RSound5::command13, &RSound5::command14, &RSound5::command15,
+ &RSound5::command16, &RSound5::command17, &RSound5::command18, &RSound5::command19,
+ &RSound5::command20, &RSound5::command21, &RSound5::command22, &RSound5::command23,
+ &RSound5::command11x24, &RSound5::command12x25, &RSound5::command26, &RSound5::command27,
+ &RSound5::command28, &RSound5::command29, &RSound5::command30, &RSound5::command31,
+ &RSound5::command32, &RSound5::command33, &RSound5::command34, &RSound5::command35,
+ &RSound5::command36, &RSound5::command37, &RSound5::command38, &RSound5::command39,
+ &RSound5::command40, &RSound5::command41
+};
+
+RSound5::RSound5(Audio::Mixer *mixer) : RSound(mixer, "rsound.005", 0x12A0, 0x1FD0) {
+}
+
+int RSound5::command(int commandId, int param) {
+ if (commandId > 41)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+int RSound5::command9() {
+ playSound(0x11C4);
+ return 0;
+}
+
+int RSound5::command10() {
+ playSound(0x1238);
+ return 0;
+}
+
+int RSound5::command11x24() {
+ playSound(0x1196);
+ return 0;
+}
+
+int RSound5::command12x25() {
+ playSound(0x1242);
+ return 0;
+}
+
+int RSound5::command13() {
+ playSound(0x125E);
+ playSound(0x1268);
+ return 0;
+}
+
+int RSound5::command14() {
+ _channels[7].load(loadData(0x1272));
+ return 0;
+}
+
+int RSound5::command15() {
+ if (_channels[7]._soundData == loadData(0x1272)) {
+ byte *pData = loadData(0x1288);
+ _channels[7]._innerLoopPtr = pData;
+ _channels[7]._outerLoopPtr = pData;
+ _channels[7]._activeCount = 1;
+ }
+ return 0;
+}
+
+int RSound5::command16() {
+ playSound(0x129A);
+ playSound(0x129A);
+ playSound(0x129A);
+ playSound(0x129A);
+ return 0;
+}
+
+int RSound5::command17() {
+ playSound(0x11B4);
+ return 0;
+}
+
+int RSound5::command18() {
+ playSound(0x12E4);
+ playSound(0x12F6);
+ playSound(0x1308);
+ playSound(0x131A);
+ return 0;
+}
+
+int RSound5::command19() {
+ playSound(0x132C);
+ return 0;
+}
+
+int RSound5::command20() {
+ playSound(0x1368);
+ return 0;
+}
+
+int RSound5::command21() {
+ playSound(0x1388);
+ return 0;
+}
+
+int RSound5::command22() {
+ playSound(0x139A);
+ return 0;
+}
+
+int RSound5::command23() {
+ playSound(0x13AA);
+ playSound(0x13AA);
+ playSound(0x13AA);
+ playSound(0x13AA);
+ return 0;
+}
+
+int RSound5::command26() {
+ playSound(0x13D6);
+ return 0;
+}
+
+int RSound5::command27() {
+ playSound(0x13F0);
+ return 0;
+}
+
+int RSound5::command28() {
+ playSound(0x121C);
+ return 0;
+}
+
+void RSound5::loadTailChannels() {
+ _channels[3].load(loadData(0x1688));
+ _channels[8].load(loadData(0x1882));
+}
+
+int RSound5::command29() {
+ byte *pData = loadData(0x1488);
+ if (!isSoundActive(pData)) {
+ command1();
+ _channels[0].load(pData);
+ _channels[1].load(loadData(0x1534));
+ _channels[2].load(loadData(0x15EA));
+ loadTailChannels();
+ }
+ return 0;
+}
+
+int RSound5::command30() {
+ playSound(0x1212);
+ playSound(0x1208);
+ return 0;
+}
+
+int RSound5::command31() {
+ playSound(0x140A);
+ return 0;
+}
+
+int RSound5::command32() {
+ playSound(0x11D0);
+ return 0;
+}
+
+int RSound5::command33() {
+ playSound(0x11DC);
+ return 0;
+}
+
+int RSound5::command34() {
+ playSound(0x11E6);
+ return 0;
+}
+
+int RSound5::command35() {
+ playSound(0x11F6);
+ return 0;
+}
+
+int RSound5::command36() {
+ playSound(0x1464);
+ playSound(0x1478);
+ return 0;
+}
+
+int RSound5::command37() {
+ playSound(0x122A);
+ return 0;
+}
+
+int RSound5::command38() {
+ _channels[4]._pSrc = loadData(0x1182);
+ loadTailChannels();
+ return 0;
+}
+
+int RSound5::command39() {
+ playSound(0x141E);
+ playSound(0x1428);
+ return 0;
+}
+
+int RSound5::command40() {
+ playSound(0x1432);
+ return 0;
+}
+
+int RSound5::command41() {
+ _channels[8]._pSrc = loadData(0x1182);
+ _channels[3].load(loadData(0x1BB6));
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+const RSound6::CommandPtr RSound6::_commandList[30] = {
+ &RSound6::command0, &RSound6::command1, &RSound6::command2, &RSound6::command3,
+ &RSound6::command4, &RSound6::command5, &RSound6::command6, &RSound6::command7,
+ &RSound6::command8, &RSound6::command9, &RSound6::command10, &RSound6::command11,
+ &RSound6::command12, &RSound6::command13x14, &RSound6::command13x14, &RSound6::command15,
+ &RSound6::command16, &RSound6::command17, &RSound6::command18, &RSound6::command19,
+ &RSound6::command20, &RSound6::command21, &RSound6::command22, &RSound6::command23,
+ &RSound6::command24, &RSound6::command25, &RSound6::nullCommand, &RSound6::nullCommand,
+ &RSound6::nullCommand, &RSound6::command28
+};
+
+RSound6::RSound6(Audio::Mixer *mixer) : RSound(mixer, "rsound.006", 0x12D0, 0x1EF0) {
+}
+
+int RSound6::command(int commandId, int param) {
+ if (commandId > 29)
+ return 0;
+
+ _commandParam = param;
+ _frameCounter = 0;
+ return (this->*_commandList[commandId])();
+}
+
+void RSound6::tickCallback() {
+ if (!_callbackPeriod)
+ return;
+ if (--_callbackCounter)
+ return;
+
+ _callbackCounter = _callbackPeriod;
+ if (_callbackFnPtr)
+ (this->*_callbackFnPtr)();
+}
+
+void RSound6::reloadCommand24() {
+ _callbackFnPtr = nullptr;
+ command1();
+ _callbackCounter = 84;
+ _callbackPeriod = 84;
+ _channels[0].load(loadData(0x1A38));
+ _channels[1].load(loadData(0x1BBE));
+ _channels[8].load(loadData(0x1B90));
+}
+
+void RSound6::reloadCommand28() {
+ _callbackFnPtr = nullptr;
+ command1();
+ _callbackCounter = 84;
+ _callbackPeriod = 84;
+ _channels[0].load(loadData(0x130A));
+ _channels[1].load(loadData(0x13B6));
+ _channels[2].load(loadData(0x146C));
+ _channels[3].load(loadData(0x150A));
+ _channels[8].load(loadData(0x1704));
+}
+
+int RSound6::command9() {
+ playSound(0x111C);
+ return 0;
+}
+
+int RSound6::command10() {
+ playSound(0x1190);
+ return 0;
+}
+
+int RSound6::command11() {
+ playSound(0x11A4);
+ playSound(0x11A4);
+ playSound(0x11A4);
+ playSound(0x11A4);
+ return 0;
+}
+
+int RSound6::command12() {
+ playSound(0x11C8);
+ return 0;
+}
+
+int RSound6::command13x14() {
+ playSound(0x11E8);
+ return 0;
+}
+
+int RSound6::command15() {
+ playSound(0x11F2);
+ playSound(0x11F2);
+ playSound(0x11F2);
+ playSound(0x11F2);
+ return 0;
+}
+
+int RSound6::command16() {
+ playSound(0x121E);
+ return 0;
+}
+
+int RSound6::command17() {
+ playSound(0x1228);
+ playSound(0x1228);
+ playSound(0x1228);
+ playSound(0x1228);
+ return 0;
+}
+
+int RSound6::command18() {
+ playSound(0x1254);
+ return 0;
+}
+
+int RSound6::command19() {
+ playSound(0x1266);
+ return 0;
+}
+
+int RSound6::command20() {
+ playSound(0x1278);
+ return 0;
+}
+
+int RSound6::command21() {
+ _channels[4].load(loadData(0x1282));
+ playSound(0x1282);
+ playSound(0x1282);
+ playSound(0x12AA);
+ return 0;
+}
+
+int RSound6::command22() {
+ _channels[4].load(loadData(0x12CE));
+ _channels[5].load(loadData(0x12CE));
+ _channels[6].load(loadData(0x12CE));
+ _channels[7].load(loadData(0x12CE));
+ return 0;
+}
+
+int RSound6::command23() {
+ playSound(0x1174);
+ return 0;
+}
+
+int RSound6::command24() {
+ if (_channels[0]._activeCount && _channels[0]._soundData == loadData(0x130A)) {
+ _callbackFnPtr = &RSound6::reloadCommand24;
+ return 0;
+ }
+
+ reloadCommand24();
+ return 0;
+}
+
+int RSound6::command25() {
+ _channels[4].load(loadData(0x12FE));
+ return 0;
+}
+
+int RSound6::command28() {
+ if (isSoundActive(loadData(0x130A)))
+ return 0;
+
+ if (_channels[0]._activeCount && _channels[0]._soundData == loadData(0x1A38)) {
+ _callbackFnPtr = &RSound6::reloadCommand28;
+ return 0;
+ }
+
+ reloadCommand28();
+ return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
const RSound9::CommandPtr RSound9::_commandList[52] = {
&RSound9::command0, &RSound9::command1, &RSound9::command2, &RSound9::command3,
&RSound9::command4, &RSound9::command5, &RSound9::command6, &RSound9::command7,
diff --git a/engines/mads/nebular/rsound_nebular.h b/engines/mads/nebular/rsound_nebular.h
index 468c0cedcdf..b84a5b9d1f4 100644
--- a/engines/mads/nebular/rsound_nebular.h
+++ b/engines/mads/nebular/rsound_nebular.h
@@ -370,6 +370,107 @@ public:
int command(int commandId, int param) override;
};
+class RSound5 : public RSound {
+private:
+ typedef int (RSound5:: *CommandPtr)();
+ static const CommandPtr _commandList[42];
+
+ /**
+ * loc_1093A in the disassembly - shared tail of command29 and
+ * command38, loading channels 4 and 9 (1-based; indices 3 and 8).
+ */
+ void loadTailChannels();
+
+ int command9();
+ int command10();
+ int command11x24();
+ int command12x25();
+ int command13();
+ int command14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command26();
+ int command27();
+ int command28();
+ int command29();
+ int command30();
+ int command31();
+ int command32();
+ int command33();
+ int command34();
+ int command35();
+ int command36();
+ int command37();
+ int command38();
+ int command39();
+ int command40();
+ int command41();
+public:
+ RSound5(Audio::Mixer *mixer);
+
+ int command(int commandId, int param) override;
+};
+
+class RSound6 : public RSound {
+private:
+ typedef int (RSound6:: *CommandPtr)();
+ static const CommandPtr _commandList[30];
+
+ /**
+ * Confirmed via rsound_update's own body (its checkCallback-equivalent
+ * is inlined directly rather than factored into a separate function
+ * like RSound4's checkCallback()): word_121B6 is the reload period,
+ * word_121B4 the countdown, and word_121B8 a genuine CODE pointer
+ * ("call bx" - not sound data) invoked once the countdown reaches 0.
+ * Matches RSound4's mechanism exactly in shape.
+ */
+ typedef void (RSound6:: *CallbackFunction)();
+ int _callbackCounter = 0;
+ int _callbackPeriod = 0;
+ CallbackFunction _callbackFnPtr = nullptr;
+
+ void tickCallback() override;
+
+ /**
+ * loc_109BA / loc_10968 in the disassembly - command24/command28's
+ * own full-reload bodies. When channel 1 is currently playing the
+ * OTHER command's theme, that command doesn't interrupt it
+ * immediately - it just points _callbackFnPtr at this same reload
+ * logic so the switch happens on the next callback tick instead.
+ */
+ void reloadCommand24();
+ void reloadCommand28();
+
+ int command9();
+ int command10();
+ int command11();
+ int command12();
+ int command13x14();
+ int command15();
+ int command16();
+ int command17();
+ int command18();
+ int command19();
+ int command20();
+ int command21();
+ int command22();
+ int command23();
+ int command24();
+ int command25();
+ int command28();
+public:
+ RSound6(Audio::Mixer *mixer);
+
+ int command(int commandId, int param) override;
+};
+
class RSound9 : public RSound {
private:
/**
More information about the Scummvm-git-logs
mailing list