MIDI music is now paused by pausing the parser(s) instead of relying on the
mixer streams to stop providing callbacks. This gives more consistent behavior
as external MIDI devices or softsynths now also pause playback.
Muting sound now sets the volume to 0 instead of pausing playback.
This updates the Simon 1 DOS AdLib driver and adds an AdLib driver for Windows.
The DOS driver now has OPL3 support, which eliminates the note cut off that
frequently occurs on an OPL2. It also allows for some limited use of stereo.
The driver now plays the floppy SFX accurately compared to the original
interpreter. It also implements multisource functionality, allowing for
separate volume control for music and SFX for the floppy version.
The Windows driver just maps the MT-32 instruments of the Simon 1 MIDI data to
the equivalent GM instruments.
This commit adds MIDI parser subclasses for the Simon 1 GMF format and for the
SMF variant used by the Windows versions of Simon 1 and 2.
The GMF format was handled by the SMF parser, which can now be removed from
that class. It also fixes the tempos not matching the DOS interpreter.
The Simon Windows SMF variant was handled in the AGOS midi class. Moving it to
a separate parser allows for some cleaner code in that class. It now also
corrects the tempos to match those of the DOS interpreter.
This adds support for the OPL rhythm mode to the AdLib multisource MIDI driver.
Some games (f.e. Simon 1) use this to generate the rhythm sounds of their music.
Regression caused by 70d1dbb00f.
This change will break the inventory changes done for DW3, and will
need to be fixed accordingly for it.
DW3 has two new fields in its INV_OBJECT struct. However, there are
variables in the code that are cast from memory blobs, so adding
these new fields breaks DW1 and DW2. We'll either need to add a new
structure for DW3, or read the struct members individually instead of
casting the memory blobs to this struct.
This behaves closer to how free() and delete works, in that it's a no-op
for nullptr. Also to be slightly safer, it will set the pointer to nullptr
afterwards.
The application is slightly indiscriminate, so a few extra nullptr
writes are added, even where the pointer would be immediately assigned
a new value afterwards.