Added preliminary support for blargg's Gb_Apu

This commit is contained in:
mudlord 2007-12-04 09:08:44 +00:00
parent 50b9e5ff4d
commit 872441ce20
5 changed files with 359 additions and 883 deletions

View File

@ -32,11 +32,14 @@ MAINDIR=src
SDLDIR=src/sdl
DMGDIR=src/gb
RESAMPLEDIR=src/libresample-0.1.3/src
GBAPUDIR=src/gb/gb_apu
ASMOBJ=${MAINDIR}/hq3x_16${OE} ${MAINDIR}/hq3x_32${OE} ${MAINDIR}/hq4x_16${OE} ${MAINDIR}/hq4x_32${OE} \
${MAINDIR}/hq3x32${OE}
GBAPUOBJ=${GBAPUDIR}/Blip_Buffer${OE} ${GBAPUDIR}/Effects_Buffer${OE} ${GBAPUDIR}/Gb_Apu${OE} \
${GBAPUDIR}/Gb_Apu_State${OE} ${GBAPUDIR}/Gb_Oscs${OE} ${GBAPUDIR}/Multi_Buffer${OE}
CALTERNOBJ=${MAINDIR}/hq3x16c${OE} ${MAINDIR}/hq3x32c${OE} ${MAINDIR}/hq4x16c${OE} ${MAINDIR}/hq4x32c${OE} \
${MAINDIR}/hq_shared32${OE}
@ -58,7 +61,7 @@ ${DMGDIR}/gbSound${OE}
SDLOBJ=${SDLDIR}/debugger${OE} ${SDLDIR}/SDL${OE} ${SDLDIR}/dummy${OE}
OBJECTS=${MAINOBJ} ${DMGOBJ} ${SDLOBJ}
OBJECTS=${MAINOBJ} ${DMGOBJ} ${SDLOBJ} ${GBAPUOBJ}
LIB=${RESAMPLEDIR}/filterkit${OE} ${RESAMPLEDIR}/resample${OE} ${RESAMPLEDIR}/resamplesubs${OE}
ifeq ($(USEASM),yes)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Version="8.00"
Name="VisualBoyAdvance"
ProjectGUID="{6D4C5EC8-933F-4C05-A1BF-498E658576DF}"
RootNamespace="VBA"
@ -129,115 +129,6 @@
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)_temp"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2"
BuildLogFile="$(IntDir)\$(ProjectName)_BuildLog.htm"
>
<Tool
Name="VCPreBuildEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="0"
AdditionalIncludeDirectories="..\dependencies\zlib;..\dependencies\libpng;&quot;..\dependencies\File_Extractor-0.4.2\fex&quot;;..\dependencies\cximage;..\dependencies\msvc"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;DEV_VERSION;BKPT_SUPPORT;CRT_SECURE_NO_WARNINGS;HAS_FILE_EXTRACTOR;C_CORE"
StringPooling="false"
MinimalRebuild="true"
BasicRuntimeChecks="3"
SmallerTypeCheck="false"
RuntimeLibrary="1"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)\$(ProjectName).pdb"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib Vfw32.Lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateManifest="true"
AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
IgnoreDefaultLibraryNames="nafxcwd.lib;LIBCMTD.lib"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="1"
EnableCOMDATFolding="1"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
@ -360,6 +251,115 @@
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)_temp"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2"
BuildLogFile="$(IntDir)\$(ProjectName)_BuildLog.htm"
>
<Tool
Name="VCPreBuildEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/MP"
Optimization="0"
AdditionalIncludeDirectories="..\dependencies\zlib;..\dependencies\libpng;&quot;..\dependencies\File_Extractor-0.4.2\fex&quot;;..\dependencies\cximage;..\dependencies\msvc"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;DEV_VERSION;BKPT_SUPPORT;CRT_SECURE_NO_WARNINGS;HAS_FILE_EXTRACTOR;C_CORE"
StringPooling="false"
MinimalRebuild="true"
BasicRuntimeChecks="3"
SmallerTypeCheck="false"
RuntimeLibrary="1"
StructMemberAlignment="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)\$(ProjectName).pdb"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories=""
/>
<Tool
Name="VCPreLinkEventTool"
ExcludedFromBuild="true"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="nafxcwd.lib LIBCMTD.lib Vfw32.Lib OpenGL32.Lib dinput8.lib dxguid.lib ddraw.lib winmm.lib Dsound.lib"
OutputFile="$(OutDir)\VisualBoyAdvance.exe"
Version=""
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateManifest="true"
AdditionalManifestDependencies="type=&apos;win32&apos; name=&apos;Microsoft.Windows.Common-Controls&apos; version=&apos;6.0.0.0&apos; processorArchitecture=&apos;amd64&apos; publicKeyToken=&apos;6595b64144ccf1df&apos; language=&apos;*&apos;"
IgnoreDefaultLibraryNames="nafxcwd.lib;LIBCMTD.lib"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="1"
EnableCOMDATFolding="1"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
ExcludedFromBuild="true"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(ProjectDir)$(PlatformName)\$(ConfigurationName)"
@ -528,16 +528,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
@ -548,6 +538,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -623,16 +623,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
@ -643,6 +633,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -667,16 +667,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
@ -687,6 +677,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -711,16 +711,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
@ -731,6 +721,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -755,16 +755,6 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
@ -775,6 +765,16 @@
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Assembling $(InputFileName)..."
CommandLine="nasm -D__DJGPP__ -O1 -Isrc/ -f win64 -o &quot;$(IntDir)\$(InputName).obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="&quot;$(IntDir)\$(InputName).obj&quot;"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
@ -1015,6 +1015,66 @@
RelativePath=".\src\gb\gbSound.cpp"
>
</File>
<Filter
Name="GB APU"
>
<File
RelativePath=".\src\gb\gb_apu\blargg_common.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\blargg_config.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\blargg_source.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Blip_Buffer.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Blip_Buffer.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Effects_Buffer.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Effects_Buffer.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Gb_Apu.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Gb_Apu.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Gb_Apu_State.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Gb_Oscs.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Gb_Oscs.h"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Multi_Buffer.cpp"
>
</File>
<File
RelativePath=".\src\gb\gb_apu\Multi_Buffer.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="UI"
@ -1319,7 +1379,7 @@
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
@ -1327,7 +1387,7 @@
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"

