Gambatte: Merge improvements from gifvex(mcmaeve)

Restores Bios support and loading GB games into GBC
Accuracy imrpovements
This commit is contained in:
alyosha-tas 2018-01-15 07:45:15 -05:00
parent c6bdae916f
commit e5ded9b139
57 changed files with 7492 additions and 7244 deletions

View File

@ -93,6 +93,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)"); throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)");
} }
if ((flags & LibGambatte.LoadFlags.FORCE_DMG) == LibGambatte.LoadFlags.FORCE_DMG)
{
byte[] Bios = comm.CoreFileProvider.GetFirmware("GB", "World", false, "BIOS Not Found, Cannot Load");
if (LibGambatte.gambatte_loaddmgbios(GambatteState, Bios) != 0)
{
throw new InvalidOperationException("gambatte_loaddmgbios() returned non-zero (bios error)");
}
}
else
{
byte[] Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", false, "BIOS Not Found, Cannot Load");
if (LibGambatte.gambatte_loadgbcbios(GambatteState, Bios) != 0)
{
throw new InvalidOperationException("gambatte_loadgbcbios() returned non-zero (bios error)");
}
}
// set real default colors (before anyone mucks with them at all) // set real default colors (before anyone mucks with them at all)
PutSettings((GambatteSettings)settings ?? new GambatteSettings()); PutSettings((GambatteSettings)settings ?? new GambatteSettings());

View File

@ -59,6 +59,24 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, long now, LoadFlags flags); public static extern int gambatte_load(IntPtr core, byte[] romdata, uint length, long now, LoadFlags flags);
/// <summary>
/// Load GB BIOS image.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="biosdata">the bios data, can be disposed of once this function returns</param>
/// <returns>0 on success, negative value on failure.</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_loaddmgbios(IntPtr core, byte[] biosdata);
/// <summary>
/// Load GBC BIOS image.
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="biosdata">the bios data, can be disposed of once this function returns</param>
/// <returns>0 on success, negative value on failure.</returns>
[DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gambatte_loadgbcbios(IntPtr core, byte[] biosdata);
/// <summary> /// <summary>
/// Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer, /// Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
/// or until a video frame has been drawn. /// or until a video frame has been drawn.

View File

@ -51,7 +51,8 @@ public:
enum LoadFlag { enum LoadFlag {
FORCE_DMG = 1, /**< Treat the ROM as not having CGB support regardless of what its header advertises. */ FORCE_DMG = 1, /**< Treat the ROM as not having CGB support regardless of what its header advertises. */
GBA_CGB = 2, /**< Use GBA intial CPU register values when in CGB mode. */ GBA_CGB = 2, /**< Use GBA intial CPU register values when in CGB mode. */
MULTICART_COMPAT = 4 /**< Use heuristics to detect and support some multicart MBCs disguised as MBC1. */ MULTICART_COMPAT = 4, /**< Use heuristics to detect and support some multicart MBCs disguised as MBC1. */
TRUE_COLOR = 8 /**< Use GBP color conversion instead of GBC-screen approximation */
}; };
/** Load ROM image. /** Load ROM image.
@ -62,6 +63,9 @@ public:
*/ */
int load(const char *romfiledata, unsigned romfilelength, std::uint32_t now, unsigned flags = 0); int load(const char *romfiledata, unsigned romfilelength, std::uint32_t now, unsigned flags = 0);
int loadGBCBios(const char* biosfiledata);
int loadDMGBios(const char* biosfiledata);
/** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer, /** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer,
* or until a video frame has been drawn. * or until a video frame has been drawn.
* *
@ -109,7 +113,7 @@ public:
void setTraceCallback(void (*callback)(void *)); void setTraceCallback(void (*callback)(void *));
void setScanlineCallback(void (*callback)(), int sl); void setScanlineCallback(void (*callback)(), int sl);
void setRTCCallback(std::uint32_t (*callback)()); void setRTCCallback(std::uint32_t (*callback)());
void setLinkCallback(void (*callback)()); void setLinkCallback(void(*callback)());
/** Returns true if the currently loaded ROM image is treated as having CGB support. */ /** Returns true if the currently loaded ROM image is treated as having CGB support. */
bool isCgb() const; bool isCgb() const;
@ -135,6 +139,9 @@ public:
void GetRegs(int *dest); void GetRegs(int *dest);
void SetInterruptAddresses(int *addrs, int numAddrs);
int GetHitInterruptAddress();
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
private: private:

View File

@ -1,231 +1,222 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Debug</Configuration> <Configuration>Release</Configuration>
<Platform>x64</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Debug|x64">
<Configuration>Release</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"> <ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<ProjectGuid>{5D630682-7BDA-474D-B387-0EB420DDC199}</ProjectGuid> <ProjectGuid>{5D630682-7BDA-474D-B387-0EB420DDC199}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>libgambatte</RootNamespace> <RootNamespace>libgambatte</RootNamespace>
</PropertyGroup> <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ConfigurationType>DynamicLibrary</ConfigurationType> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries> <ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
</PropertyGroup> <CharacterSet>Unicode</CharacterSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> </PropertyGroup>
<ConfigurationType>DynamicLibrary</ConfigurationType> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries> <ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
</PropertyGroup> <WholeProgramOptimization>true</WholeProgramOptimization>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <CharacterSet>Unicode</CharacterSet>
<ConfigurationType>DynamicLibrary</ConfigurationType> </PropertyGroup>
<UseDebugLibraries>false</UseDebugLibraries> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<WholeProgramOptimization>true</WholeProgramOptimization> <ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v140</PlatformToolset>
</PropertyGroup> <CharacterSet>Unicode</CharacterSet>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> </PropertyGroup>
<ConfigurationType>DynamicLibrary</ConfigurationType> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries> <ConfigurationType>DynamicLibrary</ConfigurationType>
<WholeProgramOptimization>true</WholeProgramOptimization> <UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet> <PlatformToolset>v140</PlatformToolset>
<PlatformToolset>v140</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup> <CharacterSet>Unicode</CharacterSet>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> </PropertyGroup>
<ImportGroup Label="ExtensionSettings"> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
</ImportGroup> <ImportGroup Label="ExtensionSettings">
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <ImportGroup Label="Shared">
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<LinkIncremental>true</LinkIncremental> </ImportGroup>
</PropertyGroup> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>true</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <LinkIncremental>false</LinkIncremental>
<PrecompiledHeader> </PropertyGroup>
</PrecompiledHeader> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<WarningLevel>Level3</WarningLevel> <ClCompile>
<Optimization>Disabled</Optimization> <PrecompiledHeader>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> </PrecompiledHeader>
<AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories> <WarningLevel>Level3</WarningLevel>
<DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings> <Optimization>Disabled</Optimization>
</ClCompile> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Link> <AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories>
<SubSystem>Windows</SubSystem> <DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings>
<GenerateDebugInformation>true</GenerateDebugInformation> </ClCompile>
</Link> <Link>
<PostBuildEvent> <SubSystem>Windows</SubSystem>
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName)</Command> <GenerateDebugInformation>true</GenerateDebugInformation>
</PostBuildEvent> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<PrecompiledHeader> <PrecompiledHeader>
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings> <DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
</Link> </Link>
<PostBuildEvent> </ItemDefinitionGroup>
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName)</Command> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PostBuildEvent> <ClCompile>
</ItemDefinitionGroup> <WarningLevel>Level3</WarningLevel>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PrecompiledHeader>
<ClCompile> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <Optimization>MaxSpeed</Optimization>
<PrecompiledHeader> <FunctionLevelLinking>true</FunctionLevelLinking>
</PrecompiledHeader> <IntrinsicFunctions>true</IntrinsicFunctions>
<Optimization>MaxSpeed</Optimization> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking> <AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories>
<IntrinsicFunctions>true</IntrinsicFunctions> <DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile>
<AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories> <Link>
<DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings> <SubSystem>Windows</SubSystem>
</ClCompile> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<Link> <OptimizeReferences>true</OptimizeReferences>
<SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>true</GenerateDebugInformation> </Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> </ItemDefinitionGroup>
<OptimizeReferences>true</OptimizeReferences> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</Link> <ClCompile>
<PostBuildEvent> <WarningLevel>Level3</WarningLevel>
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName)</Command> <PrecompiledHeader>
</PostBuildEvent> </PrecompiledHeader>
</ItemDefinitionGroup> <Optimization>MaxSpeed</Optimization>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <FunctionLevelLinking>true</FunctionLevelLinking>
<ClCompile> <IntrinsicFunctions>true</IntrinsicFunctions>
<WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader> <AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories>
</PrecompiledHeader> <DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings>
<Optimization>MaxSpeed</Optimization> </ClCompile>
<FunctionLevelLinking>true</FunctionLevelLinking> <Link>
<IntrinsicFunctions>true</IntrinsicFunctions> <SubSystem>Windows</SubSystem>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGAMBATTE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalIncludeDirectories>include;src;src\common</AdditionalIncludeDirectories> <OptimizeReferences>true</OptimizeReferences>
<DisableSpecificWarnings>4244;4373;4800;4804</DisableSpecificWarnings> <GenerateDebugInformation>true</GenerateDebugInformation>
</ClCompile> </Link>
<Link> </ItemDefinitionGroup>
<SubSystem>Windows</SubSystem> <ItemGroup>
<GenerateDebugInformation>true</GenerateDebugInformation> <ClInclude Include="include\gambatte.h" />
<EnableCOMDATFolding>true</EnableCOMDATFolding> <ClInclude Include="include\gbint.h" />
<OptimizeReferences>true</OptimizeReferences> <ClInclude Include="src\cinterface.h" />
</Link> <ClInclude Include="src\common\array.h" />
<PostBuildEvent> <ClInclude Include="src\common\uncopyable.h" />
<Command>copy /y $(TargetDir)$(TargetFileName) $(ProjectDir)..\output\dll\$(TargetFileName)</Command> <ClInclude Include="src\counterdef.h" />
</PostBuildEvent> <ClInclude Include="src\cpu.h" />
</ItemDefinitionGroup> <ClInclude Include="src\file\stdfile.h" />
<ItemGroup> <ClInclude Include="src\initstate.h" />
<ClInclude Include="include\gambatte.h" /> <ClInclude Include="src\insertion_sort.h" />
<ClInclude Include="include\gbint.h" /> <ClInclude Include="src\interrupter.h" />
<ClInclude Include="src\cinterface.h" /> <ClInclude Include="src\interruptrequester.h" />
<ClInclude Include="src\common\array.h" /> <ClInclude Include="src\memory.h" />
<ClInclude Include="src\common\uncopyable.h" /> <ClInclude Include="src\mem\cartridge.h" />
<ClInclude Include="src\counterdef.h" /> <ClInclude Include="src\mem\memptrs.h" />
<ClInclude Include="src\cpu.h" /> <ClInclude Include="src\mem\rtc.h" />
<ClInclude Include="src\file\stdfile.h" /> <ClInclude Include="src\minkeeper.h" />
<ClInclude Include="src\initstate.h" /> <ClInclude Include="src\newstate.h" />
<ClInclude Include="src\insertion_sort.h" /> <ClInclude Include="src\savestate.h" />
<ClInclude Include="src\interrupter.h" /> <ClInclude Include="src\sound.h" />
<ClInclude Include="src\interruptrequester.h" /> <ClInclude Include="src\sound\channel1.h" />
<ClInclude Include="src\memory.h" /> <ClInclude Include="src\sound\channel2.h" />
<ClInclude Include="src\mem\cartridge.h" /> <ClInclude Include="src\sound\channel3.h" />
<ClInclude Include="src\mem\memptrs.h" /> <ClInclude Include="src\sound\channel4.h" />
<ClInclude Include="src\mem\rtc.h" /> <ClInclude Include="src\sound\duty_unit.h" />
<ClInclude Include="src\minkeeper.h" /> <ClInclude Include="src\sound\envelope_unit.h" />
<ClInclude Include="src\newstate.h" /> <ClInclude Include="src\sound\length_counter.h" />
<ClInclude Include="src\savestate.h" /> <ClInclude Include="src\sound\master_disabler.h" />
<ClInclude Include="src\sound.h" /> <ClInclude Include="src\sound\sound_unit.h" />
<ClInclude Include="src\sound\channel1.h" /> <ClInclude Include="src\sound\static_output_tester.h" />
<ClInclude Include="src\sound\channel2.h" /> <ClInclude Include="src\tima.h" />
<ClInclude Include="src\sound\channel3.h" /> <ClInclude Include="src\video.h" />
<ClInclude Include="src\sound\channel4.h" /> <ClInclude Include="src\video\lyc_irq.h" />
<ClInclude Include="src\sound\duty_unit.h" /> <ClInclude Include="src\video\ly_counter.h" />
<ClInclude Include="src\sound\envelope_unit.h" /> <ClInclude Include="src\video\next_m0_time.h" />
<ClInclude Include="src\sound\length_counter.h" /> <ClInclude Include="src\video\ppu.h" />
<ClInclude Include="src\sound\master_disabler.h" /> <ClInclude Include="src\video\sprite_mapper.h" />
<ClInclude Include="src\sound\sound_unit.h" /> </ItemGroup>
<ClInclude Include="src\sound\static_output_tester.h" /> <ItemGroup>
<ClInclude Include="src\tima.h" /> <ClCompile Include="src\cinterface.cpp" />
<ClInclude Include="src\video.h" /> <ClCompile Include="src\cpu.cpp" />
<ClInclude Include="src\video\lyc_irq.h" /> <ClCompile Include="src\gambatte.cpp" />
<ClInclude Include="src\video\ly_counter.h" /> <ClCompile Include="src\initstate.cpp" />
<ClInclude Include="src\video\next_m0_time.h" /> <ClCompile Include="src\interrupter.cpp" />
<ClInclude Include="src\video\ppu.h" /> <ClCompile Include="src\interruptrequester.cpp" />
<ClInclude Include="src\video\sprite_mapper.h" /> <ClCompile Include="src\memory.cpp" />
</ItemGroup> <ClCompile Include="src\mem\cartridge.cpp" />
<ItemGroup> <ClCompile Include="src\mem\memptrs.cpp" />
<ClCompile Include="src\cinterface.cpp" /> <ClCompile Include="src\mem\rtc.cpp" />
<ClCompile Include="src\cpu.cpp" /> <ClCompile Include="src\newstate.cpp" />
<ClCompile Include="src\gambatte.cpp" /> <ClCompile Include="src\sound.cpp" />
<ClCompile Include="src\initstate.cpp" /> <ClCompile Include="src\sound\channel1.cpp" />
<ClCompile Include="src\interrupter.cpp" /> <ClCompile Include="src\sound\channel2.cpp" />
<ClCompile Include="src\interruptrequester.cpp" /> <ClCompile Include="src\sound\channel3.cpp" />
<ClCompile Include="src\memory.cpp" /> <ClCompile Include="src\sound\channel4.cpp" />
<ClCompile Include="src\mem\cartridge.cpp" /> <ClCompile Include="src\sound\duty_unit.cpp" />
<ClCompile Include="src\mem\memptrs.cpp" /> <ClCompile Include="src\sound\envelope_unit.cpp" />
<ClCompile Include="src\mem\rtc.cpp" /> <ClCompile Include="src\sound\length_counter.cpp" />
<ClCompile Include="src\newstate.cpp" /> <ClCompile Include="src\tima.cpp" />
<ClCompile Include="src\sound.cpp" /> <ClCompile Include="src\video.cpp" />
<ClCompile Include="src\sound\channel1.cpp" /> <ClCompile Include="src\video\lyc_irq.cpp" />
<ClCompile Include="src\sound\channel2.cpp" /> <ClCompile Include="src\video\ly_counter.cpp" />
<ClCompile Include="src\sound\channel3.cpp" /> <ClCompile Include="src\video\next_m0_time.cpp" />
<ClCompile Include="src\sound\channel4.cpp" /> <ClCompile Include="src\video\ppu.cpp" />
<ClCompile Include="src\sound\duty_unit.cpp" /> <ClCompile Include="src\video\sprite_mapper.cpp" />
<ClCompile Include="src\sound\envelope_unit.cpp" /> </ItemGroup>
<ClCompile Include="src\sound\length_counter.cpp" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ClCompile Include="src\tima.cpp" /> <ImportGroup Label="ExtensionTargets">
<ClCompile Include="src\video.cpp" /> </ImportGroup>
<ClCompile Include="src\video\lyc_irq.cpp" />
<ClCompile Include="src\video\ly_counter.cpp" />
<ClCompile Include="src\video\next_m0_time.cpp" />
<ClCompile Include="src\video\ppu.cpp" />
<ClCompile Include="src\video\sprite_mapper.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project> </Project>

View File

