Fixed restarting of song (hopefully thouroughly)
replaced all modulos with masks swapped Paulas stereo output svn-id: r41856
This commit is contained in:
parent
c6ba5279b1
commit
01c3db4d76
10 changed files with 248 additions and 75 deletions
|
@ -120,7 +120,7 @@
|
|||
FavorSizeOrSpeed="2"
|
||||
OmitFramePointers="true"
|
||||
AdditionalIncludeDirectories="../../;../../engines"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB;USE_MAD;USE_VORBIS"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;ENABLE_SCUMM_7_8;ENABLE_HE;USE_ZLIB"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
|
|
|
@ -12,6 +12,7 @@ Global
|
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug_Command|Win32 = Debug_Command|Win32
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release_Command|Win32 = Release_Command|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
|
@ -19,12 +20,15 @@ Global
|
|||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Debug_Command|Win32.Build.0 = Debug_Command|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Release_Command|Win32.ActiveCfg = Release_Command|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Release_Command|Win32.Build.0 = Release_Command|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8434CB15-D08F-427D-9E6D-581AE5B28440}.Release|Win32.Build.0 = Release|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Debug_Command|Win32.ActiveCfg = Debug|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Debug_Command|Win32.Build.0 = Debug|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Release_Command|Win32.ActiveCfg = Release|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B6AFD548-63D2-40CD-A652-E87095AFCBAF}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
EnableIntrinsicFunctions="true"
|
||||
OmitFramePointers="true"
|
||||
AdditionalIncludeDirectories="../../;../../engines"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;ENABLE_SCUMM;USE_ZLIB;USE_MAD;USE_VORBIS"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;ENABLE_SCUMM;USE_ZLIB"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
|
@ -160,7 +160,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="winmm.lib sdl.lib zlib.lib libmad.lib vorbisfile_static.lib vorbis_static.lib ogg_static.lib"
|
||||
AdditionalDependencies="winmm.lib sdl.lib zlib.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)-tfmx.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
|
@ -285,6 +285,98 @@
|
|||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release_Command|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/wd4201 /wd4512 /wd4511 /wd4100 /wd4121 /wd4310 /wd4706 /wd4127 /wd4189 /wd4702 /wd4996"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
OmitFramePointers="true"
|
||||
AdditionalIncludeDirectories="../../;../../engines"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;TFMX_CMDLINE_TOOL"
|
||||
StringPooling="true"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="1"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
EnableFunctionLevelLinking="false"
|
||||
DisableLanguageExtensions="false"
|
||||
ForceConformanceInForLoopScope="true"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
DebugInformationFormat="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkLibraryDependencies="false"
|
||||
AdditionalDependencies="winmm.lib sdl.lib"
|
||||
OutputFile="$(OutDir)\$(ProjectName)-tfmx.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
IgnoreDefaultLibraryNames="libc.lib"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
EntryPointSymbol="WinMainCRTStartup"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
|
@ -658,6 +750,15 @@
|
|||
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\$(InputName)1.obj"
|
||||
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound\iff.h"
|
||||
|
@ -816,6 +917,15 @@
|
|||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)/$(InputName)1.obj"
|
||||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound\softsynth\emumidi.h"
|
||||
|
@ -855,6 +965,15 @@
|
|||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)/$(InputName)1.obj"
|
||||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound\softsynth\pcspk.cpp"
|
||||
|
@ -894,6 +1013,15 @@
|
|||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)/$(InputName)1.obj"
|
||||
XMLDocumentationFileName="$(IntDir)/$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound\softsynth\ym2612.h"
|
||||
|
@ -1058,6 +1186,14 @@
|
|||
<File
|
||||
RelativePath="..\..\sound\mods\tfmx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AssemblerOutput="2"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\sound\mods\tfmx.h"
|
||||
|
@ -1150,6 +1286,15 @@
|
|||
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\$(InputName)1.obj"
|
||||
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backends\platform\sdl\sdl.cpp"
|
||||
|
@ -1719,6 +1864,15 @@
|
|||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="nasm.exe -f win32 -o "$(OutDir)\$(InputName).obj" "$(InputPath)"
"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\graphics\scaler\hq3x.cpp"
|
||||
|
@ -1758,6 +1912,15 @@
|
|||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Command|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
CommandLine="nasm.exe -f win32 -o "$(OutDir)\$(InputName).obj" "$(InputPath)"
"
|
||||
Outputs="$(OutDir)\$(InputName).obj"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\graphics\scaler\intern.h"
|
||||
|
|
|
@ -49,6 +49,7 @@ bool Player_V4A::init() {
|
|||
if (mdatExists && sampleExists) {
|
||||
Audio::Tfmx *play = new Audio::Tfmx(_mixer->getOutputRate(), true);
|
||||
if (play->load(fileMdat, fileSample)) {
|
||||
play->setSignalPtr(_signal);
|
||||
_tfmxPlay = play;
|
||||
} else
|
||||
delete play;
|
||||
|
@ -77,8 +78,10 @@ void Player_V4A::setMusicVolume(int vol) {
|
|||
|
||||
void Player_V4A::stopAllSounds() {
|
||||
debug(5, "player_v4a: stopAllSounds");
|
||||
if (_tfmxPlay)
|
||||
if (_tfmxPlay) {
|
||||
_tfmxPlay->stopSong();
|
||||
_signal[0] = 0;
|
||||
}
|
||||
_musicId = 0;
|
||||
if (_tfmxSfx)
|
||||
_tfmxSfx->stopSong();
|
||||
|
@ -87,9 +90,12 @@ void Player_V4A::stopAllSounds() {
|
|||
|
||||
void Player_V4A::stopSound(int nr) {
|
||||
debug(5, "player_v4a: stopSound %d", nr);
|
||||
if (nr == 0)
|
||||
return;
|
||||
if (nr == _musicId) {
|
||||
_tfmxPlay->stopSong();
|
||||
_musicId = 0;
|
||||
_tfmxPlay->stopSong();
|
||||
_signal[0] = 0;
|
||||
} else {
|
||||
const int chan = getSfxChan(nr);
|
||||
if (chan != -1) {
|
||||
|
@ -132,14 +138,14 @@ void Player_V4A::startSound(int nr) {
|
|||
|
||||
if (_tfmxSfx->getSongIndex() < 0)
|
||||
_tfmxSfx->doSong(0x18);
|
||||
const int chan = _tfmxSfx->doSfx(index);
|
||||
const int chan = _tfmxSfx->doSfx((uint16)index);
|
||||
if (chan >= 0 && chan < ARRAYSIZE(_sfxSlots))
|
||||
setSfxSlot(chan, nr, type);
|
||||
else
|
||||
warning("player_v4a: custom %i is not of required type", index);
|
||||
|
||||
if (!_mixer->isSoundHandleActive(_sfxHandle))
|
||||
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, _tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
|
||||
if (!_mixer->isSoundHandleActive(_musicHandle))
|
||||
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_musicHandle, _tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
|
||||
} else {
|
||||
// Song
|
||||
debug(3, "player_v4a: play %d: song %i - %02X", nr, index, type);
|
||||
|
@ -147,10 +153,11 @@ void Player_V4A::startSound(int nr) {
|
|||
warning("player_v4a: Song has wrong type");
|
||||
|
||||
_tfmxPlay->doSong(index);
|
||||
_signal[0] = 2;
|
||||
_musicId = nr;
|
||||
|
||||
if (!_mixer->isSoundHandleActive(_musicHandle))
|
||||
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, _tfmxPlay, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
|
||||
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, _tfmxPlay, -1, Audio::Mixer::kMaxChannelVolume, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,15 +166,20 @@ int Player_V4A::getMusicTimer() const {
|
|||
// TODO: The titlesong is running with ~70 ticks per second and the scale seems to be based on that.
|
||||
// Other songs dont and I have no clue if this scalevalue is anything close to correct for them.
|
||||
// The Amiga-Game doesnt counts the ticks of the song, but has an own timer and I hope thespeed is constant through the game
|
||||
const int magicScale = 359; // ~ 1000 * 25 * (10173 / 709379.0)
|
||||
const int magicScale = 357; // ~ 1000 * 25 * (10173 / 709379.0)
|
||||
return (_mixer->getSoundElapsedTime(_musicHandle)) / magicScale;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Player_V4A::getSoundStatus(int nr) const {
|
||||
if (nr == _musicId && _mixer->isSoundHandleActive(_musicHandle))
|
||||
return _tfmxPlay->getSignal(0);
|
||||
bool a = nr == _musicId;
|
||||
bool b = _tfmxPlay->getSongIndex() >= 0;
|
||||
int c = _signal[0];
|
||||
|
||||
debug(5, "player_v4a: getSoundStatus music=%d, active=%d, signal=%d", a, b, c);
|
||||
if (nr == _musicId)
|
||||
return _signal[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ private:
|
|||
Audio::SoundHandle _sfxHandle;
|
||||
|
||||
int _musicId;
|
||||
uint16 _signal[4];
|
||||
|
||||
struct SfxChan {
|
||||
int id;
|
||||
|
|
|
@ -31,10 +31,10 @@ Paula::Paula(bool stereo, int rate, uint interruptFreq) :
|
|||
_stereo(stereo), _rate(rate), _periodScale((kPalSystemClock / 2.0) / rate), _intFreq(interruptFreq) {
|
||||
|
||||
clearVoices();
|
||||
_voice[0].panning = 63;
|
||||
_voice[1].panning = 191;
|
||||
_voice[2].panning = 191;
|
||||
_voice[3].panning = 63;
|
||||
_voice[0].panning = 191;
|
||||
_voice[1].panning = 63;
|
||||
_voice[2].panning = 63;
|
||||
_voice[3].panning = 191;
|
||||
|
||||
if (_intFreq == 0)
|
||||
_intFreq = _rate;
|
||||
|
|
|
@ -44,7 +44,7 @@ const uint16 Tfmx::noteIntervalls[64] = {
|
|||
214, 202, 191, 180 };
|
||||
|
||||
Tfmx::Tfmx(int rate, bool stereo)
|
||||
: Paula(stereo, rate), _resource() {
|
||||
: Paula(stereo, rate), _resource(), _playerCtx() {
|
||||
_playerCtx.stopWithLastPattern = false;
|
||||
|
||||
for (int i = 0; i < kNumVoices; ++i)
|
||||
|
@ -52,8 +52,6 @@ Tfmx::Tfmx(int rate, bool stereo)
|
|||
|
||||
_playerCtx.song = -1;
|
||||
_playerCtx.volume = 0x40;
|
||||
_playerCtx.fadeDelta = 0;
|
||||
_playerCtx.patternCount = 0;
|
||||
_playerCtx.patternSkip = 6;
|
||||
stopPatternChannels();
|
||||
stopMacroChannels();
|
||||
|
@ -89,10 +87,8 @@ void Tfmx::interrupt() {
|
|||
// externally queued macros
|
||||
if (channel.customMacro) {
|
||||
const byte *const noteCmd = (const byte *)&channel.customMacro;
|
||||
const uint8 channelNo = (uint8)(&channel - _channelCtx);
|
||||
|
||||
channel.sfxLocked = false;
|
||||
noteCommand(noteCmd[0], noteCmd[1], (noteCmd[2] & 0xF0) | channelNo, noteCmd[3]);
|
||||
noteCommand(noteCmd[0], noteCmd[1], (noteCmd[2] & 0xF0) | (uint8)i, noteCmd[3]);
|
||||
channel.customMacro = 0;
|
||||
channel.sfxLocked = (channel.customMacroPrio != 0);
|
||||
}
|
||||
|
@ -143,8 +139,8 @@ void Tfmx::effects(ChannelContext &channel) {
|
|||
channel.portaCount = channel.portaSkip;
|
||||
|
||||
bool resetPorta = true;
|
||||
uint16 period = channel.refPeriod; // d1
|
||||
uint16 portaVal = channel.portaValue; // d0
|
||||
uint16 period = channel.refPeriod;
|
||||
uint16 portaVal = channel.portaValue;
|
||||
|
||||
if (period > portaVal) {
|
||||
portaVal = ((uint32)portaVal * (uint16)((1 << 8) + channel.portaDelta)) >> 8;
|
||||
|
@ -213,7 +209,7 @@ static void warnMacroUnimplemented(const byte *macroPtr, int level) {
|
|||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE bool Tfmx::macroStep(ChannelContext &channel) {
|
||||
inline bool Tfmx::macroStep(ChannelContext &channel) {
|
||||
const byte *const macroPtr = (byte *)(_resource.getMacroPtr(channel.macroOffset) + channel.macroStep);
|
||||
++channel.macroStep;
|
||||
|
||||
|
@ -289,8 +285,8 @@ FORCEINLINE bool Tfmx::macroStep(ChannelContext &channel) {
|
|||
return true;
|
||||
|
||||
case 0x06: // Jump. Parameters: MacroIndex, MacroStep(W)
|
||||
channel.macroIndex = macroPtr[1] % kMaxMacroOffsets;
|
||||
channel.macroOffset = _macroOffset[macroPtr[1] % kMaxMacroOffsets];
|
||||
channel.macroIndex = macroPtr[1] & (kMaxMacroOffsets - 1);
|
||||
channel.macroOffset = _macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
|
||||
channel.macroStep = READ_BE_UINT16(¯oPtr[2]);
|
||||
channel.macroLoopCount = 0xFF;
|
||||
return true;
|
||||
|
@ -359,7 +355,7 @@ FORCEINLINE bool Tfmx::macroStep(ChannelContext &channel) {
|
|||
return true;
|
||||
|
||||
case 0x12: // AddLen. Parameters: added Length(W)
|
||||
channel.sampleLen += READ_BE_UINT16(¯oPtr[2]);
|
||||
channel.sampleLen += (int16)READ_BE_UINT16(¯oPtr[2]);
|
||||
Paula::setChannelSampleLen(channel.paulaChannel, channel.sampleLen);
|
||||
return true;
|
||||
|
||||
|
@ -377,7 +373,7 @@ FORCEINLINE bool Tfmx::macroStep(ChannelContext &channel) {
|
|||
channel.macroReturnOffset = channel.macroOffset;
|
||||
channel.macroReturnStep = channel.macroStep;
|
||||
|
||||
channel.macroOffset = _macroOffset[macroPtr[1] % kMaxMacroOffsets];
|
||||
channel.macroOffset = _macroOffset[macroPtr[1] & (kMaxMacroOffsets - 1)];
|
||||
channel.macroStep = READ_BE_UINT16(¯oPtr[2]);
|
||||
// TODO: MI does some weird stuff there. Figure out which varioables need to be set
|
||||
return true;
|
||||
|
@ -440,12 +436,12 @@ FORCEINLINE bool Tfmx::macroStep(ChannelContext &channel) {
|
|||
return channel.deferWait;
|
||||
|
||||
case 0x20: // Signal. Parameters: signalnumber/value
|
||||
if (macroPtr[1] < ARRAYSIZE(_playerCtx.signal))
|
||||
if (_playerCtx.signal)
|
||||
_playerCtx.signal[macroPtr[1]] = READ_BE_UINT16(¯oPtr[2]);
|
||||
return true;
|
||||
|
||||
case 0x21: // Play macro. Parameters: macro/chan/detune
|
||||
warnMacroUnimplemented(macroPtr, 0);
|
||||
noteCommand(channel.note, (channel.relVol << 4) | macroPtr[1], macroPtr[2], macroPtr[3]);
|
||||
return true;
|
||||
#if defined(TFMX_NOT_IMPLEMENTED)
|
||||
// used by Gem`X according to the docs
|
||||
|
@ -503,7 +499,7 @@ startPatterns:
|
|||
|
||||
} else if (pattCmd == 0xFE) { // Stop voice in pattern.expose
|
||||
_patternCtx[i].command = 0xFF;
|
||||
ChannelContext &channel = _channelCtx[_patternCtx[i].expose % kNumVoices];
|
||||
ChannelContext &channel = _channelCtx[_patternCtx[i].expose & (kNumVoices - 1)];
|
||||
if (!channel.sfxLocked) {
|
||||
clearMacroProgramm(channel);
|
||||
Paula::disableChannel(channel.paulaChannel);
|
||||
|
@ -528,7 +524,7 @@ static void warnPatternUnimplemented(const byte *patternPtr, int level) {
|
|||
}
|
||||
|
||||
|
||||
FORCEINLINE bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackstep) {
|
||||
inline bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackstep) {
|
||||
const byte *const patternPtr = (byte *)(_resource.getPatternPtr(pattern.offset) + pattern.step);
|
||||
++pattern.step;
|
||||
|
||||
|
@ -538,18 +534,19 @@ FORCEINLINE bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackst
|
|||
const byte pattCmd = patternPtr[0];
|
||||
|
||||
if (pattCmd < 0xF0) { // Playnote
|
||||
const byte flags = pattCmd >> 6; // 0-1 means note, 2 means wait, 3 means portamento
|
||||
bool nextStep = true;
|
||||
byte noteCmd = pattCmd + pattern.expose;
|
||||
byte param3 = patternPtr[3];
|
||||
if (flags == 2) {
|
||||
// Store wait-value in context and delete it the (note)command
|
||||
pattern.wait = param3;
|
||||
param3 = 0;
|
||||
}
|
||||
if (flags != 3)
|
||||
if (pattCmd < 0xC0) { // Note
|
||||
if (pattCmd >= 0x80) { // Wait
|
||||
pattern.wait = param3;
|
||||
param3 = 0;
|
||||
nextStep = false;
|
||||
}
|
||||
noteCmd &= 0x3F;
|
||||
} // else Portamento
|
||||
noteCommand(noteCmd, patternPtr[1], patternPtr[2], param3);
|
||||
return (flags != 2);
|
||||
return nextStep;
|
||||
|
||||
} else { // Patterncommand
|
||||
switch (pattCmd & 0xF) {
|
||||
|
@ -588,8 +585,8 @@ FORCEINLINE bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackst
|
|||
return false;
|
||||
|
||||
case 5: // Kup^-Set key up
|
||||
if (!_channelCtx[patternPtr[2] % kNumVoices].sfxLocked)
|
||||
_channelCtx[patternPtr[2] % kNumVoices].keyUp = false;
|
||||
if (!_channelCtx[patternPtr[2] & (kNumVoices - 1)].sfxLocked)
|
||||
_channelCtx[patternPtr[2] & (kNumVoices - 1)].keyUp = false;
|
||||
return true;
|
||||
|
||||
case 6: // Vibrato
|
||||
|
@ -618,10 +615,10 @@ FORCEINLINE bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackst
|
|||
return true;
|
||||
|
||||
case 11: { // play pattern. Parameters: patternCmd, channel, expose
|
||||
PatternContext &target = _patternCtx[patternPtr[2] % kNumChannels];
|
||||
PatternContext &target = _patternCtx[patternPtr[2] & (kNumChannels - 1)];
|
||||
|
||||
target.command = patternPtr[1];
|
||||
target.offset = _patternOffset[patternPtr[1] % kMaxPatternOffsets];
|
||||
target.offset = _patternOffset[patternPtr[1] & (kMaxPatternOffsets - 1)];
|
||||
target.expose = patternPtr[3];
|
||||
target.step = 0;
|
||||
target.wait = 0;
|
||||
|
@ -630,12 +627,12 @@ FORCEINLINE bool Tfmx::patternStep(PatternContext &pattern, bool &pendingTrackst
|
|||
return true;
|
||||
|
||||
case 12: // Lock
|
||||
_channelCtx[patternPtr[2] % kNumVoices].sfxLocked = (patternPtr[1] != 0);
|
||||
_channelCtx[patternPtr[2] % kNumVoices].sfxLockTime = patternPtr[3];
|
||||
_channelCtx[patternPtr[2] & (kNumVoices - 1)].sfxLocked = (patternPtr[1] != 0);
|
||||
_channelCtx[patternPtr[2] & (kNumVoices - 1)].sfxLockTime = patternPtr[3];
|
||||
return true;
|
||||
|
||||
case 13: // Cue
|
||||
if (patternPtr[1] < ARRAYSIZE(_playerCtx.signal))
|
||||
if (_playerCtx.signal)
|
||||
_playerCtx.signal[patternPtr[1]] = READ_BE_UINT16(&patternPtr[2]);
|
||||
return true;
|
||||
|
||||
|
@ -719,7 +716,7 @@ bool Tfmx::trackStep() {
|
|||
}
|
||||
|
||||
void Tfmx::noteCommand(const uint8 note, const uint8 param1, const uint8 param2, const uint8 param3) {
|
||||
ChannelContext &channel = _channelCtx[param2 % kNumVoices];
|
||||
ChannelContext &channel = _channelCtx[param2 & (kNumVoices - 1)];
|
||||
|
||||
if (note == 0xFC) { // Lock
|
||||
channel.sfxLocked = (param1 != 0);
|
||||
|
@ -732,8 +729,8 @@ void Tfmx::noteCommand(const uint8 note, const uint8 param1, const uint8 param2,
|
|||
if (note < 0xC0) { // Play Note
|
||||
channel.prevNote = channel.note;
|
||||
channel.note = note;
|
||||
channel.macroIndex = param1 % kMaxMacroOffsets;
|
||||
channel.macroOffset = _macroOffset[param1 % kMaxMacroOffsets];
|
||||
channel.macroIndex = param1 & (kMaxMacroOffsets - 1);
|
||||
channel.macroOffset = _macroOffset[param1 & (kMaxMacroOffsets - 1)];
|
||||
channel.relVol = (param2 >> 4) & 0xF;
|
||||
channel.fineTune = (int8)param3;
|
||||
|
||||
|
@ -893,11 +890,11 @@ void Tfmx::doMacro(int note, int macro, int relVol, int finetune, int channelNo)
|
|||
assert(0 <= note && note < 0xC0);
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
channelNo %= kNumVoices;
|
||||
channelNo &= (kNumVoices - 1);
|
||||
ChannelContext &channel = _channelCtx[channelNo];
|
||||
unlockMacroChannel(channel);
|
||||
|
||||
noteCommand((uint8)note, (uint8)macro, (uint8)(relVol << 4) | channelNo, finetune);
|
||||
noteCommand((uint8)note, (uint8)macro, (uint8)(relVol << 4) | channelNo, (uint8)finetune);
|
||||
startPaula();
|
||||
}
|
||||
|
||||
|
@ -926,14 +923,14 @@ void Tfmx::doSong(int songPos, bool stopAudio) {
|
|||
_trackCtx.startInd = _trackCtx.posInd = _subsong[songPos].songstart;
|
||||
_trackCtx.stopInd = _subsong[songPos].songend;
|
||||
|
||||
const bool palFlag = (_resource.headerFlags & 2);
|
||||
const bool palFlag = (_resource.headerFlags & 2) != 0;
|
||||
const uint16 tempo = _subsong[songPos].tempo;
|
||||
uint16 ciaIntervall;
|
||||
if (tempo >= 0x10) {
|
||||
ciaIntervall = (uint16)(kCiaBaseInterval / tempo);
|
||||
_playerCtx.patternSkip = 0;
|
||||
} else {
|
||||
ciaIntervall = palFlag ? kPalDefaultCiaVal : kNtscDefaultCiaVal;
|
||||
ciaIntervall = palFlag ? (uint16)kPalDefaultCiaVal : (uint16)kNtscDefaultCiaVal;
|
||||
_playerCtx.patternSkip = tempo;
|
||||
}
|
||||
setInterruptFreqUnscaled(ciaIntervall);
|
||||
|
@ -944,7 +941,7 @@ void Tfmx::doSong(int songPos, bool stopAudio) {
|
|||
startPaula();
|
||||
}
|
||||
|
||||
int Tfmx::doSfx(int sfxIndex, bool unlockChannel) {
|
||||
int Tfmx::doSfx(uint16 sfxIndex, bool unlockChannel) {
|
||||
assert(0 <= sfxIndex && sfxIndex < 128);
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
|
@ -955,8 +952,7 @@ int Tfmx::doSfx(int sfxIndex, bool unlockChannel) {
|
|||
const int8 patExp = (int8)sfxEntry[3];
|
||||
} else {
|
||||
// custommacro
|
||||
const byte channelNo = sfxEntry[2] % kNumVoices;
|
||||
const byte index = (_playerCtx.song >= 0) ? sfxEntry[2] : sfxEntry[4];
|
||||
const byte channelNo = ((_playerCtx.song >= 0) ? sfxEntry[2] : sfxEntry[4]) & (kNumVoices - 1);
|
||||
const byte priority = sfxEntry[5] & 0x7F;
|
||||
|
||||
ChannelContext &channel = _channelCtx[channelNo];
|
||||
|
|
|
@ -48,12 +48,12 @@ public:
|
|||
void interrupt();
|
||||
void stopSong(bool stopAudio = true);
|
||||
void doSong(int songPos, bool stopAudio = false);
|
||||
int doSfx(int sfxIndex, bool unlockChannel = false);
|
||||
int doSfx(uint16 sfxIndex, bool unlockChannel = false);
|
||||
void doMacro(int note, int macro, int relVol = 0, int finetune = 0, int channelNo = 0);
|
||||
bool load(Common::SeekableReadStream &musicData, Common::SeekableReadStream &sampleData);
|
||||
int getTicks() {return _playerCtx.tickCount;}
|
||||
int getSongIndex() {return _playerCtx.song;}
|
||||
uint16 getSignal(int index) {return (index < ARRAYSIZE(_playerCtx.signal)) ? _playerCtx.signal[index] : 0xFFFF;}
|
||||
int getTicks() const {return _playerCtx.tickCount;}
|
||||
int getSongIndex() const {return _playerCtx.song;}
|
||||
void setSignalPtr(uint16 *ptr) {_playerCtx.signal = ptr;}
|
||||
void stopMacroEffect(int channel) {
|
||||
assert(0 <= channel && channel < kNumVoices);
|
||||
Common::StackLock lock(_mutex);
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
uint32 headerUnknown;
|
||||
char textField[6 * 40];
|
||||
|
||||
const byte *getSfxPtr(uint8 index = 0) {
|
||||
const byte *getSfxPtr(uint16 index = 0) {
|
||||
byte *sfxPtr = (byte *)(_mdatData + _sfxTableOffset + index * 8);
|
||||
|
||||
boundaryCheck(_mdatData, _mdatLen, sfxPtr, 8);
|
||||
|
@ -223,11 +223,11 @@ public:
|
|||
|
||||
int tickCount;
|
||||
|
||||
uint16 signal[4];
|
||||
uint16 *signal;
|
||||
|
||||
bool stopWithLastPattern; //!< hack to automatically stop the whole player if no Pattern is running
|
||||
} _playerCtx;
|
||||
|
||||
private:
|
||||
static void initMacroProgramm(ChannelContext &channel) {
|
||||
channel.macroStep = 0;
|
||||
channel.macroWait = 0;
|
||||
|
@ -271,20 +271,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void setNoteMacro(ChannelContext &channel, uint note, int fineTune) {
|
||||
static void setNoteMacro(ChannelContext &channel, uint note, int fineTune) {
|
||||
const uint16 noteInt = noteIntervalls[note & 0x3F];
|
||||
const uint16 finetune = (uint16)(fineTune + channel.fineTune + (1 << 8));
|
||||
channel.refPeriod = ((uint32)noteInt * finetune >> 8);
|
||||
if (!channel.portaDelta) {
|
||||
if (!channel.portaDelta)
|
||||
channel.period = channel.refPeriod;
|
||||
//Paula::setChannelPeriod(channel.paulaChannel, channel.period);
|
||||
}
|
||||
}
|
||||
|
||||
void effects(ChannelContext &channel);
|
||||
FORCEINLINE bool macroStep(ChannelContext &channel);
|
||||
inline bool macroStep(ChannelContext &channel);
|
||||
void advancePatterns();
|
||||
FORCEINLINE bool patternStep(PatternContext &pattern, bool &pendingTrackstep);
|
||||
inline bool patternStep(PatternContext &pattern, bool &pendingTrackstep);
|
||||
bool trackStep();
|
||||
void noteCommand(uint8 note, uint8 param1, uint8 param2, uint8 param3);
|
||||
};
|
||||
|
|
|
@ -79,7 +79,6 @@ const char *const trackstepFmt[] = {
|
|||
"Tempo tempo/ciaDiv",
|
||||
"Timeshare ?/? ",
|
||||
"Fade start/end "
|
||||
"Unknown (cc) "
|
||||
};
|
||||
|
||||
void displayPatternstep(const void *const vptr) {
|
||||
|
|
|
@ -110,7 +110,7 @@ void tfmxmain(const int argc, const char *const argv[]) {
|
|||
param = atoi(argv[++i]);
|
||||
debug( "play Macro %02X", param);
|
||||
dumpMacro(*player, param);
|
||||
player->doMacro(param,param);
|
||||
player->doMacro(0x1B, param);
|
||||
hasCmd = true;
|
||||
}
|
||||
} else if (!strcmp("-s", argv[i])) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue