Gambatte: Merge improvements from gifvex(mcmaeve)
Restores Bios support and loading GB games into GBC Accuracy imrpovements
This commit is contained in:
parent
c6bdae916f
commit
e5ded9b139
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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*/
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
Loading…
Reference in New Issue