View File

@ -998,7 +998,8 @@ void gbWriteMemory(register u16 address, register u8 value)
case 0x3d:
case 0x3e:
case 0x3f: {
gbMemory[address] = value;
SOUND_EVENT(address,value);
//gbMemory[address] = value;
return;
}
@ -1783,6 +1784,9 @@ u8 gbReadMemory(register u16 address)
}
if(address >= 0xff00) {
if ( address >= 0xFF10 && address <= 0xFF3F )
return gbSoundRead( address );
switch(address & 0x00ff) {
case 0x00:
{
@ -2057,8 +2061,8 @@ void gbSpeedSwitch()
gbLcdLYIncrementTicksDelayed *= 2;
gbLcdLYIncrementTicksDelayed--;
gbSerialTicks *= 2;
SOUND_CLOCK_TICKS = soundQuality * 24 * 2;
soundTicks *= 2;
//SOUND_CLOCK_TICKS = soundQuality * 24 * 2;
//soundTicks *= 2;
gbLine99Ticks = 3;
} else {
gbSpeed = 0;
@ -2080,8 +2084,8 @@ void gbSpeedSwitch()
gbLcdLYIncrementTicksDelayed++;
gbLcdLYIncrementTicksDelayed >>= 1;
gbSerialTicks /= 2;
SOUND_CLOCK_TICKS = soundQuality * 24;
soundTicks /= 2;
//SOUND_CLOCK_TICKS = soundQuality * 24;
//soundTicks /= 2;
gbLine99Ticks = 1;
if (gbHardware & 8)
gbLine99Ticks++;
@ -4312,8 +4316,8 @@ int gbGetNextEvent (int clockTicks)
if(gbTimerOn && (((gbInternalTimer) & gbTimerMask[gbTimerMode])+1 < clockTicks))
clockTicks = ((gbInternalTimer) & gbTimerMask[gbTimerMode])+1;
if(soundTicks && (soundTicks < clockTicks))
clockTicks = soundTicks;
//if(soundTicks && (soundTicks < clockTicks))
// clockTicks = soundTicks;
if ((clockTicks<=0) || (gbInterruptWait))
clockTicks = 1;
@ -5205,7 +5209,9 @@ void gbEmulate(int ticksToStop)
soundTicks -= clockTicks;
if ( !gbSpeed )
soundTicks -= clockTicks;
while(soundTicks < 0) {
soundTicks += SOUND_CLOCK_TICKS;

View File

@ -23,6 +23,12 @@
#include "gbGlobals.h"
#include "gbSound.h"
#include "gb_apu/Gb_Apu.h"
#include "gb_apu/Effects_Buffer.h"
static Gb_Apu* gb_apu;
static Simple_Effects_Buffer* stereo_buffer;
extern u8 soundBuffer[6][735];
extern u16 soundFinalWave[1470];
extern int soundVolume;
@ -134,6 +140,24 @@ extern bool soundOffFlag;
bool gbDigitalSound = false;
static inline blip_time_t ticks_to_time( int ticks )
{
return ticks * 2;
}
static inline blip_time_t blip_time()
{
return ticks_to_time( SOUND_CLOCK_TICKS - soundTicks );
}
u8 gbSoundRead( u16 address )
{
if ( gb_apu && address >= NR10 && address <= 0xFF3F )
return gb_apu->read_register( blip_time(), address );
return gbMemory[address];
}
void gbSoundEvent(register u16 address, register int data)
{
int freq = 0;
@ -146,626 +170,118 @@ void gbSoundEvent(register u16 address, register int data)
log("Sound event: %08lx %02x\n", address, data);
}
#endif
switch(address) {
case NR10:
gbMemory[address] = data | 0x80;
sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7);
sound1SweepSteps = data & 7;
sound1SweepUpDown = data & 0x08;
sound1SweepStep = 0;
break;
case NR11:
gbMemory[address] = data | 0x3f;
sound1Wave = soundWavePattern[data >> 6];
sound1ATL = sound1ATLreload = 172 * (64 - (data & 0x3f));
break;
case NR12:
sound1EnvelopeVolume = data >> 4;
sound1EnvelopeUpDown = data & 0x08;
sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7);
break;
case NR13:
gbMemory[address] = 0xff;
freq1low = data;
freq = ((((int)(freq1high & 7)) << 8) | freq1low);
sound1ATL = sound1ATLreload;
freq = 2048 - freq;
if(freq) {
sound1Skip = SOUND_MAGIC / freq;
} else
sound1Skip = 0;
break;
case NR14:
gbMemory[address] = data | 0xbf;
freq1high = data;
freq = ((((int)(freq1high & 7)) << 8) | freq1low);
freq = 2048 - freq;
sound1ATL = sound1ATLreload;
sound1Continue = data & 0x40;
if(freq) {
sound1Skip = SOUND_MAGIC / freq;
} else
sound1Skip = 0;
if(data & 0x80) {
gbMemory[NR52] |= 1;
sound1EnvelopeVolume = gbMemory[NR12] >> 4;
sound1EnvelopeUpDown = gbMemory[NR12] & 0x08;
sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7);
sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7);
sound1SweepSteps = gbMemory[NR10] & 7;
sound1SweepUpDown = gbMemory[NR10] & 0x08;
sound1SweepStep = 0;
sound1Index = 0;
sound1On = 1;
}
break;
case NR21:
gbMemory[address] = data | 0x3f;
sound2Wave = soundWavePattern[data >> 6];
sound2ATL = sound2ATLreload = 172 * (64 - (data & 0x3f));
break;
case NR22:
sound2EnvelopeVolume = data >> 4;
sound2EnvelopeUpDown = data & 0x08;
sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7);
break;
case NR23:
gbMemory[address] = 0xff;
freq2low = data;
freq = (((int)(freq2high & 7)) << 8) | freq2low;
sound2ATL = sound2ATLreload;
freq = 2048 - freq;
if(freq) {
sound2Skip = SOUND_MAGIC / freq;
} else
sound2Skip = 0;
break;
case NR24:
gbMemory[address] = data | 0xbf;
freq2high = data;
freq = (((int)(freq2high & 7)) << 8) | freq2low;
freq = 2048 - freq;
sound2ATL = sound2ATLreload;
sound2Continue = data & 0x40;
if(freq) {
sound2Skip = SOUND_MAGIC / freq;
} else
sound2Skip = 0;
if(data & 0x80) {
gbMemory[NR52] |= 2;
sound2EnvelopeVolume = gbMemory[NR22] >> 4;
sound2EnvelopeUpDown = gbMemory[NR22] & 0x08;
sound2ATL = sound2ATLreload;
sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7);
sound2Index = 0;
sound2On = 1;
}
break;
case NR30:
gbMemory[address] = data | 0x7f;
if(!(data & 0x80)) {
gbMemory[NR52] &= 0xfb;
sound3On = 0;
}
break;
case NR31:
gbMemory[address] = 0xff;
sound3ATL = sound3ATLreload = 172 * (256-data);
break;
case NR32:
gbMemory[address] = data | 0x9f;
sound3OutputLevel = (data >> 5) & 3;
break;
case NR33:
gbMemory[address] = 0xff;
freq3low = data;
freq = 2048 - (((int)(freq3high&7) << 8) | freq3low);
if(freq) {
sound3Skip = SOUND_MAGIC_2 / freq;
} else
sound3Skip = 0;
break;
case NR34:
gbMemory[address] = data | 0xbf;
freq3high = data;
freq = 2048 - (((int)(freq3high&7) << 8) | freq3low);
if(freq) {
sound3Skip = SOUND_MAGIC_2 / freq;
} else {
sound3Skip = 0;
}
sound3Continue = data & 0x40;
if((data & 0x80) && (gbMemory[NR30] & 0x80)) {
gbMemory[NR52] |= 4;
sound3ATL = sound3ATLreload;
sound3Index = 0;
sound3On = 1;
}
break;
case NR41:
sound4ATL = sound4ATLreload = 172 * (64 - (data & 0x3f));
break;
case NR42:
sound4EnvelopeVolume = data >> 4;
sound4EnvelopeUpDown = data & 0x08;
sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7);
break;
case NR43:
freq = freq4 = soundFreqRatio[data & 7];
sound4NSteps = data & 0x08;
sound4Skip = (freq << 8) / NOISE_MAGIC;
sound4Clock = data >> 4;
freq = freq / soundShiftClock[sound4Clock];
sound4ShiftSkip = (freq << 8) / NOISE_MAGIC;
break;
case NR44:
gbMemory[address] = data | 0xbf;
sound4Continue = data & 0x40;
if(data & 0x80) {
gbMemory[NR52] |= 8;
sound4EnvelopeVolume = gbMemory[NR42] >> 4;
sound4EnvelopeUpDown = gbMemory[NR42] & 0x08;
sound4ATL = sound4ATLreload;
sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7);
sound4On = 1;
sound4Index = 0;
sound4ShiftIndex = 0;
if(sound4NSteps)
sound4ShiftRight = 0x7fff;
else
sound4ShiftRight = 0x7f;
}
break;
case NR50:
soundVIN = data & 0x88;
soundLevel1 = data & 7;
soundLevel2 = (data >> 4) & 7;
break;
case NR51:
soundBalance = (data & soundEnableFlag);
break;
case NR52:
soundMasterOn = data & 0x80;
if(!(data & 0x80)) {
sound1On = 0;
sound2On = 0;
sound3On = 0;
sound4On = 0;
gbMemory[address] &= 0xf0;
}
gbMemory[address] = data & 0x80 | 0x70 | (gbMemory[address] & 0xf);
break;
}
gbDigitalSound = true;
if(sound1On && sound1EnvelopeVolume != 0)
gbDigitalSound = false;
if(sound2On && sound2EnvelopeVolume != 0)
gbDigitalSound = false;
if(sound3On && sound3OutputLevel != 0)
gbDigitalSound = false;
if(sound4On && sound4EnvelopeVolume != 0)
gbDigitalSound = false;
if ( gb_apu && address >= NR10 && address <= 0xFF3F )
gb_apu->write_register( blip_time(), address, data );
}
void gbSoundChannel1()
void gbSoundChannel1()
{
int vol = sound1EnvelopeVolume;
int freq = 0;
int value = 0;
if(sound1On && (sound1ATL || !sound1Continue)) {
sound1Index += soundQuality*sound1Skip;
sound1Index &= 0x1fffffff;
value = ((s8)sound1Wave[sound1Index>>24]) * vol;
}
soundBuffer[0][soundIndex] = value;
if(sound1On) {
if(sound1ATL) {
sound1ATL-=soundQuality;
if(sound1ATL <=0 && sound1Continue) {
gbMemory[NR52] &= 0xfe;
sound1On = 0;
}
}
if(sound1EnvelopeATL) {
sound1EnvelopeATL-=soundQuality;
if(sound1EnvelopeATL<=0) {
if(sound1EnvelopeUpDown) {
if(sound1EnvelopeVolume < 15)
sound1EnvelopeVolume++;
} else {
if(sound1EnvelopeVolume)
sound1EnvelopeVolume--;
}
sound1EnvelopeATL += sound1EnvelopeATLReload;
}
}
if(sound1SweepATL) {
sound1SweepATL-=soundQuality;
if(sound1SweepATL<=0) {
freq = (((int)(freq1high & 7)) << 8) | freq1low;
int updown = 1;
if(sound1SweepUpDown)
updown = -1;
int newfreq = 0;
if(sound1SweepSteps) {
newfreq = freq + updown * freq / (1 << sound1SweepSteps);
if(newfreq == freq)
newfreq = 0;
} else
newfreq = freq;
if(newfreq < 0) {
sound1SweepATL += sound1SweepATLReload;
} else if(newfreq > 2047) {
sound1SweepATL = 0;
sound1On = 0;
gbMemory[NR52] &= 0xfe;
} else {
sound1SweepATL += sound1SweepATLReload;
sound1Skip = SOUND_MAGIC/(2048 - newfreq);
freq1low = newfreq & 0xff;
freq1high = (freq1high & 0xf8) |((newfreq >> 8) & 7);
}
}
}
}
}
void gbSoundChannel2()
{
// int freq = 0;
int vol = sound2EnvelopeVolume;
int value = 0;
if(sound2On && (sound2ATL || !sound2Continue)) {
sound2Index += soundQuality*sound2Skip;
sound2Index &= 0x1fffffff;
value = ((s8)sound2Wave[sound2Index>>24]) * vol;
}
soundBuffer[1][soundIndex] = value;
if(sound2On) {
if(sound2ATL) {
sound2ATL-=soundQuality;
if(sound2ATL <= 0 && sound2Continue) {
gbMemory[NR52] &= 0xfd;
sound2On = 0;
}
}
if(sound2EnvelopeATL) {
sound2EnvelopeATL-=soundQuality;
if(sound2EnvelopeATL <= 0) {
if(sound2EnvelopeUpDown) {
if(sound2EnvelopeVolume < 15)
sound2EnvelopeVolume++;
} else {
if(sound2EnvelopeVolume)
sound2EnvelopeVolume--;
}
sound2EnvelopeATL += sound2EnvelopeATLReload;
}
}
}
}
void gbSoundChannel3()
{
int value = 0;
if(sound3On && (sound3ATL || !sound3Continue)) {
value = sound3Last;
sound3Index += soundQuality*sound3Skip;
sound3Index &= 0x1fffffff;
value = gbMemory[0xff30 + (sound3Index>>25)];
if( (sound3Index & 0x01000000)) {
value &= 0x0f;
} else {
value >>= 4;
}
value -= 8;
switch(sound3OutputLevel) {
case 0:
value = 0;
break;
case 1:
break;
case 2:
value = (value >> 1);
break;
case 3:
value = (value >> 2);
break;
}
sound3Last = value;
}
soundBuffer[2][soundIndex] = value;
if(sound3On) {
if(sound3ATL) {
sound3ATL-=soundQuality;
if(sound3ATL <= 0 && sound3Continue) {
gbMemory[NR52] &= 0xfb;
sound3On = 0;
}
}
}
}
void gbSoundChannel4()
{
int vol = sound4EnvelopeVolume;
int value = 0;
if(sound4Clock <= 0x0c) {
if(sound4On && (sound4ATL || !sound4Continue)) {
sound4Index += soundQuality*sound4Skip;
sound4ShiftIndex += soundQuality*sound4ShiftSkip;
if(sound4NSteps) {
while(sound4ShiftIndex > 0x1fffff) {
sound4ShiftRight = (((sound4ShiftRight << 6) ^
(sound4ShiftRight << 5)) & 0x40) |
(sound4ShiftRight >> 1);
sound4ShiftIndex -= 0x200000;
}
} else {
while(sound4ShiftIndex > 0x1fffff) {
sound4ShiftRight = (((sound4ShiftRight << 14) ^
(sound4ShiftRight << 13)) & 0x4000) |
(sound4ShiftRight >> 1);
sound4ShiftIndex -= 0x200000;
}
}
sound4Index &= 0x1fffff;
sound4ShiftIndex &= 0x1fffff;
value = ((sound4ShiftRight & 1)*2-1) * vol;
} else {
value = 0;
}
}
soundBuffer[3][soundIndex] = value;
if(sound4On) {
if(sound4ATL) {
sound4ATL-=soundQuality;
if(sound4ATL <= 0 && sound4Continue) {
gbMemory[NR52] &= 0xf7;
sound4On = 0;
}
}
if(sound4EnvelopeATL) {
sound4EnvelopeATL-=soundQuality;
if(sound4EnvelopeATL <= 0) {
if(sound4EnvelopeUpDown) {
if(sound4EnvelopeVolume < 15)
sound4EnvelopeVolume++;
} else {
if(sound4EnvelopeVolume)
sound4EnvelopeVolume--;
}
sound4EnvelopeATL += sound4EnvelopeATLReload;
}
}
}
}
void gbSoundMix()
static void end_frame( blip_time_t time )
{
int res = 0;
gb_apu->end_frame( time );
stereo_buffer->end_frame( time );
}
if(soundBalance & 16) {
res += ((s8)soundBuffer[0][soundIndex]);
}
if(soundBalance & 32) {
res += ((s8)soundBuffer[1][soundIndex]);
}
if(soundBalance & 64) {
res += ((s8)soundBuffer[2][soundIndex]);
}
if(soundBalance & 128) {
res += ((s8)soundBuffer[3][soundIndex]);
}
static void flush_samples()
{
int const out_buf_size = soundBufferLen / sizeof *soundFinalWave;
while ( stereo_buffer->samples_avail() >= out_buf_size )
{
stereo_buffer->read_samples( (blip_sample_t*) soundFinalWave, out_buf_size );
if(systemSoundOn)
{
if(soundPaused)
soundResume();
if(gbDigitalSound)
res *= soundLevel1*256;
else
res *= soundLevel1*60;
systemWriteDataToSoundBuffer();
}
soundIndex = 0;
soundBufferIndex = 0;
}
}
if(soundEcho) {
res *= 2;
res += soundFilter[soundEchoIndex];
res /= 2;
soundFilter[soundEchoIndex++] = res;
}
int const chan_count = 4;
if(soundLowPass) {
soundLeft[4] = soundLeft[3];
soundLeft[3] = soundLeft[2];
soundLeft[2] = soundLeft[1];
soundLeft[1] = soundLeft[0];
soundLeft[0] = res;
res = (soundLeft[4] + 2*soundLeft[3] + 8*soundLeft[2] + 2*soundLeft[1] +
soundLeft[0])/14;
}
gb_effects_config_t gb_effects_config;
static gb_effects_config_t gb_effects_config_current;
switch(soundVolume) {
case 0:
case 1:
case 2:
case 3:
res *= (soundVolume+1);
break;
case 4:
res >>= 2;
break;
case 5:
res >>= 1;
break;
}
if(res > 32767)
res = 32767;
if(res < -32768)
res = -32768;
if(soundReverse)
soundFinalWave[++soundBufferIndex] = res;
else
soundFinalWave[soundBufferIndex++] = res;
res = 0;
if(soundBalance & 1) {
res += ((s8)soundBuffer[0][soundIndex]);
}
if(soundBalance & 2) {
res += ((s8)soundBuffer[1][soundIndex]);
}
if(soundBalance & 4) {
res += ((s8)soundBuffer[2][soundIndex]);
}
if(soundBalance & 8) {
res += ((s8)soundBuffer[3][soundIndex]);
}
if(gbDigitalSound)
res *= soundLevel2*256;
else
res *= soundLevel2*60;
if(soundEcho) {
res *= 2;
res += soundFilter[soundEchoIndex];
res /= 2;
soundFilter[soundEchoIndex++] = res;
if(soundEchoIndex >= 4000)
soundEchoIndex = 0;
}
if(soundLowPass) {
soundRight[4] = soundRight[3];
soundRight[3] = soundRight[2];
soundRight[2] = soundRight[1];
soundRight[1] = soundRight[0];
soundRight[0] = res;
res = (soundRight[4] + 2*soundRight[3] + 8*soundRight[2] + 2*soundRight[1] +
soundRight[0])/14;
}
switch(soundVolume) {
case 0:
case 1:
case 2:
case 3:
res *= (soundVolume+1);
break;
case 4:
res >>= 2;
break;
case 5:
res >>= 1;
break;
}
if(res > 32767)
res = 32767;
if(res < -32768)
res = -32768;
if(soundReverse)
soundFinalWave[-1+soundBufferIndex++] = res;
else
soundFinalWave[soundBufferIndex++] = res;
static void apply_effects()
{
gb_effects_config_current = gb_effects_config;
stereo_buffer->config().enabled = gb_effects_config_current.enabled;
stereo_buffer->config().echo = gb_effects_config_current.echo;
stereo_buffer->config().stereo = gb_effects_config_current.stereo;
stereo_buffer->config().surround = gb_effects_config_current.surround;
stereo_buffer->apply_config();
for ( int i = 0; i < chan_count; i++ )
{
Multi_Buffer::channel_t ch = stereo_buffer->channel( i );
gb_apu->set_output( ch.center, ch.left, ch.right, i );
}
}
void gbSoundTick()
{
if(systemSoundOn) {
if(soundMasterOn) {
gbSoundChannel1();
gbSoundChannel2();
gbSoundChannel3();
gbSoundChannel4();
if(systemSoundOn && gb_apu && stereo_buffer)
{
end_frame( ticks_to_time( SOUND_CLOCK_TICKS ) );
flush_samples();
// Update effects config if it was changed
if ( memcmp( &gb_effects_config_current, &gb_effects_config,
sizeof gb_effects_config ) )
apply_effects();
}
}
gbSoundMix();
} else {
soundFinalWave[soundBufferIndex++] = 0;
soundFinalWave[soundBufferIndex++] = 0;
}
soundIndex++;
if(2*soundBufferIndex >= soundBufferLen) {
if(systemSoundOn) {
if(soundPaused) {
soundResume();
}
systemWriteDataToSoundBuffer();
}
soundIndex = 0;
soundBufferIndex = 0;
}
}
static void remake_stereo_buffer()
{
if ( !gb_apu )
gb_apu = new Gb_Apu;
delete stereo_buffer;
stereo_buffer = 0;
stereo_buffer = new Simple_Effects_Buffer;
stereo_buffer->set_sample_rate( 44100 / soundQuality );
stereo_buffer->clock_rate( gb_apu->clock_rate );
static int const chan_types [chan_count] = {
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
};
stereo_buffer->set_channel_count( chan_count, chan_types );
apply_effects();
gb_apu->reset( gb_apu->mode_cgb );
}
void gbSoundReset()
{
{
remake_stereo_buffer();
soundPaused = 1;
soundPlay = 0;
SOUND_CLOCK_TICKS = soundQuality * 24;
SOUND_CLOCK_TICKS = 20000;
soundTicks = SOUND_CLOCK_TICKS;
soundNextPosition = 0;
soundMasterOn = 1;
@ -891,144 +407,22 @@ void gbSoundSetQuality(int quality)
soundNextPosition = 0;
if(!soundOffFlag)
soundInit();
SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
//SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
soundIndex = 0;
soundBufferIndex = 0;
} else {
soundNextPosition = 0;
SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
//SOUND_CLOCK_TICKS = (gbSpeed ? 2 : 1) * 24 * soundQuality;
soundIndex = 0;
soundBufferIndex = 0;
}
remake_stereo_buffer();
}
variable_desc gbSoundSaveStruct[] = {
{ &soundPaused, sizeof(int) },
{ &soundPlay, sizeof(int) },
{ &soundTicks, sizeof(int) },
{ &SOUND_CLOCK_TICKS, sizeof(int) },
{ &soundLevel1, sizeof(int) },
{ &soundLevel2, sizeof(int) },
{ &soundBalance, sizeof(int) },
{ &soundMasterOn, sizeof(int) },
{ &soundIndex, sizeof(int) },
{ &soundVIN, sizeof(int) },
{ &sound1On, sizeof(int) },
{ &sound1ATL, sizeof(int) },
{ &sound1Skip, sizeof(int) },
{ &sound1Index, sizeof(int) },
{ &sound1Continue, sizeof(int) },
{ &sound1EnvelopeVolume, sizeof(int) },
{ &sound1EnvelopeATL, sizeof(int) },
{ &sound1EnvelopeATLReload, sizeof(int) },
{ &sound1EnvelopeUpDown, sizeof(int) },
{ &sound1SweepATL, sizeof(int) },
{ &sound1SweepATLReload, sizeof(int) },
{ &sound1SweepSteps, sizeof(int) },
{ &sound1SweepUpDown, sizeof(int) },
{ &sound1SweepStep, sizeof(int) },
{ &sound2On, sizeof(int) },
{ &sound2ATL, sizeof(int) },
{ &sound2Skip, sizeof(int) },
{ &sound2Index, sizeof(int) },
{ &sound2Continue, sizeof(int) },
{ &sound2EnvelopeVolume, sizeof(int) },
{ &sound2EnvelopeATL, sizeof(int) },
{ &sound2EnvelopeATLReload, sizeof(int) },
{ &sound2EnvelopeUpDown, sizeof(int) },
{ &sound3On, sizeof(int) },
{ &sound3ATL, sizeof(int) },
{ &sound3Skip, sizeof(int) },
{ &sound3Index, sizeof(int) },
{ &sound3Continue, sizeof(int) },
{ &sound3OutputLevel, sizeof(int) },
{ &sound4On, sizeof(int) },
{ &sound4ATL, sizeof(int) },
{ &sound4Skip, sizeof(int) },
{ &sound4Index, sizeof(int) },
{ &sound4Clock, sizeof(int) },
{ &sound4ShiftRight, sizeof(int) },
{ &sound4ShiftSkip, sizeof(int) },
{ &sound4ShiftIndex, sizeof(int) },
{ &sound4NSteps, sizeof(int) },
{ &sound4CountDown, sizeof(int) },
{ &sound4Continue, sizeof(int) },
{ &sound4EnvelopeVolume, sizeof(int) },
{ &sound4EnvelopeATL, sizeof(int) },
{ &sound4EnvelopeATLReload, sizeof(int) },
{ &sound4EnvelopeUpDown, sizeof(int) },
{ &soundEnableFlag, sizeof(int) },
{ NULL, 0 }
};
void gbSoundSaveGame(gzFile gzFile)
{
utilWriteData(gzFile, gbSoundSaveStruct);
utilWriteInt(gzFile, sound1ATLreload);
utilWriteInt(gzFile, freq1low);
utilWriteInt(gzFile, freq1high);
utilWriteInt(gzFile, sound2ATLreload);
utilWriteInt(gzFile, freq2low);
utilWriteInt(gzFile, freq2high);
utilWriteInt(gzFile, sound3ATLreload);
utilWriteInt(gzFile, freq3low);
utilWriteInt(gzFile, freq3high);
utilWriteInt(gzFile, sound4ATLreload);
utilWriteInt(gzFile, freq4);
utilGzWrite(gzFile, soundBuffer, 4*735);
utilGzWrite(gzFile, soundFinalWave, 2*735);
utilGzWrite(gzFile, &soundQuality, sizeof(int));
}
void gbSoundReadGame(int version,gzFile gzFile)
{
utilReadData(gzFile, gbSoundSaveStruct);
if (version<11)
{
sound1ATLreload = 172 * (64 - (gbMemory[NR11] & 0x3f));
freq1low = gbMemory[NR13];
freq1high = gbMemory[NR14] & 7;
sound2ATLreload = 172 * (64 - (gbMemory[NR21] & 0x3f));
freq2low = gbMemory[NR23];
freq2high = gbMemory[NR24] & 7;
sound3ATLreload = 172 * (256 - gbMemory[NR31]);
freq3low = gbMemory[NR33];
freq3high = gbMemory[NR34] & 7;
sound4ATLreload = 172 * (64 - (gbMemory[NR41] & 0x3f));
freq4 = soundFreqRatio[gbMemory[NR43] & 7];
}
else
{
sound1ATLreload = utilReadInt(gzFile);
freq1low = utilReadInt(gzFile);
freq1high = utilReadInt(gzFile);
sound2ATLreload = utilReadInt(gzFile);
freq2low = utilReadInt(gzFile);
freq2high = utilReadInt(gzFile);
sound3ATLreload = utilReadInt(gzFile);
freq3low = utilReadInt(gzFile);
freq3high = utilReadInt(gzFile);
sound4ATLreload = utilReadInt(gzFile);
freq4 = utilReadInt(gzFile);
}
soundBufferIndex = soundIndex * 2;
utilGzRead(gzFile, soundBuffer, 4*735);
utilGzRead(gzFile, soundFinalWave, 2*735);
if(version >=7) {
int quality = 1;
utilGzRead(gzFile, &quality, sizeof(int));
gbSoundSetQuality(quality);
} else {
soundQuality = -1;
gbSoundSetQuality(1);
}
sound1Wave = soundWavePattern[gbMemory[NR11] >> 6];
sound2Wave = soundWavePattern[gbMemory[NR21] >> 6];
}

View File

@ -54,6 +54,19 @@ extern void gbSoundReadGame(int,gzFile);
extern void gbSoundEvent(register u16, register int);
extern void gbSoundSetQuality(int);
extern u8 gbSoundRead(u16 address);
extern int soundTicks;
extern int soundQuality;
extern int SOUND_CLOCK_TICKS;
struct gb_effects_config_t
{
bool enabled; // false = disable all effects
float echo; // 0.0 = none, 1.0 = lots
float stereo; // 0.0 = channels in center, 1.0 = channels on left/right
bool surround; // true = put some channels in back
};
// Can be changed at any time, probably from another thread too.
// Sound will notice changes during next 1/100 second.
extern gb_effects_config_t gb_effects_config;