@ -1,203 +1,225 @@
#include "cinterface.h" #include "cinterface.h"
#include "gambatte.h" #include "gambatte.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "newstate.h" #include "newstate.h"
using namespace gambatte; using namespace gambatte;
// new is actually called in a few different places, so replace all of them for determinism guarantees // new is actually called in a few different places, so replace all of them for determinism guarantees
void *operator new(std::size_t n) void *operator new(std::size_t n)
{ {
void *p = std::malloc(n); void *p = std::malloc(n);
std::memset(p, 0, n); std::memset(p, 0, n);
return p; return p;
} }
void operator delete(void *p) void operator delete(void *p)
{ {
std::free(p); std::free(p);
} }
GBEXPORT GB *gambatte_create() GBEXPORT GB *gambatte_create()
{ {
return new GB(); return new GB();
} }
GBEXPORT void gambatte_destroy(GB *g) GBEXPORT void gambatte_destroy(GB *g)
{ {
delete g; delete g;
} }
GBEXPORT int gambatte_load(GB *g, const char *romfiledata, unsigned romfilelength, long long now, unsigned flags) GBEXPORT int gambatte_load(GB *g, const char *romfiledata, unsigned romfilelength, long long now, unsigned flags)
{ {
int ret = g->load(romfiledata, romfilelength, now, flags); int ret = g->load(romfiledata, romfilelength, now, flags);
return ret; return ret;
} }
GBEXPORT int gambatte_runfor(GB *g, short *soundbuf, unsigned *samples) GBEXPORT int gambatte_loadgbcbios(GB* g, const char* biosfiledata)
{ {
unsigned sampv = *samples; int ret = g->loadGBCBios(biosfiledata);
int ret = g->runFor((unsigned int *) soundbuf, sampv); return ret;
*samples = sampv; }
return ret;
} GBEXPORT int gambatte_loaddmgbios(GB* g, const char* biosfiledata)
{
GBEXPORT void gambatte_blitto(GB *g, unsigned int *videobuf, int pitch) int ret = g->loadDMGBios(biosfiledata);
{ return ret;
g->blitTo((unsigned int *)videobuf, pitch); }
}
GBEXPORT int gambatte_runfor(GB *g, short *soundbuf, unsigned *samples)
GBEXPORT void gambatte_setlayers(GB *g, unsigned mask) {
{ unsigned sampv = *samples;
g->setLayers(mask); int ret = g->runFor((unsigned int *) soundbuf, sampv);
} *samples = sampv;
return ret;
GBEXPORT void gambatte_reset(GB *g, long long now) }
{
g->reset(now); GBEXPORT void gambatte_blitto(GB *g, unsigned int *videobuf, int pitch)
} {
g->blitTo((unsigned int *)videobuf, pitch);
GBEXPORT void gambatte_setdmgpalettecolor(GB *g, unsigned palnum, unsigned colornum, unsigned rgb32) }
{
g->setDmgPaletteColor(palnum, colornum, rgb32); GBEXPORT void gambatte_setlayers(GB *g, unsigned mask)
} {
g->setLayers(mask);
GBEXPORT void gambatte_setcgbpalette(GB *g, unsigned *lut) }
{
g->setCgbPalette(lut); GBEXPORT void gambatte_reset(GB *g, long long now)
} {
g->reset(now);
GBEXPORT void gambatte_setinputgetter(GB *g, unsigned (*getinput)(void)) }
{
g->setInputGetter(getinput); GBEXPORT void gambatte_setdmgpalettecolor(GB *g, unsigned palnum, unsigned colornum, unsigned rgb32)
} {
//g->setDmgPaletteColor(palnum, colornum, rgb32);
GBEXPORT void gambatte_setreadcallback(GB *g, void (*callback)(unsigned)) }
{
g->setReadCallback(callback); GBEXPORT void gambatte_setcgbpalette(GB *g, unsigned *lut)
} {
g->setCgbPalette(lut);
GBEXPORT void gambatte_setwritecallback(GB *g, void (*callback)(unsigned)) }
{
g->setWriteCallback(callback); GBEXPORT void gambatte_setinputgetter(GB *g, unsigned (*getinput)(void))
} {
g->setInputGetter(getinput);
GBEXPORT void gambatte_setexeccallback(GB *g, void (*callback)(unsigned)) }
{
g->setExecCallback(callback); GBEXPORT void gambatte_setreadcallback(GB *g, void (*callback)(unsigned))
} {
g->setReadCallback(callback);
GBEXPORT void gambatte_setcdcallback(GB *g, CDCallback cdc) }
{
g->setCDCallback(cdc); GBEXPORT void gambatte_setwritecallback(GB *g, void (*callback)(unsigned))
} {
g->setWriteCallback(callback);
}
GBEXPORT void gambatte_settracecallback(GB *g, void (*callback)(void *))
{ GBEXPORT void gambatte_setexeccallback(GB *g, void (*callback)(unsigned))
g->setTraceCallback(callback); {
} g->setExecCallback(callback);
}
GBEXPORT void gambatte_setscanlinecallback(GB *g, void (*callback)(), int sl)
{ GBEXPORT void gambatte_setcdcallback(GB *g, CDCallback cdc)
g->setScanlineCallback(callback, sl); {
} g->setCDCallback(cdc);
}
GBEXPORT void gambatte_setrtccallback(GB *g, unsigned int (*callback)())
{
g->setRTCCallback(callback); GBEXPORT void gambatte_settracecallback(GB *g, void (*callback)(void *))
} {
g->setTraceCallback(callback);
GBEXPORT void gambatte_setlinkcallback(GB *g, void (*callback)()) }
{
g->setLinkCallback(callback); GBEXPORT void gambatte_setscanlinecallback(GB *g, void (*callback)(), int sl)
} {
g->setScanlineCallback(callback, sl);
GBEXPORT int gambatte_iscgb(GB *g) }
{
return g->isCgb(); GBEXPORT void gambatte_setrtccallback(GB *g, unsigned int (*callback)())
} {
g->setRTCCallback(callback);
GBEXPORT int gambatte_isloaded(GB *g) }
{
return g->isLoaded(); GBEXPORT void gambatte_setlinkcallback(GB *g, void(*callback)())
} {
g->setLinkCallback(callback);
GBEXPORT void gambatte_savesavedata(GB *g, char *dest) }
{
g->saveSavedata(dest); GBEXPORT int gambatte_iscgb(GB *g)
} {
return g->isCgb();
GBEXPORT void gambatte_loadsavedata(GB *g, const char *data) }
{
g->loadSavedata(data); GBEXPORT int gambatte_isloaded(GB *g)
} {
return g->isLoaded();
GBEXPORT int gambatte_savesavedatalength(GB *g) }
{
return g->saveSavedataLength(); GBEXPORT void gambatte_savesavedata(GB *g, char *dest)
} {
g->saveSavedata(dest);
GBEXPORT int gambatte_newstatelen(GB *g) }
{
NewStateDummy dummy; GBEXPORT void gambatte_loadsavedata(GB *g, const char *data)
g->SyncState<false>(&dummy); {
return dummy.GetLength(); g->loadSavedata(data);
} }
GBEXPORT int gambatte_newstatesave(GB *g, char *data, int len) GBEXPORT int gambatte_savesavedatalength(GB *g)
{ {
NewStateExternalBuffer saver(data, len); return g->saveSavedataLength();
g->SyncState<false>(&saver); }
return !saver.Overflow() && saver.GetLength() == len;
} GBEXPORT int gambatte_newstatelen(GB *g)
{
GBEXPORT int gambatte_newstateload(GB *g, const char *data, int len) NewStateDummy dummy;
{ g->SyncState<false>(&dummy);
NewStateExternalBuffer loader((char *)data, len); return dummy.GetLength();
g->SyncState<true>(&loader); }
return !loader.Overflow() && loader.GetLength() == len;
} GBEXPORT int gambatte_newstatesave(GB *g, char *data, int len)
{
GBEXPORT void gambatte_newstatesave_ex(GB *g, FPtrs *ff) NewStateExternalBuffer saver(data, len);
{ g->SyncState<false>(&saver);
NewStateExternalFunctions saver(ff); return !saver.Overflow() && saver.GetLength() == len;
g->SyncState<false>(&saver); }
}
GBEXPORT int gambatte_newstateload(GB *g, const char *data, int len)
GBEXPORT void gambatte_newstateload_ex(GB *g, FPtrs *ff) {
{ NewStateExternalBuffer loader((char *)data, len);
NewStateExternalFunctions loader(ff); g->SyncState<true>(&loader);
g->SyncState<true>(&loader); return !loader.Overflow() && loader.GetLength() == len;
} }
GBEXPORT void gambatte_romtitle(GB *g, char *dest) GBEXPORT void gambatte_newstatesave_ex(GB *g, FPtrs *ff)
{ {
std::strcpy(dest, g->romTitle().c_str()); NewStateExternalFunctions saver(ff);
} g->SyncState<false>(&saver);
}
GBEXPORT int gambatte_getmemoryarea(GB *g, int which, unsigned char **data, int *length)
{ GBEXPORT void gambatte_newstateload_ex(GB *g, FPtrs *ff)
return g->getMemoryArea(which, data, length); {
} NewStateExternalFunctions loader(ff);
g->SyncState<true>(&loader);
GBEXPORT unsigned char gambatte_cpuread(GB *g, unsigned short addr) }
{
return g->ExternalRead(addr); GBEXPORT void gambatte_romtitle(GB *g, char *dest)
} {
std::strcpy(dest, g->romTitle().c_str());
GBEXPORT void gambatte_cpuwrite(GB *g, unsigned short addr, unsigned char val) }
{
g->ExternalWrite(addr, val); GBEXPORT int gambatte_getmemoryarea(GB *g, int which, unsigned char **data, int *length)
} {
return g->getMemoryArea(which, data, length);
GBEXPORT int gambatte_linkstatus(GB *g, int which) }
{
return g->LinkStatus(which); GBEXPORT unsigned char gambatte_cpuread(GB *g, unsigned short addr)
} {
return g->ExternalRead(addr);
GBEXPORT void gambatte_getregs(GB *g, int *dest) }
{
g->GetRegs(dest); GBEXPORT void gambatte_cpuwrite(GB *g, unsigned short addr, unsigned char val)
} {
g->ExternalWrite(addr, val);
}
GBEXPORT int gambatte_linkstatus(GB *g, int which)
{
return g->LinkStatus(which);
}
GBEXPORT void gambatte_getregs(GB *g, int *dest)
{
g->GetRegs(dest);
}
GBEXPORT void gambatte_setinterruptaddresses(GB *g, int *addrs, int numAddrs)
{
g->SetInterruptAddresses(addrs, numAddrs);
}
GBEXPORT int gambatte_gethitinterruptaddress(GB *g)
{
return g->GetHitInterruptAddress();
}

View File

@ -1,8 +1,8 @@
#ifndef CINTERFACE_H #ifndef CINTERFACE_H
#define CINTERFACE_H #define CINTERFACE_H
// these are all documented on the C# side // these are all documented on the C# side
#define GBEXPORT extern "C" __declspec(dllexport) #define GBEXPORT extern "C" __declspec(dllexport)
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +1,147 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef CPU_H #ifndef CPU_H
#define CPU_H #define CPU_H
#include "memory.h" #include "memory.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
class CPU { class CPU {
Memory memory; Memory memory;
unsigned long cycleCounter_; unsigned long cycleCounter_;
unsigned short PC; unsigned short PC;
unsigned short SP; unsigned short SP;
unsigned HF1, HF2, ZF, CF; unsigned HF1, HF2, ZF, CF;
unsigned char A, B, C, D, E, /*F,*/ H, L; unsigned char A, B, C, D, E, /*F,*/ H, L;
bool skip; bool skip;
void process(unsigned long cycles); int *interruptAddresses;
int numInterruptAddresses;
void (*tracecallback)(void *); int hitInterruptAddress;
public: void process(unsigned long cycles);
CPU(); void (*tracecallback)(void *);
// void halt();
public:
// unsigned interrupt(unsigned address, unsigned cycleCounter);
CPU();
long runFor(unsigned long cycles); // void halt();
void setStatePtrs(SaveState &state);
void loadState(const SaveState &state); // unsigned interrupt(unsigned address, unsigned cycleCounter);
void setLayers(unsigned mask) { memory.setLayers(mask); }
long runFor(unsigned long cycles);
void loadSavedata(const char *data) { memory.loadSavedata(data); } void setStatePtrs(SaveState &state);
int saveSavedataLength() {return memory.saveSavedataLength(); } void loadState(const SaveState &state);
void saveSavedata(char *dest) { memory.saveSavedata(dest); } void setLayers(unsigned mask) { memory.setLayers(mask); }
bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); } void loadSavedata(const char *data) { memory.loadSavedata(data); }
int saveSavedataLength() {return memory.saveSavedataLength(); }
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { void saveSavedata(char *dest) { memory.saveSavedata(dest); }
memory.setVideoBuffer(videoBuf, pitch);
} bool getMemoryArea(int which, unsigned char **data, int *length) { return memory.getMemoryArea(which, data, length); }
void setInputGetter(unsigned (*getInput)()) { void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
memory.setInputGetter(getInput); memory.setVideoBuffer(videoBuf, pitch);
} }
void setReadCallback(void (*callback)(unsigned)) { void setInputGetter(unsigned (*getInput)()) {
memory.setReadCallback(callback); memory.setInputGetter(getInput);
} }
void setWriteCallback(void (*callback)(unsigned)) { void setReadCallback(void (*callback)(unsigned)) {
memory.setWriteCallback(callback); memory.setReadCallback(callback);
} }
void setExecCallback(void (*callback)(unsigned)) { void setWriteCallback(void (*callback)(unsigned)) {
memory.setExecCallback(callback); memory.setWriteCallback(callback);
} }
void setCDCallback(CDCallback cdc) { void setExecCallback(void (*callback)(unsigned)) {
memory.setCDCallback(cdc); memory.setExecCallback(callback);
} }
void setTraceCallback(void (*callback)(void *)) { void setCDCallback(CDCallback cdc) {
tracecallback = callback; memory.setCDCallback(cdc);
} }
void setScanlineCallback(void (*callback)(), int sl) { void setTraceCallback(void (*callback)(void *)) {
memory.setScanlineCallback(callback, sl); tracecallback = callback;
} }
void setRTCCallback(std::uint32_t (*callback)()) { void setScanlineCallback(void (*callback)(), int sl) {
memory.setRTCCallback(callback); memory.setScanlineCallback(callback, sl);
} }
void setLinkCallback(void (*callback)()) { void setRTCCallback(std::uint32_t (*callback)()) {
memory.setLinkCallback(callback); memory.setRTCCallback(callback);
} }
int load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) { void setLinkCallback(void(*callback)()) {
return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat); memory.setLinkCallback(callback);
} }
bool loaded() const { return memory.loaded(); } int load(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat) {
const char * romTitle() const { return memory.romTitle(); } return memory.loadROM(romfiledata, romfilelength, forceDmg, multicartCompat);
}
void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); }
unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); } bool loaded() const { return memory.loaded(); }
const char * romTitle() const { return memory.romTitle(); }
bool isCgb() const { return memory.isCgb(); }
void setSoundBuffer(uint_least32_t *const buf) { memory.setSoundBuffer(buf); }
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); }
memory.setDmgPaletteColor(palNum, colorNum, rgb32);
} bool isCgb() const { return memory.isCgb(); }
void setCgbPalette(unsigned *lut) { void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
memory.setCgbPalette(lut); memory.setDmgPaletteColor(palNum, colorNum, rgb32);
} }
//unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); } void setCgbPalette(unsigned *lut) {
unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); } memory.setCgbPalette(lut);
void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); } }
int LinkStatus(int which) { return memory.LinkStatus(which); } unsigned char* cgbBiosBuffer() { return memory.cgbBiosBuffer(); }
unsigned char* dmgBiosBuffer() { return memory.dmgBiosBuffer(); }
void GetRegs(int *dest); bool gbIsCgb() { return memory.gbIsCgb(); }
template<bool isReader>void SyncState(NewState *ns); //unsigned char ExternalRead(unsigned short addr) { return memory.read(addr, cycleCounter_); }
}; unsigned char ExternalRead(unsigned short addr) { return memory.peek(addr); }
void ExternalWrite(unsigned short addr, unsigned char val) { memory.write_nocb(addr, val, cycleCounter_); }
}
int LinkStatus(int which) { return memory.LinkStatus(which); }
#endif
void GetRegs(int *dest);
void SetInterruptAddresses(int *addrs, int numAddrs);
int GetHitInterruptAddress();
template<bool isReader>void SyncState(NewState *ns);
};
}
#endif

View File

