[Scummvm-git-logs] scummvm master -> a295fa5a0b7d6b46584d71b2a746d3b5536dc692
neuromancer
noreply at scummvm.org
Mon May 4 21:34:55 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
112d158f16 FREESCAPE: Add a common base class for the music players
a295fa5a0b FREESCAPE: Refactor Atari music code to be independent of the YM2149 implementation
Commit: 112d158f16d12ba4df0b8690ec5536fa81a896f2
https://github.com/scummvm/scummvm/commit/112d158f16d12ba4df0b8690ec5536fa81a896f2
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-05-04T23:34:51+02:00
Commit Message:
FREESCAPE: Add a common base class for the music players
Changed paths:
A engines/freescape/music.h
engines/freescape/games/dark/c64.cpp
engines/freescape/games/dark/c64.music.h
engines/freescape/games/dark/dark.cpp
engines/freescape/games/dark/dark.h
engines/freescape/games/driller/c64.cpp
engines/freescape/games/driller/c64.music.cpp
engines/freescape/games/driller/c64.music.h
engines/freescape/games/driller/driller.cpp
engines/freescape/games/driller/driller.h
engines/freescape/games/eclipse/ay.music.h
engines/freescape/games/eclipse/c64.cpp
engines/freescape/games/eclipse/c64.music.cpp
engines/freescape/games/eclipse/c64.music.h
engines/freescape/games/eclipse/cpc.cpp
engines/freescape/games/eclipse/dos.cpp
engines/freescape/games/eclipse/eclipse.cpp
engines/freescape/games/eclipse/eclipse.h
engines/freescape/games/eclipse/opl.music.h
engines/freescape/games/eclipse/zx.cpp
diff --git a/engines/freescape/games/dark/c64.cpp b/engines/freescape/games/dark/c64.cpp
index 6b882b15fd4..25acf870909 100644
--- a/engines/freescape/games/dark/c64.cpp
+++ b/engines/freescape/games/dark/c64.cpp
@@ -350,7 +350,7 @@ void DarkEngine::loadAssetsC64FullGame() {
// the active player's SID is created.
_playerC64Sfx = new DarkSideC64SFXPlayer();
_playerC64Sfx->destroySID();
- _playerC64Music = new DarkSideC64MusicPlayer();
+ _playerMusic = new DarkSideC64MusicPlayer();
}
void DarkEngine::playSoundC64(int index) {
@@ -363,14 +363,12 @@ void DarkEngine::toggleC64Sound() {
if (_c64UseSFX) {
if (_playerC64Sfx)
_playerC64Sfx->destroySID();
- if (_playerC64Music) {
- _playerC64Music->initSID();
- _playerC64Music->startMusic();
- }
+ if (_playerMusic)
+ _playerMusic->startMusic();
_c64UseSFX = false;
} else {
- if (_playerC64Music)
- _playerC64Music->destroySID();
+ if (_playerMusic)
+ _playerMusic->stopMusic();
if (_playerC64Sfx)
_playerC64Sfx->initSID();
_c64UseSFX = true;
diff --git a/engines/freescape/games/dark/c64.music.h b/engines/freescape/games/dark/c64.music.h
index 19d61343e6b..af5e2fa6493 100644
--- a/engines/freescape/games/dark/c64.music.h
+++ b/engines/freescape/games/dark/c64.music.h
@@ -23,21 +23,20 @@
#define FREESCAPE_DARK_C64_MUSIC_H
#include "audio/sid.h"
+#include "freescape/music.h"
namespace Freescape {
// 3-channel SID music player for Dark Side C64.
// Implements the Wally Beben byte-stream sequencer from darkside.prg ($0901).
-class DarkSideC64MusicPlayer {
+class DarkSideC64MusicPlayer : public MusicPlayer {
public:
DarkSideC64MusicPlayer();
~DarkSideC64MusicPlayer();
- void startMusic();
- void stopMusic();
- bool isPlaying() const;
- void initSID();
- void destroySID();
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
private:
SID::SID *_sid;
@@ -67,6 +66,9 @@ private:
uint8 readPatByte(int ch);
+ void initSID();
+ void destroySID();
+
// Global state
bool _musicActive;
uint8 _speedDiv; // $15A1: speed divider
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index b8d3988e021..e38695c5419 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -35,7 +35,7 @@ namespace Freescape {
DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEngine(syst, gd) {
_playerC64Sfx = nullptr;
- _playerC64Music = nullptr;
+ _playerMusic = nullptr;
_c64UseSFX = false;
_c64CompassInitialized = false;
_c64CompassPosition = 0;
@@ -106,7 +106,7 @@ DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEn
DarkEngine::~DarkEngine() {
delete _playerC64Sfx;
- delete _playerC64Music;
+ delete _playerMusic;
for (auto &indicator : _cpcIndicators) {
indicator->free();
@@ -348,8 +348,8 @@ void DarkEngine::initGameState() {
}
}
- if (isC64() && _playerC64Music)
- _playerC64Music->startMusic();
+ if (isC64() && _playerMusic)
+ _playerMusic->startMusic();
}
void DarkEngine::loadAssets() {
diff --git a/engines/freescape/games/dark/dark.h b/engines/freescape/games/dark/dark.h
index e60926e1522..e16193463ff 100644
--- a/engines/freescape/games/dark/dark.h
+++ b/engines/freescape/games/dark/dark.h
@@ -21,6 +21,7 @@
#include "audio/mixer.h"
#include "common/array.h"
+#include "freescape/music.h"
#include "freescape/games/dark/c64.music.h"
#include "freescape/games/dark/c64.sfx.h"
@@ -143,7 +144,7 @@ public:
Audio::SoundHandle _soundFxHandleJetpack;
DarkSideC64SFXPlayer *_playerC64Sfx;
- DarkSideC64MusicPlayer *_playerC64Music;
+ MusicPlayer *_playerMusic;
bool _c64UseSFX;
bool _c64CompassInitialized;
int _c64CompassPosition;
diff --git a/engines/freescape/games/driller/c64.cpp b/engines/freescape/games/driller/c64.cpp
index 0af0b4588e3..8f2bfd36c87 100644
--- a/engines/freescape/games/driller/c64.cpp
+++ b/engines/freescape/games/driller/c64.cpp
@@ -163,7 +163,7 @@ void DrillerEngine::loadAssetsC64FullGame() {
// the active player's SID is created.
_playerC64Sfx = new DrillerC64SFXPlayer();
_playerC64Sfx->destroySID();
- _playerSid = new DrillerSIDPlayer();
+ _playerMusic = new DrillerSIDPlayer();
// C64 SFX index mapping
// Based on analysis of the C64 binary SFX routines
@@ -195,14 +195,12 @@ void DrillerEngine::toggleC64Sound() {
if (_c64UseSFX) {
if (_playerC64Sfx)
_playerC64Sfx->destroySID();
- if (_playerSid) {
- _playerSid->initSID();
- _playerSid->startMusic();
- }
+ if (_playerMusic)
+ _playerMusic->startMusic();
_c64UseSFX = false;
} else {
- if (_playerSid)
- _playerSid->destroySID();
+ if (_playerMusic)
+ _playerMusic->stopMusic();
if (_playerC64Sfx)
_playerC64Sfx->initSID();
_c64UseSFX = true;
diff --git a/engines/freescape/games/driller/c64.music.cpp b/engines/freescape/games/driller/c64.music.cpp
index e595f713eb8..02c364f2dda 100644
--- a/engines/freescape/games/driller/c64.music.cpp
+++ b/engines/freescape/games/driller/c64.music.cpp
@@ -210,9 +210,10 @@ const uint8_t initialTwoCtr[] = {0x02, 0x02, 0x02};
// Debug log levels
#define DEBUG_LEVEL 4 // 0: Minimal, 1: Basic Flow, 2: Detailed State
-DrillerSIDPlayer::DrillerSIDPlayer() : _sid(nullptr),
+// Tune 0 seems unused, Tune 1 is the main theme
+DrillerSIDPlayer::DrillerSIDPlayer(int tuneIndex) : _sid(nullptr),
_playState(STOPPED),
- _targetTuneIndex(0),
+ _targetTuneIndex(tuneIndex),
_globalTempo(3), // Default tempo
_globalTempoCounter(1) // Start immediately
{
@@ -234,14 +235,8 @@ void DrillerSIDPlayer::destroySID() {
}
}
-// Tune 0 seems unused, Tune 1 is the main theme
-void DrillerSIDPlayer::startMusic(int tuneIndex) {
- if (tuneIndex < 0 || tuneIndex >= NUM_TUNES) {
- debug(DEBUG_LEVEL >= 0, "Driller: Invalid tune index %d requested", tuneIndex);
- return;
- }
- debug(DEBUG_LEVEL >= 0, "Driller: Starting Tune %d", tuneIndex);
- _targetTuneIndex = tuneIndex;
+void DrillerSIDPlayer::startMusic() {
+ initSID();
// Signal to change tune on the next frame update
// If stopped, this will trigger initialization. If playing, triggers change.
_playState = CHANGING_TUNE;
@@ -258,6 +253,11 @@ void DrillerSIDPlayer::stopMusic() {
SID_Write(offset + 4, 0); // Gate off, keep waveform bits
}
}
+ destroySID();
+}
+
+bool DrillerSIDPlayer::isPlaying() const {
+ return _playState == PLAYING;
}
// --- SID Interaction ---
diff --git a/engines/freescape/games/driller/c64.music.h b/engines/freescape/games/driller/c64.music.h
index f36fc86491f..745e35f0992 100644
--- a/engines/freescape/games/driller/c64.music.h
+++ b/engines/freescape/games/driller/c64.music.h
@@ -21,10 +21,11 @@
#include "audio/sid.h"
#include "common/debug.h"
+#include "freescape/music.h"
namespace Freescape {
-class DrillerSIDPlayer {
+class DrillerSIDPlayer : public MusicPlayer {
// --- Voice State Structure ---
struct VoiceState {
@@ -221,14 +222,15 @@ class DrillerSIDPlayer {
// Gate mask is now per-voice (v.gateMask) matching assembly's control3
public:
- DrillerSIDPlayer();
+ DrillerSIDPlayer(int tuneIndex = 1);
~DrillerSIDPlayer();
- void startMusic(int tuneIndex = 1);
- void stopMusic();
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
+
+private:
void initSID();
void destroySID();
-
- private:
void SID_Write(int reg, uint8_t data);
void onTimer();
void handleChangeTune(int tuneIndex);
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index b5c0b04c7dd..65629226fa4 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -98,13 +98,13 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
_borderExtra = nullptr;
_borderExtraTexture = nullptr;
- _playerSid = nullptr;
+ _playerMusic = nullptr;
_playerC64Sfx = nullptr;
_c64UseSFX = false;
}
DrillerEngine::~DrillerEngine() {
- delete _playerSid;
+ delete _playerMusic;
delete _playerC64Sfx;
delete _drillBase;
@@ -268,8 +268,8 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
if (areaID == _startArea && entranceID == _startEntrance) {
if (isC64()) {
- if (!_c64UseSFX && _playerSid)
- _playerSid->startMusic();
+ if (!_c64UseSFX && _playerMusic)
+ _playerMusic->startMusic();
playSound(_soundIndexStart, true, _soundFxHandle);
} else {
playSound(_soundIndexStart, true, _soundFxHandle);
diff --git a/engines/freescape/games/driller/driller.h b/engines/freescape/games/driller/driller.h
index e427f1ab3d5..6db575dc442 100644
--- a/engines/freescape/games/driller/driller.h
+++ b/engines/freescape/games/driller/driller.h
@@ -22,6 +22,7 @@
#include "audio/audiostream.h"
#include "audio/mixer.h"
+#include "engines/freescape/music.h"
#include "engines/freescape/games/driller/c64.music.h"
#include "engines/freescape/games/driller/c64.sfx.h"
@@ -45,7 +46,7 @@ public:
bool _useAutomaticDrilling;
- DrillerSIDPlayer *_playerSid;
+ MusicPlayer *_playerMusic;
DrillerC64SFXPlayer *_playerC64Sfx;
bool _c64UseSFX;
diff --git a/engines/freescape/games/eclipse/ay.music.h b/engines/freescape/games/eclipse/ay.music.h
index bf8d61434c5..e679a651b99 100644
--- a/engines/freescape/games/eclipse/ay.music.h
+++ b/engines/freescape/games/eclipse/ay.music.h
@@ -24,6 +24,7 @@
#include "audio/softsynth/ay8912.h"
#include "audio/mixer.h"
+#include "freescape/music.h"
namespace Freescape {
@@ -37,14 +38,14 @@ namespace Freescape {
* - Dropping SID-specific features (pulse width, filters)
*
*/
-class EclipseAYMusicPlayer : public Audio::AY8912Stream {
+class EclipseAYMusicPlayer : public MusicPlayer, private Audio::AY8912Stream {
public:
EclipseAYMusicPlayer(Audio::Mixer *mixer);
~EclipseAYMusicPlayer() override;
- void startMusic();
- void stopMusic();
- bool isPlaying() const;
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
// AudioStream overrides
int readBuffer(int16 *buffer, const int numSamples) override;
diff --git a/engines/freescape/games/eclipse/c64.cpp b/engines/freescape/games/eclipse/c64.cpp
index 59e954280fb..657f5434c4f 100644
--- a/engines/freescape/games/eclipse/c64.cpp
+++ b/engines/freescape/games/eclipse/c64.cpp
@@ -116,8 +116,8 @@ void EclipseEngine::loadAssetsC64FullGame() {
if (loadAddress == 0x0410) {
_c64MusicData.resize(file.size() - 2);
file.read(_c64MusicData.data(), _c64MusicData.size());
- delete _playerC64Music;
- _playerC64Music = new EclipseC64MusicPlayer(_c64MusicData);
+ delete _playerMusic;
+ _playerMusic = new EclipseC64MusicPlayer(_c64MusicData);
}
}
} else if ((_variant & GF_C64_TAPE) && _extraBuffer) {
@@ -128,8 +128,8 @@ void EclipseEngine::loadAssetsC64FullGame() {
static const int kMusicRegionSize = 0x1100; // covers 0x0410..0x14FF
_c64MusicData.resize(kMusicRegionSize);
memcpy(_c64MusicData.data(), _extraBuffer + kTapeMusicShift, kMusicRegionSize);
- delete _playerC64Music;
- _playerC64Music = new EclipseC64MusicPlayer(_c64MusicData);
+ delete _playerMusic;
+ _playerMusic = new EclipseC64MusicPlayer(_c64MusicData);
}
} else {
Common::File musicFile;
@@ -139,8 +139,8 @@ void EclipseEngine::loadAssetsC64FullGame() {
if (loadAddress == 0x0410) {
_c64MusicData.resize(musicFile.size() - 2);
musicFile.read(_c64MusicData.data(), _c64MusicData.size());
- delete _playerC64Music;
- _playerC64Music = new EclipseC64MusicPlayer(_c64MusicData);
+ delete _playerMusic;
+ _playerMusic = new EclipseC64MusicPlayer(_c64MusicData);
}
}
}
@@ -162,14 +162,12 @@ void EclipseEngine::toggleC64Sound() {
if (_c64UseSFX) {
if (_playerC64Sfx)
_playerC64Sfx->destroySID();
- if (_playerC64Music) {
- _playerC64Music->initSID();
- _playerC64Music->startMusic();
- }
+ if (_playerMusic)
+ _playerMusic->startMusic();
_c64UseSFX = false;
} else {
- if (_playerC64Music)
- _playerC64Music->destroySID();
+ if (_playerMusic)
+ _playerMusic->stopMusic();
if (_playerC64Sfx)
_playerC64Sfx->initSID();
_c64UseSFX = true;
diff --git a/engines/freescape/games/eclipse/c64.music.cpp b/engines/freescape/games/eclipse/c64.music.cpp
index 82fae5526ca..09acca9092c 100644
--- a/engines/freescape/games/eclipse/c64.music.cpp
+++ b/engines/freescape/games/eclipse/c64.music.cpp
@@ -150,12 +150,14 @@ byte EclipseC64MusicPlayer::clampNote(byte note) const {
void EclipseC64MusicPlayer::startMusic() {
if (_musicData.empty())
return;
+ initSID();
setupSong();
}
void EclipseC64MusicPlayer::stopMusic() {
_musicActive = false;
silenceAll();
+ destroySID();
}
void EclipseC64MusicPlayer::setupSong() {
diff --git a/engines/freescape/games/eclipse/c64.music.h b/engines/freescape/games/eclipse/c64.music.h
index 8496dff7f35..cf8b582c8b3 100644
--- a/engines/freescape/games/eclipse/c64.music.h
+++ b/engines/freescape/games/eclipse/c64.music.h
@@ -24,19 +24,18 @@
#include "audio/sid.h"
#include "common/array.h"
+#include "freescape/music.h"
namespace Freescape {
-class EclipseC64MusicPlayer {
+class EclipseC64MusicPlayer : public MusicPlayer {
public:
EclipseC64MusicPlayer(const Common::Array<byte> &musicData);
~EclipseC64MusicPlayer();
- void startMusic();
- void stopMusic();
- bool isPlaying() const;
- void initSID();
- void destroySID();
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
private:
static const uint16 kLoadAddress = 0x0410;
@@ -128,6 +127,9 @@ private:
void applyEffectArpeggio(int channel);
void applyTimedSlide(int channel);
void applyPulseWidthModulation(int channel);
+
+ void initSID();
+ void destroySID();
};
} // namespace Freescape
diff --git a/engines/freescape/games/eclipse/cpc.cpp b/engines/freescape/games/eclipse/cpc.cpp
index 48078bd65ff..43480d310b2 100644
--- a/engines/freescape/games/eclipse/cpc.cpp
+++ b/engines/freescape/games/eclipse/cpc.cpp
@@ -146,7 +146,7 @@ void EclipseEngine::loadAssetsCPCFullGame() {
it->convertToInPlace(_gfx->_texturePixelFormat);
if (ConfMan.getBool("ay_music"))
- _playerAYMusic = new EclipseAYMusicPlayer(_mixer);
+ _playerMusic = new EclipseAYMusicPlayer(_mixer);
}
void EclipseEngine::loadAssetsCPCDemo() {
@@ -187,7 +187,7 @@ void EclipseEngine::loadAssetsCPCDemo() {
it->convertToInPlace(_gfx->_texturePixelFormat);
if (ConfMan.getBool("ay_music"))
- _playerAYMusic = new EclipseAYMusicPlayer(_mixer);
+ _playerMusic = new EclipseAYMusicPlayer(_mixer);
}
void EclipseEngine::updateHeartFramesCPC() {
diff --git a/engines/freescape/games/eclipse/dos.cpp b/engines/freescape/games/eclipse/dos.cpp
index 2019f48a3d9..e0dc3707f7e 100644
--- a/engines/freescape/games/eclipse/dos.cpp
+++ b/engines/freescape/games/eclipse/dos.cpp
@@ -162,7 +162,7 @@ void EclipseEngine::loadAssetsDOSFullGame() {
error("Invalid or unsupported render mode %s for Total Eclipse", Common::getRenderModeDescription(_renderMode));
if (ConfMan.getBool("opl_music"))
- _playerOPLMusic = new EclipseOPLMusicPlayer();
+ _playerMusic = new EclipseOPLMusicPlayer();
}
void EclipseEngine::drawDOSUI(Graphics::Surface *surface) {
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index 23c9c54eb0b..6474c859302 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -58,10 +58,8 @@ static const WBTableOffsets kEclipseAmigaMusicOffsets = {
};
EclipseEngine::EclipseEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEngine(syst, gd) {
- _playerC64Music = nullptr;
_playerC64Sfx = nullptr;
- _playerAYMusic = nullptr;
- _playerOPLMusic = nullptr;
+ _playerMusic = nullptr;
_c64UseSFX = false;
// These sounds can be overriden by the class of each platform
@@ -136,23 +134,15 @@ EclipseEngine::EclipseEngine(OSystem *syst, const ADGameDescription *gd) : Frees
}
void EclipseEngine::stopBackgroundMusic() {
- if (_playerOPLMusic)
- _playerOPLMusic->stopMusic();
- if (_playerAYMusic)
- _playerAYMusic->stopMusic();
- if (_playerC64Music)
- _playerC64Music->stopMusic();
+ if (_playerMusic)
+ _playerMusic->stopMusic();
if (_mixer)
_mixer->stopHandle(_musicHandle);
}
void EclipseEngine::restartBackgroundMusic() {
- if (isC64() && _playerC64Music) {
- _playerC64Music->startMusic();
- } else if ((isCPC() || isSpectrum()) && _playerAYMusic) {
- _playerAYMusic->startMusic();
- } else if (isDOS() && _playerOPLMusic) {
- _playerOPLMusic->startMusic();
+ if (_playerMusic) {
+ _playerMusic->startMusic();
} else if ((isAtariST() || isAmiga()) && !_musicData.empty()) {
if (_mixer)
_mixer->stopHandle(_musicHandle);
@@ -183,9 +173,7 @@ EclipseEngine::~EclipseEngine() {
_compassBackground->free();
delete _compassBackground;
}
- delete _playerOPLMusic;
- delete _playerAYMusic;
- delete _playerC64Music;
+ delete _playerMusic;
delete _playerC64Sfx;
}
diff --git a/engines/freescape/games/eclipse/eclipse.h b/engines/freescape/games/eclipse/eclipse.h
index 2ae3b43b1ba..a36195c3696 100644
--- a/engines/freescape/games/eclipse/eclipse.h
+++ b/engines/freescape/games/eclipse/eclipse.h
@@ -21,14 +21,12 @@
#include "common/file.h"
+#include "freescape/music.h"
#include "freescape/sound.h"
namespace Freescape {
-class EclipseAYMusicPlayer;
-class EclipseC64MusicPlayer;
class EclipseC64SFXPlayer;
-class EclipseOPLMusicPlayer;
enum EclipseReleaseFlags {
GF_ZX_DEMO_CRASH = (1 << 0),
@@ -123,14 +121,12 @@ public:
Common::Array<byte> _musicData; // TEMUSIC.ST TEXT segment (Atari ST)
Common::Array<byte> _c64MusicData;
- EclipseC64MusicPlayer *_playerC64Music;
EclipseC64SFXPlayer *_playerC64Sfx;
bool _c64UseSFX;
void playSoundC64(int index) override;
void toggleC64Sound();
- EclipseAYMusicPlayer *_playerAYMusic;
- EclipseOPLMusicPlayer *_playerOPLMusic;
+ MusicPlayer *_playerMusic;
void restartBackgroundMusic();
void stopBackgroundMusic();
diff --git a/engines/freescape/games/eclipse/opl.music.h b/engines/freescape/games/eclipse/opl.music.h
index 466a898bf7d..90265ef8578 100644
--- a/engines/freescape/games/eclipse/opl.music.h
+++ b/engines/freescape/games/eclipse/opl.music.h
@@ -23,6 +23,7 @@
#define FREESCAPE_ECLIPSE_OPL_MUSIC_H
#include "audio/fmopl.h"
+#include "freescape/music.h"
namespace Freescape {
@@ -35,14 +36,14 @@ namespace Freescape {
* - Mapping SID waveforms to OPL FM instrument patches
* - Rebuilding the SID envelope and pulse-width motion on top of AdLib timbres
*/
-class EclipseOPLMusicPlayer {
+class EclipseOPLMusicPlayer : public MusicPlayer {
public:
EclipseOPLMusicPlayer();
~EclipseOPLMusicPlayer();
- void startMusic();
- void stopMusic();
- bool isPlaying() const;
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
private:
enum {
diff --git a/engines/freescape/games/eclipse/zx.cpp b/engines/freescape/games/eclipse/zx.cpp
index 2753a4c8823..103e11d3760 100644
--- a/engines/freescape/games/eclipse/zx.cpp
+++ b/engines/freescape/games/eclipse/zx.cpp
@@ -128,7 +128,7 @@ void EclipseEngine::loadAssetsZXFullGame() {
it->convertToInPlace(_gfx->_texturePixelFormat);
if (ConfMan.getBool("ay_music"))
- _playerAYMusic = new EclipseAYMusicPlayer(_mixer);
+ _playerMusic = new EclipseAYMusicPlayer(_mixer);
}
void EclipseEngine::loadAssetsZXDemo() {
@@ -173,7 +173,7 @@ void EclipseEngine::loadAssetsZXDemo() {
it->convertToInPlace(_gfx->_texturePixelFormat);
if (ConfMan.getBool("ay_music"))
- _playerAYMusic = new EclipseAYMusicPlayer(_mixer);
+ _playerMusic = new EclipseAYMusicPlayer(_mixer);
}
void EclipseEngine::drawZXUI(Graphics::Surface *surface) {
diff --git a/engines/freescape/music.h b/engines/freescape/music.h
new file mode 100644
index 00000000000..8b968078956
--- /dev/null
+++ b/engines/freescape/music.h
@@ -0,0 +1,40 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FREESCAPE_MUSIC_H
+#define FREESCAPE_MUSIC_H
+
+#include "common/scummsys.h"
+
+namespace Freescape {
+
+class MusicPlayer {
+public:
+ virtual ~MusicPlayer() {}
+
+ virtual void startMusic() = 0;
+ virtual void stopMusic() = 0;
+ virtual bool isPlaying() const = 0;
+};
+
+} // namespace Freescape
+
+#endif
Commit: a295fa5a0b7d6b46584d71b2a746d3b5536dc692
https://github.com/scummvm/scummvm/commit/a295fa5a0b7d6b46584d71b2a746d3b5536dc692
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-05-04T23:34:51+02:00
Commit Message:
FREESCAPE: Refactor Atari music code to be independent of the YM2149 implementation
Changed paths:
engines/freescape/games/eclipse/atari.cpp
engines/freescape/games/eclipse/atari.music.cpp
engines/freescape/games/eclipse/eclipse.cpp
diff --git a/engines/freescape/games/eclipse/atari.cpp b/engines/freescape/games/eclipse/atari.cpp
index 0b33e3668fc..d2d97733d58 100644
--- a/engines/freescape/games/eclipse/atari.cpp
+++ b/engines/freescape/games/eclipse/atari.cpp
@@ -29,6 +29,11 @@
namespace Freescape {
+
+// Forward declaration (defined in atari.music.cpp)
+MusicPlayer *makeEclipseAtariMusicPlayer(const byte *data, uint32 dataSize,
+ int songNum = 1);
+
extern const int kAtariCompassPhaseCount = 72;
extern const int kAtariCompassBaseFrames = 19;
extern const int kAtariCompassTotalFrames = 37;
@@ -850,6 +855,7 @@ void EclipseEngine::loadAssetsAtariFullGame() {
stream->seek(kTEMusicOffset + kGemdosHeaderSize);
_musicData.resize(kTEMusicTextSize);
stream->read(_musicData.data(), kTEMusicTextSize);
+ _playerMusic = makeEclipseAtariMusicPlayer(_musicData.data(), _musicData.size());
debug(3, "TE-Atari: Loaded TEMUSIC.ST TEXT segment (%d bytes)", kTEMusicTextSize);
// UI font (Font A): 4-plane 16-color bordered font at prog $24C3E (file offset $24C5A)
diff --git a/engines/freescape/games/eclipse/atari.music.cpp b/engines/freescape/games/eclipse/atari.music.cpp
index 29a056f5991..ca6d0dee517 100644
--- a/engines/freescape/games/eclipse/atari.music.cpp
+++ b/engines/freescape/games/eclipse/atari.music.cpp
@@ -35,9 +35,10 @@
* $0DCC Pattern pointer table (up to 31 x uint32 BE)
*/
-#include "audio/softsynth/ym2149.h"
+#include "audio/ym2149.h"
#include "freescape/freescape.h"
+#include "freescape/music.h"
#include "freescape/wb.h"
#include "common/endian.h"
@@ -58,17 +59,18 @@ static const int kTENumPeriods = 96;
static const int kTENumInstruments = 12;
static const int kTEMaxPatterns = 31;
-class EclipseAtariMusicStream : public Audio::YM2149Emu {
+class EclipseAtariMusicPlayer : public MusicPlayer {
public:
- EclipseAtariMusicStream(const byte *data, uint32 dataSize, int songNum, int rate = 44100);
- ~EclipseAtariMusicStream() override {}
+ EclipseAtariMusicPlayer(const byte *data, uint32 dataSize, int songNum);
+ ~EclipseAtariMusicPlayer();
- int readBuffer(int16 *buffer, const int numSamples) override;
- bool endOfData() const override { return !_musicActive; }
- bool endOfStream() const override { return !_musicActive; }
- Audio::AudioStream *toAudioStream() { return this; }
+ void startMusic() override;
+ void stopMusic() override;
+ bool isPlaying() const override;
private:
+ YM2149::YM2149 *_ym2149;
+
// --- Data tables ---
const byte *_data;
uint32 _dataSize;
@@ -178,10 +180,10 @@ private:
bool _musicActive;
byte _tickSpeed;
byte _tickCounter;
- int _tickSampleCount;
bool _hwEnvelopeDirty;
uint16 _hwEnvelopePeriod;
byte _hwEnvelopeShape;
+ int _songNum;
// --- Methods ---
void loadTables();
@@ -195,7 +197,7 @@ private:
void buildArpeggioTable(ChannelState &c, byte mask);
void tickUpdate();
void writeYMRegisters();
- void setReg(int reg, byte value) { writeReg(reg, value); }
+ void setReg(int reg, byte value) { if (_ym2149) _ym2149->writeReg(reg, value); }
uint16 getPeriod(int note) const {
if (note < 0 || note >= kTENumPeriods)
@@ -226,12 +228,12 @@ private:
// Construction / data loading
// ---------------------------------------------------------------------------
-EclipseAtariMusicStream::EclipseAtariMusicStream(const byte *data, uint32 dataSize,
- int songNum, int)
+EclipseAtariMusicPlayer::EclipseAtariMusicPlayer(const byte *data, uint32 dataSize,
+ int songNum)
: _data(data), _dataSize(dataSize),
_musicActive(false), _tickSpeed(6), _tickCounter(0),
- _tickSampleCount(0), _hwEnvelopeDirty(false), _hwEnvelopePeriod(0), _hwEnvelopeShape(0),
- _numPatterns(0) {
+ _hwEnvelopeDirty(false), _hwEnvelopePeriod(0), _hwEnvelopeShape(0),
+ _numPatterns(0), _songNum(songNum) {
memset(_periods, 0, sizeof(_periods));
memset(_instruments, 0, sizeof(_instruments));
@@ -240,13 +242,47 @@ EclipseAtariMusicStream::EclipseAtariMusicStream(const byte *data, uint32 dataSi
memset(_arpeggioIntervals, 0, sizeof(_arpeggioIntervals));
memset(_channels, 0, sizeof(_channels));
- init();
+ _ym2149 = YM2149::Config::create();
+ if (!_ym2149 || !_ym2149->init()) {
+ warning("EclipseAtariMusicPlayer: Failed to create YM2149 emulator");
+ delete _ym2149;
+ _ym2149 = nullptr;
+ }
loadTables();
- startSong(songNum);
}
-void EclipseAtariMusicStream::loadTables() {
+EclipseAtariMusicPlayer::~EclipseAtariMusicPlayer() {
+ stopMusic();
+ delete _ym2149;
+}
+
+
+// ============================================================================
+// Public interface
+// ============================================================================
+
+void EclipseAtariMusicPlayer::startMusic() {
+ if (!_ym2149)
+ return;
+ stopMusic();
+ _ym2149->start(new Common::Functor0Mem<void, EclipseAtariMusicPlayer>(
+ this, &EclipseAtariMusicPlayer::tickUpdate), 50);
+ startSong(_songNum);
+}
+
+void EclipseAtariMusicPlayer::stopMusic() {
+ _musicActive = false;
+ if (_ym2149) {
+ _ym2149->stop();
+ }
+}
+
+bool EclipseAtariMusicPlayer::isPlaying() const {
+ return _musicActive;
+}
+
+void EclipseAtariMusicPlayer::loadTables() {
// Period table: 96 x uint16 BE at TEXT+$0B24
for (int i = 0; i < kTENumPeriods; i++) {
_periods[i] = readDataWord(kTEPeriodTableOffset + i * 2);
@@ -314,7 +350,7 @@ void EclipseAtariMusicStream::loadTables() {
// Song init
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::startSong(int songNum) {
+void EclipseAtariMusicPlayer::startSong(int songNum) {
_musicActive = false;
if (songNum < 1 || songNum > 2)
@@ -349,7 +385,7 @@ void EclipseAtariMusicStream::startSong(int songNum) {
}
}
-void EclipseAtariMusicStream::initChannel(int ch) {
+void EclipseAtariMusicPlayer::initChannel(int ch) {
ChannelState &c = _channels[ch];
memset(&c, 0, sizeof(ChannelState));
c.duration = 1;
@@ -366,7 +402,7 @@ void EclipseAtariMusicStream::initChannel(int ch) {
// Same format as wb.cpp: $00-$C0=pattern#, $C1-$FE=transpose, $FF=loop
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::readOrderList(int ch) {
+void EclipseAtariMusicPlayer::readOrderList(int ch) {
ChannelState &c = _channels[ch];
for (int safety = 0; safety < 256; safety++) {
@@ -408,7 +444,7 @@ void EclipseAtariMusicStream::readOrderList(int ch) {
// $7D/$7C=vibrato/arpeggio, $00-$5F=note
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::readPatternCommands(int ch) {
+void EclipseAtariMusicPlayer::readPatternCommands(int ch) {
ChannelState &c = _channels[ch];
for (int safety = 0; safety < 256; safety++) {
@@ -605,7 +641,7 @@ void EclipseAtariMusicStream::readPatternCommands(int ch) {
// Note trigger â set YM period, reset envelope
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::triggerNote(int ch) {
+void EclipseAtariMusicPlayer::triggerNote(int ch) {
ChannelState &c = _channels[ch];
// Apply transpose and clamp
@@ -707,7 +743,7 @@ void EclipseAtariMusicStream::triggerNote(int ch) {
// Effects processing â runs every tick (50 Hz)
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::processEffects(int ch) {
+void EclipseAtariMusicPlayer::processEffects(int ch) {
ChannelState &c = _channels[ch];
// Noise gate: in TEMUSIC, instrument high nibble is a countdown that
@@ -823,7 +859,7 @@ void EclipseAtariMusicStream::processEffects(int ch) {
// Volume range: 0-63 internal, written to YM as >>2 (0-15)
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::processEnvelope(int ch) {
+void EclipseAtariMusicPlayer::processEnvelope(int ch) {
ChannelState &c = _channels[ch];
// Noise-only instruments may validly run with zero tone period.
if (c.outputPeriod == 0 && !c.noiseEnabled)
@@ -900,7 +936,7 @@ void EclipseAtariMusicStream::processEnvelope(int ch) {
// Arpeggio table builder
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::buildArpeggioTable(ChannelState &c, byte mask) {
+void EclipseAtariMusicPlayer::buildArpeggioTable(ChannelState &c, byte mask) {
c.arpeggioTableLen = WBCommon::buildArpeggioTable(_arpeggioIntervals, mask, c.arpeggioTable, 16, false);
c.arpeggioPos = 0;
}
@@ -909,7 +945,7 @@ void EclipseAtariMusicStream::buildArpeggioTable(ChannelState &c, byte mask) {
// Write channel state to YM2149 registers
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::writeYMRegisters() {
+void EclipseAtariMusicPlayer::writeYMRegisters() {
byte mixer = 0x3F; // Start with all disabled (bits 0-2=tone, bits 3-5=noise)
if (_hwEnvelopeDirty) {
setReg(11, _hwEnvelopePeriod & 0xFF);
@@ -970,7 +1006,7 @@ void EclipseAtariMusicStream::writeYMRegisters() {
// Main tick update â called at 50 Hz
// ---------------------------------------------------------------------------
-void EclipseAtariMusicStream::tickUpdate() {
+void EclipseAtariMusicPlayer::tickUpdate() {
if (!_musicActive)
return;
@@ -1023,49 +1059,18 @@ void EclipseAtariMusicStream::tickUpdate() {
writeYMRegisters();
}
-// ---------------------------------------------------------------------------
-// Audio stream readBuffer â tick at 50 Hz, generate AY samples
-// ---------------------------------------------------------------------------
-
-int EclipseAtariMusicStream::readBuffer(int16 *buffer, const int numSamples) {
- if (!_musicActive)
- return 0;
-
- int samplesGenerated = 0;
- int samplesPerTick = MAX(1, getRate() / 50);
-
- while (samplesGenerated < numSamples && _musicActive) {
- int remaining = samplesPerTick - _tickSampleCount;
- int toGenerate = MIN(numSamples - samplesGenerated, remaining);
-
- if (toGenerate > 0) {
- generateSamples(buffer + samplesGenerated, toGenerate);
- samplesGenerated += toGenerate;
- _tickSampleCount += toGenerate;
- }
-
- if (_tickSampleCount >= samplesPerTick) {
- _tickSampleCount -= samplesPerTick;
- tickUpdate();
- }
- }
-
- return samplesGenerated;
-}
-
// ---------------------------------------------------------------------------
// Factory function
// ---------------------------------------------------------------------------
-Audio::AudioStream *makeEclipseAtariMusicStream(const byte *data, uint32 dataSize,
- int songNum, int rate) {
+MusicPlayer *makeEclipseAtariMusicPlayer(const byte *data, uint32 dataSize,
+ int songNum) {
if (!data || dataSize < 0x1000) {
warning("TE-Atari music: invalid data (size %u)", dataSize);
return nullptr;
}
- EclipseAtariMusicStream *stream = new EclipseAtariMusicStream(data, dataSize, songNum, rate);
- return stream->toAudioStream();
+ return new EclipseAtariMusicPlayer(data, dataSize, songNum);
}
} // End of namespace Freescape
diff --git a/engines/freescape/games/eclipse/eclipse.cpp b/engines/freescape/games/eclipse/eclipse.cpp
index 6474c859302..3262c69883b 100644
--- a/engines/freescape/games/eclipse/eclipse.cpp
+++ b/engines/freescape/games/eclipse/eclipse.cpp
@@ -41,10 +41,6 @@
namespace Freescape {
-// Forward declaration (defined in atari.music.cpp)
-Audio::AudioStream *makeEclipseAtariMusicStream(const byte *data, uint32 dataSize,
- int songNum = 1, int rate = 44100);
-
// Wally Beben table offsets for Total Eclipse Amiga TEMUSIC.AM
static const WBTableOffsets kEclipseAmigaMusicOffsets = {
0x0ACA, // periodTable
@@ -143,17 +139,12 @@ void EclipseEngine::stopBackgroundMusic() {
void EclipseEngine::restartBackgroundMusic() {
if (_playerMusic) {
_playerMusic->startMusic();
- } else if ((isAtariST() || isAmiga()) && !_musicData.empty()) {
+ } else if (isAmiga() && !_musicData.empty()) {
if (_mixer)
_mixer->stopHandle(_musicHandle);
- Audio::AudioStream *musicStream = nullptr;
- if (isAmiga())
- musicStream = makeWallyBebenStream(
- _musicData.data(), _musicData.size(), 1, 44100, true,
- &kEclipseAmigaMusicOffsets);
- else
- musicStream = makeEclipseAtariMusicStream(
- _musicData.data(), _musicData.size(), 1);
+ Audio::AudioStream *musicStream = makeWallyBebenStream(
+ _musicData.data(), _musicData.size(), 1, 44100, true,
+ &kEclipseAmigaMusicOffsets);
if (musicStream) {
_mixer->playStream(Audio::Mixer::kMusicSoundType,
&_musicHandle, musicStream);
@@ -473,16 +464,11 @@ void EclipseEngine::gotoArea(uint16 areaID, int entranceID) {
}
}
- // Start background music (Atari ST / Amiga)
- if ((isAtariST() || isAmiga()) && !_musicData.empty() && !_mixer->isSoundHandleActive(_musicHandle)) {
- Audio::AudioStream *musicStream = nullptr;
- if (isAmiga())
- musicStream = makeWallyBebenStream(
- _musicData.data(), _musicData.size(), 1, 44100, true,
- &kEclipseAmigaMusicOffsets);
- else
- musicStream = makeEclipseAtariMusicStream(
- _musicData.data(), _musicData.size(), 1);
+ // Start background music (Amiga)
+ if (isAmiga() && !_musicData.empty() && !_mixer->isSoundHandleActive(_musicHandle)) {
+ Audio::AudioStream *musicStream = makeWallyBebenStream(
+ _musicData.data(), _musicData.size(), 1, 44100, true,
+ &kEclipseAmigaMusicOffsets);
if (musicStream) {
_mixer->playStream(Audio::Mixer::kMusicSoundType,
&_musicHandle, musicStream);
More information about the Scummvm-git-logs
mailing list