#include <rsound.h>
Public Member Functions | |
| RSound (Audio::Mixer *mixer, const Common::Path &filename, int dataOffset, int dataSize, int sysExOffset) | |
| int | stop () override |
| int | poll () override |
| void | noise () override |
| void | setVolume (int volume) override |
| int | getFrameCounter () |
Public Member Functions inherited from MADS::SoundDriver | |
| SoundDriver (Audio::Mixer *mixer, const Common::Path &filename, int dataOffset, int dataSize) | |
| virtual int | command (int commandId, int param)=0 |
Static Public Member Functions | |
| static void | validate () |
Public Attributes | |
| Channel | _channels [9] |
| int | _frameCounter |
| bool | _isDisabled |
| int | _pollResult |
Protected Member Functions | |
| byte * | loadData (int offset) |
| void | resetChannelRange (int first, int last) |
| virtual void | checkRandomAmbianceTrigger () |
| void | resultCheck () |
| virtual bool | callFunction (uint16 targetOffset) |
| Channel * | playSound (int offset) |
| Channel * | playSoundChannels1To5 (int offset) |
| Channel * | playSoundAny (int offset) |
| Channel * | playSoundChannels5To8 (int offset) |
| Channel * | playSoundChannels1To6 (int offset) |
| Channel * | playSoundData (byte *pData, int startingChannel, int freeScanEnd, int fallbackScanEnd) |
| bool | isSoundActive (byte *pData) |
| int | getRandomNumber () |
| void | sendNoteOn (int midiChannel, int note, int velocity) |
| void | sendProgramChange (int midiChannel, int program) |
| void | sendVolume (int midiChannel, int volume) |
| void | sendVolumeCC (int midiChannel, int volume) |
| void | resetPitchBend (int midiChannel) |
| void | sendPitchBend (int midiChannel, int value) |
| void | sendPan (int midiChannel, int value) |
| void | muteChannel (int midiChannel) |
| void | sendGmReset (int count) |
| const byte * | sendSysExData (const byte *pData, uint maxLength) |
| const byte * | sendSysEx (int offset) |
| void | sendSysExSequence () |
| void | restorePatchMemory () |
| void | sendReverbSysEx (int mode, int time, int level) |
| void | onTimer () |
| void | noOpHandler (int param) |
| virtual int | command0 () |
| int | command1 () |
| int | command2 () |
| int | command3 () |
| void | enableUpperChannels () |
| void | resetAndGmResetUpperChannels () |
| virtual int | command4 ()=0 |
| virtual int | command5 ()=0 |
| int | command6 () |
| int | command7 () |
| int | command8 () |
| int | nullCommand () |
Protected Member Functions inherited from MADS::SoundDriver | |
| Common::MemoryReadStream | getDataStream (int offset) const |
| SoundDriver (Audio::Mixer *mixer) | |
Static Protected Member Functions | |
| static void | timerCallback (void *data) |
Protected Attributes | |
| int | _commandParam |
| int | _randomAmbianceTriggerFlag |
| int | _fadeCheckPeriod |
Protected Attributes inherited from MADS::SoundDriver | |
| Audio::Mixer * | _mixer |
| Common::Array< byte > | _soundData |
| Common::Mutex | _driverMutex |
Base class for the Return of the Phantom MT-32 / MPU-401 sound player resource files (rsound.ph1-.ph9). Mirrors the structure of the Rex Nebular RSound family (see nebular/rsound.h), adapted for this game's substantially richer Channel_pollActive script VM (~65 opcodes here vs. ~15 in Rex Nebular): general arithmetic on a script-variable table, conditional branches, and a call/return pair, in addition to the shared note/fade/loop mechanics.
NOTE: DOS-specific driver ceremony from the original (timer IRQ hooking, MPU-401 hardware detection/reset, PIT-based SysEx delay calibration, the system-clock save/restore around it) has no ScummVM equivalent and is not ported - matching how Rex Nebular's RSound skips the same kind of hardware-detection dance.
| MADS::Phantom::Sound::RSound::RSound | ( | Audio::Mixer * | mixer, |
| const Common::Path & | filename, | ||
| int | dataOffset, | ||
| int | dataSize, | ||
| int | sysExOffset | ||
| ) |
Constructor
| mixer | Mixer |
| filename | Specifies the Roland sound player file to use |
| dataOffset | Offset in the file of the data segment |
| dataSize | Size of the data segment |
| sysExOffset | Offset of this driver's own command0_array |
|
protected |
Zeroes _activeCount/_pitchBendFadeStep/_volumeFadeStep/_panFadeStep for channels [first, last] (0-based indices). Protected (not private) so per-driver command4()/command5() overrides that need a narrower or differently-shaped reset than resetChannels4to9() / resetAndGmResetUpperChannels() below can call it directly - e.g. RSound3's command4(), confirmed to reset only channels 5-9 (indices 4-8), not 4-9.
|
inlineprotectedvirtual |
Hook called once per update() frame after the disabled check. Only drivers with a random-ambiance/music picker (e.g. RSound1's command16) override this; every other driver leaves it a no-op. Confirmed shape: if _randomAmbianceTriggerFlag == 0xFF, clear it and fire the driver-specific picker.
|
inlineprotectedvirtual |
Handles a native C4 callback target embedded in a sequence. Controllers override this only for statically identified native targets; the default remains a fatal rejection in the bytecode interpreter.
|
protected |
Plays the specified sound, using any free channel from 6 to 8. Matches the disassembly's playSound exactly (rsound_channel6-8).
|
protected |
Plays the specified sound, using any free channel from 1 to 5. NOTE: unlike Rex Nebular's playSoundAny() (which reaches all 9 channels), THIS driver's playSoundAny only scans channels 1-5 for a free slot - confirmed directly from the disassembly. Also confirmed: the pending-stop fallback scan only reaches down to channel 4, NOT channel 5 - a genuine asymmetry preserved exactly (channel 5 can never be pre-empted by this call, only picked while free).
|
protected |
Plays the specified sound, using any free channel from 1 to 8 (everything except channel 9) - a third, distinct scan range from playSound() and playSoundAny() above.
|
protected |
Plays the specified sound, using any free channel from 5 to 8. Matches playChannels5to8 in the disassembly - a fourth, distinct scan range (symmetric free/fallback scan, unlike playSoundAny()'s asymmetry, and one channel narrower than playSoundAny()'s 1-8).
|
protected |
Plays the specified sound, using any free channel from 1 to 6. Matches playSoundChannels1to6 in the disassembly - a fifth, distinct scan range (symmetric free/fallback scan).
|
protected |
Scans [startingChannel, freeScanEnd] for a free channel; if none found, scans [startingChannel, fallbackScanEnd] in reverse for a pending-stop channel to pre-empt. The two end bounds are usually the same, but playSoundAny() is a confirmed exception (see above).
|
protected |
Checks whether the given block of data is already loaded into a channel.
|
protected |
Sends the GM-reset Control Change sequence (all notes off, reset all controllers, volume=100, pan=center) to count MIDI channels, counting down from count to 1.
|
protected |
Sends a single Roland DT1-style SysEx message from a raw buffer: the fixed header, then bytes from pData up to (not including) a 0xFF terminator - each byte sent and folded into a running checksum - then the checksum byte and a closing F7. The shared core of sendSysEx()/sendReverbSysEx() below - split out so hardcoded protocol buffers (not driver-specific loaded sound data) can be sent without going through loadData(). Returns a pointer to the terminating 0xFF byte (matching the disassembly's own si register value on return), so callers walking a sequence of consecutive messages can advance past it to find the next one. Returns nullptr when no terminator occurs within maxLength bytes.
|
protected |
sendSysExData() for a block already in this driver's own loaded sound data.
|
protected |
Matches sendSysExSequence: repeatedly calls sendSysEx(), starting from this driver's own command0_array (_sysExOffset) and advancing past each message's terminating 0xFF to the start of the next one, until an empty message (two consecutive 0xFF bytes) marks the end of the table. Called once from the constructor (matching initDeviceOnce) - the disassembly's _deviceInitialized guard flag isn't needed since nothing else ever calls this again.
|
protected |
Restore all 128 MT-32 Patch Memory records to the standard A/B timbre mapping. Native export 2 calls this during driver teardown, after stopping playback. All checked Phantom retail and demo overlays use the same four-block, 32-record structure.
ScummVM does not call the DOS hardware teardown path: opening each MidiDriver_MT32GM resets the selected device, while closing follows the shared MIDI-driver lifecycle. Keep the exact native translation available without imposing its synchronous teardown sequence.
|
protected |
CONFIRMED: masks the 3 caller-supplied values to 2/3/3 bits (mode 0-3, time 0-7, level 0-7) and sends them via the real Roland MT-32 System Area Reverb SysEx address (10 00 01h), hardcoded here rather than read via loadData(), since it's a fixed hardware protocol address, not driver-specific sound data.
|
inlineprotected |
A confirmed no-op (reads one operand, does nothing with it).
|
protected |
Shared tail of command1() (falls through into it after command3()) and command5() (jumps straight into it, ungated, in every driver confirmed so far): enables channels 5,6,7,8.
|
protected |
Shared tail of command4() in every driver confirmed so far: resetChannels4to9() + sendGmReset(9).
|
protectedpure virtual |
PURE VIRTUAL, unlike command1-3/6-8. Confirmed (from RSound1 AND RSound2, independently) that every driver's command4/command5 are gated by isSoundActive() on a driver-specific data offset before calling resetAndGmResetUpperChannels()/enableUpperChannels() above
Implemented in MADS::Phantom::Sound::RSoundDemo.
|
static |
Validates the presence of the sound driver files.
|
overridevirtual |
Stop all currently playing sounds
Implements MADS::SoundDriver.
|
overridevirtual |
Main poll method to allow sounds to progress
Implements MADS::SoundDriver.
|
inlineoverridevirtual |
General noise/note output
Implements MADS::SoundDriver.
|
overridevirtual |
Set the volume
Implements MADS::SoundDriver.
|
protected |
Cleared to 0 by RSound1's command37 (a "cancel any pending random-ambiance trigger" side effect of playing that specific sound). CONFIRMED: the only code that ever sets it to 0xFF (arming checkRandomAmbianceTrigger()) is itself unreachable/dead code - so in the real game this mechanism never actually fires. Implemented faithfully anyway in case that changes for a different driver. Protected (not private) so driver subclasses with their own commands touching it (like RSound1's command37) can reach it directly.
|
protected |
Half-rate fade-check period reload value (see _fadeCheckCounter above). Protected (not private) so per-driver command1()/command3()/ command5() overrides that need to arm it directly (matching an inline "mov cs:_fadeCheckPeriod, 1" in the disassembly, e.g. RSound5's driver-specific 6-channel command3() and 3-channel enableChannels678()) can do so without going through the base class's own command3()/enableUpperChannels().