@ -26,12 +26,12 @@
namespace gambatte { namespace gambatte {
struct GB::Priv { struct GB::Priv {
CPU cpu; CPU cpu;
bool gbaCgbMode; unsigned loadflags;
unsigned layersMask; unsigned layersMask;
uint_least32_t vbuff[160*144]; uint_least32_t vbuff[160*144];
Priv() : gbaCgbMode(false), layersMask(LAYER_MASK_BG | LAYER_MASK_OBJ) Priv() : loadflags(0), layersMask(LAYER_MASK_BG | LAYER_MASK_OBJ)
{ {
} }
@ -94,8 +94,7 @@ void GB::reset(const std::uint32_t now) {
SaveState state; SaveState state;
p_->cpu.setStatePtrs(state); p_->cpu.setStatePtrs(state);
setInitState(state, !(p_->loadflags & FORCE_DMG), p_->loadflags & GBA_CGB, p_->loadflags & TRUE_COLOR, now);
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode, now);
p_->cpu.loadState(state); p_->cpu.loadState(state);
if (length > 0) if (length > 0)
{ {
@ -146,11 +145,12 @@ int GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_
// p_->cpu.saveSavedata(); // p_->cpu.saveSavedata();
const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT); const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
if (!failed) { if (!failed) {
SaveState state; SaveState state;
p_->cpu.setStatePtrs(state); p_->cpu.setStatePtrs(state);
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode = flags & GBA_CGB, now); p_->loadflags = flags;
setInitState(state, !(flags & FORCE_DMG), flags & GBA_CGB, flags & TRUE_COLOR, now);
p_->cpu.loadState(state); p_->cpu.loadState(state);
//p_->cpu.loadSavedata(); //p_->cpu.loadSavedata();
} }
@ -158,6 +158,16 @@ int GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_
return failed; return failed;
} }
int GB::loadGBCBios(const char* biosfiledata) {
memcpy(p_->cpu.cgbBiosBuffer(), biosfiledata, 0x900);
return 0;
}
int GB::loadDMGBios(const char* biosfiledata) {
memcpy(p_->cpu.dmgBiosBuffer(), biosfiledata, 0x100);
return 0;
}
bool GB::isCgb() const { bool GB::isCgb() const {
return p_->cpu.isCgb(); return p_->cpu.isCgb();
} }
@ -228,10 +238,20 @@ void GB::GetRegs(int *dest) {
p_->cpu.GetRegs(dest); p_->cpu.GetRegs(dest);
} }
void GB::SetInterruptAddresses(int *addrs, int numAddrs)
{
p_->cpu.SetInterruptAddresses(addrs, numAddrs);
}
int GB::GetHitInterruptAddress()
{
return p_->cpu.GetHitInterruptAddress();
}
SYNCFUNC(GB) SYNCFUNC(GB)
{ {
SSS(p_->cpu); SSS(p_->cpu);
NSS(p_->gbaCgbMode); NSS(p_->loadflags);
NSS(p_->vbuff); NSS(p_->vbuff);
} }

View File

@ -1041,11 +1041,11 @@ static void setInitialCgbIoamhram(unsigned char *const ioamhram) {
}; };
static const unsigned char ffxxDump[0x100] = { static const unsigned char ffxxDump[0x100] = {
0xCF, 0x00, 0x7C, 0xFF, 0x44, 0x00, 0x00, 0xF8, 0xCF, 0x00, 0x7C, 0xFF, 0x00, 0x00, 0x00, 0xF8,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, 0x80, 0x3F, 0x00, 0xFF, 0xBF, 0xFF, 0x3F, 0x00,
0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF, 0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF,
0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF, 0xFF, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x70, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
@ -1146,61 +1146,58 @@ static void setInitialDmgIoamhram(unsigned char *const ioamhram) {
} // anon namespace } // anon namespace
void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const std::uint32_t now) { void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbMode, const bool trueColors, const std::uint32_t now) {
static const unsigned char cgbObjpDump[0x40] = { static const unsigned char cgbObjpDump[0x40] = {
0x00, 0x00, 0xF2, 0xAB, 0x00, 0x00, 0xF2, 0xAB,
0x61, 0xC2, 0xD9, 0xBA, 0x61, 0xC2, 0xD9, 0xBA,
0x88, 0x6E, 0xDD, 0x63, 0x88, 0x6E, 0xDD, 0x63,
0x28, 0x27, 0xFB, 0x9F, 0x28, 0x27, 0xFB, 0x9F,
0x35, 0x42, 0xD6, 0xD4, 0x35, 0x42, 0xD6, 0xD4,
0x50, 0x48, 0x57, 0x5E, 0x50, 0x48, 0x57, 0x5E,
0x23, 0x3E, 0x3D, 0xCA, 0x23, 0x3E, 0x3D, 0xCA,
0x71, 0x21, 0x37, 0xC0, 0x71, 0x21, 0x37, 0xC0,
0xC6, 0xB3, 0xFB, 0xF9, 0xC6, 0xB3, 0xFB, 0xF9,
0x08, 0x00, 0x8D, 0x29, 0x08, 0x00, 0x8D, 0x29,
0xA3, 0x20, 0xDB, 0x87, 0xA3, 0x20, 0xDB, 0x87,
0x62, 0x05, 0x5D, 0xD4, 0x62, 0x05, 0x5D, 0xD4,
0x0E, 0x08, 0xFE, 0xAF, 0x0E, 0x08, 0xFE, 0xAF,
0x20, 0x02, 0xD7, 0xFF, 0x20, 0x02, 0xD7, 0xFF,
0x07, 0x6A, 0x55, 0xEC, 0x07, 0x6A, 0x55, 0xEC,
0x83, 0x40, 0x0B, 0x77 0x83, 0x40, 0x0B, 0x77
}; };
state.cpu.PC = 0x100;
state.cpu.SP = 0xFFFE;
state.cpu.A = cgb * 0x10 | 0x01;
state.cpu.B = cgb & gbaCgbMode;
state.cpu.C = 0x13;
state.cpu.D = 0x00;
state.cpu.E = 0xD8;
state.cpu.F = 0xB0;
state.cpu.H = 0x01;
state.cpu.L = 0x4D;
state.cpu.skip = false;
setInitialVram(state.mem.vram.ptr, cgb);
state.cpu.cycleCounter = cgb ? 0x102A0 : 0x102A0 + 0x8D2C;
state.cpu.cycleCounter = 8;
state.cpu.PC = 0;
state.cpu.SP = 0;
state.cpu.A = 0;
state.cpu.B = 0;
state.cpu.C = 0;
state.cpu.D = 0;
state.cpu.E = 0;
state.cpu.F = 0;
state.cpu.H = 0;
state.cpu.L = 0;
state.cpu.skip = false;
state.mem.biosMode = true;
state.mem.cgbSwitching = false;
state.mem.agbMode = gbaCgbMode;
std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz()); std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz());
setInitialVram(state.mem.vram.ptr, cgb);
if (cgb) { if (cgb) {
setInitialCgbWram(state.mem.wram.ptr); setInitialCgbWram(state.mem.wram.ptr);
}
else {
setInitialDmgWram(state.mem.wram.ptr);
}
if (cgb) {
setInitialCgbIoamhram(state.mem.ioamhram.ptr); setInitialCgbIoamhram(state.mem.ioamhram.ptr);
} } else {
else { setInitialDmgWram(state.mem.wram.ptr);
setInitialDmgIoamhram(state.mem.ioamhram.ptr); setInitialDmgIoamhram(state.mem.ioamhram.ptr);
} }
state.mem.ioamhram.ptr[0x140] = 0x91; state.mem.ioamhram.ptr[0x104] = 0;
state.mem.ioamhram.ptr[0x104] = 0x1C; state.mem.ioamhram.ptr[0x140] = 0;
state.mem.ioamhram.ptr[0x144] = 0x00; state.mem.ioamhram.ptr[0x144] = 0x00;
state.mem.divLastUpdate = 0; state.mem.divLastUpdate = 0;
state.mem.timaLastUpdate = 0; state.mem.timaLastUpdate = 0;
state.mem.tmatime = DISABLED_TIME; state.mem.tmatime = DISABLED_TIME;
@ -1218,29 +1215,30 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.mem.enableRam = false; state.mem.enableRam = false;
state.mem.rambankMode = false; state.mem.rambankMode = false;
state.mem.hdmaTransfer = false; state.mem.hdmaTransfer = false;
state.mem.gbIsCgb = cgb;
for (unsigned i = 0x00; i < 0x40; i += 0x02) { for (unsigned i = 0x00; i < 0x40; i += 0x02) {
state.ppu.bgpData.ptr[i] = 0xFF; state.ppu.bgpData.ptr[i ] = 0xFF;
state.ppu.bgpData.ptr[i + 1] = 0x7F; state.ppu.bgpData.ptr[i + 1] = 0x7F;
} }
std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof(cgbObjpDump)); std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof(cgbObjpDump));
if (!cgb) { if (!cgb) {
state.ppu.bgpData.ptr[0] = state.mem.ioamhram.get()[0x147]; state.ppu.bgpData.ptr[0] = state.mem.ioamhram.get()[0x147];
state.ppu.objpData.ptr[0] = state.mem.ioamhram.get()[0x148]; state.ppu.objpData.ptr[0] = state.mem.ioamhram.get()[0x148];
state.ppu.objpData.ptr[1] = state.mem.ioamhram.get()[0x149]; state.ppu.objpData.ptr[1] = state.mem.ioamhram.get()[0x149];
} }
for (unsigned pos = 0; pos < 80; ++pos) for (unsigned pos = 0; pos < 80; ++pos)
state.ppu.oamReaderBuf.ptr[pos] = state.mem.ioamhram.ptr[(pos * 2 & ~3) | (pos & 1)]; state.ppu.oamReaderBuf.ptr[pos] = state.mem.ioamhram.ptr[(pos * 2 & ~3) | (pos & 1)];
std::fill_n(state.ppu.oamReaderSzbuf.ptr, 40, false); std::fill_n(state.ppu.oamReaderSzbuf.ptr, 40, false);
std::memset(state.ppu.spAttribList, 0, sizeof(state.ppu.spAttribList)); std::memset(state.ppu.spAttribList, 0, sizeof(state.ppu.spAttribList));
std::memset(state.ppu.spByte0List, 0, sizeof(state.ppu.spByte0List)); std::memset(state.ppu.spByte0List, 0, sizeof(state.ppu.spByte0List));
std::memset(state.ppu.spByte1List, 0, sizeof(state.ppu.spByte1List)); std::memset(state.ppu.spByte1List, 0, sizeof(state.ppu.spByte1List));
state.ppu.videoCycles = cgb ? 144 * 456ul + 164 : 153 * 456ul + 396; state.ppu.videoCycles = 0;
state.ppu.enableDisplayM0Time = state.cpu.cycleCounter; state.ppu.enableDisplayM0Time = state.cpu.cycleCounter;
state.ppu.winYPos = 0xFF; state.ppu.winYPos = 0xFF;
state.ppu.xpos = 0; state.ppu.xpos = 0;
@ -1254,7 +1252,7 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.ppu.state = 0; state.ppu.state = 0;
state.ppu.nextSprite = 0; state.ppu.nextSprite = 0;
state.ppu.currentSprite = 0; state.ppu.currentSprite = 0;
state.ppu.lyc = state.mem.ioamhram.get()[0x145]; state.ppu.lyc = state.mem.ioamhram.get()[0x145];
state.ppu.m0lyc = state.mem.ioamhram.get()[0x145]; state.ppu.m0lyc = state.mem.ioamhram.get()[0x145];
state.ppu.weMaster = false; state.ppu.weMaster = false;
state.ppu.winDrawState = 0; state.ppu.winDrawState = 0;
@ -1263,36 +1261,39 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.ppu.nextM0Irq = 0; state.ppu.nextM0Irq = 0;
state.ppu.oldWy = state.mem.ioamhram.get()[0x14A]; state.ppu.oldWy = state.mem.ioamhram.get()[0x14A];
state.ppu.pendingLcdstatIrq = false; state.ppu.pendingLcdstatIrq = false;
state.ppu.isCgb = cgb;
state.ppu.trueColors = !trueColors;
state.spu.cycleCounter = 0x1000 | (state.cpu.cycleCounter >> 1 & 0xFFF); // spu.cycleCounter >> 12 & 7 represents the frame sequencer position.
state.spu.cycleCounter = 0; // spu.cycleCounter >> 12 & 7 represents the frame sequencer position.
state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch1.sweep.shadow = 0; state.spu.ch1.sweep.shadow = 0;
state.spu.ch1.sweep.nr0 = 0; state.spu.ch1.sweep.nr0 = 0;
state.spu.ch1.sweep.negging = false; state.spu.ch1.sweep.negging = false;
state.spu.ch1.duty.nextPosUpdate = (state.spu.cycleCounter & ~1) + 2048 * 2; state.spu.ch1.duty.nextPosUpdate = (state.spu.cycleCounter & ~1ul) + 37 * 2;
state.spu.ch1.duty.nr3 = 0; state.spu.ch1.duty.nr3 = 0;
state.spu.ch1.duty.pos = 0; state.spu.ch1.duty.pos = 0;
state.spu.ch1.env.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch1.env.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch1.env.volume = 0; state.spu.ch1.env.volume = 0;
state.spu.ch1.lcounter.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch1.lcounter.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch1.lcounter.lengthCounter = 0x40; state.spu.ch1.lcounter.lengthCounter = 0;
state.spu.ch1.nr4 = 0; state.spu.ch1.nr4 = 0;
state.spu.ch1.master = true; state.spu.ch1.master = true;
state.spu.ch2.duty.nextPosUpdate = (state.spu.cycleCounter & ~1) + 2048 * 2; state.spu.ch2.duty.nextPosUpdate = SoundUnit::COUNTER_DISABLED;
state.spu.ch2.duty.nr3 = 0; state.spu.ch2.duty.nr3 = 0;
state.spu.ch2.duty.pos = 0; state.spu.ch2.duty.pos = 0;
state.spu.ch2.env.counter = state.spu.cycleCounter - ((state.spu.cycleCounter - 0x1000) & 0x7FFF) + 8ul * 0x8000; state.spu.ch2.env.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch2.env.volume = 0; state.spu.ch2.env.volume = 0;
state.spu.ch2.lcounter.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch2.lcounter.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch2.lcounter.lengthCounter = 0x40; state.spu.ch2.lcounter.lengthCounter = 0;
state.spu.ch2.nr4 = 0; state.spu.ch2.nr4 = 0;
state.spu.ch2.master = false; state.spu.ch2.master = false;
for (unsigned i = 0; i < 0x10; ++i) for (unsigned i = 0; i < 0x10; ++i)
state.spu.ch3.waveRam.ptr[i] = state.mem.ioamhram.get()[0x130 + i]; state.spu.ch3.waveRam.ptr[i] = state.mem.ioamhram.get()[0x130 + i];
state.spu.ch3.lcounter.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch3.lcounter.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch3.lcounter.lengthCounter = 0x100; state.spu.ch3.lcounter.lengthCounter = 0x100;
state.spu.ch3.waveCounter = SoundUnit::COUNTER_DISABLED; state.spu.ch3.waveCounter = SoundUnit::COUNTER_DISABLED;
@ -1302,16 +1303,16 @@ void gambatte::setInitState(SaveState &state, const bool cgb, const bool gbaCgbM
state.spu.ch3.wavePos = 0; state.spu.ch3.wavePos = 0;
state.spu.ch3.sampleBuf = 0; state.spu.ch3.sampleBuf = 0;
state.spu.ch3.master = false; state.spu.ch3.master = false;
state.spu.ch4.lfsr.counter = state.spu.cycleCounter + 4; state.spu.ch4.lfsr.counter = state.spu.cycleCounter + 4;
state.spu.ch4.lfsr.reg = 0xFF; state.spu.ch4.lfsr.reg = 0xFF;
state.spu.ch4.env.counter = state.spu.cycleCounter - ((state.spu.cycleCounter - 0x1000) & 0x7FFF) + 8ul * 0x8000; state.spu.ch4.env.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch4.env.volume = 0; state.spu.ch4.env.volume = 0;
state.spu.ch4.lcounter.counter = SoundUnit::COUNTER_DISABLED; state.spu.ch4.lcounter.counter = SoundUnit::COUNTER_DISABLED;
state.spu.ch4.lcounter.lengthCounter = 0x40; state.spu.ch4.lcounter.lengthCounter = 0;
state.spu.ch4.nr4 = 0; state.spu.ch4.nr4 = 0;
state.spu.ch4.master = false; state.spu.ch4.master = false;
state.rtc.baseTime = now; state.rtc.baseTime = now;
state.rtc.haltTime = state.rtc.baseTime; state.rtc.haltTime = state.rtc.baseTime;
state.rtc.dataDh = 0; state.rtc.dataDh = 0;

View File

@ -22,7 +22,7 @@
#include <cstdint> #include <cstdint>
namespace gambatte { namespace gambatte {
void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode, std::uint32_t now); void setInitState(struct SaveState &state, bool cgb, bool gbaCgbMode, bool trueColors, std::uint32_t now);
} }
#endif #endif

View File

@ -1,51 +1,51 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef INSERTION_SORT_H #ifndef INSERTION_SORT_H
#define INSERTION_SORT_H #define INSERTION_SORT_H
#include <functional> #include <functional>
template<typename T, class Less> template<typename T, class Less>
void insertionSort(T *const start, T *const end, Less less) { void insertionSort(T *const start, T *const end, Less less) {
if (start >= end) if (start >= end)
return; return;
T *a = start; T *a = start;
while (++a < end) { while (++a < end) {
const T e = *a; const T e = *a;
T *b = a; T *b = a;
while (b != start && less(e, *(b - 1))) { while (b != start && less(e, *(b - 1))) {
*b = *(b - 1); *b = *(b - 1);
b = b - 1; b = b - 1;
} }
*b = e; *b = e;
} }
} }
template<typename T> template<typename T>
inline void insertionSort(T *const start, T *const end) { inline void insertionSort(T *const start, T *const end) {
insertionSort(start, end, std::less<T>()); insertionSort(start, end, std::less<T>());
} }
#endif /*INSERTION_SORT_H*/ #endif /*INSERTION_SORT_H*/

View File

@ -94,13 +94,13 @@ void InterruptRequester::setIfreg(const unsigned ifreg) {
eventTimes.setValue<INTERRUPTS>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME)); eventTimes.setValue<INTERRUPTS>(pendingIrqs() ? minIntTime : static_cast<unsigned long>(DISABLED_TIME));
} }
SYNCFUNC(InterruptRequester) SYNCFUNC(InterruptRequester)
{ {
SSS(eventTimes); SSS(eventTimes);
NSS(minIntTime); NSS(minIntTime);
NSS(ifreg_); NSS(ifreg_);
NSS(iereg_); NSS(iereg_);
NSS(intFlags.flags_); NSS(intFlags.flags_);
} }
} }

View File

@ -21,7 +21,7 @@
#include "counterdef.h" #include "counterdef.h"
#include "minkeeper.h" #include "minkeeper.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
struct SaveState; struct SaveState;
@ -62,6 +62,7 @@ public:
void resetCc(unsigned long oldCc, unsigned long newCc); void resetCc(unsigned long oldCc, unsigned long newCc);
unsigned ifreg() const { return ifreg_; } unsigned ifreg() const { return ifreg_; }
unsigned iereg() const { return iereg_; }
unsigned pendingIrqs() const { return ifreg_ & iereg_; } unsigned pendingIrqs() const { return ifreg_ & iereg_; }
bool ime() const { return intFlags.ime(); } bool ime() const { return intFlags.ime(); }
bool halted() const { return intFlags.halted(); } bool halted() const { return intFlags.halted(); }
@ -81,7 +82,7 @@ public:
void setEventTime(const MemEventId id, unsigned long value) { eventTimes.setValue(id, value); } void setEventTime(const MemEventId id, unsigned long value) { eventTimes.setValue(id, value); }
unsigned long eventTime(MemEventId id) const { return eventTimes.value(id); } unsigned long eventTime(MemEventId id) const { return eventTimes.value(id); }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
inline void flagHdmaReq(InterruptRequester *const intreq) { intreq->setEventTime<DMA>(0); } inline void flagHdmaReq(InterruptRequester *const intreq) { intreq->setEventTime<DMA>(0); }

File diff suppressed because it is too large Load Diff

View File

@ -1,112 +1,113 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007-2010 by Sindre Aamås * * Copyright (C) 2007-2010 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef CARTRIDGE_H #ifndef CARTRIDGE_H
#define CARTRIDGE_H #define CARTRIDGE_H
#include "memptrs.h" #include "memptrs.h"
#include "rtc.h" #include "rtc.h"
#include "savestate.h" #include "savestate.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
//DOOM //DOOM
//enum eAddressMappingType //enum eAddressMappingType
//{ //{
// eAddressMappingType_ROM, // eAddressMappingType_ROM,
// eAddressMappingType_RAM // eAddressMappingType_RAM
//}; //};
// //
//struct AddressMapping //struct AddressMapping
//{ //{
// int32_t address; // int32_t address;
// eAddressMappingType type; // eAddressMappingType type;
//}; //};
class Mbc { class Mbc {
public: public:
virtual ~Mbc() {} virtual ~Mbc() {}
virtual void romWrite(unsigned P, unsigned data) = 0; virtual void romWrite(unsigned P, unsigned data) = 0;
virtual void loadState(const SaveState::Mem &ss) = 0; virtual void loadState(const SaveState::Mem &ss) = 0;
virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0; virtual bool isAddressWithinAreaRombankCanBeMappedTo(unsigned address, unsigned rombank) const = 0;
//virtual void mapAddress(AddressMapping* mapping, unsigned address) const = 0; //DOOM //virtual void mapAddress(AddressMapping* mapping, unsigned address) const = 0; //DOOM
template<bool isReader>void SyncState(NewState *ns) template<bool isReader>void SyncState(NewState *ns)
{ {
// can't have virtual templates, so.. // can't have virtual templates, so..
SyncState(ns, isReader); SyncState(ns, isReader);
} }
virtual void SyncState(NewState *ns, bool isReader) = 0; virtual void SyncState(NewState *ns, bool isReader) = 0;
}; };
class Cartridge { class Cartridge {
MemPtrs memptrs; MemPtrs memptrs;
Rtc rtc; Rtc rtc;
std::auto_ptr<Mbc> mbc; std::auto_ptr<Mbc> mbc;
public: public:
void setStatePtrs(SaveState &); void setStatePtrs(SaveState &);
void loadState(const SaveState &); void loadState(const SaveState &);
bool loaded() const { return mbc.get(); } bool loaded() const { return mbc.get(); }
const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); } const unsigned char * rmem(unsigned area) const { return memptrs.rmem(area); }
unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); } unsigned char * wmem(unsigned area) const { return memptrs.wmem(area); }
unsigned char * vramdata() const { return memptrs.vramdata(); } unsigned char * vramdata() const { return memptrs.vramdata(); }
unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); } unsigned char * romdata(unsigned area) const { return memptrs.romdata(area); }
unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); } unsigned char * wramdata(unsigned area) const { return memptrs.wramdata(area); }
const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); } const unsigned char * rdisabledRam() const { return memptrs.rdisabledRam(); }
const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); } const unsigned char * rsrambankptr() const { return memptrs.rsrambankptr(); }
unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); } unsigned char * wsrambankptr() const { return memptrs.wsrambankptr(); }
unsigned char * vrambankptr() const { return memptrs.vrambankptr(); } unsigned char * vrambankptr() const { return memptrs.vrambankptr(); }
OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); } OamDmaSrc oamDmaSrc() const { return memptrs.oamDmaSrc(); }
unsigned curRomBank() const { return memptrs.curRomBank(); }
void setVrambank(unsigned bank) { memptrs.setVrambank(bank); }
void setWrambank(unsigned bank) { memptrs.setWrambank(bank); } void setVrambank(unsigned bank) { memptrs.setVrambank(bank); }
void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); } void setWrambank(unsigned bank) { memptrs.setWrambank(bank); }
void setOamDmaSrc(OamDmaSrc oamDmaSrc) { memptrs.setOamDmaSrc(oamDmaSrc); }
void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); }
void mbcWrite(unsigned addr, unsigned data) { mbc->romWrite(addr, data); }
bool isCgb() const { return gambatte::isCgb(memptrs); }
bool isCgb() const { return gambatte::isCgb(memptrs); }
void rtcWrite(unsigned data) { rtc.write(data); }
unsigned char rtcRead() const { return *rtc.getActive(); } void rtcWrite(unsigned data) { rtc.write(data); }
unsigned char rtcRead() const { return *rtc.getActive(); }
void loadSavedata(const char *data);
int saveSavedataLength(); void loadSavedata(const char *data);
void saveSavedata(char *dest); int saveSavedataLength();
void saveSavedata(char *dest);
bool getMemoryArea(int which, unsigned char **data, int *length) const;
bool getMemoryArea(int which, unsigned char **data, int *length) const;
int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
const char * romTitle() const { return reinterpret_cast<const char *>(memptrs.romdata() + 0x134); } int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
const char * romTitle() const { return reinterpret_cast<const char *>(memptrs.romdata() + 0x134); }
void setRTCCallback(std::uint32_t (*callback)()) {
rtc.setRTCCallback(callback); void setRTCCallback(std::uint32_t (*callback)()) {
} rtc.setRTCCallback(callback);
}
template<bool isReader>void SyncState(NewState *ns);
}; template<bool isReader>void SyncState(NewState *ns);
};
}
}
#endif
#endif

View File

@ -1,226 +1,223 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007-2010 by Sindre Aamås * * Copyright (C) 2007-2010 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#include "memptrs.h" #include "memptrs.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
namespace gambatte { namespace gambatte {
MemPtrs::MemPtrs() MemPtrs::MemPtrs()
: rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0), : rmem_(), wmem_(), romdata_(), wramdata_(), vrambankptr_(0), rsrambankptr_(0),
wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF), wsrambankptr_(0), memchunk_(0), rambankdata_(0), wramdataend_(0), oamDmaSrc_(OAM_DMA_SRC_OFF),
memchunk_len(0) curRomBank_(1),
{ memchunk_len(0)
} {
}
MemPtrs::~MemPtrs() {
delete []memchunk_; MemPtrs::~MemPtrs() {
} delete []memchunk_;
}
void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) {
delete []memchunk_; void MemPtrs::reset(const unsigned rombanks, const unsigned rambanks, const unsigned wrambanks) {
delete []memchunk_;
memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000; memchunk_len = 0x4000 + rombanks * 0x4000ul + 0x4000 + rambanks * 0x2000ul + wrambanks * 0x1000ul + 0x4000;
memchunk_ = new unsigned char[memchunk_len]; memchunk_ = new unsigned char[memchunk_len];
romdata_[0] = romdata(); romdata_[0] = romdata();
rambankdata_ = romdata_[0] + rombanks * 0x4000ul + 0x4000;
rambankdata_ = romdata_[0] + rombanks * 0x4000ul + 0x4000; wramdata_[0] = rambankdata_ + rambanks * 0x2000ul;
wramdata_[0] = rambankdata_ + rambanks * 0x2000ul; wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul;
wramdataend_ = wramdata_[0] + wrambanks * 0x1000ul;
std::memset(rdisabledRamw(), 0xFF, 0x2000);
std::memset(rdisabledRamw(), 0xFF, 0x2000);
oamDmaSrc_ = OAM_DMA_SRC_OFF;
oamDmaSrc_ = OAM_DMA_SRC_OFF; rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000;
rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; setRombank(1);
setRombank(1); setRambank(0, 0);
setRambank(0, 0); setVrambank(0);
setVrambank(0); setWrambank(1);
setWrambank(1);
// we save only the ram areas
// we save only the ram areas memchunk_saveoffs = vramdata() - memchunk_;
memchunk_saveoffs = vramdata() - memchunk_; memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs;
memchunk_savelen = wramdataend() - memchunk_ - memchunk_saveoffs; }
}
void MemPtrs::setRombank0(const unsigned bank) {
void MemPtrs::setRombank0(const unsigned bank) { romdata_[0] = romdata() + bank * 0x4000ul;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
romdata_[0] = romdata() + bank * 0x4000ul; disconnectOamDmaAreas();
}
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
disconnectOamDmaAreas(); void MemPtrs::setRombank(const unsigned bank) {
} curRomBank_ = bank;
romdata_[1] = romdata() + bank * 0x4000ul - 0x4000;
void MemPtrs::setRombank(const unsigned bank) { rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1];
disconnectOamDmaAreas();
romdata_[1] = romdata() + bank * 0x4000ul - 0x4000; }
rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) {
disconnectOamDmaAreas(); unsigned char *const srambankptr = flags & RTC_EN
} ? 0
: (rambankdata() != rambankdataend()
void MemPtrs::setRambank(const unsigned flags, const unsigned rambank) { ? rambankdata_ + rambank * 0x2000ul - 0xA000 : wdisabledRam() - 0xA000);
unsigned char *const srambankptr = flags & RTC_EN
? 0 rsrambankptr_ = (flags & READ_EN) && srambankptr != wdisabledRam() - 0xA000 ? srambankptr : rdisabledRamw() - 0xA000;
: (rambankdata() != rambankdataend() wsrambankptr_ = flags & WRITE_EN ? srambankptr : wdisabledRam() - 0xA000;
? rambankdata_ + rambank * 0x2000ul - 0xA000 : wdisabledRam() - 0xA000); rmem_[0xB] = rmem_[0xA] = rsrambankptr_;
wmem_[0xB] = wmem_[0xA] = wsrambankptr_;
rsrambankptr_ = (flags & READ_EN) && srambankptr != wdisabledRam() - 0xA000 ? srambankptr : rdisabledRamw() - 0xA000; disconnectOamDmaAreas();
wsrambankptr_ = flags & WRITE_EN ? srambankptr : wdisabledRam() - 0xA000; }
rmem_[0xB] = rmem_[0xA] = rsrambankptr_;
wmem_[0xB] = wmem_[0xA] = wsrambankptr_; void MemPtrs::setWrambank(const unsigned bank) {
disconnectOamDmaAreas(); wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000;
} rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
disconnectOamDmaAreas();
void MemPtrs::setWrambank(const unsigned bank) { }
wramdata_[1] = wramdata_[0] + ((bank & 0x07) ? (bank & 0x07) : 1) * 0x1000;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) {
disconnectOamDmaAreas(); rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0];
} rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1];
rmem_[0xB] = rmem_[0xA] = rsrambankptr_;
void MemPtrs::setOamDmaSrc(const OamDmaSrc oamDmaSrc) { wmem_[0xB] = wmem_[0xA] = wsrambankptr_;
rmem_[0x3] = rmem_[0x2] = rmem_[0x1] = rmem_[0x0] = romdata_[0]; rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000;
rmem_[0x7] = rmem_[0x6] = rmem_[0x5] = rmem_[0x4] = romdata_[1]; rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000;
rmem_[0xB] = rmem_[0xA] = rsrambankptr_; rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000;
wmem_[0xB] = wmem_[0xA] = wsrambankptr_;
rmem_[0xC] = wmem_[0xC] = wramdata_[0] - 0xC000; oamDmaSrc_ = oamDmaSrc;
rmem_[0xD] = wmem_[0xD] = wramdata_[1] - 0xD000; disconnectOamDmaAreas();
rmem_[0xE] = wmem_[0xE] = wramdata_[0] - 0xE000; }
oamDmaSrc_ = oamDmaSrc; void MemPtrs::disconnectOamDmaAreas() {
disconnectOamDmaAreas(); if (isCgb(*this)) {
} switch (oamDmaSrc_) {
case OAM_DMA_SRC_ROM: // fall through
void MemPtrs::disconnectOamDmaAreas() { case OAM_DMA_SRC_SRAM:
if (isCgb(*this)) { case OAM_DMA_SRC_INVALID:
switch (oamDmaSrc_) { std::fill(rmem_, rmem_ + 8, static_cast<unsigned char *>(0));
case OAM_DMA_SRC_ROM: // fall through rmem_[0xB] = rmem_[0xA] = 0;
case OAM_DMA_SRC_SRAM: wmem_[0xB] = wmem_[0xA] = 0;
case OAM_DMA_SRC_INVALID: break;
std::fill(rmem_, rmem_ + 8, static_cast<unsigned char *>(0)); case OAM_DMA_SRC_VRAM:
rmem_[0xB] = rmem_[0xA] = 0; break;
wmem_[0xB] = wmem_[0xA] = 0; case OAM_DMA_SRC_WRAM:
break; rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0;
case OAM_DMA_SRC_VRAM: wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0;
break; break;
case OAM_DMA_SRC_WRAM: case OAM_DMA_SRC_OFF:
rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; break;
wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; }
break; } else {
case OAM_DMA_SRC_OFF: switch (oamDmaSrc_) {
break; case OAM_DMA_SRC_ROM: // fall through
} case OAM_DMA_SRC_SRAM:
} else { case OAM_DMA_SRC_WRAM:
switch (oamDmaSrc_) { case OAM_DMA_SRC_INVALID:
case OAM_DMA_SRC_ROM: // fall through std::fill(rmem_, rmem_ + 8, static_cast<unsigned char *>(0));
case OAM_DMA_SRC_SRAM: rmem_[0xB] = rmem_[0xA] = 0;
case OAM_DMA_SRC_WRAM: wmem_[0xB] = wmem_[0xA] = 0;
case OAM_DMA_SRC_INVALID: rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0;
std::fill(rmem_, rmem_ + 8, static_cast<unsigned char *>(0)); wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0;
rmem_[0xB] = rmem_[0xA] = 0; break;
wmem_[0xB] = wmem_[0xA] = 0; case OAM_DMA_SRC_VRAM:
rmem_[0xE] = rmem_[0xD] = rmem_[0xC] = 0; break;
wmem_[0xE] = wmem_[0xD] = wmem_[0xC] = 0; case OAM_DMA_SRC_OFF:
break; break;
case OAM_DMA_SRC_VRAM: }
break; }
case OAM_DMA_SRC_OFF: }
break;
} // all pointers here are relative to memchunk_
} #define MSS(a) RSS(a,memchunk_)
} #define MSL(a) RSL(a,memchunk_)
// all pointers here are relative to memchunk_ SYNCFUNC(MemPtrs)
#define MSS(a) RSS(a,memchunk_) {
#define MSL(a) RSL(a,memchunk_) /*
int memchunk_len_old = memchunk_len;
SYNCFUNC(MemPtrs) int memchunk_saveoffs_old = memchunk_saveoffs;
{ int memchunk_savelen_old = memchunk_savelen;
/* */
int memchunk_len_old = memchunk_len;
int memchunk_saveoffs_old = memchunk_saveoffs; NSS(memchunk_len);
int memchunk_savelen_old = memchunk_savelen; NSS(memchunk_saveoffs);
*/ NSS(memchunk_savelen);
NSS(memchunk_len); /*
NSS(memchunk_saveoffs); if (isReader)
NSS(memchunk_savelen); {
if (memchunk_len != memchunk_len_old || memchunk_saveoffs != memchunk_saveoffs_old || memchunk_savelen != memchunk_savelen_old)
/* __debugbreak();
if (isReader) }
{ */
if (memchunk_len != memchunk_len_old || memchunk_saveoffs != memchunk_saveoffs_old || memchunk_savelen != memchunk_savelen_old)
__debugbreak(); PSS(memchunk_ + memchunk_saveoffs, memchunk_savelen);
}
*/ MSS(rmem_[0x0]);
MSS(wmem_[0x0]);
PSS(memchunk_ + memchunk_saveoffs, memchunk_savelen); MSS(rmem_[0x1]);
MSS(wmem_[0x1]);
MSS(rmem_[0x0]); MSS(rmem_[0x2]);
MSS(wmem_[0x0]); MSS(wmem_[0x2]);
MSS(rmem_[0x1]); MSS(rmem_[0x3]);
MSS(wmem_[0x1]); MSS(wmem_[0x3]);
MSS(rmem_[0x2]); MSS(rmem_[0x4]);
MSS(wmem_[0x2]); MSS(wmem_[0x4]);
MSS(rmem_[0x3]); MSS(rmem_[0x5]);
MSS(wmem_[0x3]); MSS(wmem_[0x5]);
MSS(rmem_[0x4]); MSS(rmem_[0x6]);
MSS(wmem_[0x4]); MSS(wmem_[0x6]);
MSS(rmem_[0x5]); MSS(rmem_[0x7]);
MSS(wmem_[0x5]); MSS(wmem_[0x7]);
MSS(rmem_[0x6]); MSS(rmem_[0x8]);
MSS(wmem_[0x6]); MSS(wmem_[0x8]);
MSS(rmem_[0x7]); MSS(rmem_[0x9]);
MSS(wmem_[0x7]); MSS(wmem_[0x9]);
MSS(rmem_[0x8]); MSS(rmem_[0xa]);
MSS(wmem_[0x8]); MSS(wmem_[0xa]);
MSS(rmem_[0x9]); MSS(rmem_[0xb]);
MSS(wmem_[0x9]); MSS(wmem_[0xb]);
MSS(rmem_[0xa]); MSS(rmem_[0xc]);
MSS(wmem_[0xa]); MSS(wmem_[0xc]);
MSS(rmem_[0xb]); MSS(rmem_[0xd]);
MSS(wmem_[0xb]); MSS(wmem_[0xd]);
MSS(rmem_[0xc]); MSS(rmem_[0xe]);
MSS(wmem_[0xc]); MSS(wmem_[0xe]);
MSS(rmem_[0xd]); MSS(rmem_[0xf]);
MSS(wmem_[0xd]); MSS(wmem_[0xf]);
MSS(rmem_[0xe]); //for (int i = 0; i < 0x10; i++)
MSS(wmem_[0xe]); //{
MSS(rmem_[0xf]); // MSS(rmem_[i]);
MSS(wmem_[0xf]); // MSS(wmem_[i]);
//for (int i = 0; i < 0x10; i++) //}
//{ MSS(romdata_[0]);
// MSS(rmem_[i]); MSS(romdata_[1]);
// MSS(wmem_[i]); MSS(wramdata_[0]);
//} MSS(wramdata_[1]);
MSS(romdata_[0]); MSS(vrambankptr_);
MSS(romdata_[1]); MSS(rsrambankptr_);
MSS(wramdata_[0]); MSS(wsrambankptr_);
MSS(wramdata_[1]); MSS(rambankdata_);
MSS(vrambankptr_); MSS(wramdataend_);
MSS(rsrambankptr_); NSS(oamDmaSrc_);
MSS(wsrambankptr_); NSS(curRomBank_);
MSS(rambankdata_); }
MSS(wramdataend_);
NSS(oamDmaSrc_); }
}
}

View File

@ -1,93 +1,96 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007-2010 by Sindre Aamås * * Copyright (C) 2007-2010 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef MEMPTRS_H #ifndef MEMPTRS_H
#define MEMPTRS_H #define MEMPTRS_H
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM, enum OamDmaSrc { OAM_DMA_SRC_ROM, OAM_DMA_SRC_SRAM, OAM_DMA_SRC_VRAM,
OAM_DMA_SRC_WRAM, OAM_DMA_SRC_INVALID, OAM_DMA_SRC_OFF }; OAM_DMA_SRC_WRAM, OAM_DMA_SRC_INVALID, OAM_DMA_SRC_OFF };
class MemPtrs { class MemPtrs {
const unsigned char *rmem_[0x10]; const unsigned char *rmem_[0x10];
unsigned char *wmem_[0x10]; unsigned char *wmem_[0x10];
unsigned char *romdata_[2]; unsigned char *romdata_[2];
unsigned char *wramdata_[2]; unsigned char *wramdata_[2];
unsigned char *vrambankptr_; unsigned char *vrambankptr_;
unsigned char *rsrambankptr_; unsigned char *rsrambankptr_;
unsigned char *wsrambankptr_; unsigned char *wsrambankptr_;
unsigned char *memchunk_; unsigned char *memchunk_;
unsigned char *rambankdata_; unsigned char *rambankdata_;
unsigned char *wramdataend_; unsigned char *wramdataend_;
OamDmaSrc oamDmaSrc_; OamDmaSrc oamDmaSrc_;
int memchunk_len; unsigned curRomBank_;
int memchunk_saveoffs;
int memchunk_savelen; int memchunk_len;
int memchunk_saveoffs;
MemPtrs(const MemPtrs &); int memchunk_savelen;
MemPtrs & operator=(const MemPtrs &);
void disconnectOamDmaAreas(); MemPtrs(const MemPtrs &);
unsigned char * rdisabledRamw() const { return wramdataend_ ; } MemPtrs & operator=(const MemPtrs &);
unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; } void disconnectOamDmaAreas();
public: unsigned char * rdisabledRamw() const { return wramdataend_ ; }
enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 }; unsigned char * wdisabledRam() const { return wramdataend_ + 0x2000; }
public:
MemPtrs(); enum RamFlag { READ_EN = 1, WRITE_EN = 2, RTC_EN = 4 };
~MemPtrs();
void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks); MemPtrs();
~MemPtrs();
const unsigned char * rmem(unsigned area) const { return rmem_[area]; } void reset(unsigned rombanks, unsigned rambanks, unsigned wrambanks);
unsigned char * wmem(unsigned area) const { return wmem_[area]; }
unsigned char * vramdata() const { return rambankdata_ - 0x4000; } const unsigned char * rmem(unsigned area) const { return rmem_[area]; }
unsigned char * vramdataend() const { return rambankdata_; } unsigned char * wmem(unsigned area) const { return wmem_[area]; }
unsigned char * romdata() const { return memchunk_ + 0x4000;} unsigned char * vramdata() const { return rambankdata_ - 0x4000; }
unsigned char * romdata(unsigned area) const { return romdata_[area]; } unsigned char * vramdataend() const { return rambankdata_; }
unsigned char * romdataend() const { return rambankdata_ - 0x4000; } unsigned char * romdata() const { return memchunk_ + 0x4000; }
unsigned char * wramdata(unsigned area) const { return wramdata_[area]; } unsigned char * romdata(unsigned area) const { return romdata_[area]; }
unsigned char * wramdataend() const { return wramdataend_; } unsigned char * romdataend() const { return rambankdata_ - 0x4000; }
unsigned char * rambankdata() const { return rambankdata_; } unsigned char * wramdata(unsigned area) const { return wramdata_[area]; }
unsigned char * rambankdataend() const { return wramdata_[0]; } unsigned char * wramdataend() const { return wramdataend_; }
const unsigned char * rdisabledRam() const { return rdisabledRamw(); } unsigned char * rambankdata() const { return rambankdata_; }
const unsigned char * rsrambankptr() const { return rsrambankptr_; } unsigned char * rambankdataend() const { return wramdata_[0]; }
unsigned char * wsrambankptr() const { return wsrambankptr_; } const unsigned char * rdisabledRam() const { return rdisabledRamw(); }
unsigned char * vrambankptr() const { return vrambankptr_; } const unsigned char * rsrambankptr() const { return rsrambankptr_; }
OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; } unsigned char * wsrambankptr() const { return wsrambankptr_; }
unsigned char * vrambankptr() const { return vrambankptr_; }
void setRombank0(unsigned bank); OamDmaSrc oamDmaSrc() const { return oamDmaSrc_; }
void setRombank(unsigned bank); unsigned curRomBank() const { return curRomBank_; }
void setRambank(unsigned ramFlags, unsigned rambank);
void setVrambank(unsigned bank) { vrambankptr_ = vramdata() + bank * 0x2000ul - 0x8000; } void setRombank0(unsigned bank);
void setWrambank(unsigned bank); void setRombank(unsigned bank);
void setOamDmaSrc(OamDmaSrc oamDmaSrc); void setRambank(unsigned ramFlags, unsigned rambank);
void setVrambank(unsigned bank) { vrambankptr_ = vramdata() + bank * 0x2000ul - 0x8000; }
template<bool isReader>void SyncState(NewState *ns); void setWrambank(unsigned bank);
}; void setOamDmaSrc(OamDmaSrc oamDmaSrc);
inline bool isCgb(const MemPtrs &memptrs) { template<bool isReader>void SyncState(NewState *ns);
return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000; };
}
inline bool isCgb(const MemPtrs &memptrs) {
} return memptrs.wramdataend() - memptrs.wramdata(0) == 0x8000;
}
#endif
}
#endif

View File

@ -1,177 +1,177 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#include "rtc.h" #include "rtc.h"
#include "../savestate.h" #include "../savestate.h"
#include <cstdlib> #include <cstdlib>
namespace gambatte { namespace gambatte {
Rtc::Rtc() Rtc::Rtc()
: activeData(NULL), : activeData(NULL),
activeSet(NULL), activeSet(NULL),
baseTime(0), baseTime(0),
haltTime(0), haltTime(0),
index(5), index(5),
dataDh(0), dataDh(0),
dataDl(0), dataDl(0),
dataH(0), dataH(0),
dataM(0), dataM(0),
dataS(0), dataS(0),
enabled(false), enabled(false),
lastLatchData(false), lastLatchData(false),
timeCB(0) timeCB(0)
{ {
} }
void Rtc::doLatch() { void Rtc::doLatch() {
std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime; std::uint32_t tmp = ((dataDh & 0x40) ? haltTime : timeCB()) - baseTime;
while (tmp > 0x1FF * 86400) { while (tmp > 0x1FF * 86400) {
baseTime += 0x1FF * 86400; baseTime += 0x1FF * 86400;
tmp -= 0x1FF * 86400; tmp -= 0x1FF * 86400;
dataDh |= 0x80; dataDh |= 0x80;
} }
dataDl = (tmp / 86400) & 0xFF; dataDl = (tmp / 86400) & 0xFF;
dataDh &= 0xFE; dataDh &= 0xFE;
dataDh |= ((tmp / 86400) & 0x100) >> 8; dataDh |= ((tmp / 86400) & 0x100) >> 8;
tmp %= 86400; tmp %= 86400;
dataH = tmp / 3600; dataH = tmp / 3600;
tmp %= 3600; tmp %= 3600;
dataM = tmp / 60; dataM = tmp / 60;
tmp %= 60; tmp %= 60;
dataS = tmp; dataS = tmp;
} }
void Rtc::doSwapActive() { void Rtc::doSwapActive() {
if (!enabled || index > 4) { if (!enabled || index > 4) {
activeData = NULL; activeData = NULL;
activeSet = NULL; activeSet = NULL;
} else switch (index) { } else switch (index) {
case 0x00: case 0x00:
activeData = &dataS; activeData = &dataS;
activeSet = &Rtc::setS; activeSet = &Rtc::setS;
break; break;
case 0x01: case 0x01:
activeData = &dataM; activeData = &dataM;
activeSet = &Rtc::setM; activeSet = &Rtc::setM;
break; break;
case 0x02: case 0x02:
activeData = &dataH; activeData = &dataH;
activeSet = &Rtc::setH; activeSet = &Rtc::setH;
break; break;
case 0x03: case 0x03:
activeData = &dataDl; activeData = &dataDl;
activeSet = &Rtc::setDl; activeSet = &Rtc::setDl;
break; break;
case 0x04: case 0x04:
activeData = &dataDh; activeData = &dataDh;
activeSet = &Rtc::setDh; activeSet = &Rtc::setDh;
break; break;
} }
} }
void Rtc::loadState(const SaveState &state) { void Rtc::loadState(const SaveState &state) {
baseTime = state.rtc.baseTime; baseTime = state.rtc.baseTime;
haltTime = state.rtc.haltTime; haltTime = state.rtc.haltTime;
dataDh = state.rtc.dataDh; dataDh = state.rtc.dataDh;
dataDl = state.rtc.dataDl; dataDl = state.rtc.dataDl;
dataH = state.rtc.dataH; dataH = state.rtc.dataH;
dataM = state.rtc.dataM; dataM = state.rtc.dataM;
dataS = state.rtc.dataS; dataS = state.rtc.dataS;
lastLatchData = state.rtc.lastLatchData; lastLatchData = state.rtc.lastLatchData;
doSwapActive(); doSwapActive();
} }
void Rtc::setDh(const unsigned new_dh) { void Rtc::setDh(const unsigned new_dh) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB(); const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100; const std::uint32_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100;
baseTime += old_highdays * 86400; baseTime += old_highdays * 86400;
baseTime -= ((new_dh & 0x1) << 8) * 86400; baseTime -= ((new_dh & 0x1) << 8) * 86400;
if ((dataDh ^ new_dh) & 0x40) { if ((dataDh ^ new_dh) & 0x40) {
if (new_dh & 0x40) if (new_dh & 0x40)
haltTime = timeCB(); haltTime = timeCB();
else else
baseTime += timeCB() - haltTime; baseTime += timeCB() - haltTime;
} }
} }
void Rtc::setDl(const unsigned new_lowdays) { void Rtc::setDl(const unsigned new_lowdays) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB(); const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF; const std::uint32_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF;
baseTime += old_lowdays * 86400; baseTime += old_lowdays * 86400;
baseTime -= new_lowdays * 86400; baseTime -= new_lowdays * 86400;
} }
void Rtc::setH(const unsigned new_hours) { void Rtc::setH(const unsigned new_hours) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB(); const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24; const std::uint32_t old_hours = ((unixtime - baseTime) / 3600) % 24;
baseTime += old_hours * 3600; baseTime += old_hours * 3600;
baseTime -= new_hours * 3600; baseTime -= new_hours * 3600;
} }
void Rtc::setM(const unsigned new_minutes) { void Rtc::setM(const unsigned new_minutes) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB(); const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60; const std::uint32_t old_minutes = ((unixtime - baseTime) / 60) % 60;
baseTime += old_minutes * 60; baseTime += old_minutes * 60;
baseTime -= new_minutes * 60; baseTime -= new_minutes * 60;
} }
void Rtc::setS(const unsigned new_seconds) { void Rtc::setS(const unsigned new_seconds) {
const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB(); const std::uint32_t unixtime = (dataDh & 0x40) ? haltTime : timeCB();
baseTime += (unixtime - baseTime) % 60; baseTime += (unixtime - baseTime) % 60;
baseTime -= new_seconds; baseTime -= new_seconds;
} }
SYNCFUNC(Rtc) SYNCFUNC(Rtc)
{ {
EBS(activeData, 0); EBS(activeData, 0);
EVS(activeData, &dataS, 1); EVS(activeData, &dataS, 1);
EVS(activeData, &dataM, 2); EVS(activeData, &dataM, 2);
EVS(activeData, &dataH, 3); EVS(activeData, &dataH, 3);
EVS(activeData, &dataDl, 4); EVS(activeData, &dataDl, 4);
EVS(activeData, &dataDh, 5); EVS(activeData, &dataDh, 5);
EES(activeData, NULL); EES(activeData, NULL);
EBS(activeSet, 0); EBS(activeSet, 0);
EVS(activeSet, &Rtc::setS, 1); EVS(activeSet, &Rtc::setS, 1);
EVS(activeSet, &Rtc::setM, 2); EVS(activeSet, &Rtc::setM, 2);
EVS(activeSet, &Rtc::setH, 3); EVS(activeSet, &Rtc::setH, 3);
EVS(activeSet, &Rtc::setDl, 4); EVS(activeSet, &Rtc::setDl, 4);
EVS(activeSet, &Rtc::setDh, 5); EVS(activeSet, &Rtc::setDh, 5);
EES(activeSet, NULL); EES(activeSet, NULL);
NSS(baseTime); NSS(baseTime);
NSS(haltTime); NSS(haltTime);
NSS(index); NSS(index);
NSS(dataDh); NSS(dataDh);
NSS(dataDl); NSS(dataDl);
NSS(dataH); NSS(dataH);
NSS(dataM); NSS(dataM);
NSS(dataS); NSS(dataS);
NSS(enabled); NSS(enabled);
NSS(lastLatchData); NSS(lastLatchData);
} }
} }

View File

@ -1,98 +1,98 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef RTC_H #ifndef RTC_H
#define RTC_H #define RTC_H
#include <cstdint> #include <cstdint>
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
struct SaveState; struct SaveState;
class Rtc { class Rtc {
private: private:
unsigned char *activeData; unsigned char *activeData;
void (Rtc::*activeSet)(unsigned); void (Rtc::*activeSet)(unsigned);
std::uint32_t baseTime; std::uint32_t baseTime;
std::uint32_t haltTime; std::uint32_t haltTime;
unsigned char index; unsigned char index;
unsigned char dataDh; unsigned char dataDh;
unsigned char dataDl; unsigned char dataDl;
unsigned char dataH; unsigned char dataH;
unsigned char dataM; unsigned char dataM;
unsigned char dataS; unsigned char dataS;
bool enabled; bool enabled;
bool lastLatchData; bool lastLatchData;
std::uint32_t (*timeCB)(); std::uint32_t (*timeCB)();
void doLatch(); void doLatch();
void doSwapActive(); void doSwapActive();
void setDh(unsigned new_dh); void setDh(unsigned new_dh);
void setDl(unsigned new_lowdays); void setDl(unsigned new_lowdays);
void setH(unsigned new_hours); void setH(unsigned new_hours);
void setM(unsigned new_minutes); void setM(unsigned new_minutes);
void setS(unsigned new_seconds); void setS(unsigned new_seconds);
public: public:
Rtc(); Rtc();
const unsigned char* getActive() const { return activeData; } const unsigned char* getActive() const { return activeData; }
std::uint32_t getBaseTime() const { return baseTime; } std::uint32_t getBaseTime() const { return baseTime; }
void setBaseTime(const std::uint32_t baseTime) { void setBaseTime(const std::uint32_t baseTime) {
this->baseTime = baseTime; this->baseTime = baseTime;
// doLatch(); // doLatch();
} }
void latch(const unsigned data) { void latch(const unsigned data) {
if (!lastLatchData && data == 1) if (!lastLatchData && data == 1)
doLatch(); doLatch();
lastLatchData = data; lastLatchData = data;
} }
void loadState(const SaveState &state); void loadState(const SaveState &state);
void set(const bool enabled, unsigned bank) { void set(const bool enabled, unsigned bank) {
bank &= 0xF; bank &= 0xF;
bank -= 8; bank -= 8;
this->enabled = enabled; this->enabled = enabled;
this->index = bank; this->index = bank;
doSwapActive(); doSwapActive();
} }
void write(const unsigned data) { void write(const unsigned data) {
// if (activeSet) // if (activeSet)
(this->*activeSet)(data); (this->*activeSet)(data);
*activeData = data; *activeData = data;
} }
void setRTCCallback(std::uint32_t (*callback)()) { void setRTCCallback(std::uint32_t (*callback)()) {
timeCB = callback; timeCB = callback;
} }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,298 +1,336 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef MEMORY_H #ifndef MEMORY_H
#define MEMORY_H #define MEMORY_H
#include "mem/cartridge.h" static unsigned char const agbOverride[0xD] = { 0xFF, 0x00, 0xCD, 0x03, 0x35, 0xAA, 0x31, 0x90, 0x94, 0x00, 0x00, 0x00, 0x00 };
#include "video.h"
#include "sound.h" #include "mem/cartridge.h"
#include "interrupter.h" #include "video.h"
#include "tima.h" #include "sound.h"
#include "newstate.h" #include "interrupter.h"
#include "gambatte.h" #include "tima.h"
#include "newstate.h"
namespace gambatte { #include "gambatte.h"
class InputGetter;
class FilterInfo; namespace gambatte {
class InputGetter;
class Memory { class FilterInfo;
Cartridge cart;
unsigned char ioamhram[0x200]; class Memory {
Cartridge cart;
void (*readCallback)(unsigned); unsigned char ioamhram[0x200];
void (*writeCallback)(unsigned); unsigned char cgbBios[0x900];
void (*execCallback)(unsigned); unsigned char dmgBios[0x100];
CDCallback cdCallback; bool biosMode;
void (*linkCallback)(); bool cgbSwitching;
bool agbMode;
unsigned (*getInput)(); bool gbIsCgb_;
unsigned long divLastUpdate; unsigned short &SP;
unsigned long lastOamDmaUpdate; unsigned short &PC;
InterruptRequester intreq; void (*readCallback)(unsigned);
Tima tima; void (*writeCallback)(unsigned);
LCD display; void (*execCallback)(unsigned);
PSG sound; CDCallback cdCallback;
Interrupter interrupter; void(*linkCallback)();
unsigned short dmaSource; unsigned (*getInput)();
unsigned short dmaDestination; unsigned long divLastUpdate;
unsigned char oamDmaPos; unsigned long lastOamDmaUpdate;
unsigned char serialCnt;
bool blanklcd; InterruptRequester intreq;
Tima tima;
bool LINKCABLE; LCD display;
bool linkClockTrigger; PSG sound;
Interrupter interrupter;
void decEventCycles(MemEventId eventId, unsigned long dec);
unsigned short dmaSource;
void oamDmaInitSetup(); unsigned short dmaDestination;
void updateOamDma(unsigned long cycleCounter); unsigned char oamDmaPos;
void startOamDma(unsigned long cycleCounter); unsigned char serialCnt;
void endOamDma(unsigned long cycleCounter); bool blanklcd;
const unsigned char * oamDmaSrcPtr() const;
bool LINKCABLE;
unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter); bool linkClockTrigger;
unsigned nontrivial_read(unsigned P, unsigned long cycleCounter);
void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter); void decEventCycles(MemEventId eventId, unsigned long dec);
void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter);
void oamDmaInitSetup();
unsigned nontrivial_peek(unsigned P); void updateOamDma(unsigned long cycleCounter);
unsigned nontrivial_ff_peek(unsigned P); void startOamDma(unsigned long cycleCounter);
void endOamDma(unsigned long cycleCounter);
void updateSerial(unsigned long cc); const unsigned char * oamDmaSrcPtr() const;
void updateTimaIrq(unsigned long cc);
void updateIrqs(unsigned long cc); unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter);
unsigned nontrivial_read(unsigned P, unsigned long cycleCounter);
bool isDoubleSpeed() const { return display.isDoubleSpeed(); } void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter);
void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter);
public:
explicit Memory(const Interrupter &interrupter); unsigned nontrivial_peek(unsigned P);
unsigned nontrivial_ff_peek(unsigned P);
bool loaded() const { return cart.loaded(); }
const char * romTitle() const { return cart.romTitle(); } void updateSerial(unsigned long cc);
void updateTimaIrq(unsigned long cc);
int debugGetLY() const { return display.debugGetLY(); } void updateIrqs(unsigned long cc);
void setStatePtrs(SaveState &state); bool isDoubleSpeed() const { return display.isDoubleSpeed(); }
void loadState(const SaveState &state/*, unsigned long oldCc*/);
void loadSavedata(const char *data) { cart.loadSavedata(data); } public:
int saveSavedataLength() {return cart.saveSavedataLength(); } explicit Memory(const Interrupter &interrupter, unsigned short &sp, unsigned short &pc);
void saveSavedata(char *dest) { cart.saveSavedata(dest); }
void updateInput(); bool loaded() const { return cart.loaded(); }
unsigned curRomBank() const { return cart.curRomBank(); }
bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); } const char * romTitle() const { return cart.romTitle(); }
unsigned long stop(unsigned long cycleCounter); int debugGetLY() const { return display.debugGetLY(); }
bool isCgb() const { return display.isCgb(); }
bool ime() const { return intreq.ime(); } void setStatePtrs(SaveState &state);
bool halted() const { return intreq.halted(); } void loadState(const SaveState &state/*, unsigned long oldCc*/);
unsigned long nextEventTime() const { return intreq.minEventTime(); } void loadSavedata(const char *data) { cart.loadSavedata(data); }
int saveSavedataLength() {return cart.saveSavedataLength(); }
void setLayers(unsigned mask) { display.setLayers(mask); } void saveSavedata(char *dest) { cart.saveSavedata(dest); }
void updateInput();
bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; }
unsigned char* cgbBiosBuffer() { return (unsigned char*)cgbBios; }
long cyclesSinceBlit(const unsigned long cc) const { unsigned char* dmgBiosBuffer() { return (unsigned char*)dmgBios; }
return cc < intreq.eventTime(BLIT) ? -1 : static_cast<long>((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed()); bool gbIsCgb() { return gbIsCgb_; }
}
bool getMemoryArea(int which, unsigned char **data, int *length); // { return cart.getMemoryArea(which, data, length); }
void halt() { intreq.halt(); }
void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } } unsigned long stop(unsigned long cycleCounter);
bool isCgb() const { return display.isCgb(); }
void di() { intreq.di(); } bool ime() const { return intreq.ime(); }
bool halted() const { return intreq.halted(); }
unsigned ff_read(const unsigned P, const unsigned long cycleCounter) { unsigned long nextEventTime() const { return intreq.minEventTime(); }
return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00];
} void setLayers(unsigned mask) { display.setLayers(mask); }
struct CDMapResult bool isActive() const { return intreq.eventTime(END) != DISABLED_TIME; }
{
eCDLog_AddrType type; long cyclesSinceBlit(const unsigned long cc) const {
unsigned addr; return cc < intreq.eventTime(BLIT) ? -1 : static_cast<long>((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed());
}; }
CDMapResult CDMap(const unsigned P) const void halt() { intreq.halt(); }
{ void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } }
if(P<0x4000)
{ void di() { intreq.di(); }
CDMapResult ret = { eCDLog_AddrType_ROM, P };
return ret; unsigned ff_read(const unsigned P, const unsigned long cycleCounter) {
} return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00];
else if(P<0x8000) }
{
unsigned bank = cart.rmem(P>>12) - cart.rmem(0); struct CDMapResult
unsigned addr = P+bank; {
CDMapResult ret = { eCDLog_AddrType_ROM, addr }; eCDLog_AddrType type;
return ret; unsigned addr;
} };
else if(P<0xA000) {}
else if(P<0xC000) CDMapResult CDMap(const unsigned P) const
{ {
if(cart.wsrambankptr()) if(P<0x4000)
{ {
//not bankable. but. we're not sure how much might be here CDMapResult ret = { eCDLog_AddrType_ROM, P };
unsigned char *data; return ret;
int length; }
bool has = cart.getMemoryArea(3,&data,&length); else if(P<0x8000)
unsigned addr = P&(length-1); {
if(has && length!=0) unsigned bank = cart.rmem(P>>12) - cart.rmem(0);
{ unsigned addr = P+bank;
CDMapResult ret = { eCDLog_AddrType_CartRAM, addr }; CDMapResult ret = { eCDLog_AddrType_ROM, addr };
return ret; return ret;
} }
} else if(P<0xA000) {}
} else if(P<0xC000)
else if(P<0xE000) {
{ if(cart.wsrambankptr())
unsigned bank = cart.wramdata(P >> 12 & 1) - cart.wramdata(0); {
unsigned addr = (P&0xFFF)+bank; //not bankable. but. we're not sure how much might be here
CDMapResult ret = { eCDLog_AddrType_WRAM, addr }; unsigned char *data;
return ret; int length;
} bool has = cart.getMemoryArea(3,&data,&length);
else if(P<0xFF80) {} unsigned addr = P&(length-1);
else if(has && length!=0)
{ {
////this is just for debugging, really, it's pretty useless CDMapResult ret = { eCDLog_AddrType_CartRAM, addr };
//CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) }; return ret;
//return ret; }
} }
}
CDMapResult ret = { eCDLog_AddrType_None }; else if(P<0xE000)
return ret; {
} unsigned bank = cart.wramdata(P >> 12 & 1) - cart.wramdata(0);
unsigned addr = (P&0xFFF)+bank;
CDMapResult ret = { eCDLog_AddrType_WRAM, addr };
unsigned read(const unsigned P, const unsigned long cycleCounter) { return ret;
if (readCallback) }
readCallback(P); else if(P<0xFF80) {}
if(cdCallback) else
{ {
CDMapResult map = CDMap(P); ////this is just for debugging, really, it's pretty useless
if(map.type != eCDLog_AddrType_None) //CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) };
cdCallback(map.addr,map.type,eCDLog_Flags_Data); //return ret;
} }
return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter);
} CDMapResult ret = { eCDLog_AddrType_None };
return ret;
unsigned read_excb(const unsigned P, const unsigned long cycleCounter, bool first) { }
if (execCallback)
execCallback(P);
if(cdCallback) unsigned readBios(const unsigned P) {
{ if (gbIsCgb_) {
CDMapResult map = CDMap(P); if (agbMode && P >= 0xF3 && P < 0x100) {
if(map.type != eCDLog_AddrType_None) return (agbOverride[P - 0xF3] + cgbBios[P]) & 0xFF;
cdCallback(map.addr,map.type,first?eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand); }
} return cgbBios[P];
return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter); }
} return dmgBios[P];
}
unsigned peek(const unsigned P) {
return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_peek(P); unsigned read(const unsigned P, const unsigned long cycleCounter) {
} if (readCallback)
readCallback(P);
void write_nocb(const unsigned P, const unsigned data, const unsigned long cycleCounter) { if(cdCallback)
if (cart.wmem(P >> 12)) { {
cart.wmem(P >> 12)[P] = data; CDMapResult map = CDMap(P);
} else if(map.type != eCDLog_AddrType_None)
nontrivial_write(P, data, cycleCounter); cdCallback(map.addr,map.type,eCDLog_Flags_Data);
} }
if (biosMode && ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)))) {
void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { return readBios(P);
if (cart.wmem(P >> 12)) { }
cart.wmem(P >> 12)[P] = data; return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter);
} else }
nontrivial_write(P, data, cycleCounter);
if (writeCallback) unsigned read_excb(const unsigned P, const unsigned long cycleCounter, bool first) {
writeCallback(P); if (execCallback)
if(cdCallback) execCallback(P);
{ if(cdCallback)
CDMapResult map = CDMap(P); {
if(map.type != eCDLog_AddrType_None) CDMapResult map = CDMap(P);
cdCallback(map.addr,map.type,eCDLog_Flags_Data); if(map.type != eCDLog_AddrType_None)
} cdCallback(map.addr,map.type,first?eCDLog_Flags_ExecFirst : eCDLog_Flags_ExecOperand);
} }
if (biosMode && ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)))) {
void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { return readBios(P);
if (P - 0xFF80u < 0x7Fu) { }
ioamhram[P - 0xFE00] = data; return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_read(P, cycleCounter);
} else }
nontrivial_ff_write(P, data, cycleCounter);
if(cdCallback) unsigned peek(const unsigned P) {
{ if (biosMode && ((!gbIsCgb_ && P < 0x100) || (gbIsCgb_ && P < 0x900 && (P < 0x100 || P >= 0x200)))) {
CDMapResult map = CDMap(P); return readBios(P);
if(map.type != eCDLog_AddrType_None) }
cdCallback(map.addr,map.type,eCDLog_Flags_Data); return cart.rmem(P >> 12) ? cart.rmem(P >> 12)[P] : nontrivial_peek(P);
} }
}
void write_nocb(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
unsigned long event(unsigned long cycleCounter); if (cart.wmem(P >> 12)) {
unsigned long resetCounters(unsigned long cycleCounter); cart.wmem(P >> 12)[P] = data;
} else
int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat); nontrivial_write(P, data, cycleCounter);
}
void setInputGetter(unsigned (*getInput)()) {
this->getInput = getInput; void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
} if (cart.wmem(P >> 12)) {
cart.wmem(P >> 12)[P] = data;
void setReadCallback(void (*callback)(unsigned)) { } else
this->readCallback = callback; nontrivial_write(P, data, cycleCounter);
} if (writeCallback)
void setWriteCallback(void (*callback)(unsigned)) { writeCallback(P);
this->writeCallback = callback; if(cdCallback)
} {
void setExecCallback(void (*callback)(unsigned)) { CDMapResult map = CDMap(P);
this->execCallback = callback; if(map.type != eCDLog_AddrType_None)
} cdCallback(map.addr,map.type,eCDLog_Flags_Data);
void setCDCallback(CDCallback cdc) { }
this->cdCallback = cdc; }
}
void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) {
void setScanlineCallback(void (*callback)(), int sl) { if (P - 0xFF80u < 0x7Fu) {
display.setScanlineCallback(callback, sl); ioamhram[P - 0xFE00] = data;
} } else
nontrivial_ff_write(P, data, cycleCounter);
void setRTCCallback(std::uint32_t (*callback)()) { if(cdCallback)
cart.setRTCCallback(callback); {
} CDMapResult map = CDMap(P);
if(map.type != eCDLog_AddrType_None)
void setLinkCallback(void (*callback)()) { cdCallback(map.addr,map.type,eCDLog_Flags_Data);
this->linkCallback = callback; }
} }
void setEndtime(unsigned long cc, unsigned long inc); unsigned long event(unsigned long cycleCounter);
unsigned long resetCounters(unsigned long cycleCounter);
void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); }
unsigned fillSoundBuffer(unsigned long cc); int loadROM(const char *romfiledata, unsigned romfilelength, bool forceDmg, bool multicartCompat);
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) { void setInputGetter(unsigned (*getInput)()) {
display.setVideoBuffer(videoBuf, pitch); this->getInput = getInput;
} }
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32); void setReadCallback(void (*callback)(unsigned)) {
void setCgbPalette(unsigned *lut); this->readCallback = callback;
}
int LinkStatus(int which); void setWriteCallback(void (*callback)(unsigned)) {
this->writeCallback = callback;
template<bool isReader>void SyncState(NewState *ns); }
}; void setExecCallback(void (*callback)(unsigned)) {
this->execCallback = callback;
} }
void setCDCallback(CDCallback cdc) {
#endif this->cdCallback = cdc;
}
void setScanlineCallback(void (*callback)(), int sl) {
display.setScanlineCallback(callback, sl);
}
void setRTCCallback(std::uint32_t (*callback)()) {
cart.setRTCCallback(callback);
}
void setLinkCallback(void(*callback)()) {
this->linkCallback = callback;
}
void setEndtime(unsigned long cc, unsigned long inc);
void setSoundBuffer(uint_least32_t *const buf) { sound.setBuffer(buf); }
unsigned fillSoundBuffer(unsigned long cc);
void setVideoBuffer(uint_least32_t *const videoBuf, const int pitch) {
display.setVideoBuffer(videoBuf, pitch);
}
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
void setCgbPalette(unsigned *lut);
void blackScreen() {
display.blackScreen();
}
int LinkStatus(int which);
template<bool isReader>void SyncState(NewState *ns);
};
}
#endif

View File

@ -20,7 +20,7 @@
#define MINKEEPER_H #define MINKEEPER_H
#include <algorithm> #include <algorithm>
#include "newstate.h" #include "newstate.h"
namespace MinKeeperUtil { namespace MinKeeperUtil {
template<int n> struct CeiledLog2 { enum { R = 1 + CeiledLog2<(n + 1) / 2>::R }; }; template<int n> struct CeiledLog2 { enum { R = 1 + CeiledLog2<(n + 1) / 2>::R }; };
@ -108,12 +108,12 @@ public:
unsigned long value(const int id) const { return values[id]; } unsigned long value(const int id) const { return values[id]; }
// not sure if i understood everything in minkeeper correctly, so something might be missing here? // not sure if i understood everything in minkeeper correctly, so something might be missing here?
template<bool isReader> template<bool isReader>
void SyncState(gambatte::NewState *ns) void SyncState(gambatte::NewState *ns)
{ {
NSS(values); NSS(values);
NSS(minValue_); NSS(minValue_);
NSS(a); NSS(a);
} }
}; };

View File

@ -1,69 +1,69 @@
#include "newstate.h" #include "newstate.h"
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
namespace gambatte { namespace gambatte {
NewStateDummy::NewStateDummy() NewStateDummy::NewStateDummy()
:length(0) :length(0)
{ {
} }
void NewStateDummy::Save(const void *ptr, size_t size, const char *name) void NewStateDummy::Save(const void *ptr, size_t size, const char *name)
{ {
length += size; length += size;
} }
void NewStateDummy::Load(void *ptr, size_t size, const char *name) void NewStateDummy::Load(void *ptr, size_t size, const char *name)
{ {
} }
NewStateExternalBuffer::NewStateExternalBuffer(char *buffer, long maxlength) NewStateExternalBuffer::NewStateExternalBuffer(char *buffer, long maxlength)
:buffer(buffer), length(0), maxlength(maxlength) :buffer(buffer), length(0), maxlength(maxlength)
{ {
} }
void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name) void NewStateExternalBuffer::Save(const void *ptr, size_t size, const char *name)
{ {
if (maxlength - length >= (long)size) if (maxlength - length >= (long)size)
{ {
std::memcpy(buffer + length, ptr, size); std::memcpy(buffer + length, ptr, size);
} }
length += size; length += size;
} }
void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name) void NewStateExternalBuffer::Load(void *ptr, size_t size, const char *name)
{ {
char *dst = static_cast<char *>(ptr); char *dst = static_cast<char *>(ptr);
if (maxlength - length >= (long)size) if (maxlength - length >= (long)size)
{ {
std::memcpy(dst, buffer + length, size); std::memcpy(dst, buffer + length, size);
} }
length += size; length += size;
} }
NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff) NewStateExternalFunctions::NewStateExternalFunctions(const FPtrs *ff)
:Save_(ff->Save_), :Save_(ff->Save_),
Load_(ff->Load_), Load_(ff->Load_),
EnterSection_(ff->EnterSection_), EnterSection_(ff->EnterSection_),
ExitSection_(ff->ExitSection_) ExitSection_(ff->ExitSection_)
{ {
} }
void NewStateExternalFunctions::Save(const void *ptr, size_t size, const char *name) void NewStateExternalFunctions::Save(const void *ptr, size_t size, const char *name)
{ {
Save_(ptr, size, name); Save_(ptr, size, name);
} }
void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name) void NewStateExternalFunctions::Load(void *ptr, size_t size, const char *name)
{ {
Load_(ptr, size, name); Load_(ptr, size, name);
} }
void NewStateExternalFunctions::EnterSection(const char *name) void NewStateExternalFunctions::EnterSection(const char *name)
{ {
EnterSection_(name); EnterSection_(name);
} }
void NewStateExternalFunctions::ExitSection(const char *name) void NewStateExternalFunctions::ExitSection(const char *name)
{ {
ExitSection_(name); ExitSection_(name);
} }
} }

View File

@ -1,102 +1,102 @@
#ifndef NEWSTATE_H #ifndef NEWSTATE_H
#define NEWSTATE_H #define NEWSTATE_H
#include <cstring> #include <cstring>
#include <cstddef> #include <cstddef>
namespace gambatte { namespace gambatte {
class NewState class NewState
{ {
public: public:
virtual void Save(const void *ptr, size_t size, const char *name) = 0; virtual void Save(const void *ptr, size_t size, const char *name) = 0;
virtual void Load(void *ptr, size_t size, const char *name) = 0; virtual void Load(void *ptr, size_t size, const char *name) = 0;
virtual void EnterSection(const char *name) { } virtual void EnterSection(const char *name) { }
virtual void ExitSection(const char *name) { } virtual void ExitSection(const char *name) { }
}; };
class NewStateDummy : public NewState class NewStateDummy : public NewState
{ {
private: private:
long length; long length;
public: public:
NewStateDummy(); NewStateDummy();
long GetLength() { return length; } long GetLength() { return length; }
void Rewind() { length = 0; } void Rewind() { length = 0; }
virtual void Save(const void *ptr, size_t size, const char *name); virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name); virtual void Load(void *ptr, size_t size, const char *name);
}; };
class NewStateExternalBuffer : public NewState class NewStateExternalBuffer : public NewState
{ {
private: private:
char *const buffer; char *const buffer;
long length; long length;
const long maxlength; const long maxlength;
public: public:
NewStateExternalBuffer(char *buffer, long maxlength); NewStateExternalBuffer(char *buffer, long maxlength);
long GetLength() { return length; } long GetLength() { return length; }
void Rewind() { length = 0; } void Rewind() { length = 0; }
bool Overflow() { return length > maxlength; } bool Overflow() { return length > maxlength; }
virtual void Save(const void *ptr, size_t size, const char *name); virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name); virtual void Load(void *ptr, size_t size, const char *name);
}; };
struct FPtrs struct FPtrs
{ {
void (*Save_)(const void *ptr, size_t size, const char *name); void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name); void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name); void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name); void (*ExitSection_)(const char *name);
}; };
class NewStateExternalFunctions : public NewState class NewStateExternalFunctions : public NewState
{ {
private: private:
void (*Save_)(const void *ptr, size_t size, const char *name); void (*Save_)(const void *ptr, size_t size, const char *name);
void (*Load_)(void *ptr, size_t size, const char *name); void (*Load_)(void *ptr, size_t size, const char *name);
void (*EnterSection_)(const char *name); void (*EnterSection_)(const char *name);
void (*ExitSection_)(const char *name); void (*ExitSection_)(const char *name);
public: public:
NewStateExternalFunctions(const FPtrs *ff); NewStateExternalFunctions(const FPtrs *ff);
virtual void Save(const void *ptr, size_t size, const char *name); virtual void Save(const void *ptr, size_t size, const char *name);
virtual void Load(void *ptr, size_t size, const char *name); virtual void Load(void *ptr, size_t size, const char *name);
virtual void EnterSection(const char *name); virtual void EnterSection(const char *name);
virtual void ExitSection(const char *name); virtual void ExitSection(const char *name);
}; };
// defines and explicitly instantiates // defines and explicitly instantiates
#define SYNCFUNC(x)\ #define SYNCFUNC(x)\
template void x::SyncState<false>(NewState *ns);\ template void x::SyncState<false>(NewState *ns);\
template void x::SyncState<true>(NewState *ns);\ template void x::SyncState<true>(NewState *ns);\
template<bool isReader>void x::SyncState(NewState *ns) template<bool isReader>void x::SyncState(NewState *ns)
// N = normal variable // N = normal variable
// P = pointer to fixed size data // P = pointer to fixed size data
// S = "sub object" // S = "sub object"
// T = "ptr to sub object" // T = "ptr to sub object"
// R = pointer, store its offset from some other pointer // R = pointer, store its offset from some other pointer
// E = general purpose cased value "enum" // E = general purpose cased value "enum"
// first line is default value in converted enum; last line is default value in argument x // first line is default value in converted enum; last line is default value in argument x
#define EBS(x,d) do { int _ttmp = (d); if (isReader) ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0) #define EBS(x,d) do { int _ttmp = (d); if (isReader) ns->Load(&_ttmp, sizeof(_ttmp), #x); if (0)
#define EVS(x,v,n) else if (!isReader && (x) == (v)) _ttmp = (n); else if (isReader && _ttmp == (n)) (x) = (v) #define EVS(x,v,n) else if (!isReader && (x) == (v)) _ttmp = (n); else if (isReader && _ttmp == (n)) (x) = (v)
#define EES(x,d) else if (isReader) (x) = (d); if (!isReader) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0) #define EES(x,d) else if (isReader) (x) = (d); if (!isReader) ns->Save(&_ttmp, sizeof(_ttmp), #x); } while (0)
#define RSS(x,b) do { if (isReader)\ #define RSS(x,b) do { if (isReader)\
{ ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == (ptrdiff_t)0xdeadbeef ? 0 : (b) + _ttmp); }\ { ptrdiff_t _ttmp; ns->Load(&_ttmp, sizeof(_ttmp), #x); (x) = (_ttmp == (ptrdiff_t)0xdeadbeef ? 0 : (b) + _ttmp); }\
else\ else\
{ ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } } while (0) { ptrdiff_t _ttmp = (x) == 0 ? 0xdeadbeef : (x) - (b); ns->Save(&_ttmp, sizeof(_ttmp), #x); } } while (0)
#define PSS(x,s) do { if (isReader) ns->Load((x), (s), #x); else ns->Save((x), (s), #x); } while (0) #define PSS(x,s) do { if (isReader) ns->Load((x), (s), #x); else ns->Save((x), (s), #x); } while (0)
#define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0) #define NSS(x) do { if (isReader) ns->Load(&(x), sizeof(x), #x); else ns->Save(&(x), sizeof(x), #x); } while (0)
#define SSS(x) do { ns->EnterSection(#x); (x).SyncState<isReader>(ns); ns->ExitSection(#x); } while (0) #define SSS(x) do { ns->EnterSection(#x); (x).SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
#define TSS(x) do { ns->EnterSection(#x); (x)->SyncState<isReader>(ns); ns->ExitSection(#x); } while (0) #define TSS(x) do { ns->EnterSection(#x); (x)->SyncState<isReader>(ns); ns->ExitSection(#x); } while (0)
} }
#endif #endif

View File

@ -38,7 +38,7 @@ struct SaveState {
void set(T *ptr, const unsigned long sz) { this->ptr = ptr; this->sz = sz; } void set(T *ptr, const unsigned long sz) { this->ptr = ptr; this->sz = sz; }
friend class SaverList; friend class SaverList;
friend void setInitState(SaveState &, bool, bool, std::uint32_t); friend void setInitState(SaveState &, bool, bool, bool, std::uint32_t);
}; };
struct CPU { struct CPU {
@ -78,6 +78,10 @@ struct SaveState {
bool enableRam; bool enableRam;
bool rambankMode; bool rambankMode;
bool hdmaTransfer; bool hdmaTransfer;
bool biosMode;
bool cgbSwitching;
bool agbMode;
bool gbIsCgb;
} mem; } mem;
struct PPU { struct PPU {
@ -113,6 +117,8 @@ struct SaveState {
unsigned char wscx; unsigned char wscx;
bool weMaster; bool weMaster;
bool pendingLcdstatIrq; bool pendingLcdstatIrq;
bool isCgb;
bool trueColors;
} ppu; } ppu;
struct SPU { struct SPU {

View File

@ -173,16 +173,16 @@ unsigned PSG::getStatus() const {
} }
// the buffer and position are not saved, as they're set and flushed on each runfor() call // the buffer and position are not saved, as they're set and flushed on each runfor() call
SYNCFUNC(PSG) SYNCFUNC(PSG)
{ {
SSS(ch1); SSS(ch1);
SSS(ch2); SSS(ch2);
SSS(ch3); SSS(ch3);
SSS(ch4); SSS(ch4);
NSS(lastUpdate); NSS(lastUpdate);
NSS(soVol); NSS(soVol);
NSS(rsum); NSS(rsum);
NSS(enabled); NSS(enabled);
} }
} }

View File

@ -23,7 +23,7 @@
#include "sound/channel2.h" #include "sound/channel2.h"
#include "sound/channel3.h" #include "sound/channel3.h"
#include "sound/channel4.h" #include "sound/channel4.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -89,7 +89,7 @@ public:
void map_so(unsigned nr51); void map_so(unsigned nr51);
unsigned getStatus() const; unsigned getStatus() const;
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -97,14 +97,14 @@ void Channel1::SweepUnit::loadState(const SaveState &state) {
negging = state.spu.ch1.sweep.negging; negging = state.spu.ch1.sweep.negging;
} }
template<bool isReader> template<bool isReader>
void Channel1::SweepUnit::SyncState(NewState *ns) void Channel1::SweepUnit::SyncState(NewState *ns)
{ {
NSS(counter); NSS(counter);
NSS(shadow); NSS(shadow);
NSS(nr0); NSS(nr0);
NSS(negging); NSS(negging);
} }
Channel1::Channel1() : Channel1::Channel1() :
staticOutputTest(*this, dutyUnit), staticOutputTest(*this, dutyUnit),
@ -250,26 +250,26 @@ void Channel1::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
} }
} }
SYNCFUNC(Channel1) SYNCFUNC(Channel1)
{ {
SSS(lengthCounter); SSS(lengthCounter);
SSS(dutyUnit); SSS(dutyUnit);
SSS(envelopeUnit); SSS(envelopeUnit);
SSS(sweepUnit); SSS(sweepUnit);
EBS(nextEventUnit, 0); EBS(nextEventUnit, 0);
EVS(nextEventUnit, &dutyUnit, 1); EVS(nextEventUnit, &dutyUnit, 1);
EVS(nextEventUnit, &sweepUnit, 2); EVS(nextEventUnit, &sweepUnit, 2);
EVS(nextEventUnit, &envelopeUnit, 3); EVS(nextEventUnit, &envelopeUnit, 3);
EVS(nextEventUnit, &lengthCounter, 4); EVS(nextEventUnit, &lengthCounter, 4);
EES(nextEventUnit, NULL); EES(nextEventUnit, NULL);
NSS(cycleCounter); NSS(cycleCounter);
NSS(soMask); NSS(soMask);
NSS(prevOut); NSS(prevOut);
NSS(nr4); NSS(nr4);
NSS(master); NSS(master);
} }
} }

View File

@ -1,97 +1,97 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef SOUND_CHANNEL1_H #ifndef SOUND_CHANNEL1_H
#define SOUND_CHANNEL1_H #define SOUND_CHANNEL1_H
#include "gbint.h" #include "gbint.h"
#include "master_disabler.h" #include "master_disabler.h"
#include "length_counter.h" #include "length_counter.h"
#include "duty_unit.h" #include "duty_unit.h"
#include "envelope_unit.h" #include "envelope_unit.h"
#include "static_output_tester.h" #include "static_output_tester.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
struct SaveState; struct SaveState;
class Channel1 { class Channel1 {
class SweepUnit : public SoundUnit { class SweepUnit : public SoundUnit {
MasterDisabler &disableMaster; MasterDisabler &disableMaster;
DutyUnit &dutyUnit; DutyUnit &dutyUnit;
unsigned short shadow; unsigned short shadow;
unsigned char nr0; unsigned char nr0;
bool negging; bool negging;
unsigned calcFreq(); unsigned calcFreq();
public: public:
SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit); SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit);
void event(); void event();
void nr0Change(unsigned newNr0); void nr0Change(unsigned newNr0);
void nr4Init(unsigned long cycleCounter); void nr4Init(unsigned long cycleCounter);
void reset(); void reset();
void loadState(const SaveState &state); void loadState(const SaveState &state);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
friend class StaticOutputTester<Channel1,DutyUnit>; friend class StaticOutputTester<Channel1,DutyUnit>;
StaticOutputTester<Channel1,DutyUnit> staticOutputTest; StaticOutputTester<Channel1,DutyUnit> staticOutputTest;
DutyMasterDisabler disableMaster; DutyMasterDisabler disableMaster;
LengthCounter lengthCounter; LengthCounter lengthCounter;
DutyUnit dutyUnit; DutyUnit dutyUnit;
EnvelopeUnit envelopeUnit; EnvelopeUnit envelopeUnit;
SweepUnit sweepUnit; SweepUnit sweepUnit;
SoundUnit *nextEventUnit; SoundUnit *nextEventUnit;
unsigned long cycleCounter; unsigned long cycleCounter;
unsigned long soMask; unsigned long soMask;
unsigned long prevOut; unsigned long prevOut;
unsigned char nr4; unsigned char nr4;
bool master; bool master;
void setEvent(); void setEvent();
public: public:
Channel1(); Channel1();
void setNr0(unsigned data); void setNr0(unsigned data);
void setNr1(unsigned data); void setNr1(unsigned data);
void setNr2(unsigned data); void setNr2(unsigned data);
void setNr3(unsigned data); void setNr3(unsigned data);
void setNr4(unsigned data); void setNr4(unsigned data);
void setSo(unsigned long soMask); void setSo(unsigned long soMask);
bool isActive() const { return master; } bool isActive() const { return master; }
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
void reset(); void reset();
void init(bool cgb); void init(bool cgb);
void loadState(const SaveState &state); void loadState(const SaveState &state);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }
#endif #endif

View File

@ -153,24 +153,24 @@ void Channel2::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
} }
} }
SYNCFUNC(Channel2) SYNCFUNC(Channel2)
{ {
SSS(lengthCounter); SSS(lengthCounter);
SSS(dutyUnit); SSS(dutyUnit);
SSS(envelopeUnit); SSS(envelopeUnit);
EBS(nextEventUnit, 0); EBS(nextEventUnit, 0);
EVS(nextEventUnit, &dutyUnit, 1); EVS(nextEventUnit, &dutyUnit, 1);
EVS(nextEventUnit, &envelopeUnit, 2); EVS(nextEventUnit, &envelopeUnit, 2);
EVS(nextEventUnit, &lengthCounter, 3); EVS(nextEventUnit, &lengthCounter, 3);
EES(nextEventUnit, NULL); EES(nextEventUnit, NULL);
NSS(cycleCounter); NSS(cycleCounter);
NSS(soMask); NSS(soMask);
NSS(prevOut); NSS(prevOut);
NSS(nr4); NSS(nr4);
NSS(master); NSS(master);
} }
} }

View File

@ -1,75 +1,75 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef SOUND_CHANNEL2_H #ifndef SOUND_CHANNEL2_H
#define SOUND_CHANNEL2_H #define SOUND_CHANNEL2_H
#include "gbint.h" #include "gbint.h"
#include "length_counter.h" #include "length_counter.h"
#include "duty_unit.h" #include "duty_unit.h"
#include "envelope_unit.h" #include "envelope_unit.h"
#include "static_output_tester.h" #include "static_output_tester.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
struct SaveState; struct SaveState;
class Channel2 { class Channel2 {
friend class StaticOutputTester<Channel2,DutyUnit>; friend class StaticOutputTester<Channel2,DutyUnit>;
StaticOutputTester<Channel2,DutyUnit> staticOutputTest; StaticOutputTester<Channel2,DutyUnit> staticOutputTest;
DutyMasterDisabler disableMaster; DutyMasterDisabler disableMaster;
LengthCounter lengthCounter; LengthCounter lengthCounter;
DutyUnit dutyUnit; DutyUnit dutyUnit;
EnvelopeUnit envelopeUnit; EnvelopeUnit envelopeUnit;
SoundUnit *nextEventUnit; SoundUnit *nextEventUnit;
unsigned long cycleCounter; unsigned long cycleCounter;
unsigned long soMask; unsigned long soMask;
unsigned long prevOut; unsigned long prevOut;
unsigned char nr4; unsigned char nr4;
bool master; bool master;
void setEvent(); void setEvent();
public: public:
Channel2(); Channel2();
void setNr1(unsigned data); void setNr1(unsigned data);
void setNr2(unsigned data); void setNr2(unsigned data);
void setNr3(unsigned data); void setNr3(unsigned data);
void setNr4(unsigned data); void setNr4(unsigned data);
void setSo(unsigned long soMask); void setSo(unsigned long soMask);
// void deactivate() { disableMaster(); setEvent(); } // void deactivate() { disableMaster(); setEvent(); }
bool isActive() const { return master; } bool isActive() const { return master; }
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
void reset(); void reset();
void init(bool cgb); void init(bool cgb);
void loadState(const SaveState &state); void loadState(const SaveState &state);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }
#endif #endif

View File

@ -196,27 +196,27 @@ void Channel3::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
} }
} }
SYNCFUNC(Channel3) SYNCFUNC(Channel3)
{ {
NSS(waveRam); NSS(waveRam);
SSS(lengthCounter); SSS(lengthCounter);
NSS(cycleCounter); NSS(cycleCounter);
NSS(soMask); NSS(soMask);
NSS(prevOut); NSS(prevOut);
NSS(waveCounter); NSS(waveCounter);
NSS(lastReadTime); NSS(lastReadTime);
NSS(nr0); NSS(nr0);
NSS(nr3); NSS(nr3);
NSS(nr4); NSS(nr4);
NSS(wavePos); NSS(wavePos);
NSS(rShift); NSS(rShift);
NSS(sampleBuf); NSS(sampleBuf);
NSS(master); NSS(master);
NSS(cgb); NSS(cgb);
} }
} }

View File

@ -1,105 +1,105 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2007 by Sindre Aamås * * Copyright (C) 2007 by Sindre Aamås *
* aamas@stud.ntnu.no * * aamas@stud.ntnu.no *
* * * *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 as * * it under the terms of the GNU General Public License version 2 as *
* published by the Free Software Foundation. * * published by the Free Software Foundation. *
* * * *
* This program is distributed in the hope that it will be useful, * * This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * * but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License version 2 for more details. * * GNU General Public License version 2 for more details. *
* * * *
* You should have received a copy of the GNU General Public License * * You should have received a copy of the GNU General Public License *
* version 2 along with this program; if not, write to the * * version 2 along with this program; if not, write to the *
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef SOUND_CHANNEL3_H #ifndef SOUND_CHANNEL3_H
#define SOUND_CHANNEL3_H #define SOUND_CHANNEL3_H
#include "gbint.h" #include "gbint.h"
#include "master_disabler.h" #include "master_disabler.h"
#include "length_counter.h" #include "length_counter.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
struct SaveState; struct SaveState;
class Channel3 { class Channel3 {
class Ch3MasterDisabler : public MasterDisabler { class Ch3MasterDisabler : public MasterDisabler {
unsigned long &waveCounter; unsigned long &waveCounter;
public: public:
Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {} Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {}
void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; } void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; }
}; };
unsigned char waveRam[0x10]; unsigned char waveRam[0x10];
Ch3MasterDisabler disableMaster; Ch3MasterDisabler disableMaster;
LengthCounter lengthCounter; LengthCounter lengthCounter;
unsigned long cycleCounter; unsigned long cycleCounter;
unsigned long soMask; unsigned long soMask;
unsigned long prevOut; unsigned long prevOut;
unsigned long waveCounter; unsigned long waveCounter;
unsigned long lastReadTime; unsigned long lastReadTime;
unsigned char nr0; unsigned char nr0;
unsigned char nr3; unsigned char nr3;
unsigned char nr4; unsigned char nr4;
unsigned char wavePos; unsigned char wavePos;
unsigned char rShift; unsigned char rShift;
unsigned char sampleBuf; unsigned char sampleBuf;
bool master; bool master;
bool cgb; bool cgb;
void updateWaveCounter(unsigned long cc); void updateWaveCounter(unsigned long cc);
public: public:
Channel3(); Channel3();
bool isActive() const { return master; } bool isActive() const { return master; }
void reset(); void reset();
void init(bool cgb); void init(bool cgb);
void setStatePtrs(SaveState &state); void setStatePtrs(SaveState &state);
void loadState(const SaveState &state); void loadState(const SaveState &state);
void setNr0(unsigned data); void setNr0(unsigned data);
void setNr1(unsigned data) { lengthCounter.nr1Change(data, nr4, cycleCounter); } void setNr1(unsigned data) { lengthCounter.nr1Change(data, nr4, cycleCounter); }
void setNr2(unsigned data); void setNr2(unsigned data);
void setNr3(unsigned data) { nr3 = data; } void setNr3(unsigned data) { nr3 = data; }
void setNr4(unsigned data); void setNr4(unsigned data);
void setSo(unsigned long soMask); void setSo(unsigned long soMask);
void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); void update(uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles);
unsigned waveRamRead(unsigned index) const { unsigned waveRamRead(unsigned index) const {
if (master) { if (master) {
if (!cgb && cycleCounter != lastReadTime) if (!cgb && cycleCounter != lastReadTime)
return 0xFF; return 0xFF;
index = wavePos >> 1; index = wavePos >> 1;
} }
return waveRam[index]; return waveRam[index];
} }
void waveRamWrite(unsigned index, unsigned data) { void waveRamWrite(unsigned index, unsigned data) {
if (master) { if (master) {
if (!cgb && cycleCounter != lastReadTime) if (!cgb && cycleCounter != lastReadTime)
return; return;
index = wavePos >> 1; index = wavePos >> 1;
} }
waveRam[index] = data; waveRam[index] = data;
} }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }
#endif #endif

View File

@ -157,15 +157,15 @@ void Channel4::Lfsr::loadState(const SaveState &state) {
nr3 = state.mem.ioamhram.get()[0x122]; nr3 = state.mem.ioamhram.get()[0x122];
} }
template<bool isReader> template<bool isReader>
void Channel4::Lfsr::SyncState(NewState *ns) void Channel4::Lfsr::SyncState(NewState *ns)
{ {
NSS(counter); NSS(counter);
NSS(backupCounter); NSS(backupCounter);
NSS(reg); NSS(reg);
NSS(nr3); NSS(nr3);
NSS(master); NSS(master);
} }
Channel4::Channel4() : Channel4::Channel4() :
staticOutputTest(*this, lfsr), staticOutputTest(*this, lfsr),
@ -295,25 +295,25 @@ void Channel4::update(uint_least32_t *buf, const unsigned long soBaseVol, unsign
cycleCounter -= SoundUnit::COUNTER_MAX; cycleCounter -= SoundUnit::COUNTER_MAX;
} }
} }
SYNCFUNC(Channel4) SYNCFUNC(Channel4)
{ {
SSS(lengthCounter); SSS(lengthCounter);
SSS(envelopeUnit); SSS(envelopeUnit);
SSS(lfsr); SSS(lfsr);
EBS(nextEventUnit, 0); EBS(nextEventUnit, 0);
EVS(nextEventUnit, &lfsr, 1); EVS(nextEventUnit, &lfsr, 1);
EVS(nextEventUnit, &envelopeUnit, 2); EVS(nextEventUnit, &envelopeUnit, 2);
EVS(nextEventUnit, &lengthCounter, 3); EVS(nextEventUnit, &lengthCounter, 3);
EES(nextEventUnit, NULL); EES(nextEventUnit, NULL);
NSS(cycleCounter); NSS(cycleCounter);
NSS(soMask); NSS(soMask);
NSS(prevOut); NSS(prevOut);
NSS(nr4); NSS(nr4);
NSS(master); NSS(master);
} }
} }

View File

@ -24,7 +24,7 @@
#include "length_counter.h" #include "length_counter.h"
#include "envelope_unit.h" #include "envelope_unit.h"
#include "static_output_tester.h" #include "static_output_tester.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -52,7 +52,7 @@ class Channel4 {
void killCounter() { counter = COUNTER_DISABLED; } void killCounter() { counter = COUNTER_DISABLED; }
void reviveCounter(unsigned long cc); void reviveCounter(unsigned long cc);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
class Ch4MasterDisabler : public MasterDisabler { class Ch4MasterDisabler : public MasterDisabler {
@ -97,7 +97,7 @@ public:
void init(bool cgb); void init(bool cgb);
void loadState(const SaveState &state); void loadState(const SaveState &state);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -142,15 +142,15 @@ void DutyUnit::reviveCounter(const unsigned long cc) {
setCounter(); setCounter();
} }
SYNCFUNC(DutyUnit) SYNCFUNC(DutyUnit)
{ {
NSS(counter); NSS(counter);
NSS(nextPosUpdate); NSS(nextPosUpdate);
NSS(period); NSS(period);
NSS(pos); NSS(pos);
NSS(duty); NSS(duty);
NSS(high); NSS(high);
NSS(enableEvents); NSS(enableEvents);
} }
} }

View File

@ -22,7 +22,7 @@
#include "sound_unit.h" #include "sound_unit.h"
#include "master_disabler.h" #include "master_disabler.h"
#include "../savestate.h" #include "../savestate.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -55,7 +55,7 @@ public:
unsigned getFreq() const { return 2048 - (period >> 1); } unsigned getFreq() const { return 2048 - (period >> 1); }
void setFreq(unsigned newFreq, unsigned long cc); void setFreq(unsigned newFreq, unsigned long cc);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
class DutyMasterDisabler : public MasterDisabler { class DutyMasterDisabler : public MasterDisabler {

View File

@ -98,11 +98,11 @@ void EnvelopeUnit::loadState(const SaveState::SPU::Env &estate, const unsigned n
this->nr2 = nr2; this->nr2 = nr2;
} }
SYNCFUNC(EnvelopeUnit) SYNCFUNC(EnvelopeUnit)
{ {
NSS(counter); NSS(counter);
NSS(nr2); NSS(nr2);
NSS(volume); NSS(volume);
} }
} }

View File

@ -21,7 +21,7 @@
#include "sound_unit.h" #include "sound_unit.h"
#include "../savestate.h" #include "../savestate.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -48,7 +48,7 @@ public:
void reset(); void reset();
void loadState(const SaveState::SPU::Env &estate, unsigned nr2, unsigned long cc); void loadState(const SaveState::SPU::Env &estate, unsigned nr2, unsigned long cc);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -83,11 +83,11 @@ void LengthCounter::loadState(const SaveState::SPU::LCounter &lstate, const unsi
lengthCounter = lstate.lengthCounter; lengthCounter = lstate.lengthCounter;
} }
SYNCFUNC(LengthCounter) SYNCFUNC(LengthCounter)
{ {
NSS(counter); NSS(counter);
NSS(lengthCounter); NSS(lengthCounter);
NSS(cgb); NSS(cgb);
} }
} }

View File

@ -21,7 +21,7 @@
#include "sound_unit.h" #include "sound_unit.h"
#include "../savestate.h" #include "../savestate.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -42,7 +42,7 @@ public:
void init(bool cgb); void init(bool cgb);
void loadState(const SaveState::SPU::LCounter &lstate, unsigned long cc); void loadState(const SaveState::SPU::LCounter &lstate, unsigned long cc);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -163,13 +163,13 @@ void Tima::doIrqEvent(const TimaInterruptRequester timaIrq) {
timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3])); timaIrq.setNextIrqEventTime(timaIrq.nextIrqEventTime() + ((256u - tma_) << timaClock[tac_ & 3]));
} }
SYNCFUNC(Tima) SYNCFUNC(Tima)
{ {
NSS(lastUpdate_); NSS(lastUpdate_);
NSS(tmatime_); NSS(tmatime_);
NSS(tima_); NSS(tima_);
NSS(tma_); NSS(tma_);
NSS(tac_); NSS(tac_);
} }
} }

View File

@ -60,7 +60,7 @@ public:
void doIrqEvent(TimaInterruptRequester timaIrq); void doIrqEvent(TimaInterruptRequester timaIrq);
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -36,7 +36,14 @@ void LCD::setCgbPalette(unsigned *lut) {
refreshPalettes(); refreshPalettes();
} }
unsigned long LCD::gbcToRgb32(const unsigned bgr15) { unsigned long LCD::gbcToRgb32(const unsigned bgr15, bool trueColor) {
unsigned long const r = bgr15 & 0x1F;
unsigned long const g = bgr15 >> 5 & 0x1F;
unsigned long const b = bgr15 >> 10 & 0x1F;
if (trueColor)
return (r << 19) | (g << 11) | (b << 3);
return cgbColorsRgb32[bgr15 & 0x7FFF]; return cgbColorsRgb32[bgr15 & 0x7FFF];
} }
@ -66,6 +73,10 @@ void LCD::reset(const unsigned char *const oamram, const unsigned char *vram, co
refreshPalettes(); refreshPalettes();
} }
void LCD::setCgb(bool cgb) {
ppu.setCgb(cgb);
}
static unsigned long mode2IrqSchedule(const unsigned statReg, const LyCounter &lyCounter, const unsigned long cycleCounter) { static unsigned long mode2IrqSchedule(const unsigned statReg, const LyCounter &lyCounter, const unsigned long cycleCounter) {
if (!(statReg & 0x20)) if (!(statReg & 0x20))
return DISABLED_TIME; return DISABLED_TIME;
@ -140,8 +151,8 @@ void LCD::loadState(const SaveState &state, const unsigned char *const oamram) {
void LCD::refreshPalettes() { void LCD::refreshPalettes() {
if (ppu.cgb()) { if (ppu.cgb()) {
for (unsigned i = 0; i < 8 * 8; i += 2) { for (unsigned i = 0; i < 8 * 8; i += 2) {
ppu.bgPalette()[i >> 1] = gbcToRgb32( bgpData[i] | bgpData[i + 1] << 8); ppu.bgPalette()[i >> 1] = gbcToRgb32( bgpData[i] | bgpData[i + 1] << 8, isTrueColors());
ppu.spPalette()[i >> 1] = gbcToRgb32(objpData[i] | objpData[i + 1] << 8); ppu.spPalette()[i >> 1] = gbcToRgb32(objpData[i] | objpData[i + 1] << 8, isTrueColors());
} }
} else { } else {
setDmgPalette(ppu.bgPalette() , dmgColorsRgb32 , bgpData[0]); setDmgPalette(ppu.bgPalette() , dmgColorsRgb32 , bgpData[0]);
@ -150,6 +161,32 @@ void LCD::refreshPalettes() {
} }
} }
void LCD::copyCgbPalettesToDmg() {
for (unsigned i = 0; i < 4; i++) {
dmgColorsRgb32[i] = gbcToRgb32(bgpData[i * 2] | bgpData[i * 2 + 1] << 8, isTrueColors());
}
for (unsigned i = 0; i < 8; i++) {
dmgColorsRgb32[i + 4] = gbcToRgb32(objpData[i * 2] | objpData[i * 2 + 1] << 8, isTrueColors());
}
}
void LCD::blackScreen() {
if (ppu.cgb()) {
for (unsigned i = 0; i < 8 * 8; i += 2) {
ppu.bgPalette()[i >> 1] = 0;
ppu.spPalette()[i >> 1] = 0;
}
}
else {
for (unsigned i = 0; i < 4; i++) {
dmgColorsRgb32[i] = 0;
}
for (unsigned i = 0; i < 8; i++) {
dmgColorsRgb32[i + 4] = 0;
}
}
}
namespace { namespace {
template<typename T> template<typename T>
@ -168,7 +205,7 @@ void LCD::updateScreen(const bool blanklcd, const unsigned long cycleCounter) {
update(cycleCounter); update(cycleCounter);
if (blanklcd && ppu.frameBuf().fb()) { if (blanklcd && ppu.frameBuf().fb()) {
const unsigned long color = ppu.cgb() ? gbcToRgb32(0xFFFF) : dmgColorsRgb32[0]; const unsigned long color = ppu.cgb() ? gbcToRgb32(0xFFFF, isTrueColors()) : dmgColorsRgb32[0];
clear(ppu.frameBuf().fb(), color, ppu.frameBuf().pitch()); clear(ppu.frameBuf().fb(), color, ppu.frameBuf().pitch());
} }
} }
@ -282,23 +319,23 @@ bool LCD::cgbpAccessible(const unsigned long cycleCounter) {
} }
void LCD::doCgbColorChange(unsigned char *const pdata, void LCD::doCgbColorChange(unsigned char *const pdata,
unsigned long *const palette, unsigned index, const unsigned data) { unsigned long *const palette, unsigned index, const unsigned data, bool trueColor) {
pdata[index] = data; pdata[index] = data;
index >>= 1; index >>= 1;
palette[index] = gbcToRgb32(pdata[index << 1] | pdata[(index << 1) + 1] << 8); palette[index] = gbcToRgb32(pdata[index << 1] | pdata[(index << 1) + 1] << 8, trueColor);
} }
void LCD::doCgbBgColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) { void LCD::doCgbBgColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
if (cgbpAccessible(cycleCounter)) { if (cgbpAccessible(cycleCounter)) {
update(cycleCounter); update(cycleCounter);
doCgbColorChange(bgpData, ppu.bgPalette(), index, data); doCgbColorChange(bgpData, ppu.bgPalette(), index, data, isTrueColors());
} }
} }
void LCD::doCgbSpColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) { void LCD::doCgbSpColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
if (cgbpAccessible(cycleCounter)) { if (cgbpAccessible(cycleCounter)) {
update(cycleCounter); update(cycleCounter);
doCgbColorChange(objpData, ppu.spPalette(), index, data); doCgbColorChange(objpData, ppu.spPalette(), index, data, isTrueColors());
} }
} }
@ -734,19 +771,19 @@ void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, con
// don't need to save or load rgb32 color data // don't need to save or load rgb32 color data
SYNCFUNC(LCD) SYNCFUNC(LCD)
{ {
SSS(ppu); SSS(ppu);
NSS(bgpData); NSS(bgpData);
NSS(objpData); NSS(objpData);
SSS(eventTimes_); SSS(eventTimes_);
SSS(m0Irq_); SSS(m0Irq_);
SSS(lycIrq); SSS(lycIrq);
SSS(nextM0Time_); SSS(nextM0Time_);
NSS(statReg); NSS(statReg);
NSS(m2IrqStatReg_); NSS(m2IrqStatReg_);
NSS(m1IrqStatReg_); NSS(m1IrqStatReg_);
} }
} }

View File

@ -25,7 +25,7 @@
#include "interruptrequester.h" #include "interruptrequester.h"
#include "minkeeper.h" #include "minkeeper.h"
#include <memory> #include <memory>
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -79,10 +79,10 @@ public:
unsigned statReg() const { return statReg_; } unsigned statReg() const { return statReg_; }
template<bool isReader> template<bool isReader>
void SyncState(NewState *ns) void SyncState(NewState *ns)
{ {
NSS(statReg_); NSS(statReg_);
NSS(lycReg_); NSS(lycReg_);
} }
}; };
@ -120,12 +120,12 @@ class LCD {
void flagIrq(const unsigned bit) { memEventRequester_.flagIrq(bit); } void flagIrq(const unsigned bit) { memEventRequester_.flagIrq(bit); }
void flagHdmaReq() { memEventRequester_.flagHdmaReq(); } void flagHdmaReq() { memEventRequester_.flagHdmaReq(); }
template<bool isReader> template<bool isReader>
void SyncState(NewState *ns) void SyncState(NewState *ns)
{ {
SSS(eventMin_); SSS(eventMin_);
SSS(memEventMin_); SSS(memEventMin_);
//SSS(memEventRequester_); // not needed //SSS(memEventRequester_); // not needed
} }
}; };
@ -147,8 +147,8 @@ class LCD {
static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data); static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data);
void setDmgPaletteColor(unsigned index, unsigned long rgb32); void setDmgPaletteColor(unsigned index, unsigned long rgb32);
unsigned long gbcToRgb32(const unsigned bgr15); unsigned long gbcToRgb32(const unsigned bgr15, bool trueColor);
void doCgbColorChange(unsigned char *const pdata, unsigned long *const palette, unsigned index, const unsigned data); void doCgbColorChange(unsigned char *const pdata, unsigned long *const palette, unsigned index, const unsigned data, bool trueColor);
void refreshPalettes(); void refreshPalettes();
void setDBuffer(); void setDBuffer();
@ -175,6 +175,9 @@ public:
void setCgbPalette(unsigned *lut); void setCgbPalette(unsigned *lut);
void setVideoBuffer(uint_least32_t *videoBuf, int pitch); void setVideoBuffer(uint_least32_t *videoBuf, int pitch);
void setLayers(unsigned mask) { ppu.setLayers(mask); } void setLayers(unsigned mask) { ppu.setLayers(mask); }
void setCgb(bool cgb);
void copyCgbPalettesToDmg();
void blackScreen();
int debugGetLY() const { return ppu.lyCounter().ly(); } int debugGetLY() const { return ppu.lyCounter().ly(); }
@ -267,13 +270,14 @@ public:
bool isCgb() const { return ppu.cgb(); } bool isCgb() const { return ppu.cgb(); }
bool isDoubleSpeed() const { return ppu.lyCounter().isDoubleSpeed(); } bool isDoubleSpeed() const { return ppu.lyCounter().isDoubleSpeed(); }
bool isTrueColors() const { return ppu.trueColors(); }
unsigned long *bgPalette() { return ppu.bgPalette(); } unsigned long *bgPalette() { return ppu.bgPalette(); }
unsigned long *spPalette() { return ppu.spPalette(); } unsigned long *spPalette() { return ppu.spPalette(); }
void setScanlineCallback(void (*callback)(), int sl) { scanlinecallback = callback; scanlinecallbacksl = sl; } void setScanlineCallback(void (*callback)(), int sl) { scanlinecallback = callback; scanlinecallbacksl = sl; }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -64,13 +64,13 @@ void LyCounter::setDoubleSpeed(const bool ds_in) {
ds = ds_in; ds = ds_in;
lineTime_ = 456U << ds_in; lineTime_ = 456U << ds_in;
} }
SYNCFUNC(LyCounter) SYNCFUNC(LyCounter)
{ {
NSS(time_); NSS(time_);
NSS(lineTime_); NSS(lineTime_);
NSS(ly_); NSS(ly_);
NSS(ds); NSS(ds);
} }
} }

View File

@ -19,7 +19,7 @@
#ifndef LY_COUNTER_H #ifndef LY_COUNTER_H
#define LY_COUNTER_H #define LY_COUNTER_H
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -52,7 +52,7 @@ public:
void setDoubleSpeed(bool ds_in); void setDoubleSpeed(bool ds_in);
unsigned long time() const { return time_; } unsigned long time() const { return time_; }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -95,14 +95,14 @@ void LycIrq::lcdReset() {
lycReg_ = lycRegSrc_; lycReg_ = lycRegSrc_;
} }
SYNCFUNC(LycIrq) SYNCFUNC(LycIrq)
{ {
NSS(time_); NSS(time_);
NSS(lycRegSrc_); NSS(lycRegSrc_);
NSS(statRegSrc_); NSS(statRegSrc_);
NSS(lycReg_); NSS(lycReg_);
NSS(statReg_); NSS(statReg_);
NSS(cgb_); NSS(cgb_);
} }
} }

View File

@ -19,7 +19,7 @@
#ifndef VIDEO_LYC_IRQ_H #ifndef VIDEO_LYC_IRQ_H
#define VIDEO_LYC_IRQ_H #define VIDEO_LYC_IRQ_H
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -54,7 +54,7 @@ public:
regChange(statRegSrc_, lycReg, lyCounter, cc); regChange(statRegSrc_, lycReg, lyCounter, cc);
} }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -7,9 +7,9 @@ void NextM0Time::predictNextM0Time(const PPU &ppu) {
predictedNextM0Time_ = ppu.predictedNextXposTime(167); predictedNextM0Time_ = ppu.predictedNextXposTime(167);
} }
SYNCFUNC(NextM0Time) SYNCFUNC(NextM0Time)
{ {
NSS(predictedNextM0Time_); NSS(predictedNextM0Time_);
} }
} }

View File

@ -1,7 +1,7 @@
#ifndef NEXT_M0_TIME_H_ #ifndef NEXT_M0_TIME_H_
#define NEXT_M0_TIME_H_ #define NEXT_M0_TIME_H_
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -14,7 +14,7 @@ public:
void invalidatePredictedNextM0Time() { predictedNextM0Time_ = 0; } void invalidatePredictedNextM0Time() { predictedNextM0Time_ = 0; }
unsigned predictedNextM0Time() const { return predictedNextM0Time_; } unsigned predictedNextM0Time() const { return predictedNextM0Time_; }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -1630,6 +1630,8 @@ void PPU::loadState(const SaveState &ss, const unsigned char *const oamram) {
p_.weMaster = ss.ppu.weMaster; p_.weMaster = ss.ppu.weMaster;
p_.winDrawState = ss.ppu.winDrawState & (WIN_DRAW_START | WIN_DRAW_STARTED); p_.winDrawState = ss.ppu.winDrawState & (WIN_DRAW_START | WIN_DRAW_STARTED);
p_.lastM0Time = p_.now - ss.ppu.lastM0Time; p_.lastM0Time = p_.now - ss.ppu.lastM0Time;
p_.cgb = ss.ppu.isCgb;
p_.trueColors = ss.ppu.trueColors;
loadSpriteList(p_, ss); loadSpriteList(p_, ss);
if (m3loopState && videoCycles < 144 * 456L && p_.xpos < 168 if (m3loopState && videoCycles < 144 * 456L && p_.xpos < 168
@ -1739,70 +1741,71 @@ void PPU::update(const unsigned long cc) {
} }
} }
SYNCFUNC(PPU) SYNCFUNC(PPU)
{ {
NSS(p_.bgPalette); NSS(p_.bgPalette);
NSS(p_.spPalette); NSS(p_.spPalette);
NSS(p_.spriteList); NSS(p_.spriteList);
NSS(p_.spwordList); NSS(p_.spwordList);
NSS(p_.nextSprite); NSS(p_.nextSprite);
NSS(p_.currentSprite); NSS(p_.currentSprite);
EBS(p_.nextCallPtr, 0); EBS(p_.nextCallPtr, 0);
EVS(p_.nextCallPtr, &M2::Ly0::f0_, 1); EVS(p_.nextCallPtr, &M2::Ly0::f0_, 1);
EVS(p_.nextCallPtr, &M2::LyNon0::f0_, 2); EVS(p_.nextCallPtr, &M2::LyNon0::f0_, 2);
EVS(p_.nextCallPtr, &M2::LyNon0::f1_, 3); EVS(p_.nextCallPtr, &M2::LyNon0::f1_, 3);
EVS(p_.nextCallPtr, &M3Start::f0_, 4); EVS(p_.nextCallPtr, &M3Start::f0_, 4);
EVS(p_.nextCallPtr, &M3Start::f1_, 5); EVS(p_.nextCallPtr, &M3Start::f1_, 5);
EVS(p_.nextCallPtr, &M3Loop::Tile::f0_, 6); EVS(p_.nextCallPtr, &M3Loop::Tile::f0_, 6);
EVS(p_.nextCallPtr, &M3Loop::Tile::f1_, 7); EVS(p_.nextCallPtr, &M3Loop::Tile::f1_, 7);
EVS(p_.nextCallPtr, &M3Loop::Tile::f2_, 8); EVS(p_.nextCallPtr, &M3Loop::Tile::f2_, 8);
EVS(p_.nextCallPtr, &M3Loop::Tile::f3_, 9); EVS(p_.nextCallPtr, &M3Loop::Tile::f3_, 9);
EVS(p_.nextCallPtr, &M3Loop::Tile::f4_, 10); EVS(p_.nextCallPtr, &M3Loop::Tile::f4_, 10);
EVS(p_.nextCallPtr, &M3Loop::Tile::f5_, 11); EVS(p_.nextCallPtr, &M3Loop::Tile::f5_, 11);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f0_, 12); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f0_, 12);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f1_, 13); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f1_, 13);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f2_, 14); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f2_, 14);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f3_, 15); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f3_, 15);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f4_, 16); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f4_, 16);
EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f5_, 17); EVS(p_.nextCallPtr, &M3Loop::LoadSprites::f5_, 17);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f0_, 18); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f0_, 18);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f1_, 19); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f1_, 19);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f2_, 20); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f2_, 20);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f3_, 21); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f3_, 21);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f4_, 22); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f4_, 22);
EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f5_, 23); EVS(p_.nextCallPtr, &M3Loop::StartWindowDraw::f5_, 23);
EES(p_.nextCallPtr, NULL); EES(p_.nextCallPtr, NULL);
NSS(p_.now); NSS(p_.now);
NSS(p_.lastM0Time); NSS(p_.lastM0Time);
NSS(p_.cycles); NSS(p_.cycles);
NSS(p_.tileword); NSS(p_.tileword);
NSS(p_.ntileword); NSS(p_.ntileword);
SSS(p_.spriteMapper); SSS(p_.spriteMapper);
SSS(p_.lyCounter); SSS(p_.lyCounter);
//SSS(p_.framebuf); // no state //SSS(p_.framebuf); // no state
NSS(p_.lcdc); NSS(p_.lcdc);
NSS(p_.scy); NSS(p_.scy);
NSS(p_.scx); NSS(p_.scx);
NSS(p_.wy); NSS(p_.wy);
NSS(p_.wy2); NSS(p_.wy2);
NSS(p_.wx); NSS(p_.wx);
NSS(p_.winDrawState); NSS(p_.winDrawState);
NSS(p_.wscx); NSS(p_.wscx);
NSS(p_.winYPos); NSS(p_.winYPos);
NSS(p_.reg0); NSS(p_.reg0);
NSS(p_.reg1); NSS(p_.reg1);
NSS(p_.attrib); NSS(p_.attrib);
NSS(p_.nattrib); NSS(p_.nattrib);
NSS(p_.xpos); NSS(p_.xpos);
NSS(p_.endx); NSS(p_.endx);
NSS(p_.cgb); NSS(p_.cgb);
NSS(p_.weMaster); NSS(p_.trueColors);
} NSS(p_.weMaster);
}
} }

View File

@ -23,7 +23,7 @@
#include "video/sprite_mapper.h" #include "video/sprite_mapper.h"
#include "gbint.h" #include "gbint.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
@ -92,6 +92,7 @@ struct PPUPriv {
unsigned char endx; unsigned char endx;
bool cgb; bool cgb;
bool trueColors;
bool weMaster; bool weMaster;
PPUPriv(NextM0Time &nextM0Time, const unsigned char *oamram, const unsigned char *vram); PPUPriv(NextM0Time &nextM0Time, const unsigned char *oamram, const unsigned char *vram);
@ -107,6 +108,7 @@ public:
unsigned long * bgPalette() { return p_.bgPalette; } unsigned long * bgPalette() { return p_.bgPalette; }
bool cgb() const { return p_.cgb; } bool cgb() const { return p_.cgb; }
bool trueColors() const { return p_.trueColors; }
void doLyCountEvent() { p_.lyCounter.doEvent(); } void doLyCountEvent() { p_.lyCounter.doEvent(); }
unsigned long doSpriteMapEvent(unsigned long time) { return p_.spriteMapper.doEvent(time); } unsigned long doSpriteMapEvent(unsigned long time) { return p_.spriteMapper.doEvent(time); }
const PPUFrameBuf & frameBuf() const { return p_.framebuf; } const PPUFrameBuf & frameBuf() const { return p_.framebuf; }
@ -133,8 +135,10 @@ public:
unsigned long * spPalette() { return p_.spPalette; } unsigned long * spPalette() { return p_.spPalette; }
void update(unsigned long cc); void update(unsigned long cc);
void setLayers(unsigned mask) { p_.layersMask = mask; } void setLayers(unsigned mask) { p_.layersMask = mask; }
void setCgb(bool cgb) { p_.cgb = cgb; }
void setTrueColors(bool trueColors) { p_.trueColors = trueColors; }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

View File

@ -117,16 +117,16 @@ void SpriteMapper::OamReader::loadState(const SaveState &ss, const unsigned char
change(lu); change(lu);
} }
SYNCFUNC(SpriteMapper::OamReader) SYNCFUNC(SpriteMapper::OamReader)
{ {
NSS(buf); NSS(buf);
NSS(szbuf); NSS(szbuf);
NSS(lu); NSS(lu);
NSS(lastChange); NSS(lastChange);
NSS(largeSpritesSrc); NSS(largeSpritesSrc);
NSS(cgb_); NSS(cgb_);
} }
void SpriteMapper::OamReader::enableDisplay(const unsigned long cc) { void SpriteMapper::OamReader::enableDisplay(const unsigned long cc) {
std::memset(buf, 0x00, sizeof(buf)); std::memset(buf, 0x00, sizeof(buf));
@ -190,13 +190,13 @@ unsigned long SpriteMapper::doEvent(const unsigned long time) {
return oamReader.changed() ? time + oamReader.lyCounter.lineTime() : static_cast<unsigned long>(DISABLED_TIME); return oamReader.changed() ? time + oamReader.lyCounter.lineTime() : static_cast<unsigned long>(DISABLED_TIME);
} }
SYNCFUNC(SpriteMapper) SYNCFUNC(SpriteMapper)
{ {
NSS(spritemap); NSS(spritemap);
NSS(num); NSS(num);
SSS(nextM0Time_); SSS(nextM0Time_);
SSS(oamReader); SSS(oamReader);
} }
} }

View File

@ -21,7 +21,7 @@
#include "ly_counter.h" #include "ly_counter.h"
#include "../savestate.h" #include "../savestate.h"
#include "newstate.h" #include "newstate.h"
namespace gambatte { namespace gambatte {
class NextM0Time; class NextM0Time;
@ -58,7 +58,7 @@ class SpriteMapper {
void loadState(const SaveState &ss, const unsigned char *oamram); void loadState(const SaveState &ss, const unsigned char *oamram);
bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { return cc < lu; } bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { return cc < lu; }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
enum { NEED_SORTING_MASK = 0x80 }; enum { NEED_SORTING_MASK = 0x80 };
@ -124,7 +124,7 @@ public:
void loadState(const SaveState &state, const unsigned char *const oamram) { oamReader.loadState(state, oamram); mapSprites(); } void loadState(const SaveState &state, const unsigned char *const oamram) { oamReader.loadState(state, oamram); mapSprites(); }
bool inactivePeriodAfterDisplayEnable(unsigned long cc) const { return oamReader.inactivePeriodAfterDisplayEnable(cc); } bool inactivePeriodAfterDisplayEnable(unsigned long cc) const { return oamReader.inactivePeriodAfterDisplayEnable(cc); }
template<bool isReader>void SyncState(NewState *ns); template<bool isReader>void SyncState(NewState *ns);
}; };
} }

Binary file not shown.